Splitting out a first bunch of functions out to /live/live/boot/.
[live-boot-grml.git] / scripts / boot / snapshot.sh
1 #!/bin/sh
2
3 do_snap_copy ()
4 {
5         fromdev="${1}"
6         todir="${2}"
7         snap_type="${3}"
8         size=$(fs_size "${fromdev}" "" "used")
9
10         if [ -b "${fromdev}" ]
11         then
12                 log_success_msg "Copying snapshot ${fromdev} to ${todir}..."
13
14                 # look for free mem
15                 if [ -n "${HOMEMOUNTED}" -a "${snap_type}" = "HOME" ]
16                 then
17                         todev=$(awk -v pat="$(base_path ${todir})" '$2 == pat { print $1 }' /proc/mounts)
18                         freespace=$(df -k | awk '/'${todev}'/{print $4}')
19                 else
20                         freespace=$(awk '/^MemFree:/{f=$2} /^Cached:/{c=$2} END{print f+c}' /proc/meminfo)
21                 fi
22
23                 tomount="/mnt/tmpsnap"
24
25                 if [ ! -d "${tomount}" ]
26                 then
27                         mkdir -p "${tomount}"
28                 fi
29
30                 fstype=$(get_fstype "${fromdev}")
31
32                 if [ -n "${fstype}" ]
33                 then
34                         # Copying stuff...
35                         mount -o ro -t "${fstype}" "${fromdev}" "${tomount}" || log_warning_msg "Error in mount -t ${fstype} -o ro ${fromdev} ${tomount}"
36                         cp -a "${tomount}"/* ${todir}
37                         umount "${tomount}"
38                 else
39                         log_warning_msg "Unrecognized fstype: ${fstype} on ${fromdev}:${snap_type}"
40                 fi
41
42                 rmdir "${tomount}"
43
44                 if echo ${fromdev} | grep -qs loop
45                 then
46                         losetup -d "${fromdev}"
47                 fi
48
49                 return 0
50         else
51                 log_warning_msg "Unable to find the snapshot ${snap_type} medium"
52                 return 1
53         fi
54 }
55
56 try_snap ()
57 {
58         # copy the contents of previously found snapshot to ${snap_mount}
59         # and remember the device and filename for resync on exit in live-boot.init
60
61         snapdata="${1}"
62         snap_mount="${2}"
63         snap_type="${3}"
64         snap_relpath="${4}"
65
66         if [ -z "${snap_relpath}" ]
67         then
68                 # root snapshot, default usage
69                 snap_relpath="/"
70         else
71                 # relative snapshot (actually used just for "/home" snapshots)
72                 snap_mount="${2}${snap_relpath}"
73         fi
74
75         if [ -n "${snapdata}" ] && [ ! -b "${snapdata}" ]
76         then
77                 log_success_msg "found snapshot: ${snapdata}"
78                 snapdev="$(echo ${snapdata} | cut -f1 -d ' ')"
79                 snapback="$(echo ${snapdata} | cut -f2 -d ' ')"
80                 snapfile="$(echo ${snapdata} | cut -f3 -d ' ')"
81
82                 if ! try_mount "${snapdev}" "${snapback}" "ro"
83                 then
84                         break
85                 fi
86
87                 RES="0"
88
89                 if echo "${snapfile}" | grep -qs '\(squashfs\|ext2\|ext3\|ext4\|jffs2\)'
90                 then
91                         # squashfs, jffs2 or ext2/ext3/ext4 snapshot
92                         dev=$(get_backing_device "${snapback}/${snapfile}")
93
94                         do_snap_copy "${dev}" "${snap_mount}" "${snap_type}"
95                         RES="$?"
96                 else
97                         # cpio.gz snapshot
98
99                         # Unfortunately klibc's cpio is incompatible with the
100                         # rest of the world; everything else requires -u -d,
101                         # while klibc doesn't implement them. Try to detect
102                         # whether it's in use.
103                         cpiopath="$(which cpio)" || true
104                         if [ "$cpiopath" ] && grep -aq /lib/klibc "$cpiopath"
105                         then
106                                 cpioargs=
107                         else
108                                 cpioargs='--unconditional --make-directories'
109                         fi
110
111                         if [ -s "${snapback}/${snapfile}" ]
112                         then
113                                 BEFOREDIR="$(pwd)"
114                                 cd "${snap_mount}" && zcat "${snapback}/${snapfile}" | $cpiopath $cpioargs --extract --preserve-modification-time --no-absolute-filenames --sparse 2>/dev/null
115                                 RES="$?"
116                                 cd "${BEFOREDIR}"
117                         else
118                                 log_warning_msg "${snapback}/${snapfile} is empty, adding it for sync on reboot."
119                                 RES="0"
120                         fi
121
122                         if [ "${RES}" != "0" ]
123                         then
124                                 log_warning_msg "failure to \"zcat ${snapback}/${snapfile} | $cpiopath $cpioargs --extract --preserve-modification-time --no-absolute-filenames --sparse\""
125                         fi
126                 fi
127
128                 umount "${snapback}" ||  log_warning_msg "failure to \"umount ${snapback}\""
129
130                 if [ "${RES}" != "0" ]
131                 then
132                         log_warning_msg "Impossible to include the ${snapfile} Snapshot file"
133                 fi
134
135         elif [ -b "${snapdata}" ]
136         then
137                 # Try to find if it could be a snapshot partition
138                 dev="${snapdata}"
139                 log_success_msg "found snapshot ${snap_type} device on ${dev}"
140                 if echo "${dev}" | grep -qs loop
141                 then
142                         # strange things happens, user confused?
143                         snaploop=$( losetup ${dev} | awk '{print $3}' | tr -d '()' )
144                         snapfile=$(basename ${snaploop})
145                         snapdev=$(awk -v pat="$( dirname ${snaploop})" '$2 == pat { print $1 }' /proc/mounts)
146                 else
147                         snapdev="${dev}"
148                 fi
149
150                 if ! do_snap_copy "${dev}" "${snap_mount}" "${snap_type}"
151                 then
152                         log_warning_msg "Impossible to include the ${snap_type} Snapshot (i)"
153                         return 1
154                 else
155                         if [ -n "${snapfile}" ]
156                         then
157                                 # it was a loop device, user confused
158                                 umount ${snapdev}
159                         fi
160                 fi
161         else
162                 log_warning_msg "Impossible to include the ${snap_type} Snapshot (o)"
163                 return 1
164         fi
165
166         if [ -z ${PERSISTENCE_READONLY} ]
167         then
168                 echo "export ${snap_type}SNAP=${snap_relpath}:${snapdev}:${snapfile}" >> snapshot.conf # for resync on reboot/halt
169         fi
170         return 0
171 }