"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "fstransform/fstransform.sh" between
fstransform-0.9.3-src.tar.gz and fstransform-0.9.4.tar.gz

About: fstransform is a tool to change a file-system from one format to another, for example from jfs, xfs, or reiser to ext2, ext3, or ext4, in-place and without the need for backup.

fstransform.sh  (fstransform-0.9.3-src):fstransform.sh  (fstransform-0.9.4)
#!/bin/dash #!/bin/bash
# #
# fstransform - transform a file-system to another file-system type, # fstransform - transform a file-system to another file-system type,
# preserving its contents and without the need for a backup # preserving its contents and without the need for a backup
# #
# Copyright (C) 2012 Massimiliano Ghilardi # Copyright (C) 2012 Massimiliano Ghilardi
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
skipping to change at line 34 skipping to change at line 34
# Author: max # Author: max
# #
____=' ' ____=' '
PROG=fstransform PROG=fstransform
PROG_VERSION=%PACKAGE_VERSION% PROG_VERSION=%PACKAGE_VERSION%
BOOT_CMD_which=which BOOT_CMD_which=which
CMDS_bootstrap="which expr id" CMDS_bootstrap="which expr id"
CMDS="stat mkfifo blockdev losetup fsck mkfs mount umount mkdir rmdir rm dd sync CMDS="stat mkfifo blockdev losetup fsck mkfs mount umount mkdir rmdir rm dd sync
fsmove fsremap" fsmove fsmount_kernel fsremap"
# optional commands # optional commands
CMDS_optional="sleep date" CMDS_optional="sleep date"
# commands that are optional or required, depending on --prealloc command-line o
ption
CMDS_prealloc="fsattr"
# commands that may need different variants for source and target file-systems # commands that may need different variants for source and target file-systems
CMDS_dual="fsck" CMDS_dual="fsck"
# commands not found in environment # commands not found in environment
CMDS_missing= CMDS_missing=
# start with a clean environment # start with a clean environment
ERR=0 ERR=0
DEVICE= DEVICE=
FSTYPE= FSTYPE=
FSTYPES_TESTED="minix ext2 ext3 ext4 reiserfs jfs xfs"
# nilfs2 is under test, works as target but as fails as source: gets full with u
sage = 100%
# ocfs2 and reiserfs4 are under test, got kernel crash testing them
# ntfs is under test. ntfs->ext4 gives nasty "/dev/loop0: I/O error" kernel mess
ages
# ntfs->ext2 seems to work but FUSE ntfs-3g is unbearably sl
ow on large files
FSTYPES_TESTED="ext2 ext3 ext4 reiserfs jfs xfs"
DEVICE_BLOCK_SIZE= DEVICE_BLOCK_SIZE=
DEVICE_SIZE_IN_BYTES= DEVICE_SIZE_IN_BYTES=
DEVICE_SIZE_IN_BLOCKS= DEVICE_SIZE_IN_BLOCKS=
DEVICE_IS_INITIALLY_MOUNTED= DEVICE_IS_INITIALLY_MOUNTED=
DEVICE_MOUNT_POINT= DEVICE_MOUNT_POINT=
DEVICE_MOUNT_OPTS_RW=rw
DEVICE_FSTYPE= DEVICE_FSTYPE=
LOOP_FILE= LOOP_FILE=
LOOP_DEVICE= LOOP_DEVICE=
LOOP_SIZE_IN_BYTES= LOOP_SIZE_IN_BYTES=
LOOP_MOUNT_POINT= LOOP_MOUNT_POINT=
LOOP_MOUNT_OPTS_RW=rw
ZERO_FILE= ZERO_FILE=
OPT_CREATE_ZERO_FILE=no OPT_CREATE_ZERO_FILE=no
OPT_ASK_QUESTIONS=yes OPT_ASK_QUESTIONS=yes
OPT_TTY_SHOW_TIME=yes OPT_TTY_SHOW_TIME=yes
OPT_PREALLOC=
OPTS_fsattr=
OPTS_fsmove= OPTS_fsmove=
OPTS_fsremap= OPTS_fsremap=
OPTS_fsmount_kernel=
OPTS_mkfs="-q" OPTS_mkfs="-q"
OPTS_fsck_source="-p -f" OPTS_fsck_source="-p -f"
OPTS_fsck_target="-p -f" OPTS_fsck_target="-p -f"
X_COPY_LOOP_FILE= X_COPY_LOOP_FILE=
X_COPY_DEVICE= X_COPY_DEVICE=
USER_ANSWER= USER_ANSWER=
USER_LOOP_SIZE_IN_BYTES= USER_LOOP_SIZE_IN_BYTES=
USER_FORCE_UNTESTED_FSTYPES= USER_FORCE_UNTESTED_FSTYPES=
for cmd in $CMDS_bootstrap $CMDS $CMDS_optional; do for cmd in $CMDS_bootstrap $CMDS $CMDS_maybe_required $CMDS_optional; do
eval "CMD_$cmd=" eval "CMD_$cmd="
done done
for cmd in $CMDS_dual; do for cmd in $CMDS_dual; do
eval "CMD_${cmd}_source=" eval "CMD_${cmd}_source="
eval "CMD_${cmd}_target=" eval "CMD_${cmd}_target="
done done
TMP_DIR="/tmp" TMP_DIR="/tmp"
VAR_TMP_DIR="/var/tmp" VAR_TMP_DIR="/var/tmp"
skipping to change at line 103 skipping to change at line 120
exec 5>/dev/null exec 5>/dev/null
# after log_init_{tty,gui}(), file descriptor 1 will be tty or gui file descript or # after log_init_{tty,gui}(), file descriptor 1 will be tty or gui file descript or
show_usage() { show_usage() {
echo "Usage: $0 [OPTION]... DEVICE NEW-FILE-SYSTEM-TYPE" echo "Usage: $0 [OPTION]... DEVICE NEW-FILE-SYSTEM-TYPE"
echo "Transform file system inside DEVICE to NEW-FILE-SYSTEM-TYPE," echo "Transform file system inside DEVICE to NEW-FILE-SYSTEM-TYPE,"
echo "preserving its contents and without need for backup" echo "preserving its contents and without need for backup"
echo echo
echo "Options:" echo "Options:"
echo " --help Print this help and exit" echo " --cmd-CMD-NAME=CMD-PATH set external command CMD-NAME to use."
echo " --new-size=SIZE Set new file system length. default: dev echo " default: autodetect"
ice length" echo " --force-untested-file-systems also transform untested file systems (DA
echo " --old-file-system=OLD-TYPE Override current (old) file system type NGEROUS)"
autodetection" echo " --list-source-file-systems list file systems supported as source an
echo " --force-untested-file-systems Transform also untested file systems (DA d exit"
NGEROUS)" echo " --list-target-file-systems list file systems supported as target an
echo " --list-source-file-systems Print list of file systems supported as d exit"
source" echo " --loop-file=LOOP-FILE override loop-file path"
echo " --list-target-file-systems Print list of file systems supported as echo " --loop-mount-point=PATH override loop-file mount point"
target" echo " --new-size=SIZE set new file system length. default: dev
echo " --reversible[=yes|no] Create zero-file, fsremap will do a reversible ice length"
transformation" echo " --current-fstype=OLD-TYPE override current (old) file system type
echo " default: no" autodetection"
echo " --no-questions Never ask any question or confirmation" echo " required for 'ntfs' file system"
echo " --show-time[=yes|=no] Show current time before each message. default echo " --opts-fsmove=OPTS pass OPTS as additional options to 'fsmo
: yes" ve'"
echo " --loop-file=LOOP-FILE Override loop-file path" echo " --opts-fsremap=OPTS pass OPTS as additional options to 'fsre
echo " --loop-mount-point=PATH Override loop-file mount point" map'"
echo " --zero-file=ZERO-FILE Override zero-file path" echo " --opts-mkfs=OPTS pass OPTS as options to 'mkfs'. default:
echo " --cmd-CMD-NAME=CMD-PATH Set external command CMD-NAME to use. default: '-q'"
autodetected" echo " --opts-fsck-source=OPTS override 'fsck' options for old file sys
echo " --opts-fsmove=OPTS Pass OPTS as additional options to 'fsmove'" tem. default: '-p -f'"
echo " --opts-fsremap=OPTS Pass OPTS as additional options to 'fsremap'" echo " --opts-fsck-target=OPTS override 'fsck' options for new file sys
echo " --opts-mkfs=OPTS Pass OPTS as options to 'mkfs'. default: '-q'" tem. default: '-p -f'"
echo " --opts-fsck-source=OPTS Override 'fsck' options for old file system. d echo " --show-time[=yes|=no] show current time before each message. d
efault: '-p -f'" efault: yes"
echo " --opts-fsck-target=OPTS Override 'fsck' options for new file system. d echo " --prealloc[=yes|no] use EXPERIMENTAL files preallocation. de
efault: '-p -f'" fault: no"
echo " --x-OPTION=VALUE Set internal, undocumented option. For maintai echo " --questions=[yes|no|on-error] whether to ask questions interactively.
ners only." default: on-error"
echo " --reversible[=yes|no] create zero-file, fsremap will do a reve
rsible transformation"
echo " default: no"
echo " --x-OPTION=VALUE set internal, undocumented option. For maintai
ners only."
echo " --zero-file=ZERO-FILE override zero-file path"
echo " --help display this help and exit"
echo " --version output version information and exit"
}
show_version() {
echo "fstransform (fstransform utilities) $PROG_VERSION"
echo "Copyright (C) 2011-2017 Massimiliano Ghilardi"
echo ""
echo "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.
html>."
echo "This is free software: you are free to change and redistribute it."
echo "There is NO WARRANTY, to the extent permitted by law."
} }
show_tested_fstypes() { show_tested_fstypes() {
for fstype in $FSTYPES_TESTED; do for fstype in $FSTYPES_TESTED; do
echo "$fstype" echo "$fstype"
done done
} }
if test "$#" = 1; then if test "$#" = 1; then
case "$1" in case "$1" in
--help) show_usage; exit 0;; --help) show_usage; exit 0;;
--version) show_version; exit 0;;
--list-source-file-systems) show_tested_fstypes; exit 0;; --list-source-file-systems) show_tested_fstypes; exit 0;;
--list-target-file-systems) show_tested_fstypes; exit 0;; --list-target-file-systems) show_tested_fstypes; exit 0;;
esac esac
fi fi
# parse command line arguments and set USER_CMD_* variables accordingly # parse command line arguments and set USER_CMD_* variables accordingly
parse_args() { parse_args() {
log_info "parsing command line arguments" log_info "parsing command line arguments"
for arg in "$@"; do for arg in "$@"; do
case "$arg" in case "$arg" in
--old-file-system=*) --cmd-*=* )
DEVICE_FSTYPE="`\"$CMD_expr\" match \"$arg\" '--old-fstype=\(.*\)'`" cmd="`\"$CMD_expr\" match \"$arg\" '--cmd-\(.*\)=.*'`"
log_info "device old (initial) file-system type '$DEVICE_FSTYPE' specifie user_cmd="`\"$CMD_expr\" match \"$arg\" '--cmd-.*=\(.*\)'`"
d on command line" eval "USER_CMD_$cmd='$user_cmd'"
;;
--new-size=*)
USER_LOOP_SIZE_IN_BYTES="`\"$CMD_expr\" match \"$arg\" '--new-size=\(.*\
)'`"
log_info "device new (final) file-system length '$USER_LOOP_SIZE_IN_BYTES
' bytes specified on command line"
;; ;;
--force-untested-file-systems) --force-untested-file-systems)
USER_FORCE_UNTESTED_FSTYPES="yes" USER_FORCE_UNTESTED_FSTYPES="yes"
log_info "forcing trasformation of untested file systems (DANGEROUS). '$a log_info "forcing trasformation of untested file systems (DANGEROUS). '$
rg' bytes specified on command line" arg' bytes specified on command line"
;;
--reversible|--reversible=yes)
OPT_CREATE_ZERO_FILE=yes
log_info "zero file will be created, '$arg' specified on command line"
;;
--reversible=no)
OPT_CREATE_ZERO_FILE=no
log_info "skipping creation of zero file, '$arg' specified on command lin
e"
;;
--no-questions)
OPT_ASK_QUESTIONS=no
log_info "assuming non-interactive execution, '$arg' specified on command
line"
;;
--show-time|--show-time=yes)
OPT_TTY_SHOW_TIME=yes
log_info "showing time-of-day for each message, '$arg' specified on comma
nd line"
;;
--show-time=no)
OPT_TTY_SHOW_TIME=no
log_info "hiding time-of-day for each message, '$arg' specified on comman
d line"
;; ;;
--loop-file=*) --loop-file=*)
LOOP_FILE="`\"$CMD_expr\" match \"$arg\" '--loop-file=\(.*\)'`" LOOP_FILE="`\"$CMD_expr\" match \"$arg\" '--loop-file=\(.*\)'`"
log_info "loop file '$LOOP_FILE' specified on command line" log_info "loop file '$LOOP_FILE' specified on command line"
;; ;;
--loop-mount-point=*) --loop-mount-point=*)
LOOP_MOUNT_POINT="`\"$CMD_expr\" match \"$arg\" '--loop-mount-point=\(.* \)'`" LOOP_MOUNT_POINT="`\"$CMD_expr\" match \"$arg\" '--loop-mount-point=\(.* \)'`"
log_info "loop file mount point '$LOOP_MOUNT_POINT' specified on command line" log_info "loop file mount point '$LOOP_MOUNT_POINT' specified on command line"
;; ;;
--zero-file=*) --new-size=*)
ZERO_FILE="`\"$CMD_expr\" match \"$arg\" '--zero-file=\(.*\)'`" USER_LOOP_SIZE_IN_BYTES="`\"$CMD_expr\" match \"$arg\" '--new-size=\(.*\
log_info "zero file '$ZERO_FILE' specified on command line" )'`"
log_info "device new (final) file-system length '$USER_LOOP_SIZE_IN_BYTE
S' bytes specified on command line"
;; ;;
--cmd-*=* ) --current-fstype=*)
cmd="`\"$CMD_expr\" match \"$arg\" '--cmd-\(.*\)=.*'`" DEVICE_FSTYPE="`\"$CMD_expr\" match \"$arg\" '--current-fstype=\(.*\)'`"
user_cmd="`\"$CMD_expr\" match \"$arg\" '--cmd-.*=\(.*\)'`" log_info "device initial (current) file-system type '$DEVICE_FSTYPE' spe
eval "USER_CMD_$cmd='$user_cmd'" cified on command line"
;; ;;
--opts-fsmove=*) --opts-fsmove=*)
OPTS_fsmove="`\"$CMD_expr\" match \"$arg\" '--opts-fsmove=\(.*\)'`" OPTS_fsmove="`\"$CMD_expr\" match \"$arg\" '--opts-fsmove=\(.*\)'`"
log_info "options '$OPTS_fsmove' for fsmove specified on command line" log_info "options '$OPTS_fsmove' for fsmove specified on command line"
;; ;;
--opts-fsremap=*) --opts-fsremap=*)
OPTS_fsremap="`\"$CMD_expr\" match \"$arg\" '--opts-fsremap=\(.*\)'`" OPTS_fsremap="`\"$CMD_expr\" match \"$arg\" '--opts-fsremap=\(.*\)'`"
log_info "options '$OPTS_fsremap' for fsremap specified on command line" log_info "options '$OPTS_fsremap' for fsremap specified on command line"
;; ;;
--opts-mkfs=*) --opts-mkfs=*)
OPTS_mkfs="`\"$CMD_expr\" match \"$arg\" '--opts-mkfs=\(.*\)'`" OPTS_mkfs="`\"$CMD_expr\" match \"$arg\" '--opts-mkfs=\(.*\)'`"
log_info "options '$OPTS_mkfs' for mkfs specified on command line" log_info "options '$OPTS_mkfs' for mkfs specified on command line"
;; ;;
--opts-fsck-source=*) --opts-fsck-source=*)
OPTS_fsck_source="`\"$CMD_expr\" match \"$arg\" '--opts-fsck-source=\(.* \)'`" OPTS_fsck_source="`\"$CMD_expr\" match \"$arg\" '--opts-fsck-source=\(.* \)'`"
log_info "options '$OPTS_fsck_source' for fsck(source file-system) specif log_info "options '$OPTS_fsck_source' for fsck(source file-system) speci
ied on command line" fied on command line"
;; ;;
--opts-fsck-target=*) --opts-fsck-target=*)
OPTS_fsck_target="`\"$CMD_expr\" match \"$arg\" '--opts-fsck-target=\(.* \)'`" OPTS_fsck_target="`\"$CMD_expr\" match \"$arg\" '--opts-fsck-target=\(.* \)'`"
log_info "options '$OPTS_FSCK_TARGET_FS' for fsck(target file-system) spe log_info "options '$OPTS_FSCK_TARGET_FS' for fsck(target file-system) sp
cified on command line" ecified on command line"
;; ;;
--prealloc|--prealloc=*)
# handled in parse_args_late() below
;;
--questions=yes|--interactive)
OPT_ASK_QUESTIONS=yes
log_info "assuming interactive execution, '$arg' specified on command li
ne"
;;
--questions=on-error)
OPT_ASK_QUESTIONS=on-error
log_info "assuming interactive execution, '$arg' specified on command li
ne"
;;
--questions=no|--no-questions)
OPT_ASK_QUESTIONS=no
log_info "assuming non-interactive execution, '$arg' specified on comman
d line"
;;
--reversible|--reversible=yes)
OPT_CREATE_ZERO_FILE=yes
log_info "zero file will be created, '$arg' specified on command line"
;;
--reversible=no)
OPT_CREATE_ZERO_FILE=no
log_info "skipping creation of zero file, '$arg' specified on command li
ne"
;;
--show-time|--show-time=yes)
OPT_TTY_SHOW_TIME=yes
log_info "showing time-of-day for each message, '$arg' specified on comm
and line"
;;
--show-time=no)
OPT_TTY_SHOW_TIME=no
log_info "hiding time-of-day for each message, '$arg' specified on comma
nd line"
;;
--x-copy-device=*) --x-copy-device=*)
X_COPY_DEVICE="`\"$CMD_expr\" match \"$arg\" '--x-copy-device=\(.*\)'`" X_COPY_DEVICE="`\"$CMD_expr\" match \"$arg\" '--x-copy-device=\(.*\)'`"
log_info "(internal option) device will be copied to '$X_COPY_DEVICE' jus t before remapping" log_info "(internal option) device will be copied to '$X_COPY_DEVICE' ju st before remapping"
;; ;;
--x-copy-loop-file=*) --x-copy-loop-file=*)
X_COPY_LOOP_FILE="`\"$CMD_expr\" match \"$arg\" '--x-copy-loop-file=\(.* \)'`" X_COPY_LOOP_FILE="`\"$CMD_expr\" match \"$arg\" '--x-copy-loop-file=\(.* \)'`"
CMDS="$CMDS cmp" CMDS="$CMDS cmp"
CMD_cmp= CMD_cmp=
log_info "(internal option) loop file will be copied to '$X_COPY_LOOP_FIL log_info "(internal option) loop file will be copied to '$X_COPY_LOOP_FI
E'" LE'"
log_info_add "command 'cmp' will be needed to verify it after transformat log_info_add "command 'cmp' will be needed to verify it after transforma
ion." tion."
;;
--zero-file=*)
ZERO_FILE="`\"$CMD_expr\" match \"$arg\" '--zero-file=\(.*\)'`"
log_info "zero file '$ZERO_FILE' specified on command line"
;; ;;
--*) --*)
log_info "ignoring unknown option '$arg'" log_warn "ignoring unknown option '$arg'"
;; ;;
*) *)
if test "$DEVICE" = ""; then if test "$DEVICE" = ""; then
DEVICE="$arg" DEVICE="$arg"
elif test "$FSTYPE" = ""; then elif test "$FSTYPE" = ""; then
FSTYPE="$arg" FSTYPE="$arg"
else else
log_info "ignoring extra argument '$arg'" log_info "ignoring extra argument '$arg'"
fi fi
;; ;;
esac
done
}
parse_args_late() {
for arg in "$@"; do
case "$arg" in
--prealloc=yes-i-want-to-lose-my-data)
OPT_PREALLOC=yes
log_warn "trying to enable EXPERIMENTAL files preallocation,"
log_warn_add "option '$arg' specified on command line."
log_warn_add "be prepared to LOSE your data!"
if test "$CMD_sleep" != ""; then
log_warn_add "continuing in 5 seconds..."
"$CMD_sleep" 5
fi
log_warn_add
;;
--prealloc|--prealloc=yes)
OPT_PREALLOC=no
log_warn "preallocation is EXPERIMENTAL and not well tested. if you real
ly want to enable it,"
log_warn_add "specify '--prealloc=yes-i-want-to-lose-my-data' on command
line and be prepared to LOSE your data."
if test "$CMD_sleep" != ""; then
log_warn_add "continuing in 5 seconds without preallocation..."
"$CMD_sleep" 5
fi
log_warn_add
;;
--prealloc=no)
OPT_PREALLOC=no
log_info "disabling preallocation, '$arg' specified on command line"
;;
esac esac
done done
} }
log_def_file() { log_def_file() {
log_file_timestamp() { log_file_timestamp() {
if test "$CMD_date" != ""; then if test "$CMD_date" != ""; then
echo -n "`\"$CMD_date\" \"+%Y-%m-%d %H:%M:%S\"` " 1>&5 echo -n "`\"$CMD_date\" \"+%Y-%m-%d %H:%M:%S\"` " 1>&5
fi fi
} }
skipping to change at line 312 skipping to change at line 386
"$CMD_mkdir" -p "$PROG_DIR" >/dev/null 2>&1 "$CMD_mkdir" -p "$PROG_DIR" >/dev/null 2>&1
> "$PROG_LOG_FILE" >/dev/null 2>&1 > "$PROG_LOG_FILE" >/dev/null 2>&1
if test -w "$PROG_LOG_FILE"; then if test -w "$PROG_LOG_FILE"; then
exec 5>"$PROG_LOG_FILE" exec 5>"$PROG_LOG_FILE"
fi fi
} }
log_def_tty() { log_def_tty() {
read_user_answer() { read_user_answer() {
if test "$OPT_ASK_QUESTIONS" = "yes"; then if test "$OPT_ASK_QUESTIONS" = "no"; then
read USER_ANSWER
else
USER_ANSWER= USER_ANSWER=
else
read USER_ANSWER
fi fi
} }
log_tty_timestamp() { log_tty_timestamp() {
if test "$OPT_TTY_SHOW_TIME" = "yes" -a "$CMD_date" != ""; then if test "$OPT_TTY_SHOW_TIME" = "yes" -a "$CMD_date" != ""; then
echo -n "`\"$CMD_date\" \"+%H:%M:%S\"` " echo -n "`\"$CMD_date\" \"+%H:%M:%S\"` "
fi fi
} }
log_tty_no_timestamp() { log_tty_no_timestamp() {
if test "$OPT_TTY_SHOW_TIME" = "yes" -a "$CMD_date" != ""; then if test "$OPT_TTY_SHOW_TIME" = "yes" -a "$CMD_date" != ""; then
skipping to change at line 423 skipping to change at line 497
detect_cmd() { detect_cmd() {
local my_cmd_which="$CMD_which" local my_cmd_which="$CMD_which"
if test "$my_cmd_which" = ""; then if test "$my_cmd_which" = ""; then
my_cmd_which="$BOOT_CMD_which" my_cmd_which="$BOOT_CMD_which"
fi fi
local cmd="$1" local cmd="$1"
local my_cmd= local my_cmd=
local user_cmd="`eval echo '$USER_CMD_'\"$cmd\"`" local user_cmd="`eval echo '$USER_CMD_'\"$cmd\"`"
log_start "checking for $cmd... " log_start "checking for $cmd... "
if test "$user_cmd" != ""; then if test "$user_cmd" != ""; then
my_cmd="`$my_cmd_which \"$user_cmd\"`" >/dev/null 2>&1 my_cmd="`$my_cmd_which \"$user_cmd\"`" >/dev/null 2>&1
if test "$my_cmd" != ""; then if test "$my_cmd" != ""; then
if test -x "$my_cmd"; then if test -x "$my_cmd"; then
log_end "'$my_cmd' ('$user_cmd' was specified)" log_end "'$my_cmd' ('$user_cmd' was specified)"
eval "CMD_$cmd='$my_cmd'" eval "CMD_$cmd='$my_cmd'"
return 0 return 0
fi fi
fi fi
skipping to change at line 463 skipping to change at line 537
local my_cmd_which="$CMD_which" local my_cmd_which="$CMD_which"
if test "$my_cmd_which" = ""; then if test "$my_cmd_which" = ""; then
my_cmd_which="$BOOT_CMD_which" my_cmd_which="$BOOT_CMD_which"
fi fi
local cmd="$1" local cmd="$1"
local source_or_target="$2" local source_or_target="$2"
local user_cmd="`eval echo '$USER_CMD_'\"$cmd\"'_'\"$source_or_target\"`" local user_cmd="`eval echo '$USER_CMD_'\"$cmd\"'_'\"$source_or_target\"`"
local my_cmd= local my_cmd=
log_start "checking for ${cmd}($source_or_target file-system)... " log_start "checking for ${cmd}($source_or_target file-system)... "
if test "$user_cmd" != ""; then if test "$user_cmd" != ""; then
my_cmd="`$my_cmd_which \"$user_cmd\"`" >/dev/null 2>&1 my_cmd="`$my_cmd_which \"$user_cmd\"`" >/dev/null 2>&1
if test "$my_cmd" != ""; then if test "$my_cmd" != ""; then
if test -x "$my_cmd"; then if test -x "$my_cmd"; then
log_end "'$my_cmd' ('$user_cmd' was specified)" log_end "'$my_cmd' ('$user_cmd' was specified)"
eval "CMD_${cmd}_$source_or_target='$my_cmd'" eval "CMD_${cmd}_$source_or_target='$my_cmd'"
return 0 return 0
fi fi
fi fi
fi fi
local nondual_cmd="`eval echo '$CMD_'\"$cmd\"`" local nondual_cmd="`eval echo '$CMD_'\"$cmd\"`"
log_end "'$nondual_cmd'" log_end "'$nondual_cmd'"
eval "CMD_${cmd}_$source_or_target='$nondual_cmd'" eval "CMD_${cmd}_$source_or_target='$nondual_cmd'"
return 0 return 0
} }
# apply fixes for special cases... fix_for_fstype_ntfs() {
fix_for_special_cases() {
if test "$DEVICE_FSTYPE" = "ntfs-3g"; then if test "$DEVICE_FSTYPE" = "ntfs-3g"; then
DEVICE_FSTYPE="ntfs" DEVICE_FSTYPE="ntfs"
fi fi
if test "$FSTYPE" = "ntfs-3g"; then if test "$FSTYPE" = "ntfs-3g"; then
FSTYPE="ntfs" FSTYPE="ntfs"
fi fi
local my_cmd_ntfsresize= local my_cmd_ntfsresize=
if test "$FSTYPE" = "ntfs" -o "$DEVICE_FSTYPE" = "ntfs"; then if test "$FSTYPE" = "ntfs" -o "$DEVICE_FSTYPE" = "ntfs"; then
log_info "applying special options for file-system type 'ntfs'" log_info "applying special options for file-system type 'ntfs'"
# we need 'ntfsresize', check if it's available # we need 'ntfsresize', check if it's available
my_cmd_ntfsresize="`$CMD_which ntfsresize`" my_cmd_ntfsresize="`$CMD_which ntfsresize`"
if test "$my_cmd_ntfsresize" = ""; then if test "$my_cmd_ntfsresize" = ""; then
log_warn "command 'ntfsresize' not found, it is needed to check integrity of file-system type 'ntfs'" log_warn "command 'ntfsresize' not found, it is needed to check integrity of file-system type 'ntfs'"
fi fi
fi fi
if test "$DEVICE_FSTYPE" = "ntfs"; then if test "$DEVICE_FSTYPE" = "ntfs"; then
DEVICE_MOUNT_OPTS_RW="rw,big_writes"
if test "$my_cmd_ntfsresize" != "" -a "$USER_CMD_fsck_source" = ""; then if test "$my_cmd_ntfsresize" != "" -a "$USER_CMD_fsck_source" = ""; then
USER_CMD_fsck_source="ntfsresize" USER_CMD_fsck_source="ntfsresize"
OPTS_fsck_source="-n" OPTS_fsck_source="-n"
detect_cmd_dual "fsck" "source" detect_cmd_dual "fsck" "source"
fi fi
fi fi
if test "$FSTYPE" = "ntfs"; then if test "$FSTYPE" = "ntfs"; then
LOOP_MOUNT_OPTS_RW="rw,big_writes"
if test "$my_cmd_ntfsresize" != "" -a "$USER_CMD_fsck_target" = ""; then if test "$my_cmd_ntfsresize" != "" -a "$USER_CMD_fsck_target" = ""; then
USER_CMD_fsck_target="ntfsresize" USER_CMD_fsck_target="ntfsresize"
OPTS_fsck_target="-n" OPTS_fsck_target="-n"
detect_cmd_dual "fsck" "target" detect_cmd_dual "fsck" "target"
fi fi
# 'mkfs -t nfs' needs option '-f' (quick format) to maintain sparse files # 'mkfs -t ntfs' needs option '-f' (quick format) to maintain sparse files
OPTS_mkfs="$OPTS_mkfs -f" OPTS_mkfs="$OPTS_mkfs -f"
fi fi
} }
fix_for_fstype_nilfs2() {
if test "$DEVICE_FSTYPE" = "nilfs2" -a "$USER_CMD_fsck_target" = ""; then
# fsck.nilfs2 does not exist.
# use ':', the standard 'do nothing successfully' command. no need to rely o
n /bin/true
USER_CMD_fsck_source=":"
fi
if test "$FSTYPE" = "nilfs2" -a "$USER_CMD_fsck_target" = ""; then
# fsck.nilfs2 does not exist.
# use ':', the standard 'do nothing successfully' command. no need to rely o
n /bin/true
USER_CMD_fsck_target=":"
fi
}
fix_for_fstype_xfs() {
if test "$DEVICE_FSTYPE" = "xfs" -a "$USER_CMD_fsck_target" = ""; then
# fsck.xfs does nothing, use xfs_repair instead.
USER_CMD_fsck_source="xfs_repair"
fi
if test "$FSTYPE" = "xfs" -a "$USER_CMD_fsck_target" = ""; then
# fsck.xfs does nothing, use xfs_repair instead.
USER_CMD_fsck_target="xfs_repair"
fi
}
# apply fixes for special cases...
fix_for_special_cases() {
fix_for_fstype_nilfs2
fix_for_fstype_ntfs
fix_for_fstype_xfs
}
fail_missing_cmds() { fail_missing_cmds() {
log_err "environment check failed." log_err "environment check failed."
log_err_add "Please install the commands$CMDS_missing before running $PROG" log_err_add "Please install the commands$CMDS_missing before running $PROG"
log_err_add "If these commands are already installed, add them to your \$PATH" log_err_add "If these commands are already installed, add them to your \$PATH"
log_err_add "or tell their location with the option --cmd-COMMAND=/path/to/you r/command" log_err_add "or tell their location with the option --cmd-COMMAND=/path/to/you r/command"
exit "$ERR" exit "$ERR"
} }
# bootstrap command detection (command 'which') and argument parsing (command 'e xpr') # bootstrap command detection (command 'which') and argument parsing (command 'e xpr')
for cmd in $CMDS_bootstrap; do for cmd in $CMDS_bootstrap; do
skipping to change at line 559 skipping to change at line 665
for cmd in $CMDS_dual; do for cmd in $CMDS_dual; do
detect_cmd_dual "$cmd" "source" || ERR="$?" detect_cmd_dual "$cmd" "source" || ERR="$?"
detect_cmd_dual "$cmd" "target" || ERR="$?" detect_cmd_dual "$cmd" "target" || ERR="$?"
done done
log_info "looking for optional commands" log_info "looking for optional commands"
for cmd in $CMDS_optional; do for cmd in $CMDS_optional; do
detect_cmd "$cmd" detect_cmd "$cmd"
done done
parse_args_late "$@"
if test "$OPT_PREALLOC" = yes; then
CMDS="$CMDS $CMDS_prealloc"
for cmd in $CMDS_prealloc; do
detect_cmd "$cmd" || ERR="$?"
done
fi
fix_for_special_cases fix_for_special_cases
if test "$ERR" != 0; then if test "$ERR" != 0; then
fail_missing_cmds fail_missing_cmds
fi fi
log_info "environment check passed." log_info "environment check passed."
ERR=0 ERR=0
skipping to change at line 591 skipping to change at line 707
log_err "Try '$0 --help' for more information" log_err "Try '$0 --help' for more information"
exit 1 exit 1
} }
check_command_line_args check_command_line_args
# inform if a command failed, and offer to fix manually # inform if a command failed, and offer to fix manually
exec_cmd_status() { exec_cmd_status() {
if test "$ERR" != 0; then if test "$ERR" != 0; then
log_err "command '$@' failed (exit status $ERR)" log_err "command '$@' failed (exit status $ERR)"
log_err_add "this is potentially a problem." log_err_add "this is potentially a problem."
if test "$OPT_ASK_QUESTIONS" = "yes"; then if test "$OPT_ASK_QUESTIONS" = "no"; then
log_err_add
log_err_add "you could try fix the problem yourself and continue"
log_err_add "but this is a non-interactive run, so $PROG will exit now"
else
log_err_add "you can either quit now by pressing ENTER or CTRL+C," log_err_add "you can either quit now by pressing ENTER or CTRL+C,"
log_err_add log_err_add
log_err_add "or, if you know what went wrong, you can fix it yourself," log_err_add "or, if you know what went wrong, you can fix it yourself,"
log_err_add "then manually run the command '$@'" log_err_add "then manually run the command '$@'"
log_err_add "(or something equivalent)" log_err_add "(or something equivalent)"
log_err_add_prompt "and finally resume this script by typing CONTINUE and pressing ENTER: " log_err_add_prompt "and finally resume this script by typing CONTINUE and pressing ENTER: "
else
log_err_add
log_err_add "you could try fix the problem yourself and continue"
log_err_add "but this is a non-interactive run, so $PROG will exit now"
fi fi
read_user_answer read_user_answer
if test "$USER_ANSWER" != "CONTINUE"; then if test "$USER_ANSWER" != "CONTINUE"; then
log_info 'exiting.' log_info 'exiting.'
exit "$ERR" exit "$ERR"
fi fi
ERR=0 ERR=0
fi fi
} }
skipping to change at line 644 skipping to change at line 760
exec_cmd_status "$CMD_mkfifo" -m 600 "$FIFO_OUT" "$FIFO_ERR" exec_cmd_status "$CMD_mkfifo" -m 600 "$FIFO_OUT" "$FIFO_ERR"
} }
create_fifo_out_err create_fifo_out_err
CLEANUP_SIGNALS="HUP INT QUIT ILL TRAP ABRT BUS FPE KILL SEGV PIPE TERM URG XCPU XFSZ VTALRM PROF IO PWR SYS" CLEANUP_SIGNALS="HUP INT QUIT ILL TRAP ABRT BUS FPE KILL SEGV PIPE TERM URG XCPU XFSZ VTALRM PROF IO PWR SYS"
CLEANUP_0= CLEANUP_0=
CLEANUP_1= CLEANUP_1=
CLEANUP_2= CLEANUP_2=
CLEANUP_3= CLEANUP_3=
CLEANUP_4= CLEANUP_4=
CLEANUP_5=
do_cleanup() { do_cleanup() {
trap - 0 $CLEANUP_SIGNALS trap - 0 $CLEANUP_SIGNALS
if test "$CLEANUP_5" != ""; then
eval "$CLEANUP_5" >/dev/null 2>/dev/null
fi
if test "$CLEANUP_4" != ""; then if test "$CLEANUP_4" != ""; then
eval "$CLEANUP_4" >/dev/null 2>/dev/null eval "$CLEANUP_4" >/dev/null 2>/dev/null
fi fi
if test "$CLEANUP_3" != ""; then if test "$CLEANUP_3" != ""; then
eval "$CLEANUP_3" >/dev/null 2>/dev/null eval "$CLEANUP_3" >/dev/null 2>/dev/null
fi fi
if test "$CLEANUP_2" != ""; then if test "$CLEANUP_2" != ""; then
eval "$CLEANUP_2" >/dev/null 2>/dev/null eval "$CLEANUP_2" >/dev/null 2>/dev/null
fi fi
if test "$CLEANUP_1" != ""; then if test "$CLEANUP_1" != ""; then
skipping to change at line 771 skipping to change at line 891
done done
} }
initial_mount_device() { initial_mount_device() {
DEVICE_MOUNT_POINT="$TMP_DIR/fstransform.mount.$$" DEVICE_MOUNT_POINT="$TMP_DIR/fstransform.mount.$$"
"$CMD_mkdir" -p "$DEVICE_MOUNT_POINT" >/dev/null 2>&1 "$CMD_mkdir" -p "$DEVICE_MOUNT_POINT" >/dev/null 2>&1
CLEANUP_0="'$CMD_rmdir' '$DEVICE_MOUNT_POINT'" CLEANUP_0="'$CMD_rmdir' '$DEVICE_MOUNT_POINT'"
if test "$DEVICE_FSTYPE" != ""; then if test "$DEVICE_FSTYPE" != ""; then
exec_cmd "$CMD_mount" -t "$DEVICE_FSTYPE" "$DEVICE" "$DEVICE_MOUNT_POINT" exec_cmd "$CMD_mount" "$DEVICE" "$DEVICE_MOUNT_POINT" -t "$DEVICE_FSTYPE"
else else
exec_cmd "$CMD_mount" "$DEVICE" "$DEVICE_MOUNT_POINT" exec_cmd "$CMD_mount" "$DEVICE" "$DEVICE_MOUNT_POINT"
fi fi
CLEANUP_0="'$CMD_umount' '$DEVICE'; $CLEANUP_0" CLEANUP_0="'$CMD_umount' '$DEVICE'; $CLEANUP_0"
} }
find_device_mount_point_and_fstype() { find_device_mount_point_and_fstype() {
local my_dev="$DEVICE" local my_dev="$DEVICE"
local my_mount_point= my_fstype= my_now= local my_mount_point= my_fstype= my_now=
local ret="`echo_device_mount_point_and_fstype \"$my_dev\"`" local ret="`echo_device_mount_point_and_fstype \"$my_dev\"`"
skipping to change at line 819 skipping to change at line 939
fi fi
if test ! -d "$my_mount_point"; then if test ! -d "$my_mount_point"; then
log_err "mount point '$my_mount_point' is not a directory" log_err "mount point '$my_mount_point' is not a directory"
exit 1 exit 1
fi fi
DEVICE_MOUNT_POINT="$my_mount_point" DEVICE_MOUNT_POINT="$my_mount_point"
if test "$my_fstype" = fuseblk; then if test "$my_fstype" = fuseblk; then
if test "$DEVICE_FSTYPE" != ""; then if test "$DEVICE_FSTYPE" != ""; then
log_info "file-system type '$my_fstype' is a placeholder name for FUSE... ignoring it (user specified type '$DEVICE_FSTYPE')" log_info "file-system type '$my_fstype' is a placeholder name for FUSE... ignoring it (user specified type '$DEVICE_FSTYPE')"
else else
log_info "file-system type '$my_fstype' is a placeholder name for FUSE... log_err "file-system type '$my_fstype' is a placeholder name for FUSE... u
ignoring it" nable to detect actual file-system type!"
log_err_add "please re-run $PROG adding the option --current-fstype={CURRE
NT_FILE_SYSTEM_TYPE}"
log_err_add "as for example --current-fstype=ntfs"
log_err_add "exiting now."
exit 1
fi fi
elif test "$DEVICE_FSTYPE" != ""; then elif test "$DEVICE_FSTYPE" != ""; then
# let's compare user-specified file-system type with what we found... # let's compare user-specified file-system type with what we found...
# still we honour what the user said. # still we honour what the user said.
if test "$DEVICE_FSTYPE" != "$my_fstype"; then if test "$DEVICE_FSTYPE" != "$my_fstype"; then
log_warn "does not match user-specified device file-system type '$DEVICE_F STYPE'. using user-specified value." log_warn "does not match user-specified device file-system type '$DEVICE_F STYPE'. using user-specified value."
fi fi
else else
DEVICE_FSTYPE="$my_fstype" DEVICE_FSTYPE="$my_fstype"
fi fi
skipping to change at line 855 skipping to change at line 979
for my_fstype in $FSTYPES_TESTED; do for my_fstype in $FSTYPES_TESTED; do
if test "$FSTYPE" = "$my_fstype"; then if test "$FSTYPE" = "$my_fstype"; then
my_fstype_target_ok=yes my_fstype_target_ok=yes
break break
fi fi
done done
if test "$my_fstype_source_ok" = "yes" -a "$my_fstype_target_ok" = "yes"; then if test "$my_fstype_source_ok" = "yes" -a "$my_fstype_target_ok" = "yes"; then
return 0 return 0
fi fi
local my_log=log_err local my_log=log_err my_log_add=log_err_add
if test "$USER_FORCE_UNTESTED_FSTYPES" = "yes"; then if test "$USER_FORCE_UNTESTED_FSTYPES" = "yes"; then
my_log=log_warn my_log=log_warn
my_log_add=log_warn_add
fi fi
if test "$my_fstype_source_ok" != "yes"; then if test "$my_fstype_source_ok" != "yes"; then
if test "$DEVICE_FSTYPE" = ""; then if test "$DEVICE_FSTYPE" = ""; then
"$my_log" "failed to detect device current file system type" "$my_log" "failed to detect device current file system type"
else else
"$my_log" "this program is UNTESTED on device current file system '$DEVICE _FSTYPE' !" "$my_log" "this program is UNTESTED on device current file system '$DEVICE _FSTYPE' !"
fi fi
fi fi
if test "$my_fstype_target_ok" != "yes"; then if test "$my_fstype_target_ok" != "yes"; then
"$my_log" "this program is UNTESTED on target file system '$FSTYPE' !" "$my_log" "this program is UNTESTED on target file system '$FSTYPE' !"
fi fi
"$my_log" "this program is tested ONLY on file systems: $FSTYPES_TESTED" "$my_log_add" "this program is tested ONLY on file systems: $FSTYPES_TESTED"
if test "$USER_FORCE_UNTESTED_FSTYPES" = "yes"; then if test "$USER_FORCE_UNTESTED_FSTYPES" = "yes"; then
"$my_log" "continuing anyway due to option '--force-untested-file-systems' ( DANGEROUS)" "$my_log_add" "continuing anyway due to option '--force-untested-file-system s' (DANGEROUS)"
return 0 return 0
else else
"$my_log" "cowardly refusing to run. you can use option '--force-untested-fi "$my_log_add" "cowardly refusing to run. if you know what you are doing, you
le-systems' if you know what you are doing (DANGEROUS, you can LOSE your DATA)" can use"
"$my_log_add" "option '--force-untested-file-systems' (DANGEROUS, you can LO
SE your DATA)"
exit 1 exit 1
fi fi
} }
check_for_tested_fstypes check_for_tested_fstypes
check_for_prealloc() {
if test "$OPT_PREALLOC" = "yes"; then
if test "$FSTYPE" = "ext4"; then
# detect if we can use preallocation
if test "$CMD_fsattr" != ""; then
if "$CMD_fsattr" --help >/dev/null 2>&1; then
log_info "enabling EXPERIMENTAL files preallocation: target FSTYPE is
'$FSTYPE' and command 'fsattr' is available"
OPT_PREALLOC=yes
else
log_warn "cannot enable EXPERIMENTAL files preallocation: target FSTYP
E is '$FSTYPE' but command 'fsattr' is a stub"
OPT_PREALLOC=no
fi
else
log_warn "cannot enable EXPERIMENTAL files preallocation: target FSTYPE
is '$FSTYPE' but command 'fsattr' is not available"
OPT_PREALLOC=no
fi
else
log_warn "cannot enable EXPERIMENTAL files preallocation: currently suppor
ted only 'ext4' target, not '$FSTYPE'"
OPT_PREALLOC=no
fi
fi
}
check_for_prealloc
find_device_size() { find_device_size() {
capture_cmd DEVICE_SIZE_IN_BYTES "$CMD_blockdev" --getsize64 "$DEVICE" capture_cmd DEVICE_SIZE_IN_BYTES "$CMD_blockdev" --getsize64 "$DEVICE"
log_info "device raw size = $DEVICE_SIZE_IN_BYTES bytes" log_info "device raw size = $DEVICE_SIZE_IN_BYTES bytes"
} }
find_device_size find_device_size
create_loop_or_zero_file() { create_loop_or_zero_file() {
local my_kind="$1" my_var="$2" my_file="$3" local my_kind="$1" my_var="$2" my_file="$3"
local my_pattern="$DEVICE_MOUNT_POINT/.fstransform.$my_kind.*" local my_pattern="$DEVICE_MOUNT_POINT/.fstransform.$my_kind.*"
local my_files="`echo $my_pattern`" local my_files="`echo $my_pattern`"
skipping to change at line 962 skipping to change at line 1112
# and in any case truncate it down to a multiple of device block size # and in any case truncate it down to a multiple of device block size
if test "$USER_LOOP_SIZE_IN_BYTES" -lt "$LOOP_SIZE_IN_BYTES"; then if test "$USER_LOOP_SIZE_IN_BYTES" -lt "$LOOP_SIZE_IN_BYTES"; then
: $(( LOOP_SIZE_IN_BYTES = USER_LOOP_SIZE_IN_BYTES / DEVICE_BLOCK_SIZE * D EVICE_BLOCK_SIZE )) : $(( LOOP_SIZE_IN_BYTES = USER_LOOP_SIZE_IN_BYTES / DEVICE_BLOCK_SIZE * D EVICE_BLOCK_SIZE ))
fi fi
log_info "sparse loop file will be $LOOP_SIZE_IN_BYTES bytes long (user spec ified $USER_LOOP_SIZE_IN_BYTES bytes)" log_info "sparse loop file will be $LOOP_SIZE_IN_BYTES bytes long (user spec ified $USER_LOOP_SIZE_IN_BYTES bytes)"
fi fi
exec_cmd "$CMD_dd" if=/dev/zero of="$LOOP_FILE" bs=1 count=1 seek="$(( LOOP_SI ZE_IN_BYTES - 1 ))" exec_cmd "$CMD_dd" if=/dev/zero of="$LOOP_FILE" bs=1 count=1 seek="$(( LOOP_SI ZE_IN_BYTES - 1 ))"
} }
create_loop_file create_loop_file
remount_device_ro() {
log_info "unmounting device '$DEVICE' and remounting it read-only using kernel
driver"
exec_cmd "$CMD_umount" "$DEVICE"
exec_cmd "$CMD_fsmount_kernel" "$DEVICE" "$DEVICE_MOUNT_POINT" -o ro -t "$DEVI
CE_FSTYPE"
}
remount_device_rw() {
log_info "unmounting device '$DEVICE' and remounting it read-write"
exec_cmd "$CMD_umount" "$DEVICE"
exec_cmd "$CMD_mount" "$DEVICE" "$DEVICE_MOUNT_POINT" -o "$DEVICE_MOUNT_OPTS_R
W" -t "$DEVICE_FSTYPE"
}
# detect unsupported corner cases, for example:
# 1) source file systems without FIEMAP support and too large for FIBMAP
# 2) other inconsistencies (which?)
early_remap_validate() {
log_info "launching '$CMD_fsremap' in simulated mode for pre-validation"
exec_cmd "$CMD_fsremap" -q $my_OPTS_fsremap -n -- "$DEVICE" "$LOOP_FILE"
}
remount_device_ro
early_remap_validate
remount_device_rw
connect_loop_device() { connect_loop_device() {
capture_cmd LOOP_DEVICE "$CMD_losetup" -f capture_cmd LOOP_DEVICE "$CMD_losetup" -f
exec_cmd "$CMD_losetup" "$LOOP_DEVICE" "$LOOP_FILE" exec_cmd "$CMD_losetup" "$@" "$LOOP_DEVICE" "$LOOP_FILE"
log_info "connected loop device '$LOOP_DEVICE' to file '$LOOP_FILE'" log_info "connected loop device '$LOOP_DEVICE' to file '$LOOP_FILE'"
CLEANUP_2="'$CMD_losetup' -d '$LOOP_DEVICE'" CLEANUP_2="'$CMD_losetup' -d '$LOOP_DEVICE'"
} }
connect_loop_device connect_loop_device
disconnect_loop_device() { disconnect_loop_device() {
local my_iter=0 local my_iter=0
# loop device sometimes needs a little time to become free... # loop device sometimes needs a little time to become free...
for my_iter in 1 2 3 4; do for my_iter in 1 2 3 4; do
skipping to change at line 1008 skipping to change at line 1183
if test "$LOOP_MOUNT_POINT" = ""; then if test "$LOOP_MOUNT_POINT" = ""; then
LOOP_MOUNT_POINT="$TMP_DIR/fstransform.loop.$$" LOOP_MOUNT_POINT="$TMP_DIR/fstransform.loop.$$"
exec_cmd "$CMD_mkdir" "$LOOP_MOUNT_POINT" exec_cmd "$CMD_mkdir" "$LOOP_MOUNT_POINT"
else else
"$CMD_expr" match "$LOOP_MOUNT_POINT" "/.*" >/dev/null 2>/dev/null "$CMD_expr" match "$LOOP_MOUNT_POINT" "/.*" >/dev/null 2>/dev/null
ERR="$?" ERR="$?"
if test "$ERR" != 0; then if test "$ERR" != 0; then
log_warn "user-specified loop file mount point '$LOOP_MOUNT_POINT' should start with '/'" log_warn "user-specified loop file mount point '$LOOP_MOUNT_POINT' should start with '/'"
log_warn_add "i.e. it should be an absolute path." log_warn_add "i.e. it should be an absolute path."
log_warn_add "$PROG cannot ensure that '$LOOP_MOUNT_POINT' is outside '$DE VICE_MOUNT_POINT'" log_warn_add "$PROG cannot ensure that '$LOOP_MOUNT_POINT' is outside '$DE VICE_MOUNT_POINT'"
if test "$OPT_ASK_QUESTIONS" = "yes"; then if test "$OPT_ASK_QUESTIONS" = "no"; then
log_warn_add "continue at your own risk"
log_warn_add
log_warn_add_prompt "press ENTER to continue, or CTRL+C to quit: "
read_user_answer
else
log_err_add "you could examine the previous warning and decide to contin ue at your own risk" log_err_add "you could examine the previous warning and decide to contin ue at your own risk"
log_err_add "but this is a non-interactive run, so $PROG will exit now" log_err_add "but this is a non-interactive run, so $PROG will exit now"
log_info "exiting." log_info "exiting."
exit "$ERR" exit "$ERR"
else
log_warn_add "continue at your own risk"
log_warn_add
log_warn_add_prompt "press ENTER to continue, or CTRL+C to quit: "
read_user_answer
fi fi
else else
"$CMD_expr" match "$LOOP_MOUNT_POINT" "$DEVICE_MOUNT_POINT/.*" >/dev/null 2>/dev/null "$CMD_expr" match "$LOOP_MOUNT_POINT" "$DEVICE_MOUNT_POINT/.*" >/dev/null 2>/dev/null
if test "$?" = 0; then if test "$?" = 0; then
log_err "user-specified loop file mount point '$LOOP_MOUNT_POINT' seems to be inside '$DEVICE_MOUNT_POINT'" log_err "user-specified loop file mount point '$LOOP_MOUNT_POINT' seems to be inside '$DEVICE_MOUNT_POINT'"
log_err_add "maybe somebody is trying to break $PROG and lose data?" log_err_add "maybe somebody is trying to break $PROG and lose data?"
log_err_add "I give up, sorry" log_err_add "I give up, sorry"
exit 1 exit 1
fi fi
fi fi
fi fi
log_info "mounting loop device '$LOOP_DEVICE' on '$LOOP_MOUNT_POINT' ..." log_info "mounting loop device '$LOOP_DEVICE' on '$LOOP_MOUNT_POINT' $1..."
exec_cmd "$CMD_mount" -t "$FSTYPE" "$LOOP_DEVICE" "$LOOP_MOUNT_POINT"
local my_mount_opts="$LOOP_MOUNT_OPTS_RW"
if test "$1" = readonly; then
my_mount_opts="ro"
fi
exec_cmd "$CMD_mount" "$LOOP_DEVICE" "$LOOP_MOUNT_POINT" -t "$FSTYPE" -o "$my_
mount_opts"
log_info "loop device '$LOOP_DEVICE' mounted successfully." log_info "loop device '$LOOP_DEVICE' mounted successfully."
CLEANUP_3="'$CMD_umount' $LOOP_DEVICE" CLEANUP_3="'$CMD_rmdir' $LOOP_MOUNT_POINT"
CLEANUP_4="'$CMD_umount' $LOOP_DEVICE"
} }
mount_loop_file mount_loop_file
move_device_contents_into_loop_file() { move_device_contents_into_loop_file() {
log_info "preliminary steps completed, now comes the delicate part:"
log_info "$PROG will move '$DEVICE' contents into the loop file."
log_warn "THIS IS IMPORTANT! if either the original device '$DEVICE'" if test "$OPT_PREALLOC" = yes; then
log_warn_add "or the loop device '$LOOP_DEVICE' become FULL," log_info "preallocating loop file contents."
log_warn_add log_info "this may take some time, please be patient..."
log_warn_add " YOU WILL LOSE YOUR DATA !"
log_warn_add
log_warn_add "$PROG checks for enough available space,"
log_warn_add "in any case it is recommended to open another terminal, type"
log_warn_add " watch df $DEVICE $LOOP_DEVICE"
log_warn_add "and check that both the original device '$DEVICE'"
log_warn_add "and the loop device '$LOOP_DEVICE' are NOT becoming full."
log_warn_add "if one of them is becoming full (or both),"
log_warn_add "you MUST stop $PROG with CTRL+C or equivalent."
log_warn_add
if test "$OPT_ASK_QUESTIONS" = "yes"; then
log_warn_add "this is your chance to quit."
log_warn_add_prompt "press ENTER to continue, or CTRL+C to quit: "
read_user_answer
fi
log_info "moving '$DEVICE' contents into the loop file."
log_info "this may take a long time, please be patient..."
# do not remove $LOOP_FILE anymore: in a moment it will contain users' data! OPTS_fsmove="$OPTS_fsmove --io=prealloc"
CLEANUP_1= else
log_info "preliminary steps completed, now comes the delicate part:"
log_info "$PROG will move '$DEVICE' contents into the loop file."
exec_cmd "$CMD_fsmove" $OPTS_fsmove -- "$DEVICE_MOUNT_POINT" "$LOOP_MOUNT_POIN log_warn "THIS IS IMPORTANT! if either the original device '$DEVICE'"
T" --exclude "$LOOP_FILE" log_warn_add "or the loop device '$LOOP_DEVICE' become FULL,"
log_warn_add
log_warn_add " YOU WILL LOSE YOUR DATA !"
log_warn_add
log_warn_add "$PROG checks for enough available space,"
log_warn_add "in any case it is recommended to open another terminal, type"
log_warn_add " watch df $DEVICE $LOOP_DEVICE"
log_warn_add "and check that both the original device '$DEVICE'"
log_warn_add "and the loop device '$LOOP_DEVICE' are NOT becoming full."
log_warn_add "if one of them is becoming full (or both),"
log_warn_add "you MUST stop $PROG with CTRL+C or equivalent."
log_warn_add
if test "$OPT_ASK_QUESTIONS" = "extra"; then
log_warn_add "this is your chance to quit."
log_warn_add_prompt "press ENTER to continue, or CTRL+C to quit: "
read_user_answer
fi
log_info "moving '$DEVICE' contents into the loop file."
log_info "this may take a long time, please be patient..."
# do not remove $LOOP_FILE anymore: in a moment it will contain users' data!
CLEANUP_1=
fi
exec_cmd "$CMD_fsmove" $OPTS_fsmove -- "$DEVICE_MOUNT_POINT" "$LOOP_MOUNT_POIN
T" --exclude "$LOOP_FILE"
} }
move_device_contents_into_loop_file move_device_contents_into_loop_file
umount_and_fsck_loop_file() { umount_and_fsck_loop_file() {
log_info "unmounting and running '$CMD_fsck_target' (disk check) on loop file '$LOOP_FILE'" log_info "unmounting and running '$CMD_fsck_target' (disk check) on loop file '$LOOP_FILE'"
exec_cmd "$CMD_umount" "$LOOP_DEVICE" exec_cmd "$CMD_umount" "$LOOP_DEVICE"
CLEANUP_3= CLEANUP_4=
# ignore errors if removing "$LOOP_MOUNT_POINT" fails
"$CMD_rmdir" "$LOOP_MOUNT_POINT" >/dev/null 2>/dev/null
exec_cmd_fsck "$CMD_fsck_target" $OPTS_fsck_target "$LOOP_DEVICE" exec_cmd_fsck "$CMD_fsck_target" $OPTS_fsck_target "$LOOP_DEVICE"
exec_cmd "$CMD_sync" exec_cmd "$CMD_sync"
if test "$X_COPY_LOOP_FILE" != ""; then if test "$X_COPY_LOOP_FILE" != ""; then
log_info "(internal option) copying loop file '$LOOP_FILE' to '$X_COPY_LOOP_ FILE'" log_info "(internal option) copying loop file '$LOOP_FILE' to '$X_COPY_LOOP_ FILE'"
exec_cmd "$CMD_dd" bs=64k if="$LOOP_DEVICE" of="$X_COPY_LOOP_FILE" exec_cmd "$CMD_dd" bs=64k if="$LOOP_DEVICE" of="$X_COPY_LOOP_FILE"
fi fi
} }
umount_and_fsck_loop_file umount_and_fsck_loop_file
disconnect_loop_device disconnect_loop_device
clear_loop_file_prealloc_flag() {
if test "$OPT_PREALLOC" = yes; then
log_info "executing 'fsattr' to clear preallocation flags inside loop file '
$LOOP_FILE'"
exec_cmd "$CMD_fsattr" --fstype="$FSTYPE" --files=normal "$LOOP_FILE"
fi
}
clear_loop_file_prealloc_flag
create_zero_file() { create_zero_file() {
if test "$OPT_CREATE_ZERO_FILE" != "yes"; then if test "$OPT_CREATE_ZERO_FILE" != "yes"; then
return 0 return 0
fi fi
create_loop_or_zero_file zero ZERO_FILE "$ZERO_FILE" create_loop_or_zero_file zero ZERO_FILE "$ZERO_FILE"
CLEANUP_4="'$CMD_rm' -f '$ZERO_FILE'" CLEANUP_5="'$CMD_rm' -f '$ZERO_FILE'"
log_info "filling '$ZERO_FILE' with zeroes until device '$DEVICE' is full" log_info "filling '$ZERO_FILE' with zeroes until device '$DEVICE' is full"
log_info_add "needed by '$CMD_fsremap' to locate unused space." log_info_add "needed by '$CMD_fsremap' to locate unused space."
log_info_add "this may take a while, please be patient..." log_info_add "this may take a while, please be patient..."
# trying to fill a device until it fails with "no space left on device" is not very nice # trying to fill a device until it fails with "no space left on device" is not very nice
# and can probably cause file-system corruption if device happens to be a loop -mounted file # and can probably cause file-system corruption if device happens to be a loop -mounted file
# which contains non-synced data. # which contains non-synced data.
# to be safe, we 'sync' BEFORE and AFTER filling the device # to be safe, we 'sync' BEFORE and AFTER filling the device
exec_cmd "$CMD_sync" exec_cmd "$CMD_sync"
skipping to change at line 1134 skipping to change at line 1328
exec_cmd "$CMD_umount" "$DEVICE" exec_cmd "$CMD_umount" "$DEVICE"
log_info "running '$CMD_fsck_source' (disk check) on device '$DEVICE'" log_info "running '$CMD_fsck_source' (disk check) on device '$DEVICE'"
exec_cmd_fsck "$CMD_fsck_source" $OPTS_fsck_source "$DEVICE" exec_cmd_fsck "$CMD_fsck_source" $OPTS_fsck_source "$DEVICE"
exec_cmd "$CMD_sync" exec_cmd "$CMD_sync"
if test "$X_COPY_DEVICE" != ""; then if test "$X_COPY_DEVICE" != ""; then
log_info "(internal option) copying device '$DEVICE' to '$X_COPY_DEVICE'" log_info "(internal option) copying device '$DEVICE' to '$X_COPY_DEVICE'"
exec_cmd "$CMD_dd" bs=64k if="$DEVICE" of="$X_COPY_DEVICE" exec_cmd "$CMD_dd" bs=64k if="$DEVICE" of="$X_COPY_DEVICE"
fi fi
log_info "mounting again device '$DEVICE' read-only" log_info "mounting again device '$DEVICE' read-only with kernel driver"
if test "$DEVICE_FSTYPE" != ""; then exec_cmd "$CMD_fsmount_kernel" "$DEVICE" "$DEVICE_MOUNT_POINT" -o ro -t "$DEVI
exec_cmd "$CMD_mount" -t "$DEVICE_FSTYPE" "$DEVICE" "$DEVICE_MOUNT_POINT" -o CE_FSTYPE"
ro
else
exec_cmd "$CMD_mount" "$DEVICE" "$DEVICE_MOUNT_POINT" -o ro
fi
} }
remount_device_ro_and_fsck remount_device_ro_and_fsck
reconnect_and_remount_ro_loop_device_for_prealloc() {
# losetup option "-r" means read-only
connect_loop_device "-r"
mount_loop_file readonly
# update 'fsremap' options
OPTS_fsremap="$OPTS_fsremap --io=prealloc --device-mount-point=$DEVICE_MOUNT_P
OINT --loop-mount-point=$LOOP_MOUNT_POINT --loop-device=$LOOP_DEVICE --cmd-loset
up=$CMD_losetup"
}
if test "$OPT_PREALLOC" = yes; then
reconnect_and_remount_ro_loop_device_for_prealloc
fi
remap_device_and_sync() { remap_device_and_sync() {
local my_OPTS_fsremap="$OPTS_fsremap" local my_OPTS_fsremap="--questions=$OPT_ASK_QUESTIONS $OPTS_fsremap"
if test "$OPT_ASK_QUESTIONS" != "yes"; then
my_OPTS_fsremap="$my_OPTS_fsremap --no-questions"
fi
log_info "launching '$CMD_fsremap' in simulated mode" log_info "launching '$CMD_fsremap' in simulated mode"
if test "$OPT_CREATE_ZERO_FILE" = "yes"; then if test "$OPT_CREATE_ZERO_FILE" = "yes"; then
exec_cmd "$CMD_fsremap" -n -q $my_OPTS_fsremap -- "$DEVICE" "$LOOP_FILE" "$Z ERO_FILE" exec_cmd "$CMD_fsremap" -q $my_OPTS_fsremap -n -- "$DEVICE" "$LOOP_FILE" "$Z ERO_FILE"
else else
exec_cmd "$CMD_fsremap" -n -q $my_OPTS_fsremap -- "$DEVICE" "$LOOP_FILE" exec_cmd "$CMD_fsremap" -q $my_OPTS_fsremap -n -- "$DEVICE" "$LOOP_FILE"
fi fi
log_info "launching '$CMD_fsremap' in REAL mode to perform in-place remapping. " log_info "launching '$CMD_fsremap' in REAL mode to perform in-place remapping. "
# starting to remap device, $ZERO_FILE will not exist anymore # starting to remap device, $ZERO_FILE will not exist anymore
CLEANUP_4= CLEANUP_5=
if test "$OPT_CREATE_ZERO_FILE" = "yes"; then if test "$OPT_CREATE_ZERO_FILE" = "yes"; then
exec_cmd "$CMD_fsremap" -q --cmd-umount="$CMD_umount" $my_OPTS_fsremap -- "$ DEVICE" "$LOOP_FILE" "$ZERO_FILE" exec_cmd "$CMD_fsremap" -q $my_OPTS_fsremap --cmd-umount="$CMD_umount" -- "$ DEVICE" "$LOOP_FILE" "$ZERO_FILE"
else else
exec_cmd "$CMD_fsremap" -q --cmd-umount="$CMD_umount" $my_OPTS_fsremap -- "$ DEVICE" "$LOOP_FILE" exec_cmd "$CMD_fsremap" -q $my_OPTS_fsremap --cmd-umount="$CMD_umount" -- "$ DEVICE" "$LOOP_FILE"
fi fi
exec_cmd "$CMD_sync" exec_cmd "$CMD_sync"
if test "$X_COPY_LOOP_FILE" != ""; then if test "$X_COPY_LOOP_FILE" != ""; then
log_info "(internal option) comparing transformed device '$DEVICE' with prev iously saved loop file '$X_COPY_LOOP_FILE'" log_info "(internal option) comparing transformed device '$DEVICE' with prev iously saved loop file '$X_COPY_LOOP_FILE'"
# loop file may be smaller than device... # loop file may be smaller than device...
# more exactly its length will be = device length rounded down to device blo ck size # more exactly its length will be = device length rounded down to device blo ck size
"$CMD_dd" if="$DEVICE" bs="$DEVICE_BLOCK_SIZE" count="$DEVICE_SIZE_IN_BLOCKS " | "$CMD_cmp" - "$X_COPY_LOOP_FILE" || exit 1 "$CMD_dd" if="$DEVICE" bs="$DEVICE_BLOCK_SIZE" count="$DEVICE_SIZE_IN_BLOCKS " | "$CMD_cmp" - "$X_COPY_LOOP_FILE" || exit 1
skipping to change at line 1187 skipping to change at line 1387
remap_device_and_sync remap_device_and_sync
fsck_device() { fsck_device() {
log_info "running again '$CMD_fsck_target' (disk check) on device '$DEVICE'" log_info "running again '$CMD_fsck_target' (disk check) on device '$DEVICE'"
exec_cmd_fsck "$CMD_fsck_target" $OPTS_fsck_target "$DEVICE" exec_cmd_fsck "$CMD_fsck_target" $OPTS_fsck_target "$DEVICE"
} }
fsck_device fsck_device
final_mount_device() { final_mount_device() {
log_info "mounting transformed device '$DEVICE'" log_info "mounting transformed device '$DEVICE'"
exec_cmd "$CMD_mount" -t "$FSTYPE" "$DEVICE" "$DEVICE_MOUNT_POINT" exec_cmd "$CMD_mount" "$DEVICE" "$DEVICE_MOUNT_POINT" -t "$FSTYPE"
log_info "completed successfully. your new '$FSTYPE' file-system is mounted at '$DEVICE_MOUNT_POINT'" log_info "completed successfully. your new '$FSTYPE' file-system is mounted at '$DEVICE_MOUNT_POINT'"
} }
if test "$DEVICE_IS_INITIALLY_MOUNTED" = "yes"; then if test "$DEVICE_IS_INITIALLY_MOUNTED" = "yes"; then
final_mount_device final_mount_device
else else
log_info "completed successfully. device '$DEVICE' now contains '$FSTYPE' file -system" log_info "completed successfully. device '$DEVICE' now contains '$FSTYPE' file -system"
fi fi
 End of changes. 76 change blocks. 
188 lines changed or deleted 416 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)