-
-
Save residentsummer/ab437dea72346dce85e04fa5b5ff382f to your computer and use it in GitHub Desktop.
Script to edit iOS backups
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
##### Configuration ##### | |
BACKUPS_ROOT="$HOME/Library/Application Support/MobileSync/Backup/" | |
##### Script support funcs (just skip to the next section) ##### | |
declare -a ACTIONS | |
declare -a USAGE=("Usage:") | |
add-action () { | |
ACTIONS+=($1) | |
USAGE[${#USAGE[@]}]=`echo " " $BASENAME $@` | |
} | |
usage () { | |
for ((i = 0; i < ${#USAGE[@]}; i++)); do | |
echo "${USAGE[$i]}" | |
done | |
} | |
main () { | |
action=$1 | |
shift | |
if [[ -z "${action// /}" ]]; then | |
usage && exit | |
fi | |
for a in ${ACTIONS[@]}; do | |
if [[ $action == $a ]]; then | |
$a "$@" | |
exit | |
fi | |
done | |
usage | |
} | |
##### Functional part ##### | |
add-action list-backups "- list available backups" | |
function list-backups () { | |
ls -l "$BACKUPS_ROOT" | |
} | |
add-action get-blob "backup_id blob_id dst_path - pull file from backup" | |
function get-blob () { | |
local backup_id="$1" | |
local blob_id="$2" | |
local dst_path="$3" | |
if [[ -z "$backup_id" || -z "$blob_id" || -z "$dst_path" ]]; then | |
echo "not enough arguments" | |
exit 1 | |
fi | |
local backup_path="$BACKUPS_ROOT/$backup_id" | |
if [[ ! -d "$backup_path" ]]; then | |
echo "no such backup" | |
exit 1 | |
fi | |
local blob_path=$(guess-path "$backup_path" "$blob_id") | |
if [[ -z "$blob_path" ]]; then | |
echo "no such blob" | |
exit 1 | |
fi | |
cp "$blob_path" "$dst_path" | |
} | |
function guess-path () { | |
local backup_path="$1" | |
local blob_id="$2" | |
for res in "$backup_path/$blob_id" "$backup_path/${blob_id:0:2}/$blob_id"; do | |
if [[ -f "$res" ]]; then | |
echo "$res" | |
exit 0 | |
fi | |
done | |
exit 1 | |
} | |
add-action replace-blob "backup_id blob_id src_path - put modified file into backup" | |
function replace-blob () { | |
local backup_id="$1" | |
local blob_id="$2" | |
local src_path="$3" | |
if [[ -z "$backup_id" || -z "$blob_id" || -z "$src_path" ]]; then | |
echo "not enough arguments" | |
exit 1 | |
fi | |
local backup_path="$BACKUPS_ROOT/$backup_id" | |
if [[ ! -d "$backup_path" ]]; then | |
echo "no such backup" | |
exit 1 | |
fi | |
local manifest_path="$backup_path/Manifest.db" | |
if [[ ! -f "$manifest_path" ]]; then | |
echo "unknown backup format" | |
exit 1 | |
fi | |
local blob_path=$(guess-path "$backup_path" "$blob_id") | |
if [[ -z "$blob_path" ]]; then | |
echo "no such blob" | |
exit 1 | |
fi | |
# Put modified blob into backup | |
cp "$src_path" "$blob_path" | |
# Fix file size in backup manifest | |
local size=$(stat -f%z "$blob_path") | |
local tmpfile=$(mktemp) | |
sqlite3 "$manifest_path" "select HEX(file) from Files where fileID == \"$blob_id\";" | xxd -r -p > "$tmpfile" | |
# PlistBuddy messes up the plist format | |
# plutil errors out on changing the value | |
# have to use both | |
/usr/libexec/PlistBuddy -c "Set \$objects:1:Size $size" "$tmpfile" | |
plutil -convert binary1 -o "${tmpfile}.bin" "$tmpfile" | |
local fixed_hex=$(cat "${tmpfile}.bin" | xxd -p -c 9999) | |
sqlite3 "$manifest_path" "update Files set file = X'$fixed_hex' where fileID == \"$blob_id\";" | |
rm -f "${tmpfile}.bin" "$tmpfile" | |
} | |
main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment