· 10 years ago · Apr 11, 2016, 06:15 PM
1#!/bin/sh
2
3# ############################################################################ #
4# ############################################################################ #
5# ############################################################################ #
6# #
7# SuRep (2015-05-10 00:15:51) by Fravadona #
8# #
9 version=1.0.1
10# #
11# Send an email to notify changes made in a directory of the NAS #
12# #
13# TODO: #
14# * option to set a minimum number of modifications before sending email #
15# * rollback logging support #
16# * demonize the script #
17# * plain text connection with telnet (it shouldn't worth it) #
18# #
19# LIMITATIONS: #
20# * this script is not intended to monitor a directory with waaaay too #
21# much files inside it #
22# * UTF8 and strange (but legal) ASCII email addresses may cause problems #
23# * encoding of email message may be limited #
24# #
25# COMMENT: #
26# * an implementation with "inotify" and "sendmail" is without a doubt a #
27# much better approach, but DSM doesn't provide it by default #
28# #
29# ############################################################################ #
30# ############################################################################ #
31# ############################################################################ #
32
33# ============================================================================ #
34
35#IFS=' '$'\t'$'\n'
36#PATH=/bin:/usr/bin:/usr/syno/bin
37
38# ============================================================================ #
39
40ddbfile="/tmp/SuRep-`/bin/date '+%s'`-$$.ddb"
41nodfile="/tmp/SuRep-`/bin/date '+%s'`-$$.nod"
42
43trap "exit 2" 1 2 3 15
44trap "/bin/rm -f '${ddbfile}' '${nodfile}' >& /dev/null" 0
45
46# ============================================================================ #
47
48# ############################################################################ #
49# #
50# surep_sendmail () : function for sending an email #
51# #
52# ############################################################################ #
53
54 surep_sendmail () {
55
56local FNAME="surep_sendmail"
57
58local usage="
59${FNAME} -- Send an email
60
61Usage: ${FNAME} OPTION...
62
63OPTION:
64 -h display this help and exit
65 -f ADDRESS from (=sender) email address
66 -t ADDRESS to (=recipient) email address(es)
67 -u SUBJECT message subject (def: empty)
68 -m MESSAGE message body (def: empty)
69 -s SERVER:PORT smtp mail relay
70 -o username=USERNAME username for SMTP authentication
71 -o password=PASSWORD password for SMTP authentication
72 -o fqdn=FQDN FQDN of this computer
73 -o isp=<none|ssl|tls> internet security protocol (def: tls)
74 -o pause=SECONDS wait time between each SMTP command (def: 1)
75"
76
77if [ $# -eq 0 ]
78then
79 printf '%s\n' "${usage}"
80 return 1
81fi
82
83# ---------------------------------------------------------------------------- #
84
85local _from _to _subject _message _server _username _password _fqdn _isp _pause
86local _from_email _to_email _server_fqdn _server_port
87
88_isp='tls'
89_pause=1
90
91local OPTION OPTIND OPTARG
92
93while getopts ":f:t:u:m:s:o:h" OPTION
94do
95 case "${OPTION}" in
96 h)
97 printf '%s\n' "${usage}"
98 return 0
99 ;;
100 f)
101 _from="${OPTARG}"
102 ;;
103 t)
104 if [ -z ${_to} ]
105 then
106 _to="${OPTARG}"
107 else
108 _to="${_to}, ${OPTARG}"
109 fi
110 ;;
111 u)
112 _subject="${OPTARG}"
113 ;;
114 m)
115 _message="${OPTARG}"
116 ;;
117 s)
118 _server="${OPTARG}"
119 _server_fqdn="${_server%:*}"
120 _server_port="${_server#*:}"
121 ;;
122 o)
123 case "${OPTARG}" in
124 username=*) _username="${OPTARG#username=}" ;;
125 password=*) _password="${OPTARG#password=}" ;;
126 fqdn=*) _fqdn="${OPTARG#fqdn=}" ;;
127 isp=*) _isp="${OPTARG#isp=}" ;;
128 pause=*) _pause="${OPTARG#pause=}" ;;
129 *)
130 printf '%s\n' "${FNAME}: illegal option -o ${OPTARG}" >&2
131 return 1
132 ;;
133 esac
134 ;;
135 :)
136 printf '%s\n' "${FNAME}: option requires an argument -${OPTARG}" >&2
137 return 1
138 ;;
139 ?)
140 printf '%s\n' "${FNAME}: illegal option -${OPTARG}" >&2
141 return 1
142 ;;
143 esac
144done
145
146# check mandatory arguments
147
148local _opt
149for _opt in _from _to _server _username _password _fqdn
150do
151 if [ -z "`eval printf '%s\n' \\${${_opt}}`" ]
152 then
153 case "${_opt}" in
154 _from)
155 printf '%s\n' "${FNAME}: option is mandatory -f" 1>&2
156 return 1
157 ;;
158 _to)
159 printf '%s\n' "${FNAME}: option is mandatory -t" 1>&2
160 return 1
161 ;;
162 _server)
163 printf '%s\n' "${FNAME}: option is mandatory -s" 1>&2
164 return 1
165 ;;
166 _username)
167 printf '%s\n' "${FNAME}: option is mandatory -o username=" 1>&2
168 return 1
169 ;;
170 _password)
171 printf '%s\n' "${FNAME}: option is mandatory -o password=" 1>&2
172 return 1
173 ;;
174 _fqdn)
175 printf '%s\n' "${FNAME}: option is mandatory -o fqdn=" 1>&2
176 return 1
177 ;;
178 esac
179 fi
180done
181
182# check server
183
184if [ -z ${_server_fqdn} ] || \
185 [ -z ${_server_port} ] || \
186 [ X"${_server}" != X"${_server_fqdn}:${_server_port}" ]
187then
188 printf '%s\n' "${FNAME}: wrong format for option -s '${_server}'" >&2
189 return 1
190fi
191
192# check protocol
193
194case "${_isp}" in
195 [tT][lL][sS])
196 _isp="-starttls smtp"
197 ;;
198 [sS][sS][lL])
199 _isp=""
200 ;;
201 [nN][oO][nN][eE])
202 printf '%s\n' "${FNAME}: plain text connexion is not supported -o isp=none"
203 return 0
204 ;;
205 *)
206 printf '%s\n' "${FNAME}: unknown protocol for option -o isp='${_isp}'" >&2
207 return 1
208 ;;
209esac
210
211# ---------------------------------------------------------------------------- #
212
213# reformat the sender string
214
215_from=`printf '%s\n' "${_from}" | /bin/sed -e 's/</ /' -e 's/>//' \
216 -e 's/ */ /g' \
217 -e 's/\([^ ]*@[^ ]*\) */<\1>/' \
218 -e 's/^ //'`
219
220# extract the "pure" email from the sender string
221
222_from_email=`printf '%s\n' "${_from}" | /bin/sed -e 's/[^<]*<\([^>]*\)>.*/\1/g'`
223
224# reformat the receivers string
225
226_to=`printf '%s\n' "${_to}" | /usr/bin/tr '\n' ','`
227_to=`printf '%s\n' "${_to}" | /bin/sed -e 's/</ /g' -e 's/>//g' \
228 -e 's/,/, /g' -e 's/ */ /g' \
229 -e 's/\([^ ]*@[^ ,)]*\) */<\1>/g' \
230 -e 's/^ //'`
231
232# extract the list of "pure" emails from the receiver string
233
234_to_email=`printf '%s\n' "${_to}" | /bin/sed -e 's/[^<]*<\([^>]*\)>[^<]*/\1 /g' \
235 -e 's/ $//'`
236
237# ---------------------------------------------------------------------------- #
238
239# create a shell pipe for communating with the SMTP client software
240
241if [ ! -e "${nodfile}" ]
242then
243 /bin/mknod "${nodfile}" p
244 exec 3<> "${nodfile}"
245fi
246
247# ---------------------------------------------------------------------------- #
248
249# launch the SMTP client and send the email
250
251eval /usr/syno/bin/openssl s_client "${_isp}" -connect "${_server}" -crlf -quiet -ign_eof <&3 2> /dev/null &
252local _pid=$!
253
254#
255# _auth : base64 authentification string for SMTP server
256#
257local _auth=`printf '\000%s\000%s' "${_username}" "${_password}" \
258 | /usr/syno/bin/openssl enc -base64 -A 2>/dev/null`
259
260local _email=
261
262printf '%s\n' "EHLO ${_server_fqdn}" >&3 ; /bin/sleep ${_pause}
263printf '%s\n' "AUTH PLAIN ${_auth}" >&3 ; /bin/sleep ${_pause}
264printf '%s\n' "HELO ${_fqdn}" >&3 ; /bin/sleep ${_pause}
265printf '%s\n' "MAIL FROM: <${_from_email}>" >&3 ; /bin/sleep ${_pause}
266for _email in ${_to_email}
267do
268 printf '%s\n' "RCPT TO: <${_email}>" >&3 ; /bin/sleep ${_pause}
269done
270printf '%s\n' "DATA" >&3 ; /bin/sleep ${_pause}
271printf '%s\n' "\
272Date: `/bin/date --rfc-2822`
273Subject: ${_subject}
274From: ${_from}
275To: ${_to}
276${_message}
277." >&3 ; /bin/sleep ${_pause}
278printf '%s\n' "QUIT" >&3 ; /bin/sleep ${_pause}
279
280wait ${_pid}
281
282}
283
284# ############################# (surep_sendmail) ############################# #
285
286# ============================================================================ #
287
288#
289# surep_snapshot_header : first bytes of a snapshot file
290#
291surep_snapshot_header="SuRep snapshot format 1"
292
293# ============================================================================ #
294
295# ############################################################################ #
296# #
297# surep_mksnapshot () : function that takes a snapshot of a directory #
298# #
299# ############################################################################ #
300
301 surep_mksnapshot () {
302
303local FNAME="surep_mksnapshot"
304
305local usage="
306${FNAME} -- Take a snapshot of the files in a directory
307
308Usage: ${FNAME} DIR...
309
310Take a snapshot of all the files in DIR(s) with the following format :
311
312file size blocks mode uid gid devid inode hard major minor access modify change iob
313
314Where :
315
316file = File name encoded in base64
317size = File size in bytes
318blocks = Number of used blocks
319mode = File type and ACLs
320uid = Owner UID
321gid = Owner GID
322devid = Device number
323inode = Inode number
324hard = Number of hardlinks referencing the file
325major = Major number
326Minor = Minor number
327access = Last access date in second since Epoch
328modify = Last modify date in second since Epoch
329change = Last change date in second since Epoch
330iob = Block size in bytes
331"
332
333if [ $# -eq 0 ]
334then
335 printf '%s\n' "${usage}"
336 return 1
337fi
338
339# ---------------------------------------------------------------------------- #
340
341printf '%s\n' "${surep_snapshot_header}"
342
343/usr/bin/find "${@}" -type f -print0 | /usr/bin/xargs -0 /bin/sh -c '
344for file in "${0}" "${@}"
345do
346 stat=$(/bin/stat -t "${file}")
347 stat=${stat#"${file} "}
348 file=$(printf "%s" "${file}" | /usr/syno/bin/openssl enc -base64 -A 2> /dev/null)
349 printf "%s %s\n" "${file}" "${stat}"
350done' | /usr/bin/sort
351
352}
353
354# ############################ (surep_mksnapshot) ############################ #
355
356# ============================================================================ #
357
358#
359# surep_diffdb_header : first bytes of a SuRep diff database file
360#
361surep_diffdb_header="SQLite format 3"
362
363# ============================================================================ #
364
365# ############################################################################ #
366# #
367# surep_mkdiffdb () : function that compares two snapshots and stores the #
368# the differences in a database #
369# #
370# ############################################################################ #
371
372 surep_mkdiffdb () {
373
374local FNAME="surep_mkdiffdb"
375
376local usage="
377${FNAME} -- Make a database of differences between snapshots
378
379Usage: ${FNAME} DIFFDB SNAPSHOT SNAPSHOT
380
381Create a database file DIFFDB filled with the non matching lines between the
382two SNAPSHOT files
383"
384
385if [ $# -ne 3 ]
386then
387 printf '%s\n' "${usage}"
388 return
389fi
390
391# ---------------------------------------------------------------------------- #
392
393local _diffdb="${1}"
394local _snap_1="${2}"
395local _snap_2="${3}"
396
397# verify DIFFDB
398
399if [ -s "${_diffdb}" ]
400then
401 if [ ! -f "${_diffdb}" ] || [ X"`/usr/bin/head -c ${#surep_diffdb_header} "${_diffdb}" 2> /dev/null`" != X"${surep_diffdb_header}" ]
402 then
403 printf '%s\n' "${FNAME}: ${_diffdb}: not a diffdb file" 1>&2
404 return 1
405 fi
406else
407 if [ -n "${_diffdb%/*}" ]
408 then
409 /bin/mkdir -p "${_diffdb%/*}" 2> /dev/null
410 if [ $? -ne 0 ]
411 then
412 printf '%s\n' "${FNAME}: can't create diffdb file '${_diffdb}': Permission denied" 1>&2
413 return 1
414 fi
415 fi
416 /bin/touch "${_diffdb}" 2> /dev/null
417 if [ $? -ne 0 ]
418 then
419 printf '%s\n' "${FNAME}: can't create diffdb file '${_diffdb}': Permission denied" 1>&2
420 return 1
421 fi
422fi
423
424# verify SNAPSHOT 1
425
426if [ ! -e "${_snap_1}" ]
427then
428 printf '%s\n' "${FNAME}: ${_snap_1}: no such file" 1>&2
429 return 1
430fi
431if [ ! -r "${_snap_1}" ]
432then
433 printf '%s\n' "${FNAME}: ${_snap_1}: permission denied" 1>&2
434 return 1
435fi
436if [ ! -f "${_snap_1}" ] || [ X"`/usr/bin/head -c ${#surep_snapshot_header} "${_snap_1}" 2> /dev/null`" != X"${surep_snapshot_header}" ]
437then
438 printf '%s\n' "${FNAME}: ${_snap_1}: not a snapshot file" 1>&2
439 return 1
440fi
441
442# verify SNAPSHOT 2
443
444if [ ! -e "${_snap_2}" ]
445then
446 printf '%s\n' "${FNAME}: ${_snap_2}: no such file" 1>&2
447 return 1
448fi
449if [ ! -r "${_snap_2}" ]
450then
451 printf '%s\n' "${FNAME}: ${_snap_2}: permission denied" 1>&2
452 return 1
453fi
454if [ ! -f "${_snap_2}" ] || [ X"`/usr/bin/head -c ${#surep_snapshot_header} "${_snap_2}" 2> /dev/null`" != X"${surep_snapshot_header}" ]
455then
456 printf '%s\n' "${FNAME}: ${_snap_2}: not a snapshot file" 1>&2
457 return 1
458fi
459
460# ---------------------------------------------------------------------------- #
461
462# create tables in database
463
464/usr/bin/sqlite3 "${_diffdb}" <<EOF
465
466drop table if exists T_PLUS;
467
468create table T_PLUS (
469 file text, -- file name (base64 encoded)
470 size integer, -- size in bytes
471 blocks integer, -- number of blocks
472 type integer, -- file type
473 acl integer, -- access control list (sugo)
474 uid integer, -- user id of owner
475 gid integer, -- group id of owner
476 devid integer, -- device id
477 inode integer, -- inode number
478 hard integer, -- number of hard hard pointing to this file
479 major integer, -- major number
480 minor integer, -- minor number
481 access integer, -- last access date
482 modify integer, -- last modify date
483 change integer, -- last change date
484 iob integer -- size of blocks
485);
486
487drop table if exists T_MINUS;
488
489create table T_MINUS (
490 file text, -- file name (base64 encoded)
491 size integer, -- size in bytes
492 blocks integer, -- number of blocks
493 type integer, -- file type
494 acl integer, -- access control list (sugo)
495 uid integer, -- user id of owner
496 gid integer, -- group id of owner
497 devid integer, -- device id
498 inode integer, -- inode number
499 hard integer, -- number of hard hard pointing to this file
500 major integer, -- major number
501 minor integer, -- minor number
502 access integer, -- last access date
503 modify integer, -- last modify date
504 change integer, -- last change date
505 iob integer -- size of blocks
506);
507
508EOF
509
510# ---------------------------------------------------------------------------- #
511
512# right order for reading the lines of surep_mksnapshot
513
514local _file _size _blocks _mode _uid _gid _devid _inode _hard _major _minor _access _modify _change _iob
515local _type _acl _table
516
517# inserting the file stats in the diff database
518
519while read _file _size _blocks _mode _uid _gid _devid _inode _hard _major _minor _access _modify _change _iob
520do
521 if [ -z "${_file}" ]
522 then
523 continue
524 fi
525
526 case "${_file}" in
527 -*) _table=T_MINUS
528 ;;
529 +*) _table=T_PLUS
530 ;;
531 esac
532
533 _file=${_file#?}
534 _type=${_mode%???}
535 _acl=${_mode#?}
536
537 printf "insert into ${_table} values ('%s',%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d);\n" \
538 "${_file}" \
539 "${_size}" \
540 "${_blocks}" \
541 "0x${_type}" \
542 "0x${_acl}" \
543 "${_uid}" \
544 "${_gid}" \
545 "0x${_devid}" \
546 "${_inode}" \
547 "${_hard}" \
548 "${_major}" \
549 "${_minor}" \
550 "${_access}" \
551 "${_modify}" \
552 "${_change}" \
553 "${_iob}"
554
555done <<EOF | /usr/bin/sqlite3 "${_diffdb}"
556`/usr/bin/diff -U 0 "${_snap_1}" "${_snap_2}" | /bin/grep -v -e '^[@+-][@+-]'`
557EOF
558
559}
560
561# ############################# (surep_mkdiffdb) ############################# #
562
563# ============================================================================ #
564
565# ############################################################################ #
566# #
567# surep_lsdiffdb () : function for displaying different views of the content #
568# of a diff database #
569# #
570# ############################################################################ #
571
572 surep_lsdiffdb () {
573
574local FNAME="surep_lsdiffdb"
575
576local usage="
577Usage: ${FNAME} [OPTION]... DIFFDB
578
579Extract various views from the DIFFDB database file
580
581OPTIONS
582 -h display this help and exit
583 -n display new files
584 -d display deleted files
585 -m display modified files
586 -r display renamed files
587 -x display new files excluding the renamed ones
588"
589
590local _view=
591
592local OPTION OPTIND OPTARG
593
594while getopts ":hndmrx" OPTION
595do
596 case "${OPTION}" in
597 h)
598 printf '%s\n' "${usage}"
599 return 0
600 ;;
601 n)
602 _view="${_view} n"
603 ;;
604 d)
605 _view="${_view} d"
606 ;;
607 m)
608 _view="${_view} m"
609 ;;
610 r)
611 _view="${_view} r"
612 ;;
613 x)
614 _view="${_view} x"
615 ;;
616 :)
617 printf '%s\n' "${FNAME}: option requires an argument -${OPTARG}" >&2
618 return 1
619 ;;
620 ?)
621 printf '%s\n' "${FNAME}: illegal option -${OPTARG}" >&2
622 return 1
623 ;;
624 esac
625done
626shift `/usr/bin/expr ${OPTIND} - 1`
627
628if [ $# -ne 1 ]
629then
630 printf '%s\n' "${usage}" 1>&2
631 return 1
632fi
633
634# ---------------------------------------------------------------------------- #
635
636local _diffdb="${1}"
637
638# verify DIFFDB
639
640if [ ! -e "${_diffdb}" ]
641then
642 printf '%s\n' "${FNAME}: ${_diffdb}: no such file" 1>&2
643 return 1
644fi
645if [ ! -r "${_diffdb}" ]
646then
647 printf '%s\n' "${FNAME}: ${_diffdb}: permission denied" 1>&2
648 return 1
649fi
650if [ ! -f "${_diffdb}" ] || [ X"`/usr/bin/head -c ${#surep_diffdb_header} "${_diffdb}" 2> /dev/null`" != X"${surep_diffdb_header}" ]
651then
652 printf '%s\n' "${FNAME}: ${_diffdb}: not a diffdb file" 1>&2
653 return 1
654fi
655
656# ---------------------------------------------------------------------------- #
657
658# We suppose that two files with the same Name, Inode, ModDate and Size
659# are identical (rsync algorithm)
660
661local _file
662
663for _view in ${_view}
664do
665 case ${_view} in
666
667 n) # display new files
668
669/usr/bin/sqlite3 "${_diffdb}" <<SQLITE
670.separator " "
671select file from T_PLUS where file not in (select file from T_MINUS);
672SQLITE
673 ;;
674
675 d) # display deleted files
676
677/usr/bin/sqlite3 "${_diffdb}" <<SQLITE
678.separator " "
679select file from T_MINUS where file not in (select file from T_PLUS);
680SQLITE
681 ;;
682
683 m) # display modified files
684
685/usr/bin/sqlite3 "${_diffdb}" <<SQLITE
686.separator " "
687select P.file from T_PLUS P left join T_MINUS M
688on P.file = M.file
689where P.inode != M.inode or P.modify != M.modify or P.size != M.size ;
690SQLITE
691 ;;
692
693 r) # display renamed files (not 100% accurate because an inode may
694 # be recycled and allocated for a file of
695 # the same size and modification time)
696
697/usr/bin/sqlite3 "${_diffdb}" <<SQLITE
698.separator " "
699select P.file from T_PLUS P left join T_MINUS M
700on M.inode = P.inode
701where M.file != P.file and M.modify = P.modify and M.size = P.size;
702SQLITE
703 ;;
704
705 x) # display new file excluding the renamed ones
706
707/usr/bin/sqlite3 "${_diffdb}" <<SQLITE
708.separator " "
709select file from T_PLUS where file not in (select file from T_MINUS)
710except
711select P.file from T_PLUS P left join T_MINUS M
712on M.inode = P.inode
713where M.file != P.file and M.modify = P.modify and M.size = P.size;
714SQLITE
715 ;;
716 esac
717done
718
719}
720
721# ############################# (surep_lsdiffdb) ############################# #
722
723# ============================================================================ #
724
725SCRIPTNAME="${0##*/}"
726
727usage="
728Usage: ${SCRIPTNAME} -c CONFIG
729"
730
731while getopts ":c:h" OPTION
732do
733 case "${OPTION}" in
734 h)
735 printf '%s\n' "${usage}"
736 exit 0
737 ;;
738 c)
739 config="${OPTARG}"
740 ;;
741 :)
742 printf '%s\n' "${FNAME}: option requires an argument -${OPTARG}" 1>&2
743 return 1
744 ;;
745 ?)
746 printf '%s\n' "${FNAME}: illegal option -${OPTARG}" 1>&2
747 return 1
748 ;;
749 esac
750done
751shift `/usr/bin/expr ${OPTIND} - 1`
752
753# ============================================================================ #
754
755# check if configuration file is correct
756
757if [ ! -e "${config}" ]
758then
759 printf '%s\n' "${SCRIPTNAME}: ${config}: no such configuration file" 1>&2
760 exit 1
761fi
762if [ ! -f "${config}" ]
763then
764 printf '%s\n' "${SCRIPTNAME}: ${config}: not a configuration file" 1>&2
765 exit 1
766fi
767if [ ! -r "${config}" ]
768then
769 printf '%s\n' "${SCRIPTNAME}: ${config}: permission denied" 1>&2
770 exit 1
771fi
772
773# load the configuration file
774
775. "${config}"
776
777# verify compatibility of the configuration
778
779if [ -z "${conf_compat}" ] || [ X"${version%.*}" != X"${conf_compat}" ]
780then
781 printf '%s\n' "${SCRIPTNAME}: ${config}: incompatible configuration file" 1>&2
782 exit 1
783fi
784
785# verify nas_dir
786
787if [ ! -d "${nas_dir}" ]
788then
789 printf '%s\n' "${SCRIPTNAME}: ${nas_dir}: no such directory" 1>&2
790 exit 1
791fi
792
793# verify snapshot_dir
794
795if [ ! -d "${snapshot_dir}" ]
796then
797 /bin/mkdir -p "${snapshot_dir}" 2> /dev/null
798 if [ $? -ne 0 ]
799 then
800 printf '%s\n' "${SCRIPTNAME}: ${snapshot_dir}: cannot create snapshot directory" 1>&2
801 exit 1
802 fi
803fi
804
805# ============================================================================ #
806
807/bin/date '+[%Y-%m-%d %H:%M:%S] launched SuRep'
808
809# snapshot_id : unique identifier for the snapshots of this nas_dir
810snapshot_id="`printf '%s\n' "${nas_dir}" | /usr/syno/bin/openssl enc -base64 -A 2> /dev/null`"
811
812# snapshot_file: file containing the snapshot
813snapshot_file="${snapshot_dir}/${snapshot_id}.ss"
814
815# save previous snapshot file
816
817if [ -e "${snapshot_file}" ]
818then
819 /bin/mv "${snapshot_file}" "${snapshot_file}.0"
820fi
821
822# make a new snapshot of nas_dir
823
824/bin/date "+[%Y-%m-%d %H:%M:%S] taking a new snapshot of '${nas_dir}'"
825
826surep_mksnapshot "${nas_dir}" > "${snapshot_file}"
827
828/bin/date "+[%Y-%m-%d %H:%M:%S] snapshot done"
829
830# is that the first run for 'nas_dir' ?
831
832if [ ! -e "${snapshot_file}.0" ]
833then
834 /bin/date "+[%Y-%m-%d %H:%M:%S] detected initial run, see you next time !"
835 exit 0
836fi
837
838# ============================================================================ #
839
840# generating a temporary diff database
841
842/bin/date "+[%Y-%m-%d %H:%M:%S] creating diff database by comparing snapshots"
843
844surep_mkdiffdb "${ddbfile}" "${snapshot_file}.0" "${snapshot_file}"
845
846/bin/date "+[%Y-%m-%d %H:%M:%S] diff database generated"
847
848# clean old snapshot
849
850/bin/rm -f "${snapshot_file}.0"
851
852# ============================================================================ #
853
854# what are we asked to display ?
855
856/bin/date "+[%Y-%m-%d %H:%M:%S] getting the requested file list from the diff database"
857
858case ${notify_level} in
859
860 0) # new - renamed files
861 filelist="`surep_lsdiffdb -x "${ddbfile}"`"
862 ;;
863
864 1) # new files
865 filelist="`surep_lsdiffdb -n "${ddbfile}"`"
866 ;;
867
868 2) # new - renamed + edited files
869 filelist="`surep_lsdiffdb -x -m "${ddbfile}"`"
870 ;;
871 3) # new + edited files
872 filelist="`surep_lsdiffdb -n -m "${ddbfile}"`"
873 ;;
874esac
875
876# filter the result
877
878if [ -z "${exclude_filter}" ] && [ -z "${include_filter}" ]
879then
880 filtlist="${filelist}"
881else
882 filtlist=
883
884 while read file64
885 do
886 file=`printf '%s\n' "${file64}" | /usr/syno/bin/openssl enc -base64 -d -A 2>/dev/null`
887 filt=
888 if [ ! -z "${exclude_filter}" ] && [ ! -z "${include_filter}" ]
889 then
890 filt=`eval "case \"\${file}\" in
891 ${exclude_filter}) ;;
892 ${include_filter}) printf '%s\n' \"\${file64}\" ;;
893 esac"`
894 elif [ ! -z "${exclude_filter}" ]
895 then
896 filt=`eval "case \"\${file}\" in
897 ${exclude_filter}) ;;
898 *) printf '%s\n' \"\${file64}\" ;;
899 esac"`
900 else
901 # [ ! -z "${include_filter}" ]
902 filt=`eval "case \"\${file}\" in
903 ${include_filter}) printf '%s\n' \"\${file64}\" ;;
904 esac"`
905 fi
906 if [ -n "${filt}" ]
907 then
908 filtlist="${filtlist}"$'\n'"${filt}"
909 fi
910 done <<EOF
911${filelist}
912EOF
913 filtlist="${filtlist#?}"
914fi
915
916# is there something to display ?
917
918if [ -z "${filtlist}" ]
919then
920 /bin/date "+[%Y-%m-%d %H:%M:%S] no changes to report, see you next time !"
921 exit 0
922fi
923
924# ============================================================================ #
925
926# convert the file list from base64 to human language and apply the user view
927
928viewlist=
929
930while read file64
931do
932 file=`printf '%s\n' "${file64}" | /usr/syno/bin/openssl enc -base64 -d -A 2>/dev/null`
933 if [ ! -z ${message_nasdir+x} ]
934 then
935 file="${message_nasdir}${file#${nas_dir}}"
936 fi
937 viewlist="${viewlist}"$'\n'"${file}"
938done <<EOF
939${filtlist}
940EOF
941
942viewlist="${viewlist#?}"
943
944# ============================================================================ #
945
946# replace @FILELIST@ with the file list in the email message
947
948case "${message_body}" in
949 *@FILELIST@*)
950 message_head=${message_body%@FILELIST@*}
951 message_tail=${message_body#*@FILELIST@}
952 message_body="${message_head}${viewlist}${message_tail}"
953 ;;
954esac
955
956# ============================================================================ #
957
958#
959# nas_fqdn : NAS Full Qualified Domain Name (extracted from the NAS url)
960#
961nas_fqdn="`printf '%s\n' "${nas_url}" | /bin/sed -e 's#^.*://\([^/: ]*\).*#\1#'`"
962
963# send the email
964
965/bin/date "+[%Y-%m-%d %H:%M:%S] sending notification email :"
966printf '--------------------------------------------------\n'
967printf '%s\n' "${message_body}"
968printf '--------------------------------------------------\n'
969
970surep_sendmail -f "${sender_email}" \
971 -t "${recipient_email}" \
972 -u "${message_subject}" \
973 -m "${message_body}" \
974 -s "${smtp_server}" \
975 -o username="${smtp_username}" \
976 -o password="${smtp_password}" \
977 -o fqdn="${nas_fqdn}" \
978 -o isp="${smtp_isp}" \
979 -o pause="${smtp_cmdwait}"
980
981/bin/date "+[%Y-%m-%d %H:%M:%S] a notification should have been sent by email, goodbye !"
982
983# ############################################################################ #
984# ############################################################################ #
985# ############################################################################ #