Advertisement
Guest User

surep.sh

a guest
Apr 11th, 2016
245
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 29.17 KB | None | 0 0
  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.  
  41. ddbfile="/tmp/SuRep-`/bin/date '+%s'`-$$.ddb"
  42. nodfile="/tmp/SuRep-`/bin/date '+%s'`-$$.nod"
  43.  
  44. trap "exit 2" 1 2 3 15
  45. trap "/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.  
  57. local FNAME="surep_sendmail"
  58.  
  59. local usage="
  60. ${FNAME} -- Send an email
  61.  
  62. Usage: ${FNAME} OPTION...
  63.  
  64. OPTION:
  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.  
  78. if [ $# -eq 0 ]
  79. then
  80.     printf '%s\n' "${usage}"
  81.     return 1
  82. fi
  83.  
  84. # ---------------------------------------------------------------------------- #
  85.  
  86. local _from _to _subject _message _server _username _password _fqdn _isp _pause
  87. local _from_email _to_email _server_fqdn _server_port
  88.  
  89. _isp='tls'
  90. _pause=1
  91.  
  92. local OPTION OPTIND OPTARG
  93.  
  94. while getopts ":f:t:u:m:s:o:h" OPTION
  95. do
  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
  145. done
  146.  
  147. # check mandatory arguments
  148.  
  149. local _opt
  150. for _opt in _from _to _server _username _password _fqdn
  151. do
  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
  181. done
  182.  
  183. # check server
  184.  
  185. if [ -z ${_server_fqdn} ] || \
  186.    [ -z ${_server_port} ] || \
  187.    [ X"${_server}" != X"${_server_fqdn}:${_server_port}" ]
  188. then
  189.     printf '%s\n' "${FNAME}: wrong format for option -s '${_server}'" >&2
  190.     return 1
  191. fi
  192.  
  193. # check protocol
  194.  
  195. case "${_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.     ;;
  210. esac
  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.  
  242. if [ ! -e "${nodfile}" ]
  243. then
  244.     /bin/mknod "${nodfile}" p
  245.     exec 3<> "${nodfile}"
  246. fi
  247.  
  248. # ---------------------------------------------------------------------------- #
  249.  
  250. # launch the SMTP client and send the email
  251.  
  252. eval /usr/bin/openssl s_client "${_isp}" -connect "${_server}" -crlf -quiet -ign_eof <&3 2> /dev/null &
  253. local _pid=$!
  254.  
  255. #
  256. # _auth : base64 authentification string for SMTP server
  257. #
  258. local _auth=`printf '\000%s\000%s' "${_username}" "${_password}" \
  259.            | /usr/bin/openssl enc -base64 -A 2>/dev/null`
  260.  
  261. local _email=
  262.  
  263. printf '%s\n' "EHLO ${_server_fqdn}"        >&3 ; /bin/sleep ${_pause}
  264. printf '%s\n' "AUTH PLAIN ${_auth}"         >&3 ; /bin/sleep ${_pause}
  265. printf '%s\n' "HELO ${_fqdn}"               >&3 ; /bin/sleep ${_pause}
  266. printf '%s\n' "MAIL FROM: <${_from_email}>" >&3 ; /bin/sleep ${_pause}
  267. for _email in ${_to_email}
  268. do
  269.     printf '%s\n' "RCPT TO: <${_email}>"    >&3 ; /bin/sleep ${_pause}
  270. done
  271. printf '%s\n' "DATA"                        >&3 ; /bin/sleep ${_pause}
  272. printf '%s\n' "\
  273. Date: `/bin/date --rfc-2822`
  274. Subject: ${_subject}
  275. From: ${_from}
  276. To: ${_to}
  277. ${_message}
  278. ."                                          >&3 ; /bin/sleep ${_pause}
  279. printf '%s\n' "QUIT"                        >&3 ; /bin/sleep ${_pause}
  280.  
  281. wait ${_pid}
  282.  
  283. }
  284.  
  285. # ############################# (surep_sendmail) ############################# #
  286.  
  287. # ============================================================================ #
  288.  
  289. #
  290. # surep_snapshot_header : first bytes of a snapshot file
  291. #
  292. surep_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.  
  304. local FNAME="surep_mksnapshot"
  305.  
  306. local usage="
  307. ${FNAME} -- Take a snapshot of the files in a directory
  308.  
  309. Usage: ${FNAME} DIR...
  310.  
  311. Take a snapshot of all the files in DIR(s) with the following format :
  312.  
  313. file size blocks mode uid gid devid inode hard major minor access modify change iob
  314.  
  315. Where :
  316.  
  317. file   = File name encoded in base64
  318. size   = File size in bytes
  319. blocks = Number of used blocks
  320. mode   = File type and ACLs
  321. uid    = Owner UID
  322. gid    = Owner GID
  323. devid  = Device number
  324. inode  = Inode number
  325. hard   = Number of hardlinks referencing the file
  326. major  = Major number
  327. Minor  = Minor number
  328. access = Last access date in second since Epoch
  329. modify = Last modify date in second since Epoch
  330. change = Last change date in second since Epoch
  331. iob    = Block size in bytes
  332. "
  333.  
  334. if [ $# -eq 0 ]
  335. then
  336.     printf '%s\n' "${usage}"
  337.     return 1
  338. fi
  339.  
  340. # ---------------------------------------------------------------------------- #
  341.  
  342. printf '%s\n' "${surep_snapshot_header}"
  343.  
  344. /usr/bin/find "${@}" -type f -print0 | /usr/bin/xargs -0 /bin/sh -c '
  345. for file in "${0}" "${@}"
  346. do
  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}"
  351. done' | /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. #
  362. surep_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.  
  375. local FNAME="surep_mkdiffdb"
  376.  
  377. local usage="
  378. ${FNAME} -- Make a database of differences between snapshots
  379.  
  380. Usage: ${FNAME} DIFFDB SNAPSHOT SNAPSHOT
  381.  
  382. Create a database file DIFFDB filled with the non matching lines between the
  383. two SNAPSHOT files
  384. "
  385.  
  386. if [ $# -ne 3 ]
  387. then
  388.     printf '%s\n' "${usage}"
  389.     return
  390. fi
  391.  
  392. # ---------------------------------------------------------------------------- #
  393.  
  394. local _diffdb="${1}"
  395. local _snap_1="${2}"
  396. local _snap_2="${3}"
  397.  
  398. # verify DIFFDB
  399.  
  400. if [ -s "${_diffdb}" ]
  401. then
  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
  407. else
  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
  423. fi
  424.  
  425. # verify SNAPSHOT 1
  426.  
  427. if [ ! -e "${_snap_1}" ]
  428. then
  429.     printf '%s\n' "${FNAME}: ${_snap_1}: no such file" 1>&2
  430.     return 1
  431. fi
  432. if [ ! -r "${_snap_1}" ]
  433. then
  434.     printf '%s\n' "${FNAME}: ${_snap_1}: permission denied" 1>&2
  435.     return 1
  436. fi
  437. if [ ! -f "${_snap_1}" ] || [ X"`/usr/bin/head -c ${#surep_snapshot_header} "${_snap_1}" 2> /dev/null`" != X"${surep_snapshot_header}" ]
  438. then
  439.     printf '%s\n' "${FNAME}: ${_snap_1}: not a snapshot file" 1>&2
  440.     return 1
  441. fi  
  442.  
  443. # verify SNAPSHOT 2
  444.  
  445. if [ ! -e "${_snap_2}" ]
  446. then
  447.     printf '%s\n' "${FNAME}: ${_snap_2}: no such file" 1>&2
  448.     return 1
  449. fi
  450. if [ ! -r "${_snap_2}" ]
  451. then
  452.     printf '%s\n' "${FNAME}: ${_snap_2}: permission denied" 1>&2
  453.     return 1
  454. fi
  455. if [ ! -f "${_snap_2}" ] || [ X"`/usr/bin/head -c ${#surep_snapshot_header} "${_snap_2}" 2> /dev/null`" != X"${surep_snapshot_header}" ]
  456. then
  457.     printf '%s\n' "${FNAME}: ${_snap_2}: not a snapshot file" 1>&2
  458.     return 1
  459. fi  
  460.  
  461. # ---------------------------------------------------------------------------- #
  462.  
  463. # create tables in database
  464.  
  465. /usr/bin/sqlite3 "${_diffdb}" <<EOF
  466.  
  467. drop table if exists T_PLUS;
  468.  
  469. create 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.  
  488. drop table if exists T_MINUS;
  489.  
  490. create 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.  
  509. EOF
  510.  
  511. # ---------------------------------------------------------------------------- #
  512.  
  513. # right order for reading the lines of surep_mksnapshot
  514.  
  515. local _file _size _blocks _mode _uid _gid _devid _inode _hard _major _minor _access _modify _change _iob
  516. local _type _acl _table
  517.  
  518. # inserting the file stats in the diff database
  519.  
  520. while read _file _size _blocks _mode _uid _gid _devid _inode _hard _major _minor _access _modify _change _iob
  521. do
  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.  
  556. done <<EOF | /usr/bin/sqlite3 "${_diffdb}"
  557. `/usr/bin/diff -U 0 "${_snap_1}" "${_snap_2}" | /bin/grep -v -e '^[@+-][@+-]'`
  558. EOF
  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.  
  575. local FNAME="surep_lsdiffdb"
  576.  
  577. local usage="
  578. Usage: ${FNAME} [OPTION]... DIFFDB
  579.  
  580. Extract various views from the DIFFDB database file
  581.  
  582. OPTIONS
  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.  
  591. local _view=
  592.  
  593. local OPTION OPTIND OPTARG
  594.  
  595. while getopts ":hndmrx" OPTION
  596. do
  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
  626. done
  627. shift `/usr/bin/expr ${OPTIND} - 1`
  628.  
  629. if [ $# -ne 1 ]
  630. then
  631.     printf '%s\n' "${usage}" 1>&2
  632.     return 1
  633. fi
  634.  
  635. # ---------------------------------------------------------------------------- #
  636.  
  637. local _diffdb="${1}"
  638.  
  639. # verify DIFFDB
  640.  
  641. if [ ! -e "${_diffdb}" ]
  642. then
  643.      printf '%s\n' "${FNAME}: ${_diffdb}: no such file" 1>&2
  644.      return 1
  645. fi
  646. if [ ! -r "${_diffdb}" ]
  647. then
  648.      printf '%s\n' "${FNAME}: ${_diffdb}: permission denied" 1>&2
  649.      return 1
  650. fi
  651. if [ ! -f "${_diffdb}" ] || [ X"`/usr/bin/head -c ${#surep_diffdb_header} "${_diffdb}" 2> /dev/null`" != X"${surep_diffdb_header}" ]
  652. then
  653.     printf '%s\n' "${FNAME}: ${_diffdb}: not a diffdb file" 1>&2
  654.     return 1
  655. fi
  656.  
  657. # ---------------------------------------------------------------------------- #
  658.  
  659. # We suppose that two files with the same Name, Inode, ModDate and Size
  660. # are identical (rsync algorithm)
  661.  
  662. local _file
  663.  
  664. for _view in ${_view}
  665. do
  666.     case ${_view} in
  667.  
  668.         n)  # display new files
  669.  
  670. /usr/bin/sqlite3 "${_diffdb}" <<SQLITE
  671. .separator " "
  672. select file from T_PLUS where file not in (select file from T_MINUS);
  673. SQLITE
  674.         ;;
  675.  
  676.         d)  # display deleted files
  677.  
  678. /usr/bin/sqlite3 "${_diffdb}" <<SQLITE
  679. .separator " "
  680. select file from T_MINUS where file not in (select file from T_PLUS);
  681. SQLITE
  682.         ;;
  683.  
  684.         m)  # display modified files
  685.  
  686. /usr/bin/sqlite3 "${_diffdb}" <<SQLITE
  687. .separator " "
  688. select P.file from T_PLUS P left join T_MINUS M
  689. on P.file = M.file
  690. where P.inode != M.inode or P.modify != M.modify or P.size != M.size ;
  691. SQLITE
  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 " "
  700. select P.file from T_PLUS P left join T_MINUS M
  701. on M.inode = P.inode
  702. where M.file != P.file and M.modify = P.modify and M.size = P.size;
  703. SQLITE
  704.         ;;
  705.  
  706.         x)  # display new file excluding the renamed ones
  707.  
  708. /usr/bin/sqlite3 "${_diffdb}" <<SQLITE
  709. .separator " "
  710. select file from T_PLUS where file not in (select file from T_MINUS)
  711. except
  712. select P.file from T_PLUS P left join T_MINUS M
  713. on M.inode = P.inode
  714. where M.file != P.file and M.modify = P.modify and M.size = P.size;
  715. SQLITE
  716.         ;;
  717.     esac
  718. done
  719.  
  720. }
  721.  
  722. # ############################# (surep_lsdiffdb) ############################# #
  723.  
  724. # ============================================================================ #
  725.  
  726. SCRIPTNAME="${0##*/}"
  727.  
  728. usage="
  729. Usage: ${SCRIPTNAME} -c CONFIG
  730. "
  731.  
  732. while getopts ":c:h" OPTION
  733. do      
  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
  751. done
  752. shift `/usr/bin/expr ${OPTIND} - 1`
  753.  
  754. # ============================================================================ #
  755.  
  756. # check if configuration file is correct
  757.  
  758. if [ ! -e "${config}" ]
  759. then
  760.     printf '%s\n' "${SCRIPTNAME}: ${config}: no such configuration file" 1>&2
  761.     exit 1
  762. fi
  763. if [ ! -f "${config}" ]
  764. then
  765.     printf '%s\n' "${SCRIPTNAME}: ${config}: not a configuration file" 1>&2
  766.     exit 1
  767. fi
  768. if [ ! -r "${config}" ]
  769. then
  770.     printf '%s\n' "${SCRIPTNAME}: ${config}: permission denied" 1>&2
  771.     exit 1
  772. fi
  773.  
  774. # load the configuration file
  775.  
  776. . "${config}"
  777.  
  778. # verify compatibility of the configuration
  779.  
  780. if [ -z "${conf_compat}" ] || [ X"${version%.*}" != X"${conf_compat}" ]
  781. then
  782.     printf '%s\n' "${SCRIPTNAME}: ${config}: incompatible configuration file" 1>&2
  783.     exit 1
  784. fi
  785.  
  786. # verify nas_dir
  787.  
  788. if [ ! -d "${nas_dir}" ]
  789. then
  790.     printf '%s\n' "${SCRIPTNAME}: ${nas_dir}: no such directory" 1>&2
  791.     exit 1
  792. fi
  793.  
  794. # verify snapshot_dir
  795.  
  796. if [ ! -d "${snapshot_dir}" ]
  797. then
  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
  804. fi
  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
  811. snapshot_id="`printf '%s\n' "${nas_dir}" | /usr/bin/openssl enc -base64 -A 2> /dev/null`"
  812.  
  813. # snapshot_file: file containing the snapshot
  814. snapshot_file="${snapshot_dir}/${snapshot_id}.ss"
  815.  
  816. # save previous snapshot file
  817.  
  818. if [ -e "${snapshot_file}" ]
  819. then
  820.     /bin/mv "${snapshot_file}" "${snapshot_file}.0"
  821. fi
  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.  
  827. surep_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.  
  833. if [ ! -e "${snapshot_file}.0" ]
  834. then
  835.     /bin/date "+[%Y-%m-%d %H:%M:%S] detected initial run, see you next time !"
  836.     exit 0
  837. fi
  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.  
  845. surep_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.  
  859. case ${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.     ;;
  875. esac
  876.  
  877. # filter the result
  878.  
  879. if [ -z "${exclude_filter}" ] && [ -z "${include_filter}" ]
  880. then
  881.     filtlist="${filelist}"
  882. else
  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}
  913. EOF
  914.     filtlist="${filtlist#?}"
  915. fi
  916.  
  917. # is there something to display ?
  918.  
  919. if [ -z "${filtlist}" ]
  920. then
  921.     /bin/date "+[%Y-%m-%d %H:%M:%S] no changes to report, see you next time !"
  922.     exit 0
  923. fi
  924.  
  925. # ============================================================================ #
  926.  
  927. # convert the file list from base64 to human language and apply the user view
  928.  
  929. viewlist=
  930.  
  931. while read file64
  932. do
  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}"
  939. done <<EOF
  940. ${filtlist}
  941. EOF
  942.  
  943. viewlist="${viewlist#?}"
  944.  
  945. # ============================================================================ #
  946.  
  947. # replace @FILELIST@ with the file list in the email message
  948.  
  949. case "${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.     ;;
  955. esac
  956.  
  957. # ============================================================================ #
  958.  
  959. #
  960. # nas_fqdn : NAS Full Qualified Domain Name (extracted from the NAS url)
  961. #
  962. nas_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 :"
  967. printf '--------------------------------------------------\n'
  968. printf '%s\n' "${message_body}"
  969. printf '--------------------------------------------------\n'
  970.  
  971. surep_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. # ############################################################################ #
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement