diff options
Diffstat (limited to 'package')
| -rwxr-xr-x | package/base-files/files/etc/preinit | 8 | ||||
| -rw-r--r-- | package/base-files/files/lib/upgrade/common.sh | 151 | ||||
| -rwxr-xr-x | package/base-files/files/sbin/sysupgrade | 92 | ||||
| -rw-r--r-- | package/mtd/src/jffs2.c | 7 | ||||
| -rw-r--r-- | package/mtd/src/mtd.c | 2 | 
5 files changed, 257 insertions, 3 deletions
| diff --git a/package/base-files/files/etc/preinit b/package/base-files/files/etc/preinit index c11732f7a..452209ff9 100755 --- a/package/base-files/files/etc/preinit +++ b/package/base-files/files/etc/preinit @@ -60,6 +60,14 @@ echo "$HOTPLUG" > /proc/sys/kernel/hotplug  eval ${FAILSAFE:+failsafe}  lock -w /tmp/.failsafe  mount_root +[ -f /sysupgrade.tgz ] && { +	echo "- config restore -" +	cd / +	mv sysupgrade.tgz /tmp +	tar xzf /tmp/sysupgrade.tgz +	rm -f /tmp/sysupgrade.tgz +	sync +}  echo "- init -" diff --git a/package/base-files/files/lib/upgrade/common.sh b/package/base-files/files/lib/upgrade/common.sh new file mode 100644 index 000000000..6cc09e1a4 --- /dev/null +++ b/package/base-files/files/lib/upgrade/common.sh @@ -0,0 +1,151 @@ +#!/bin/sh + +RAM_ROOT=/tmp/root + +ldd() { LD_TRACE_LOADED_OBJECTS=1 $*; } +libs() { ldd $* | awk '{print $3}'; } + +install_file() { # <file> [ <file> ... ] +	for file in "$@"; do +		dest="$RAM_ROOT/$file" +		[ -f $file -a ! -f $dest ] && { +			dir="$(dirname $dest)" +			mkdir -p "$dir" +			cp $file $dest +		} +	done +} + +install_bin() { # <file> [ <symlink> ... ] +	src=$1 +	files=$1 +	[ -x "$src" ] && files="$src $(libs $src)" +	install_file $files +	shift +	for link in "$@"; do { +		dest="$RAM_ROOT/$link" +		dir="$(dirname $dest)" +		mkdir -p "$dir" +		[ -f "$dest" ] || ln -s $src $dest +	}; done +} + +pivot() { # <new_root> <old_root> +	mount | grep "on $1 type" 2>&- 1>&- || mount -o bind $1 $1 +	mkdir -p $1$2 $1/proc $1/dev $1/tmp $1/jffs && \ +	mount -o move /proc $1/proc && \ +	pivot_root $1 $1$2 || { +        umount $1 $1 +		return 1 +	} +	mount -o move $2/dev /dev +	mount -o move $2/tmp /tmp +	mount -o move $2/jffs /jffs 2>&- +	return 0 +} + +run_ramfs() { # <command> [...] +	install_bin /bin/busybox /bin/ash /bin/sh /bin/mount /bin/umount /sbin/pivot_root /usr/bin/wget /sbin/reboot /bin/sync /bin/dd /bin/grep /bin/cp /bin/mv /bin/tar /usr/bin/md5sum "/usr/bin/[" /bin/vi +	install_bin /sbin/mtd +	for file in $RAMFS_COPY_BIN; do +		install_bin $file +	done +	install_file /etc/resolv.conf /etc/functions.sh /lib/upgrade/*.sh $RAMFS_COPY_DATA + +	pivot $RAM_ROOT /mnt || { +		echo "Failed to switch over to ramfs. Please reboot." +		exit 1 +	} + +	mount -o remount,ro /mnt +	umount -l /mnt + +	grep /jffs /proc/mounts > /dev/null && { +		mount -o remount,ro /jffs +		umount -l /jffs +	} + +	# spawn a new shell from ramdisk to reduce the probability of cache issues +	exec /bin/busybox ash -c "$*" +} + +run_hooks() { +	local arg="$1"; shift +	for func in "$@"; do +		eval "$func $arg" +	done +} + +ask_bool() { +	local default="$1"; shift; +	local answer="$default" + +	[ "$INTERACTIVE" -eq 1 ] && { +		case "$default" in +			0) echo -n "$* (y/N): ";; +			*) echo -n "$* (Y/n): ";; +		esac +		read answer +		case "$answer" in +			y*) answer=1;; +			n*) answer=0;; +			*) answer="$default";; +		esac +	} +	[ "$answer" -gt 0 ] +} + +v() { +	[ "$VERBOSE" -ge 1 ] && echo "$@" +} + +rootfs_type() { +	mount | awk '($3 ~ /^\/$/) && ($5 !~ /rootfs/) { print $5 }' +} + +get_image() { +	local from="$1" + +	case "$from" in +		http://*|ftp://*) wget -O- -q "$from";; +		*) cat "$from" +	esac +} + +get_magic_word() { +	get_image "$1" | dd bs=2 count=1 2>/dev/null | hexdump | awk '$2 { print $2 }' +} + +refresh_mtd_partitions() { +	mtd refresh rootfs +} + +jffs2_copy_config() { +	if grep rootfs_data /proc/mtd >/dev/null; then +		# squashfs+jffs2 +		mtd -e rootfs_data jffs2write "$CONF_TAR" rootfs_data +	else +		# jffs2 +		mtd jffs2write "$CONF_TAR" rootfs +	fi +} + +do_upgrade() { +	v "Performing system upgrade..." +	platform_do_upgrade "$ARGV" +	 +	[ "$SAVE_CONFIG" -eq 1 ] && { +		v "Refreshing partitions" +		if type 'platform_refresh_partitions' >/dev/null 2>/dev/null; then +			platform_refresh_partitions +		else +			refresh_mtd_partitions +		fi +		if type 'platform_copy_config' >/dev/null 2>/dev/null; then +			platform_copy_config +		else +			jffs2_copy_config +		fi +	} +	ask_bool 1 "Reboot" && reboot +} diff --git a/package/base-files/files/sbin/sysupgrade b/package/base-files/files/sbin/sysupgrade new file mode 100755 index 000000000..2805c314d --- /dev/null +++ b/package/base-files/files/sbin/sysupgrade @@ -0,0 +1,92 @@ +#!/bin/sh +. /etc/functions.sh + +# initialize defaults +RAMFS_COPY_BIN=""	# extra programs for temporary ramfs root +RAMFS_COPY_DATA=""	# extra data files +export INTERACTIVE=0 +export VERBOSE=1 +export SAVE_CONFIG=1 + +# parse options +while [ -n "$1" ]; do  +	case "$1" in +		-i) export INTERACTIVE=1;; +		-v) export VERBOSE="$(($VERBOSE + 1))";; +		-q) export VERBOSE="$(($VERBOSE - 1))";; +		-*) +			echo "Invalid option: $1" +			exit 1 +		;; +		*) break;; +	esac +	shift; +done + +export CONFFILES=/tmp/sysupgrade.conffiles +export CONF_TAR=/tmp/sysupgrade.tgz + +export ARGV="$*" +export ARGC="$#" + +[ -z "$ARGV" ] && { +	cat <<EOF +Usage: $0 [options] <image file or URL> + +Options: +	-i	interactive mode +	-v	more verbose +	-q	less verbose + +EOF +	exit 1 +} + +add_uci_conffiles() { +	local file="$1" +	find /etc/config > "$file" +	return 0 +} + +# hooks +sysupgrade_image_check="platform_check_image" +sysupgrade_init_conffiles="add_uci_conffiles" + +include /lib/upgrade + +do_save_conffiles() { +	[ -z "$(rootfs_type)" ] && { +		echo "Cannot save config while running from ramdisk." +		ask_bool 0 "Abort" && exit +		return 0 +	} +	run_hooks "$CONFFILES" $sysupgrade_init_conffiles +	ask_bool 0 "Edit config file list" && vi "$CONFFILES" + +	v "Saving config files..." +	[ "$VERBOSE" -gt 1 ] && TAR_V="v" || TAR_V="" +	tar c${TAR_V}zf "$CONF_TAR" -T "$CONFFILES" 2>/dev/null +} + +type platform_check_image >/dev/null 2>/dev/null || { +	echo "Firmware upgrade is not implemented for this platform." +	exit 1 +} + +for check in $sysupgrade_image_check; do +	( eval "$check \"\$ARGV\"" ) || { +		echo "Image check '$check' failed." +		exit 1 +	} +done + +if ask_bool $SAVE_CONFIG "Keep config files over reflash"; then +	do_save_conffiles +	export SAVE_CONFIG=1 +else +	export SAVE_CONFIG=0 +fi +run_hooks "" $sysupgrade_pre_upgrade + +v "Switching to ramdisk..." +run_ramfs '. /etc/functions.sh; include /lib/upgrade; do_upgrade' diff --git a/package/mtd/src/jffs2.c b/package/mtd/src/jffs2.c index 7b68ae575..f614a336e 100644 --- a/package/mtd/src/jffs2.c +++ b/package/mtd/src/jffs2.c @@ -147,7 +147,7 @@ static void add_file(char *name, int parent)  	else  		fname = name; -	inode = add_dirent(name, IFTODT(S_IFREG), parent); +	inode = add_dirent(fname, IFTODT(S_IFREG), parent);  	memset(&ri, 0, sizeof(ri));  	ri.magic = JFFS2_MAGIC_BITMASK;  	ri.nodetype = JFFS2_NODETYPE_INODE; @@ -223,6 +223,9 @@ int mtd_write_jffs2(char *mtd, char *filename, char *dir)  		goto done;  	} +	if (!*dir) +		target_ino = 1; +  	/* parse the structure of the jffs2 first  	 * locate the directory that the file is going to be placed in */  	for(;;) { @@ -253,7 +256,7 @@ int mtd_write_jffs2(char *mtd, char *filename, char *dir)  					struct jffs2_raw_dirent *de = (struct jffs2_raw_dirent *) node;  					/* is this the right directory name and is it a subdirectory of / */ -					if ((de->pino == 1) && !strncmp(de->name, dir, de->nsize)) +					if (*dir && (de->pino == 1) && !strncmp(de->name, dir, de->nsize))  						target_ino = de->ino;  					/* store the last inode and version numbers for adding extra files */ diff --git a/package/mtd/src/mtd.c b/package/mtd/src/mtd.c index 92018c23c..f3a13efd2 100644 --- a/package/mtd/src/mtd.c +++ b/package/mtd/src/mtd.c @@ -52,7 +52,7 @@  #define DEBUG -#define JFFS2_DEFAULT_DIR	"tmp" +#define JFFS2_DEFAULT_DIR	"" /* directory name without /, empty means root dir */  #define SYSTYPE_UNKNOWN     0  #define SYSTYPE_BROADCOM    1 | 
