Modular backuptool.sh. Executes backup and restore methods defined in arbitrary /system/addon.d/*.sh scripts.
Tips & Tricks
=============
* 50-cm.sh contains only a reference implementation. You may customize the methods however you wish.
For example, 20-foobar.sh pre-backup can use a loop with conditionals to generate a dynamic backup list in
/tmp/foobar_file_list which is later printed by list_files() so the backup method will act on those files.
* Optional methods pre-backup, post-backup, pre-restore, or post-restore may be defined for special purposes.
* Inject new files into /tmp/addon.d/ prior to backuptool.sh backup if you want to act during the current CM upgrade.
* Delete files from /tmp/addon.d/ during post-restore if you want to permanently remove files from /system/addon.d/
Addons may use this approach to run a script only once.
* Scripts run in sort -n order. Prefix with numbers 00 through 99 if want to run in a particular order.
* You can have two separate scripts, implementing only backup in one, and only restore in the other with a different
number prefix of each. This allows even greater control the backup/restore order even further.
* You could use pre-backup to generate a one-time use backup script in /tmp/addon.d/ that deletes itself in
post-restore.
Patch Series
============
http://review.cyanogenmod.com/#change,13265
CyanogenMod/android_build
* edify generator
http://review.cyanogenmod.com/#change,13266
CyanogenMod/android_system_core
* permissions on /system/addon.d
http://review.cyanogenmod.com/#change,13267
CyanogenMod/android_vendor_cm
* 50-cm.sh reference backup script
* modular backuptool.sh
* support backuptool.functions used by /system/addon.d/*.sh scripts
Change-Id: Ifd5eaf9dcfd68d92e5043c21d1bae1dc0ad54860
diff --git a/config/common.mk b/config/common.mk
index 57b81f8..03f6225 100644
--- a/config/common.mk
+++ b/config/common.mk
@@ -24,8 +24,11 @@
PRODUCT_COPY_FILES += \
vendor/cm/CHANGELOG.mkdn:system/etc/CHANGELOG-CM.txt
+# Backup Tool
PRODUCT_COPY_FILES += \
- vendor/cm/prebuilt/common/bin/backuptool.sh:system/bin/backuptool.sh
+ vendor/cm/prebuilt/common/bin/backuptool.sh:system/bin/backuptool.sh \
+ vendor/cm/prebuilt/common/bin/backuptool.functions:system/bin/backuptool.functions \
+ vendor/cm/prebuilt/common/bin/50-cm.sh:system/addon.d/50-cm.sh
# init.d support
PRODUCT_COPY_FILES += \
@@ -116,4 +119,4 @@
PRODUCT_PROPERTY_OVERRIDES += \
ro.cm.version=$(CM_VERSION) \
- ro.modversion=$(CM_VERSION)
\ No newline at end of file
+ ro.modversion=$(CM_VERSION)
diff --git a/prebuilt/common/bin/50-cm.sh b/prebuilt/common/bin/50-cm.sh
new file mode 100755
index 0000000..24bfe33
--- /dev/null
+++ b/prebuilt/common/bin/50-cm.sh
@@ -0,0 +1,41 @@
+#!/sbin/sh
+#
+# /system/addon.d/50-cm.sh
+# During a CM9 upgrade, this script backs up /system/etc/hosts,
+# /system is formatted and reinstalled, then the file is restored.
+#
+
+. /tmp/backuptool.functions
+
+list_files() {
+cat <<EOF
+etc/hosts
+EOF
+}
+
+case "$1" in
+ backup)
+ list_files | while read FILE DUMMY; do
+ backup_file $S/"$FILE"
+ done
+ ;;
+ restore)
+ list_files | while read FILE REPLACEMENT; do
+ R=""
+ [ -n "$REPLACEMENT" ] && R="$S/$REPLACEMENT"
+ [ -f "$C/$S/$FILE" ] && restore_file $S/"$FILE" "$R"
+ done
+ ;;
+ pre-backup)
+ # Stub
+ ;;
+ post-backup)
+ # Stub
+ ;;
+ pre-restore)
+ # Stub
+ ;;
+ post-restore)
+ # Stub
+ ;;
+esac
diff --git a/prebuilt/common/bin/backuptool.functions b/prebuilt/common/bin/backuptool.functions
new file mode 100644
index 0000000..833460f
--- /dev/null
+++ b/prebuilt/common/bin/backuptool.functions
@@ -0,0 +1,37 @@
+#!/sbin/sh
+#
+# Functions for backuptool.sh
+#
+
+export C=/tmp/backupdir
+export S=/system
+export V=9
+
+backup_file() {
+ if [ -e "$1" ]; then
+ local F=`basename "$1"`
+ local D=`dirname "$1"`
+ # dont backup any apps that have odex files, they are useless
+ if ( echo "$F" | grep -q "\.apk$" ) && [ -e `echo "$1" | sed -e 's/\.apk$/\.odex/'` ]; then
+ echo "Skipping odexed apk $1";
+ else
+ mkdir -p "$C/$D"
+ cp -p $1 "$C/$D/$F"
+ fi
+ fi
+}
+
+restore_file() {
+ local FILE=`basename "$1"`
+ local DIR=`dirname "$1"`
+ if [ -e "$C/$DIR/$FILE" ]; then
+ if [ ! -d "$DIR" ]; then
+ mkdir -p "$DIR";
+ fi
+ cp -p "$C/$DIR/$FILE" "$1";
+ if [ -n "$2" ]; then
+ echo "Deleting obsolete file $2"
+ rm "$2";
+ fi
+ fi
+}
diff --git a/prebuilt/common/bin/backuptool.sh b/prebuilt/common/bin/backuptool.sh
index 3b13843..fd62159 100755
--- a/prebuilt/common/bin/backuptool.sh
+++ b/prebuilt/common/bin/backuptool.sh
@@ -1,215 +1,80 @@
#!/sbin/sh
#
-# Backup and restore proprietary Android system files
+# Backup and restore addon /system files
#
-C=/tmp/backupdir
-S=/system
-V=9
+export C=/tmp/backupdir
+export S=/system
+export V=9
-PROCEED=1;
+# Mount /system if it is not already mounted
+mount_system() {
+if [ ! -f "$S/build.prop" ]; then
+ mount $S
+fi
+}
+# Unmount /system unless it is already unmounted
+umount_system() {
+if [ -f "$S/build.prop" ]; then
+ umount $S
+fi
+}
+
+# Preserve /system/addon.d in /tmp/addon.d
+preserve_addon_d() {
+ mkdir -p /tmp/addon.d/
+ cp -a /system/addon.d/* /tmp/addon.d/
+ chmod 755 /tmp/addon.d/*.sh
+}
+
+# Restore /system/addon.d in /tmp/addon.d
+restore_addon_d() {
+ cp -a /tmp/addon.d/* /system/addon.d/
+ rm -rf /tmp/addon.d/
+}
+
+# Proceed only if /system is the expected major version
check_prereq() {
- if ( ! grep -q "^ro.cm.version=$V.*" /system/build.prop );
- then
- echo "Not backing up files from incompatible version.";
- PROCEED=0;
- fi
+if ( ! grep -q "^ro.cm.version=$V.*" /system/build.prop ); then
+ echo "Not backing up files from incompatible version."
+ umount_system
+ exit 127
+fi
}
-check_installscript() {
- if [ -f "/tmp/.installscript" ] && [ $PROCEED -ne 0 ];
- then
- # We have an install script, and ROM versions match!
- # We now need to check and see if we have force_backup
- # in either /etc or /tmp/backupdir
- if [ -f "$S/etc/force_backuptool" ] || [ -f "$C/force_backuptool" ];
- then
- echo "force_backuptool file found, Forcing backuptool."
- else
- echo "/tmp/.installscript found. Skipping backuptool."
- PROCEED=0;
- fi
- fi
+# Execute /system/addon.d/*.sh scripts with $1 parameter
+run_stage() {
+for script in $(find /tmp/addon.d/ -name '*.sh' |sort -n); do
+ $script $1
+done
}
-get_files() {
- cat <<EOF
-vendor/pittpatt/models/recognition/face.face.y0-y0-22-b-N/full_model.bin
-vendor/pittpatt/models/detection/multi_pose_face_landmark_detectors.3/left_eye-y0-yi45-p0-pi45-rn7-ri20.2d_n2/full_model.bin
-vendor/pittpatt/models/detection/multi_pose_face_landmark_detectors.3/nose_base-y0-yi45-p0-pi45-r0-ri20.2d_n2/full_model.bin
-vendor/pittpatt/models/detection/multi_pose_face_landmark_detectors.3/right_eye-y0-yi45-p0-pi45-rp7-ri20.2d_n2/full_model.bin
-vendor/pittpatt/models/detection/multi_pose_face_landmark_detectors.3/nose_base-y0-yi45-p0-pi45-rp7-ri20.2d_n2/full_model.bin
-vendor/pittpatt/models/detection/multi_pose_face_landmark_detectors.3/left_eye-y0-yi45-p0-pi45-rp7-ri20.2d_n2/full_model.bin
-vendor/pittpatt/models/detection/multi_pose_face_landmark_detectors.3/right_eye-y0-yi45-p0-pi45-rn7-ri20.2d_n2/full_model.bin
-vendor/pittpatt/models/detection/multi_pose_face_landmark_detectors.3/nose_base-y0-yi45-p0-pi45-rn7-ri20.2d_n2/full_model.bin
-vendor/pittpatt/models/detection/multi_pose_face_landmark_detectors.3/right_eye-y0-yi45-p0-pi45-r0-ri20.2d_n2/full_model.bin
-vendor/pittpatt/models/detection/multi_pose_face_landmark_detectors.3/left_eye-y0-yi45-p0-pi45-r0-ri20.2d_n2/full_model.bin
-vendor/pittpatt/models/detection/yaw_roll_face_detectors.3/head-y0-yi45-p0-pi45-rn30-ri30.5/full_model.bin
-vendor/pittpatt/models/detection/yaw_roll_face_detectors.3/head-y0-yi45-p0-pi45-rp30-ri30.5/full_model.bin
-vendor/pittpatt/models/detection/yaw_roll_face_detectors.3/head-y0-yi45-p0-pi45-r0-ri30.4a/full_model.bin
-framework/com.android.nfc_extras.jar
-framework/com.google.widevine.software.drm.jar
-framework/com.google.android.maps.jar
-framework/com.google.android.media.effects.jar
-lib/libfacelock_jni.so
-lib/libfilterpack_facedetect.so
-lib/libflint_engine_jni_api.so
-lib/libfrsdk.so
-lib/libgcomm_jni.so
-lib/libpicowrapper.so
-lib/libspeexresampler.so
-lib/libspeexwrapper.so
-lib/libvideochat_jni.so
-lib/libvideochat_stabilize.so
-lib/libvoicesearch.so
-etc/permissions/com.google.android.nfc_extras.xml
-etc/permissions/com.google.android.media.effects.xml
-etc/permissions/com.google.android.maps.xml
-etc/permissions/com.google.widevine.software.drm.xml
-etc/permissions/features.xml
-app/MediaUploader.apk
-app/GoogleFeedback.apk
-app/GoogleTTS.apk
-app/MarketUpdater.apk
-app/GoogleServicesFramework.apk
-app/YouTube.apk
-app/GenieWidget.apk
-app/GooglePackageVerifierUpdater.apk
-app/SetupWizard.apk app/Provision.apk
-app/GoogleEarth.apk
-app/ChromeBookmarksSyncAdapter.apk
-app/GoogleQuickSearchBox.apk app/QuickSearchBox.apk
-app/GoogleLoginService.apk
-app/Talk.apk
-app/Maps.apk
-app/GooglePackageVerifier.apk
-app/GoogleBackupTransport.apk
-app/GalleryGoogle.apk app/Gallery2.apk
-app/FaceLock.apk
-app/Vending.apk
-app/GoogleContactsSyncAdapter.apk
-app/GoogleCalendarSyncAdapter.apk
-app/Gmail.apk
-app/OneTimeInitializer.apk
-app/NetworkLocation.apk
-app/GooglePartnerSetup.apk
-app/Phonesky.apk
-app/VoiceSearch.apk
-etc/hosts
-etc/custom_backup_list.txt
-etc/force_backuptool
-EOF
-}
-
-get_custom_files() {
- local L
- if [ -f "$C/custom_backup_list.txt" ];
- then
- [ ! -f $C/fixed_custom_backup_list.txt ] && tr -d '\r' < $C/custom_backup_list.txt \
- > $C/fixed_custom_backup_list.txt
- L=`cat $C/fixed_custom_backup_list.txt`
- cat <<EOF
-$L
-EOF
- fi
-}
-
-backup_file() {
- if [ -e "$1" ];
- then
- if [ -n "$2" ];
- then
- echo "$2 $1" | md5sum -c -
- if [ $? -ne 0 ];
- then
- echo "MD5Sum check for $1 failed!";
- exit $?;
- fi
- fi
-
- local F=`basename $1`
- local D=`dirname $1`
-
- # dont backup any apps that have odex files, they are useless
- if ( echo $F | grep -q "\.apk$" ) && [ -e `echo $1 | sed -e 's/\.apk$/\.odex/'` ];
- then
- echo "Skipping odexed apk $1";
- else
- mkdir -p $C/bak/$D
- cp -p $1 $C/bak/$D/$F
- fi
- fi
-}
-
-restore_file() {
- local FILE=`basename $1`
- local DIR=`dirname $1`
- if [ -e "$C/bak/$DIR/$FILE" ];
- then
- if [ ! -d "$DIR" ];
- then
- mkdir -p $DIR;
- fi
- cp -p $C/bak/$DIR/$FILE $1;
- if [ -n "$2" ];
- then
- rm $2;
- fi
- fi
-}
-
-# don't (u)mount system if already done
-UMOUNT=0
-
case "$1" in
- backup)
- if [ ! -f "$S/build.prop" ]; then
- mount $S
- UMOUNT=1
- fi
- check_prereq;
- check_installscript;
- if [ $PROCEED -ne 0 ];
- then
- rm -rf $C
- mkdir -p $C
- for file_list in get_files get_custom_files; do
- $file_list | while read FILE REPLACEMENT; do
- backup_file $S/$FILE
- done
- done
- fi
- if [ $UMOUNT -ne 0 ]; then
- umount $S
- fi
- ;;
- restore)
- if [ ! -f "$S/build.prop" ]; then
- mount $S
- UMOUNT=1
- fi
- check_prereq;
- check_installscript;
- if [ $PROCEED -ne 0 ];
- then
- for file_list in get_files get_custom_files; do
- $file_list | while read FILE REPLACEMENT; do
- R=""
- [ -n "$REPLACEMENT" ] && R="$S/$REPLACEMENT"
- restore_file $S/$FILE $R
- done
- done
- rm -rf $C
- fi
- if [ $UMOUNT -ne 0 ]; then
- umount $S
- fi
- sync
- ;;
- *)
- echo "Usage: $0 {backup|restore}"
- exit 1
+ backup)
+ mkdir -p $C
+ mount_system
+ check_prereq
+ preserve_addon_d
+ run_stage pre-backup
+ run_stage backup
+ run_stage post-backup
+ umount_system
+ ;;
+ restore)
+ mount_system
+ check_prereq
+ run_stage pre-restore
+ run_stage restore
+ run_stage post-restore
+ restore_addon_d
+ umount_system
+ rm -rf $C
+ sync
+ ;;
+ *)
+ echo "Usage: $0 {backup|restore}"
+ exit 1
esac
exit 0