snapmergepuppy 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. #!/bin/ash
  2. #2007 Lesser GPL licence v2 (http://www.fsf.org/licensing/licenses/lgpl.html)
  3. #Barry Kauler www.puppylinux.com
  4. #called from savepuppyd and rc.shutdown, to save tmpfs layer to permanent flash storage.
  5. #updated 13 Sept 2007. copy-down only. flushing is done in petget.
  6. #updated 24 Sept 2007. removed '-u' option when copy-down files.
  7. #8 oct 2007: screen out /root/tmp when saving.
  8. #4 nov 2007: reintroduce '-u' copy option.
  9. #v4.01 19may2008 BK: now called from /sbin/pup_eventd daemon (savepuppyd now history).
  10. #v4.01 19may2008 BK: if called from pup_eventd then X running: graceful exit if X shutdown.
  11. #v409 BK: XRUNNING test should be 'pup_event_frontend_d'.
  12. #v409 BK: save /var dir. previously screened out to save space, but prevents crontab from running.
  13. #v412 /etc/DISTRO_SPECS, renamed pup_xxx.sfs, pup_save.2fs etc.
  14. #w000 pup files renamed to woofr555.sfs, woofsave.2fs.
  15. #w003 bug fix for .wh.__dir_opaque whiteout file.
  16. #w003 screened out some dirs in /dev that should not be saved.
  17. #v424 fix for more layers in unionfs/aufs.
  18. #100222 shinobar: possible timezone problem with BOOTCONFIG. more file exclusions.
  19. #100422 added ^root/ftpd exclusion.
  20. #100429 modify 'trash' exclusion.
  21. #100820 added /var/tmp exclusion (apparently filled by opera crashes).
  22. #101221 yaf-splash fix.
  23. #110206 Dougal: clean up some testing. speedup: LANG=C, also change to /bin/ash.
  24. #110212 recent aufs: .wh.__dir_opaque name changed to .wh..wh..opq.
  25. #110212 Jemimah: files may disappear, more efficient calc of free space, fix i/o err.
  26. #110222 shinobar: remove all /dev, allow 'pup_ro10-19', exit code for no space
  27. #110224 BK: revert remove all /dev, for now. 110503 added dev/snd
  28. #110505 support sudo for non-root user.
  29. #111229 rerwin: fix jemimah code (110212).
  30. #120103 rerwin: screen out /.XLOADED when save.
  31. #140102 SFR: various fixes + gettext
  32. #140512 SFR: performance improvements
  33. [ "`whoami`" != "root" ] && exec sudo -A ${0} ${@} #110505
  34. export TEXTDOMAIN=snapmergepuppy
  35. export OUTPUT_CHARSET=UTF-8
  36. OLDLANG="$LANG"
  37. export LANG=C #110206 Dougal: I **think** this should not cause problems with filenames
  38. #variables created at bootup by 'init' script in initramfs...
  39. . /etc/rc.d/PUPSTATE
  40. . /etc/DISTRO_SPECS #v412
  41. SAVEPART="`echo -n "$PUPSAVE" | cut -f 1 -d ','`"
  42. #v3.02 first time, do not use '-u' option when saving, save everything...
  43. NEXTPASSTHRU=""
  44. [ -e /tmp/flagnextpassthru ] && NEXTPASSTHRU="yes"
  45. RUNPS="`ps`"
  46. SHUTDOWN="no"
  47. [ "`echo "$RUNPS" | grep 'rc.shutdown'`" != "" ] && SHUTDOWN="yes"
  48. XRUNNING="no"
  49. [ "`echo "$RUNPS" | grep 'pup_event_frontend_d'`" != "" ] && XRUNNING="yes"
  50. PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R7/bin"
  51. WD="`pwd`"
  52. SNAP="/initrd/pup_rw"
  53. cd $SNAP || exit 1
  54. if [ "$SAVE_LAYER" ]; then #defined in PUPSTATE
  55. BASE="/initrd${SAVE_LAYER}"
  56. else
  57. BASE="/initrd/pup_ro1"
  58. fi
  59. # Precautions
  60. [ $PUPMODE -eq 3 -o $PUPMODE -eq 7 -o $PUPMODE -eq 13 ] || { echo "Wrong PUPMODE ($PUPMODE)!"; exit 1; }
  61. mountpoint -q "$BASE" || { echo "$BASE is not mounted!"; exit 1; }
  62. echo "Merging $SNAP onto $BASE..."
  63. # =============================================================================
  64. # WHITEOUTS
  65. # =============================================================================
  66. SFSPoints=$( grep -o -E "/initrd/pup_ro[0-9]+" /proc/mounts |sort -t o -k2 -nu ) #110206 Dougal: get a list of the sfs mountpoints SFR: increase amount of mountpoints (sfs_load can load >=10)
  67. find . -mount \( -regex '.*/\.wh\.[^/]*' -type f \) | sed -e 's/\.\///;s/\.wh\.//' |
  68. while read -r N
  69. do
  70. DN="${N%/*}"
  71. BN="${N##*/}"
  72. [ "$DN" = "$N" ] || [ "$DN" = "" ] && DN="."
  73. [ "$DN" = "." ] && continue
  74. [ "$BN" = ".wh.aufs" ] && continue #w003 aufs has file .wh..wh.aufs in /initrd/pup_rw.
  75. #110212 unionfs and early aufs: '.wh.__dir_opaque' marks ignore all contents in lower layers...
  76. if [ "$BN" = "__dir_opaque" ];then #w003
  77. #'.wh.__dir_opaque' marks ignore all contents in lower layers...
  78. rm -rf "${BASE}/${DN}" 2>/dev/null #wipe anything in save layer. 110212 delete entire dir.
  79. mkdir -p "${BASE}/${DN}" #jemimah: files sometimes mysteriously reappear if you don't delete and recreate the directory, aufs bug? 111229 rerwin: need -p, may have to create parent dir.
  80. #also need to save the whiteout file to block all lower layers (may be readonly)...
  81. touch "${BASE}/${DN}/.wh.__dir_opaque" 2>/dev/null
  82. rm -f "$SNAP/$DN/.wh.__dir_opaque" #should force aufs layer "reval".
  83. continue
  84. fi
  85. #110212 recent aufs: .wh.__dir_opaque name changed to .wh..wh..opq ...
  86. if [ "$BN" = ".wh..opq" ] ; then
  87. rm -rf "${BASE}/${DN}" 2>/dev/null #wipe anything in save layer.
  88. mkdir -p "${BASE}/${DN}" #jemimah: files sometimes mysteriously reappear if you don't delete and recreate the directory, aufs bug? 111229 rerwin: need -p, may have to create parent dir.
  89. #also need to save the whiteout file to block all lower layers (may be readonly)...
  90. touch "${BASE}/${DN}/.wh..wh..opq" 2>/dev/null
  91. rm -f "$SNAP/$DN/.wh..wh..opq" #should force aufs layer "reval".
  92. continue
  93. fi
  94. #comes in here with the '.wh.' prefix stripped off, leaving actual filename...
  95. rm -rf "$BASE/$N"
  96. #if file exists on a lower layer, have to save the whiteout file...
  97. #110206 Dougal: speedup and refine the search...
  98. for P in $SFSPoints
  99. do
  100. if [ -e "$P/$N" ] || [ -L "$P/$N" ] ; then # SFR: broken symlinks also deserve to be processed ( '-e' won't detect them, needs to be also '-L')
  101. [ -d "${BASE}/${DN}" ] || mkdir -p "${BASE}/${DN}"
  102. touch "${BASE}/${DN}/.wh.${BN}"
  103. break
  104. fi
  105. done #110206 End Dougal.
  106. rm -f "$SNAP/$DN/.wh.$BN" #remove whiteout file. should force aufs layer "reval".
  107. done
  108. # =============================================================================
  109. # DIRECTORIES
  110. # =============================================================================
  111. #110224 BK revert, leave save of /dev in for now, just take out some subdirs... 110503 added dev/snd
  112. find . -mount -type d | tail +2 | sed -e 's/\.\///' | grep -v -E '^mnt|^initrd|^proc|^sys|^tmp|^root/tmp|^\.wh\.|/\.wh\.|^dev/\.|^dev/fd|^dev/pts|^dev/shm|^dev/snd|^var/tmp' |
  113. while read -r N
  114. do
  115. #v4.01 graceful exit if shutdown X (see /usr/X11R7/bin/restartwm,wmreboot,wmpoweroff)...
  116. [ "$XRUNNING" = "yes" ] && [ -f /tmp/wmexitmode.txt ] && exit
  117. mkdir -p "$BASE/$N"
  118. #i think nathan advised this, to handle non-root user (SFR: improved/simplified)
  119. chmod "$BASE/$N" --reference="$N"
  120. OWNERSHIP="`stat --format=%u:%g "$N"`"
  121. chown $OWNERSHIP "$BASE/$N"
  122. touch "$BASE/$N" --reference="$N"
  123. done
  124. # =============================================================================
  125. # FILES
  126. # =============================================================================
  127. #100222 a quick hack: BOOTCONFIG written to in init, before timezone set, can cause trouble...
  128. touch /etc/rc.d/BOOTCONFIG
  129. FREEBASE=`df -B 1 | grep -w "$BASE"| head -n 1 | tr -s ' ' | cut -f 4 -d ' '` #110212 Jemimah #110222 shinobar # SFR: result in bytes (see 'find' below)
  130. rm -f /tmp/snapmergepuppy-nospace #110222 shinobar
  131. rm -f /tmp/snapmergepuppy-error #140102 SFR
  132. #Copy Files... v409 remove '^var'. w003 screen out some /dev files. 100222 shinobar: more exclusions. 100422 added ^root/ftpd. 100429 modify 'trash' exclusion. 100820 added var/tmp #110224 BK: revert, leave save of /dev in for now... 120103 rerwin: add .XLOADED # SFR: added dev/snd # SFR: added .crdownload
  133. # SFR: move as much as possible into 'find' itself
  134. # Limitation - files with newline (\n) in its name are processed wrong (but this is not a new issue)
  135. find . -mount \
  136. -not -path . \
  137. -not -type d \
  138. -regextype posix-extended \
  139. -not \( -regex '.*/\.wh\.[^\]*' -type f \) \
  140. -not \( -regex '^./mnt.*|^./initrd.*|^./proc.*|^./sys.*|^./tmp.*|^./pup_.*|^./zdrv_.*|^./root/tmp.*|.*_zdrv_.*|^./dev/\..*|^./dev/fd.*|^./dev/pts.*|^./dev/snd.*|^./dev/shm.*|^./\.wh\..*|^./var/run.*|^./root/ftpd.*|^./var/tmp.*|.*\.XLOADED$' \) \
  141. -not \( -regex '.*\.thumbnails.*|.*\.part$|.*\.crdownload$' \) \
  142. -printf "%s %C@ %P\n" |
  143. while read -r NSIZE NCTIME N
  144. do
  145. #v4.01 graceful exit if shutdown X (see /usr/X11R7/bin/restartwm,wmreboot,wmpoweroff)...
  146. [ "$XRUNNING" = "yes" ] && [ -f /tmp/wmexitmode.txt ] && exit
  147. ([ ! -e "$N" ] && [ ! -L "$N" ]) && continue # SFR: skip non-existing files (btw, '-e' won't detect broken symlinks, so '-L' is necessary!)
  148. #stop saving if not enough room left in ${DISTRO_FILE_PREFIX}save file...
  149. if [ $((NSIZE+204800)) -gt $FREEBASE ]; then # 204800 = 200K slack space
  150. FREEBASE=`df -B 1 | grep -w "$BASE" | head -n 1 | tr -s ' ' | cut -f 4 -d ' '` #110212 Jemimah: this is very slow; try not to check every iteration #110222 shinobar: fix for pup_ro10 and more
  151. if [ $((NSIZE+204800)) -gt $FREEBASE ]; then #110212 Jemimah.
  152. touch /tmp/snapmergepuppy-nospace #110222 shinobar
  153. break
  154. fi
  155. else
  156. FREEBASE=$((FREEBASE-NSIZE)) #110212 Jemimah: keep track of the worst case
  157. fi
  158. ##v2.21 -u causes trouble if timezone malconfigured...
  159. [ -L "$BASE/$N" ] && rm -f "$BASE/$N"
  160. if [ -L "$N" -o "$NEXTPASSTHRU" = "" ];then
  161. #link, or first run of snapmergepuppy. no '-u' (update) option.
  162. [ -L "$N" ] && [ -d "$BASE/$N" ] && rm -rf "$BASE/$N" # SFR: in case if folder has been replaced with a symlink (cp won't overwrite a dir with a symlink)
  163. cp -a -f "$N" "$BASE/$N" 2>>/tmp/snapmergepuppy-error
  164. else
  165. [ ! -e "$BASE/$N" ] || [ ${NCTIME%%.*} -gt `stat -c %Z "$BASE/$N"` ] && cp -a -f "$N" "$BASE/$N" 2>>/tmp/snapmergepuppy-error
  166. fi
  167. DN="${N%/*}" #111229 rerwin: bugfix for jemimah code (110212) (SFR: improved performance)
  168. BN="${N##*/}" #111229 "
  169. [ "$DN" = "$N" ] || [ "$DN" = "" ] && DN="."
  170. [ -e "$BASE/$DN/.wh.${BN}" ] && rm "$BASE/$DN/.wh.${BN}" #110212 jemimah bugfix - I/O errors if you don't do this
  171. done
  172. # =============================================================================
  173. touch /tmp/flagnextpassthru
  174. # SFR: fix for .wh files not being created (in some cases) in pup_rw
  175. if [ "`lsmod | grep "^aufs" `" != "" ]; then
  176. # force re-evalution of all the layers
  177. busybox mount -t aufs -o remount,udba=reval unionfs /
  178. fi
  179. sync
  180. cd "$WD"
  181. # =============================================================================
  182. error_msg () {
  183. if [ "$SHUTDOWN" = "no" -a "$XRUNNING" = "yes" ];then
  184. export DISPLAY=':0'
  185. /usr/lib/gtkdialog/box_splash -timeout 30 -close box -icon gtk-dialog-warning -bg red -text "$1"
  186. else
  187. echo "$1"
  188. fi
  189. }
  190. export LANG="$OLDLANG"
  191. ERRSTATUS=0
  192. if [ -f /tmp/snapmergepuppy-nospace ]; then #110222 shinobar
  193. ERRMSG="$(gettext 'WARNING!
  194. Unable to save all files. You need to delete some.')"
  195. error_msg "$ERRMSG"
  196. ERRSTATUS=1
  197. fi
  198. if [ -s /tmp/snapmergepuppy-error ]; then #140102 SFR
  199. ERRMSG="$(gettext "WARNING!
  200. There were some errors detected.
  201. (see '/tmp/snapmergepuppy-error' for details)
  202. Filesystem check of the savefile (pfix=fsck) is highly recommended.")"
  203. error_msg "$ERRMSG"
  204. ERRSTATUS=1
  205. fi
  206. exit $ERRSTATUS
  207. # =============================================================================