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