diff -pruN genkernel.a/defaults/busy-config genkernel.b/defaults/busy-config --- genkernel.a/defaults/busy-config 2011-01-12 21:05:44.000000000 +0200 +++ genkernel.b/defaults/busy-config 2011-01-12 21:49:05.000000000 +0200 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Busybox version: 1.7.4 -# Tue Mar 11 13:29:47 2008 +# Busybox version: 1.18.1 +# Wed Jan 12 21:45:31 2011 # CONFIG_HAVE_DOT_CONFIG=y @@ -12,19 +12,35 @@ CONFIG_HAVE_DOT_CONFIG=y # # General Configuration # -# CONFIG_NITPICK is not set # CONFIG_DESKTOP is not set -# CONFIG_FEATURE_BUFFERS_USE_MALLOC is not set +# CONFIG_EXTRA_COMPAT is not set +# CONFIG_INCLUDE_SUSv2 is not set +# CONFIG_USE_PORTABLE_CODE is not set +CONFIG_PLATFORM_LINUX=y +CONFIG_FEATURE_BUFFERS_USE_MALLOC=y # CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set # CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set CONFIG_SHOW_USAGE=y # CONFIG_FEATURE_VERBOSE_USAGE is not set CONFIG_FEATURE_COMPRESS_USAGE=y CONFIG_FEATURE_INSTALLER=y +# CONFIG_INSTALL_NO_USR is not set # CONFIG_LOCALE_SUPPORT is not set -CONFIG_GETOPT_LONG=y +CONFIG_UNICODE_SUPPORT=y +# CONFIG_UNICODE_USING_LOCALE is not set +# CONFIG_FEATURE_CHECK_UNICODE_IN_ENV is not set +CONFIG_SUBST_WCHAR=63 +CONFIG_LAST_SUPPORTED_WCHAR=767 +# CONFIG_UNICODE_COMBINING_WCHARS is not set +# CONFIG_UNICODE_WIDE_WCHARS is not set +# CONFIG_UNICODE_BIDI_SUPPORT is not set +# CONFIG_UNICODE_NEUTRAL_TABLE is not set +# CONFIG_UNICODE_PRESERVE_BROKEN is not set +CONFIG_LONG_OPTS=y CONFIG_FEATURE_DEVPTS=y # CONFIG_FEATURE_CLEAN_UP is not set +# CONFIG_FEATURE_WTMP is not set +# CONFIG_FEATURE_UTMP is not set # CONFIG_FEATURE_PIDFILE is not set # CONFIG_FEATURE_SUID is not set # CONFIG_FEATURE_SUID_CONFIG is not set @@ -39,29 +55,35 @@ CONFIG_FEATURE_HAVE_RPC=y # Build Options # CONFIG_STATIC=y +# CONFIG_PIE is not set +# CONFIG_NOMMU is not set # CONFIG_BUILD_LIBBUSYBOX is not set -# CONFIG_FEATURE_FULL_LIBBUSYBOX is not set +# CONFIG_FEATURE_INDIVIDUAL is not set # CONFIG_FEATURE_SHARED_BUSYBOX is not set CONFIG_LFS=y -# CONFIG_BUILD_AT_ONCE is not set +CONFIG_CROSS_COMPILER_PREFIX="" +CONFIG_EXTRA_CFLAGS="" # # Debugging Options # # CONFIG_DEBUG is not set +# CONFIG_DEBUG_PESSIMIZE is not set # CONFIG_WERROR is not set CONFIG_NO_DEBUG_LIB=y # CONFIG_DMALLOC is not set # CONFIG_EFENCE is not set -# CONFIG_INCLUDE_SUSv2 is not set # -# Installation Options +# Installation Options ("make install" behavior) # -# CONFIG_INSTALL_NO_USR is not set CONFIG_INSTALL_APPLET_SYMLINKS=y # CONFIG_INSTALL_APPLET_HARDLINKS is not set +# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set # CONFIG_INSTALL_APPLET_DONT is not set +# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set +# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set +# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set CONFIG_PREFIX="./_install" # @@ -71,17 +93,22 @@ CONFIG_PASSWORD_MINLEN=6 CONFIG_MD5_SIZE_VS_SPEED=2 # CONFIG_FEATURE_FAST_TOP is not set # CONFIG_FEATURE_ETC_NETWORKS is not set +CONFIG_FEATURE_USE_TERMIOS=y CONFIG_FEATURE_EDITING=y CONFIG_FEATURE_EDITING_MAX_LEN=1024 -# CONFIG_FEATURE_EDITING_FANCY_KEYS is not set # CONFIG_FEATURE_EDITING_VI is not set CONFIG_FEATURE_EDITING_HISTORY=15 # CONFIG_FEATURE_EDITING_SAVEHISTORY is not set CONFIG_FEATURE_TAB_COMPLETION=y # CONFIG_FEATURE_USERNAME_COMPLETION is not set # CONFIG_FEATURE_EDITING_FANCY_PROMPT is not set +# CONFIG_FEATURE_EDITING_ASK_TERMINAL is not set +CONFIG_FEATURE_NON_POSIX_CP=y +# CONFIG_FEATURE_VERBOSE_CP_MESSAGE is not set +CONFIG_FEATURE_COPYBUF_KB=4 CONFIG_MONOTONIC_SYSCALL=y CONFIG_IOCTL_HEX2STR_ERROR=y +CONFIG_FEATURE_HWIB=y # # Applets @@ -90,64 +117,82 @@ CONFIG_IOCTL_HEX2STR_ERROR=y # # Archival Utilities # +CONFIG_FEATURE_SEAMLESS_XZ=y +CONFIG_FEATURE_SEAMLESS_LZMA=y +CONFIG_FEATURE_SEAMLESS_BZ2=y +CONFIG_FEATURE_SEAMLESS_GZ=y +CONFIG_FEATURE_SEAMLESS_Z=y # CONFIG_AR is not set # CONFIG_FEATURE_AR_LONG_FILENAMES is not set -# CONFIG_BUNZIP2 is not set +# CONFIG_FEATURE_AR_CREATE is not set +CONFIG_BUNZIP2=y +CONFIG_BZIP2=y # CONFIG_CPIO is not set +# CONFIG_FEATURE_CPIO_O is not set +# CONFIG_FEATURE_CPIO_P is not set # CONFIG_DPKG is not set # CONFIG_DPKG_DEB is not set # CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY is not set CONFIG_GUNZIP=y -# CONFIG_FEATURE_GUNZIP_UNCOMPRESS is not set CONFIG_GZIP=y +# CONFIG_FEATURE_GZIP_LONG_OPTIONS is not set +CONFIG_LZOP=y +# CONFIG_LZOP_COMPR_HIGH is not set # CONFIG_RPM2CPIO is not set # CONFIG_RPM is not set -# CONFIG_FEATURE_RPM_BZ2 is not set CONFIG_TAR=y CONFIG_FEATURE_TAR_CREATE=y -CONFIG_FEATURE_TAR_BZIP2=y -# CONFIG_FEATURE_TAR_LZMA is not set +CONFIG_FEATURE_TAR_AUTODETECT=y # CONFIG_FEATURE_TAR_FROM is not set -CONFIG_FEATURE_TAR_GZIP=y -# CONFIG_FEATURE_TAR_COMPRESS is not set # CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set # CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY is not set CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y # CONFIG_FEATURE_TAR_LONG_OPTIONS is not set +# CONFIG_FEATURE_TAR_TO_COMMAND is not set +CONFIG_FEATURE_TAR_UNAME_GNAME=y +CONFIG_FEATURE_TAR_NOPRESERVE_TIME=y +# CONFIG_FEATURE_TAR_SELINUX is not set # CONFIG_UNCOMPRESS is not set # CONFIG_UNLZMA is not set # CONFIG_FEATURE_LZMA_FAST is not set +# CONFIG_LZMA is not set +# CONFIG_UNXZ is not set +# CONFIG_XZ is not set # CONFIG_UNZIP is not set # -# Common options for cpio and tar -# -# CONFIG_FEATURE_UNARCHIVE_TAPE is not set -# CONFIG_FEATURE_DEB_TAR_GZ is not set -# CONFIG_FEATURE_DEB_TAR_BZ2 is not set -# CONFIG_FEATURE_DEB_TAR_LZMA is not set - -# # Coreutils # CONFIG_BASENAME=y -# CONFIG_CAL is not set CONFIG_CAT=y +CONFIG_DATE=y +CONFIG_FEATURE_DATE_ISOFMT=y +# CONFIG_FEATURE_DATE_NANO is not set +CONFIG_FEATURE_DATE_COMPAT=y +CONFIG_TEST=y +# CONFIG_FEATURE_TEST_64 is not set +# CONFIG_TR is not set +# CONFIG_FEATURE_TR_CLASSES is not set +# CONFIG_FEATURE_TR_EQUIV is not set +CONFIG_BASE64=y +# CONFIG_CAL is not set # CONFIG_CATV is not set CONFIG_CHGRP=y CONFIG_CHMOD=y CONFIG_CHOWN=y +CONFIG_FEATURE_CHOWN_LONG_OPTIONS=y CONFIG_CHROOT=y # CONFIG_CKSUM is not set # CONFIG_COMM is not set CONFIG_CP=y +CONFIG_FEATURE_CP_LONG_OPTIONS=y CONFIG_CUT=y -CONFIG_DATE=y -CONFIG_FEATURE_DATE_ISOFMT=y CONFIG_DD=y CONFIG_FEATURE_DD_SIGNAL_HANDLING=y +CONFIG_FEATURE_DD_THIRD_STATUS_LINE=y # CONFIG_FEATURE_DD_IBS_OBS is not set CONFIG_DF=y +CONFIG_FEATURE_DF_FANCY=y CONFIG_DIRNAME=y # CONFIG_DOS2UNIX is not set # CONFIG_UNIX2DOS is not set @@ -163,6 +208,7 @@ CONFIG_ENV=y # CONFIG_EXPR_MATH_SUPPORT_64 is not set CONFIG_FALSE=y # CONFIG_FOLD is not set +CONFIG_FSYNC=y CONFIG_HEAD=y # CONFIG_FEATURE_FANCY_HEAD is not set # CONFIG_HOSTID is not set @@ -199,10 +245,14 @@ CONFIG_READLINK=y # CONFIG_REALPATH is not set CONFIG_RM=y CONFIG_RMDIR=y +CONFIG_FEATURE_RMDIR_LONG_OPTIONS=y # CONFIG_SEQ is not set # CONFIG_SHA1SUM is not set +CONFIG_SHA256SUM=y +CONFIG_SHA512SUM=y CONFIG_SLEEP=y # CONFIG_FEATURE_FANCY_SLEEP is not set +# CONFIG_FEATURE_FLOAT_SLEEP is not set CONFIG_SORT=y CONFIG_FEATURE_SORT_BIG=y # CONFIG_SPLIT is not set @@ -212,16 +262,12 @@ CONFIG_FEATURE_SORT_BIG=y CONFIG_STTY=y # CONFIG_SUM is not set CONFIG_SYNC=y +CONFIG_TAC=y CONFIG_TAIL=y # CONFIG_FEATURE_FANCY_TAIL is not set # CONFIG_TEE is not set # CONFIG_FEATURE_TEE_USE_BLOCK_IO is not set -CONFIG_TEST=y -# CONFIG_FEATURE_TEST_64 is not set CONFIG_TOUCH=y -# CONFIG_TR is not set -# CONFIG_FEATURE_TR_CLASSES is not set -# CONFIG_FEATURE_TR_EQUIV is not set CONFIG_TRUE=y CONFIG_TTY=y CONFIG_UNAME=y @@ -251,15 +297,21 @@ CONFIG_FEATURE_AUTOWIDTH=y # Common options for df, du, ls # CONFIG_FEATURE_HUMAN_READABLE=y + +# +# Common options for md5sum, sha1sum, sha256sum, sha512sum +# # CONFIG_FEATURE_MD5_SHA1_SUM_CHECK is not set # # Console Utilities # CONFIG_CHVT=y +CONFIG_FGCONSOLE=y CONFIG_CLEAR=y # CONFIG_DEALLOCVT is not set CONFIG_DUMPKMAP=y +CONFIG_KBD_MODE=y CONFIG_LOADFONT=y CONFIG_LOADKMAP=y # CONFIG_OPENVT is not set @@ -268,8 +320,18 @@ CONFIG_RESET=y # CONFIG_FEATURE_RESIZE_PRINT is not set # CONFIG_SETCONSOLE is not set # CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set +CONFIG_SETFONT=y +CONFIG_FEATURE_SETFONT_TEXTUAL_MAP=y +CONFIG_DEFAULT_SETFONT_DIR="" # CONFIG_SETKEYCODES is not set # CONFIG_SETLOGCONS is not set +CONFIG_SHOWKEY=y + +# +# Common options for loadfont and setfont +# +CONFIG_FEATURE_LOADFONT_PSF2=y +CONFIG_FEATURE_LOADFONT_RAW=y # # Debian Utilities @@ -287,18 +349,18 @@ CONFIG_WHICH=y # # Editors # +# CONFIG_PATCH is not set # CONFIG_AWK is not set -# CONFIG_FEATURE_AWK_MATH is not set +# CONFIG_FEATURE_AWK_LIBM is not set # CONFIG_CMP is not set # CONFIG_DIFF is not set -# CONFIG_FEATURE_DIFF_BINARY is not set +# CONFIG_FEATURE_DIFF_LONG_OPTIONS is not set # CONFIG_FEATURE_DIFF_DIR is not set -# CONFIG_FEATURE_DIFF_MINIMAL is not set # CONFIG_ED is not set -# CONFIG_PATCH is not set CONFIG_SED=y # CONFIG_VI is not set -CONFIG_FEATURE_VI_MAX_LEN= +CONFIG_FEATURE_VI_MAX_LEN=0 +# CONFIG_FEATURE_VI_8BIT is not set # CONFIG_FEATURE_VI_COLON is not set # CONFIG_FEATURE_VI_YANKMARK is not set # CONFIG_FEATURE_VI_SEARCH is not set @@ -308,6 +370,7 @@ CONFIG_FEATURE_VI_MAX_LEN= # CONFIG_FEATURE_VI_SETOPTS is not set # CONFIG_FEATURE_VI_SET is not set # CONFIG_FEATURE_VI_WIN_RESIZE is not set +# CONFIG_FEATURE_VI_ASK_TERMINAL is not set # CONFIG_FEATURE_VI_OPTIMIZE_CURSOR is not set # CONFIG_FEATURE_ALLOW_EXEC is not set @@ -336,6 +399,7 @@ CONFIG_FEATURE_FIND_SIZE=y # CONFIG_FEATURE_FIND_PATH is not set # CONFIG_FEATURE_FIND_REGEX is not set # CONFIG_FEATURE_FIND_CONTEXT is not set +CONFIG_FEATURE_FIND_LINKS=y CONFIG_GREP=y # CONFIG_FEATURE_GREP_EGREP_ALIAS is not set CONFIG_FEATURE_GREP_FGREP_ALIAS=y @@ -349,32 +413,46 @@ CONFIG_XARGS=y # # Init Utilities # +CONFIG_BOOTCHARTD=y +CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER=y +CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE=y +CONFIG_HALT=y +# CONFIG_FEATURE_CALL_TELINIT is not set +CONFIG_TELINIT_PATH="" CONFIG_INIT=y -# CONFIG_DEBUG_INIT is not set CONFIG_FEATURE_USE_INITTAB=y +# CONFIG_FEATURE_KILL_REMOVED is not set +CONFIG_FEATURE_KILL_DELAY=0 # CONFIG_FEATURE_INIT_SCTTY is not set # CONFIG_FEATURE_INIT_SYSLOG is not set # CONFIG_FEATURE_EXTRA_QUIET is not set # CONFIG_FEATURE_INIT_COREDUMPS is not set CONFIG_FEATURE_INITRD=y -CONFIG_HALT=y +CONFIG_INIT_TERMINAL_TYPE="linux" CONFIG_MESG=y # # Login/Password Management Utilities # +# CONFIG_ADD_SHELL is not set +# CONFIG_REMOVE_SHELL is not set # CONFIG_FEATURE_SHADOWPASSWDS is not set -# CONFIG_USE_BB_SHADOW is not set # CONFIG_USE_BB_PWD_GRP is not set +# CONFIG_USE_BB_SHADOW is not set +# CONFIG_USE_BB_CRYPT is not set +# CONFIG_USE_BB_CRYPT_SHA is not set +# CONFIG_ADDUSER is not set +# CONFIG_FEATURE_ADDUSER_LONG_OPTIONS is not set +# CONFIG_FEATURE_CHECK_NAMES is not set +CONFIG_FIRST_SYSTEM_ID=0 +CONFIG_LAST_SYSTEM_ID=0 # CONFIG_ADDGROUP is not set +# CONFIG_FEATURE_ADDGROUP_LONG_OPTIONS is not set # CONFIG_FEATURE_ADDUSER_TO_GROUP is not set +# CONFIG_DELUSER is not set # CONFIG_DELGROUP is not set # CONFIG_FEATURE_DEL_USER_FROM_GROUP is not set -# CONFIG_ADDUSER is not set -# CONFIG_DELUSER is not set # CONFIG_GETTY is not set -# CONFIG_FEATURE_UTMP is not set -# CONFIG_FEATURE_WTMP is not set # CONFIG_LOGIN is not set # CONFIG_PAM is not set # CONFIG_LOGIN_SCRIPTS is not set @@ -396,34 +474,52 @@ CONFIG_CHPASSWD=y # CONFIG_CHATTR is not set # CONFIG_FSCK is not set # CONFIG_LSATTR is not set +# CONFIG_TUNE2FS is not set + +# +# Linux mdadm Utilities +# +CONFIG_MDADM=y # # Linux Module Utilities # +# CONFIG_MODINFO is not set +# CONFIG_MODPROBE_SMALL is not set +# CONFIG_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE is not set +# CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED is not set CONFIG_INSMOD=y -# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set -# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set -# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set -# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set -# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set CONFIG_RMMOD=y CONFIG_LSMOD=y # CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set CONFIG_MODPROBE=y -CONFIG_FEATURE_MODPROBE_MULTIPLE_OPTIONS=y -CONFIG_FEATURE_MODPROBE_FANCY_ALIAS=y +CONFIG_FEATURE_MODPROBE_BLACKLIST=y +# CONFIG_DEPMOD is not set # # Options common to multiple modutils # +# CONFIG_FEATURE_2_4_MODULES is not set +CONFIG_FEATURE_INSMOD_TRY_MMAP=y +# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set +# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set +# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set +# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set +# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set CONFIG_FEATURE_CHECK_TAINTED_MODULE=y -CONFIG_FEATURE_2_4_MODULES=y -CONFIG_FEATURE_2_6_MODULES=y -# CONFIG_FEATURE_QUERY_MODULE_INTERFACE is not set +CONFIG_FEATURE_MODUTILS_ALIAS=y +CONFIG_FEATURE_MODUTILS_SYMBOLS=y +CONFIG_DEFAULT_MODULES_DIR="/lib/modules" +CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" # # Linux System Utilities # +CONFIG_BLOCKDEV=y +CONFIG_REV=y +CONFIG_ACPID=y +CONFIG_FEATURE_ACPID_COMPAT=y +CONFIG_BLKID=y CONFIG_DMESG=y CONFIG_FEATURE_DMESG_PRETTY=y # CONFIG_FBSET is not set @@ -438,39 +534,59 @@ CONFIG_FDISK_SUPPORT_LARGE_DISKS=y # CONFIG_FEATURE_SGI_LABEL is not set # CONFIG_FEATURE_SUN_LABEL is not set # CONFIG_FEATURE_OSF_LABEL is not set +# CONFIG_FEATURE_GPT_LABEL is not set # CONFIG_FEATURE_FDISK_ADVANCED is not set +CONFIG_FINDFS=y +CONFIG_FLOCK=y CONFIG_FREERAMDISK=y # CONFIG_FSCK_MINIX is not set +CONFIG_MKFS_EXT2=y # CONFIG_MKFS_MINIX is not set # CONFIG_FEATURE_MINIX2 is not set +CONFIG_MKFS_REISER=y +# CONFIG_MKFS_VFAT is not set # CONFIG_GETOPT is not set +# CONFIG_FEATURE_GETOPT_LONG is not set CONFIG_HEXDUMP=y +CONFIG_FEATURE_HEXDUMP_REVERSE=y +CONFIG_HD=y # CONFIG_HWCLOCK is not set # CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS is not set # CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS is not set # CONFIG_IPCRM is not set # CONFIG_IPCS is not set CONFIG_LOSETUP=y -CONFIG_MDADM=y +CONFIG_LSPCI=y +CONFIG_LSUSB=y CONFIG_MDEV=y # CONFIG_FEATURE_MDEV_CONF is not set +# CONFIG_FEATURE_MDEV_RENAME is not set +# CONFIG_FEATURE_MDEV_RENAME_REGEXP is not set # CONFIG_FEATURE_MDEV_EXEC is not set CONFIG_FEATURE_MDEV_LOAD_FIRMWARE=y CONFIG_MDSTART=y # CONFIG_MKSWAP is not set -# CONFIG_FEATURE_MKSWAP_V0 is not set +# CONFIG_FEATURE_MKSWAP_UUID is not set CONFIG_MORE=y -CONFIG_FEATURE_USE_TERMIOS=y CONFIG_MOUNT=y +CONFIG_FEATURE_MOUNT_FAKE=y +CONFIG_FEATURE_MOUNT_VERBOSE=y +# CONFIG_FEATURE_MOUNT_HELPERS is not set +CONFIG_FEATURE_MOUNT_LABEL=y CONFIG_FEATURE_MOUNT_NFS=y -# CONFIG_FEATURE_MOUNT_CIFS is not set +CONFIG_FEATURE_MOUNT_CIFS=y CONFIG_FEATURE_MOUNT_FLAGS=y CONFIG_FEATURE_MOUNT_FSTAB=y CONFIG_PIVOT_ROOT=y CONFIG_RDATE=y +CONFIG_RDEV=y # CONFIG_READPROFILE is not set +CONFIG_RTCWAKE=y +CONFIG_SCRIPT=y +CONFIG_SCRIPTREPLAY=y # CONFIG_SETARCH is not set CONFIG_SWAPONOFF=y +CONFIG_FEATURE_SWAPON_PRI=y CONFIG_SWITCH_ROOT=y CONFIG_UMOUNT=y # CONFIG_FEATURE_UMOUNT_ALL is not set @@ -479,33 +595,88 @@ CONFIG_UMOUNT=y # Common options for mount/umount # CONFIG_FEATURE_MOUNT_LOOP=y +CONFIG_FEATURE_MOUNT_LOOP_CREATE=y CONFIG_FEATURE_MTAB_SUPPORT=y +CONFIG_VOLUMEID=y + +# +# Filesystem/Volume identification +# +CONFIG_FEATURE_VOLUMEID_EXT=y +CONFIG_FEATURE_VOLUMEID_BTRFS=y +CONFIG_FEATURE_VOLUMEID_REISERFS=y +CONFIG_FEATURE_VOLUMEID_FAT=y +CONFIG_FEATURE_VOLUMEID_HFS=y +CONFIG_FEATURE_VOLUMEID_JFS=y +CONFIG_FEATURE_VOLUMEID_XFS=y +CONFIG_FEATURE_VOLUMEID_NTFS=y +CONFIG_FEATURE_VOLUMEID_ISO9660=y +CONFIG_FEATURE_VOLUMEID_UDF=y +CONFIG_FEATURE_VOLUMEID_LUKS=y +CONFIG_FEATURE_VOLUMEID_LINUXSWAP=y +CONFIG_FEATURE_VOLUMEID_CRAMFS=y +CONFIG_FEATURE_VOLUMEID_ROMFS=y +CONFIG_FEATURE_VOLUMEID_SYSV=y +CONFIG_FEATURE_VOLUMEID_OCFS2=y +CONFIG_FEATURE_VOLUMEID_LINUXRAID=y # # Miscellaneous Utilities # +# CONFIG_CONSPY is not set +# CONFIG_NANDWRITE is not set +# CONFIG_NANDDUMP is not set +# CONFIG_UBIATTACH is not set +# CONFIG_UBIDETACH is not set # CONFIG_ADJTIMEX is not set # CONFIG_BBCONFIG is not set +# CONFIG_FEATURE_COMPRESS_BBCONFIG is not set +# CONFIG_BEEP is not set +CONFIG_FEATURE_BEEP_FREQ=0 +CONFIG_FEATURE_BEEP_LENGTH_MS=0 +# CONFIG_CHAT is not set +# CONFIG_FEATURE_CHAT_NOFAIL is not set +# CONFIG_FEATURE_CHAT_TTY_HIFI is not set +# CONFIG_FEATURE_CHAT_IMPLICIT_CR is not set +# CONFIG_FEATURE_CHAT_SWALLOW_OPTS is not set +# CONFIG_FEATURE_CHAT_SEND_ESCAPES is not set +# CONFIG_FEATURE_CHAT_VAR_ABORT_LEN is not set +# CONFIG_FEATURE_CHAT_CLR_ABORT is not set # CONFIG_CHRT is not set # CONFIG_CROND is not set -# CONFIG_DEBUG_CROND_OPTION is not set +# CONFIG_FEATURE_CROND_D is not set # CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set +CONFIG_FEATURE_CROND_DIR="" # CONFIG_CRONTAB is not set # CONFIG_DC is not set +# CONFIG_FEATURE_DC_LIBM is not set # CONFIG_DEVFSD is not set # CONFIG_DEVFSD_MODLOAD is not set # CONFIG_DEVFSD_FG_NP is not set # CONFIG_DEVFSD_VERBOSE is not set # CONFIG_FEATURE_DEVFS is not set +# CONFIG_DEVMEM is not set # CONFIG_EJECT is not set +# CONFIG_FEATURE_EJECT_SCSI is not set +CONFIG_FBSPLASH=y +# CONFIG_FLASHCP is not set +# CONFIG_FLASH_LOCK is not set +# CONFIG_FLASH_UNLOCK is not set +# CONFIG_FLASH_ERASEALL is not set +# CONFIG_IONICE is not set +# CONFIG_INOTIFYD is not set # CONFIG_LAST is not set +# CONFIG_FEATURE_LAST_SMALL is not set +# CONFIG_FEATURE_LAST_FANCY is not set # CONFIG_LESS is not set -CONFIG_FEATURE_LESS_MAXLINES= +CONFIG_FEATURE_LESS_MAXLINES=0 # CONFIG_FEATURE_LESS_BRACKETS is not set # CONFIG_FEATURE_LESS_FLAGS is not set -# CONFIG_FEATURE_LESS_FLAGCS is not set # CONFIG_FEATURE_LESS_MARKS is not set # CONFIG_FEATURE_LESS_REGEXP is not set +# CONFIG_FEATURE_LESS_WINCH is not set +# CONFIG_FEATURE_LESS_DASHCMD is not set +# CONFIG_FEATURE_LESS_LINENUMS is not set # CONFIG_HDPARM is not set # CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set # CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set @@ -516,54 +687,76 @@ CONFIG_FEATURE_LESS_MAXLINES= CONFIG_MAKEDEVS=y CONFIG_FEATURE_MAKEDEVS_LEAF=y # CONFIG_FEATURE_MAKEDEVS_TABLE is not set +# CONFIG_MAN is not set +CONFIG_MICROCOM=y # CONFIG_MOUNTPOINT is not set # CONFIG_MT is not set -# CONFIG_RAIDAUTORUN is not set -# CONFIG_READAHEAD is not set +CONFIG_RAIDAUTORUN=y +CONFIG_READAHEAD=y +# CONFIG_RFKILL is not set # CONFIG_RUNLEVEL is not set # CONFIG_RX is not set -# CONFIG_STRINGS is not set # CONFIG_SETSID is not set +# CONFIG_STRINGS is not set # CONFIG_TASKSET is not set # CONFIG_FEATURE_TASKSET_FANCY is not set # CONFIG_TIME is not set +# CONFIG_TIMEOUT is not set # CONFIG_TTYSIZE is not set +# CONFIG_VOLNAME is not set +# CONFIG_WALL is not set # CONFIG_WATCHDOG is not set # # Networking Utilities # -# CONFIG_FEATURE_IPV6 is not set +CONFIG_NBDCLIENT=y +# CONFIG_NC is not set +# CONFIG_NC_SERVER is not set +# CONFIG_NC_EXTRA is not set +# CONFIG_NC_110_COMPAT is not set +CONFIG_FEATURE_IPV6=y +# CONFIG_FEATURE_UNIX_LOCAL is not set +# CONFIG_FEATURE_PREFER_IPV4_ADDRESS is not set # CONFIG_VERBOSE_RESOLUTION_ERRORS is not set # CONFIG_ARP is not set # CONFIG_ARPING is not set +# CONFIG_BRCTL is not set +# CONFIG_FEATURE_BRCTL_FANCY is not set +# CONFIG_FEATURE_BRCTL_SHOW is not set # CONFIG_DNSD is not set # CONFIG_ETHER_WAKE is not set # CONFIG_FAKEIDENTD is not set +# CONFIG_FTPD is not set +# CONFIG_FEATURE_FTP_WRITE is not set +# CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST is not set # CONFIG_FTPGET is not set # CONFIG_FTPPUT is not set # CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set CONFIG_HOSTNAME=y # CONFIG_HTTPD is not set +# CONFIG_FEATURE_HTTPD_RANGES is not set # CONFIG_FEATURE_HTTPD_USE_SENDFILE is not set -# CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP is not set # CONFIG_FEATURE_HTTPD_SETUID is not set # CONFIG_FEATURE_HTTPD_BASIC_AUTH is not set # CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set -# CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES is not set # CONFIG_FEATURE_HTTPD_CGI is not set # CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set # CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set # CONFIG_FEATURE_HTTPD_ENCODE_URL_STR is not set # CONFIG_FEATURE_HTTPD_ERROR_PAGES is not set +# CONFIG_FEATURE_HTTPD_PROXY is not set +# CONFIG_FEATURE_HTTPD_GZIP is not set CONFIG_IFCONFIG=y CONFIG_FEATURE_IFCONFIG_STATUS=y # CONFIG_FEATURE_IFCONFIG_SLIP is not set -# CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set +CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ=y CONFIG_FEATURE_IFCONFIG_HW=y # CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS is not set +# CONFIG_IFENSLAVE is not set +# CONFIG_IFPLUGD is not set # CONFIG_IFUPDOWN is not set -CONFIG_IFUPDOWN_IFSTATE_PATH="/var/run/ifstate" +CONFIG_IFUPDOWN_IFSTATE_PATH="" # CONFIG_FEATURE_IFUPDOWN_IP is not set # CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN is not set # CONFIG_FEATURE_IFUPDOWN_IFCONFIG_BUILTIN is not set @@ -585,6 +778,7 @@ CONFIG_IFUPDOWN_IFSTATE_PATH="/var/run/i # CONFIG_FEATURE_IP_TUNNEL is not set # CONFIG_FEATURE_IP_RULE is not set # CONFIG_FEATURE_IP_SHORT_FORMS is not set +# CONFIG_FEATURE_IP_RARE_PROTOCOLS is not set # CONFIG_IPADDR is not set # CONFIG_IPLINK is not set # CONFIG_IPROUTE is not set @@ -594,112 +788,192 @@ CONFIG_IFUPDOWN_IFSTATE_PATH="/var/run/i # CONFIG_FEATURE_IPCALC_FANCY is not set # CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set # CONFIG_NAMEIF is not set -# CONFIG_NC is not set -# CONFIG_NC_SERVER is not set -# CONFIG_NC_EXTRA is not set +# CONFIG_FEATURE_NAMEIF_EXTENDED is not set # CONFIG_NETSTAT is not set # CONFIG_FEATURE_NETSTAT_WIDE is not set +# CONFIG_FEATURE_NETSTAT_PRG is not set # CONFIG_NSLOOKUP is not set +# CONFIG_NTPD is not set +# CONFIG_FEATURE_NTPD_SERVER is not set CONFIG_PING=y # CONFIG_PING6 is not set -# CONFIG_PSCAN is not set CONFIG_FEATURE_FANCY_PING=y +# CONFIG_PSCAN is not set CONFIG_ROUTE=y # CONFIG_SLATTACH is not set +# CONFIG_TCPSVD is not set # CONFIG_TELNET is not set # CONFIG_FEATURE_TELNET_TTYPE is not set # CONFIG_FEATURE_TELNET_AUTOLOGIN is not set # CONFIG_TELNETD is not set # CONFIG_FEATURE_TELNETD_STANDALONE is not set +# CONFIG_FEATURE_TELNETD_INETD_WAIT is not set # CONFIG_TFTP is not set +# CONFIG_TFTPD is not set # CONFIG_FEATURE_TFTP_GET is not set # CONFIG_FEATURE_TFTP_PUT is not set # CONFIG_FEATURE_TFTP_BLOCKSIZE is not set -# CONFIG_DEBUG_TFTP is not set +# CONFIG_FEATURE_TFTP_PROGRESS_BAR is not set +# CONFIG_TFTP_DEBUG is not set # CONFIG_TRACEROUTE is not set +# CONFIG_TRACEROUTE6 is not set # CONFIG_FEATURE_TRACEROUTE_VERBOSE is not set # CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE is not set # CONFIG_FEATURE_TRACEROUTE_USE_ICMP is not set -# CONFIG_APP_UDHCPD is not set -# CONFIG_APP_DHCPRELAY is not set -# CONFIG_APP_DUMPLEASES is not set +# CONFIG_TUNCTL is not set +# CONFIG_FEATURE_TUNCTL_UG is not set +# CONFIG_UDHCPD is not set +# CONFIG_DHCPRELAY is not set +# CONFIG_DUMPLEASES is not set # CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY is not set -CONFIG_APP_UDHCPC=y -# CONFIG_FEATURE_UDHCP_DEBUG is not set -# CONFIG_FEATURE_RFC3397 is not set -# CONFIG_VCONFIG is not set +CONFIG_DHCPD_LEASES_FILE="" +CONFIG_UDHCPC=y +CONFIG_FEATURE_UDHCPC_ARPING=y +CONFIG_FEATURE_UDHCP_PORT=y +CONFIG_UDHCP_DEBUG=9 +# CONFIG_FEATURE_UDHCP_RFC3397 is not set +CONFIG_UDHCPC_DEFAULT_SCRIPT="/usr/share/udhcpc/default.script" +CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=80 +CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS="" +# CONFIG_UDPSVD is not set +CONFIG_VCONFIG=y CONFIG_WGET=y # CONFIG_FEATURE_WGET_STATUSBAR is not set # CONFIG_FEATURE_WGET_AUTHENTICATION is not set # CONFIG_FEATURE_WGET_LONG_OPTIONS is not set +CONFIG_FEATURE_WGET_TIMEOUT=y # CONFIG_ZCIP is not set # +# Print Utilities +# +# CONFIG_LPD is not set +# CONFIG_LPR is not set +# CONFIG_LPQ is not set + +# +# Mail Utilities +# +# CONFIG_MAKEMIME is not set +CONFIG_FEATURE_MIME_CHARSET="" +# CONFIG_POPMAILDIR is not set +# CONFIG_FEATURE_POPMAILDIR_DELIVERY is not set +# CONFIG_REFORMIME is not set +# CONFIG_FEATURE_REFORMIME_COMPAT is not set +# CONFIG_SENDMAIL is not set + +# # Process Utilities # +CONFIG_IOSTAT=y +CONFIG_MPSTAT=y +CONFIG_PMAP=y +CONFIG_POWERTOP=y +# CONFIG_SMEMCAP is not set CONFIG_FREE=y # CONFIG_FUSER is not set CONFIG_KILL=y CONFIG_KILLALL=y # CONFIG_KILLALL5 is not set # CONFIG_NMETER is not set +# CONFIG_PGREP is not set # CONFIG_PIDOF is not set # CONFIG_FEATURE_PIDOF_SINGLE is not set # CONFIG_FEATURE_PIDOF_OMIT is not set +# CONFIG_PKILL is not set CONFIG_PS=y # CONFIG_FEATURE_PS_WIDE is not set +# CONFIG_FEATURE_PS_TIME is not set +# CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS is not set +# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set # CONFIG_RENICE is not set # CONFIG_BB_SYSCTL is not set # CONFIG_TOP is not set # CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE is not set # CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS is not set +# CONFIG_FEATURE_TOP_SMP_CPU is not set # CONFIG_FEATURE_TOP_DECIMALS is not set -CONFIG_UPTIME=y +# CONFIG_FEATURE_TOP_SMP_PROCESS is not set +# CONFIG_FEATURE_TOPMEM is not set +CONFIG_FEATURE_SHOW_THREADS=y +# CONFIG_UPTIME is not set # CONFIG_WATCH is not set # -# Shells +# Runit Utilities # -CONFIG_FEATURE_SH_IS_ASH=y -# CONFIG_FEATURE_SH_IS_HUSH is not set -# CONFIG_FEATURE_SH_IS_LASH is not set -# CONFIG_FEATURE_SH_IS_MSH is not set -# CONFIG_FEATURE_SH_IS_NONE is not set -CONFIG_ASH=y +# CONFIG_RUNSV is not set +# CONFIG_RUNSVDIR is not set +# CONFIG_FEATURE_RUNSVDIR_LOG is not set +# CONFIG_SV is not set +CONFIG_SV_DEFAULT_SERVICE_DIR="" +# CONFIG_SVLOGD is not set +# CONFIG_CHPST is not set +# CONFIG_SETUIDGID is not set +# CONFIG_ENVUIDGID is not set +# CONFIG_ENVDIR is not set +# CONFIG_SOFTLIMIT is not set +# CONFIG_CHCON is not set +# CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set +# CONFIG_GETENFORCE is not set +# CONFIG_GETSEBOOL is not set +# CONFIG_LOAD_POLICY is not set +# CONFIG_MATCHPATHCON is not set +# CONFIG_RESTORECON is not set +# CONFIG_RUNCON is not set +# CONFIG_FEATURE_RUNCON_LONG_OPTIONS is not set +# CONFIG_SELINUXENABLED is not set +# CONFIG_SETENFORCE is not set +# CONFIG_SETFILES is not set +# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set +# CONFIG_SETSEBOOL is not set +# CONFIG_SESTATUS is not set # -# Ash Shell Options +# Shells # +CONFIG_ASH=y +CONFIG_ASH_BASH_COMPAT=y CONFIG_ASH_JOB_CONTROL=y -# CONFIG_ASH_READ_NCHARS is not set -CONFIG_ASH_READ_TIMEOUT=y CONFIG_ASH_ALIAS=y -CONFIG_ASH_MATH_SUPPORT=y -# CONFIG_ASH_MATH_SUPPORT_64 is not set # CONFIG_ASH_GETOPTS is not set # CONFIG_ASH_BUILTIN_ECHO is not set +# CONFIG_ASH_BUILTIN_PRINTF is not set CONFIG_ASH_BUILTIN_TEST=y # CONFIG_ASH_CMDCMD is not set -CONFIG_ASH_MAIL=y +# CONFIG_ASH_MAIL is not set CONFIG_ASH_OPTIMIZE_FOR_SIZE=y # CONFIG_ASH_RANDOM_SUPPORT is not set # CONFIG_ASH_EXPAND_PRMT is not set +# CONFIG_CTTYHACK is not set # CONFIG_HUSH is not set +# CONFIG_HUSH_BASH_COMPAT is not set +# CONFIG_HUSH_BRACE_EXPANSION is not set # CONFIG_HUSH_HELP is not set # CONFIG_HUSH_INTERACTIVE is not set +# CONFIG_HUSH_SAVEHISTORY is not set # CONFIG_HUSH_JOB is not set # CONFIG_HUSH_TICK is not set # CONFIG_HUSH_IF is not set # CONFIG_HUSH_LOOPS is not set -# CONFIG_LASH is not set +# CONFIG_HUSH_CASE is not set +# CONFIG_HUSH_FUNCTIONS is not set +# CONFIG_HUSH_LOCAL is not set +# CONFIG_HUSH_RANDOM_SUPPORT is not set +# CONFIG_HUSH_EXPORT_N is not set +# CONFIG_HUSH_MODE_X is not set # CONFIG_MSH is not set - -# -# Bourne Shell Options -# +CONFIG_FEATURE_SH_IS_ASH=y +# CONFIG_FEATURE_SH_IS_HUSH is not set +# CONFIG_FEATURE_SH_IS_NONE is not set +# CONFIG_FEATURE_BASH_IS_ASH is not set +# CONFIG_FEATURE_BASH_IS_HUSH is not set +CONFIG_FEATURE_BASH_IS_NONE=y +CONFIG_SH_MATH_SUPPORT=y +CONFIG_SH_MATH_SUPPORT_64=y # CONFIG_FEATURE_SH_EXTRA_QUIET is not set # CONFIG_FEATURE_SH_STANDALONE is not set -# CONFIG_CTTYHACK is not set +CONFIG_FEATURE_SH_NOFORK=y # # System Logging Utilities @@ -707,41 +981,12 @@ CONFIG_ASH_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSLOGD is not set # CONFIG_FEATURE_ROTATE_LOGFILE is not set # CONFIG_FEATURE_REMOTE_LOG is not set +# CONFIG_FEATURE_SYSLOGD_DUP is not set +CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=0 # CONFIG_FEATURE_IPC_SYSLOG is not set -CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE= +CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=0 # CONFIG_LOGREAD is not set # CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set # CONFIG_KLOGD is not set +# CONFIG_FEATURE_KLOGD_KLOGCTL is not set # CONFIG_LOGGER is not set - -# -# Runit Utilities -# -# CONFIG_RUNSV is not set -# CONFIG_RUNSVDIR is not set -# CONFIG_SV is not set -# CONFIG_SVLOGD is not set -# CONFIG_CHPST is not set -# CONFIG_SETUIDGID is not set -# CONFIG_ENVUIDGID is not set -# CONFIG_ENVDIR is not set -# CONFIG_SOFTLIMIT is not set -# CONFIG_CHCON is not set -# CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set -# CONFIG_GETENFORCE is not set -# CONFIG_GETSEBOOL is not set -# CONFIG_LOAD_POLICY is not set -# CONFIG_MATCHPATHCON is not set -# CONFIG_RESTORECON is not set -# CONFIG_RUNCON is not set -# CONFIG_FEATURE_RUNCON_LONG_OPTIONS is not set -# CONFIG_SELINUXENABLED is not set -# CONFIG_SETENFORCE is not set -# CONFIG_SETFILES is not set -# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set - -# -# ipsvd utilities -# -# CONFIG_TCPSVD is not set -# CONFIG_UDPSVD is not set diff -pruN genkernel.a/netboot/busy-config genkernel.b/netboot/busy-config --- genkernel.a/netboot/busy-config 2011-01-12 21:05:44.000000000 +0200 +++ genkernel.b/netboot/busy-config 2011-01-12 21:50:48.000000000 +0200 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Busybox version: 1.7.4 -# Thu Apr 16 15:04:31 2009 +# Busybox version: 1.18.1 +# Wed Jan 12 21:49:31 2011 # CONFIG_HAVE_DOT_CONFIG=y @@ -12,8 +12,11 @@ CONFIG_HAVE_DOT_CONFIG=y # # General Configuration # -CONFIG_NITPICK=y # CONFIG_DESKTOP is not set +# CONFIG_EXTRA_COMPAT is not set +# CONFIG_INCLUDE_SUSv2 is not set +# CONFIG_USE_PORTABLE_CODE is not set +CONFIG_PLATFORM_LINUX=y # CONFIG_FEATURE_BUFFERS_USE_MALLOC is not set CONFIG_FEATURE_BUFFERS_GO_ON_STACK=y # CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set @@ -21,10 +24,23 @@ CONFIG_SHOW_USAGE=y CONFIG_FEATURE_VERBOSE_USAGE=y CONFIG_FEATURE_COMPRESS_USAGE=y CONFIG_FEATURE_INSTALLER=y +# CONFIG_INSTALL_NO_USR is not set # CONFIG_LOCALE_SUPPORT is not set -CONFIG_GETOPT_LONG=y +CONFIG_UNICODE_SUPPORT=y +# CONFIG_UNICODE_USING_LOCALE is not set +# CONFIG_FEATURE_CHECK_UNICODE_IN_ENV is not set +CONFIG_SUBST_WCHAR=63 +CONFIG_LAST_SUPPORTED_WCHAR=767 +# CONFIG_UNICODE_COMBINING_WCHARS is not set +# CONFIG_UNICODE_WIDE_WCHARS is not set +# CONFIG_UNICODE_BIDI_SUPPORT is not set +# CONFIG_UNICODE_NEUTRAL_TABLE is not set +# CONFIG_UNICODE_PRESERVE_BROKEN is not set +CONFIG_LONG_OPTS=y CONFIG_FEATURE_DEVPTS=y # CONFIG_FEATURE_CLEAN_UP is not set +# CONFIG_FEATURE_WTMP is not set +# CONFIG_FEATURE_UTMP is not set # CONFIG_FEATURE_PIDFILE is not set CONFIG_FEATURE_SUID=y # CONFIG_FEATURE_SUID_CONFIG is not set @@ -39,29 +55,35 @@ CONFIG_FEATURE_HAVE_RPC=y # Build Options # CONFIG_STATIC=y +# CONFIG_PIE is not set +# CONFIG_NOMMU is not set # CONFIG_BUILD_LIBBUSYBOX is not set -# CONFIG_FEATURE_FULL_LIBBUSYBOX is not set +# CONFIG_FEATURE_INDIVIDUAL is not set # CONFIG_FEATURE_SHARED_BUSYBOX is not set CONFIG_LFS=y -# CONFIG_BUILD_AT_ONCE is not set +CONFIG_CROSS_COMPILER_PREFIX="" +CONFIG_EXTRA_CFLAGS="" # # Debugging Options # # CONFIG_DEBUG is not set +# CONFIG_DEBUG_PESSIMIZE is not set # CONFIG_WERROR is not set CONFIG_NO_DEBUG_LIB=y # CONFIG_DMALLOC is not set # CONFIG_EFENCE is not set -# CONFIG_INCLUDE_SUSv2 is not set # -# Installation Options +# Installation Options ("make install" behavior) # -# CONFIG_INSTALL_NO_USR is not set CONFIG_INSTALL_APPLET_SYMLINKS=y # CONFIG_INSTALL_APPLET_HARDLINKS is not set +# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set # CONFIG_INSTALL_APPLET_DONT is not set +# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set +# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set +# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set CONFIG_PREFIX="./_install" # @@ -69,19 +91,24 @@ CONFIG_PREFIX="./_install" # CONFIG_PASSWORD_MINLEN=6 CONFIG_MD5_SIZE_VS_SPEED=2 -# CONFIG_FEATURE_FAST_TOP is not set +CONFIG_FEATURE_FAST_TOP=y # CONFIG_FEATURE_ETC_NETWORKS is not set +CONFIG_FEATURE_USE_TERMIOS=y CONFIG_FEATURE_EDITING=y CONFIG_FEATURE_EDITING_MAX_LEN=1024 -# CONFIG_FEATURE_EDITING_FANCY_KEYS is not set # CONFIG_FEATURE_EDITING_VI is not set CONFIG_FEATURE_EDITING_HISTORY=15 -# CONFIG_FEATURE_EDITING_SAVEHISTORY is not set +CONFIG_FEATURE_EDITING_SAVEHISTORY=y CONFIG_FEATURE_TAB_COMPLETION=y # CONFIG_FEATURE_USERNAME_COMPLETION is not set CONFIG_FEATURE_EDITING_FANCY_PROMPT=y +# CONFIG_FEATURE_EDITING_ASK_TERMINAL is not set +CONFIG_FEATURE_NON_POSIX_CP=y +CONFIG_FEATURE_VERBOSE_CP_MESSAGE=y +CONFIG_FEATURE_COPYBUF_KB=4 CONFIG_MONOTONIC_SYSCALL=y CONFIG_IOCTL_HEX2STR_ERROR=y +CONFIG_FEATURE_HWIB=y # # Applets @@ -90,68 +117,82 @@ CONFIG_IOCTL_HEX2STR_ERROR=y # # Archival Utilities # +CONFIG_FEATURE_SEAMLESS_XZ=y +CONFIG_FEATURE_SEAMLESS_LZMA=y +CONFIG_FEATURE_SEAMLESS_BZ2=y +CONFIG_FEATURE_SEAMLESS_GZ=y +CONFIG_FEATURE_SEAMLESS_Z=y CONFIG_AR=y CONFIG_FEATURE_AR_LONG_FILENAMES=y +CONFIG_FEATURE_AR_CREATE=y CONFIG_BUNZIP2=y +CONFIG_BZIP2=y CONFIG_CPIO=y +CONFIG_FEATURE_CPIO_O=y +CONFIG_FEATURE_CPIO_P=y CONFIG_DPKG=y # CONFIG_DPKG_DEB is not set # CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY is not set CONFIG_GUNZIP=y -CONFIG_FEATURE_GUNZIP_UNCOMPRESS=y CONFIG_GZIP=y -CONFIG_RPM2CPIO=y -CONFIG_RPM=y -# CONFIG_FEATURE_RPM_BZ2 is not set +CONFIG_FEATURE_GZIP_LONG_OPTIONS=y +CONFIG_LZOP=y +CONFIG_LZOP_COMPR_HIGH=y +# CONFIG_RPM2CPIO is not set +# CONFIG_RPM is not set CONFIG_TAR=y CONFIG_FEATURE_TAR_CREATE=y -CONFIG_FEATURE_TAR_BZIP2=y -CONFIG_FEATURE_TAR_LZMA=y +CONFIG_FEATURE_TAR_AUTODETECT=y CONFIG_FEATURE_TAR_FROM=y -CONFIG_FEATURE_TAR_GZIP=y -CONFIG_FEATURE_TAR_COMPRESS=y CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY=y -# CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY is not set +CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY=y CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y CONFIG_FEATURE_TAR_LONG_OPTIONS=y +CONFIG_FEATURE_TAR_TO_COMMAND=y +CONFIG_FEATURE_TAR_UNAME_GNAME=y +CONFIG_FEATURE_TAR_NOPRESERVE_TIME=y +# CONFIG_FEATURE_TAR_SELINUX is not set CONFIG_UNCOMPRESS=y CONFIG_UNLZMA=y CONFIG_FEATURE_LZMA_FAST=y +CONFIG_LZMA=y +CONFIG_UNXZ=y +CONFIG_XZ=y CONFIG_UNZIP=y # -# Common options for cpio and tar -# -CONFIG_FEATURE_UNARCHIVE_TAPE=y - -# -# Common options for dpkg and dpkg_deb -# -CONFIG_FEATURE_DEB_TAR_GZ=y -# CONFIG_FEATURE_DEB_TAR_BZ2 is not set -# CONFIG_FEATURE_DEB_TAR_LZMA is not set - -# # Coreutils # CONFIG_BASENAME=y -# CONFIG_CAL is not set CONFIG_CAT=y -# CONFIG_CATV is not set +CONFIG_DATE=y +CONFIG_FEATURE_DATE_ISOFMT=y +CONFIG_FEATURE_DATE_NANO=y +CONFIG_FEATURE_DATE_COMPAT=y +CONFIG_TEST=y +# CONFIG_FEATURE_TEST_64 is not set +CONFIG_TR=y +CONFIG_FEATURE_TR_CLASSES=y +CONFIG_FEATURE_TR_EQUIV=y +CONFIG_BASE64=y +CONFIG_CAL=y +CONFIG_CATV=y CONFIG_CHGRP=y CONFIG_CHMOD=y CONFIG_CHOWN=y +CONFIG_FEATURE_CHOWN_LONG_OPTIONS=y CONFIG_CHROOT=y -# CONFIG_CKSUM is not set -# CONFIG_COMM is not set +CONFIG_CKSUM=y +CONFIG_COMM=y CONFIG_CP=y +CONFIG_FEATURE_CP_LONG_OPTIONS=y CONFIG_CUT=y -CONFIG_DATE=y -CONFIG_FEATURE_DATE_ISOFMT=y CONFIG_DD=y CONFIG_FEATURE_DD_SIGNAL_HANDLING=y -# CONFIG_FEATURE_DD_IBS_OBS is not set +CONFIG_FEATURE_DD_THIRD_STATUS_LINE=y +CONFIG_FEATURE_DD_IBS_OBS=y CONFIG_DF=y +CONFIG_FEATURE_DF_FANCY=y CONFIG_DIRNAME=y CONFIG_DOS2UNIX=y CONFIG_UNIX2DOS=y @@ -160,22 +201,23 @@ CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K=y CONFIG_ECHO=y CONFIG_FEATURE_FANCY_ECHO=y CONFIG_ENV=y -# CONFIG_FEATURE_ENV_LONG_OPTIONS is not set -# CONFIG_EXPAND is not set -# CONFIG_FEATURE_EXPAND_LONG_OPTIONS is not set +CONFIG_FEATURE_ENV_LONG_OPTIONS=y +CONFIG_EXPAND=y +CONFIG_FEATURE_EXPAND_LONG_OPTIONS=y CONFIG_EXPR=y # CONFIG_EXPR_MATH_SUPPORT_64 is not set CONFIG_FALSE=y -# CONFIG_FOLD is not set +CONFIG_FOLD=y +CONFIG_FSYNC=y CONFIG_HEAD=y CONFIG_FEATURE_FANCY_HEAD=y -# CONFIG_HOSTID is not set +CONFIG_HOSTID=y CONFIG_ID=y CONFIG_INSTALL=y -# CONFIG_FEATURE_INSTALL_LONG_OPTIONS is not set +CONFIG_FEATURE_INSTALL_LONG_OPTIONS=y CONFIG_LENGTH=y CONFIG_LN=y -# CONFIG_LOGNAME is not set +CONFIG_LOGNAME=y CONFIG_LS=y CONFIG_FEATURE_LS_FILETYPES=y CONFIG_FEATURE_LS_FOLLOWLINKS=y @@ -187,54 +229,54 @@ CONFIG_FEATURE_LS_COLOR=y # CONFIG_FEATURE_LS_COLOR_IS_DEFAULT is not set CONFIG_MD5SUM=y CONFIG_MKDIR=y -# CONFIG_FEATURE_MKDIR_LONG_OPTIONS is not set +CONFIG_FEATURE_MKDIR_LONG_OPTIONS=y CONFIG_MKFIFO=y CONFIG_MKNOD=y CONFIG_MV=y -# CONFIG_FEATURE_MV_LONG_OPTIONS is not set +CONFIG_FEATURE_MV_LONG_OPTIONS=y CONFIG_NICE=y # CONFIG_NOHUP is not set -# CONFIG_OD is not set +CONFIG_OD=y CONFIG_PRINTENV=y -# CONFIG_PRINTF is not set +CONFIG_PRINTF=y CONFIG_PWD=y CONFIG_READLINK=y -# CONFIG_FEATURE_READLINK_FOLLOW is not set -# CONFIG_REALPATH is not set +CONFIG_FEATURE_READLINK_FOLLOW=y +CONFIG_REALPATH=y CONFIG_RM=y CONFIG_RMDIR=y +CONFIG_FEATURE_RMDIR_LONG_OPTIONS=y CONFIG_SEQ=y CONFIG_SHA1SUM=y +CONFIG_SHA256SUM=y +CONFIG_SHA512SUM=y CONFIG_SLEEP=y # CONFIG_FEATURE_FANCY_SLEEP is not set +# CONFIG_FEATURE_FLOAT_SLEEP is not set CONFIG_SORT=y CONFIG_FEATURE_SORT_BIG=y -# CONFIG_SPLIT is not set -# CONFIG_FEATURE_SPLIT_FANCY is not set +CONFIG_SPLIT=y +CONFIG_FEATURE_SPLIT_FANCY=y CONFIG_STAT=y -# CONFIG_FEATURE_STAT_FORMAT is not set +CONFIG_FEATURE_STAT_FORMAT=y CONFIG_STTY=y -# CONFIG_SUM is not set +CONFIG_SUM=y CONFIG_SYNC=y +CONFIG_TAC=y CONFIG_TAIL=y CONFIG_FEATURE_FANCY_TAIL=y CONFIG_TEE=y CONFIG_FEATURE_TEE_USE_BLOCK_IO=y -CONFIG_TEST=y -# CONFIG_FEATURE_TEST_64 is not set CONFIG_TOUCH=y -CONFIG_TR=y -CONFIG_FEATURE_TR_CLASSES=y -CONFIG_FEATURE_TR_EQUIV=y CONFIG_TRUE=y CONFIG_TTY=y CONFIG_UNAME=y -# CONFIG_UNEXPAND is not set -# CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS is not set +CONFIG_UNEXPAND=y +CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS=y CONFIG_UNIQ=y CONFIG_USLEEP=y -# CONFIG_UUDECODE is not set -# CONFIG_UUENCODE is not set +CONFIG_UUDECODE=y +CONFIG_UUENCODE=y CONFIG_WC=y # CONFIG_FEATURE_WC_LARGE is not set # CONFIG_WHO is not set @@ -257,7 +299,7 @@ CONFIG_FEATURE_AUTOWIDTH=y CONFIG_FEATURE_HUMAN_READABLE=y # -# Common options for md5sum, sha1sum +# Common options for md5sum, sha1sum, sha256sum, sha512sum # CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y @@ -265,19 +307,31 @@ CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y # Console Utilities # CONFIG_CHVT=y +CONFIG_FGCONSOLE=y CONFIG_CLEAR=y CONFIG_DEALLOCVT=y CONFIG_DUMPKMAP=y +CONFIG_KBD_MODE=y CONFIG_LOADFONT=y CONFIG_LOADKMAP=y CONFIG_OPENVT=y CONFIG_RESET=y -# CONFIG_RESIZE is not set -# CONFIG_FEATURE_RESIZE_PRINT is not set +CONFIG_RESIZE=y +CONFIG_FEATURE_RESIZE_PRINT=y CONFIG_SETCONSOLE=y # CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set +CONFIG_SETFONT=y +CONFIG_FEATURE_SETFONT_TEXTUAL_MAP=y +CONFIG_DEFAULT_SETFONT_DIR="" CONFIG_SETKEYCODES=y -# CONFIG_SETLOGCONS is not set +CONFIG_SETLOGCONS=y +CONFIG_SHOWKEY=y + +# +# Common options for loadfont and setfont +# +CONFIG_FEATURE_LOADFONT_PSF2=y +CONFIG_FEATURE_LOADFONT_RAW=y # # Debian Utilities @@ -295,18 +349,18 @@ CONFIG_WHICH=y # # Editors # +CONFIG_PATCH=y # CONFIG_AWK is not set -# CONFIG_FEATURE_AWK_MATH is not set +# CONFIG_FEATURE_AWK_LIBM is not set CONFIG_CMP=y CONFIG_DIFF=y -CONFIG_FEATURE_DIFF_BINARY=y +CONFIG_FEATURE_DIFF_LONG_OPTIONS=y CONFIG_FEATURE_DIFF_DIR=y -# CONFIG_FEATURE_DIFF_MINIMAL is not set -# CONFIG_ED is not set -# CONFIG_PATCH is not set +CONFIG_ED=y CONFIG_SED=y CONFIG_VI=y CONFIG_FEATURE_VI_MAX_LEN=1024 +# CONFIG_FEATURE_VI_8BIT is not set CONFIG_FEATURE_VI_COLON=y CONFIG_FEATURE_VI_YANKMARK=y CONFIG_FEATURE_VI_SEARCH=y @@ -316,6 +370,7 @@ CONFIG_FEATURE_VI_READONLY=y CONFIG_FEATURE_VI_SETOPTS=y CONFIG_FEATURE_VI_SET=y CONFIG_FEATURE_VI_WIN_RESIZE=y +CONFIG_FEATURE_VI_ASK_TERMINAL=y CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y CONFIG_FEATURE_ALLOW_EXEC=y @@ -340,10 +395,11 @@ CONFIG_FEATURE_FIND_DEPTH=y CONFIG_FEATURE_FIND_PAREN=y CONFIG_FEATURE_FIND_SIZE=y CONFIG_FEATURE_FIND_PRUNE=y -# CONFIG_FEATURE_FIND_DELETE is not set +CONFIG_FEATURE_FIND_DELETE=y CONFIG_FEATURE_FIND_PATH=y CONFIG_FEATURE_FIND_REGEX=y # CONFIG_FEATURE_FIND_CONTEXT is not set +CONFIG_FEATURE_FIND_LINKS=y CONFIG_GREP=y CONFIG_FEATURE_GREP_EGREP_ALIAS=y CONFIG_FEATURE_GREP_FGREP_ALIAS=y @@ -357,32 +413,46 @@ CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y # # Init Utilities # +# CONFIG_BOOTCHARTD is not set +# CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER is not set +# CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE is not set +CONFIG_HALT=y +# CONFIG_FEATURE_CALL_TELINIT is not set +CONFIG_TELINIT_PATH="" CONFIG_INIT=y -# CONFIG_DEBUG_INIT is not set CONFIG_FEATURE_USE_INITTAB=y +# CONFIG_FEATURE_KILL_REMOVED is not set +CONFIG_FEATURE_KILL_DELAY=0 # CONFIG_FEATURE_INIT_SCTTY is not set # CONFIG_FEATURE_INIT_SYSLOG is not set CONFIG_FEATURE_EXTRA_QUIET=y # CONFIG_FEATURE_INIT_COREDUMPS is not set CONFIG_FEATURE_INITRD=y -CONFIG_HALT=y +CONFIG_INIT_TERMINAL_TYPE="linux" CONFIG_MESG=y # # Login/Password Management Utilities # +# CONFIG_ADD_SHELL is not set +# CONFIG_REMOVE_SHELL is not set CONFIG_FEATURE_SHADOWPASSWDS=y -# CONFIG_USE_BB_SHADOW is not set # CONFIG_USE_BB_PWD_GRP is not set +# CONFIG_USE_BB_SHADOW is not set +# CONFIG_USE_BB_CRYPT is not set +# CONFIG_USE_BB_CRYPT_SHA is not set +# CONFIG_ADDUSER is not set +# CONFIG_FEATURE_ADDUSER_LONG_OPTIONS is not set +# CONFIG_FEATURE_CHECK_NAMES is not set +CONFIG_FIRST_SYSTEM_ID=0 +CONFIG_LAST_SYSTEM_ID=0 # CONFIG_ADDGROUP is not set +# CONFIG_FEATURE_ADDGROUP_LONG_OPTIONS is not set # CONFIG_FEATURE_ADDUSER_TO_GROUP is not set +# CONFIG_DELUSER is not set # CONFIG_DELGROUP is not set # CONFIG_FEATURE_DEL_USER_FROM_GROUP is not set -# CONFIG_ADDUSER is not set -# CONFIG_DELUSER is not set CONFIG_GETTY=y -# CONFIG_FEATURE_UTMP is not set -# CONFIG_FEATURE_WTMP is not set CONFIG_LOGIN=y # CONFIG_PAM is not set # CONFIG_LOGIN_SCRIPTS is not set @@ -401,9 +471,10 @@ CONFIG_CHPASSWD=y # # Linux Ext2 FS Progs # -# CONFIG_CHATTR is not set -# CONFIG_FSCK is not set -# CONFIG_LSATTR is not set +CONFIG_CHATTR=y +CONFIG_FSCK=y +CONFIG_LSATTR=y +CONFIG_TUNE2FS=y # # Linux mdadm Utilities @@ -413,37 +484,49 @@ CONFIG_MDADM=y # # Linux Module Utilities # +CONFIG_MODINFO=y +# CONFIG_MODPROBE_SMALL is not set +# CONFIG_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE is not set +# CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED is not set CONFIG_INSMOD=y -# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set -# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set -# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set -# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set -# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set CONFIG_RMMOD=y CONFIG_LSMOD=y CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT=y CONFIG_MODPROBE=y -CONFIG_FEATURE_MODPROBE_MULTIPLE_OPTIONS=y -CONFIG_FEATURE_MODPROBE_FANCY_ALIAS=y +CONFIG_FEATURE_MODPROBE_BLACKLIST=y +CONFIG_DEPMOD=y # # Options common to multiple modutils # -CONFIG_FEATURE_CHECK_TAINTED_MODULE=y -CONFIG_FEATURE_2_4_MODULES=y -CONFIG_FEATURE_2_6_MODULES=y -# CONFIG_FEATURE_QUERY_MODULE_INTERFACE is not set +# CONFIG_FEATURE_2_4_MODULES is not set +CONFIG_FEATURE_INSMOD_TRY_MMAP=y +# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set +# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set +# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set +# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set +# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set +# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set +CONFIG_FEATURE_MODUTILS_ALIAS=y +CONFIG_FEATURE_MODUTILS_SYMBOLS=y +CONFIG_DEFAULT_MODULES_DIR="/lib/modules" +CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" # # Linux System Utilities # +CONFIG_BLOCKDEV=y +CONFIG_REV=y +CONFIG_ACPID=y +CONFIG_FEATURE_ACPID_COMPAT=y +CONFIG_BLKID=y CONFIG_DMESG=y CONFIG_FEATURE_DMESG_PRETTY=y -# CONFIG_FBSET is not set +CONFIG_FBSET=y # CONFIG_FEATURE_FBSET_FANCY is not set -# CONFIG_FEATURE_FBSET_READMODE is not set +CONFIG_FEATURE_FBSET_READMODE=y # CONFIG_FDFLUSH is not set -# CONFIG_FDFORMAT is not set +CONFIG_FDFORMAT=y CONFIG_FDISK=y CONFIG_FDISK_SUPPORT_LARGE_DISKS=y CONFIG_FEATURE_FDISK_WRITABLE=y @@ -451,38 +534,59 @@ CONFIG_FEATURE_AIX_LABEL=y CONFIG_FEATURE_SGI_LABEL=y CONFIG_FEATURE_SUN_LABEL=y CONFIG_FEATURE_OSF_LABEL=y +# CONFIG_FEATURE_GPT_LABEL is not set CONFIG_FEATURE_FDISK_ADVANCED=y +CONFIG_FINDFS=y +CONFIG_FLOCK=y CONFIG_FREERAMDISK=y # CONFIG_FSCK_MINIX is not set +CONFIG_MKFS_EXT2=y # CONFIG_MKFS_MINIX is not set # CONFIG_FEATURE_MINIX2 is not set -# CONFIG_GETOPT is not set +CONFIG_MKFS_REISER=y +CONFIG_MKFS_VFAT=y +CONFIG_GETOPT=y +# CONFIG_FEATURE_GETOPT_LONG is not set CONFIG_HEXDUMP=y +CONFIG_FEATURE_HEXDUMP_REVERSE=y +CONFIG_HD=y # CONFIG_HWCLOCK is not set # CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS is not set # CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS is not set # CONFIG_IPCRM is not set # CONFIG_IPCS is not set CONFIG_LOSETUP=y +CONFIG_LSPCI=y +CONFIG_LSUSB=y CONFIG_MDEV=y CONFIG_FEATURE_MDEV_CONF=y +CONFIG_FEATURE_MDEV_RENAME=y +CONFIG_FEATURE_MDEV_RENAME_REGEXP=y CONFIG_FEATURE_MDEV_EXEC=y CONFIG_FEATURE_MDEV_LOAD_FIRMWARE=y CONFIG_MDSTART=y CONFIG_MKSWAP=y -# CONFIG_FEATURE_MKSWAP_V0 is not set +CONFIG_FEATURE_MKSWAP_UUID=y CONFIG_MORE=y -CONFIG_FEATURE_USE_TERMIOS=y CONFIG_MOUNT=y +CONFIG_FEATURE_MOUNT_FAKE=y +CONFIG_FEATURE_MOUNT_VERBOSE=y +# CONFIG_FEATURE_MOUNT_HELPERS is not set +CONFIG_FEATURE_MOUNT_LABEL=y CONFIG_FEATURE_MOUNT_NFS=y CONFIG_FEATURE_MOUNT_CIFS=y CONFIG_FEATURE_MOUNT_FLAGS=y CONFIG_FEATURE_MOUNT_FSTAB=y CONFIG_PIVOT_ROOT=y CONFIG_RDATE=y +CONFIG_RDEV=y # CONFIG_READPROFILE is not set +CONFIG_RTCWAKE=y +CONFIG_SCRIPT=y +CONFIG_SCRIPTREPLAY=y # CONFIG_SETARCH is not set CONFIG_SWAPONOFF=y +CONFIG_FEATURE_SWAPON_PRI=y CONFIG_SWITCH_ROOT=y CONFIG_UMOUNT=y CONFIG_FEATURE_UMOUNT_ALL=y @@ -491,33 +595,88 @@ CONFIG_FEATURE_UMOUNT_ALL=y # Common options for mount/umount # CONFIG_FEATURE_MOUNT_LOOP=y +CONFIG_FEATURE_MOUNT_LOOP_CREATE=y CONFIG_FEATURE_MTAB_SUPPORT=y +CONFIG_VOLUMEID=y + +# +# Filesystem/Volume identification +# +CONFIG_FEATURE_VOLUMEID_EXT=y +CONFIG_FEATURE_VOLUMEID_BTRFS=y +CONFIG_FEATURE_VOLUMEID_REISERFS=y +CONFIG_FEATURE_VOLUMEID_FAT=y +CONFIG_FEATURE_VOLUMEID_HFS=y +CONFIG_FEATURE_VOLUMEID_JFS=y +CONFIG_FEATURE_VOLUMEID_XFS=y +CONFIG_FEATURE_VOLUMEID_NTFS=y +CONFIG_FEATURE_VOLUMEID_ISO9660=y +CONFIG_FEATURE_VOLUMEID_UDF=y +CONFIG_FEATURE_VOLUMEID_LUKS=y +CONFIG_FEATURE_VOLUMEID_LINUXSWAP=y +CONFIG_FEATURE_VOLUMEID_CRAMFS=y +CONFIG_FEATURE_VOLUMEID_ROMFS=y +CONFIG_FEATURE_VOLUMEID_SYSV=y +CONFIG_FEATURE_VOLUMEID_OCFS2=y +CONFIG_FEATURE_VOLUMEID_LINUXRAID=y # # Miscellaneous Utilities # +# CONFIG_CONSPY is not set +# CONFIG_NANDWRITE is not set +# CONFIG_NANDDUMP is not set +# CONFIG_UBIATTACH is not set +# CONFIG_UBIDETACH is not set # CONFIG_ADJTIMEX is not set CONFIG_BBCONFIG=y +CONFIG_FEATURE_COMPRESS_BBCONFIG=y +# CONFIG_BEEP is not set +CONFIG_FEATURE_BEEP_FREQ=0 +CONFIG_FEATURE_BEEP_LENGTH_MS=0 +CONFIG_CHAT=y +CONFIG_FEATURE_CHAT_NOFAIL=y +# CONFIG_FEATURE_CHAT_TTY_HIFI is not set +CONFIG_FEATURE_CHAT_IMPLICIT_CR=y +CONFIG_FEATURE_CHAT_SWALLOW_OPTS=y +CONFIG_FEATURE_CHAT_SEND_ESCAPES=y +CONFIG_FEATURE_CHAT_VAR_ABORT_LEN=y +CONFIG_FEATURE_CHAT_CLR_ABORT=y # CONFIG_CHRT is not set # CONFIG_CROND is not set -# CONFIG_DEBUG_CROND_OPTION is not set +# CONFIG_FEATURE_CROND_D is not set # CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set +CONFIG_FEATURE_CROND_DIR="" # CONFIG_CRONTAB is not set CONFIG_DC=y +CONFIG_FEATURE_DC_LIBM=y # CONFIG_DEVFSD is not set # CONFIG_DEVFSD_MODLOAD is not set # CONFIG_DEVFSD_FG_NP is not set # CONFIG_DEVFSD_VERBOSE is not set # CONFIG_FEATURE_DEVFS is not set +# CONFIG_DEVMEM is not set # CONFIG_EJECT is not set +# CONFIG_FEATURE_EJECT_SCSI is not set +# CONFIG_FBSPLASH is not set +# CONFIG_FLASHCP is not set +# CONFIG_FLASH_LOCK is not set +# CONFIG_FLASH_UNLOCK is not set +# CONFIG_FLASH_ERASEALL is not set +CONFIG_IONICE=y +# CONFIG_INOTIFYD is not set # CONFIG_LAST is not set +# CONFIG_FEATURE_LAST_SMALL is not set +# CONFIG_FEATURE_LAST_FANCY is not set # CONFIG_LESS is not set -CONFIG_FEATURE_LESS_MAXLINES= +CONFIG_FEATURE_LESS_MAXLINES=0 # CONFIG_FEATURE_LESS_BRACKETS is not set # CONFIG_FEATURE_LESS_FLAGS is not set -# CONFIG_FEATURE_LESS_FLAGCS is not set # CONFIG_FEATURE_LESS_MARKS is not set # CONFIG_FEATURE_LESS_REGEXP is not set +# CONFIG_FEATURE_LESS_WINCH is not set +# CONFIG_FEATURE_LESS_DASHCMD is not set +# CONFIG_FEATURE_LESS_LINENUMS is not set # CONFIG_HDPARM is not set # CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set # CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set @@ -528,54 +687,76 @@ CONFIG_FEATURE_LESS_MAXLINES= CONFIG_MAKEDEVS=y CONFIG_FEATURE_MAKEDEVS_LEAF=y # CONFIG_FEATURE_MAKEDEVS_TABLE is not set +CONFIG_MAN=y +CONFIG_MICROCOM=y CONFIG_MOUNTPOINT=y CONFIG_MT=y -# CONFIG_RAIDAUTORUN is not set -# CONFIG_READAHEAD is not set +CONFIG_RAIDAUTORUN=y +CONFIG_READAHEAD=y +# CONFIG_RFKILL is not set # CONFIG_RUNLEVEL is not set # CONFIG_RX is not set -CONFIG_STRINGS=y # CONFIG_SETSID is not set +CONFIG_STRINGS=y # CONFIG_TASKSET is not set # CONFIG_FEATURE_TASKSET_FANCY is not set CONFIG_TIME=y +CONFIG_TIMEOUT=y # CONFIG_TTYSIZE is not set +CONFIG_VOLNAME=y +CONFIG_WALL=y # CONFIG_WATCHDOG is not set # # Networking Utilities # -# CONFIG_FEATURE_IPV6 is not set +CONFIG_NBDCLIENT=y +CONFIG_NC=y +CONFIG_NC_SERVER=y +# CONFIG_NC_EXTRA is not set +# CONFIG_NC_110_COMPAT is not set +CONFIG_FEATURE_IPV6=y +# CONFIG_FEATURE_UNIX_LOCAL is not set +CONFIG_FEATURE_PREFER_IPV4_ADDRESS=y CONFIG_VERBOSE_RESOLUTION_ERRORS=y -# CONFIG_ARP is not set -# CONFIG_ARPING is not set +CONFIG_ARP=y +CONFIG_ARPING=y +CONFIG_BRCTL=y +CONFIG_FEATURE_BRCTL_FANCY=y +CONFIG_FEATURE_BRCTL_SHOW=y # CONFIG_DNSD is not set # CONFIG_ETHER_WAKE is not set # CONFIG_FAKEIDENTD is not set +# CONFIG_FTPD is not set +# CONFIG_FEATURE_FTP_WRITE is not set +# CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST is not set CONFIG_FTPGET=y CONFIG_FTPPUT=y # CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set CONFIG_HOSTNAME=y # CONFIG_HTTPD is not set +# CONFIG_FEATURE_HTTPD_RANGES is not set # CONFIG_FEATURE_HTTPD_USE_SENDFILE is not set -# CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP is not set # CONFIG_FEATURE_HTTPD_SETUID is not set # CONFIG_FEATURE_HTTPD_BASIC_AUTH is not set # CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set -# CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES is not set # CONFIG_FEATURE_HTTPD_CGI is not set # CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set # CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set # CONFIG_FEATURE_HTTPD_ENCODE_URL_STR is not set # CONFIG_FEATURE_HTTPD_ERROR_PAGES is not set +# CONFIG_FEATURE_HTTPD_PROXY is not set +# CONFIG_FEATURE_HTTPD_GZIP is not set CONFIG_IFCONFIG=y CONFIG_FEATURE_IFCONFIG_STATUS=y # CONFIG_FEATURE_IFCONFIG_SLIP is not set CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ=y CONFIG_FEATURE_IFCONFIG_HW=y CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS=y +CONFIG_IFENSLAVE=y +CONFIG_IFPLUGD=y # CONFIG_IFUPDOWN is not set -CONFIG_IFUPDOWN_IFSTATE_PATH="/var/run/ifstate" +CONFIG_IFUPDOWN_IFSTATE_PATH="" # CONFIG_FEATURE_IFUPDOWN_IP is not set # CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN is not set # CONFIG_FEATURE_IFUPDOWN_IFCONFIG_BUILTIN is not set @@ -597,6 +778,7 @@ CONFIG_IFUPDOWN_IFSTATE_PATH="/var/run/i # CONFIG_FEATURE_IP_TUNNEL is not set # CONFIG_FEATURE_IP_RULE is not set # CONFIG_FEATURE_IP_SHORT_FORMS is not set +# CONFIG_FEATURE_IP_RARE_PROTOCOLS is not set # CONFIG_IPADDR is not set # CONFIG_IPLINK is not set # CONFIG_IPROUTE is not set @@ -606,154 +788,205 @@ CONFIG_IPCALC=y CONFIG_FEATURE_IPCALC_FANCY=y # CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set # CONFIG_NAMEIF is not set -CONFIG_NC=y -CONFIG_NC_SERVER=y -# CONFIG_NC_EXTRA is not set +# CONFIG_FEATURE_NAMEIF_EXTENDED is not set CONFIG_NETSTAT=y # CONFIG_FEATURE_NETSTAT_WIDE is not set +CONFIG_FEATURE_NETSTAT_PRG=y CONFIG_NSLOOKUP=y +CONFIG_NTPD=y +CONFIG_FEATURE_NTPD_SERVER=y CONFIG_PING=y -# CONFIG_PING6 is not set -# CONFIG_PSCAN is not set +CONFIG_PING6=y CONFIG_FEATURE_FANCY_PING=y +# CONFIG_PSCAN is not set CONFIG_ROUTE=y # CONFIG_SLATTACH is not set -# CONFIG_TELNET is not set -# CONFIG_FEATURE_TELNET_TTYPE is not set -# CONFIG_FEATURE_TELNET_AUTOLOGIN is not set -# CONFIG_TELNETD is not set -# CONFIG_FEATURE_TELNETD_STANDALONE is not set +# CONFIG_TCPSVD is not set +CONFIG_TELNET=y +CONFIG_FEATURE_TELNET_TTYPE=y +CONFIG_FEATURE_TELNET_AUTOLOGIN=y +CONFIG_TELNETD=y +CONFIG_FEATURE_TELNETD_STANDALONE=y +# CONFIG_FEATURE_TELNETD_INETD_WAIT is not set # CONFIG_TFTP is not set +# CONFIG_TFTPD is not set # CONFIG_FEATURE_TFTP_GET is not set # CONFIG_FEATURE_TFTP_PUT is not set # CONFIG_FEATURE_TFTP_BLOCKSIZE is not set -# CONFIG_DEBUG_TFTP is not set +# CONFIG_FEATURE_TFTP_PROGRESS_BAR is not set +# CONFIG_TFTP_DEBUG is not set CONFIG_TRACEROUTE=y +CONFIG_TRACEROUTE6=y CONFIG_FEATURE_TRACEROUTE_VERBOSE=y CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE=y CONFIG_FEATURE_TRACEROUTE_USE_ICMP=y -# CONFIG_APP_UDHCPD is not set -# CONFIG_APP_DHCPRELAY is not set -# CONFIG_APP_DUMPLEASES is not set +CONFIG_TUNCTL=y +CONFIG_FEATURE_TUNCTL_UG=y +# CONFIG_UDHCPD is not set +# CONFIG_DHCPRELAY is not set +# CONFIG_DUMPLEASES is not set # CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY is not set -CONFIG_APP_UDHCPC=y -# CONFIG_FEATURE_UDHCP_DEBUG is not set -# CONFIG_FEATURE_RFC3397 is not set +CONFIG_DHCPD_LEASES_FILE="" +CONFIG_UDHCPC=y +CONFIG_FEATURE_UDHCPC_ARPING=y +CONFIG_FEATURE_UDHCP_PORT=y +CONFIG_UDHCP_DEBUG=9 +CONFIG_FEATURE_UDHCP_RFC3397=y +CONFIG_UDHCPC_DEFAULT_SCRIPT="/usr/share/udhcpc/default.script" +CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=80 +CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS="" +# CONFIG_UDPSVD is not set CONFIG_VCONFIG=y CONFIG_WGET=y CONFIG_FEATURE_WGET_STATUSBAR=y CONFIG_FEATURE_WGET_AUTHENTICATION=y -# CONFIG_FEATURE_WGET_LONG_OPTIONS is not set +CONFIG_FEATURE_WGET_LONG_OPTIONS=y +CONFIG_FEATURE_WGET_TIMEOUT=y # CONFIG_ZCIP is not set # +# Print Utilities +# +# CONFIG_LPD is not set +# CONFIG_LPR is not set +# CONFIG_LPQ is not set + +# +# Mail Utilities +# +# CONFIG_MAKEMIME is not set +CONFIG_FEATURE_MIME_CHARSET="" +# CONFIG_POPMAILDIR is not set +# CONFIG_FEATURE_POPMAILDIR_DELIVERY is not set +# CONFIG_REFORMIME is not set +# CONFIG_FEATURE_REFORMIME_COMPAT is not set +# CONFIG_SENDMAIL is not set + +# # Process Utilities # +CONFIG_IOSTAT=y +CONFIG_MPSTAT=y +CONFIG_PMAP=y +CONFIG_POWERTOP=y +CONFIG_SMEMCAP=y CONFIG_FREE=y # CONFIG_FUSER is not set CONFIG_KILL=y CONFIG_KILLALL=y # CONFIG_KILLALL5 is not set # CONFIG_NMETER is not set +CONFIG_PGREP=y CONFIG_PIDOF=y CONFIG_FEATURE_PIDOF_SINGLE=y CONFIG_FEATURE_PIDOF_OMIT=y +CONFIG_PKILL=y CONFIG_PS=y CONFIG_FEATURE_PS_WIDE=y +# CONFIG_FEATURE_PS_TIME is not set +# CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS is not set +# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set CONFIG_RENICE=y # CONFIG_BB_SYSCTL is not set CONFIG_TOP=y CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS=y +CONFIG_FEATURE_TOP_SMP_CPU=y # CONFIG_FEATURE_TOP_DECIMALS is not set +CONFIG_FEATURE_TOP_SMP_PROCESS=y +CONFIG_FEATURE_TOPMEM=y +CONFIG_FEATURE_SHOW_THREADS=y CONFIG_UPTIME=y # CONFIG_WATCH is not set # -# Shells +# Runit Utilities # -CONFIG_FEATURE_SH_IS_ASH=y -# CONFIG_FEATURE_SH_IS_HUSH is not set -# CONFIG_FEATURE_SH_IS_LASH is not set -# CONFIG_FEATURE_SH_IS_MSH is not set -# CONFIG_FEATURE_SH_IS_NONE is not set -CONFIG_ASH=y +# CONFIG_RUNSV is not set +# CONFIG_RUNSVDIR is not set +# CONFIG_FEATURE_RUNSVDIR_LOG is not set +# CONFIG_SV is not set +CONFIG_SV_DEFAULT_SERVICE_DIR="" +# CONFIG_SVLOGD is not set +# CONFIG_CHPST is not set +# CONFIG_SETUIDGID is not set +# CONFIG_ENVUIDGID is not set +# CONFIG_ENVDIR is not set +# CONFIG_SOFTLIMIT is not set +# CONFIG_CHCON is not set +# CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set +# CONFIG_GETENFORCE is not set +# CONFIG_GETSEBOOL is not set +# CONFIG_LOAD_POLICY is not set +# CONFIG_MATCHPATHCON is not set +# CONFIG_RESTORECON is not set +# CONFIG_RUNCON is not set +# CONFIG_FEATURE_RUNCON_LONG_OPTIONS is not set +# CONFIG_SELINUXENABLED is not set +# CONFIG_SETENFORCE is not set +# CONFIG_SETFILES is not set +# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set +# CONFIG_SETSEBOOL is not set +# CONFIG_SESTATUS is not set # -# Ash Shell Options +# Shells # +CONFIG_ASH=y +CONFIG_ASH_BASH_COMPAT=y CONFIG_ASH_JOB_CONTROL=y -CONFIG_ASH_READ_NCHARS=y -CONFIG_ASH_READ_TIMEOUT=y CONFIG_ASH_ALIAS=y -CONFIG_ASH_MATH_SUPPORT=y -# CONFIG_ASH_MATH_SUPPORT_64 is not set # CONFIG_ASH_GETOPTS is not set CONFIG_ASH_BUILTIN_ECHO=y +CONFIG_ASH_BUILTIN_PRINTF=y CONFIG_ASH_BUILTIN_TEST=y # CONFIG_ASH_CMDCMD is not set # CONFIG_ASH_MAIL is not set CONFIG_ASH_OPTIMIZE_FOR_SIZE=y CONFIG_ASH_RANDOM_SUPPORT=y # CONFIG_ASH_EXPAND_PRMT is not set +# CONFIG_CTTYHACK is not set # CONFIG_HUSH is not set +# CONFIG_HUSH_BASH_COMPAT is not set +# CONFIG_HUSH_BRACE_EXPANSION is not set # CONFIG_HUSH_HELP is not set # CONFIG_HUSH_INTERACTIVE is not set +# CONFIG_HUSH_SAVEHISTORY is not set # CONFIG_HUSH_JOB is not set # CONFIG_HUSH_TICK is not set # CONFIG_HUSH_IF is not set # CONFIG_HUSH_LOOPS is not set -# CONFIG_LASH is not set +# CONFIG_HUSH_CASE is not set +# CONFIG_HUSH_FUNCTIONS is not set +# CONFIG_HUSH_LOCAL is not set +# CONFIG_HUSH_RANDOM_SUPPORT is not set +# CONFIG_HUSH_EXPORT_N is not set +# CONFIG_HUSH_MODE_X is not set # CONFIG_MSH is not set - -# -# Bourne Shell Options -# +CONFIG_FEATURE_SH_IS_ASH=y +# CONFIG_FEATURE_SH_IS_HUSH is not set +# CONFIG_FEATURE_SH_IS_NONE is not set +# CONFIG_FEATURE_BASH_IS_ASH is not set +# CONFIG_FEATURE_BASH_IS_HUSH is not set +CONFIG_FEATURE_BASH_IS_NONE=y +CONFIG_SH_MATH_SUPPORT=y +CONFIG_SH_MATH_SUPPORT_64=y # CONFIG_FEATURE_SH_EXTRA_QUIET is not set # CONFIG_FEATURE_SH_STANDALONE is not set -# CONFIG_CTTYHACK is not set +CONFIG_FEATURE_SH_NOFORK=y # # System Logging Utilities # CONFIG_SYSLOGD=y # CONFIG_FEATURE_ROTATE_LOGFILE is not set -# CONFIG_FEATURE_REMOTE_LOG is not set +CONFIG_FEATURE_REMOTE_LOG=y +CONFIG_FEATURE_SYSLOGD_DUP=y +CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=256 CONFIG_FEATURE_IPC_SYSLOG=y CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=16 CONFIG_LOGREAD=y -# CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set +CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING=y CONFIG_KLOGD=y +CONFIG_FEATURE_KLOGD_KLOGCTL=y CONFIG_LOGGER=y - -# -# Runit Utilities -# -# CONFIG_RUNSV is not set -# CONFIG_RUNSVDIR is not set -# CONFIG_SV is not set -# CONFIG_SVLOGD is not set -# CONFIG_CHPST is not set -# CONFIG_SETUIDGID is not set -# CONFIG_ENVUIDGID is not set -# CONFIG_ENVDIR is not set -# CONFIG_SOFTLIMIT is not set -# CONFIG_CHCON is not set -# CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set -# CONFIG_GETENFORCE is not set -# CONFIG_GETSEBOOL is not set -# CONFIG_LOAD_POLICY is not set -# CONFIG_MATCHPATHCON is not set -# CONFIG_RESTORECON is not set -# CONFIG_RUNCON is not set -# CONFIG_FEATURE_RUNCON_LONG_OPTIONS is not set -# CONFIG_SELINUXENABLED is not set -# CONFIG_SETENFORCE is not set -# CONFIG_SETFILES is not set -# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set - -# -# ipsvd utilities -# -# CONFIG_TCPSVD is not set -# CONFIG_UDPSVD is not set diff -pruN genkernel.a/patches/busybox/1.18.1/1.18.1-mdadm.diff genkernel.b/patches/busybox/1.18.1/1.18.1-mdadm.diff --- genkernel.a/patches/busybox/1.18.1/1.18.1-mdadm.diff 1970-01-01 03:00:00.000000000 +0300 +++ genkernel.b/patches/busybox/1.18.1/1.18.1-mdadm.diff 2011-01-12 21:35:19.000000000 +0200 @@ -0,0 +1,5876 @@ +Based on: + +> Forward-port the mdadm tool from the Gentoo Busybox-1.1.3. +> Should handle all types of metadata 0.90, 1.0, 1.1, 1.2. +> If /etc/mdadm.conf does not exist in the initrd, it is created first, by +> scanning devices, and then it is used. + +> Signed-off-by: Robin H. Johnson + +--- a/Config.in 2010-12-21 06:31:04.000000000 +0200 ++++ mdadm/Config.in 2011-01-12 21:33:01.000000000 +0200 +@@ -749,6 +749,7 @@ source findutils/Config.in + source init/Config.in + source loginutils/Config.in + source e2fsprogs/Config.in ++source mdadm/Config.in + source modutils/Config.in + source util-linux/Config.in + source miscutils/Config.in +--- a/include/applets.src.h 2010-12-21 06:31:04.000000000 +0200 ++++ mdadm/include/applets.src.h 2011-01-12 21:33:01.000000000 +0200 +@@ -206,6 +206,7 @@ IF_KILLALL5(APPLET_ODDNAME(killall5, kil + IF_KLOGD(APPLET(klogd, _BB_DIR_SBIN, _BB_SUID_DROP)) + IF_LAST(APPLET(last, _BB_DIR_USR_BIN, _BB_SUID_DROP)) + IF_LENGTH(APPLET_NOFORK(length, length, _BB_DIR_USR_BIN, _BB_SUID_DROP, length)) ++IF_MDADM(APPLET(mdadm, _BB_DIR_SBIN, _BB_SUID_DROP)) + IF_LESS(APPLET(less, _BB_DIR_USR_BIN, _BB_SUID_DROP)) + IF_SETARCH(APPLET_ODDNAME(linux32, setarch, _BB_DIR_BIN, _BB_SUID_DROP, linux32)) + IF_SETARCH(APPLET_ODDNAME(linux64, setarch, _BB_DIR_BIN, _BB_SUID_DROP, linux64)) +--- a/include/usage.src.h 2010-12-21 06:29:45.000000000 +0200 ++++ mdadm/include/usage.src.h 2011-01-12 21:33:01.000000000 +0200 +@@ -2404,6 +2404,11 @@ INSERT + "\n -w Warn about improperly formatted checksum lines" \ + ) + ++#define mdadm_trivial_usage \ ++ "" ++#define mdadm_full_usage \ ++ "Assemble or Examine the mdadm arrays." ++ + #define mdev_trivial_usage \ + "[-s]" + #define mdev_full_usage "\n\n" \ +--- a/Makefile 2010-12-21 06:31:43.000000000 +0200 ++++ mdadm/Makefile 2011-01-12 21:33:01.000000000 +0200 +@@ -478,6 +478,7 @@ libs-y := \ + loginutils/ \ + mailutils/ \ + miscutils/ \ ++ mdadm/ \ + modutils/ \ + networking/ \ + networking/libiproute/ \ +--- a/mdadm/bitmap.h 1970-01-01 03:00:00.000000000 +0300 ++++ mdadm/mdadm/bitmap.h 2011-01-12 21:33:01.000000000 +0200 +@@ -0,0 +1,287 @@ ++/* ++ * bitmap.h: Copyright (C) Peter T. Breuer (ptb@ot.uc3m.es) 2003 ++ * ++ * additions: Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc. ++ */ ++#ifndef BITMAP_H ++#define BITMAP_H 1 ++ ++#define BITMAP_MAJOR_LO 3 ++/* version 4 insists the bitmap is in little-endian order ++ * with version 3, it is host-endian which is non-portable ++ */ ++#define BITMAP_MAJOR_HI 4 ++#define BITMAP_MAJOR_HOSTENDIAN 3 ++ ++#define BITMAP_MINOR 39 ++ ++/* ++ * in-memory bitmap: ++ * ++ * Use 16 bit block counters to track pending writes to each "chunk". ++ * The 2 high order bits are special-purpose, the first is a flag indicating ++ * whether a resync is needed. The second is a flag indicating whether a ++ * resync is active. ++ * This means that the counter is actually 14 bits: ++ * ++ * +--------+--------+------------------------------------------------+ ++ * | resync | resync | counter | ++ * | needed | active | | ++ * | (0-1) | (0-1) | (0-16383) | ++ * +--------+--------+------------------------------------------------+ ++ * ++ * The "resync needed" bit is set when: ++ * a '1' bit is read from storage at startup. ++ * a write request fails on some drives ++ * a resync is aborted on a chunk with 'resync active' set ++ * It is cleared (and resync-active set) when a resync starts across all drives ++ * of the chunk. ++ * ++ * ++ * The "resync active" bit is set when: ++ * a resync is started on all drives, and resync_needed is set. ++ * resync_needed will be cleared (as long as resync_active wasn't already set). ++ * It is cleared when a resync completes. ++ * ++ * The counter counts pending write requests, plus the on-disk bit. ++ * When the counter is '1' and the resync bits are clear, the on-disk ++ * bit can be cleared aswell, thus setting the counter to 0. ++ * When we set a bit, or in the counter (to start a write), if the fields is ++ * 0, we first set the disk bit and set the counter to 1. ++ * ++ * If the counter is 0, the on-disk bit is clear and the stipe is clean ++ * Anything that dirties the stipe pushes the counter to 2 (at least) ++ * and sets the on-disk bit (lazily). ++ * If a periodic sweep find the counter at 2, it is decremented to 1. ++ * If the sweep find the counter at 1, the on-disk bit is cleared and the ++ * counter goes to zero. ++ * ++ * Also, we'll hijack the "map" pointer itself and use it as two 16 bit block ++ * counters as a fallback when "page" memory cannot be allocated: ++ * ++ * Normal case (page memory allocated): ++ * ++ * page pointer (32-bit) ++ * ++ * [ ] ------+ ++ * | ++ * +-------> [ ][ ]..[ ] (4096 byte page == 2048 counters) ++ * c1 c2 c2048 ++ * ++ * Hijacked case (page memory allocation failed): ++ * ++ * hijacked page pointer (32-bit) ++ * ++ * [ ][ ] (no page memory allocated) ++ * counter #1 (16-bit) counter #2 (16-bit) ++ * ++ */ ++ ++#ifdef __KERNEL__ ++ ++#define PAGE_BITS (PAGE_SIZE << 3) ++#define PAGE_BIT_SHIFT (PAGE_SHIFT + 3) ++ ++typedef __u16 bitmap_counter_t; ++#define COUNTER_BITS 16 ++#define COUNTER_BIT_SHIFT 4 ++#define COUNTER_BYTE_RATIO (COUNTER_BITS / 8) ++#define COUNTER_BYTE_SHIFT (COUNTER_BIT_SHIFT - 3) ++ ++#define NEEDED_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 1))) ++#define RESYNC_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 2))) ++#define COUNTER_MAX ((bitmap_counter_t) RESYNC_MASK - 1) ++#define NEEDED(x) (((bitmap_counter_t) x) & NEEDED_MASK) ++#define RESYNC(x) (((bitmap_counter_t) x) & RESYNC_MASK) ++#define COUNTER(x) (((bitmap_counter_t) x) & COUNTER_MAX) ++ ++/* how many counters per page? */ ++#define PAGE_COUNTER_RATIO (PAGE_BITS / COUNTER_BITS) ++/* same, except a shift value for more efficient bitops */ ++#define PAGE_COUNTER_SHIFT (PAGE_BIT_SHIFT - COUNTER_BIT_SHIFT) ++/* same, except a mask value for more efficient bitops */ ++#define PAGE_COUNTER_MASK (PAGE_COUNTER_RATIO - 1) ++ ++#define BITMAP_BLOCK_SIZE 512 ++#define BITMAP_BLOCK_SHIFT 9 ++ ++/* how many blocks per chunk? (this is variable) */ ++#define CHUNK_BLOCK_RATIO(bitmap) ((bitmap)->chunksize >> BITMAP_BLOCK_SHIFT) ++#define CHUNK_BLOCK_SHIFT(bitmap) ((bitmap)->chunkshift - BITMAP_BLOCK_SHIFT) ++#define CHUNK_BLOCK_MASK(bitmap) (CHUNK_BLOCK_RATIO(bitmap) - 1) ++ ++/* when hijacked, the counters and bits represent even larger "chunks" */ ++/* there will be 1024 chunks represented by each counter in the page pointers */ ++#define PAGEPTR_BLOCK_RATIO(bitmap) \ ++ (CHUNK_BLOCK_RATIO(bitmap) << PAGE_COUNTER_SHIFT >> 1) ++#define PAGEPTR_BLOCK_SHIFT(bitmap) \ ++ (CHUNK_BLOCK_SHIFT(bitmap) + PAGE_COUNTER_SHIFT - 1) ++#define PAGEPTR_BLOCK_MASK(bitmap) (PAGEPTR_BLOCK_RATIO(bitmap) - 1) ++ ++/* ++ * on-disk bitmap: ++ * ++ * Use one bit per "chunk" (block set). We do the disk I/O on the bitmap ++ * file a page at a time. There's a superblock at the start of the file. ++ */ ++ ++/* map chunks (bits) to file pages - offset by the size of the superblock */ ++#define CHUNK_BIT_OFFSET(chunk) ((chunk) + (sizeof(bitmap_super_t) << 3)) ++ ++#endif ++ ++/* ++ * bitmap structures: ++ */ ++ ++#define BITMAP_MAGIC 0x6d746962 ++ ++/* use these for bitmap->flags and bitmap->sb->state bit-fields */ ++enum bitmap_state { ++ BITMAP_ACTIVE = 0x001, /* the bitmap is in use */ ++ BITMAP_STALE = 0x002 /* the bitmap file is out of date or had -EIO */ ++}; ++ ++/* the superblock at the front of the bitmap file -- little endian */ ++typedef struct bitmap_super_s { ++ __u32 magic; /* 0 BITMAP_MAGIC */ ++ __u32 version; /* 4 the bitmap major for now, could change... */ ++ __u8 uuid[16]; /* 8 128 bit uuid - must match md device uuid */ ++ __u64 events; /* 24 event counter for the bitmap (1)*/ ++ __u64 events_cleared;/*32 event counter when last bit cleared (2) */ ++ __u64 sync_size; /* 40 the size of the md device's sync range(3) */ ++ __u32 state; /* 48 bitmap state information */ ++ __u32 chunksize; /* 52 the bitmap chunk size in bytes */ ++ __u32 daemon_sleep; /* 56 seconds between disk flushes */ ++ __u32 write_behind; /* 60 number of outstanding write-behind writes */ ++ ++ __u8 pad[256 - 64]; /* set to zero */ ++} bitmap_super_t; ++ ++/* notes: ++ * (1) This event counter is updated before the eventcounter in the md superblock ++ * When a bitmap is loaded, it is only accepted if this event counter is equal ++ * to, or one greater than, the event counter in the superblock. ++ * (2) This event counter is updated when the other one is *if*and*only*if* the ++ * array is not degraded. As bits are not cleared when the array is degraded, ++ * this represents the last time that any bits were cleared. ++ * If a device is being added that has an event count with this value or ++ * higher, it is accepted as conforming to the bitmap. ++ * (3)This is the number of sectors represented by the bitmap, and is the range that ++ * resync happens across. For raid1 and raid5/6 it is the size of individual ++ * devices. For raid10 it is the size of the array. ++ */ ++ ++#ifdef __KERNEL__ ++ ++/* the in-memory bitmap is represented by bitmap_pages */ ++struct bitmap_page { ++ /* ++ * map points to the actual memory page ++ */ ++ char *map; ++ /* ++ * in emergencies (when map cannot be alloced), hijack the map ++ * pointer and use it as two counters itself ++ */ ++ unsigned int hijacked; ++ /* ++ * count of dirty bits on the page ++ */ ++ int count; ++}; ++ ++/* keep track of bitmap file pages that have pending writes on them */ ++struct page_list { ++ struct list_head list; ++ struct page *page; ++}; ++ ++/* the main bitmap structure - one per mddev */ ++struct bitmap { ++ struct bitmap_page *bp; ++ unsigned long pages; /* total number of pages in the bitmap */ ++ unsigned long missing_pages; /* number of pages not yet allocated */ ++ ++ mddev_t *mddev; /* the md device that the bitmap is for */ ++ ++ int counter_bits; /* how many bits per block counter */ ++ ++ /* bitmap chunksize -- how much data does each bit represent? */ ++ unsigned long chunksize; ++ unsigned long chunkshift; /* chunksize = 2^chunkshift (for bitops) */ ++ unsigned long chunks; /* total number of data chunks for the array */ ++ ++ /* We hold a count on the chunk currently being synced, and drop ++ * it when the last block is started. If the resync is aborted ++ * midway, we need to be able to drop that count, so we remember ++ * the counted chunk.. ++ */ ++ unsigned long syncchunk; ++ ++ __u64 events_cleared; ++ ++ /* bitmap spinlock */ ++ spinlock_t lock; ++ ++ struct file *file; /* backing disk file */ ++ struct page *sb_page; /* cached copy of the bitmap file superblock */ ++ struct page **filemap; /* list of cache pages for the file */ ++ unsigned long *filemap_attr; /* attributes associated w/ filemap pages */ ++ unsigned long file_pages; /* number of pages in the file */ ++ ++ unsigned long flags; ++ ++ /* ++ * the bitmap daemon - periodically wakes up and sweeps the bitmap ++ * file, cleaning up bits and flushing out pages to disk as necessary ++ */ ++ mdk_thread_t *daemon; ++ unsigned long daemon_sleep; /* how many seconds between updates? */ ++ ++ /* ++ * bitmap write daemon - this daemon performs writes to the bitmap file ++ * this thread is only needed because of a limitation in ext3 (jbd) ++ * that does not allow a task to have two journal transactions ongoing ++ * simultaneously (even if the transactions are for two different ++ * filesystems) -- in the case of bitmap, that would be the filesystem ++ * that the bitmap file resides on and the filesystem that is mounted ++ * on the md device -- see current->journal_info in jbd/transaction.c ++ */ ++ mdk_thread_t *write_daemon; ++ mdk_thread_t *writeback_daemon; ++ spinlock_t write_lock; ++ struct semaphore write_ready; ++ struct semaphore write_done; ++ unsigned long writes_pending; ++ wait_queue_head_t write_wait; ++ struct list_head write_pages; ++ struct list_head complete_pages; ++ mempool_t *write_pool; ++}; ++ ++/* the bitmap API */ ++ ++/* these are used only by md/bitmap */ ++int bitmap_create(mddev_t *mddev); ++void bitmap_destroy(mddev_t *mddev); ++int bitmap_active(struct bitmap *bitmap); ++ ++char *file_path(struct file *file, char *buf, int count); ++void bitmap_print_sb(struct bitmap *bitmap); ++int bitmap_update_sb(struct bitmap *bitmap); ++ ++int bitmap_setallbits(struct bitmap *bitmap); ++ ++/* these are exported */ ++void bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors); ++void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors, ++ int success); ++int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks); ++void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted); ++void bitmap_close_sync(struct bitmap *bitmap); ++ ++int bitmap_unplug(struct bitmap *bitmap); ++#endif ++ ++#endif +diff -pruN a/mdadm/config.c mdadm/mdadm/config.c +--- a/mdadm/config.c 1970-01-01 03:00:00.000000000 +0300 ++++ mdadm/mdadm/config.c 2011-01-12 21:33:01.000000000 +0200 +@@ -0,0 +1,824 @@ ++/* ++ * mdadm - manage Linux "md" devices aka RAID arrays. ++ * ++ * Copyright (C) 2001-2006 Neil Brown ++ * ++ * ++ * 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 ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * Author: Neil Brown ++ * Email: ++ * Paper: Neil Brown ++ * School of Computer Science and Engineering ++ * The University of New South Wales ++ * Sydney, 2052 ++ * Australia ++ */ ++ ++#include "mdadm.h" ++#include "dlink.h" ++#include ++#include ++#include ++#include ++#include ++#include ++ ++mapping_t r5layout[] = { ++ { "left-asymmetric", 0}, ++ { "right-asymmetric", 1}, ++ { "left-symmetric", 2}, ++ { "right-symmetric", 3}, ++ ++ { "default", 2}, ++ { "la", 0}, ++ { "ra", 1}, ++ { "ls", 2}, ++ { "rs", 3}, ++ { NULL, 0} ++}; ++ ++mapping_t pers[] = { ++ { "linear", -1}, ++ { "raid0", 0}, ++ { "0", 0}, ++ { "stripe", 0}, ++ { "raid1", 1}, ++ { "1", 1}, ++ { "mirror", 1}, ++ { "raid4", 4}, ++ { "4", 4}, ++ { "raid5", 5}, ++ { "5", 5}, ++ { "multipath", -4}, ++ { "mp", -4}, ++ { "raid6", 6}, ++ { "6", 6}, ++ { "raid10", 10}, ++ { "10", 10}, ++ { "faulty", -5}, ++ { NULL, 0} ++}; ++/* ++ * Read the config file ++ * ++ * conf_get_uuids gets a list of devicename+uuid pairs ++ * conf_get_devs gets device names after expanding wildcards ++ * ++ * Each keeps the returned list and frees it when asked to make ++ * a new list. ++ * ++ * The format of the config file needs to be fairly extensible. ++ * Now, arrays only have names and uuids and devices merely are. ++ * But later arrays might want names, and devices might want superblock ++ * versions, and who knows what else. ++ * I like free format, abhore backslash line continuation, adore ++ * indentation for structure and am ok about # comments. ++ * ++ * So, each line that isn't blank or a #comment must either start ++ * with a key word, and not be indented, or must start with a ++ * non-key-word and must be indented. ++ * ++ * Keywords are DEVICE and ARRAY ++ * DEV{ICE} introduces some devices that might contain raid components. ++ * e.g. ++ * DEV style=0 /dev/sda* /dev/hd* ++ * DEV style=1 /dev/sd[b-f]* ++ * ARR{AY} describes an array giving md device and attributes like uuid=whatever ++ * e.g. ++ * ARRAY /dev/md0 uuid=whatever name=something ++ * Spaces separate words on each line. Quoting, with "" or '' protects them, ++ * but may not wrap over lines ++ * ++ */ ++ ++#ifndef CONFFILE ++#define CONFFILE "/etc/mdadm.conf" ++#endif ++#ifndef CONFFILE2 ++/* for Debian compatibility .... */ ++#define CONFFILE2 "/etc/mdadm/mdadm.conf" ++#endif ++char DefaultConfFile[] = CONFFILE; ++char DefaultAltConfFile[] = CONFFILE2; ++ ++enum linetype { Devices, Array, Mailaddr, Mailfrom, Program, CreateDev, Homehost, LTEnd }; ++char *keywords[] = { ++ [Devices] = "devices", ++ [Array] = "array", ++ [Mailaddr] = "mailaddr", ++ [Mailfrom] = "mailfrom", ++ [Program] = "program", ++ [CreateDev]= "create", ++ [Homehost] = "homehost", ++ [LTEnd] = NULL ++}; ++ ++/* ++ * match_keyword returns an index into the keywords array, or -1 for no match ++ * case is ignored, and at least three characters must be given ++ */ ++ ++int match_keyword(char *word) ++{ ++ int len = strlen(word); ++ int n; ++ ++ if (len < 3) return -1; ++ for (n=0; keywords[n]; n++) { ++ if (strncasecmp(word, keywords[n], len)==0) ++ return n; ++ } ++ return -1; ++} ++ ++/* conf_word gets one word from the conf file. ++ * if "allow_key", then accept words at the start of a line, ++ * otherwise stop when such a word is found. ++ * We assume that the file pointer is at the end of a word, so the ++ * next character is a space, or a newline. If not, it is the start of a line. ++ */ ++ ++char *conf_word(FILE *file, int allow_key) ++{ ++ int wsize = 100; ++ int len = 0; ++ int c; ++ int quote; ++ int wordfound = 0; ++ char *word = malloc(wsize); ++ ++ if (!word) abort(); ++ ++ while (wordfound==0) { ++ /* at the end of a word.. */ ++ c = getc(file); ++ if (c == '#') ++ while (c != EOF && c != '\n') ++ c = getc(file); ++ if (c == EOF) break; ++ if (c == '\n') continue; ++ ++ if (c != ' ' && c != '\t' && ! allow_key) { ++ ungetc(c, file); ++ break; ++ } ++ /* looks like it is safe to get a word here, if there is one */ ++ quote = 0; ++ /* first, skip any spaces */ ++ while (c == ' ' || c == '\t') ++ c = getc(file); ++ if (c != EOF && c != '\n' && c != '#') { ++ /* we really have a character of a word, so start saving it */ ++ while (c != EOF && c != '\n' && (quote || (c!=' ' && c != '\t'))) { ++ wordfound = 1; ++ if (quote && c == quote) quote = 0; ++ else if (quote == 0 && (c == '\'' || c == '"')) ++ quote = c; ++ else { ++ if (len == wsize-1) { ++ wsize += 100; ++ word = realloc(word, wsize); ++ if (!word) abort(); ++ } ++ word[len++] = c; ++ } ++ c = getc(file); ++ } ++ } ++ if (c != EOF) ungetc(c, file); ++ } ++ word[len] = 0; ++/* printf("word is <%s>\n", word); */ ++ if (!wordfound) { ++ free(word); ++ word = NULL; ++ } ++ return word; ++} ++ ++/* ++ * conf_line reads one logical line from the conffile. ++ * It skips comments and continues until it finds a line that starts ++ * with a non blank/comment. This character is pushed back for the next call ++ * A doubly linked list of words is returned. ++ * the first word will be a keyword. Other words will have had quotes removed. ++ */ ++ ++char *conf_line(FILE *file) ++{ ++ char *w; ++ char *list; ++ ++ w = conf_word(file, 1); ++ if (w == NULL) return NULL; ++ ++ list = dl_strdup(w); ++ free(w); ++ dl_init(list); ++ ++ while ((w = conf_word(file,0))){ ++ char *w2 = dl_strdup(w); ++ free(w); ++ dl_add(list, w2); ++ } ++/* printf("got a line\n");*/ ++ return list; ++} ++ ++void free_line(char *line) ++{ ++ char *w; ++ for (w=dl_next(line); w != line; w=dl_next(line)) { ++ dl_del(w); ++ dl_free(w); ++ } ++ dl_free(line); ++} ++ ++ ++struct conf_dev { ++ struct conf_dev *next; ++ char *name; ++} *cdevlist = NULL; ++ ++mddev_dev_t load_partitions(void) ++{ ++ FILE *f = fopen("/proc/partitions", "r"); ++ char buf[1024]; ++ mddev_dev_t rv = NULL; ++ if (f == NULL) { ++ fprintf(stderr, Name ": cannot open /proc/partitions\n"); ++ return NULL; ++ } ++ while (fgets(buf, 1024, f)) { ++ int major, minor; ++ char *name, *mp; ++ mddev_dev_t d; ++ ++ buf[1023] = '\0'; ++ if (buf[0] != ' ') ++ continue; ++ major = strtoul(buf, &mp, 10); ++ if (mp == buf || *mp != ' ') ++ continue; ++ minor = strtoul(mp, NULL, 10); ++ ++ name = map_dev(major, minor, 1); ++ if (!name) ++ continue; ++ d = malloc(sizeof(*d)); ++ d->devname = strdup(name); ++ d->next = rv; ++ d->used = 0; ++ rv = d; ++ } ++ fclose(f); ++ return rv; ++} ++ ++struct createinfo createinfo = { ++ .autof = 2, /* by default, create devices with standard names */ ++ .symlinks = 1, ++#ifdef DEBIAN ++ .gid = 6, /* disk */ ++ .mode = 0660, ++#else ++ .mode = 0600, ++#endif ++}; ++ ++int parse_auto(char *str, char *msg, int config) ++{ ++ int autof; ++ if (str == NULL || *str == 0) ++ autof = 2; ++ else if (strcasecmp(str,"no")==0) ++ autof = 1; ++ else if (strcasecmp(str,"yes")==0) ++ autof = 2; ++ else if (strcasecmp(str,"md")==0) ++ autof = config?5:3; ++ else { ++ /* There might be digits, and maybe a hypen, at the end */ ++ char *e = str + strlen(str); ++ int num = 4; ++ int len; ++ while (e > str && isdigit(e[-1])) ++ e--; ++ if (*e) { ++ num = atoi(e); ++ if (num <= 0) num = 1; ++ } ++ if (e > str && e[-1] == '-') ++ e--; ++ len = e - str; ++ if ((len == 2 && strncasecmp(str,"md",2)==0)) { ++ autof = config ? 5 : 3; ++ } else if ((len == 3 && strncasecmp(str,"yes",3)==0)) { ++ autof = 2; ++ } else if ((len == 3 && strncasecmp(str,"mdp",3)==0)) { ++ autof = config ? 6 : 4; ++ } else if ((len == 1 && strncasecmp(str,"p",1)==0) || ++ (len >= 4 && strncasecmp(str,"part",4)==0)) { ++ autof = 6; ++ } else { ++ fprintf(stderr, Name ": %s arg of \"%s\" unrecognised: use no,yes,md,mdp,part\n" ++ " optionally followed by a number.\n", ++ msg, str); ++ exit(2); ++ } ++ autof |= num << 3; ++ } ++ return autof; ++} ++ ++static void createline(char *line) ++{ ++ char *w; ++ char *ep; ++ ++ for (w=dl_next(line); w!=line; w=dl_next(w)) { ++ if (strncasecmp(w, "auto=", 5) == 0) ++ createinfo.autof = parse_auto(w+5, "auto=", 1); ++ else if (strncasecmp(w, "owner=", 6) == 0) { ++ if (w[6] == 0) { ++ fprintf(stderr, Name ": missing owner name\n"); ++ continue; ++ } ++ createinfo.uid = strtoul(w+6, &ep, 10); ++ if (*ep != 0) { ++ struct passwd *pw; ++ /* must be a name */ ++ pw = getpwnam(w+6); ++ if (pw) ++ createinfo.uid = pw->pw_uid; ++ else ++ fprintf(stderr, Name ": CREATE user %s not found\n", w+6); ++ } ++ } else if (strncasecmp(w, "group=", 6) == 0) { ++ if (w[6] == 0) { ++ fprintf(stderr, Name ": missing group name\n"); ++ continue; ++ } ++ createinfo.gid = strtoul(w+6, &ep, 10); ++ if (*ep != 0) { ++ struct group *gr; ++ /* must be a name */ ++ gr = getgrnam(w+6); ++ if (gr) ++ createinfo.gid = gr->gr_gid; ++ else ++ fprintf(stderr, Name ": CREATE group %s not found\n", w+6); ++ } ++ } else if (strncasecmp(w, "mode=", 5) == 0) { ++ if (w[5] == 0) { ++ fprintf(stderr, Name ": missing CREATE mode\n"); ++ continue; ++ } ++ createinfo.mode = strtoul(w+5, &ep, 8); ++ if (*ep != 0) { ++ createinfo.mode = 0600; ++ fprintf(stderr, Name ": unrecognised CREATE mode %s\n", ++ w+5); ++ } ++ } else if (strncasecmp(w, "metadata=", 9) == 0) { ++ /* style of metadata to use by default */ ++ int i; ++ for (i=0; superlist[i] && !createinfo.supertype; i++) ++ createinfo.supertype = ++ superlist[i]->match_metadata_desc(w+9); ++ if (!createinfo.supertype) ++ fprintf(stderr, Name ": metadata format %s unknown, ignoring\n", ++ w+9); ++ } else if (strncasecmp(w, "symlinks=yes", 12) == 0) ++ createinfo.symlinks = 1; ++ else if (strncasecmp(w, "symlinks=no", 11) == 0) ++ createinfo.symlinks = 0; ++ else { ++ fprintf(stderr, Name ": unrecognised word on CREATE line: %s\n", ++ w); ++ } ++ } ++} ++ ++void devline(char *line) ++{ ++ char *w; ++ struct conf_dev *cd; ++ ++ for (w=dl_next(line); w != line; w=dl_next(w)) { ++ if (w[0] == '/' || strcasecmp(w, "partitions") == 0) { ++ cd = malloc(sizeof(*cd)); ++ cd->name = strdup(w); ++ cd->next = cdevlist; ++ cdevlist = cd; ++ } else { ++ fprintf(stderr, Name ": unreconised word on DEVICE line: %s\n", ++ w); ++ } ++ } ++} ++ ++mddev_ident_t mddevlist = NULL; ++mddev_ident_t *mddevlp = &mddevlist; ++ ++void arrayline(char *line) ++{ ++ char *w; ++ ++ struct mddev_ident_s mis; ++ mddev_ident_t mi; ++ ++ mis.uuid_set = 0; ++ mis.super_minor = UnSet; ++ mis.level = UnSet; ++ mis.raid_disks = UnSet; ++ mis.spare_disks = 0; ++ mis.devices = NULL; ++ mis.devname = NULL; ++ mis.spare_group = NULL; ++ mis.autof = 0; ++ mis.next = NULL; ++ mis.st = NULL; ++ mis.bitmap_fd = -1; ++ mis.bitmap_file = NULL; ++ mis.name[0] = 0; ++ ++ for (w=dl_next(line); w!=line; w=dl_next(w)) { ++ if (w[0] == '/') { ++ if (mis.devname) ++ fprintf(stderr, Name ": only give one device per ARRAY line: %s and %s\n", ++ mis.devname, w); ++ else mis.devname = w; ++ } else if (strncasecmp(w, "uuid=", 5)==0 ) { ++ if (mis.uuid_set) ++ fprintf(stderr, Name ": only specify uuid once, %s ignored.\n", ++ w); ++ else { ++ if (parse_uuid(w+5, mis.uuid)) ++ mis.uuid_set = 1; ++ else ++ fprintf(stderr, Name ": bad uuid: %s\n", w); ++ } ++ } else if (strncasecmp(w, "super-minor=", 12)==0 ) { ++ if (mis.super_minor != UnSet) ++ fprintf(stderr, Name ": only specify super-minor once, %s ignored.\n", ++ w); ++ else { ++ char *endptr; ++ mis.super_minor= strtol(w+12, &endptr, 10); ++ if (w[12]==0 || endptr[0]!=0 || mis.super_minor < 0) { ++ fprintf(stderr, Name ": invalid super-minor number: %s\n", ++ w); ++ mis.super_minor = UnSet; ++ } ++ } ++ } else if (strncasecmp(w, "name=", 5)==0) { ++ if (mis.name[0]) ++ fprintf(stderr, Name ": only specify name once, %s ignored.\n", ++ w); ++ else if (strlen(w+5) > 32) ++ fprintf(stderr, Name ": name too long, ignoring %s\n", w); ++ else ++ strcpy(mis.name, w+5); ++ ++ } else if (strncasecmp(w, "bitmap=", 7) == 0) { ++ if (mis.bitmap_file) ++ fprintf(stderr, Name ": only specify bitmap file once. %s ignored\n", ++ w); ++ else ++ mis.bitmap_file = strdup(w+7); ++ ++ } else if (strncasecmp(w, "devices=", 8 ) == 0 ) { ++ if (mis.devices) ++ fprintf(stderr, Name ": only specify devices once (use a comma separated list). %s ignored\n", ++ w); ++ else ++ mis.devices = strdup(w+8); ++ } else if (strncasecmp(w, "spare-group=", 12) == 0 ) { ++ if (mis.spare_group) ++ fprintf(stderr, Name ": only specify one spare group per array. %s ignored.\n", ++ w); ++ else ++ mis.spare_group = strdup(w+12); ++ } else if (strncasecmp(w, "level=", 6) == 0 ) { ++ /* this is mainly for compatability with --brief output */ ++ mis.level = map_name(pers, w+6); ++ } else if (strncasecmp(w, "disks=", 6) == 0 ) { ++ /* again, for compat */ ++ mis.raid_disks = atoi(w+6); ++ } else if (strncasecmp(w, "num-devices=", 12) == 0 ) { ++ /* again, for compat */ ++ mis.raid_disks = atoi(w+12); ++ } else if (strncasecmp(w, "spares=", 7) == 0 ) { ++ /* for warning if not all spares present */ ++ mis.spare_disks = atoi(w+7); ++ } else if (strncasecmp(w, "metadata=", 9) == 0) { ++ /* style of metadata on the devices. */ ++ int i; ++ ++ for(i=0; superlist[i] && !mis.st; i++) ++ mis.st = superlist[i]->match_metadata_desc(w+9); ++ ++ if (!mis.st) ++ fprintf(stderr, Name ": metadata format %s unknown, ignored.\n", w+9); ++ } else if (strncasecmp(w, "auto=", 5) == 0 ) { ++ /* whether to create device special files as needed */ ++ mis.autof = parse_auto(w+5, "auto type", 0); ++ } else { ++ fprintf(stderr, Name ": unrecognised word on ARRAY line: %s\n", ++ w); ++ } ++ } ++ if (mis.devname == NULL) ++ fprintf(stderr, Name ": ARRAY line with no device\n"); ++ else if (mis.uuid_set == 0 && mis.devices == NULL && mis.super_minor == UnSet && mis.name[0] == 0) ++ fprintf(stderr, Name ": ARRAY line %s has no identity information.\n", mis.devname); ++ else { ++ mi = malloc(sizeof(*mi)); ++ *mi = mis; ++ mi->devname = strdup(mis.devname); ++ mi->next = NULL; ++ *mddevlp = mi; ++ mddevlp = &mi->next; ++ } ++} ++ ++static char *alert_email = NULL; ++void mailline(char *line) ++{ ++ char *w; ++ ++ for (w=dl_next(line); w != line ; w=dl_next(w)) { ++ if (alert_email == NULL) ++ alert_email = strdup(w); ++ else ++ fprintf(stderr, Name ": excess address on MAIL line: %s - ignored\n", ++ w); ++ } ++} ++ ++static char *alert_mail_from = NULL; ++void mailfromline(char *line) ++{ ++ char *w; ++ ++ for (w=dl_next(line); w != line ; w=dl_next(w)) { ++ if (alert_mail_from == NULL) ++ alert_mail_from = strdup(w); ++ else { ++ char *t= NULL; ++ asprintf(&t, "%s %s", alert_mail_from, w); ++ free(alert_mail_from); ++ alert_mail_from = t; ++ } ++ } ++} ++ ++ ++static char *alert_program = NULL; ++void programline(char *line) ++{ ++ char *w; ++ ++ for (w=dl_next(line); w != line ; w=dl_next(w)) { ++ if (alert_program == NULL) ++ alert_program = strdup(w); ++ else ++ fprintf(stderr, Name ": excess program on PROGRAM line: %s - ignored\n", ++ w); ++ } ++} ++ ++static char *home_host = NULL; ++void homehostline(char *line) ++{ ++ char *w; ++ ++ for (w=dl_next(line); w != line ; w=dl_next(w)) { ++ if (home_host == NULL) ++ home_host = strdup(w); ++ else ++ fprintf(stderr, Name ": excess host name on HOMEHOST line: %s - ignored\n", ++ w); ++ } ++} ++ ++ ++int loaded = 0; ++ ++static char *conffile = NULL; ++void set_conffile(char *file) ++{ ++ conffile = file; ++} ++ ++void load_conffile(void) ++{ ++ FILE *f; ++ char *line; ++ ++ if (loaded) return; ++ if (conffile == NULL) ++ conffile = DefaultConfFile; ++ ++ if (strcmp(conffile, "none") == 0) { ++ loaded = 1; ++ return; ++ } ++ if (strcmp(conffile, "partitions")==0) { ++ char *list = dl_strdup("DEV"); ++ dl_init(list); ++ dl_add(list, dl_strdup("partitions")); ++ devline(list); ++ free_line(list); ++ loaded = 1; ++ return; ++ } ++ f = fopen(conffile, "r"); ++ /* Debian chose to relocate mdadm.conf into /etc/mdadm/. ++ * To allow Debian users to compile from clean source and still ++ * have a working mdadm, we read /etc/mdadm/mdadm.conf ++ * if /etc/mdadm.conf doesn't exist ++ */ ++ if (f == NULL && ++ conffile == DefaultConfFile) { ++ f = fopen(DefaultAltConfFile, "r"); ++ if (f) ++ conffile = DefaultAltConfFile; ++ } ++ if (f == NULL) ++ return; ++ ++ loaded = 1; ++ while ((line=conf_line(f))) { ++ switch(match_keyword(line)) { ++ case Devices: ++ devline(line); ++ break; ++ case Array: ++ arrayline(line); ++ break; ++ case Mailaddr: ++ mailline(line); ++ break; ++ case Mailfrom: ++ mailfromline(line); ++ break; ++ case Program: ++ programline(line); ++ break; ++ case CreateDev: ++ createline(line); ++ break; ++ case Homehost: ++ homehostline(line); ++ break; ++ default: ++ fprintf(stderr, Name ": Unknown keyword %s\n", line); ++ } ++ free_line(line); ++ } ++ ++ fclose(f); ++ ++/* printf("got file\n"); */ ++} ++ ++char *conf_get_mailaddr(void) ++{ ++ load_conffile(); ++ return alert_email; ++} ++ ++char *conf_get_mailfrom(void) ++{ ++ load_conffile(); ++ return alert_mail_from; ++} ++ ++char *conf_get_program(void) ++{ ++ load_conffile(); ++ return alert_program; ++} ++ ++char *conf_get_homehost(void) ++{ ++ load_conffile(); ++ return home_host; ++} ++ ++struct createinfo *conf_get_create_info(void) ++{ ++ load_conffile(); ++ return &createinfo; ++} ++ ++mddev_ident_t conf_get_ident(char *dev) ++{ ++ mddev_ident_t rv; ++ load_conffile(); ++ rv = mddevlist; ++ while (dev && rv && strcmp(dev, rv->devname)!=0) ++ rv = rv->next; ++ return rv; ++} ++ ++mddev_dev_t conf_get_devs() ++{ ++ glob_t globbuf; ++ struct conf_dev *cd; ++ int flags = 0; ++ static mddev_dev_t dlist = NULL; ++ unsigned int i; ++ ++ while (dlist) { ++ mddev_dev_t t = dlist; ++ dlist = dlist->next; ++ free(t->devname); ++ free(t); ++ } ++ ++ load_conffile(); ++ ++ if (cdevlist == NULL) ++ /* default to 'partitions */ ++ dlist = load_partitions(); ++ ++ for (cd=cdevlist; cd; cd=cd->next) { ++ if (strcasecmp(cd->name, "partitions")==0 && dlist == NULL) ++ dlist = load_partitions(); ++ else { ++ glob(cd->name, flags, NULL, &globbuf); ++ flags |= GLOB_APPEND; ++ } ++ } ++ if (flags & GLOB_APPEND) { ++ for (i=0; idevname = strdup(globbuf.gl_pathv[i]); ++ t->next = dlist; ++ t->used = 0; ++ dlist = t; ++/* printf("one dev is %s\n", t->devname);*/ ++ } ++ globfree(&globbuf); ++ } ++ ++ return dlist; ++} ++ ++int conf_test_dev(char *devname) ++{ ++ struct conf_dev *cd; ++ if (cdevlist == NULL) ++ /* allow anything by default */ ++ return 1; ++ for (cd = cdevlist ; cd ; cd = cd->next) { ++ if (strcasecmp(cd->name, "partitions") == 0) ++ return 1; ++ if (fnmatch(cd->name, devname, FNM_PATHNAME) == 0) ++ return 1; ++ } ++ return 0; ++} ++ ++ ++int match_oneof(char *devices, char *devname) ++{ ++ /* check if one of the comma separated patterns in devices ++ * matches devname ++ */ ++ ++ ++ while (devices && *devices) { ++ char patn[1024]; ++ char *p = devices; ++ devices = strchr(devices, ','); ++ if (!devices) ++ devices = p + strlen(p); ++ if (devices-p < 1024) { ++ strncpy(patn, p, devices-p); ++ patn[devices-p] = 0; ++ if (fnmatch(patn, devname, FNM_PATHNAME)==0) ++ return 1; ++ } ++ if (*devices == ',') ++ devices++; ++ } ++ return 0; ++} +--- a/mdadm/Config.in 1970-01-01 03:00:00.000000000 +0300 ++++ mdadm/mdadm/Config.in 2011-01-12 21:33:01.000000000 +0200 +@@ -0,0 +1,15 @@ ++# ++# For a description of the syntax of this configuration file, ++# see scripts/kbuild/config-language.txt. ++# ++ ++menu "Linux mdadm Utilities" ++ ++config MDADM ++ bool "mdadm" ++ default n ++ help ++ assemble or examine raid array ++ ++endmenu ++ +--- a/mdadm/dlink.c 1970-01-01 03:00:00.000000000 +0300 ++++ mdadm/mdadm/dlink.c 2011-01-12 21:33:01.000000000 +0200 +@@ -0,0 +1,79 @@ ++ ++/* doubly linked lists */ ++/* This is free software. No strings attached. No copyright claimed */ ++ ++#include ++#include ++#include ++#ifdef __dietlibc__ ++char *strncpy(char *dest, const char *src, size_t n) __THROW; ++#endif ++#include "dlink.h" ++ ++ ++void *dl_head() ++{ ++ void *h; ++ h = dl_alloc(0); ++ dl_next(h) = h; ++ dl_prev(h) = h; ++ return h; ++} ++ ++void dl_free(void *v) ++{ ++ struct __dl_head *vv = v; ++ free(vv-1); ++} ++ ++void dl_init(void *v) ++{ ++ dl_next(v) = v; ++ dl_prev(v) = v; ++} ++ ++void dl_insert(void *head, void *val) ++{ ++ dl_next(val) = dl_next(head); ++ dl_prev(val) = head; ++ dl_next(dl_prev(val)) = val; ++ dl_prev(dl_next(val)) = val; ++} ++ ++void dl_add(void *head, void *val) ++{ ++ dl_prev(val) = dl_prev(head); ++ dl_next(val) = head; ++ dl_next(dl_prev(val)) = val; ++ dl_prev(dl_next(val)) = val; ++} ++ ++void dl_del(void *val) ++{ ++ if (dl_prev(val) == 0 || dl_next(val) == 0) ++ return; ++ dl_prev(dl_next(val)) = dl_prev(val); ++ dl_next(dl_prev(val)) = dl_next(val); ++ dl_prev(val) = dl_next(val) = 0; ++} ++ ++char *dl_strndup(char *s, int l) ++{ ++ char *n; ++ if (s == NULL) ++ return NULL; ++ n = dl_newv(char, l+1); ++ if (n == NULL) ++ return NULL; ++ else ++ { ++ strncpy(n, s, l); ++ n[l] = 0; ++ return n; ++ } ++} ++ ++char *dl_strdup(char *s) ++{ ++ return dl_strndup(s, (int)strlen(s)); ++} +--- a/mdadm/dlink.h 1970-01-01 03:00:00.000000000 +0300 ++++ mdadm/mdadm/dlink.h 2011-01-12 21:33:01.000000000 +0200 +@@ -0,0 +1,25 @@ ++ ++/* doubley linked lists */ ++/* This is free software. No strings attached. No copyright claimed */ ++ ++struct __dl_head ++{ ++ void * dh_prev; ++ void * dh_next; ++}; ++ ++#define dl_alloc(size) ((void*)(((char*)calloc(1,(size)+sizeof(struct __dl_head)))+sizeof(struct __dl_head))) ++#define dl_new(t) ((t*)dl_alloc(sizeof(t))) ++#define dl_newv(t,n) ((t*)dl_alloc(sizeof(t)*n)) ++ ++#define dl_next(p) *(&(((struct __dl_head*)(p))[-1].dh_next)) ++#define dl_prev(p) *(&(((struct __dl_head*)(p))[-1].dh_prev)) ++ ++void *dl_head(void); ++char *dl_strdup(char *); ++char *dl_strndup(char *, int); ++void dl_insert(void*, void*); ++void dl_add(void*, void*); ++void dl_del(void*); ++void dl_free(void*); ++void dl_init(void*); +--- a/mdadm/Kbuild 1970-01-01 03:00:00.000000000 +0300 ++++ mdadm/mdadm/Kbuild 2011-01-12 21:33:01.000000000 +0200 +@@ -0,0 +1,9 @@ ++# Makefile for busybox ++# ++# Copyright (C) 1999-2005 by Erik Andersen ++# ++# Licensed under the GPL v2, see the file LICENSE in this tarball. ++ ++lib-y:= ++MDADM-y:= config.o util.o dlink.o sha1.o super0.o super1.o mdexamine.o mdassemble.o ++lib-$(CONFIG_MDADM) += mdadm.o $(MDADM-y) +--- a/mdadm/md5.h 1970-01-01 03:00:00.000000000 +0300 ++++ mdadm/mdadm/md5.h 2011-01-12 21:33:01.000000000 +0200 +@@ -0,0 +1,134 @@ ++/* Declaration of functions and data types used for MD5 sum computing ++ library functions. ++ Copyright (C) 1995-1997,1999-2005 Free Software Foundation, Inc. ++ ++ NOTE: The canonical source of this file is maintained with the GNU C ++ Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. ++ ++ 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 the ++ Free Software Foundation; either version 2, or (at your option) any ++ later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software Foundation, ++ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ ++ ++#ifndef _MD5_H ++#define _MD5_H 1 ++ ++#include ++ ++# include ++#if HAVE_STDINT_H || _LIBC ++# include ++#endif ++ ++#ifndef __GNUC_PREREQ ++# if defined __GNUC__ && defined __GNUC_MINOR__ ++# define __GNUC_PREREQ(maj, min) \ ++ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) ++# else ++# define __GNUC_PREREQ(maj, min) 0 ++# endif ++#endif ++ ++#ifndef __THROW ++# if defined __cplusplus && __GNUC_PREREQ (2,8) ++# define __THROW throw () ++# else ++# define __THROW ++# endif ++#endif ++ ++#ifndef __attribute__ ++# if ! __GNUC_PREREQ (2,8) || __STRICT_ANSI__ ++# define __attribute__(x) ++# endif ++#endif ++ ++#ifndef _LIBC ++# define __md5_buffer md5_buffer ++# define __md5_finish_ctx md5_finish_ctx ++# define __md5_init_ctx md5_init_ctx ++# define __md5_process_block md5_process_block ++# define __md5_process_bytes md5_process_bytes ++# define __md5_read_ctx md5_read_ctx ++# define __md5_stream md5_stream ++#endif ++ ++typedef uint32_t md5_uint32; ++ ++/* Structure to save state of computation between the single steps. */ ++struct md5_ctx ++{ ++ md5_uint32 A; ++ md5_uint32 B; ++ md5_uint32 C; ++ md5_uint32 D; ++ ++ md5_uint32 total[2]; ++ md5_uint32 buflen; ++ char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32)))); ++}; ++ ++/* ++ * The following three functions are build up the low level used in ++ * the functions `md5_stream' and `md5_buffer'. ++ */ ++ ++/* Initialize structure containing state of computation. ++ (RFC 1321, 3.3: Step 3) */ ++extern void __md5_init_ctx (struct md5_ctx *ctx) __THROW; ++ ++/* Starting with the result of former calls of this function (or the ++ initialization function update the context for the next LEN bytes ++ starting at BUFFER. ++ It is necessary that LEN is a multiple of 64!!! */ ++extern void __md5_process_block (const void *buffer, size_t len, ++ struct md5_ctx *ctx) __THROW; ++ ++/* Starting with the result of former calls of this function (or the ++ initialization function update the context for the next LEN bytes ++ starting at BUFFER. ++ It is NOT required that LEN is a multiple of 64. */ ++extern void __md5_process_bytes (const void *buffer, size_t len, ++ struct md5_ctx *ctx) __THROW; ++ ++/* Process the remaining bytes in the buffer and put result from CTX ++ in first 16 bytes following RESBUF. The result is always in little ++ endian byte order, so that a byte-wise output yields to the wanted ++ ASCII representation of the message digest. ++ ++ IMPORTANT: On some systems it is required that RESBUF be correctly ++ aligned for a 32 bits value. */ ++extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) __THROW; ++ ++ ++/* Put result from CTX in first 16 bytes following RESBUF. The result is ++ always in little endian byte order, so that a byte-wise output yields ++ to the wanted ASCII representation of the message digest. ++ ++ IMPORTANT: On some systems it is required that RESBUF is correctly ++ aligned for a 32 bits value. */ ++extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) __THROW; ++ ++ ++/* Compute MD5 message digest for bytes read from STREAM. The ++ resulting message digest number will be written into the 16 bytes ++ beginning at RESBLOCK. */ ++extern int __md5_stream (FILE *stream, void *resblock) __THROW; ++ ++/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The ++ result is always in little endian byte order, so that a byte-wise ++ output yields to the wanted ASCII representation of the message ++ digest. */ ++extern void *__md5_buffer (const char *buffer, size_t len, ++ void *resblock) __THROW; ++ ++#endif /* md5.h */ +--- a/mdadm/mdadm.c 1970-01-01 03:00:00.000000000 +0300 ++++ mdadm/mdadm/mdadm.c 2011-01-12 21:33:01.000000000 +0200 +@@ -0,0 +1,18 @@ ++/* ++ * mdadm support for busybox. ++ * added by Alan Hourihane ++ */ ++#include ++ ++extern int mdassemble_main(int argc, char **argv); ++extern int mdexamine_main(int argc, char **argv); ++ ++int mdadm_main(int argc, char **argv) { ++ if (argc >= 2) { ++ if (!strncmp(argv[1],"--assemble",10)) ++ return mdassemble_main(argc, argv); ++ if (!strncmp(argv[1],"--examine",9)) ++ return mdexamine_main(argc, argv); ++ } ++ return 0; ++} +--- a/mdadm/mdadm.h 1970-01-01 03:00:00.000000000 +0300 ++++ mdadm/mdadm/mdadm.h 2011-01-12 21:33:01.000000000 +0200 +@@ -0,0 +1,540 @@ ++/* ++ * mdadm - manage Linux "md" devices aka RAID arrays. ++ * ++ * Copyright (C) 2001-2006 Neil Brown ++ * ++ * ++ * 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 ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * Author: Neil Brown ++ * Email: ++ * Paper: Neil Brown ++ * School of Computer Science and Engineering ++ * The University of New South Wales ++ * Sydney, 2052 ++ * Australia ++ */ ++ ++#include ++#ifndef __dietlibc__ ++extern __off64_t lseek64 __P ((int __fd, __off64_t __offset, int __whence)); ++#else ++# if defined(__NO_STAT64) || __WORDSIZE != 32 ++# define lseek64 lseek ++# endif ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef __dietlibc__ ++#include ++/* dietlibc has deprecated random and srandom!! */ ++#define random rand ++#define srandom srand ++#endif ++ ++ ++#include ++/*#include */ ++#include ++#include ++#include ++#define MD_MAJOR 9 ++#define MdpMinorShift 6 ++ ++#ifndef BLKGETSIZE64 ++#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */ ++#endif ++ ++#define DEFAULT_BITMAP_CHUNK 4096 ++#define DEFAULT_BITMAP_DELAY 5 ++#define DEFAULT_MAX_WRITE_BEHIND 256 ++ ++#include "md_u.h" ++#include "md_p.h" ++#include "bitmap.h" ++ ++#include ++/* Redhat don't like to #include , and ++ * some time include isn't enough, ++ * and there is no standard conversion function so... */ ++/* And dietlibc doesn't think byteswap is ok, so.. */ ++/* #include */ ++#define bswap_16(x) (((x) & 0x00ffU) << 8 | \ ++ ((x) & 0xff00U) >> 8) ++#define bswap_32(x) (((x) & 0x000000ffU) << 24 | \ ++ ((x) & 0xff000000U) >> 24 | \ ++ ((x) & 0x0000ff00U) << 8 | \ ++ ((x) & 0x00ff0000U) >> 8) ++#define bswap_64(x) (((x) & 0x00000000000000ffULL) << 56 | \ ++ ((x) & 0xff00000000000000ULL) >> 56 | \ ++ ((x) & 0x000000000000ff00ULL) << 40 | \ ++ ((x) & 0x00ff000000000000ULL) >> 40 | \ ++ ((x) & 0x0000000000ff0000ULL) << 24 | \ ++ ((x) & 0x0000ff0000000000ULL) >> 24 | \ ++ ((x) & 0x00000000ff000000ULL) << 8 | \ ++ ((x) & 0x000000ff00000000ULL) >> 8) ++ ++#if BYTE_ORDER == LITTLE_ENDIAN ++#define __cpu_to_le16(_x) (_x) ++#define __cpu_to_le32(_x) (_x) ++#define __cpu_to_le64(_x) (_x) ++#define __le16_to_cpu(_x) (_x) ++#define __le32_to_cpu(_x) (_x) ++#define __le64_to_cpu(_x) (_x) ++#elif BYTE_ORDER == BIG_ENDIAN ++#define __cpu_to_le16(_x) bswap_16(_x) ++#define __cpu_to_le32(_x) bswap_32(_x) ++#define __cpu_to_le64(_x) bswap_64(_x) ++#define __le16_to_cpu(_x) bswap_16(_x) ++#define __le32_to_cpu(_x) bswap_32(_x) ++#define __le64_to_cpu(_x) bswap_64(_x) ++#else ++# error "unknown endianness." ++#endif ++ ++ ++ ++/* general information that might be extracted from a superblock */ ++struct mdinfo { ++ mdu_array_info_t array; ++ mdu_disk_info_t disk; ++ __u64 events; ++ int uuid[4]; ++ char name[33]; ++ unsigned long long data_offset; ++ unsigned long long component_size; ++ int reshape_active; ++ unsigned long long reshape_progress; ++ int new_level, delta_disks, new_layout, new_chunk; ++}; ++ ++struct createinfo { ++ int uid; ++ int gid; ++ int autof; ++ int mode; ++ int symlinks; ++ struct supertype *supertype; ++}; ++ ++#define Name "mdadm" ++ ++enum mode { ++ ASSEMBLE=1, ++ BUILD, ++ CREATE, ++ MANAGE, ++ MISC, ++ MONITOR, ++ GROW, ++ INCREMENTAL, ++ AUTODETECT, ++}; ++ ++extern char short_options[]; ++extern char short_bitmap_auto_options[]; ++extern struct option long_options[]; ++extern char Version[], Usage[], Help[], OptionHelp[], ++ Help_create[], Help_build[], Help_assemble[], Help_grow[], ++ Help_incr[], ++ Help_manage[], Help_misc[], Help_monitor[], Help_config[]; ++ ++/* for option that don't have short equivilents, we assign arbitrary ++ * small numbers. '1' means an undecorated option, so we start at '2'. ++ */ ++enum special_options { ++ AssumeClean = 2, ++ BitmapChunk, ++ WriteBehind, ++ ReAdd, ++ NoDegraded, ++ Sparc22, ++ BackupFile, ++ HomeHost, ++ AutoHomeHost, ++ Symlinks, ++ AutoDetect, ++}; ++ ++/* structures read from config file */ ++/* List of mddevice names and identifiers ++ * Identifiers can be: ++ * uuid=128-hex-uuid ++ * super-minor=decimal-minor-number-from-superblock ++ * devices=comma,separated,list,of,device,names,with,wildcards ++ * ++ * If multiple fields are present, the intersection of all matching ++ * devices is considered ++ */ ++#define UnSet (0xfffe) ++typedef struct mddev_ident_s { ++ char *devname; ++ ++ int uuid_set; ++ int uuid[4]; ++ char name[33]; ++ ++ unsigned int super_minor; ++ ++ char *devices; /* comma separated list of device ++ * names with wild cards ++ */ ++ int level; ++ unsigned int raid_disks; ++ unsigned int spare_disks; ++ struct supertype *st; ++ int autof; /* 1 for normal, 2 for partitioned */ ++ char *spare_group; ++ char *bitmap_file; ++ int bitmap_fd; ++ ++ struct mddev_ident_s *next; ++} *mddev_ident_t; ++ ++/* List of device names - wildcards expanded */ ++typedef struct mddev_dev_s { ++ char *devname; ++ char disposition; /* 'a' for add, 'r' for remove, 'f' for fail. ++ * Not set for names read from .config ++ */ ++ char writemostly; ++ char re_add; ++ char used; /* set when used */ ++ struct mddev_dev_s *next; ++} *mddev_dev_t; ++ ++typedef struct mapping { ++ char *name; ++ int num; ++} mapping_t; ++ ++ ++struct mdstat_ent { ++ char *dev; ++ int devnum; ++ int active; ++ char *level; ++ char *pattern; /* U or up, _ for down */ ++ int percent; /* -1 if no resync */ ++ int resync; /* 1 if resync, 0 if recovery */ ++ struct mdstat_ent *next; ++}; ++ ++extern struct mdstat_ent *mdstat_read(int hold, int start); ++extern void free_mdstat(struct mdstat_ent *ms); ++extern void mdstat_wait(int seconds); ++extern int mddev_busy(int devnum); ++ ++struct map_ent { ++ struct map_ent *next; ++ int devnum; ++ int major,minor; ++ int uuid[4]; ++ char *path; ++}; ++extern int map_update(struct map_ent **mpp, int devnum, int major, int minor, ++ int uuid[4], char *path); ++extern struct map_ent *map_by_uuid(struct map_ent **map, int uuid[4]); ++extern void map_read(struct map_ent **melp); ++extern int map_write(struct map_ent *mel); ++extern void map_delete(struct map_ent **mapp, int devnum); ++extern void map_free(struct map_ent *map); ++extern void map_add(struct map_ent **melp, ++ int devnum, int major, int minor, int uuid[4], char *path); ++ ++/* Data structure for holding info read from sysfs */ ++struct sysdev { ++ char name[20]; ++ int role; ++ int major, minor; ++ unsigned long long offset, size; ++ int state; ++ int errors; ++ struct sysdev *next; ++}; ++struct sysarray { ++ char name[20]; ++ struct sysdev *devs; ++ int chunk; ++ unsigned long long component_size; ++ int layout; ++ int level; ++ int spares; ++ int cache_size; ++ int mismatch_cnt; ++ int major_version, minor_version; ++}; ++/* various details can be requested */ ++#define GET_LEVEL 1 ++#define GET_LAYOUT 2 ++#define GET_COMPONENT 4 ++#define GET_CHUNK 8 ++#define GET_CACHE 16 ++#define GET_MISMATCH 32 ++#define GET_VERSION 64 ++ ++#define GET_DEVS 1024 /* gets role, major, minor */ ++#define GET_OFFSET 2048 ++#define GET_SIZE 4096 ++#define GET_STATE 8192 ++#define GET_ERROR 16384 ++ ++/* If fd >= 0, get the array it is open on, ++ * else use devnum. >=0 -> major9. <0..... ++ */ ++extern void sysfs_free(struct sysarray *sra); ++extern struct sysarray *sysfs_read(int fd, int devnum, unsigned long options); ++extern int sysfs_set_str(struct sysarray *sra, struct sysdev *dev, ++ char *name, char *val); ++extern int sysfs_set_num(struct sysarray *sra, struct sysdev *dev, ++ char *name, unsigned long long val); ++extern int sysfs_get_ll(struct sysarray *sra, struct sysdev *dev, ++ char *name, unsigned long long *val); ++ ++ ++extern int save_stripes(int *source, unsigned long long *offsets, ++ int raid_disks, int chunk_size, int level, int layout, ++ int nwrites, int *dest, ++ unsigned long long start, unsigned long long length); ++extern int restore_stripes(int *dest, unsigned long long *offsets, ++ int raid_disks, int chunk_size, int level, int layout, ++ int source, unsigned long long read_offset, ++ unsigned long long start, unsigned long long length); ++ ++#ifndef Sendmail ++#define Sendmail "/usr/lib/sendmail -t" ++#endif ++ ++#define SYSLOG_FACILITY LOG_DAEMON ++ ++extern char *map_num(mapping_t *map, int num); ++extern int map_name(mapping_t *map, char *name); ++extern mapping_t r5layout[], pers[], modes[], faultylayout[]; ++ ++extern char *map_dev(int major, int minor, int create); ++ ++ ++extern struct superswitch { ++ void (*examine_super)(void *sbv, char *homehost); ++ void (*brief_examine_super)(void *sbv); ++ void (*detail_super)(void *sbv, char *homehost); ++ void (*export_super)(void *sbv); ++ void (*brief_detail_super)(void *sbv); ++ void (*uuid_from_super)(int uuid[4], void *sbv); ++ void (*getinfo_super)(struct mdinfo *info, void *sbv); ++ int (*match_home)(void *sbv, char *homehost); ++ int (*update_super)(struct mdinfo *info, void *sbv, char *update, ++ char *devname, int verbose, ++ int uuid_set, char *homehost); ++ int (*init_super)(struct supertype *st, void **sbp, mdu_array_info_t *info, unsigned long long size, char *name, char *homehost, int *uuid); ++ void (*add_to_super)(void *sbv, mdu_disk_info_t *dinfo); ++ int (*store_super)(struct supertype *st, int fd, void *sbv); ++ int (*write_init_super)(struct supertype *st, void *sbv, mdu_disk_info_t *dinfo, char *devname); ++ int (*compare_super)(void **firstp, void *secondv); ++ int (*load_super)(struct supertype *st, int fd, void **sbp, char *devname); ++ struct supertype * (*match_metadata_desc)(char *arg); ++ __u64 (*avail_size)(struct supertype *st, __u64 size); ++ int (*add_internal_bitmap)(struct supertype *st, void *sbv, int *chunkp, ++ int delay, int write_behind, ++ unsigned long long size, int may_change, int major); ++ void (*locate_bitmap)(struct supertype *st, int fd, void *sbv); ++ int (*write_bitmap)(struct supertype *st, int fd, void *sbv); ++ int major; ++ int swapuuid; /* true if uuid is bigending rather than hostendian */ ++} super0, super1, *superlist[]; ++ ++struct supertype { ++ struct superswitch *ss; ++ int minor_version; ++ int max_devs; ++}; ++ ++extern struct supertype *super_by_version(int vers, int minor); ++extern struct supertype *guess_super(int fd); ++extern int get_dev_size(int fd, char *dname, unsigned long long *sizep); ++extern void get_one_disk(int mdfd, mdu_array_info_t *ainf, ++ mdu_disk_info_t *disk); ++ ++#if __GNUC__ < 3 ++struct stat64; ++#endif ++ ++#define HAVE_NFTW we assume ++#define HAVE_FTW ++ ++#ifdef UCLIBC ++# include ++# ifndef __UCLIBC_HAS_FTW__ ++# undef HAVE_FTW ++# undef HAVE_NFTW ++# endif ++#endif ++ ++#ifdef __dietlibc__ ++# undef HAVE_NFTW ++#endif ++ ++#ifndef HAVE_NFTW ++# define FTW_PHYS 1 ++# ifndef HAVE_FTW ++ struct FTW {}; ++# endif ++#endif ++ ++#ifdef HAVE_FTW ++# include ++#endif ++ ++extern int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s); ++ ++ ++extern int Manage_ro(char *devname, int fd, int readonly); ++extern int Manage_runstop(char *devname, int fd, int runstop, int quiet); ++extern int Manage_resize(char *devname, int fd, long long size, int raid_disks); ++extern int Manage_reconfig(char *devname, int fd, int layout); ++extern int Manage_subdevs(char *devname, int fd, ++ mddev_dev_t devlist, int verbose); ++extern int autodetect(void); ++extern int Grow_Add_device(char *devname, int fd, char *newdev); ++extern int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int write_behind, int force); ++extern int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, ++ long long size, ++ int level, int layout, int chunksize, int raid_disks); ++extern int Grow_restart(struct supertype *st, struct mdinfo *info, ++ int *fdlist, int cnt, char *backup_file); ++ ++ ++extern int Assemble(struct supertype *st, char *mddev, int mdfd, ++ mddev_ident_t ident, ++ mddev_dev_t devlist, char *backup_file, ++ int readonly, int runstop, ++ char *update, char *homehost, ++ int verbose, int force); ++ ++extern int Build(char *mddev, int mdfd, int chunk, int level, int layout, ++ int raiddisks, ++ mddev_dev_t devlist, int assume_clean, ++ char *bitmap_file, int bitmap_chunk, int write_behind, int delay, int verbose); ++ ++ ++extern int Create(struct supertype *st, char *mddev, int mdfd, ++ int chunk, int level, int layout, unsigned long long size, int raiddisks, int sparedisks, ++ char *name, char *homehost, int *uuid, ++ int subdevs, mddev_dev_t devlist, ++ int runstop, int verbose, int force, int assume_clean, ++ char *bitmap_file, int bitmap_chunk, int write_behind, int delay); ++ ++extern int Detail(char *dev, int brief, int export, int test, char *homehost); ++extern int Query(char *dev); ++ ++extern int md_get_version(int fd); ++extern int get_linux_version(void); ++extern int parse_uuid(char *str, int uuid[4]); ++extern int check_ext2(int fd, char *name); ++extern int check_reiser(int fd, char *name); ++extern int check_raid(int fd, char *name); ++ ++extern int get_mdp_major(void); ++extern int dev_open(char *dev, int flags); ++extern int is_standard(char *dev, int *nump); ++ ++extern int parse_auto(char *str, char *msg, int config); ++extern mddev_ident_t conf_get_ident(char *dev); ++extern mddev_dev_t conf_get_devs(void); ++extern int conf_test_dev(char *devname); ++extern struct createinfo *conf_get_create_info(void); ++extern void set_conffile(char *file); ++extern char *conf_get_mailaddr(void); ++extern char *conf_get_mailfrom(void); ++extern char *conf_get_program(void); ++extern char *conf_get_homehost(void); ++extern char *conf_line(FILE *file); ++extern char *conf_word(FILE *file, int allow_key); ++extern void free_line(char *line); ++extern int match_oneof(char *devices, char *devname); ++extern void uuid_from_super(int uuid[4], mdp_super_t *super); ++extern int same_uuid(int a[4], int b[4], int swapuuid); ++extern void copy_uuid(void *a, int b[4], int swapuuid); ++/* extern int compare_super(mdp_super_t *first, mdp_super_t *second);*/ ++extern unsigned long calc_csum(void *super, int bytes); ++extern int enough(int level, int raid_disks, int layout, int clean, ++ char *avail, int avail_disks); ++extern int ask(char *mesg); ++extern unsigned long long get_component_size(int fd); ++extern void remove_partitions(int fd); ++ ++ ++extern char *human_size(long long bytes); ++char *human_size_brief(long long bytes); ++ ++extern void put_md_name(char *name); ++extern char *get_md_name(int dev); ++ ++extern char DefaultConfFile[]; ++ ++extern int open_mddev(char *dev, int autof); ++extern int open_mddev_devnum(char *devname, int devnum, char *name, ++ char *chosen_name); ++ ++ ++#define LEVEL_MULTIPATH (-4) ++#define LEVEL_LINEAR (-1) ++#define LEVEL_FAULTY (-5) ++ ++ ++/* faulty stuff */ ++ ++#define WriteTransient 0 ++#define ReadTransient 1 ++#define WritePersistent 2 ++#define ReadPersistent 3 ++#define WriteAll 4 /* doesn't go to device */ ++#define ReadFixable 5 ++#define Modes 6 ++ ++#define ClearErrors 31 ++#define ClearFaults 30 ++ ++#define AllPersist 100 /* internal use only */ ++#define NoPersist 101 ++ ++#define ModeMask 0x1f ++#define ModeShift 5 ++ ++ ++#ifdef __TINYC__ ++#undef minor ++#undef major ++#undef makedev ++#define minor(x) ((x)&0xff) ++#define major(x) (((x)>>8)&0xff) ++#define makedev(M,m) (((M)<<8) | (m)) ++#endif ++ ++/* for raid5 */ ++#define ALGORITHM_LEFT_ASYMMETRIC 0 ++#define ALGORITHM_RIGHT_ASYMMETRIC 1 ++#define ALGORITHM_LEFT_SYMMETRIC 2 ++#define ALGORITHM_RIGHT_SYMMETRIC 3 +--- a/mdadm/mdassemble.c 1970-01-01 03:00:00.000000000 +0300 ++++ mdadm/mdadm/mdassemble.c 2011-01-12 21:33:01.000000000 +0200 +@@ -0,0 +1,908 @@ ++/* ++ * mdadm - manage Linux "md" devices aka RAID arrays. ++ * ++ * Copyright (C) 2001-2006 Neil Brown ++ * ++ * ++ * 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 ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * Author: Neil Brown ++ * Email: ++ * Paper: Neil Brown ++ * School of Computer Science and Engineering ++ * The University of New South Wales ++ * Sydney, 2052 ++ * Australia ++ */ ++ ++#include "mdadm.h" ++#include ++ ++static int name_matches(char *found, char *required, char *homehost) ++{ ++ /* See if the name found matches the required name, possibly ++ * prefixed with 'homehost' ++ */ ++ char fnd[33]; ++ ++ strncpy(fnd, found, 32); ++ fnd[32] = 0; ++ if (strcmp(found, required)==0) ++ return 1; ++ if (homehost) { ++ int l = strlen(homehost); ++ if (l < 32 && fnd[l] == ':' && ++ strcmp(fnd+l+1, required)==0) ++ return 1; ++ } ++ return 0; ++} ++ ++int open_mddev(char *dev, int autof/*unused */) ++{ ++ int mdfd = open(dev, O_RDWR, 0); ++ if (mdfd < 0) ++ fprintf(stderr, Name ": error opening %s: %s\n", ++ dev, strerror(errno)); ++ else if (md_get_version(mdfd) <= 0) { ++ fprintf(stderr, Name ": %s does not appear to be an md device\n", ++ dev); ++ close(mdfd); ++ mdfd = -1; ++ } ++ return mdfd; ++} ++ ++int Assemble(struct supertype *st, char *mddev, int mdfd, ++ mddev_ident_t ident, ++ mddev_dev_t devlist, char *backup_file, ++ int readonly, int runstop, ++ char *update, char *homehost, ++ int verbose, int force) ++{ ++ /* ++ * The task of Assemble is to find a collection of ++ * devices that should (according to their superblocks) ++ * form an array, and to give this collection to the MD driver. ++ * In Linux-2.4 and later, this involves submitting a ++ * SET_ARRAY_INFO ioctl with no arg - to prepare ++ * the array - and then submit a number of ++ * ADD_NEW_DISK ioctls to add disks into ++ * the array. Finally RUN_ARRAY might ++ * be submitted to start the array. ++ * ++ * Much of the work of Assemble is in finding and/or ++ * checking the disks to make sure they look right. ++ * ++ * If mddev is not set, then scan must be set and we ++ * read through the config file for dev+uuid mapping ++ * We recurse, setting mddev, for each device that ++ * - isn't running ++ * - has a valid uuid (or any uuid if !uuidset) ++ * ++ * If mddev is set, we try to determine state of md. ++ * check version - must be at least 0.90.0 ++ * check kernel version. must be at least 2.4. ++ * If not, we can possibly fall back on START_ARRAY ++ * Try to GET_ARRAY_INFO. ++ * If possible, give up ++ * If not, try to STOP_ARRAY just to make sure ++ * ++ * If !uuidset and scan, look in conf-file for uuid ++ * If not found, give up ++ * If !devlist and scan and uuidset, get list of devs from conf-file ++ * ++ * For each device: ++ * Check superblock - discard if bad ++ * Check uuid (set if we don't have one) - discard if no match ++ * Check superblock similarity if we have a superblock - discard if different ++ * Record events, devicenum ++ * This should give us a list of devices for the array ++ * We should collect the most recent event number ++ * ++ * Count disks with recent enough event count ++ * While force && !enough disks ++ * Choose newest rejected disks, update event count ++ * mark clean and rewrite superblock ++ * If recent kernel: ++ * SET_ARRAY_INFO ++ * foreach device with recent events : ADD_NEW_DISK ++ * if runstop == 1 || "enough" disks and runstop==0 -> RUN_ARRAY ++ * If old kernel: ++ * Check the device numbers in superblock are right ++ * update superblock if any changes ++ * START_ARRAY ++ * ++ */ ++ int clean = 0; ++ int old_linux = 0; ++ int vers = 0; /* Keep gcc quite - it really is initialised */ ++ void *first_super = NULL, *super = NULL; ++ struct { ++ char *devname; ++ unsigned int major, minor; ++ unsigned int oldmajor, oldminor; ++ long long events; ++ int uptodate; ++ int state; ++ int raid_disk; ++ int disk_nr; ++ } *devices; ++ int *best = NULL; /* indexed by raid_disk */ ++ unsigned int bestcnt = 0; ++ int devcnt = 0; ++ unsigned int okcnt, sparecnt; ++ unsigned int req_cnt; ++ unsigned int i; ++ int most_recent = 0; ++ int chosen_drive; ++ int change = 0; ++ int inargv = 0; ++ int bitmap_done; ++ int start_partial_ok = (runstop >= 0) && (force || devlist==NULL || mdfd < 0); ++ unsigned int num_devs; ++ mddev_dev_t tmpdev; ++ struct mdinfo info; ++ char *avail; ++ int nextspare = 0; ++ ++ if (mdfd < 0) ++ return 2; ++ ++ if (get_linux_version() < 2004000) ++ old_linux = 1; ++ ++ if (mdfd >= 0) { ++ vers = md_get_version(mdfd); ++ if (vers <= 0) { ++ fprintf(stderr, Name ": %s appears not to be an md device.\n", mddev); ++ return 1; ++ } ++ if (vers < 9000) { ++ fprintf(stderr, Name ": Assemble requires driver version 0.90.0 or later.\n" ++ " Upgrade your kernel or try --build\n"); ++ return 1; ++ } ++ ++ if (ioctl(mdfd, GET_ARRAY_INFO, &info.array)>=0) { ++ fprintf(stderr, Name ": device %s already active - cannot assemble it\n", ++ mddev); ++ return 1; ++ } ++ ioctl(mdfd, STOP_ARRAY, NULL); /* just incase it was started but has no content */ ++ } ++ /* ++ * If any subdevs are listed, then any that don't ++ * match ident are discarded. Remainder must all match and ++ * become the array. ++ * If no subdevs, then we scan all devices in the config file, but ++ * there must be something in the identity ++ */ ++ ++ if (!devlist && ++ ident->uuid_set == 0 && ++ ident->super_minor < 0 && ++ ident->devices == NULL) { ++ fprintf(stderr, Name ": No identity information available for %s - cannot assemble.\n", ++ mddev ? mddev : "further assembly"); ++ return 1; ++ } ++ if (devlist == NULL) ++ devlist = conf_get_devs(); ++ else if (mdfd >= 0) ++ inargv = 1; ++ ++ tmpdev = devlist; num_devs = 0; ++ while (tmpdev) { ++ if (tmpdev->used) ++ tmpdev->used = 2; ++ else ++ num_devs++; ++ tmpdev = tmpdev->next; ++ } ++ devices = malloc(num_devs * sizeof(*devices)); ++ ++ if (!st && ident->st) st = ident->st; ++ ++ if (verbose>0) ++ fprintf(stderr, Name ": looking for devices for %s\n", ++ mddev ? mddev : "further assembly"); ++ ++ /* first walk the list of devices to find a consistent set ++ * that match the criterea, if that is possible. ++ * We flag the one we like with 'used'. ++ */ ++ for (tmpdev = devlist; ++ tmpdev; ++ tmpdev = tmpdev->next) { ++ char *devname = tmpdev->devname; ++ int dfd; ++ struct stat stb; ++ struct supertype *tst = st; ++ ++ if (tmpdev->used > 1) continue; ++ ++ if (ident->devices && ++ !match_oneof(ident->devices, devname)) { ++ if ((inargv && verbose>=0) || verbose > 0) ++ fprintf(stderr, Name ": %s is not one of %s\n", devname, ident->devices); ++ continue; ++ } ++ ++ if (super) { ++ free(super); ++ super = NULL; ++ } ++ ++ dfd = dev_open(devname, O_RDONLY|O_EXCL); ++ if (dfd < 0) { ++ if ((inargv && verbose >= 0) || verbose > 0) ++ fprintf(stderr, Name ": cannot open device %s: %s\n", ++ devname, strerror(errno)); ++ tmpdev->used = 2; ++ } else if (fstat(dfd, &stb)< 0) { ++ /* Impossible! */ ++ fprintf(stderr, Name ": fstat failed for %s: %s\n", ++ devname, strerror(errno)); ++ tmpdev->used = 2; ++ } else if ((stb.st_mode & S_IFMT) != S_IFBLK) { ++ fprintf(stderr, Name ": %s is not a block device.\n", ++ devname); ++ tmpdev->used = 2; ++ } else if (!tst && (tst = guess_super(dfd)) == NULL) { ++ if ((inargv && verbose >= 0) || verbose > 0) ++ fprintf(stderr, Name ": no recogniseable superblock on %s\n", ++ devname); ++ tmpdev->used = 2; ++ } else if (tst->ss->load_super(tst,dfd, &super, NULL)) { ++ if ((inargv && verbose >= 0) || verbose > 0) ++ fprintf( stderr, Name ": no RAID superblock on %s\n", ++ devname); ++ } else { ++ tst->ss->getinfo_super(&info, super); ++ } ++ if (dfd >= 0) close(dfd); ++ ++ if (ident->uuid_set && (!update || strcmp(update, "uuid")!= 0) && ++ (!super || same_uuid(info.uuid, ident->uuid, tst->ss->swapuuid)==0)) { ++ if ((inargv && verbose >= 0) || verbose > 0) ++ fprintf(stderr, Name ": %s has wrong uuid.\n", ++ devname); ++ continue; ++ } ++ if (ident->name[0] && (!update || strcmp(update, "name")!= 0) && ++ (!super || name_matches(info.name, ident->name, homehost)==0)) { ++ if ((inargv && verbose >= 0) || verbose > 0) ++ fprintf(stderr, Name ": %s has wrong name.\n", ++ devname); ++ continue; ++ } ++ if (ident->super_minor != UnSet && ++ (!super || ident->super_minor != info.array.md_minor)) { ++ if ((inargv && verbose >= 0) || verbose > 0) ++ fprintf(stderr, Name ": %s has wrong super-minor.\n", ++ devname); ++ continue; ++ } ++ if (ident->level != UnSet && ++ (!super|| ident->level != info.array.level)) { ++ if ((inargv && verbose >= 0) || verbose > 0) ++ fprintf(stderr, Name ": %s has wrong raid level.\n", ++ devname); ++ continue; ++ } ++ if (ident->raid_disks != UnSet && ++ (!super || ident->raid_disks!= info.array.raid_disks)) { ++ if ((inargv && verbose >= 0) || verbose > 0) ++ fprintf(stderr, Name ": %s requires wrong number of drives.\n", ++ devname); ++ continue; ++ } ++ if (mdfd < 0) { ++ if (tst == NULL || super == NULL) ++ continue; ++ if (update == NULL && ++ tst->ss->match_home(super, homehost)==0) { ++ if ((inargv && verbose >= 0) || verbose > 0) ++ fprintf(stderr, Name ": %s is not built for host %s.\n", ++ devname, homehost); ++ /* Auto-assemble, and this is not a usable host */ ++ /* if update != NULL, we are updating the host ++ * name... */ ++ continue; ++ } ++ } ++ /* If we are this far, then we are nearly commited to this device. ++ * If the super_block doesn't exist, or doesn't match others, ++ * then we probably cannot continue ++ * However if one of the arrays is for the homehost, and ++ * the other isn't that can disambiguate. ++ */ ++ ++ if (!super) { ++ fprintf(stderr, Name ": %s has no superblock - assembly aborted\n", ++ devname); ++ free(first_super); ++ return 1; ++ } ++ ++ if (st == NULL) ++ st = tst; ++ if (st->ss != tst->ss || ++ st->minor_version != tst->minor_version || ++ st->ss->compare_super(&first_super, super) != 0) { ++ /* Some mismatch. If exactly one array matches this host, ++ * we can resolve on that one. ++ * Or, if we are auto assembling, we just ignore the second ++ * for now. ++ */ ++ if (mdfd < 0) ++ continue; ++ if (homehost) { ++ int first = st->ss->match_home(first_super, homehost); ++ int last = tst->ss->match_home(super, homehost); ++ if (first+last == 1) { ++ /* We can do something */ ++ if (first) {/* just ignore this one */ ++ if ((inargv && verbose >= 0) || verbose > 0) ++ fprintf(stderr, Name ": %s misses out due to wrong homehost\n", ++ devname); ++ continue; ++ } else { /* reject all those sofar */ ++ mddev_dev_t td; ++ if ((inargv && verbose >= 0) || verbose > 0) ++ fprintf(stderr, Name ": %s overrides previous devices due to good homehost\n", ++ devname); ++ for (td=devlist; td != tmpdev; td=td->next) ++ if (td->used == 1) ++ td->used = 0; ++ tmpdev->used = 1; ++ continue; ++ } ++ } ++ } ++ fprintf(stderr, Name ": superblock on %s doesn't match others - assembly aborted\n", ++ devname); ++ free(super); ++ free(first_super); ++ return 1; ++ } ++ ++ tmpdev->used = 1; ++ } ++ ++ /* Ok, no bad inconsistancy, we can try updating etc */ ++ bitmap_done = 0; ++ for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) if (tmpdev->used == 1) { ++ char *devname = tmpdev->devname; ++ struct stat stb; ++ /* looks like a good enough match to update the super block if needed */ ++ { ++ int dfd; ++ dfd = dev_open(devname, O_RDWR|O_EXCL); ++ ++ remove_partitions(dfd); ++ ++ if (super) { ++ free(super); ++ super = NULL; ++ } ++ ++ st->ss->load_super(st, dfd, &super, NULL); ++ st->ss->getinfo_super(&info, super); ++ close(dfd); ++ } ++ ++ stat(devname, &stb); ++ ++ if (verbose > 0) ++ fprintf(stderr, Name ": %s is identified as a member of %s, slot %d.\n", ++ devname, mddev, info.disk.raid_disk); ++ devices[devcnt].devname = devname; ++ devices[devcnt].major = major(stb.st_rdev); ++ devices[devcnt].minor = minor(stb.st_rdev); ++ devices[devcnt].oldmajor = info.disk.major; ++ devices[devcnt].oldminor = info.disk.minor; ++ devices[devcnt].events = info.events; ++ devices[devcnt].raid_disk = info.disk.raid_disk; ++ devices[devcnt].disk_nr = info.disk.number; ++ devices[devcnt].uptodate = 0; ++ devices[devcnt].state = info.disk.state; ++ if (most_recent < devcnt) { ++ if (devices[devcnt].events ++ > devices[most_recent].events) ++ most_recent = devcnt; ++ } ++ if (info.array.level == -4) ++ /* with multipath, the raid_disk from the superblock is meaningless */ ++ i = devcnt; ++ else ++ i = devices[devcnt].raid_disk; ++ if (i+1 == 0) { ++ if (nextspare < info.array.raid_disks) ++ nextspare = info.array.raid_disks; ++ i = nextspare++; ++ } else { ++ if (i >= info.array.raid_disks && ++ i >= nextspare) ++ nextspare = i+1; ++ } ++ if (i < 10000) { ++ if (i >= bestcnt) { ++ unsigned int newbestcnt = i+10; ++ int *newbest = malloc(sizeof(int)*newbestcnt); ++ unsigned int c; ++ for (c=0; c < newbestcnt; c++) ++ if (c < bestcnt) ++ newbest[c] = best[c]; ++ else ++ newbest[c] = -1; ++ if (best)free(best); ++ best = newbest; ++ bestcnt = newbestcnt; ++ } ++ if (best[i] >=0 && ++ devices[best[i]].events == devices[devcnt].events && ++ devices[best[i]].minor != devices[devcnt].minor && ++ st->ss->major == 0 && ++ info.array.level != -4) { ++ /* two different devices with identical superblock. ++ * Could be a mis-detection caused by overlapping ++ * partitions. fail-safe. ++ */ ++ fprintf(stderr, Name ": WARNING %s and %s appear" ++ " to have very similar superblocks.\n" ++ " If they are really different, " ++ "please --zero the superblock on one\n" ++ " If they are the same or overlap," ++ " please remove one from %s.\n", ++ devices[best[i]].devname, devname, ++ inargv ? "the list" : ++ "the\n DEVICE list in mdadm.conf" ++ ); ++ return 1; ++ } ++ if (best[i] == -1 ++ || devices[best[i]].events < devices[devcnt].events) ++ best[i] = devcnt; ++ } ++ devcnt++; ++ } ++ ++ if (super) ++ free(super); ++ super = NULL; ++ ++ if (update && strcmp(update, "byteorder")==0) ++ st->minor_version = 90; ++ ++ if (devcnt == 0) { ++ fprintf(stderr, Name ": no devices found for %s\n", ++ mddev); ++ free(first_super); ++ return 1; ++ } ++ ++ st->ss->getinfo_super(&info, first_super); ++ clean = info.array.state & 1; ++ ++ /* now we have some devices that might be suitable. ++ * I wonder how many ++ */ ++ avail = malloc(info.array.raid_disks); ++ memset(avail, 0, info.array.raid_disks); ++ okcnt = 0; ++ sparecnt=0; ++ for (i=0; i< bestcnt ;i++) { ++ int j = best[i]; ++ int event_margin = 1; /* always allow a difference of '1' ++ * like the kernel does ++ */ ++ if (j < 0) continue; ++ /* note: we ignore error flags in multipath arrays ++ * as they don't make sense ++ */ ++ if (info.array.level != -4) ++ if (!(devices[j].state & (1<= ++ devices[most_recent].events) { ++ devices[j].uptodate = 1; ++ if (i < info.array.raid_disks) { ++ okcnt++; ++ avail[i]=1; ++ } else ++ sparecnt++; ++ } ++ } ++ while (force && !enough(info.array.level, info.array.raid_disks, ++ info.array.layout, 1, ++ avail, okcnt)) { ++ /* Choose the newest best drive which is ++ * not up-to-date, update the superblock ++ * and add it. ++ */ ++ int fd; ++ long long current_events; ++ chosen_drive = -1; ++ for (i=0; i=0 && ++ !devices[j].uptodate && ++ devices[j].events > 0 && ++ (chosen_drive < 0 || ++ devices[j].events > devices[chosen_drive].events)) ++ chosen_drive = j; ++ } ++ if (chosen_drive < 0) ++ break; ++ current_events = devices[chosen_drive].events; ++ add_another: ++ if (verbose >= 0) ++ fprintf(stderr, Name ": forcing event count in %s(%d) from %d upto %d\n", ++ devices[chosen_drive].devname, devices[chosen_drive].raid_disk, ++ (int)(devices[chosen_drive].events), ++ (int)(devices[most_recent].events)); ++ fd = dev_open(devices[chosen_drive].devname, O_RDWR|O_EXCL); ++ if (fd < 0) { ++ fprintf(stderr, Name ": Couldn't open %s for write - not updating\n", ++ devices[chosen_drive].devname); ++ devices[chosen_drive].events = 0; ++ continue; ++ } ++ if (st->ss->load_super(st,fd, &super, NULL)) { ++ close(fd); ++ fprintf(stderr, Name ": RAID superblock disappeared from %s - not updating.\n", ++ devices[chosen_drive].devname); ++ devices[chosen_drive].events = 0; ++ continue; ++ } ++ info.events = devices[most_recent].events; ++ st->ss->update_super(&info, super, "force-one", ++ devices[chosen_drive].devname, verbose, ++ 0, NULL); ++ ++ if (st->ss->store_super(st, fd, super)) { ++ close(fd); ++ fprintf(stderr, Name ": Could not re-write superblock on %s\n", ++ devices[chosen_drive].devname); ++ devices[chosen_drive].events = 0; ++ free(super); ++ continue; ++ } ++ close(fd); ++ devices[chosen_drive].events = devices[most_recent].events; ++ devices[chosen_drive].uptodate = 1; ++ avail[chosen_drive] = 1; ++ okcnt++; ++ free(super); ++ ++ /* If there are any other drives of the same vintage, ++ * add them in as well. We can't lose and we might gain ++ */ ++ for (i=0; i= 0 && ++ !devices[j].uptodate && ++ devices[j].events > 0 && ++ devices[j].events == current_events) { ++ chosen_drive = j; ++ goto add_another; ++ } ++ } ++ } ++ ++ /* Now we want to look at the superblock which the kernel will base things on ++ * and compare the devices that we think are working with the devices that the ++ * superblock thinks are working. ++ * If there are differences and --force is given, then update this chosen ++ * superblock. ++ */ ++ chosen_drive = -1; ++ super = NULL; ++ for (i=0; chosen_drive < 0 && iss->load_super(st,fd, &super, NULL)) { ++ close(fd); ++ fprintf(stderr, Name ": RAID superblock has disappeared from %s\n", ++ devices[j].devname); ++ return 1; ++ } ++ close(fd); ++ } ++ if (super == NULL) { ++ fprintf(stderr, Name ": No suitable drives found for %s\n", mddev); ++ return 1; ++ } ++ st->ss->getinfo_super(&info, super); ++ for (i=0; iss->update_super(&info, super, "assemble", NULL, verbose, 0, NULL)) { ++ if (force) { ++ if (verbose >= 0) ++ fprintf(stderr, Name ": " ++ "clearing FAULTY flag for device %d in %s for %s\n", ++ j, mddev, devices[j].devname); ++ change = 1; ++ } else { ++ if (verbose >= -1) ++ fprintf(stderr, Name ": " ++ "device %d in %s has wrong state in superblock, but %s seems ok\n", ++ i, mddev, devices[j].devname); ++ } ++ } ++#if 0 ++ if (!devices[j].uptodate && ++ !(super.disks[i].state & (1 << MD_DISK_FAULTY))) { ++ fprintf(stderr, Name ": devices %d of %s is not marked FAULTY in superblock, but cannot be found\n", ++ i, mddev); ++ } ++#endif ++ } ++ if (force && !clean && ++ !enough(info.array.level, info.array.raid_disks, ++ info.array.layout, clean, ++ avail, okcnt)) { ++ change += st->ss->update_super(&info, super, "force-array", ++ devices[chosen_drive].devname, verbose, ++ 0, NULL); ++ clean = 1; ++ } ++ ++ if (change) { ++ int fd; ++ fd = dev_open(devices[chosen_drive].devname, O_RDWR|O_EXCL); ++ if (fd < 0) { ++ fprintf(stderr, Name ": Could not open %s for write - cannot Assemble array.\n", ++ devices[chosen_drive].devname); ++ return 1; ++ } ++ if (st->ss->store_super(st, fd, super)) { ++ close(fd); ++ fprintf(stderr, Name ": Could not re-write superblock on %s\n", ++ devices[chosen_drive].devname); ++ return 1; ++ } ++ close(fd); ++ } ++ ++ /* count number of in-sync devices according to the superblock. ++ * We must have this number to start the array without -s or -R ++ */ ++ req_cnt = info.array.working_disks; ++ ++ /* Almost ready to actually *do* something */ ++ if (!old_linux) { ++ int rv; ++ if ((vers % 100) >= 1) { /* can use different versions */ ++ mdu_array_info_t inf; ++ memset(&inf, 0, sizeof(inf)); ++ inf.major_version = st->ss->major; ++ inf.minor_version = st->minor_version; ++ rv = ioctl(mdfd, SET_ARRAY_INFO, &inf); ++ } else ++ rv = ioctl(mdfd, SET_ARRAY_INFO, NULL); ++ ++ if (rv) { ++ fprintf(stderr, Name ": SET_ARRAY_INFO failed for %s: %s\n", ++ mddev, strerror(errno)); ++ return 1; ++ } ++ if (ident->bitmap_fd >= 0) { ++ if (ioctl(mdfd, SET_BITMAP_FILE, ident->bitmap_fd) != 0) { ++ fprintf(stderr, Name ": SET_BITMAP_FILE failed.\n"); ++ return 1; ++ } ++ } else if (ident->bitmap_file) { ++ /* From config file */ ++ int bmfd = open(ident->bitmap_file, O_RDWR); ++ if (bmfd < 0) { ++ fprintf(stderr, Name ": Could not open bitmap file %s\n", ++ ident->bitmap_file); ++ return 1; ++ } ++ if (ioctl(mdfd, SET_BITMAP_FILE, bmfd) != 0) { ++ fprintf(stderr, Name ": Failed to set bitmapfile for %s\n", mddev); ++ close(bmfd); ++ return 1; ++ } ++ close(bmfd); ++ } ++ ++ /* First, add the raid disks, but add the chosen one last */ ++ for (i=0; i<= bestcnt; i++) { ++ int j; ++ if (i < bestcnt) { ++ j = best[i]; ++ if (j == chosen_drive) ++ continue; ++ } else ++ j = chosen_drive; ++ ++ if (j >= 0 /* && devices[j].uptodate */) { ++ mdu_disk_info_t disk; ++ memset(&disk, 0, sizeof(disk)); ++ disk.major = devices[j].major; ++ disk.minor = devices[j].minor; ++ if (ioctl(mdfd, ADD_NEW_DISK, &disk)!=0) { ++ fprintf(stderr, Name ": failed to add %s to %s: %s\n", ++ devices[j].devname, ++ mddev, ++ strerror(errno)); ++ if (i < info.array.raid_disks || i == bestcnt) ++ okcnt--; ++ else ++ sparecnt--; ++ } else if (verbose > 0) ++ fprintf(stderr, Name ": added %s to %s as %d\n", ++ devices[j].devname, mddev, devices[j].raid_disk); ++ } else if (verbose > 0 && i < info.array.raid_disks) ++ fprintf(stderr, Name ": no uptodate device for slot %d of %s\n", ++ i, mddev); ++ } ++ ++ if (runstop == 1 || ++ (runstop <= 0 && ++ ( enough(info.array.level, info.array.raid_disks, ++ info.array.layout, clean, avail, okcnt) && ++ (okcnt >= req_cnt || start_partial_ok) ++ ))) { ++ if (ioctl(mdfd, RUN_ARRAY, NULL)==0) { ++ if (verbose >= 0) { ++ fprintf(stderr, Name ": %s has been started with %d drive%s", ++ mddev, okcnt, okcnt==1?"":"s"); ++ if (okcnt < info.array.raid_disks) ++ fprintf(stderr, " (out of %d)", info.array.raid_disks); ++ if (sparecnt) ++ fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s"); ++ fprintf(stderr, ".\n"); ++ } ++ return 0; ++ } ++ fprintf(stderr, Name ": failed to RUN_ARRAY %s: %s\n", ++ mddev, strerror(errno)); ++ ++ if (!enough(info.array.level, info.array.raid_disks, ++ info.array.layout, 1, avail, okcnt)) ++ fprintf(stderr, Name ": Not enough devices to " ++ "start the array.\n"); ++ else if (!enough(info.array.level, ++ info.array.raid_disks, ++ info.array.layout, clean, ++ avail, okcnt)) ++ fprintf(stderr, Name ": Not enough devices to " ++ "start the array while not clean " ++ "- consider --force.\n"); ++ ++ return 1; ++ } ++ if (runstop == -1) { ++ fprintf(stderr, Name ": %s assembled from %d drive%s", ++ mddev, okcnt, okcnt==1?"":"s"); ++ if (okcnt != info.array.raid_disks) ++ fprintf(stderr, " (out of %d)", info.array.raid_disks); ++ fprintf(stderr, ", but not started.\n"); ++ return 0; ++ } ++ if (verbose >= -1) { ++ fprintf(stderr, Name ": %s assembled from %d drive%s", mddev, okcnt, okcnt==1?"":"s"); ++ if (sparecnt) ++ fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s"); ++ if (!enough(info.array.level, info.array.raid_disks, ++ info.array.layout, 1, avail, okcnt)) ++ fprintf(stderr, " - not enough to start the array.\n"); ++ else if (!enough(info.array.level, ++ info.array.raid_disks, ++ info.array.layout, clean, ++ avail, okcnt)) ++ fprintf(stderr, " - not enough to start the " ++ "array while not clean - consider " ++ "--force.\n"); ++ else { ++ if (req_cnt == info.array.raid_disks) ++ fprintf(stderr, " - need all %d to start it", req_cnt); ++ else ++ fprintf(stderr, " - need %d of %d to start", req_cnt, info.array.raid_disks); ++ fprintf(stderr, " (use --run to insist).\n"); ++ } ++ } ++ return 1; ++ } else { ++ /* The "chosen_drive" is a good choice, and if necessary, the superblock has ++ * been updated to point to the current locations of devices. ++ * so we can just start the array ++ */ ++ unsigned long dev; ++ dev = makedev(devices[chosen_drive].major, ++ devices[chosen_drive].minor); ++ if (ioctl(mdfd, START_ARRAY, dev)) { ++ fprintf(stderr, Name ": Cannot start array: %s\n", ++ strerror(errno)); ++ } ++ ++ } ++ return 0; ++} ++ ++int mdfd = -1; ++int runstop = 0; ++int readonly = 0; ++int verbose = 0; ++int force = 0; ++ ++int mdassemble_main(int argc, char **argv) { ++ mddev_ident_t array_list = conf_get_ident(NULL); ++ int minor; ++ if (!array_list) { ++ fprintf(stderr, Name ": No arrays found in config file\n"); ++ return 1; ++ } else { ++ for (; array_list; array_list = array_list->next) { ++ mdu_array_info_t array; ++ if (!strncmp("/dev/md", array_list->devname, 7)) { ++ errno = 0; ++ minor = strtoul(array_list->devname + 7, NULL, 0); ++ if (!errno) { ++ mknod(array_list->devname, S_IFBLK|0600, makedev(MD_MAJOR, minor)); ++ } ++ } ++ mdfd = open_mddev(array_list->devname, array_list->autof); ++ if (mdfd < 0) { ++ ++ fprintf(stderr, Name ": failed to open array\n"); ++ continue; ++ } ++ if (ioctl(mdfd, GET_ARRAY_INFO, &array) < 0) { ++ Assemble(array_list->st, array_list->devname, mdfd, ++ array_list, NULL, NULL, ++ readonly, runstop, NULL, NULL, verbose, force); ++ } ++ close(mdfd); ++ } ++ } ++ return 0; ++} ++ +--- a/mdadm/mdexamine.c 1970-01-01 03:00:00.000000000 +0300 ++++ mdadm/mdadm/mdexamine.c 2011-01-12 21:33:01.000000000 +0200 +@@ -0,0 +1,157 @@ ++/* ++ * mdadm - manage Linux "md" devices aka RAID arrays. ++ * ++ * Copyright (C) 2001-2006 Neil Brown ++ * ++ * ++ * 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 ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * Author: Neil Brown ++ * Email: ++ * Paper: Neil Brown ++ * School of Computer Science and Engineering ++ * The University of New South Wales ++ * Sydney, 2052 ++ * Australia ++ */ ++ ++#include "mdadm.h" ++#include "dlink.h" ++ ++#if ! defined(__BIG_ENDIAN) && ! defined(__LITTLE_ENDIAN) ++#error no endian defined ++#endif ++#include "md_u.h" ++#include "md_p.h" ++ ++static int Examine(mddev_dev_t devlist, int brief, int scan, ++ int SparcAdjust, struct supertype *forcest, ++ char *homehost) ++{ ++ ++ /* Read the raid superblock from a device and ++ * display important content. ++ * ++ * If cannot be found, print reason: too small, bad magic ++ * ++ * Print: ++ * version, ctime, level, size, raid+spare+ ++ * prefered minor ++ * uuid ++ * ++ * utime, state etc ++ * ++ * If (brief) gather devices for same array and just print a mdadm.conf line including devices= ++ * if devlist==NULL, use conf_get_devs() ++ */ ++ int fd; ++ void *super = NULL; ++ int rv = 0; ++ int err = 0; ++ ++ struct array { ++ void *super; ++ struct supertype *st; ++ struct mdinfo info; ++ void *devs; ++ struct array *next; ++ int spares; ++ } *arrays = NULL; ++ ++ for (; devlist ; devlist=devlist->next) { ++ struct supertype *st = forcest; ++ ++ fd = dev_open(devlist->devname, O_RDONLY); ++ if (fd < 0) { ++ if (!scan) { ++ fprintf(stderr,Name ": cannot open %s: %s\n", ++ devlist->devname, strerror(errno)); ++ rv = 1; ++ } ++ err = 1; ++ } ++ else { ++ if (!st) ++ st = guess_super(fd); ++ if (st) ++ err = st->ss->load_super(st, fd, &super, (brief||scan)?NULL:devlist->devname); ++ else { ++ if (!brief) { ++ fprintf(stderr, Name ": No md superblock detected on %s.\n", devlist->devname); ++ rv = 1; ++ } ++ err = 1; ++ } ++ close(fd); ++ } ++ if (err) ++ continue; ++ ++ if (SparcAdjust) ++ st->ss->update_super(NULL, super, "sparc2.2", devlist->devname, 0, 0, NULL); ++ /* Ok, its good enough to try, though the checksum could be wrong */ ++ if (brief) { ++ struct array *ap; ++ char *d; ++ for (ap=arrays; ap; ap=ap->next) { ++ if (st->ss == ap->st->ss && st->ss->compare_super(&ap->super, super)==0) ++ break; ++ } ++ if (!ap) { ++ ap = malloc(sizeof(*ap)); ++ ap->super = super; ++ ap->devs = dl_head(); ++ ap->next = arrays; ++ ap->spares = 0; ++ ap->st = st; ++ arrays = ap; ++ st->ss->getinfo_super(&ap->info, super); ++ } else { ++ st->ss->getinfo_super(&ap->info, super); ++ free(super); ++ } ++ if (!(ap->info.disk.state & MD_DISK_SYNC)) ++ ap->spares++; ++ d = dl_strdup(devlist->devname); ++ dl_add(ap->devs, d); ++ } ++ } ++ if (brief) { ++ struct array *ap; ++ for (ap=arrays; ap; ap=ap->next) { ++ char sep='='; ++ char *d; ++ ap->st->ss->brief_examine_super(ap->super); ++ if (ap->spares) printf(" spares=%d", ap->spares); ++ if (brief > 1) { ++ printf(" devices"); ++ for (d=dl_next(ap->devs); d!= ap->devs; d=dl_next(d)) { ++ printf("%c%s", sep, d); ++ sep=','; ++ } ++ } ++ free(ap->super); ++ /* FIXME free ap */ ++ if (ap->spares || brief > 1) ++ printf("\n"); ++ } ++ } ++ return rv; ++} ++ ++int mdexamine_main(int argc, char **argv) { ++ return Examine(conf_get_devs(), 1, 0, 0, NULL, NULL); ++} ++ +--- a/mdadm/md_p.h 1970-01-01 03:00:00.000000000 +0300 ++++ mdadm/mdadm/md_p.h 2011-01-12 21:33:01.000000000 +0200 +@@ -0,0 +1,194 @@ ++/* ++ md_p.h : physical layout of Linux RAID devices ++ Copyright (C) 1996-98 Ingo Molnar, Gadi Oxman ++ ++ 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 ++ the Free Software Foundation; either version 2, or (at your option) ++ any later version. ++ ++ You should have received a copy of the GNU General Public License ++ (for example /usr/src/linux/COPYING); if not, write to the Free ++ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++#ifndef _MD_P_H ++#define _MD_P_H ++ ++/* ++ * RAID superblock. ++ * ++ * The RAID superblock maintains some statistics on each RAID configuration. ++ * Each real device in the RAID set contains it near the end of the device. ++ * Some of the ideas are copied from the ext2fs implementation. ++ * ++ * We currently use 4096 bytes as follows: ++ * ++ * word offset function ++ * ++ * 0 - 31 Constant generic RAID device information. ++ * 32 - 63 Generic state information. ++ * 64 - 127 Personality specific information. ++ * 128 - 511 12 32-words descriptors of the disks in the raid set. ++ * 512 - 911 Reserved. ++ * 912 - 1023 Disk specific descriptor. ++ */ ++ ++/* ++ * If x is the real device size in bytes, we return an apparent size of: ++ * ++ * y = (x & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES ++ * ++ * and place the 4kB superblock at offset y. ++ */ ++#define MD_RESERVED_BYTES (64 * 1024) ++#define MD_RESERVED_SECTORS (MD_RESERVED_BYTES / 512) ++#define MD_RESERVED_BLOCKS (MD_RESERVED_BYTES / BLOCK_SIZE) ++ ++#define MD_NEW_SIZE_SECTORS(x) ((x & ~(MD_RESERVED_SECTORS - 1)) - MD_RESERVED_SECTORS) ++#define MD_NEW_SIZE_BLOCKS(x) ((x & ~(MD_RESERVED_BLOCKS - 1)) - MD_RESERVED_BLOCKS) ++ ++#define MD_SB_BYTES 4096 ++#define MD_SB_WORDS (MD_SB_BYTES / 4) ++#define MD_SB_BLOCKS (MD_SB_BYTES / BLOCK_SIZE) ++#define MD_SB_SECTORS (MD_SB_BYTES / 512) ++ ++/* ++ * The following are counted in 32-bit words ++ */ ++#define MD_SB_GENERIC_OFFSET 0 ++#define MD_SB_PERSONALITY_OFFSET 64 ++#define MD_SB_DISKS_OFFSET 128 ++#define MD_SB_DESCRIPTOR_OFFSET 992 ++ ++#define MD_SB_GENERIC_CONSTANT_WORDS 32 ++#define MD_SB_GENERIC_STATE_WORDS 32 ++#define MD_SB_GENERIC_WORDS (MD_SB_GENERIC_CONSTANT_WORDS + MD_SB_GENERIC_STATE_WORDS) ++#define MD_SB_PERSONALITY_WORDS 64 ++#define MD_SB_DESCRIPTOR_WORDS 32 ++#define MD_SB_DISKS 27 ++#define MD_SB_DISKS_WORDS (MD_SB_DISKS*MD_SB_DESCRIPTOR_WORDS) ++#define MD_SB_RESERVED_WORDS (1024 - MD_SB_GENERIC_WORDS - MD_SB_PERSONALITY_WORDS - MD_SB_DISKS_WORDS - MD_SB_DESCRIPTOR_WORDS) ++#define MD_SB_EQUAL_WORDS (MD_SB_GENERIC_WORDS + MD_SB_PERSONALITY_WORDS + MD_SB_DISKS_WORDS) ++ ++/* ++ * Device "operational" state bits ++ */ ++#define MD_DISK_FAULTY 0 /* disk is faulty / operational */ ++#define MD_DISK_ACTIVE 1 /* disk is running or spare disk */ ++#define MD_DISK_SYNC 2 /* disk is in sync with the raid set */ ++#define MD_DISK_REMOVED 3 /* disk is in sync with the raid set */ ++ ++#define MD_DISK_WRITEMOSTLY 9 /* disk is "write-mostly" is RAID1 config. ++ * read requests will only be sent here in ++ * dire need ++ */ ++ ++typedef struct mdp_device_descriptor_s { ++ __u32 number; /* 0 Device number in the entire set */ ++ __u32 major; /* 1 Device major number */ ++ __u32 minor; /* 2 Device minor number */ ++ __u32 raid_disk; /* 3 The role of the device in the raid set */ ++ __u32 state; /* 4 Operational state */ ++ __u32 reserved[MD_SB_DESCRIPTOR_WORDS - 5]; ++} mdp_disk_t; ++ ++#define MD_SB_MAGIC 0xa92b4efc ++ ++/* ++ * Superblock state bits ++ */ ++#define MD_SB_CLEAN 0 ++#define MD_SB_ERRORS 1 ++ ++#define MD_SB_BITMAP_PRESENT 8 /* bitmap may be present nearby */ ++ ++typedef struct mdp_superblock_s { ++ /* ++ * Constant generic information ++ */ ++ __u32 md_magic; /* 0 MD identifier */ ++ __u32 major_version; /* 1 major version to which the set conforms */ ++ __u32 minor_version; /* 2 minor version ... */ ++ __u32 patch_version; /* 3 patchlevel version ... */ ++ __u32 gvalid_words; /* 4 Number of used words in this section */ ++ __u32 set_uuid0; /* 5 Raid set identifier */ ++ __u32 ctime; /* 6 Creation time */ ++ __u32 level; /* 7 Raid personality */ ++ __u32 size; /* 8 Apparent size of each individual disk */ ++ __u32 nr_disks; /* 9 total disks in the raid set */ ++ __u32 raid_disks; /* 10 disks in a fully functional raid set */ ++ __u32 md_minor; /* 11 preferred MD minor device number */ ++ __u32 not_persistent; /* 12 does it have a persistent superblock */ ++ __u32 set_uuid1; /* 13 Raid set identifier #2 */ ++ __u32 set_uuid2; /* 14 Raid set identifier #3 */ ++ __u32 set_uuid3; /* 15 Raid set identifier #4 */ ++ __u32 gstate_creserved[MD_SB_GENERIC_CONSTANT_WORDS - 16]; ++ ++ /* ++ * Generic state information ++ */ ++ __u32 utime; /* 0 Superblock update time */ ++ __u32 state; /* 1 State bits (clean, ...) */ ++ __u32 active_disks; /* 2 Number of currently active disks */ ++ __u32 working_disks; /* 3 Number of working disks */ ++ __u32 failed_disks; /* 4 Number of failed disks */ ++ __u32 spare_disks; /* 5 Number of spare disks */ ++ __u32 sb_csum; /* 6 checksum of the whole superblock */ ++#if __BYTE_ORDER == __BIG_ENDIAN ++ __u32 events_hi; /* 7 high-order of superblock update count */ ++ __u32 events_lo; /* 8 low-order of superblock update count */ ++ __u32 cp_events_hi; /* 9 high-order of checkpoint update count */ ++ __u32 cp_events_lo; /* 10 low-order of checkpoint update count */ ++#else ++ __u32 events_lo; /* 7 low-order of superblock update count */ ++ __u32 events_hi; /* 8 high-order of superblock update count */ ++ __u32 cp_events_lo; /* 9 low-order of checkpoint update count */ ++ __u32 cp_events_hi; /* 10 high-order of checkpoint update count */ ++#endif ++ __u32 recovery_cp; /* 11 recovery checkpoint sector count */ ++ /* There are only valid for minor_version > 90 */ ++ __u64 reshape_position; /* 12,13 next address in array-space for reshape */ ++ __u32 new_level; /* 14 new level we are reshaping to */ ++ __u32 delta_disks; /* 15 change in number of raid_disks */ ++ __u32 new_layout; /* 16 new layout */ ++ __u32 new_chunk; /* 17 new chunk size (bytes) */ ++ __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 18]; ++ ++ /* ++ * Personality information ++ */ ++ __u32 layout; /* 0 the array's physical layout */ ++ __u32 chunk_size; /* 1 chunk size in bytes */ ++ __u32 root_pv; /* 2 LV root PV */ ++ __u32 root_block; /* 3 LV root block */ ++ __u32 pstate_reserved[MD_SB_PERSONALITY_WORDS - 4]; ++ ++ /* ++ * Disks information ++ */ ++ mdp_disk_t disks[MD_SB_DISKS]; ++ ++ /* ++ * Reserved ++ */ ++ __u32 reserved[MD_SB_RESERVED_WORDS]; ++ ++ /* ++ * Active descriptor ++ */ ++ mdp_disk_t this_disk; ++ ++} mdp_super_t; ++ ++#ifdef __TINYC__ ++typedef unsigned long long __u64; ++#endif ++ ++static inline __u64 md_event(mdp_super_t *sb) { ++ __u64 ev = sb->events_hi; ++ return (ev<<32)| sb->events_lo; ++} ++ ++#endif ++ +--- a/mdadm/md_u.h 1970-01-01 03:00:00.000000000 +0300 ++++ mdadm/mdadm/md_u.h 2011-01-12 21:33:01.000000000 +0200 +@@ -0,0 +1,123 @@ ++/* ++ md_u.h : user <=> kernel API between Linux raidtools and RAID drivers ++ Copyright (C) 1998 Ingo Molnar ++ ++ 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 ++ the Free Software Foundation; either version 2, or (at your option) ++ any later version. ++ ++ You should have received a copy of the GNU General Public License ++ (for example /usr/src/linux/COPYING); if not, write to the Free ++ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++#ifndef _MD_U_H ++#define _MD_U_H ++ ++/* ioctls */ ++ ++/* status */ ++#define RAID_VERSION _IOR (MD_MAJOR, 0x10, mdu_version_t) ++#define GET_ARRAY_INFO _IOR (MD_MAJOR, 0x11, mdu_array_info_t) ++#define GET_DISK_INFO _IOR (MD_MAJOR, 0x12, mdu_disk_info_t) ++#define PRINT_RAID_DEBUG _IO (MD_MAJOR, 0x13) ++#define RAID_AUTORUN _IO (MD_MAJOR, 0x14) ++#define GET_BITMAP_FILE _IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t) ++ ++/* configuration */ ++#define CLEAR_ARRAY _IO (MD_MAJOR, 0x20) ++#define ADD_NEW_DISK _IOW (MD_MAJOR, 0x21, mdu_disk_info_t) ++#define HOT_REMOVE_DISK _IO (MD_MAJOR, 0x22) ++#define SET_ARRAY_INFO _IOW (MD_MAJOR, 0x23, mdu_array_info_t) ++#define SET_DISK_INFO _IO (MD_MAJOR, 0x24) ++#define WRITE_RAID_INFO _IO (MD_MAJOR, 0x25) ++#define UNPROTECT_ARRAY _IO (MD_MAJOR, 0x26) ++#define PROTECT_ARRAY _IO (MD_MAJOR, 0x27) ++#define HOT_ADD_DISK _IO (MD_MAJOR, 0x28) ++#define SET_DISK_FAULTY _IO (MD_MAJOR, 0x29) ++#define SET_BITMAP_FILE _IOW (MD_MAJOR, 0x2b, int) ++ ++/* usage */ ++#define RUN_ARRAY _IOW (MD_MAJOR, 0x30, mdu_param_t) ++#define START_ARRAY _IO (MD_MAJOR, 0x31) ++#define STOP_ARRAY _IO (MD_MAJOR, 0x32) ++#define STOP_ARRAY_RO _IO (MD_MAJOR, 0x33) ++#define RESTART_ARRAY_RW _IO (MD_MAJOR, 0x34) ++ ++typedef struct mdu_version_s { ++ int major; ++ int minor; ++ int patchlevel; ++} mdu_version_t; ++ ++typedef struct mdu_array_info_s { ++ /* ++ * Generic constant information ++ */ ++ int major_version; ++ int minor_version; ++ int patch_version; ++ int ctime; ++ int level; ++ int size; ++ int nr_disks; ++ int raid_disks; ++ int md_minor; ++ int not_persistent; ++ ++ /* ++ * Generic state information ++ */ ++ int utime; /* 0 Superblock update time */ ++ int state; /* 1 State bits (clean, ...) */ ++ int active_disks; /* 2 Number of currently active disks */ ++ int working_disks; /* 3 Number of working disks */ ++ int failed_disks; /* 4 Number of failed disks */ ++ int spare_disks; /* 5 Number of spare disks */ ++ ++ /* ++ * Personality information ++ */ ++ int layout; /* 0 the array's physical layout */ ++ int chunk_size; /* 1 chunk size in bytes */ ++ ++} mdu_array_info_t; ++ ++typedef struct mdu_disk_info_s { ++ /* ++ * configuration/status of one particular disk ++ */ ++ int number; ++ int major; ++ int minor; ++ int raid_disk; ++ int state; ++ ++} mdu_disk_info_t; ++ ++typedef struct mdu_start_info_s { ++ /* ++ * configuration/status of one particular disk ++ */ ++ int major; ++ int minor; ++ int raid_disk; ++ int state; ++ ++} mdu_start_info_t; ++ ++typedef struct mdu_bitmap_file_s ++{ ++ char pathname[4096]; ++} mdu_bitmap_file_t; ++ ++typedef struct mdu_param_s ++{ ++ int personality; /* 1,2,3,4 */ ++ int chunk_size; /* in bytes */ ++ int max_fault; /* unused for now */ ++} mdu_param_t; ++ ++#endif ++ +--- a/mdadm/sha1.c 1970-01-01 03:00:00.000000000 +0300 ++++ mdadm/mdadm/sha1.c 2011-01-12 21:33:01.000000000 +0200 +@@ -0,0 +1,423 @@ ++/* sha1.c - Functions to compute SHA1 message digest of files or ++ memory blocks according to the NIST specification FIPS-180-1. ++ ++ Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc. ++ ++ 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 the ++ Free Software Foundation; either version 2, or (at your option) any ++ later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software Foundation, ++ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ ++ ++/* Written by Scott G. Miller ++ Credits: ++ Robert Klep -- Expansion function fix ++*/ ++ ++#ifdef HAVE_CONFIG_H ++# include ++#endif ++ ++#include "sha1.h" ++ ++#include ++#include ++ ++#if USE_UNLOCKED_IO ++# include "unlocked-io.h" ++#endif ++ ++/* SWAP does an endian swap on architectures that are little-endian, ++ as SHA1 needs some data in a big-endian form. */ ++ ++#ifdef WORDS_BIGENDIAN ++# define SWAP(n) (n) ++#else ++# define SWAP(n) \ ++ (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) ++#endif ++ ++#define BLOCKSIZE 4096 ++#if BLOCKSIZE % 64 != 0 ++# error "invalid BLOCKSIZE" ++#endif ++ ++/* This array contains the bytes used to pad the buffer to the next ++ 64-byte boundary. (RFC 1321, 3.1: Step 1) */ ++static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; ++ ++ ++/* ++ Takes a pointer to a 160 bit block of data (five 32 bit ints) and ++ intializes it to the start constants of the SHA1 algorithm. This ++ must be called before using hash in the call to sha1_hash. ++*/ ++void ++sha1_init_ctx (struct sha1_ctx *ctx) ++{ ++ ctx->A = 0x67452301; ++ ctx->B = 0xefcdab89; ++ ctx->C = 0x98badcfe; ++ ctx->D = 0x10325476; ++ ctx->E = 0xc3d2e1f0; ++ ++ ctx->total[0] = ctx->total[1] = 0; ++ ctx->buflen = 0; ++} ++ ++/* Put result from CTX in first 20 bytes following RESBUF. The result ++ must be in little endian byte order. ++ ++ IMPORTANT: On some systems it is required that RESBUF is correctly ++ aligned for a 32 bits value. */ ++void * ++sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf) ++{ ++ ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A); ++ ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B); ++ ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C); ++ ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D); ++ ((md5_uint32 *) resbuf)[4] = SWAP (ctx->E); ++ ++ return resbuf; ++} ++ ++/* Process the remaining bytes in the internal buffer and the usual ++ prolog according to the standard and write the result to RESBUF. ++ ++ IMPORTANT: On some systems it is required that RESBUF is correctly ++ aligned for a 32 bits value. */ ++void * ++sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf) ++{ ++ /* Take yet unprocessed bytes into account. */ ++ md5_uint32 bytes = ctx->buflen; ++ size_t pad; ++ ++ /* Now count remaining bytes. */ ++ ctx->total[0] += bytes; ++ if (ctx->total[0] < bytes) ++ ++ctx->total[1]; ++ ++ pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; ++ memcpy (&ctx->buffer[bytes], fillbuf, pad); ++ ++ /* Put the 64-bit file length in *bits* at the end of the buffer. */ ++ *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP (ctx->total[0] << 3); ++ *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP ((ctx->total[1] << 3) | ++ (ctx->total[0] >> 29)); ++ ++ /* Process last bytes. */ ++ sha1_process_block (ctx->buffer, bytes + pad + 8, ctx); ++ ++ return sha1_read_ctx (ctx, resbuf); ++} ++ ++/* Compute SHA1 message digest for bytes read from STREAM. The ++ resulting message digest number will be written into the 16 bytes ++ beginning at RESBLOCK. */ ++int ++sha1_stream (FILE *stream, void *resblock) ++{ ++ struct sha1_ctx ctx; ++ char buffer[BLOCKSIZE + 72]; ++ size_t sum; ++ ++ /* Initialize the computation context. */ ++ sha1_init_ctx (&ctx); ++ ++ /* Iterate over full file contents. */ ++ while (1) ++ { ++ /* We read the file in blocks of BLOCKSIZE bytes. One call of the ++ computation function processes the whole buffer so that with the ++ next round of the loop another block can be read. */ ++ size_t n; ++ sum = 0; ++ ++ /* Read block. Take care for partial reads. */ ++ while (1) ++ { ++ n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); ++ ++ sum += n; ++ ++ if (sum == BLOCKSIZE) ++ break; ++ ++ if (n == 0) ++ { ++ /* Check for the error flag IFF N == 0, so that we don't ++ exit the loop after a partial read due to e.g., EAGAIN ++ or EWOULDBLOCK. */ ++ if (ferror (stream)) ++ return 1; ++ goto process_partial_block; ++ } ++ ++ /* We've read at least one byte, so ignore errors. But always ++ check for EOF, since feof may be true even though N > 0. ++ Otherwise, we could end up calling fread after EOF. */ ++ if (feof (stream)) ++ goto process_partial_block; ++ } ++ ++ /* Process buffer with BLOCKSIZE bytes. Note that ++ BLOCKSIZE % 64 == 0 ++ */ ++ sha1_process_block (buffer, BLOCKSIZE, &ctx); ++ } ++ ++ process_partial_block:; ++ ++ /* Process any remaining bytes. */ ++ if (sum > 0) ++ sha1_process_bytes (buffer, sum, &ctx); ++ ++ /* Construct result in desired memory. */ ++ sha1_finish_ctx (&ctx, resblock); ++ return 0; ++} ++ ++/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The ++ result is always in little endian byte order, so that a byte-wise ++ output yields to the wanted ASCII representation of the message ++ digest. */ ++void * ++sha1_buffer (const char *buffer, size_t len, void *resblock) ++{ ++ struct sha1_ctx ctx; ++ ++ /* Initialize the computation context. */ ++ sha1_init_ctx (&ctx); ++ ++ /* Process whole buffer but last len % 64 bytes. */ ++ sha1_process_bytes (buffer, len, &ctx); ++ ++ /* Put result in desired memory area. */ ++ return sha1_finish_ctx (&ctx, resblock); ++} ++ ++void ++sha1_process_bytes (const void *buffer, size_t len, struct sha1_ctx *ctx) ++{ ++ /* When we already have some bits in our internal buffer concatenate ++ both inputs first. */ ++ if (ctx->buflen != 0) ++ { ++ size_t left_over = ctx->buflen; ++ size_t add = 128 - left_over > len ? len : 128 - left_over; ++ ++ memcpy (&ctx->buffer[left_over], buffer, add); ++ ctx->buflen += add; ++ ++ if (ctx->buflen > 64) ++ { ++ sha1_process_block (ctx->buffer, ctx->buflen & ~63, ctx); ++ ++ ctx->buflen &= 63; ++ /* The regions in the following copy operation cannot overlap. */ ++ memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], ++ ctx->buflen); ++ } ++ ++ buffer = (const char *) buffer + add; ++ len -= add; ++ } ++ ++ /* Process available complete blocks. */ ++ if (len >= 64) ++ { ++#if !_STRING_ARCH_unaligned ++# define alignof(type) offsetof (struct { char c; type x; }, x) ++# define UNALIGNED_P(p) (((size_t) p) % alignof (md5_uint32) != 0) ++ if (UNALIGNED_P (buffer)) ++ while (len > 64) ++ { ++ sha1_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); ++ buffer = (const char *) buffer + 64; ++ len -= 64; ++ } ++ else ++#endif ++ { ++ sha1_process_block (buffer, len & ~63, ctx); ++ buffer = (const char *) buffer + (len & ~63); ++ len &= 63; ++ } ++ } ++ ++ /* Move remaining bytes in internal buffer. */ ++ if (len > 0) ++ { ++ size_t left_over = ctx->buflen; ++ ++ memcpy (&ctx->buffer[left_over], buffer, len); ++ left_over += len; ++ if (left_over >= 64) ++ { ++ sha1_process_block (ctx->buffer, 64, ctx); ++ left_over -= 64; ++ memcpy (ctx->buffer, &ctx->buffer[64], left_over); ++ } ++ ctx->buflen = left_over; ++ } ++} ++ ++/* --- Code below is the primary difference between md5.c and sha1.c --- */ ++ ++/* SHA1 round constants */ ++#define K1 0x5a827999L ++#define K2 0x6ed9eba1L ++#define K3 0x8f1bbcdcL ++#define K4 0xca62c1d6L ++ ++/* Round functions. Note that F2 is the same as F4. */ ++#define F1(B,C,D) ( D ^ ( B & ( C ^ D ) ) ) ++#define F2(B,C,D) (B ^ C ^ D) ++#define F3(B,C,D) ( ( B & C ) | ( D & ( B | C ) ) ) ++#define F4(B,C,D) (B ^ C ^ D) ++ ++/* Process LEN bytes of BUFFER, accumulating context into CTX. ++ It is assumed that LEN % 64 == 0. ++ Most of this code comes from GnuPG's cipher/sha1.c. */ ++ ++void ++sha1_process_block (const void *buffer, size_t len, struct sha1_ctx *ctx) ++{ ++ const md5_uint32 *words = buffer; ++ size_t nwords = len / sizeof (md5_uint32); ++ const md5_uint32 *endp = words + nwords; ++ md5_uint32 x[16]; ++ md5_uint32 a = ctx->A; ++ md5_uint32 b = ctx->B; ++ md5_uint32 c = ctx->C; ++ md5_uint32 d = ctx->D; ++ md5_uint32 e = ctx->E; ++ ++ /* First increment the byte count. RFC 1321 specifies the possible ++ length of the file up to 2^64 bits. Here we only compute the ++ number of bytes. Do a double word increment. */ ++ ctx->total[0] += len; ++ if (ctx->total[0] < len) ++ ++ctx->total[1]; ++ ++#define rol(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) ++ ++#define M(I) ( tm = x[I&0x0f] ^ x[(I-14)&0x0f] \ ++ ^ x[(I-8)&0x0f] ^ x[(I-3)&0x0f] \ ++ , (x[I&0x0f] = rol(tm, 1)) ) ++ ++#define R(A,B,C,D,E,F,K,M) do { E += rol( A, 5 ) \ ++ + F( B, C, D ) \ ++ + K \ ++ + M; \ ++ B = rol( B, 30 ); \ ++ } while(0) ++ ++ while (words < endp) ++ { ++ md5_uint32 tm; ++ int t; ++ for (t = 0; t < 16; t++) ++ { ++ x[t] = SWAP (*words); ++ words++; ++ } ++ ++ R( a, b, c, d, e, F1, K1, x[ 0] ); ++ R( e, a, b, c, d, F1, K1, x[ 1] ); ++ R( d, e, a, b, c, F1, K1, x[ 2] ); ++ R( c, d, e, a, b, F1, K1, x[ 3] ); ++ R( b, c, d, e, a, F1, K1, x[ 4] ); ++ R( a, b, c, d, e, F1, K1, x[ 5] ); ++ R( e, a, b, c, d, F1, K1, x[ 6] ); ++ R( d, e, a, b, c, F1, K1, x[ 7] ); ++ R( c, d, e, a, b, F1, K1, x[ 8] ); ++ R( b, c, d, e, a, F1, K1, x[ 9] ); ++ R( a, b, c, d, e, F1, K1, x[10] ); ++ R( e, a, b, c, d, F1, K1, x[11] ); ++ R( d, e, a, b, c, F1, K1, x[12] ); ++ R( c, d, e, a, b, F1, K1, x[13] ); ++ R( b, c, d, e, a, F1, K1, x[14] ); ++ R( a, b, c, d, e, F1, K1, x[15] ); ++ R( e, a, b, c, d, F1, K1, M(16) ); ++ R( d, e, a, b, c, F1, K1, M(17) ); ++ R( c, d, e, a, b, F1, K1, M(18) ); ++ R( b, c, d, e, a, F1, K1, M(19) ); ++ R( a, b, c, d, e, F2, K2, M(20) ); ++ R( e, a, b, c, d, F2, K2, M(21) ); ++ R( d, e, a, b, c, F2, K2, M(22) ); ++ R( c, d, e, a, b, F2, K2, M(23) ); ++ R( b, c, d, e, a, F2, K2, M(24) ); ++ R( a, b, c, d, e, F2, K2, M(25) ); ++ R( e, a, b, c, d, F2, K2, M(26) ); ++ R( d, e, a, b, c, F2, K2, M(27) ); ++ R( c, d, e, a, b, F2, K2, M(28) ); ++ R( b, c, d, e, a, F2, K2, M(29) ); ++ R( a, b, c, d, e, F2, K2, M(30) ); ++ R( e, a, b, c, d, F2, K2, M(31) ); ++ R( d, e, a, b, c, F2, K2, M(32) ); ++ R( c, d, e, a, b, F2, K2, M(33) ); ++ R( b, c, d, e, a, F2, K2, M(34) ); ++ R( a, b, c, d, e, F2, K2, M(35) ); ++ R( e, a, b, c, d, F2, K2, M(36) ); ++ R( d, e, a, b, c, F2, K2, M(37) ); ++ R( c, d, e, a, b, F2, K2, M(38) ); ++ R( b, c, d, e, a, F2, K2, M(39) ); ++ R( a, b, c, d, e, F3, K3, M(40) ); ++ R( e, a, b, c, d, F3, K3, M(41) ); ++ R( d, e, a, b, c, F3, K3, M(42) ); ++ R( c, d, e, a, b, F3, K3, M(43) ); ++ R( b, c, d, e, a, F3, K3, M(44) ); ++ R( a, b, c, d, e, F3, K3, M(45) ); ++ R( e, a, b, c, d, F3, K3, M(46) ); ++ R( d, e, a, b, c, F3, K3, M(47) ); ++ R( c, d, e, a, b, F3, K3, M(48) ); ++ R( b, c, d, e, a, F3, K3, M(49) ); ++ R( a, b, c, d, e, F3, K3, M(50) ); ++ R( e, a, b, c, d, F3, K3, M(51) ); ++ R( d, e, a, b, c, F3, K3, M(52) ); ++ R( c, d, e, a, b, F3, K3, M(53) ); ++ R( b, c, d, e, a, F3, K3, M(54) ); ++ R( a, b, c, d, e, F3, K3, M(55) ); ++ R( e, a, b, c, d, F3, K3, M(56) ); ++ R( d, e, a, b, c, F3, K3, M(57) ); ++ R( c, d, e, a, b, F3, K3, M(58) ); ++ R( b, c, d, e, a, F3, K3, M(59) ); ++ R( a, b, c, d, e, F4, K4, M(60) ); ++ R( e, a, b, c, d, F4, K4, M(61) ); ++ R( d, e, a, b, c, F4, K4, M(62) ); ++ R( c, d, e, a, b, F4, K4, M(63) ); ++ R( b, c, d, e, a, F4, K4, M(64) ); ++ R( a, b, c, d, e, F4, K4, M(65) ); ++ R( e, a, b, c, d, F4, K4, M(66) ); ++ R( d, e, a, b, c, F4, K4, M(67) ); ++ R( c, d, e, a, b, F4, K4, M(68) ); ++ R( b, c, d, e, a, F4, K4, M(69) ); ++ R( a, b, c, d, e, F4, K4, M(70) ); ++ R( e, a, b, c, d, F4, K4, M(71) ); ++ R( d, e, a, b, c, F4, K4, M(72) ); ++ R( c, d, e, a, b, F4, K4, M(73) ); ++ R( b, c, d, e, a, F4, K4, M(74) ); ++ R( a, b, c, d, e, F4, K4, M(75) ); ++ R( e, a, b, c, d, F4, K4, M(76) ); ++ R( d, e, a, b, c, F4, K4, M(77) ); ++ R( c, d, e, a, b, F4, K4, M(78) ); ++ R( b, c, d, e, a, F4, K4, M(79) ); ++ ++ a = ctx->A += a; ++ b = ctx->B += b; ++ c = ctx->C += c; ++ d = ctx->D += d; ++ e = ctx->E += e; ++ } ++} +--- a/mdadm/sha1.h 1970-01-01 03:00:00.000000000 +0300 ++++ mdadm/mdadm/sha1.h 2011-01-12 21:33:01.000000000 +0200 +@@ -0,0 +1,87 @@ ++/* Declarations of functions and data types used for SHA1 sum ++ library functions. ++ Copyright (C) 2000, 2001, 2003, 2005 Free Software Foundation, Inc. ++ ++ 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 the ++ Free Software Foundation; either version 2, or (at your option) any ++ later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software Foundation, ++ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ ++ ++#ifndef SHA1_H ++# define SHA1_H 1 ++ ++# include ++# include "md5.h" ++ ++/* Structure to save state of computation between the single steps. */ ++struct sha1_ctx ++{ ++ md5_uint32 A; ++ md5_uint32 B; ++ md5_uint32 C; ++ md5_uint32 D; ++ md5_uint32 E; ++ ++ md5_uint32 total[2]; ++ md5_uint32 buflen; ++ char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32)))); ++}; ++ ++ ++/* Initialize structure containing state of computation. */ ++extern void sha1_init_ctx (struct sha1_ctx *ctx); ++ ++/* Starting with the result of former calls of this function (or the ++ initialization function update the context for the next LEN bytes ++ starting at BUFFER. ++ It is necessary that LEN is a multiple of 64!!! */ ++extern void sha1_process_block (const void *buffer, size_t len, ++ struct sha1_ctx *ctx); ++ ++/* Starting with the result of former calls of this function (or the ++ initialization function update the context for the next LEN bytes ++ starting at BUFFER. ++ It is NOT required that LEN is a multiple of 64. */ ++extern void sha1_process_bytes (const void *buffer, size_t len, ++ struct sha1_ctx *ctx); ++ ++/* Process the remaining bytes in the buffer and put result from CTX ++ in first 20 bytes following RESBUF. The result is always in little ++ endian byte order, so that a byte-wise output yields to the wanted ++ ASCII representation of the message digest. ++ ++ IMPORTANT: On some systems it is required that RESBUF be correctly ++ aligned for a 32 bits value. */ ++extern void *sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf); ++ ++ ++/* Put result from CTX in first 20 bytes following RESBUF. The result is ++ always in little endian byte order, so that a byte-wise output yields ++ to the wanted ASCII representation of the message digest. ++ ++ IMPORTANT: On some systems it is required that RESBUF is correctly ++ aligned for a 32 bits value. */ ++extern void *sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf); ++ ++ ++/* Compute SHA1 message digest for bytes read from STREAM. The ++ resulting message digest number will be written into the 20 bytes ++ beginning at RESBLOCK. */ ++extern int sha1_stream (FILE *stream, void *resblock); ++ ++/* Compute SHA1 message digest for LEN bytes beginning at BUFFER. The ++ result is always in little endian byte order, so that a byte-wise ++ output yields to the wanted ASCII representation of the message ++ digest. */ ++extern void *sha1_buffer (const char *buffer, size_t len, void *resblock); ++ ++#endif +--- a/mdadm/super0.c 1970-01-01 03:00:00.000000000 +0300 ++++ mdadm/mdadm/super0.c 2011-01-12 21:33:01.000000000 +0200 +@@ -0,0 +1,562 @@ ++/* ++ * mdadm - manage Linux "md" devices aka RAID arrays. ++ * ++ * Copyright (C) 2001-2006 Neil Brown ++ * ++ * ++ * 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 ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * Author: Neil Brown ++ * Email: ++ * Paper: Neil Brown ++ * School of Computer Science and Engineering ++ * The University of New South Wales ++ * Sydney, 2052 ++ * Australia ++ */ ++ ++#define HAVE_STDINT_H 1 ++#include "mdadm.h" ++/* ++ * All handling for the 0.90.0 version superblock is in ++ * this file. ++ * This includes: ++ * - finding, loading, and writing the superblock. ++ * - initialising a new superblock ++ * - printing the superblock for --examine ++ * - printing part of the superblock for --detail ++ * .. other stuff ++ */ ++ ++ ++static unsigned long calc_sb0_csum(mdp_super_t *super) ++{ ++ unsigned long csum = super->sb_csum; ++ unsigned long newcsum; ++ super->sb_csum= 0 ; ++ newcsum = calc_csum(super, MD_SB_BYTES); ++ super->sb_csum = csum; ++ return newcsum; ++} ++ ++ ++void super0_swap_endian(struct mdp_superblock_s *sb) ++{ ++ /* as super0 superblocks are host-endian, it is sometimes ++ * useful to be able to swap the endianness ++ * as (almost) everything is u32's we byte-swap every 4byte ++ * number. ++ * We then also have to swap the events_hi and events_lo ++ */ ++ char *sbc = (char *)sb; ++ __u32 t32; ++ int i; ++ ++ for (i=0; i < MD_SB_BYTES ; i+=4) { ++ char t = sbc[i]; ++ sbc[i] = sbc[i+3]; ++ sbc[i+3] = t; ++ t=sbc[i+1]; ++ sbc[i+1]=sbc[i+2]; ++ sbc[i+2]=t; ++ } ++ t32 = sb->events_hi; ++ sb->events_hi = sb->events_lo; ++ sb->events_lo = t32; ++ ++ t32 = sb->cp_events_hi; ++ sb->cp_events_hi = sb->cp_events_lo; ++ sb->cp_events_lo = t32; ++ ++} ++ ++static void brief_examine_super0(void *sbv) ++{ ++ mdp_super_t *sb = sbv; ++ char *c=map_num(pers, sb->level); ++ char devname[20]; ++ ++ sprintf(devname, "/dev/md%d", sb->md_minor); ++ ++ printf("ARRAY %s level=%s num-devices=%d UUID=", ++ devname, ++ c?c:"-unknown-", sb->raid_disks); ++ if (sb->minor_version >= 90) ++ printf("%08x:%08x:%08x:%08x", sb->set_uuid0, sb->set_uuid1, ++ sb->set_uuid2, sb->set_uuid3); ++ else ++ printf("%08x", sb->set_uuid0); ++ printf("\n"); ++} ++ ++static int match_home0(void *sbv, char *homehost) ++{ ++ mdp_super_t *sb = sbv; ++ char buf[20]; ++ char *hash = sha1_buffer(homehost, ++ strlen(homehost), ++ buf); ++ ++ return (memcmp(&sb->set_uuid2, hash, 8)==0); ++} ++ ++static void uuid_from_super0(int uuid[4], void * sbv) ++{ ++ mdp_super_t *super = sbv; ++ uuid[0] = super->set_uuid0; ++ if (super->minor_version >= 90) { ++ uuid[1] = super->set_uuid1; ++ uuid[2] = super->set_uuid2; ++ uuid[3] = super->set_uuid3; ++ } else { ++ uuid[1] = 0; ++ uuid[2] = 0; ++ uuid[3] = 0; ++ } ++} ++ ++static void getinfo_super0(struct mdinfo *info, void *sbv) ++{ ++ mdp_super_t *sb = sbv; ++ int working = 0; ++ int i; ++ ++ info->array.major_version = sb->major_version; ++ info->array.minor_version = sb->minor_version; ++ info->array.patch_version = sb->patch_version; ++ info->array.raid_disks = sb->raid_disks; ++ info->array.level = sb->level; ++ info->array.layout = sb->layout; ++ info->array.md_minor = sb->md_minor; ++ info->array.ctime = sb->ctime; ++ info->array.utime = sb->utime; ++ info->array.chunk_size = sb->chunk_size; ++ info->array.state = sb->state; ++ info->component_size = sb->size*2; ++ ++ info->disk.state = sb->this_disk.state; ++ info->disk.major = sb->this_disk.major; ++ info->disk.minor = sb->this_disk.minor; ++ info->disk.raid_disk = sb->this_disk.raid_disk; ++ info->disk.number = sb->this_disk.number; ++ ++ info->events = md_event(sb); ++ info->data_offset = 0; ++ ++ uuid_from_super0(info->uuid, sbv); ++ ++ if (sb->minor_version > 90 && (sb->reshape_position+1) != 0) { ++ info->reshape_active = 1; ++ info->reshape_progress = sb->reshape_position; ++ info->new_level = sb->new_level; ++ info->delta_disks = sb->delta_disks; ++ info->new_layout = sb->new_layout; ++ info->new_chunk = sb->new_chunk; ++ } else ++ info->reshape_active = 0; ++ ++ sprintf(info->name, "%d", sb->md_minor); ++ /* work_disks is calculated rather than read directly */ ++ for (i=0; i < MD_SB_DISKS; i++) ++ if ((sb->disks[i].state & (1<disks[i].raid_disk < info->array.raid_disks) && ++ (sb->disks[i].state & (1<disks[i].state & (1<array.working_disks = working; ++} ++ ++ ++static int update_super0(struct mdinfo *info, void *sbv, char *update, ++ char *devname, int verbose, ++ int uuid_set, char *homehost) ++{ ++ /* NOTE: for 'assemble' and 'force' we need to return non-zero if any change was made. ++ * For others, the return value is ignored. ++ */ ++ int rv = 0; ++ mdp_super_t *sb = sbv; ++ if (strcmp(update, "sparc2.2")==0 ) { ++ /* 2.2 sparc put the events in the wrong place ++ * So we copy the tail of the superblock ++ * up 4 bytes before continuing ++ */ ++ __u32 *sb32 = (__u32*)sb; ++ memcpy(sb32+MD_SB_GENERIC_CONSTANT_WORDS+7, ++ sb32+MD_SB_GENERIC_CONSTANT_WORDS+7+1, ++ (MD_SB_WORDS - (MD_SB_GENERIC_CONSTANT_WORDS+7+1))*4); ++ if (verbose >= 0) ++ fprintf (stderr, Name ": adjusting superblock of %s for 2.2/sparc compatability.\n", ++ devname); ++ } ++ if (strcmp(update, "super-minor") ==0) { ++ sb->md_minor = info->array.md_minor; ++ if (verbose > 0) ++ fprintf(stderr, Name ": updating superblock of %s with minor number %d\n", ++ devname, info->array.md_minor); ++ } ++ if (strcmp(update, "summaries") == 0) { ++ int i; ++ /* set nr_disks, active_disks, working_disks, ++ * failed_disks, spare_disks based on disks[] ++ * array in superblock. ++ * Also make sure extra slots aren't 'failed' ++ */ ++ sb->nr_disks = sb->active_disks = ++ sb->working_disks = sb->failed_disks = ++ sb->spare_disks = 0; ++ for (i=0; i < MD_SB_DISKS ; i++) ++ if (sb->disks[i].major || ++ sb->disks[i].minor) { ++ int state = sb->disks[i].state; ++ if (state & (1<nr_disks++; ++ if (state & (1<active_disks++; ++ if (state & (1<failed_disks++; ++ else ++ sb->working_disks++; ++ if (state == 0) ++ sb->spare_disks++; ++ } else if (i >= sb->raid_disks && sb->disks[i].number == 0) ++ sb->disks[i].state = 0; ++ } ++ if (strcmp(update, "force-one")==0) { ++ /* Not enough devices for a working array, so ++ * bring this one up-to-date. ++ */ ++ __u32 ehi = sb->events_hi, elo = sb->events_lo; ++ sb->events_hi = (info->events>>32) & 0xFFFFFFFF; ++ sb->events_lo = (info->events) & 0xFFFFFFFF; ++ if (sb->events_hi != ehi || ++ sb->events_lo != elo) ++ rv = 1; ++ } ++ if (strcmp(update, "force-array")==0) { ++ /* degraded array and 'force' requested, so ++ * maybe need to mark it 'clean' ++ */ ++ if ((sb->level == 5 || sb->level == 4 || sb->level == 6) && ++ (sb->state & (1 << MD_SB_CLEAN)) == 0) { ++ /* need to force clean */ ++ sb->state |= (1 << MD_SB_CLEAN); ++ rv = 1; ++ } ++ } ++ if (strcmp(update, "assemble")==0) { ++ int d = info->disk.number; ++ int wonly = sb->disks[d].state & (1<disks[d].state & ~(1<disk.state) { ++ sb->disks[d].state = info->disk.state | wonly; ++ rv = 1; ++ } ++ } ++ if (strcmp(update, "linear-grow-new") == 0) { ++ memset(&sb->disks[info->disk.number], 0, sizeof(sb->disks[0])); ++ sb->disks[info->disk.number].number = info->disk.number; ++ sb->disks[info->disk.number].major = info->disk.major; ++ sb->disks[info->disk.number].minor = info->disk.minor; ++ sb->disks[info->disk.number].raid_disk = info->disk.raid_disk; ++ sb->disks[info->disk.number].state = info->disk.state; ++ sb->this_disk = sb->disks[info->disk.number]; ++ } ++ if (strcmp(update, "linear-grow-update") == 0) { ++ sb->raid_disks = info->array.raid_disks; ++ sb->nr_disks = info->array.nr_disks; ++ sb->active_disks = info->array.active_disks; ++ sb->working_disks = info->array.working_disks; ++ memset(&sb->disks[info->disk.number], 0, sizeof(sb->disks[0])); ++ sb->disks[info->disk.number].number = info->disk.number; ++ sb->disks[info->disk.number].major = info->disk.major; ++ sb->disks[info->disk.number].minor = info->disk.minor; ++ sb->disks[info->disk.number].raid_disk = info->disk.raid_disk; ++ sb->disks[info->disk.number].state = info->disk.state; ++ } ++ if (strcmp(update, "resync") == 0) { ++ /* make sure resync happens */ ++ sb->state &= ~(1<recovery_cp = 0; ++ } ++ if (strcmp(update, "homehost") == 0 && ++ homehost) { ++ uuid_set = 0; ++ update = "uuid"; ++ info->uuid[0] = sb->set_uuid0; ++ info->uuid[1] = sb->set_uuid1; ++ } ++ if (strcmp(update, "uuid") == 0) { ++ if (!uuid_set && homehost) { ++ char buf[20]; ++ char *hash = sha1_buffer(homehost, ++ strlen(homehost), ++ buf); ++ memcpy(info->uuid+2, hash, 8); ++ } ++ sb->set_uuid0 = info->uuid[0]; ++ sb->set_uuid1 = info->uuid[1]; ++ sb->set_uuid2 = info->uuid[2]; ++ sb->set_uuid3 = info->uuid[3]; ++ if (sb->state & (1<uuid, sbv); ++ } ++ } ++ if (strcmp(update, "_reshape_progress")==0) ++ sb->reshape_position = info->reshape_progress; ++ ++ sb->sb_csum = calc_sb0_csum(sb); ++ return rv; ++} ++ ++static int store_super0(struct supertype *st, int fd, void *sbv) ++{ ++ unsigned long long dsize; ++ unsigned long long offset; ++ mdp_super_t *super = sbv; ++ ++ if (!get_dev_size(fd, NULL, &dsize)) ++ return 1; ++ ++ if (dsize < MD_RESERVED_SECTORS*2*512) ++ return 2; ++ ++ offset = MD_NEW_SIZE_SECTORS(dsize>>9); ++ ++ offset *= 512; ++ ++ if (lseek64(fd, offset, 0)< 0LL) ++ return 3; ++ ++ if (write(fd, super, sizeof(*super)) != sizeof(*super)) ++ return 4; ++ ++ if (super->state & (1<magic) == BITMAP_MAGIC) ++ if (write(fd, bm, sizeof(*bm)) != sizeof(*bm)) ++ return 5; ++ } ++ ++ fsync(fd); ++ return 0; ++} ++ ++static int compare_super0(void **firstp, void *secondv) ++{ ++ /* ++ * return: ++ * 0 same, or first was empty, and second was copied ++ * 1 second had wrong number ++ * 2 wrong uuid ++ * 3 wrong other info ++ */ ++ mdp_super_t *first = *firstp; ++ mdp_super_t *second = secondv; ++ ++ int uuid1[4], uuid2[4]; ++ if (second->md_magic != MD_SB_MAGIC) ++ return 1; ++ if (!first) { ++ first = malloc(MD_SB_BYTES + sizeof(struct bitmap_super_s)); ++ memcpy(first, second, MD_SB_BYTES + sizeof(struct bitmap_super_s)); ++ *firstp = first; ++ return 0; ++ } ++ ++ uuid_from_super0(uuid1, first); ++ uuid_from_super0(uuid2, second); ++ if (!same_uuid(uuid1, uuid2, 0)) ++ return 2; ++ if (first->major_version != second->major_version || ++ first->minor_version != second->minor_version || ++ first->patch_version != second->patch_version || ++ first->gvalid_words != second->gvalid_words || ++ first->ctime != second->ctime || ++ first->level != second->level || ++ first->size != second->size || ++ first->raid_disks != second->raid_disks ) ++ return 3; ++ ++ return 0; ++} ++ ++ ++static int load_super0(struct supertype *st, int fd, void **sbp, char *devname) ++{ ++ /* try to read in the superblock ++ * Return: ++ * 0 on success ++ * 1 on cannot get superblock ++ * 2 on superblock meaningless ++ */ ++ unsigned long long dsize; ++ unsigned long long offset; ++ mdp_super_t *super; ++ int uuid[4]; ++ struct bitmap_super_s *bsb; ++ ++ if (!get_dev_size(fd, devname, &dsize)) ++ return 1; ++ ++ if (dsize < MD_RESERVED_SECTORS*512 * 2) { ++ if (devname) ++ fprintf(stderr, Name ++ ": %s is too small for md: size is %llu sectors.\n", ++ devname, dsize); ++ return 1; ++ } ++ ++ offset = MD_NEW_SIZE_SECTORS(dsize>>9); ++ ++ offset *= 512; ++ ++ ioctl(fd, BLKFLSBUF, 0); /* make sure we read current data */ ++ ++ if (lseek64(fd, offset, 0)< 0LL) { ++ if (devname) ++ fprintf(stderr, Name ": Cannot seek to superblock on %s: %s\n", ++ devname, strerror(errno)); ++ return 1; ++ } ++ ++ super = malloc(MD_SB_BYTES + sizeof(bitmap_super_t)); ++ ++ if (read(fd, super, sizeof(*super)) != MD_SB_BYTES) { ++ if (devname) ++ fprintf(stderr, Name ": Cannot read superblock on %s\n", ++ devname); ++ free(super); ++ return 1; ++ } ++ ++ if (st->ss && st->minor_version == 9) ++ super0_swap_endian(super); ++ ++ if (super->md_magic != MD_SB_MAGIC) { ++ if (devname) ++ fprintf(stderr, Name ": No super block found on %s (Expected magic %08x, got %08x)\n", ++ devname, MD_SB_MAGIC, super->md_magic); ++ free(super); ++ return 2; ++ } ++ ++ if (super->major_version != 0) { ++ if (devname) ++ fprintf(stderr, Name ": Cannot interpret superblock on %s - version is %d\n", ++ devname, super->major_version); ++ free(super); ++ return 2; ++ } ++ *sbp = super; ++ if (st->ss == NULL) { ++ st->ss = &super0; ++ st->minor_version = 90; ++ st->max_devs = MD_SB_DISKS; ++ } ++ ++ /* Now check on the bitmap superblock */ ++ if ((super->state & (1<magic) != BITMAP_MAGIC || ++ memcmp(bsb->uuid, uuid, 16) != 0) ++ goto no_bitmap; ++ return 0; ++ ++ no_bitmap: ++ super->state &= ~(1<ss = &super0; ++ st->minor_version = 90; ++ st->max_devs = MD_SB_DISKS; ++ if (strcmp(arg, "0") == 0 || ++ strcmp(arg, "0.90") == 0 || ++ strcmp(arg, "default") == 0 ++ ) ++ return st; ++ ++ st->minor_version = 9; /* flag for 'byte-swapped' */ ++ if (strcmp(arg, "0.swap")==0) ++ return st; ++ ++ free(st); ++ return NULL; ++} ++ ++void locate_bitmap0(struct supertype *st, int fd, void *sbv) ++{ ++ unsigned long long dsize; ++ unsigned long long offset; ++ ++ if (!get_dev_size(fd, NULL, &dsize)) ++ return; ++ ++ if (dsize < MD_RESERVED_SECTORS*512 * 2) ++ return; ++ ++ offset = MD_NEW_SIZE_SECTORS(dsize>>9); ++ ++ offset *= 512; ++ ++ offset += MD_SB_BYTES; ++ ++ lseek64(fd, offset, 0); ++} ++ ++struct superswitch super0 = { ++ .examine_super = NULL, ++ .brief_examine_super = brief_examine_super0, ++ .detail_super = NULL, ++ .brief_detail_super = NULL, ++ .export_super = NULL, ++ .match_home = match_home0, ++ .uuid_from_super = uuid_from_super0, ++ .getinfo_super = getinfo_super0, ++ .update_super = update_super0, ++ .init_super = NULL, ++ .add_to_super = NULL, ++ .store_super = store_super0, ++ .write_init_super = NULL, ++ .compare_super = compare_super0, ++ .load_super = load_super0, ++ .match_metadata_desc = match_metadata_desc0, ++ .avail_size = NULL, ++ .add_internal_bitmap = NULL, ++ .locate_bitmap = locate_bitmap0, ++ .write_bitmap = NULL, ++ .major = 0, ++ .swapuuid = 0, ++}; +--- a/mdadm/super1.c 1970-01-01 03:00:00.000000000 +0300 ++++ mdadm/mdadm/super1.c 2011-01-12 21:33:01.000000000 +0200 +@@ -0,0 +1,731 @@ ++/* ++ * mdadm - manage Linux "md" devices aka RAID arrays. ++ * ++ * Copyright (C) 2001-2006 Neil Brown ++ * ++ * ++ * 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 ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * Author: Neil Brown ++ * Email: ++ * Paper: Neil Brown ++ * School of Computer Science and Engineering ++ * The University of New South Wales ++ * Sydney, 2052 ++ * Australia ++ */ ++ ++#include "mdadm.h" ++/* ++ * The version-1 superblock : ++ * All numeric fields are little-endian. ++ * ++ * total size: 256 bytes plus 2 per device. ++ * 1K allows 384 devices. ++ */ ++struct mdp_superblock_1 { ++ /* constant array information - 128 bytes */ ++ __u32 magic; /* MD_SB_MAGIC: 0xa92b4efc - little endian */ ++ __u32 major_version; /* 1 */ ++ __u32 feature_map; /* 0 for now */ ++ __u32 pad0; /* always set to 0 when writing */ ++ ++ __u8 set_uuid[16]; /* user-space generated. */ ++ char set_name[32]; /* set and interpreted by user-space */ ++ ++ __u64 ctime; /* lo 40 bits are seconds, top 24 are microseconds or 0*/ ++ __u32 level; /* -4 (multipath), -1 (linear), 0,1,4,5 */ ++ __u32 layout; /* only for raid5 currently */ ++ __u64 size; /* used size of component devices, in 512byte sectors */ ++ ++ __u32 chunksize; /* in 512byte sectors */ ++ __u32 raid_disks; ++ __u32 bitmap_offset; /* sectors after start of superblock that bitmap starts ++ * NOTE: signed, so bitmap can be before superblock ++ * only meaningful of feature_map[0] is set. ++ */ ++ ++ /* These are only valid with feature bit '4' */ ++ __u32 new_level; /* new level we are reshaping to */ ++ __u64 reshape_position; /* next address in array-space for reshape */ ++ __u32 delta_disks; /* change in number of raid_disks */ ++ __u32 new_layout; /* new layout */ ++ __u32 new_chunk; /* new chunk size (bytes) */ ++ __u8 pad1[128-124]; /* set to 0 when written */ ++ ++ /* constant this-device information - 64 bytes */ ++ __u64 data_offset; /* sector start of data, often 0 */ ++ __u64 data_size; /* sectors in this device that can be used for data */ ++ __u64 super_offset; /* sector start of this superblock */ ++ __u64 recovery_offset;/* sectors before this offset (from data_offset) have been recovered */ ++ __u32 dev_number; /* permanent identifier of this device - not role in raid */ ++ __u32 cnt_corrected_read; /* number of read errors that were corrected by re-writing */ ++ __u8 device_uuid[16]; /* user-space setable, ignored by kernel */ ++ __u8 devflags; /* per-device flags. Only one defined...*/ ++#define WriteMostly1 1 /* mask for writemostly flag in above */ ++ __u8 pad2[64-57]; /* set to 0 when writing */ ++ ++ /* array state information - 64 bytes */ ++ __u64 utime; /* 40 bits second, 24 btes microseconds */ ++ __u64 events; /* incremented when superblock updated */ ++ __u64 resync_offset; /* data before this offset (from data_offset) known to be in sync */ ++ __u32 sb_csum; /* checksum upto devs[max_dev] */ ++ __u32 max_dev; /* size of devs[] array to consider */ ++ __u8 pad3[64-32]; /* set to 0 when writing */ ++ ++ /* device state information. Indexed by dev_number. ++ * 2 bytes per device ++ * Note there are no per-device state flags. State information is rolled ++ * into the 'roles' value. If a device is spare or faulty, then it doesn't ++ * have a meaningful role. ++ */ ++ __u16 dev_roles[0]; /* role in array, or 0xffff for a spare, or 0xfffe for faulty */ ++}; ++ ++struct misc_dev_info { ++ __u64 device_size; ++}; ++ ++/* feature_map bits */ ++#define MD_FEATURE_BITMAP_OFFSET 1 ++#define MD_FEATURE_RECOVERY_OFFSET 2 /* recovery_offset is present and ++ * must be honoured ++ */ ++#define MD_FEATURE_RESHAPE_ACTIVE 4 ++ ++#define MD_FEATURE_ALL (1|2|4) ++ ++#ifndef offsetof ++#define offsetof(t,f) ((size_t)&(((t*)0)->f)) ++#endif ++static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb) ++{ ++ unsigned int disk_csum, csum; ++ unsigned long long newcsum; ++ int size = sizeof(*sb) + __le32_to_cpu(sb->max_dev)*2; ++ unsigned int *isuper = (unsigned int*)sb; ++ int i; ++ ++/* make sure I can count... */ ++ if (offsetof(struct mdp_superblock_1,data_offset) != 128 || ++ offsetof(struct mdp_superblock_1, utime) != 192 || ++ sizeof(struct mdp_superblock_1) != 256) { ++ fprintf(stderr, "WARNING - superblock isn't sized correctly\n"); ++ } ++ ++ disk_csum = sb->sb_csum; ++ sb->sb_csum = 0; ++ newcsum = 0; ++ for (i=0; size>=4; size -= 4 ) { ++ newcsum += __le32_to_cpu(*isuper); ++ isuper++; ++ } ++ ++ if (size == 2) ++ newcsum += __le16_to_cpu(*(unsigned short*) isuper); ++ ++ csum = (newcsum & 0xffffffff) + (newcsum >> 32); ++ sb->sb_csum = disk_csum; ++ return __cpu_to_le32(csum); ++} ++ ++static void brief_examine_super1(void *sbv) ++{ ++ struct mdp_superblock_1 *sb = sbv; ++ int i; ++ unsigned long long sb_offset; ++ char *nm; ++ char *c=map_num(pers, __le32_to_cpu(sb->level)); ++ ++ nm = strchr(sb->set_name, ':'); ++ if (nm) ++ nm++; ++ else if (sb->set_name[0]) ++ nm = sb->set_name; ++ else ++ nm = "??"; ++ ++ printf("ARRAY /dev/md%s level=%s ", nm, c?c:"-unknown-"); ++ sb_offset = __le64_to_cpu(sb->super_offset); ++ if (sb_offset <= 4) ++ printf("metadata=1.1 "); ++ else if (sb_offset <= 8) ++ printf("metadata=1.2 "); ++ else ++ printf("metadata=1.0 "); ++ printf("num-devices=%d UUID=", __le32_to_cpu(sb->raid_disks)); ++ for (i=0; i<16; i++) { ++ if ((i&3)==0 && i != 0) printf(":"); ++ printf("%02x", sb->set_uuid[i]); ++ } ++ if (sb->set_name[0]) ++ printf(" name=%.32s", sb->set_name); ++ printf("\n"); ++} ++ ++static int match_home1(void *sbv, char *homehost) ++{ ++ struct mdp_superblock_1 *sb = sbv; ++ int l = homehost ? strlen(homehost) : 0; ++ ++ return (l > 0 && l < 32 && ++ sb->set_name[l] == ':' && ++ strncmp(sb->set_name, homehost, l) == 0); ++} ++ ++static void uuid_from_super1(int uuid[4], void * sbv) ++{ ++ struct mdp_superblock_1 *super = sbv; ++ char *cuuid = (char*)uuid; ++ int i; ++ for (i=0; i<16; i++) ++ cuuid[i] = super->set_uuid[i]; ++} ++ ++static void getinfo_super1(struct mdinfo *info, void *sbv) ++{ ++ struct mdp_superblock_1 *sb = sbv; ++ int working = 0; ++ int i; ++ int role; ++ ++ info->array.major_version = 1; ++ info->array.minor_version = __le32_to_cpu(sb->feature_map); ++ info->array.patch_version = 0; ++ info->array.raid_disks = __le32_to_cpu(sb->raid_disks); ++ info->array.level = __le32_to_cpu(sb->level); ++ info->array.layout = __le32_to_cpu(sb->layout); ++ info->array.md_minor = -1; ++ info->array.ctime = __le64_to_cpu(sb->ctime); ++ info->array.utime = __le64_to_cpu(sb->utime); ++ info->array.chunk_size = __le32_to_cpu(sb->chunksize)*512; ++ info->array.state = ++ (__le64_to_cpu(sb->resync_offset) >= __le64_to_cpu(sb->size)) ++ ? 1 : 0; ++ ++ info->data_offset = __le64_to_cpu(sb->data_offset); ++ info->component_size = __le64_to_cpu(sb->size); ++ ++ info->disk.major = 0; ++ info->disk.minor = 0; ++ info->disk.number = __le32_to_cpu(sb->dev_number); ++ if (__le32_to_cpu(sb->dev_number) >= __le32_to_cpu(sb->max_dev) || ++ __le32_to_cpu(sb->max_dev) > 512) ++ role = 0xfffe; ++ else ++ role = __le16_to_cpu(sb->dev_roles[__le32_to_cpu(sb->dev_number)]); ++ ++ info->disk.raid_disk = -1; ++ switch(role) { ++ case 0xFFFF: ++ info->disk.state = 2; /* spare: ACTIVE, not sync, not faulty */ ++ break; ++ case 0xFFFE: ++ info->disk.state = 1; /* faulty */ ++ break; ++ default: ++ info->disk.state = 6; /* active and in sync */ ++ info->disk.raid_disk = role; ++ } ++ info->events = __le64_to_cpu(sb->events); ++ ++ memcpy(info->uuid, sb->set_uuid, 16); ++ ++ strncpy(info->name, sb->set_name, 32); ++ info->name[32] = 0; ++ ++ if (sb->feature_map & __le32_to_cpu(MD_FEATURE_RESHAPE_ACTIVE)) { ++ info->reshape_active = 1; ++ info->reshape_progress = __le64_to_cpu(sb->reshape_position); ++ info->new_level = __le32_to_cpu(sb->new_level); ++ info->delta_disks = __le32_to_cpu(sb->delta_disks); ++ info->new_layout = __le32_to_cpu(sb->new_layout); ++ info->new_chunk = __le32_to_cpu(sb->new_chunk)<<9; ++ } else ++ info->reshape_active = 0; ++ ++ for (i=0; i< __le32_to_cpu(sb->max_dev); i++) { ++ role = __le16_to_cpu(sb->dev_roles[i]); ++ if (/*role == 0xFFFF || */role < info->array.raid_disks) ++ working++; ++ } ++ ++ info->array.working_disks = working; ++} ++ ++static int update_super1(struct mdinfo *info, void *sbv, char *update, ++ char *devname, int verbose, ++ int uuid_set, char *homehost) ++{ ++ /* NOTE: for 'assemble' and 'force' we need to return non-zero if any change was made. ++ * For others, the return value is ignored. ++ */ ++ int rv = 0; ++ struct mdp_superblock_1 *sb = sbv; ++ ++ if (strcmp(update, "force-one")==0) { ++ /* Not enough devices for a working array, ++ * so bring this one up-to-date ++ */ ++ if (sb->events != __cpu_to_le64(info->events)) ++ rv = 1; ++ sb->events = __cpu_to_le64(info->events); ++ } ++ if (strcmp(update, "force-array")==0) { ++ /* Degraded array and 'force' requests to ++ * maybe need to mark it 'clean'. ++ */ ++ switch(__le32_to_cpu(sb->level)) { ++ case 5: case 4: case 6: ++ /* need to force clean */ ++ if (sb->resync_offset != ~0ULL) ++ rv = 1; ++ sb->resync_offset = ~0ULL; ++ } ++ } ++ if (strcmp(update, "assemble")==0) { ++ int d = info->disk.number; ++ int want; ++ if (info->disk.state == 6) ++ want = __cpu_to_le32(info->disk.raid_disk); ++ else ++ want = 0xFFFF; ++ if (sb->dev_roles[d] != want) { ++ sb->dev_roles[d] = want; ++ rv = 1; ++ } ++ } ++ if (strcmp(update, "linear-grow-new") == 0) { ++ int i; ++ int rfd; ++ int max = __le32_to_cpu(sb->max_dev); ++ ++ for (i=0 ; i < max ; i++) ++ if (__le16_to_cpu(sb->dev_roles[i]) >= 0xfffe) ++ break; ++ sb->dev_number = __cpu_to_le32(i); ++ info->disk.number = i; ++ if (max >= __le32_to_cpu(sb->max_dev)) ++ sb->max_dev = __cpu_to_le32(max+1); ++ ++ if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 || ++ read(rfd, sb->device_uuid, 16) != 16) { ++ *(__u32*)(sb->device_uuid) = random(); ++ *(__u32*)(sb->device_uuid+4) = random(); ++ *(__u32*)(sb->device_uuid+8) = random(); ++ *(__u32*)(sb->device_uuid+12) = random(); ++ } ++ ++ sb->dev_roles[i] = ++ __cpu_to_le16(info->disk.raid_disk); ++ } ++ if (strcmp(update, "linear-grow-update") == 0) { ++ sb->raid_disks = __cpu_to_le32(info->array.raid_disks); ++ sb->dev_roles[info->disk.number] = ++ __cpu_to_le16(info->disk.raid_disk); ++ } ++ if (strcmp(update, "resync") == 0) { ++ /* make sure resync happens */ ++ sb->resync_offset = 0ULL; ++ } ++ if (strcmp(update, "uuid") == 0) { ++ copy_uuid(sb->set_uuid, info->uuid, super1.swapuuid); ++ ++ if (__le32_to_cpu(sb->feature_map)&MD_FEATURE_BITMAP_OFFSET) { ++ struct bitmap_super_s *bm; ++ bm = (struct bitmap_super_s*)(sbv+1024); ++ memcpy(bm->uuid, sb->set_uuid, 16); ++ } ++ } ++ if (strcmp(update, "homehost") == 0 && ++ homehost) { ++ char *c; ++ update = "name"; ++ c = strchr(sb->set_name, ':'); ++ if (c) ++ strncpy(info->name, c+1, 31 - (c-sb->set_name)); ++ else ++ strncpy(info->name, sb->set_name, 32); ++ info->name[32] = 0; ++ } ++ if (strcmp(update, "name") == 0) { ++ if (info->name[0] == 0) ++ sprintf(info->name, "%d", info->array.md_minor); ++ memset(sb->set_name, 0, sizeof(sb->set_name)); ++ if (homehost && ++ strchr(info->name, ':') == NULL && ++ strlen(homehost)+1+strlen(info->name) < 32) { ++ strcpy(sb->set_name, homehost); ++ strcat(sb->set_name, ":"); ++ strcat(sb->set_name, info->name); ++ } else ++ strcpy(sb->set_name, info->name); ++ } ++ if (strcmp(update, "devicesize") == 0 && ++ __le64_to_cpu(sb->super_offset) < ++ __le64_to_cpu(sb->data_offset)) { ++ /* set data_size to device size less data_offset */ ++ struct misc_dev_info *misc = (struct misc_dev_info*) ++ (sbv + 1024 + sizeof(struct bitmap_super_s)); ++ printf("Size was %llu\n", (unsigned long long) ++ __le64_to_cpu(sb->data_size)); ++ sb->data_size = __cpu_to_le64( ++ misc->device_size - __le64_to_cpu(sb->data_offset)); ++ printf("Size is %llu\n", (unsigned long long) ++ __le64_to_cpu(sb->data_size)); ++ } ++ if (strcmp(update, "_reshape_progress")==0) ++ sb->reshape_position = __cpu_to_le64(info->reshape_progress); ++ ++ sb->sb_csum = calc_sb_1_csum(sb); ++ return rv; ++} ++ ++static void locate_bitmap1(struct supertype *st, int fd, void *sbv); ++ ++static int store_super1(struct supertype *st, int fd, void *sbv) ++{ ++ struct mdp_superblock_1 *sb = sbv; ++ unsigned long long sb_offset; ++ int sbsize; ++ unsigned long long dsize; ++ ++ if (!get_dev_size(fd, NULL, &dsize)) ++ return 1; ++ ++ dsize >>= 9; ++ ++ if (dsize < 24) ++ return 2; ++ ++ /* ++ * Calculate the position of the superblock. ++ * It is always aligned to a 4K boundary and ++ * depending on minor_version, it can be: ++ * 0: At least 8K, but less than 12K, from end of device ++ * 1: At start of device ++ * 2: 4K from start of device. ++ */ ++ switch(st->minor_version) { ++ case 0: ++ sb_offset = dsize; ++ sb_offset -= 8*2; ++ sb_offset &= ~(4*2-1); ++ break; ++ case 1: ++ sb_offset = 0; ++ break; ++ case 2: ++ sb_offset = 4*2; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ ++ ++ if (sb_offset != __le64_to_cpu(sb->super_offset) && ++ 0 != __le64_to_cpu(sb->super_offset) ++ ) { ++ fprintf(stderr, Name ": internal error - sb_offset is wrong\n"); ++ abort(); ++ } ++ ++ if (lseek64(fd, sb_offset << 9, 0)< 0LL) ++ return 3; ++ ++ sbsize = sizeof(*sb) + 2 * __le32_to_cpu(sb->max_dev); ++ ++ if (write(fd, sb, sbsize) != sbsize) ++ return 4; ++ ++ if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) { ++ struct bitmap_super_s *bm = (struct bitmap_super_s*) ++ (((char*)sb)+1024); ++ if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC) { ++ locate_bitmap1(st, fd, sbv); ++ if (write(fd, bm, sizeof(*bm)) != sizeof(*bm)) ++ return 5; ++ } ++ } ++ fsync(fd); ++ return 0; ++} ++ ++static int load_super1(struct supertype *st, int fd, void **sbp, char *devname); ++ ++static int compare_super1(void **firstp, void *secondv) ++{ ++ /* ++ * return: ++ * 0 same, or first was empty, and second was copied ++ * 1 second had wrong number ++ * 2 wrong uuid ++ * 3 wrong other info ++ */ ++ struct mdp_superblock_1 *first = *firstp; ++ struct mdp_superblock_1 *second = secondv; ++ ++ if (second->magic != __cpu_to_le32(MD_SB_MAGIC)) ++ return 1; ++ if (second->major_version != __cpu_to_le32(1)) ++ return 1; ++ ++ if (!first) { ++ first = malloc(1024+sizeof(bitmap_super_t) + ++ sizeof(struct misc_dev_info)); ++ memcpy(first, second, 1024+sizeof(bitmap_super_t) + ++ sizeof(struct misc_dev_info)); ++ *firstp = first; ++ return 0; ++ } ++ if (memcmp(first->set_uuid, second->set_uuid, 16)!= 0) ++ return 2; ++ ++ if (first->ctime != second->ctime || ++ first->level != second->level || ++ first->layout != second->layout || ++ first->size != second->size || ++ first->chunksize != second->chunksize || ++ first->raid_disks != second->raid_disks) ++ return 3; ++ return 0; ++} ++ ++static int load_super1(struct supertype *st, int fd, void **sbp, char *devname) ++{ ++ unsigned long long dsize; ++ unsigned long long sb_offset; ++ struct mdp_superblock_1 *super; ++ int uuid[4]; ++ struct bitmap_super_s *bsb; ++ struct misc_dev_info *misc; ++ ++ ++ if (st->ss == NULL) { ++ int bestvers = -1; ++ __u64 bestctime = 0; ++ /* guess... choose latest ctime */ ++ st->ss = &super1; ++ for (st->minor_version = 0; st->minor_version <= 2 ; st->minor_version++) { ++ switch(load_super1(st, fd, sbp, devname)) { ++ case 0: super = *sbp; ++ if (bestvers == -1 || ++ bestctime < __le64_to_cpu(super->ctime)) { ++ bestvers = st->minor_version; ++ bestctime = __le64_to_cpu(super->ctime); ++ } ++ free(super); ++ *sbp = NULL; ++ break; ++ case 1: st->ss = NULL; return 1; /*bad device */ ++ case 2: break; /* bad, try next */ ++ } ++ } ++ if (bestvers != -1) { ++ int rv; ++ st->minor_version = bestvers; ++ st->ss = &super1; ++ st->max_devs = 384; ++ rv = load_super1(st, fd, sbp, devname); ++ if (rv) st->ss = NULL; ++ return rv; ++ } ++ st->ss = NULL; ++ return 2; ++ } ++ if (!get_dev_size(fd, devname, &dsize)) ++ return 1; ++ dsize >>= 9; ++ ++ if (dsize < 24) { ++ if (devname) ++ fprintf(stderr, Name ": %s is too small for md: size is %llu sectors.\n", ++ devname, dsize); ++ return 1; ++ } ++ ++ /* ++ * Calculate the position of the superblock. ++ * It is always aligned to a 4K boundary and ++ * depending on minor_version, it can be: ++ * 0: At least 8K, but less than 12K, from end of device ++ * 1: At start of device ++ * 2: 4K from start of device. ++ */ ++ switch(st->minor_version) { ++ case 0: ++ sb_offset = dsize; ++ sb_offset -= 8*2; ++ sb_offset &= ~(4*2-1); ++ break; ++ case 1: ++ sb_offset = 0; ++ break; ++ case 2: ++ sb_offset = 4*2; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ ioctl(fd, BLKFLSBUF, 0); /* make sure we read current data */ ++ ++ ++ if (lseek64(fd, sb_offset << 9, 0)< 0LL) { ++ if (devname) ++ fprintf(stderr, Name ": Cannot seek to superblock on %s: %s\n", ++ devname, strerror(errno)); ++ return 1; ++ } ++ ++ super = malloc(1024 + sizeof(bitmap_super_t) + ++ sizeof(struct misc_dev_info)); ++ ++ if (read(fd, super, 1024) != 1024) { ++ if (devname) ++ fprintf(stderr, Name ": Cannot read superblock on %s\n", ++ devname); ++ free(super); ++ return 1; ++ } ++ ++ if (__le32_to_cpu(super->magic) != MD_SB_MAGIC) { ++ if (devname) ++ fprintf(stderr, Name ": No super block found on %s (Expected magic %08x, got %08x)\n", ++ devname, MD_SB_MAGIC, __le32_to_cpu(super->magic)); ++ free(super); ++ return 2; ++ } ++ ++ if (__le32_to_cpu(super->major_version) != 1) { ++ if (devname) ++ fprintf(stderr, Name ": Cannot interpret superblock on %s - version is %d\n", ++ devname, __le32_to_cpu(super->major_version)); ++ free(super); ++ return 2; ++ } ++ if (__le64_to_cpu(super->super_offset) != sb_offset) { ++ if (devname) ++ fprintf(stderr, Name ": No superblock found on %s (super_offset is wrong)\n", ++ devname); ++ free(super); ++ return 2; ++ } ++ *sbp = super; ++ ++ bsb = (struct bitmap_super_s *)(((char*)super)+1024); ++ ++ misc = (struct misc_dev_info*) (bsb+1); ++ misc->device_size = dsize; ++ ++ /* Now check on the bitmap superblock */ ++ if ((__le32_to_cpu(super->feature_map)&MD_FEATURE_BITMAP_OFFSET) == 0) ++ return 0; ++ /* Read the bitmap superblock and make sure it looks ++ * valid. If it doesn't clear the bit. An --assemble --force ++ * should get that written out. ++ */ ++ locate_bitmap1(st, fd, super); ++ if (read(fd, ((char*)super)+1024, sizeof(struct bitmap_super_s)) ++ != sizeof(struct bitmap_super_s)) ++ goto no_bitmap; ++ ++ uuid_from_super1(uuid, super); ++ if (__le32_to_cpu(bsb->magic) != BITMAP_MAGIC || ++ memcmp(bsb->uuid, uuid, 16) != 0) ++ goto no_bitmap; ++ return 0; ++ ++ no_bitmap: ++ super->feature_map = __cpu_to_le32(__le32_to_cpu(super->feature_map) & ~1); ++ return 0; ++} ++ ++ ++static struct supertype *match_metadata_desc1(char *arg) ++{ ++ struct supertype *st = malloc(sizeof(*st)); ++ if (!st) return st; ++ ++ st->ss = &super1; ++ st->max_devs = 384; ++ if (strcmp(arg, "1") == 0 || ++ strcmp(arg, "1.0") == 0 || ++ strcmp(arg, "default/large") == 0) { ++ st->minor_version = 0; ++ return st; ++ } ++ if (strcmp(arg, "1.1") == 0) { ++ st->minor_version = 1; ++ return st; ++ } ++ if (strcmp(arg, "1.2") == 0) { ++ st->minor_version = 2; ++ return st; ++ } ++ ++ free(st); ++ return NULL; ++} ++ ++static void locate_bitmap1(struct supertype *st, int fd, void *sbv) ++{ ++ unsigned long long offset; ++ struct mdp_superblock_1 *sb; ++ int mustfree = 0; ++ ++ if (!sbv) { ++ if (st->ss->load_super(st, fd, &sbv, NULL)) ++ return; /* no error I hope... */ ++ mustfree = 1; ++ } ++ sb = sbv; ++ ++ offset = __le64_to_cpu(sb->super_offset); ++ offset += (int32_t) __le32_to_cpu(sb->bitmap_offset); ++ if (mustfree) ++ free(sb); ++ lseek64(fd, offset<<9, 0); ++} ++ ++struct superswitch super1 = { ++ .examine_super = NULL, ++ .brief_examine_super = brief_examine_super1, ++ .detail_super = NULL, ++ .brief_detail_super = NULL, ++ .export_super = NULL, ++ .match_home = match_home1, ++ .uuid_from_super = uuid_from_super1, ++ .getinfo_super = getinfo_super1, ++ .update_super = update_super1, ++ .init_super = NULL, ++ .add_to_super = NULL, ++ .store_super = store_super1, ++ .write_init_super = NULL, ++ .compare_super = compare_super1, ++ .load_super = load_super1, ++ .match_metadata_desc = match_metadata_desc1, ++ .avail_size = NULL, ++ .add_internal_bitmap = NULL, ++ .locate_bitmap = locate_bitmap1, ++ .write_bitmap = NULL, ++ .major = 1, ++#if __BYTE_ORDER == BIG_ENDIAN ++ .swapuuid = 0, ++#else ++ .swapuuid = 1, ++#endif ++}; +--- a/mdadm/util.c 1970-01-01 03:00:00.000000000 +0300 ++++ mdadm/mdadm/util.c 2011-01-12 21:33:01.000000000 +0200 +@@ -0,0 +1,652 @@ ++/* ++ * mdadm - manage Linux "md" devices aka RAID arrays. ++ * ++ * Copyright (C) 2001-2006 Neil Brown ++ * ++ * ++ * 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 ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * Author: Neil Brown ++ * Email: ++ * Paper: Neil Brown ++ * School of Computer Science and Engineering ++ * The University of New South Wales ++ * Sydney, 2052 ++ * Australia ++ */ ++ ++#include "mdadm.h" ++#include "md_p.h" ++#include ++#include ++ ++/* ++ * following taken from linux/blkpg.h because they aren't ++ * anywhere else and it isn't safe to #include linux/ * stuff. ++ */ ++ ++#define BLKPG _IO(0x12,105) ++ ++/* The argument structure */ ++struct blkpg_ioctl_arg { ++ int op; ++ int flags; ++ int datalen; ++ void *data; ++}; ++ ++/* The subfunctions (for the op field) */ ++#define BLKPG_ADD_PARTITION 1 ++#define BLKPG_DEL_PARTITION 2 ++ ++/* Sizes of name fields. Unused at present. */ ++#define BLKPG_DEVNAMELTH 64 ++#define BLKPG_VOLNAMELTH 64 ++ ++/* The data structure for ADD_PARTITION and DEL_PARTITION */ ++struct blkpg_partition { ++ long long start; /* starting offset in bytes */ ++ long long length; /* length in bytes */ ++ int pno; /* partition number */ ++ char devname[BLKPG_DEVNAMELTH]; /* partition name, like sda5 or c0d1p2, ++ to be used in kernel messages */ ++ char volname[BLKPG_VOLNAMELTH]; /* volume label */ ++}; ++ ++/* ++ * Parse a 128 bit uuid in 4 integers ++ * format is 32 hexx nibbles with options :. separator ++ * If not exactly 32 hex digits are found, return 0 ++ * else return 1 ++ */ ++int parse_uuid(char *str, int uuid[4]) ++{ ++ int hit = 0; /* number of Hex digIT */ ++ int i; ++ char c; ++ for (i=0; i<4; i++) uuid[i]=0; ++ ++ while ((c= *str++)) { ++ int n; ++ if (c>='0' && c<='9') ++ n = c-'0'; ++ else if (c>='a' && c <= 'f') ++ n = 10 + c - 'a'; ++ else if (c>='A' && c <= 'F') ++ n = 10 + c - 'A'; ++ else if (strchr(":. -", c)) ++ continue; ++ else return 0; ++ ++ if (hit<32) { ++ uuid[hit/8] <<= 4; ++ uuid[hit/8] += n; ++ } ++ hit++; ++ } ++ if (hit == 32) ++ return 1; ++ return 0; ++ ++} ++ ++ ++/* ++ * Get the md version number. ++ * We use the RAID_VERSION ioctl if it is supported ++ * If not, but we have a block device with major '9', we assume ++ * 0.36.0 ++ * ++ * Return version number as 24 but number - assume version parts ++ * always < 255 ++ */ ++ ++int md_get_version(int fd) ++{ ++ struct stat stb; ++ mdu_version_t vers; ++ ++ if (fstat(fd, &stb)<0) ++ return -1; ++ if ((S_IFMT&stb.st_mode) != S_IFBLK) ++ return -1; ++ ++ if (ioctl(fd, RAID_VERSION, &vers) == 0) ++ return (vers.major*10000) + (vers.minor*100) + vers.patchlevel; ++ if (errno == EACCES) ++ return -1; ++ if (major(stb.st_rdev) == MD_MAJOR) ++ return (3600); ++ return -1; ++} ++ ++ ++int get_linux_version() ++{ ++ struct utsname name; ++ char *cp; ++ int a,b,c; ++ if (uname(&name) <0) ++ return -1; ++ ++ cp = name.release; ++ a = strtoul(cp, &cp, 10); ++ if (*cp != '.') return -1; ++ b = strtoul(cp+1, &cp, 10); ++ if (*cp != '.') return -1; ++ c = strtoul(cp+1, NULL, 10); ++ ++ return (a*1000000)+(b*1000)+c; ++} ++ ++void remove_partitions(int fd) ++{ ++ /* remove partitions from this block devices. ++ * This is used for components added to an array ++ */ ++#ifdef BLKPG_DEL_PARTITION ++ struct blkpg_ioctl_arg a; ++ struct blkpg_partition p; ++ ++ a.op = BLKPG_DEL_PARTITION; ++ a.data = (void*)&p; ++ a.datalen = sizeof(p); ++ a.flags = 0; ++ memset(a.data, 0, a.datalen); ++ for (p.pno=0; p.pno < 16; p.pno++) ++ ioctl(fd, BLKPG, &a); ++#endif ++} ++ ++int enough(int level, int raid_disks, int layout, int clean, ++ char *avail, int avail_disks) ++{ ++ int copies, first; ++ switch (level) { ++ case 10: ++ /* This is the tricky one - we need to check ++ * which actual disks are present. ++ */ ++ copies = (layout&255)* ((layout>>8) & 255); ++ first=0; ++ do { ++ /* there must be one of the 'copies' form 'first' */ ++ int n = copies; ++ int cnt=0; ++ while (n--) { ++ if (avail[first]) ++ cnt++; ++ first = (first+1) % raid_disks; ++ } ++ if (cnt == 0) ++ return 0; ++ ++ } while (first != 0); ++ return 1; ++ ++ case -4: ++ return avail_disks>= 1; ++ case -1: ++ case 0: ++ return avail_disks == raid_disks; ++ case 1: ++ return avail_disks >= 1; ++ case 4: ++ case 5: ++ if (clean) ++ return avail_disks >= raid_disks-1; ++ else ++ return avail_disks >= raid_disks; ++ case 6: ++ if (clean) ++ return avail_disks >= raid_disks-2; ++ else ++ return avail_disks >= raid_disks; ++ default: ++ return 0; ++ } ++} ++ ++int same_uuid(int a[4], int b[4], int swapuuid) ++{ ++ if (swapuuid) { ++ /* parse uuids are hostendian. ++ * uuid's from some superblocks are big-ending ++ * if there is a difference, we need to swap.. ++ */ ++ unsigned char *ac = (unsigned char *)a; ++ unsigned char *bc = (unsigned char *)b; ++ int i; ++ for (i=0; i<16; i+= 4) { ++ if (ac[i+0] != bc[i+3] || ++ ac[i+1] != bc[i+2] || ++ ac[i+2] != bc[i+1] || ++ ac[i+3] != bc[i+0]) ++ return 0; ++ } ++ return 1; ++ } else { ++ if (a[0]==b[0] && ++ a[1]==b[1] && ++ a[2]==b[2] && ++ a[3]==b[3]) ++ return 1; ++ return 0; ++ } ++} ++void copy_uuid(void *a, int b[4], int swapuuid) ++{ ++ if (swapuuid) { ++ /* parse uuids are hostendian. ++ * uuid's from some superblocks are big-ending ++ * if there is a difference, we need to swap.. ++ */ ++ unsigned char *ac = (unsigned char *)a; ++ unsigned char *bc = (unsigned char *)b; ++ int i; ++ for (i=0; i<16; i+= 4) { ++ ac[i+0] = bc[i+3]; ++ ac[i+1] = bc[i+2]; ++ ac[i+2] = bc[i+1]; ++ ac[i+3] = bc[i+0]; ++ } ++ } else ++ memcpy(a, b, 16); ++} ++ ++char *map_num(mapping_t *map, int num) ++{ ++ while (map->name) { ++ if (map->num == num) ++ return map->name; ++ map++; ++ } ++ return NULL; ++} ++ ++int map_name(mapping_t *map, char *name) ++{ ++ while (map->name) { ++ if (strcmp(map->name, name)==0) ++ return map->num; ++ map++; ++ } ++ return UnSet; ++} ++ ++ ++int is_standard(char *dev, int *nump) ++{ ++ /* tests if dev is a "standard" md dev name. ++ * i.e if the last component is "/dNN" or "/mdNN", ++ * where NN is a string of digits ++ */ ++ char *d = strrchr(dev, '/'); ++ int type=0; ++ int num; ++ if (!d) ++ return 0; ++ if (strncmp(d, "/d",2)==0) ++ d += 2, type=1; /* /dev/md/dN{pM} */ ++ else if (strncmp(d, "/md_d", 5)==0) ++ d += 5, type=1; /* /dev/md_dNpM */ ++ else if (strncmp(d, "/md", 3)==0) ++ d += 3, type=-1; /* /dev/mdN */ ++ else if (d-dev > 3 && strncmp(d-2, "md/", 3)==0) ++ d += 1, type=-1; /* /dev/md/N */ ++ else ++ return 0; ++ if (!*d) ++ return 0; ++ num = atoi(d); ++ while (isdigit(*d)) ++ d++; ++ if (*d) ++ return 0; ++ if (nump) *nump = num; ++ ++ return type; ++} ++ ++ ++/* ++ * convert a major/minor pair for a block device into a name in /dev, if possible. ++ * On the first call, walk /dev collecting name. ++ * Put them in a simple linked listfor now. ++ */ ++struct devmap { ++ int major, minor; ++ char *name; ++ struct devmap *next; ++} *devlist = NULL; ++int devlist_ready = 0; ++ ++int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s) ++{ ++ struct stat st; ++ if (S_ISLNK(stb->st_mode)) { ++ stat(name, &st); ++ stb = &st; ++ } ++ ++ if ((stb->st_mode&S_IFMT)== S_IFBLK) { ++ char *n = strdup(name); ++ struct devmap *dm = malloc(sizeof(*dm)); ++ if (strncmp(n, "/dev/./", 7)==0) ++ strcpy(n+4, name+6); ++ if (dm) { ++ dm->major = major(stb->st_rdev); ++ dm->minor = minor(stb->st_rdev); ++ dm->name = n; ++ dm->next = devlist; ++ devlist = dm; ++ } ++ } ++ return 0; ++} ++ ++#ifndef HAVE_NFTW ++#ifdef HAVE_FTW ++int add_dev_1(const char *name, const struct stat *stb, int flag) ++{ ++ return add_dev(name, stb, flag, NULL); ++} ++int nftw(const char *path, int (*han)(const char *name, const struct stat *stb, int flag, struct FTW *s), int nopenfd, int flags) ++{ ++ return ftw(path, add_dev_1, nopenfd); ++} ++#else ++int nftw(const char *path, int (*han)(const char *name, const struct stat *stb, int flag, struct FTW *s), int nopenfd, int flags) ++{ ++ return 0; ++} ++#endif /* HAVE_FTW */ ++#endif /* HAVE_NFTW */ ++ ++/* ++ * Find a block device with the right major/minor number. ++ * If we find multiple names, choose the shortest. ++ * If we find a non-standard name, it is probably there ++ * deliberately so prefer it over a standard name. ++ * This applies only to names for MD devices. ++ */ ++char *map_dev(int major, int minor, int create) ++{ ++ struct devmap *p; ++ char *std = NULL, *nonstd=NULL; ++ int did_check = 0; ++ ++ if (major == 0 && minor == 0) ++ return NULL; ++ ++ retry: ++ if (!devlist_ready) { ++ char *dev = "/dev"; ++ struct stat stb; ++ while(devlist) { ++ struct devmap *d = devlist; ++ devlist = d->next; ++ free(d->name); ++ free(d); ++ } ++ if (lstat(dev, &stb)==0 && ++ S_ISLNK(stb.st_mode)) ++ dev = "/dev/."; ++ nftw(dev, add_dev, 10, FTW_PHYS); ++ devlist_ready=1; ++ did_check = 1; ++ } ++ ++ for (p=devlist; p; p=p->next) ++ if (p->major == major && ++ p->minor == minor) { ++ if (is_standard(p->name, NULL)) { ++ if (std == NULL || ++ strlen(p->name) < strlen(std)) ++ std = p->name; ++ } else { ++ if (nonstd == NULL || ++ strlen(p->name) < strlen(nonstd)) ++ nonstd = p->name; ++ } ++ } ++ if (!std && !nonstd && !did_check) { ++ devlist_ready = 0; ++ goto retry; ++ } ++ if (create && !std && !nonstd) { ++ static char buf[30]; ++ snprintf(buf, sizeof(buf), "%d:%d", major, minor); ++ nonstd = buf; ++ } ++ ++ return nonstd ? nonstd : std; ++} ++ ++unsigned long calc_csum(void *super, int bytes) ++{ ++ unsigned long long newcsum = 0; ++ int i; ++ unsigned int csum; ++ unsigned int *superc = (unsigned int*) super; ++ ++ for(i=0; i>32); ++#ifdef __alpha__ ++/* The in-kernel checksum calculation is always 16bit on ++ * the alpha, though it is 32 bit on i386... ++ * I wonder what it is elsewhere... (it uses and API in ++ * a way that it shouldn't). ++ */ ++ csum = (csum & 0xffff) + (csum >> 16); ++ csum = (csum & 0xffff) + (csum >> 16); ++#endif ++ return csum; ++} ++ ++char *human_size(long long bytes) ++{ ++ static char buf[30]; ++ ++ /* We convert bytes to either centi-M{ega,ibi}bytes or ++ * centi-G{igi,ibi}bytes, with appropriate rounding, ++ * and then print 1/100th of those as a decimal. ++ * We allow upto 2048Megabytes before converting to ++ * gigabytes, as that shows more precision and isn't ++ * too large a number. ++ * Terrabytes are not yet handled. ++ */ ++ ++ if (bytes < 5000*1024) ++ buf[0]=0; ++ else if (bytes < 2*1024LL*1024LL*1024LL) { ++ long cMiB = (bytes / ( (1LL<<20) / 200LL ) +1) /2; ++ long cMB = (bytes / ( 1000000LL / 200LL ) +1) /2; ++ snprintf(buf, sizeof(buf), " (%ld.%02ld MiB %ld.%02ld MB)", ++ cMiB/100 , cMiB % 100, ++ cMB/100, cMB % 100); ++ } else { ++ long cGiB = (bytes / ( (1LL<<30) / 200LL ) +1) /2; ++ long cGB = (bytes / (1000000000LL/200LL ) +1) /2; ++ snprintf(buf, sizeof(buf), " (%ld.%02ld GiB %ld.%02ld GB)", ++ cGiB/100 , cGiB % 100, ++ cGB/100, cGB % 100); ++ } ++ return buf; ++} ++ ++char *human_size_brief(long long bytes) ++{ ++ static char buf[30]; ++ ++ ++ if (bytes < 5000*1024) ++ snprintf(buf, sizeof(buf), "%ld.%02ldKiB", ++ (long)(bytes>>10), (long)(((bytes&1023)*100+512)/1024) ++ ); ++ else if (bytes < 2*1024LL*1024LL*1024LL) ++ snprintf(buf, sizeof(buf), "%ld.%02ldMiB", ++ (long)(bytes>>20), ++ (long)((bytes&0xfffff)+0x100000/200)/(0x100000/100) ++ ); ++ else ++ snprintf(buf, sizeof(buf), "%ld.%02ldGiB", ++ (long)(bytes>>30), ++ (long)(((bytes>>10)&0xfffff)+0x100000/200)/(0x100000/100) ++ ); ++ return buf; ++} ++ ++int get_mdp_major(void) ++{ ++static int mdp_major = -1; ++ FILE *fl; ++ char *w; ++ int have_block = 0; ++ int have_devices = 0; ++ int last_num = -1; ++ ++ if (mdp_major != -1) ++ return mdp_major; ++ fl = fopen("/proc/devices", "r"); ++ if (!fl) ++ return -1; ++ while ((w = conf_word(fl, 1))) { ++ if (have_block && strcmp(w, "devices:")==0) ++ have_devices = 1; ++ have_block = (strcmp(w, "Block")==0); ++ if (isdigit(w[0])) ++ last_num = atoi(w); ++ if (have_devices && strcmp(w, "mdp")==0) ++ mdp_major = last_num; ++ free(w); ++ } ++ fclose(fl); ++ return mdp_major; ++} ++ ++int dev_open(char *dev, int flags) ++{ ++ /* like 'open', but if 'dev' matches %d:%d, create a temp ++ * block device and open that ++ */ ++ char *e; ++ int fd = -1; ++ char devname[32]; ++ int major; ++ int minor; ++ ++ if (!dev) return -1; ++ ++ major = strtoul(dev, &e, 0); ++ if (e > dev && *e == ':' && e[1] && ++ (minor = strtoul(e+1, &e, 0)) >= 0 && ++ *e == 0) { ++ snprintf(devname, sizeof(devname), "/dev/.tmp.md.%d:%d", major, minor); ++ if (mknod(devname, S_IFBLK|0600, makedev(major, minor))==0) { ++ fd = open(devname, flags); ++ unlink(devname); ++ } ++ } else ++ fd = open(dev, flags); ++ return fd; ++} ++ ++struct superswitch *superlist[] = { &super0, &super1, NULL }; ++ ++struct supertype *super_by_version(int vers, int minor) ++{ ++ struct supertype *st = malloc(sizeof(*st)); ++ if (!st) return st; ++ if (vers == 0) { ++ st->ss = &super0; ++ st->max_devs = MD_SB_DISKS; ++ } ++ ++ if (vers == 1) { ++ st->ss = &super1; ++ st->max_devs = 384; ++ } ++ st->minor_version = minor; ++ return st; ++} ++ ++struct supertype *guess_super(int fd) ++{ ++ /* try each load_super to find the best match, ++ * and return the best superswitch ++ */ ++ struct superswitch *ss; ++ struct supertype *st; ++ unsigned long besttime = 0; ++ int bestsuper = -1; ++ ++ void *sbp = NULL; ++ int i; ++ ++ st = malloc(sizeof(*st)); ++ memset(st, 0, sizeof(*st)); ++ for (i=0 ; superlist[i]; i++) { ++ int rv; ++ ss = superlist[i]; ++ st->ss = NULL; ++ rv = ss->load_super(st, fd, &sbp, NULL); ++ if (rv == 0) { ++ struct mdinfo info; ++ ss->getinfo_super(&info, sbp); ++ if (bestsuper == -1 || ++ besttime < info.array.ctime) { ++ bestsuper = i; ++ besttime = info.array.ctime; ++ } ++ free(sbp); ++ } ++ } ++ if (bestsuper != -1) { ++ int rv; ++ st->ss = NULL; ++ rv = superlist[bestsuper]->load_super(st, fd, &sbp, NULL); ++ if (rv == 0) { ++ free(sbp); ++ return st; ++ } ++ } ++ free(st); ++ return NULL; ++} ++ ++/* Return size of device in bytes */ ++int get_dev_size(int fd, char *dname, unsigned long long *sizep) ++{ ++ unsigned long long ldsize; ++#ifdef BLKGETSIZE64 ++ if (ioctl(fd, BLKGETSIZE64, &ldsize) != 0) ++#endif ++ { ++ unsigned long dsize; ++ if (ioctl(fd, BLKGETSIZE, &dsize) == 0) { ++ ldsize = dsize; ++ ldsize <<= 9; ++ } else { ++ if (dname) ++ fprintf(stderr, Name ": Cannot get size of %s: %s\b", ++ dname, strerror(errno)); ++ return 0; ++ } ++ } ++ *sizep = ldsize; ++ return 1; ++} diff -pruN genkernel.a/patches/busybox/1.18.1/1.18.1-mdstart.diff genkernel.b/patches/busybox/1.18.1/1.18.1-mdstart.diff --- genkernel.a/patches/busybox/1.18.1/1.18.1-mdstart.diff 1970-01-01 03:00:00.000000000 +0300 +++ genkernel.b/patches/busybox/1.18.1/1.18.1-mdstart.diff 2011-01-12 21:32:10.000000000 +0200 @@ -0,0 +1,113 @@ +Based on: + +> Forward-port the old mdstart tool from the Gentoo Busybox-1.1.3. +> Only fires the RAID_AUTORUN ioctl on existing /dev/md nodes. + +> Signed-off-by: Robin H. Johnson + +diff -pruN a/include/usage.src.h mdstart/include/usage.src.h +--- a/include/usage.src.h 2010-12-21 06:29:45.000000000 +0200 ++++ mdstart/include/usage.src.h 2011-01-12 21:29:47.000000000 +0200 +@@ -847,6 +847,11 @@ INSERT + "$ dirname /tmp/foo/\n" \ + "/tmp\n" + ++#define mdstart_trivial_usage \ ++ "{[PARTITION] MD-NODE}..." ++#define mdstart_full_usage \ ++ Run the RAID_AUTORUN ioctl on the given MD number" ++ + #define dmesg_trivial_usage \ + "[-c] [-n LEVEL] [-s SIZE]" + #define dmesg_full_usage "\n\n" \ +diff -pruN a/util-linux/Config.src mdstart/util-linux/Config.src +--- a/util-linux/Config.src 2010-12-20 02:41:27.000000000 +0200 ++++ mdstart/util-linux/Config.src 2011-01-12 21:30:09.000000000 +0200 +@@ -456,6 +456,13 @@ config FEATURE_MDEV_LOAD_FIRMWARE + /lib/firmware/ and if it exists, send it to the kernel for + loading into the hardware. + ++config MDSTART ++ bool "mdstart" ++ default n ++ help ++ Allows you to autostart /dev/md devices if using an initramfs to ++ boot. ++ + config MKSWAP + bool "mkswap" + default y +diff -pruN a/util-linux/Kbuild.src mdstart/util-linux/Kbuild.src +--- a/util-linux/Kbuild.src 2010-12-20 02:41:27.000000000 +0200 ++++ mdstart/util-linux/Kbuild.src 2011-01-12 21:30:09.000000000 +0200 +@@ -24,6 +24,7 @@ lib-$(CONFIG_HWCLOCK) += hwclo + lib-$(CONFIG_IPCRM) += ipcrm.o + lib-$(CONFIG_IPCS) += ipcs.o + lib-$(CONFIG_LOSETUP) += losetup.o ++lib-$(CONFIG_MDSTART) += mdStart.o + lib-$(CONFIG_LSPCI) += lspci.o + lib-$(CONFIG_LSUSB) += lsusb.o + lib-$(CONFIG_MDEV) += mdev.o +diff -pruN a/util-linux/mdStart.c mdstart/util-linux/mdStart.c +--- a/util-linux/mdStart.c 1970-01-01 03:00:00.000000000 +0300 ++++ mdstart/util-linux/mdStart.c 2011-01-12 21:30:09.000000000 +0200 +@@ -0,0 +1,59 @@ ++/* ++ * Linux 2.6(+) RAID Autostarter ++ * ++ * Copyright (C) 2005 by Tim Yamin ++ * ++ * 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 ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++extern int ++mdstart_main(int argc, char *argv[]) ++{ ++ int i, fd, part = 0, retval = 0; ++ ++ if(argc < 2) ++ { ++ bb_show_usage(); ++ } ++ ++ for(i = 1; i < argc; i++) ++ { ++ if(sscanf(argv[i], "%d", &part) == 1) ++ continue; ++ ++ fd = open(argv[i], 0, 0); ++ if (fd >= 0) ++ { ++ ioctl(fd, RAID_AUTORUN, part); ++ close(fd); ++ } else ++ { ++ printf("Error: Failed to open %s!\n", argv[i]); ++ retval=1; ++ } ++ ++ part = 0; ++ } ++ ++ return retval; ++} diff -pruN genkernel.a/patches/busybox/1.18.1/1.18.1-openvt.diff genkernel.b/patches/busybox/1.18.1/1.18.1-openvt.diff --- genkernel.a/patches/busybox/1.18.1/1.18.1-openvt.diff 1970-01-01 03:00:00.000000000 +0300 +++ genkernel.b/patches/busybox/1.18.1/1.18.1-openvt.diff 2011-01-12 21:17:53.000000000 +0200 @@ -0,0 +1,21 @@ +Based on: + +> Allow a slightly wider range of valid vt numbers. Forward-ported from Gentoo +> Busybox 1.1.3. + +> The previous spin of this patch on 1.1.3 had a 'wait(NULL);' right before +> return EXIT_SUCCESS. I don't think it's needed anymore, so I left it out. + +> Signed-off-by: Robin H. Johnson + +--- a/console-tools/openvt.c 2010-11-22 22:24:58.000000000 +0200 ++++ b/console-tools/openvt.c 2010-11-29 15:32:18.000000000 +0200 +@@ -124,7 +124,7 @@ int openvt_main(int argc UNUSED_PARAM, c + + if (flags & OPT_c) { + /* Check for illegal vt number: < 1 or > 63 */ +- vtno = xatou_range(str_c, 1, 63); ++ vtno = xatou_range(str_c, 0, 63); + } else { + vtno = find_free_vtno(); + } diff -pruN genkernel.a/patches/busybox/1.18.1/busybox-1.7.4-signal-hack.patch genkernel.b/patches/busybox/1.18.1/busybox-1.7.4-signal-hack.patch --- genkernel.a/patches/busybox/1.18.1/busybox-1.7.4-signal-hack.patch 1970-01-01 03:00:00.000000000 +0300 +++ genkernel.b/patches/busybox/1.18.1/busybox-1.7.4-signal-hack.patch 2010-11-29 21:39:38.000000000 +0200 @@ -0,0 +1,28 @@ +workaround while we get it fixed upstream + +http://bugs.gentoo.org/201114 + +--- libbb/u_signal_names.c ++++ libbb/u_signal_names.c +@@ -66,7 +66,7 @@ + #ifdef SIGTERM + [SIGTERM ] = "TERM", + #endif +-#ifdef SIGSTKFLT ++#if defined(SIGSTKFLT) && SIGSTKFLT < 32 + [SIGSTKFLT] = "STKFLT", + #endif + #ifdef SIGCHLD +@@ -90,10 +90,10 @ + #ifdef SIGURG + [SIGURG ] = "URG", + #endif +-#ifdef SIGXCPU ++#if defined(SIGXCPU) && SIGXCPU < 32 + [SIGXCPU ] = "XCPU", + #endif +-#ifdef SIGXFSZ ++#if defined(SIGXFSZ) && SIGXFSZ < 32 + [SIGXFSZ ] = "XFSZ", + #endif + #ifdef SIGVTALRM diff -pruN genkernel.a/patches/busybox/1.7.4/1.7.4-ash-timeout.diff genkernel.b/patches/busybox/1.7.4/1.7.4-ash-timeout.diff --- genkernel.a/patches/busybox/1.7.4/1.7.4-ash-timeout.diff 2011-01-12 21:05:44.000000000 +0200 +++ genkernel.b/patches/busybox/1.7.4/1.7.4-ash-timeout.diff 1970-01-01 03:00:00.000000000 +0300 @@ -1,123 +0,0 @@ -'read -t' support, forward-ported from Gentoo Busybox 1.1.3. -Used during the LiveCD boot when prompting for a keymap. - -Signed-off-by: Robin H. Johnson - -diff -Nuar --exclude '*.orig' busybox-1.7.4/shell/ash.c busybox-1.7.4+gentoo/shell/ash.c ---- busybox-1.7.4/shell/ash.c 2007-11-03 16:06:35.000000000 -0700 -+++ busybox-1.7.4+gentoo/shell/ash.c 2008-03-11 10:21:28.000000000 -0700 -@@ -11485,11 +11485,13 @@ - int startword; - int status; - int i; -+#if ENABLE_ASH_READ_NCHARS || ENABLE_ASH_READ_TIMEOUT -+ struct termios tty, old_tty; -+#endif - #if ENABLE_ASH_READ_NCHARS - int nch_flag = 0; - int nchars = 0; - int silent = 0; -- struct termios tty, old_tty; - #endif - #if ENABLE_ASH_READ_TIMEOUT - fd_set set; -@@ -11566,44 +11568,74 @@ - ifs = bltinlookup("IFS"); - if (ifs == NULL) - ifs = defifs; --#if ENABLE_ASH_READ_NCHARS -+#if ENABLE_ASH_READ_NCHARS || ENABLE_ASH_READ_TIMEOUT -+#if ENABLE_ASH_READ_NCHARS && ENABLE_ASH_READ_TIMEOUT -+ if (nch_flag || silent || ts.tv_sec || ts.tv_usec) { -+#elif ENABLE_ASH_READ_TIMEOUT -+ if (ts.tv_sec || ts.tv_usec) { -+#elif ENABLE_ASH_READ_NCHARS - if (nch_flag || silent) { -+#endif - tcgetattr(0, &tty); - old_tty = tty; -- if (nch_flag) { -+#if ENABLE_ASH_READ_NCHARS && ENABLE_ASH_READ_TIMEOUT -+ if (nch_flag || ts.tv_sec || ts.tv_usec) -+#elif ENABLE_ASH_READ_TIMEOUT -+ if (ts.tv_sec || ts.tv_usec) -+#elif ENABLE_ASH_READ_NCHARS -+ if (nch_flag) -+#endif - tty.c_lflag &= ~ICANON; -- tty.c_cc[VMIN] = nchars; -- } -- if (silent) { -- tty.c_lflag &= ~(ECHO|ECHOK|ECHONL); - -- } -+ -+#if ENABLE_ASH_READ_NCHARS -+ if (silent) -+ tty.c_lflag &= ~(ECHO|ECHOK|ECHONL); -+#endif - tcsetattr(0, TCSANOW, &tty); - } - #endif -+ i = 1; -+ STARTSTACKSTR(p); - #if ENABLE_ASH_READ_TIMEOUT - if (ts.tv_sec || ts.tv_usec) { - FD_ZERO(&set); - FD_SET(0, &set); - - i = select(FD_SETSIZE, &set, NULL, NULL, &ts); -- if (!i) { -+ if (i == 1) -+ { -+ read(0, &c, 1); -+ if(c == '\n' || c == 4) /* Handle newlines and EOF */ -+ i = 0; /* Don't read further... */ -+ else -+ STPUTC(c, p); /* Ok, keep reading... */ -+ } - #if ENABLE_ASH_READ_NCHARS -- if (nch_flag) -- tcsetattr(0, TCSANOW, &old_tty); -+ if (!silent && !nch_flag) - #endif -- return 1; -+ tcsetattr(0, TCSANOW, &old_tty); -+ -+#if ENABLE_ASH_READ_NCHARS -+ if(i == 0) -+ { -+ nchars = 0; -+ nch_flag = 1; -+ } else -+ { -+ if (nch_flag) -+ nchars--; - } -+#endif - } - #endif - status = 0; - startword = 1; - backslash = 0; -- STARTSTACKSTR(p); - #if ENABLE_ASH_READ_NCHARS - while (!nch_flag || nchars--) - #else -- for (;;) -+ for (;i > 0;) - #endif - { - if (read(0, &c, 1) != 1) { -@@ -11640,8 +11672,10 @@ - } - } - #if ENABLE_ASH_READ_NCHARS -- if (nch_flag || silent) -+ if (silent || nch_flag) - tcsetattr(0, TCSANOW, &old_tty); -+ if (!silent && nch_flag) -+ printf("\n"); - #endif - - STACKSTRNUL(p); diff -pruN genkernel.a/patches/busybox/1.7.4/1.7.4-make-3.82.diff genkernel.b/patches/busybox/1.7.4/1.7.4-make-3.82.diff --- genkernel.a/patches/busybox/1.7.4/1.7.4-make-3.82.diff 2011-01-12 21:05:44.000000000 +0200 +++ genkernel.b/patches/busybox/1.7.4/1.7.4-make-3.82.diff 1970-01-01 03:00:00.000000000 +0300 @@ -1,42 +0,0 @@ -From d508d972c7f808eec5139255f661d37817c79260 Mon Sep 17 00:00:00 2001 -From: Sebastian Pipping -Date: Mon, 29 Nov 2010 09:52:22 +0100 -Subject: [PATCH] Split implicit and normal rules for make 3.82 - ---- - Makefile | 12 ++++++++++-- - 1 files changed, 10 insertions(+), 2 deletions(-) - -diff --git a/Makefile b/Makefile -index c1fe21b..a2bfe4b 100644 ---- Makefile -+++ Makefile -@@ -402,7 +402,12 @@ ifeq ($(config-targets),1) - -include $(srctree)/arch/$(ARCH)/Makefile - export KBUILD_DEFCONFIG - --config %config: scripts_basic outputmakefile FORCE -+config: scripts_basic outputmakefile FORCE -+ $(Q)mkdir -p include -+ $(Q)$(MAKE) $(build)=scripts/kconfig $@ -+ $(Q)$(MAKE) -C $(srctree) KBUILD_SRC= .kernelrelease -+ -+%config: scripts_basic outputmakefile FORCE - $(Q)mkdir -p include - $(Q)$(MAKE) $(build)=scripts/kconfig $@ - $(Q)$(MAKE) -C $(srctree) KBUILD_SRC= .kernelrelease -@@ -1239,7 +1244,10 @@ endif - $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) - - # Modules --/ %/: prepare scripts FORCE -+/: prepare scripts FORCE -+ $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \ -+ $(build)=$(build-dir) -+%/: prepare scripts FORCE - $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \ - $(build)=$(build-dir) - %.ko: prepare scripts FORCE --- -1.7.3.2 - diff -pruN genkernel.a/patches/busybox/1.7.4/1.7.4-mdadm.diff genkernel.b/patches/busybox/1.7.4/1.7.4-mdadm.diff --- genkernel.a/patches/busybox/1.7.4/1.7.4-mdadm.diff 2011-01-12 21:05:44.000000000 +0200 +++ genkernel.b/patches/busybox/1.7.4/1.7.4-mdadm.diff 1970-01-01 03:00:00.000000000 +0300 @@ -1,5882 +0,0 @@ -Forward-port the mdadm tool from the Gentoo Busybox-1.1.3. -Should handle all types of metadata 0.90, 1.0, 1.1, 1.2. -If /etc/mdadm.conf does not exist in the initrd, it is created first, by -scanning devices, and then it is used. - -Signed-off-by: Robin H. Johnson - -diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/Config.in busybox-1.7.4+gentoo+mdadm/Config.in ---- busybox-1.7.4+gentoo/Config.in 2007-09-03 04:48:58.000000000 -0700 -+++ busybox-1.7.4+gentoo+mdadm/Config.in 2008-03-11 10:31:00.000000000 -0700 -@@ -499,2 +499,3 @@ - source e2fsprogs/Config.in -+source mdadm/Config.in - source modutils/Config.in -diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/include/applets.h busybox-1.7.4+gentoo+mdadm/include/applets.h ---- busybox-1.7.4+gentoo/include/applets.h 2008-03-11 10:25:43.000000000 -0700 -+++ busybox-1.7.4+gentoo+mdadm/include/applets.h 2008-03-11 10:32:22.000000000 -0700 -@@ -223,2 +223,3 @@ - USE_MD5SUM(APPLET_ODDNAME(md5sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_NEVER, md5sum)) -+USE_MDADM(APPLET(mdadm, _BB_DIR_SBIN, _BB_SUID_NEVER)) - USE_MDEV(APPLET(mdev, _BB_DIR_SBIN, _BB_SUID_NEVER)) -diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/include/usage.h busybox-1.7.4+gentoo+mdadm/include/usage.h ---- busybox-1.7.4+gentoo/include/usage.h 2008-03-11 10:19:04.000000000 -0700 -+++ busybox-1.7.4+gentoo+mdadm/include/usage.h 2008-03-11 10:31:00.000000000 -0700 -@@ -2048,2 +2048,7 @@ - -+#define mdadm_trivial_usage \ -+ "" -+#define mdadm_full_usage \ -+ "Assemble or Examine the mdadm arrays." -+ - #define mdev_trivial_usage \ -diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/Makefile busybox-1.7.4+gentoo+mdadm/Makefile ---- busybox-1.7.4+gentoo/Makefile 2007-11-23 20:34:41.000000000 -0800 -+++ busybox-1.7.4+gentoo+mdadm/Makefile 2008-03-11 10:31:49.000000000 -0700 -@@ -442,6 +442,7 @@ - libpwdgrp/ \ - loginutils/ \ - miscutils/ \ -+ mdadm/ \ - modutils/ \ - networking/ \ - networking/libiproute/ \ -diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/bitmap.h busybox-1.7.4+gentoo+mdadm/mdadm/bitmap.h ---- busybox-1.7.4+gentoo/mdadm/bitmap.h 1969-12-31 16:00:00.000000000 -0800 -+++ busybox-1.7.4+gentoo+mdadm/mdadm/bitmap.h 2008-03-11 10:31:00.000000000 -0700 -@@ -0,0 +1,287 @@ -+/* -+ * bitmap.h: Copyright (C) Peter T. Breuer (ptb@ot.uc3m.es) 2003 -+ * -+ * additions: Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc. -+ */ -+#ifndef BITMAP_H -+#define BITMAP_H 1 -+ -+#define BITMAP_MAJOR_LO 3 -+/* version 4 insists the bitmap is in little-endian order -+ * with version 3, it is host-endian which is non-portable -+ */ -+#define BITMAP_MAJOR_HI 4 -+#define BITMAP_MAJOR_HOSTENDIAN 3 -+ -+#define BITMAP_MINOR 39 -+ -+/* -+ * in-memory bitmap: -+ * -+ * Use 16 bit block counters to track pending writes to each "chunk". -+ * The 2 high order bits are special-purpose, the first is a flag indicating -+ * whether a resync is needed. The second is a flag indicating whether a -+ * resync is active. -+ * This means that the counter is actually 14 bits: -+ * -+ * +--------+--------+------------------------------------------------+ -+ * | resync | resync | counter | -+ * | needed | active | | -+ * | (0-1) | (0-1) | (0-16383) | -+ * +--------+--------+------------------------------------------------+ -+ * -+ * The "resync needed" bit is set when: -+ * a '1' bit is read from storage at startup. -+ * a write request fails on some drives -+ * a resync is aborted on a chunk with 'resync active' set -+ * It is cleared (and resync-active set) when a resync starts across all drives -+ * of the chunk. -+ * -+ * -+ * The "resync active" bit is set when: -+ * a resync is started on all drives, and resync_needed is set. -+ * resync_needed will be cleared (as long as resync_active wasn't already set). -+ * It is cleared when a resync completes. -+ * -+ * The counter counts pending write requests, plus the on-disk bit. -+ * When the counter is '1' and the resync bits are clear, the on-disk -+ * bit can be cleared aswell, thus setting the counter to 0. -+ * When we set a bit, or in the counter (to start a write), if the fields is -+ * 0, we first set the disk bit and set the counter to 1. -+ * -+ * If the counter is 0, the on-disk bit is clear and the stipe is clean -+ * Anything that dirties the stipe pushes the counter to 2 (at least) -+ * and sets the on-disk bit (lazily). -+ * If a periodic sweep find the counter at 2, it is decremented to 1. -+ * If the sweep find the counter at 1, the on-disk bit is cleared and the -+ * counter goes to zero. -+ * -+ * Also, we'll hijack the "map" pointer itself and use it as two 16 bit block -+ * counters as a fallback when "page" memory cannot be allocated: -+ * -+ * Normal case (page memory allocated): -+ * -+ * page pointer (32-bit) -+ * -+ * [ ] ------+ -+ * | -+ * +-------> [ ][ ]..[ ] (4096 byte page == 2048 counters) -+ * c1 c2 c2048 -+ * -+ * Hijacked case (page memory allocation failed): -+ * -+ * hijacked page pointer (32-bit) -+ * -+ * [ ][ ] (no page memory allocated) -+ * counter #1 (16-bit) counter #2 (16-bit) -+ * -+ */ -+ -+#ifdef __KERNEL__ -+ -+#define PAGE_BITS (PAGE_SIZE << 3) -+#define PAGE_BIT_SHIFT (PAGE_SHIFT + 3) -+ -+typedef __u16 bitmap_counter_t; -+#define COUNTER_BITS 16 -+#define COUNTER_BIT_SHIFT 4 -+#define COUNTER_BYTE_RATIO (COUNTER_BITS / 8) -+#define COUNTER_BYTE_SHIFT (COUNTER_BIT_SHIFT - 3) -+ -+#define NEEDED_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 1))) -+#define RESYNC_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 2))) -+#define COUNTER_MAX ((bitmap_counter_t) RESYNC_MASK - 1) -+#define NEEDED(x) (((bitmap_counter_t) x) & NEEDED_MASK) -+#define RESYNC(x) (((bitmap_counter_t) x) & RESYNC_MASK) -+#define COUNTER(x) (((bitmap_counter_t) x) & COUNTER_MAX) -+ -+/* how many counters per page? */ -+#define PAGE_COUNTER_RATIO (PAGE_BITS / COUNTER_BITS) -+/* same, except a shift value for more efficient bitops */ -+#define PAGE_COUNTER_SHIFT (PAGE_BIT_SHIFT - COUNTER_BIT_SHIFT) -+/* same, except a mask value for more efficient bitops */ -+#define PAGE_COUNTER_MASK (PAGE_COUNTER_RATIO - 1) -+ -+#define BITMAP_BLOCK_SIZE 512 -+#define BITMAP_BLOCK_SHIFT 9 -+ -+/* how many blocks per chunk? (this is variable) */ -+#define CHUNK_BLOCK_RATIO(bitmap) ((bitmap)->chunksize >> BITMAP_BLOCK_SHIFT) -+#define CHUNK_BLOCK_SHIFT(bitmap) ((bitmap)->chunkshift - BITMAP_BLOCK_SHIFT) -+#define CHUNK_BLOCK_MASK(bitmap) (CHUNK_BLOCK_RATIO(bitmap) - 1) -+ -+/* when hijacked, the counters and bits represent even larger "chunks" */ -+/* there will be 1024 chunks represented by each counter in the page pointers */ -+#define PAGEPTR_BLOCK_RATIO(bitmap) \ -+ (CHUNK_BLOCK_RATIO(bitmap) << PAGE_COUNTER_SHIFT >> 1) -+#define PAGEPTR_BLOCK_SHIFT(bitmap) \ -+ (CHUNK_BLOCK_SHIFT(bitmap) + PAGE_COUNTER_SHIFT - 1) -+#define PAGEPTR_BLOCK_MASK(bitmap) (PAGEPTR_BLOCK_RATIO(bitmap) - 1) -+ -+/* -+ * on-disk bitmap: -+ * -+ * Use one bit per "chunk" (block set). We do the disk I/O on the bitmap -+ * file a page at a time. There's a superblock at the start of the file. -+ */ -+ -+/* map chunks (bits) to file pages - offset by the size of the superblock */ -+#define CHUNK_BIT_OFFSET(chunk) ((chunk) + (sizeof(bitmap_super_t) << 3)) -+ -+#endif -+ -+/* -+ * bitmap structures: -+ */ -+ -+#define BITMAP_MAGIC 0x6d746962 -+ -+/* use these for bitmap->flags and bitmap->sb->state bit-fields */ -+enum bitmap_state { -+ BITMAP_ACTIVE = 0x001, /* the bitmap is in use */ -+ BITMAP_STALE = 0x002 /* the bitmap file is out of date or had -EIO */ -+}; -+ -+/* the superblock at the front of the bitmap file -- little endian */ -+typedef struct bitmap_super_s { -+ __u32 magic; /* 0 BITMAP_MAGIC */ -+ __u32 version; /* 4 the bitmap major for now, could change... */ -+ __u8 uuid[16]; /* 8 128 bit uuid - must match md device uuid */ -+ __u64 events; /* 24 event counter for the bitmap (1)*/ -+ __u64 events_cleared;/*32 event counter when last bit cleared (2) */ -+ __u64 sync_size; /* 40 the size of the md device's sync range(3) */ -+ __u32 state; /* 48 bitmap state information */ -+ __u32 chunksize; /* 52 the bitmap chunk size in bytes */ -+ __u32 daemon_sleep; /* 56 seconds between disk flushes */ -+ __u32 write_behind; /* 60 number of outstanding write-behind writes */ -+ -+ __u8 pad[256 - 64]; /* set to zero */ -+} bitmap_super_t; -+ -+/* notes: -+ * (1) This event counter is updated before the eventcounter in the md superblock -+ * When a bitmap is loaded, it is only accepted if this event counter is equal -+ * to, or one greater than, the event counter in the superblock. -+ * (2) This event counter is updated when the other one is *if*and*only*if* the -+ * array is not degraded. As bits are not cleared when the array is degraded, -+ * this represents the last time that any bits were cleared. -+ * If a device is being added that has an event count with this value or -+ * higher, it is accepted as conforming to the bitmap. -+ * (3)This is the number of sectors represented by the bitmap, and is the range that -+ * resync happens across. For raid1 and raid5/6 it is the size of individual -+ * devices. For raid10 it is the size of the array. -+ */ -+ -+#ifdef __KERNEL__ -+ -+/* the in-memory bitmap is represented by bitmap_pages */ -+struct bitmap_page { -+ /* -+ * map points to the actual memory page -+ */ -+ char *map; -+ /* -+ * in emergencies (when map cannot be alloced), hijack the map -+ * pointer and use it as two counters itself -+ */ -+ unsigned int hijacked; -+ /* -+ * count of dirty bits on the page -+ */ -+ int count; -+}; -+ -+/* keep track of bitmap file pages that have pending writes on them */ -+struct page_list { -+ struct list_head list; -+ struct page *page; -+}; -+ -+/* the main bitmap structure - one per mddev */ -+struct bitmap { -+ struct bitmap_page *bp; -+ unsigned long pages; /* total number of pages in the bitmap */ -+ unsigned long missing_pages; /* number of pages not yet allocated */ -+ -+ mddev_t *mddev; /* the md device that the bitmap is for */ -+ -+ int counter_bits; /* how many bits per block counter */ -+ -+ /* bitmap chunksize -- how much data does each bit represent? */ -+ unsigned long chunksize; -+ unsigned long chunkshift; /* chunksize = 2^chunkshift (for bitops) */ -+ unsigned long chunks; /* total number of data chunks for the array */ -+ -+ /* We hold a count on the chunk currently being synced, and drop -+ * it when the last block is started. If the resync is aborted -+ * midway, we need to be able to drop that count, so we remember -+ * the counted chunk.. -+ */ -+ unsigned long syncchunk; -+ -+ __u64 events_cleared; -+ -+ /* bitmap spinlock */ -+ spinlock_t lock; -+ -+ struct file *file; /* backing disk file */ -+ struct page *sb_page; /* cached copy of the bitmap file superblock */ -+ struct page **filemap; /* list of cache pages for the file */ -+ unsigned long *filemap_attr; /* attributes associated w/ filemap pages */ -+ unsigned long file_pages; /* number of pages in the file */ -+ -+ unsigned long flags; -+ -+ /* -+ * the bitmap daemon - periodically wakes up and sweeps the bitmap -+ * file, cleaning up bits and flushing out pages to disk as necessary -+ */ -+ mdk_thread_t *daemon; -+ unsigned long daemon_sleep; /* how many seconds between updates? */ -+ -+ /* -+ * bitmap write daemon - this daemon performs writes to the bitmap file -+ * this thread is only needed because of a limitation in ext3 (jbd) -+ * that does not allow a task to have two journal transactions ongoing -+ * simultaneously (even if the transactions are for two different -+ * filesystems) -- in the case of bitmap, that would be the filesystem -+ * that the bitmap file resides on and the filesystem that is mounted -+ * on the md device -- see current->journal_info in jbd/transaction.c -+ */ -+ mdk_thread_t *write_daemon; -+ mdk_thread_t *writeback_daemon; -+ spinlock_t write_lock; -+ struct semaphore write_ready; -+ struct semaphore write_done; -+ unsigned long writes_pending; -+ wait_queue_head_t write_wait; -+ struct list_head write_pages; -+ struct list_head complete_pages; -+ mempool_t *write_pool; -+}; -+ -+/* the bitmap API */ -+ -+/* these are used only by md/bitmap */ -+int bitmap_create(mddev_t *mddev); -+void bitmap_destroy(mddev_t *mddev); -+int bitmap_active(struct bitmap *bitmap); -+ -+char *file_path(struct file *file, char *buf, int count); -+void bitmap_print_sb(struct bitmap *bitmap); -+int bitmap_update_sb(struct bitmap *bitmap); -+ -+int bitmap_setallbits(struct bitmap *bitmap); -+ -+/* these are exported */ -+void bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors); -+void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors, -+ int success); -+int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks); -+void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted); -+void bitmap_close_sync(struct bitmap *bitmap); -+ -+int bitmap_unplug(struct bitmap *bitmap); -+#endif -+ -+#endif -diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/config.c busybox-1.7.4+gentoo+mdadm/mdadm/config.c ---- busybox-1.7.4+gentoo/mdadm/config.c 1969-12-31 16:00:00.000000000 -0800 -+++ busybox-1.7.4+gentoo+mdadm/mdadm/config.c 2008-03-11 10:31:00.000000000 -0700 -@@ -0,0 +1,824 @@ -+/* -+ * mdadm - manage Linux "md" devices aka RAID arrays. -+ * -+ * Copyright (C) 2001-2006 Neil Brown -+ * -+ * -+ * 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 -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Author: Neil Brown -+ * Email: -+ * Paper: Neil Brown -+ * School of Computer Science and Engineering -+ * The University of New South Wales -+ * Sydney, 2052 -+ * Australia -+ */ -+ -+#include "mdadm.h" -+#include "dlink.h" -+#include -+#include -+#include -+#include -+#include -+#include -+ -+mapping_t r5layout[] = { -+ { "left-asymmetric", 0}, -+ { "right-asymmetric", 1}, -+ { "left-symmetric", 2}, -+ { "right-symmetric", 3}, -+ -+ { "default", 2}, -+ { "la", 0}, -+ { "ra", 1}, -+ { "ls", 2}, -+ { "rs", 3}, -+ { NULL, 0} -+}; -+ -+mapping_t pers[] = { -+ { "linear", -1}, -+ { "raid0", 0}, -+ { "0", 0}, -+ { "stripe", 0}, -+ { "raid1", 1}, -+ { "1", 1}, -+ { "mirror", 1}, -+ { "raid4", 4}, -+ { "4", 4}, -+ { "raid5", 5}, -+ { "5", 5}, -+ { "multipath", -4}, -+ { "mp", -4}, -+ { "raid6", 6}, -+ { "6", 6}, -+ { "raid10", 10}, -+ { "10", 10}, -+ { "faulty", -5}, -+ { NULL, 0} -+}; -+/* -+ * Read the config file -+ * -+ * conf_get_uuids gets a list of devicename+uuid pairs -+ * conf_get_devs gets device names after expanding wildcards -+ * -+ * Each keeps the returned list and frees it when asked to make -+ * a new list. -+ * -+ * The format of the config file needs to be fairly extensible. -+ * Now, arrays only have names and uuids and devices merely are. -+ * But later arrays might want names, and devices might want superblock -+ * versions, and who knows what else. -+ * I like free format, abhore backslash line continuation, adore -+ * indentation for structure and am ok about # comments. -+ * -+ * So, each line that isn't blank or a #comment must either start -+ * with a key word, and not be indented, or must start with a -+ * non-key-word and must be indented. -+ * -+ * Keywords are DEVICE and ARRAY -+ * DEV{ICE} introduces some devices that might contain raid components. -+ * e.g. -+ * DEV style=0 /dev/sda* /dev/hd* -+ * DEV style=1 /dev/sd[b-f]* -+ * ARR{AY} describes an array giving md device and attributes like uuid=whatever -+ * e.g. -+ * ARRAY /dev/md0 uuid=whatever name=something -+ * Spaces separate words on each line. Quoting, with "" or '' protects them, -+ * but may not wrap over lines -+ * -+ */ -+ -+#ifndef CONFFILE -+#define CONFFILE "/etc/mdadm.conf" -+#endif -+#ifndef CONFFILE2 -+/* for Debian compatibility .... */ -+#define CONFFILE2 "/etc/mdadm/mdadm.conf" -+#endif -+char DefaultConfFile[] = CONFFILE; -+char DefaultAltConfFile[] = CONFFILE2; -+ -+enum linetype { Devices, Array, Mailaddr, Mailfrom, Program, CreateDev, Homehost, LTEnd }; -+char *keywords[] = { -+ [Devices] = "devices", -+ [Array] = "array", -+ [Mailaddr] = "mailaddr", -+ [Mailfrom] = "mailfrom", -+ [Program] = "program", -+ [CreateDev]= "create", -+ [Homehost] = "homehost", -+ [LTEnd] = NULL -+}; -+ -+/* -+ * match_keyword returns an index into the keywords array, or -1 for no match -+ * case is ignored, and at least three characters must be given -+ */ -+ -+int match_keyword(char *word) -+{ -+ int len = strlen(word); -+ int n; -+ -+ if (len < 3) return -1; -+ for (n=0; keywords[n]; n++) { -+ if (strncasecmp(word, keywords[n], len)==0) -+ return n; -+ } -+ return -1; -+} -+ -+/* conf_word gets one word from the conf file. -+ * if "allow_key", then accept words at the start of a line, -+ * otherwise stop when such a word is found. -+ * We assume that the file pointer is at the end of a word, so the -+ * next character is a space, or a newline. If not, it is the start of a line. -+ */ -+ -+char *conf_word(FILE *file, int allow_key) -+{ -+ int wsize = 100; -+ int len = 0; -+ int c; -+ int quote; -+ int wordfound = 0; -+ char *word = malloc(wsize); -+ -+ if (!word) abort(); -+ -+ while (wordfound==0) { -+ /* at the end of a word.. */ -+ c = getc(file); -+ if (c == '#') -+ while (c != EOF && c != '\n') -+ c = getc(file); -+ if (c == EOF) break; -+ if (c == '\n') continue; -+ -+ if (c != ' ' && c != '\t' && ! allow_key) { -+ ungetc(c, file); -+ break; -+ } -+ /* looks like it is safe to get a word here, if there is one */ -+ quote = 0; -+ /* first, skip any spaces */ -+ while (c == ' ' || c == '\t') -+ c = getc(file); -+ if (c != EOF && c != '\n' && c != '#') { -+ /* we really have a character of a word, so start saving it */ -+ while (c != EOF && c != '\n' && (quote || (c!=' ' && c != '\t'))) { -+ wordfound = 1; -+ if (quote && c == quote) quote = 0; -+ else if (quote == 0 && (c == '\'' || c == '"')) -+ quote = c; -+ else { -+ if (len == wsize-1) { -+ wsize += 100; -+ word = realloc(word, wsize); -+ if (!word) abort(); -+ } -+ word[len++] = c; -+ } -+ c = getc(file); -+ } -+ } -+ if (c != EOF) ungetc(c, file); -+ } -+ word[len] = 0; -+/* printf("word is <%s>\n", word); */ -+ if (!wordfound) { -+ free(word); -+ word = NULL; -+ } -+ return word; -+} -+ -+/* -+ * conf_line reads one logical line from the conffile. -+ * It skips comments and continues until it finds a line that starts -+ * with a non blank/comment. This character is pushed back for the next call -+ * A doubly linked list of words is returned. -+ * the first word will be a keyword. Other words will have had quotes removed. -+ */ -+ -+char *conf_line(FILE *file) -+{ -+ char *w; -+ char *list; -+ -+ w = conf_word(file, 1); -+ if (w == NULL) return NULL; -+ -+ list = dl_strdup(w); -+ free(w); -+ dl_init(list); -+ -+ while ((w = conf_word(file,0))){ -+ char *w2 = dl_strdup(w); -+ free(w); -+ dl_add(list, w2); -+ } -+/* printf("got a line\n");*/ -+ return list; -+} -+ -+void free_line(char *line) -+{ -+ char *w; -+ for (w=dl_next(line); w != line; w=dl_next(line)) { -+ dl_del(w); -+ dl_free(w); -+ } -+ dl_free(line); -+} -+ -+ -+struct conf_dev { -+ struct conf_dev *next; -+ char *name; -+} *cdevlist = NULL; -+ -+mddev_dev_t load_partitions(void) -+{ -+ FILE *f = fopen("/proc/partitions", "r"); -+ char buf[1024]; -+ mddev_dev_t rv = NULL; -+ if (f == NULL) { -+ fprintf(stderr, Name ": cannot open /proc/partitions\n"); -+ return NULL; -+ } -+ while (fgets(buf, 1024, f)) { -+ int major, minor; -+ char *name, *mp; -+ mddev_dev_t d; -+ -+ buf[1023] = '\0'; -+ if (buf[0] != ' ') -+ continue; -+ major = strtoul(buf, &mp, 10); -+ if (mp == buf || *mp != ' ') -+ continue; -+ minor = strtoul(mp, NULL, 10); -+ -+ name = map_dev(major, minor, 1); -+ if (!name) -+ continue; -+ d = malloc(sizeof(*d)); -+ d->devname = strdup(name); -+ d->next = rv; -+ d->used = 0; -+ rv = d; -+ } -+ fclose(f); -+ return rv; -+} -+ -+struct createinfo createinfo = { -+ .autof = 2, /* by default, create devices with standard names */ -+ .symlinks = 1, -+#ifdef DEBIAN -+ .gid = 6, /* disk */ -+ .mode = 0660, -+#else -+ .mode = 0600, -+#endif -+}; -+ -+int parse_auto(char *str, char *msg, int config) -+{ -+ int autof; -+ if (str == NULL || *str == 0) -+ autof = 2; -+ else if (strcasecmp(str,"no")==0) -+ autof = 1; -+ else if (strcasecmp(str,"yes")==0) -+ autof = 2; -+ else if (strcasecmp(str,"md")==0) -+ autof = config?5:3; -+ else { -+ /* There might be digits, and maybe a hypen, at the end */ -+ char *e = str + strlen(str); -+ int num = 4; -+ int len; -+ while (e > str && isdigit(e[-1])) -+ e--; -+ if (*e) { -+ num = atoi(e); -+ if (num <= 0) num = 1; -+ } -+ if (e > str && e[-1] == '-') -+ e--; -+ len = e - str; -+ if ((len == 2 && strncasecmp(str,"md",2)==0)) { -+ autof = config ? 5 : 3; -+ } else if ((len == 3 && strncasecmp(str,"yes",3)==0)) { -+ autof = 2; -+ } else if ((len == 3 && strncasecmp(str,"mdp",3)==0)) { -+ autof = config ? 6 : 4; -+ } else if ((len == 1 && strncasecmp(str,"p",1)==0) || -+ (len >= 4 && strncasecmp(str,"part",4)==0)) { -+ autof = 6; -+ } else { -+ fprintf(stderr, Name ": %s arg of \"%s\" unrecognised: use no,yes,md,mdp,part\n" -+ " optionally followed by a number.\n", -+ msg, str); -+ exit(2); -+ } -+ autof |= num << 3; -+ } -+ return autof; -+} -+ -+static void createline(char *line) -+{ -+ char *w; -+ char *ep; -+ -+ for (w=dl_next(line); w!=line; w=dl_next(w)) { -+ if (strncasecmp(w, "auto=", 5) == 0) -+ createinfo.autof = parse_auto(w+5, "auto=", 1); -+ else if (strncasecmp(w, "owner=", 6) == 0) { -+ if (w[6] == 0) { -+ fprintf(stderr, Name ": missing owner name\n"); -+ continue; -+ } -+ createinfo.uid = strtoul(w+6, &ep, 10); -+ if (*ep != 0) { -+ struct passwd *pw; -+ /* must be a name */ -+ pw = getpwnam(w+6); -+ if (pw) -+ createinfo.uid = pw->pw_uid; -+ else -+ fprintf(stderr, Name ": CREATE user %s not found\n", w+6); -+ } -+ } else if (strncasecmp(w, "group=", 6) == 0) { -+ if (w[6] == 0) { -+ fprintf(stderr, Name ": missing group name\n"); -+ continue; -+ } -+ createinfo.gid = strtoul(w+6, &ep, 10); -+ if (*ep != 0) { -+ struct group *gr; -+ /* must be a name */ -+ gr = getgrnam(w+6); -+ if (gr) -+ createinfo.gid = gr->gr_gid; -+ else -+ fprintf(stderr, Name ": CREATE group %s not found\n", w+6); -+ } -+ } else if (strncasecmp(w, "mode=", 5) == 0) { -+ if (w[5] == 0) { -+ fprintf(stderr, Name ": missing CREATE mode\n"); -+ continue; -+ } -+ createinfo.mode = strtoul(w+5, &ep, 8); -+ if (*ep != 0) { -+ createinfo.mode = 0600; -+ fprintf(stderr, Name ": unrecognised CREATE mode %s\n", -+ w+5); -+ } -+ } else if (strncasecmp(w, "metadata=", 9) == 0) { -+ /* style of metadata to use by default */ -+ int i; -+ for (i=0; superlist[i] && !createinfo.supertype; i++) -+ createinfo.supertype = -+ superlist[i]->match_metadata_desc(w+9); -+ if (!createinfo.supertype) -+ fprintf(stderr, Name ": metadata format %s unknown, ignoring\n", -+ w+9); -+ } else if (strncasecmp(w, "symlinks=yes", 12) == 0) -+ createinfo.symlinks = 1; -+ else if (strncasecmp(w, "symlinks=no", 11) == 0) -+ createinfo.symlinks = 0; -+ else { -+ fprintf(stderr, Name ": unrecognised word on CREATE line: %s\n", -+ w); -+ } -+ } -+} -+ -+void devline(char *line) -+{ -+ char *w; -+ struct conf_dev *cd; -+ -+ for (w=dl_next(line); w != line; w=dl_next(w)) { -+ if (w[0] == '/' || strcasecmp(w, "partitions") == 0) { -+ cd = malloc(sizeof(*cd)); -+ cd->name = strdup(w); -+ cd->next = cdevlist; -+ cdevlist = cd; -+ } else { -+ fprintf(stderr, Name ": unreconised word on DEVICE line: %s\n", -+ w); -+ } -+ } -+} -+ -+mddev_ident_t mddevlist = NULL; -+mddev_ident_t *mddevlp = &mddevlist; -+ -+void arrayline(char *line) -+{ -+ char *w; -+ -+ struct mddev_ident_s mis; -+ mddev_ident_t mi; -+ -+ mis.uuid_set = 0; -+ mis.super_minor = UnSet; -+ mis.level = UnSet; -+ mis.raid_disks = UnSet; -+ mis.spare_disks = 0; -+ mis.devices = NULL; -+ mis.devname = NULL; -+ mis.spare_group = NULL; -+ mis.autof = 0; -+ mis.next = NULL; -+ mis.st = NULL; -+ mis.bitmap_fd = -1; -+ mis.bitmap_file = NULL; -+ mis.name[0] = 0; -+ -+ for (w=dl_next(line); w!=line; w=dl_next(w)) { -+ if (w[0] == '/') { -+ if (mis.devname) -+ fprintf(stderr, Name ": only give one device per ARRAY line: %s and %s\n", -+ mis.devname, w); -+ else mis.devname = w; -+ } else if (strncasecmp(w, "uuid=", 5)==0 ) { -+ if (mis.uuid_set) -+ fprintf(stderr, Name ": only specify uuid once, %s ignored.\n", -+ w); -+ else { -+ if (parse_uuid(w+5, mis.uuid)) -+ mis.uuid_set = 1; -+ else -+ fprintf(stderr, Name ": bad uuid: %s\n", w); -+ } -+ } else if (strncasecmp(w, "super-minor=", 12)==0 ) { -+ if (mis.super_minor != UnSet) -+ fprintf(stderr, Name ": only specify super-minor once, %s ignored.\n", -+ w); -+ else { -+ char *endptr; -+ mis.super_minor= strtol(w+12, &endptr, 10); -+ if (w[12]==0 || endptr[0]!=0 || mis.super_minor < 0) { -+ fprintf(stderr, Name ": invalid super-minor number: %s\n", -+ w); -+ mis.super_minor = UnSet; -+ } -+ } -+ } else if (strncasecmp(w, "name=", 5)==0) { -+ if (mis.name[0]) -+ fprintf(stderr, Name ": only specify name once, %s ignored.\n", -+ w); -+ else if (strlen(w+5) > 32) -+ fprintf(stderr, Name ": name too long, ignoring %s\n", w); -+ else -+ strcpy(mis.name, w+5); -+ -+ } else if (strncasecmp(w, "bitmap=", 7) == 0) { -+ if (mis.bitmap_file) -+ fprintf(stderr, Name ": only specify bitmap file once. %s ignored\n", -+ w); -+ else -+ mis.bitmap_file = strdup(w+7); -+ -+ } else if (strncasecmp(w, "devices=", 8 ) == 0 ) { -+ if (mis.devices) -+ fprintf(stderr, Name ": only specify devices once (use a comma separated list). %s ignored\n", -+ w); -+ else -+ mis.devices = strdup(w+8); -+ } else if (strncasecmp(w, "spare-group=", 12) == 0 ) { -+ if (mis.spare_group) -+ fprintf(stderr, Name ": only specify one spare group per array. %s ignored.\n", -+ w); -+ else -+ mis.spare_group = strdup(w+12); -+ } else if (strncasecmp(w, "level=", 6) == 0 ) { -+ /* this is mainly for compatability with --brief output */ -+ mis.level = map_name(pers, w+6); -+ } else if (strncasecmp(w, "disks=", 6) == 0 ) { -+ /* again, for compat */ -+ mis.raid_disks = atoi(w+6); -+ } else if (strncasecmp(w, "num-devices=", 12) == 0 ) { -+ /* again, for compat */ -+ mis.raid_disks = atoi(w+12); -+ } else if (strncasecmp(w, "spares=", 7) == 0 ) { -+ /* for warning if not all spares present */ -+ mis.spare_disks = atoi(w+7); -+ } else if (strncasecmp(w, "metadata=", 9) == 0) { -+ /* style of metadata on the devices. */ -+ int i; -+ -+ for(i=0; superlist[i] && !mis.st; i++) -+ mis.st = superlist[i]->match_metadata_desc(w+9); -+ -+ if (!mis.st) -+ fprintf(stderr, Name ": metadata format %s unknown, ignored.\n", w+9); -+ } else if (strncasecmp(w, "auto=", 5) == 0 ) { -+ /* whether to create device special files as needed */ -+ mis.autof = parse_auto(w+5, "auto type", 0); -+ } else { -+ fprintf(stderr, Name ": unrecognised word on ARRAY line: %s\n", -+ w); -+ } -+ } -+ if (mis.devname == NULL) -+ fprintf(stderr, Name ": ARRAY line with no device\n"); -+ else if (mis.uuid_set == 0 && mis.devices == NULL && mis.super_minor == UnSet && mis.name[0] == 0) -+ fprintf(stderr, Name ": ARRAY line %s has no identity information.\n", mis.devname); -+ else { -+ mi = malloc(sizeof(*mi)); -+ *mi = mis; -+ mi->devname = strdup(mis.devname); -+ mi->next = NULL; -+ *mddevlp = mi; -+ mddevlp = &mi->next; -+ } -+} -+ -+static char *alert_email = NULL; -+void mailline(char *line) -+{ -+ char *w; -+ -+ for (w=dl_next(line); w != line ; w=dl_next(w)) { -+ if (alert_email == NULL) -+ alert_email = strdup(w); -+ else -+ fprintf(stderr, Name ": excess address on MAIL line: %s - ignored\n", -+ w); -+ } -+} -+ -+static char *alert_mail_from = NULL; -+void mailfromline(char *line) -+{ -+ char *w; -+ -+ for (w=dl_next(line); w != line ; w=dl_next(w)) { -+ if (alert_mail_from == NULL) -+ alert_mail_from = strdup(w); -+ else { -+ char *t= NULL; -+ asprintf(&t, "%s %s", alert_mail_from, w); -+ free(alert_mail_from); -+ alert_mail_from = t; -+ } -+ } -+} -+ -+ -+static char *alert_program = NULL; -+void programline(char *line) -+{ -+ char *w; -+ -+ for (w=dl_next(line); w != line ; w=dl_next(w)) { -+ if (alert_program == NULL) -+ alert_program = strdup(w); -+ else -+ fprintf(stderr, Name ": excess program on PROGRAM line: %s - ignored\n", -+ w); -+ } -+} -+ -+static char *home_host = NULL; -+void homehostline(char *line) -+{ -+ char *w; -+ -+ for (w=dl_next(line); w != line ; w=dl_next(w)) { -+ if (home_host == NULL) -+ home_host = strdup(w); -+ else -+ fprintf(stderr, Name ": excess host name on HOMEHOST line: %s - ignored\n", -+ w); -+ } -+} -+ -+ -+int loaded = 0; -+ -+static char *conffile = NULL; -+void set_conffile(char *file) -+{ -+ conffile = file; -+} -+ -+void load_conffile(void) -+{ -+ FILE *f; -+ char *line; -+ -+ if (loaded) return; -+ if (conffile == NULL) -+ conffile = DefaultConfFile; -+ -+ if (strcmp(conffile, "none") == 0) { -+ loaded = 1; -+ return; -+ } -+ if (strcmp(conffile, "partitions")==0) { -+ char *list = dl_strdup("DEV"); -+ dl_init(list); -+ dl_add(list, dl_strdup("partitions")); -+ devline(list); -+ free_line(list); -+ loaded = 1; -+ return; -+ } -+ f = fopen(conffile, "r"); -+ /* Debian chose to relocate mdadm.conf into /etc/mdadm/. -+ * To allow Debian users to compile from clean source and still -+ * have a working mdadm, we read /etc/mdadm/mdadm.conf -+ * if /etc/mdadm.conf doesn't exist -+ */ -+ if (f == NULL && -+ conffile == DefaultConfFile) { -+ f = fopen(DefaultAltConfFile, "r"); -+ if (f) -+ conffile = DefaultAltConfFile; -+ } -+ if (f == NULL) -+ return; -+ -+ loaded = 1; -+ while ((line=conf_line(f))) { -+ switch(match_keyword(line)) { -+ case Devices: -+ devline(line); -+ break; -+ case Array: -+ arrayline(line); -+ break; -+ case Mailaddr: -+ mailline(line); -+ break; -+ case Mailfrom: -+ mailfromline(line); -+ break; -+ case Program: -+ programline(line); -+ break; -+ case CreateDev: -+ createline(line); -+ break; -+ case Homehost: -+ homehostline(line); -+ break; -+ default: -+ fprintf(stderr, Name ": Unknown keyword %s\n", line); -+ } -+ free_line(line); -+ } -+ -+ fclose(f); -+ -+/* printf("got file\n"); */ -+} -+ -+char *conf_get_mailaddr(void) -+{ -+ load_conffile(); -+ return alert_email; -+} -+ -+char *conf_get_mailfrom(void) -+{ -+ load_conffile(); -+ return alert_mail_from; -+} -+ -+char *conf_get_program(void) -+{ -+ load_conffile(); -+ return alert_program; -+} -+ -+char *conf_get_homehost(void) -+{ -+ load_conffile(); -+ return home_host; -+} -+ -+struct createinfo *conf_get_create_info(void) -+{ -+ load_conffile(); -+ return &createinfo; -+} -+ -+mddev_ident_t conf_get_ident(char *dev) -+{ -+ mddev_ident_t rv; -+ load_conffile(); -+ rv = mddevlist; -+ while (dev && rv && strcmp(dev, rv->devname)!=0) -+ rv = rv->next; -+ return rv; -+} -+ -+mddev_dev_t conf_get_devs() -+{ -+ glob_t globbuf; -+ struct conf_dev *cd; -+ int flags = 0; -+ static mddev_dev_t dlist = NULL; -+ unsigned int i; -+ -+ while (dlist) { -+ mddev_dev_t t = dlist; -+ dlist = dlist->next; -+ free(t->devname); -+ free(t); -+ } -+ -+ load_conffile(); -+ -+ if (cdevlist == NULL) -+ /* default to 'partitions */ -+ dlist = load_partitions(); -+ -+ for (cd=cdevlist; cd; cd=cd->next) { -+ if (strcasecmp(cd->name, "partitions")==0 && dlist == NULL) -+ dlist = load_partitions(); -+ else { -+ glob(cd->name, flags, NULL, &globbuf); -+ flags |= GLOB_APPEND; -+ } -+ } -+ if (flags & GLOB_APPEND) { -+ for (i=0; idevname = strdup(globbuf.gl_pathv[i]); -+ t->next = dlist; -+ t->used = 0; -+ dlist = t; -+/* printf("one dev is %s\n", t->devname);*/ -+ } -+ globfree(&globbuf); -+ } -+ -+ return dlist; -+} -+ -+int conf_test_dev(char *devname) -+{ -+ struct conf_dev *cd; -+ if (cdevlist == NULL) -+ /* allow anything by default */ -+ return 1; -+ for (cd = cdevlist ; cd ; cd = cd->next) { -+ if (strcasecmp(cd->name, "partitions") == 0) -+ return 1; -+ if (fnmatch(cd->name, devname, FNM_PATHNAME) == 0) -+ return 1; -+ } -+ return 0; -+} -+ -+ -+int match_oneof(char *devices, char *devname) -+{ -+ /* check if one of the comma separated patterns in devices -+ * matches devname -+ */ -+ -+ -+ while (devices && *devices) { -+ char patn[1024]; -+ char *p = devices; -+ devices = strchr(devices, ','); -+ if (!devices) -+ devices = p + strlen(p); -+ if (devices-p < 1024) { -+ strncpy(patn, p, devices-p); -+ patn[devices-p] = 0; -+ if (fnmatch(patn, devname, FNM_PATHNAME)==0) -+ return 1; -+ } -+ if (*devices == ',') -+ devices++; -+ } -+ return 0; -+} -diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/Config.in busybox-1.7.4+gentoo+mdadm/mdadm/Config.in ---- busybox-1.7.4+gentoo/mdadm/Config.in 1969-12-31 16:00:00.000000000 -0800 -+++ busybox-1.7.4+gentoo+mdadm/mdadm/Config.in 2008-03-11 10:31:00.000000000 -0700 -@@ -0,0 +1,15 @@ -+# -+# For a description of the syntax of this configuration file, -+# see scripts/kbuild/config-language.txt. -+# -+ -+menu "Linux mdadm Utilities" -+ -+config MDADM -+ bool "mdadm" -+ default n -+ help -+ assemble or examine raid array -+ -+endmenu -+ -diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/dlink.c busybox-1.7.4+gentoo+mdadm/mdadm/dlink.c ---- busybox-1.7.4+gentoo/mdadm/dlink.c 1969-12-31 16:00:00.000000000 -0800 -+++ busybox-1.7.4+gentoo+mdadm/mdadm/dlink.c 2008-03-11 10:31:00.000000000 -0700 -@@ -0,0 +1,79 @@ -+ -+/* doubly linked lists */ -+/* This is free software. No strings attached. No copyright claimed */ -+ -+#include -+#include -+#include -+#ifdef __dietlibc__ -+char *strncpy(char *dest, const char *src, size_t n) __THROW; -+#endif -+#include "dlink.h" -+ -+ -+void *dl_head() -+{ -+ void *h; -+ h = dl_alloc(0); -+ dl_next(h) = h; -+ dl_prev(h) = h; -+ return h; -+} -+ -+void dl_free(void *v) -+{ -+ struct __dl_head *vv = v; -+ free(vv-1); -+} -+ -+void dl_init(void *v) -+{ -+ dl_next(v) = v; -+ dl_prev(v) = v; -+} -+ -+void dl_insert(void *head, void *val) -+{ -+ dl_next(val) = dl_next(head); -+ dl_prev(val) = head; -+ dl_next(dl_prev(val)) = val; -+ dl_prev(dl_next(val)) = val; -+} -+ -+void dl_add(void *head, void *val) -+{ -+ dl_prev(val) = dl_prev(head); -+ dl_next(val) = head; -+ dl_next(dl_prev(val)) = val; -+ dl_prev(dl_next(val)) = val; -+} -+ -+void dl_del(void *val) -+{ -+ if (dl_prev(val) == 0 || dl_next(val) == 0) -+ return; -+ dl_prev(dl_next(val)) = dl_prev(val); -+ dl_next(dl_prev(val)) = dl_next(val); -+ dl_prev(val) = dl_next(val) = 0; -+} -+ -+char *dl_strndup(char *s, int l) -+{ -+ char *n; -+ if (s == NULL) -+ return NULL; -+ n = dl_newv(char, l+1); -+ if (n == NULL) -+ return NULL; -+ else -+ { -+ strncpy(n, s, l); -+ n[l] = 0; -+ return n; -+ } -+} -+ -+char *dl_strdup(char *s) -+{ -+ return dl_strndup(s, (int)strlen(s)); -+} -diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/dlink.h busybox-1.7.4+gentoo+mdadm/mdadm/dlink.h ---- busybox-1.7.4+gentoo/mdadm/dlink.h 1969-12-31 16:00:00.000000000 -0800 -+++ busybox-1.7.4+gentoo+mdadm/mdadm/dlink.h 2008-03-11 10:31:00.000000000 -0700 -@@ -0,0 +1,25 @@ -+ -+/* doubley linked lists */ -+/* This is free software. No strings attached. No copyright claimed */ -+ -+struct __dl_head -+{ -+ void * dh_prev; -+ void * dh_next; -+}; -+ -+#define dl_alloc(size) ((void*)(((char*)calloc(1,(size)+sizeof(struct __dl_head)))+sizeof(struct __dl_head))) -+#define dl_new(t) ((t*)dl_alloc(sizeof(t))) -+#define dl_newv(t,n) ((t*)dl_alloc(sizeof(t)*n)) -+ -+#define dl_next(p) *(&(((struct __dl_head*)(p))[-1].dh_next)) -+#define dl_prev(p) *(&(((struct __dl_head*)(p))[-1].dh_prev)) -+ -+void *dl_head(void); -+char *dl_strdup(char *); -+char *dl_strndup(char *, int); -+void dl_insert(void*, void*); -+void dl_add(void*, void*); -+void dl_del(void*); -+void dl_free(void*); -+void dl_init(void*); -diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/md5.h busybox-1.7.4+gentoo+mdadm/mdadm/md5.h ---- busybox-1.7.4+gentoo/mdadm/md5.h 1969-12-31 16:00:00.000000000 -0800 -+++ busybox-1.7.4+gentoo+mdadm/mdadm/md5.h 2008-03-11 10:31:00.000000000 -0700 -@@ -0,0 +1,134 @@ -+/* Declaration of functions and data types used for MD5 sum computing -+ library functions. -+ Copyright (C) 1995-1997,1999-2005 Free Software Foundation, Inc. -+ -+ NOTE: The canonical source of this file is maintained with the GNU C -+ Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. -+ -+ 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 the -+ Free Software Foundation; either version 2, or (at your option) any -+ later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software Foundation, -+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -+ -+#ifndef _MD5_H -+#define _MD5_H 1 -+ -+#include -+ -+# include -+#if HAVE_STDINT_H || _LIBC -+# include -+#endif -+ -+#ifndef __GNUC_PREREQ -+# if defined __GNUC__ && defined __GNUC_MINOR__ -+# define __GNUC_PREREQ(maj, min) \ -+ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) -+# else -+# define __GNUC_PREREQ(maj, min) 0 -+# endif -+#endif -+ -+#ifndef __THROW -+# if defined __cplusplus && __GNUC_PREREQ (2,8) -+# define __THROW throw () -+# else -+# define __THROW -+# endif -+#endif -+ -+#ifndef __attribute__ -+# if ! __GNUC_PREREQ (2,8) || __STRICT_ANSI__ -+# define __attribute__(x) -+# endif -+#endif -+ -+#ifndef _LIBC -+# define __md5_buffer md5_buffer -+# define __md5_finish_ctx md5_finish_ctx -+# define __md5_init_ctx md5_init_ctx -+# define __md5_process_block md5_process_block -+# define __md5_process_bytes md5_process_bytes -+# define __md5_read_ctx md5_read_ctx -+# define __md5_stream md5_stream -+#endif -+ -+typedef uint32_t md5_uint32; -+ -+/* Structure to save state of computation between the single steps. */ -+struct md5_ctx -+{ -+ md5_uint32 A; -+ md5_uint32 B; -+ md5_uint32 C; -+ md5_uint32 D; -+ -+ md5_uint32 total[2]; -+ md5_uint32 buflen; -+ char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32)))); -+}; -+ -+/* -+ * The following three functions are build up the low level used in -+ * the functions `md5_stream' and `md5_buffer'. -+ */ -+ -+/* Initialize structure containing state of computation. -+ (RFC 1321, 3.3: Step 3) */ -+extern void __md5_init_ctx (struct md5_ctx *ctx) __THROW; -+ -+/* Starting with the result of former calls of this function (or the -+ initialization function update the context for the next LEN bytes -+ starting at BUFFER. -+ It is necessary that LEN is a multiple of 64!!! */ -+extern void __md5_process_block (const void *buffer, size_t len, -+ struct md5_ctx *ctx) __THROW; -+ -+/* Starting with the result of former calls of this function (or the -+ initialization function update the context for the next LEN bytes -+ starting at BUFFER. -+ It is NOT required that LEN is a multiple of 64. */ -+extern void __md5_process_bytes (const void *buffer, size_t len, -+ struct md5_ctx *ctx) __THROW; -+ -+/* Process the remaining bytes in the buffer and put result from CTX -+ in first 16 bytes following RESBUF. The result is always in little -+ endian byte order, so that a byte-wise output yields to the wanted -+ ASCII representation of the message digest. -+ -+ IMPORTANT: On some systems it is required that RESBUF be correctly -+ aligned for a 32 bits value. */ -+extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) __THROW; -+ -+ -+/* Put result from CTX in first 16 bytes following RESBUF. The result is -+ always in little endian byte order, so that a byte-wise output yields -+ to the wanted ASCII representation of the message digest. -+ -+ IMPORTANT: On some systems it is required that RESBUF is correctly -+ aligned for a 32 bits value. */ -+extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) __THROW; -+ -+ -+/* Compute MD5 message digest for bytes read from STREAM. The -+ resulting message digest number will be written into the 16 bytes -+ beginning at RESBLOCK. */ -+extern int __md5_stream (FILE *stream, void *resblock) __THROW; -+ -+/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The -+ result is always in little endian byte order, so that a byte-wise -+ output yields to the wanted ASCII representation of the message -+ digest. */ -+extern void *__md5_buffer (const char *buffer, size_t len, -+ void *resblock) __THROW; -+ -+#endif /* md5.h */ -diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/mdadm.c busybox-1.7.4+gentoo+mdadm/mdadm/mdadm.c ---- busybox-1.7.4+gentoo/mdadm/mdadm.c 1969-12-31 16:00:00.000000000 -0800 -+++ busybox-1.7.4+gentoo+mdadm/mdadm/mdadm.c 2008-03-11 10:31:00.000000000 -0700 -@@ -0,0 +1,18 @@ -+/* -+ * mdadm support for busybox. -+ * added by Alan Hourihane -+ */ -+#include -+ -+extern int mdassemble_main(int argc, char **argv); -+extern int mdexamine_main(int argc, char **argv); -+ -+int mdadm_main(int argc, char **argv) { -+ if (argc >= 2) { -+ if (!strncmp(argv[1],"--assemble",10)) -+ return mdassemble_main(argc, argv); -+ if (!strncmp(argv[1],"--examine",9)) -+ return mdexamine_main(argc, argv); -+ } -+ return 0; -+} -diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/mdadm.h busybox-1.7.4+gentoo+mdadm/mdadm/mdadm.h ---- busybox-1.7.4+gentoo/mdadm/mdadm.h 1969-12-31 16:00:00.000000000 -0800 -+++ busybox-1.7.4+gentoo+mdadm/mdadm/mdadm.h 2008-03-11 10:31:00.000000000 -0700 -@@ -0,0 +1,540 @@ -+/* -+ * mdadm - manage Linux "md" devices aka RAID arrays. -+ * -+ * Copyright (C) 2001-2006 Neil Brown -+ * -+ * -+ * 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 -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Author: Neil Brown -+ * Email: -+ * Paper: Neil Brown -+ * School of Computer Science and Engineering -+ * The University of New South Wales -+ * Sydney, 2052 -+ * Australia -+ */ -+ -+#include -+#ifndef __dietlibc__ -+extern __off64_t lseek64 __P ((int __fd, __off64_t __offset, int __whence)); -+#else -+# if defined(__NO_STAT64) || __WORDSIZE != 32 -+# define lseek64 lseek -+# endif -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#ifdef __dietlibc__ -+#include -+/* dietlibc has deprecated random and srandom!! */ -+#define random rand -+#define srandom srand -+#endif -+ -+ -+#include -+/*#include */ -+#include -+#include -+#include -+#define MD_MAJOR 9 -+#define MdpMinorShift 6 -+ -+#ifndef BLKGETSIZE64 -+#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */ -+#endif -+ -+#define DEFAULT_BITMAP_CHUNK 4096 -+#define DEFAULT_BITMAP_DELAY 5 -+#define DEFAULT_MAX_WRITE_BEHIND 256 -+ -+#include "md_u.h" -+#include "md_p.h" -+#include "bitmap.h" -+ -+#include -+/* Redhat don't like to #include , and -+ * some time include isn't enough, -+ * and there is no standard conversion function so... */ -+/* And dietlibc doesn't think byteswap is ok, so.. */ -+/* #include */ -+#define bswap_16(x) (((x) & 0x00ffU) << 8 | \ -+ ((x) & 0xff00U) >> 8) -+#define bswap_32(x) (((x) & 0x000000ffU) << 24 | \ -+ ((x) & 0xff000000U) >> 24 | \ -+ ((x) & 0x0000ff00U) << 8 | \ -+ ((x) & 0x00ff0000U) >> 8) -+#define bswap_64(x) (((x) & 0x00000000000000ffULL) << 56 | \ -+ ((x) & 0xff00000000000000ULL) >> 56 | \ -+ ((x) & 0x000000000000ff00ULL) << 40 | \ -+ ((x) & 0x00ff000000000000ULL) >> 40 | \ -+ ((x) & 0x0000000000ff0000ULL) << 24 | \ -+ ((x) & 0x0000ff0000000000ULL) >> 24 | \ -+ ((x) & 0x00000000ff000000ULL) << 8 | \ -+ ((x) & 0x000000ff00000000ULL) >> 8) -+ -+#if BYTE_ORDER == LITTLE_ENDIAN -+#define __cpu_to_le16(_x) (_x) -+#define __cpu_to_le32(_x) (_x) -+#define __cpu_to_le64(_x) (_x) -+#define __le16_to_cpu(_x) (_x) -+#define __le32_to_cpu(_x) (_x) -+#define __le64_to_cpu(_x) (_x) -+#elif BYTE_ORDER == BIG_ENDIAN -+#define __cpu_to_le16(_x) bswap_16(_x) -+#define __cpu_to_le32(_x) bswap_32(_x) -+#define __cpu_to_le64(_x) bswap_64(_x) -+#define __le16_to_cpu(_x) bswap_16(_x) -+#define __le32_to_cpu(_x) bswap_32(_x) -+#define __le64_to_cpu(_x) bswap_64(_x) -+#else -+# error "unknown endianness." -+#endif -+ -+ -+ -+/* general information that might be extracted from a superblock */ -+struct mdinfo { -+ mdu_array_info_t array; -+ mdu_disk_info_t disk; -+ __u64 events; -+ int uuid[4]; -+ char name[33]; -+ unsigned long long data_offset; -+ unsigned long long component_size; -+ int reshape_active; -+ unsigned long long reshape_progress; -+ int new_level, delta_disks, new_layout, new_chunk; -+}; -+ -+struct createinfo { -+ int uid; -+ int gid; -+ int autof; -+ int mode; -+ int symlinks; -+ struct supertype *supertype; -+}; -+ -+#define Name "mdadm" -+ -+enum mode { -+ ASSEMBLE=1, -+ BUILD, -+ CREATE, -+ MANAGE, -+ MISC, -+ MONITOR, -+ GROW, -+ INCREMENTAL, -+ AUTODETECT, -+}; -+ -+extern char short_options[]; -+extern char short_bitmap_auto_options[]; -+extern struct option long_options[]; -+extern char Version[], Usage[], Help[], OptionHelp[], -+ Help_create[], Help_build[], Help_assemble[], Help_grow[], -+ Help_incr[], -+ Help_manage[], Help_misc[], Help_monitor[], Help_config[]; -+ -+/* for option that don't have short equivilents, we assign arbitrary -+ * small numbers. '1' means an undecorated option, so we start at '2'. -+ */ -+enum special_options { -+ AssumeClean = 2, -+ BitmapChunk, -+ WriteBehind, -+ ReAdd, -+ NoDegraded, -+ Sparc22, -+ BackupFile, -+ HomeHost, -+ AutoHomeHost, -+ Symlinks, -+ AutoDetect, -+}; -+ -+/* structures read from config file */ -+/* List of mddevice names and identifiers -+ * Identifiers can be: -+ * uuid=128-hex-uuid -+ * super-minor=decimal-minor-number-from-superblock -+ * devices=comma,separated,list,of,device,names,with,wildcards -+ * -+ * If multiple fields are present, the intersection of all matching -+ * devices is considered -+ */ -+#define UnSet (0xfffe) -+typedef struct mddev_ident_s { -+ char *devname; -+ -+ int uuid_set; -+ int uuid[4]; -+ char name[33]; -+ -+ unsigned int super_minor; -+ -+ char *devices; /* comma separated list of device -+ * names with wild cards -+ */ -+ int level; -+ unsigned int raid_disks; -+ unsigned int spare_disks; -+ struct supertype *st; -+ int autof; /* 1 for normal, 2 for partitioned */ -+ char *spare_group; -+ char *bitmap_file; -+ int bitmap_fd; -+ -+ struct mddev_ident_s *next; -+} *mddev_ident_t; -+ -+/* List of device names - wildcards expanded */ -+typedef struct mddev_dev_s { -+ char *devname; -+ char disposition; /* 'a' for add, 'r' for remove, 'f' for fail. -+ * Not set for names read from .config -+ */ -+ char writemostly; -+ char re_add; -+ char used; /* set when used */ -+ struct mddev_dev_s *next; -+} *mddev_dev_t; -+ -+typedef struct mapping { -+ char *name; -+ int num; -+} mapping_t; -+ -+ -+struct mdstat_ent { -+ char *dev; -+ int devnum; -+ int active; -+ char *level; -+ char *pattern; /* U or up, _ for down */ -+ int percent; /* -1 if no resync */ -+ int resync; /* 1 if resync, 0 if recovery */ -+ struct mdstat_ent *next; -+}; -+ -+extern struct mdstat_ent *mdstat_read(int hold, int start); -+extern void free_mdstat(struct mdstat_ent *ms); -+extern void mdstat_wait(int seconds); -+extern int mddev_busy(int devnum); -+ -+struct map_ent { -+ struct map_ent *next; -+ int devnum; -+ int major,minor; -+ int uuid[4]; -+ char *path; -+}; -+extern int map_update(struct map_ent **mpp, int devnum, int major, int minor, -+ int uuid[4], char *path); -+extern struct map_ent *map_by_uuid(struct map_ent **map, int uuid[4]); -+extern void map_read(struct map_ent **melp); -+extern int map_write(struct map_ent *mel); -+extern void map_delete(struct map_ent **mapp, int devnum); -+extern void map_free(struct map_ent *map); -+extern void map_add(struct map_ent **melp, -+ int devnum, int major, int minor, int uuid[4], char *path); -+ -+/* Data structure for holding info read from sysfs */ -+struct sysdev { -+ char name[20]; -+ int role; -+ int major, minor; -+ unsigned long long offset, size; -+ int state; -+ int errors; -+ struct sysdev *next; -+}; -+struct sysarray { -+ char name[20]; -+ struct sysdev *devs; -+ int chunk; -+ unsigned long long component_size; -+ int layout; -+ int level; -+ int spares; -+ int cache_size; -+ int mismatch_cnt; -+ int major_version, minor_version; -+}; -+/* various details can be requested */ -+#define GET_LEVEL 1 -+#define GET_LAYOUT 2 -+#define GET_COMPONENT 4 -+#define GET_CHUNK 8 -+#define GET_CACHE 16 -+#define GET_MISMATCH 32 -+#define GET_VERSION 64 -+ -+#define GET_DEVS 1024 /* gets role, major, minor */ -+#define GET_OFFSET 2048 -+#define GET_SIZE 4096 -+#define GET_STATE 8192 -+#define GET_ERROR 16384 -+ -+/* If fd >= 0, get the array it is open on, -+ * else use devnum. >=0 -> major9. <0..... -+ */ -+extern void sysfs_free(struct sysarray *sra); -+extern struct sysarray *sysfs_read(int fd, int devnum, unsigned long options); -+extern int sysfs_set_str(struct sysarray *sra, struct sysdev *dev, -+ char *name, char *val); -+extern int sysfs_set_num(struct sysarray *sra, struct sysdev *dev, -+ char *name, unsigned long long val); -+extern int sysfs_get_ll(struct sysarray *sra, struct sysdev *dev, -+ char *name, unsigned long long *val); -+ -+ -+extern int save_stripes(int *source, unsigned long long *offsets, -+ int raid_disks, int chunk_size, int level, int layout, -+ int nwrites, int *dest, -+ unsigned long long start, unsigned long long length); -+extern int restore_stripes(int *dest, unsigned long long *offsets, -+ int raid_disks, int chunk_size, int level, int layout, -+ int source, unsigned long long read_offset, -+ unsigned long long start, unsigned long long length); -+ -+#ifndef Sendmail -+#define Sendmail "/usr/lib/sendmail -t" -+#endif -+ -+#define SYSLOG_FACILITY LOG_DAEMON -+ -+extern char *map_num(mapping_t *map, int num); -+extern int map_name(mapping_t *map, char *name); -+extern mapping_t r5layout[], pers[], modes[], faultylayout[]; -+ -+extern char *map_dev(int major, int minor, int create); -+ -+ -+extern struct superswitch { -+ void (*examine_super)(void *sbv, char *homehost); -+ void (*brief_examine_super)(void *sbv); -+ void (*detail_super)(void *sbv, char *homehost); -+ void (*export_super)(void *sbv); -+ void (*brief_detail_super)(void *sbv); -+ void (*uuid_from_super)(int uuid[4], void *sbv); -+ void (*getinfo_super)(struct mdinfo *info, void *sbv); -+ int (*match_home)(void *sbv, char *homehost); -+ int (*update_super)(struct mdinfo *info, void *sbv, char *update, -+ char *devname, int verbose, -+ int uuid_set, char *homehost); -+ int (*init_super)(struct supertype *st, void **sbp, mdu_array_info_t *info, unsigned long long size, char *name, char *homehost, int *uuid); -+ void (*add_to_super)(void *sbv, mdu_disk_info_t *dinfo); -+ int (*store_super)(struct supertype *st, int fd, void *sbv); -+ int (*write_init_super)(struct supertype *st, void *sbv, mdu_disk_info_t *dinfo, char *devname); -+ int (*compare_super)(void **firstp, void *secondv); -+ int (*load_super)(struct supertype *st, int fd, void **sbp, char *devname); -+ struct supertype * (*match_metadata_desc)(char *arg); -+ __u64 (*avail_size)(struct supertype *st, __u64 size); -+ int (*add_internal_bitmap)(struct supertype *st, void *sbv, int *chunkp, -+ int delay, int write_behind, -+ unsigned long long size, int may_change, int major); -+ void (*locate_bitmap)(struct supertype *st, int fd, void *sbv); -+ int (*write_bitmap)(struct supertype *st, int fd, void *sbv); -+ int major; -+ int swapuuid; /* true if uuid is bigending rather than hostendian */ -+} super0, super1, *superlist[]; -+ -+struct supertype { -+ struct superswitch *ss; -+ int minor_version; -+ int max_devs; -+}; -+ -+extern struct supertype *super_by_version(int vers, int minor); -+extern struct supertype *guess_super(int fd); -+extern int get_dev_size(int fd, char *dname, unsigned long long *sizep); -+extern void get_one_disk(int mdfd, mdu_array_info_t *ainf, -+ mdu_disk_info_t *disk); -+ -+#if __GNUC__ < 3 -+struct stat64; -+#endif -+ -+#define HAVE_NFTW we assume -+#define HAVE_FTW -+ -+#ifdef UCLIBC -+# include -+# ifndef __UCLIBC_HAS_FTW__ -+# undef HAVE_FTW -+# undef HAVE_NFTW -+# endif -+#endif -+ -+#ifdef __dietlibc__ -+# undef HAVE_NFTW -+#endif -+ -+#ifndef HAVE_NFTW -+# define FTW_PHYS 1 -+# ifndef HAVE_FTW -+ struct FTW {}; -+# endif -+#endif -+ -+#ifdef HAVE_FTW -+# include -+#endif -+ -+extern int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s); -+ -+ -+extern int Manage_ro(char *devname, int fd, int readonly); -+extern int Manage_runstop(char *devname, int fd, int runstop, int quiet); -+extern int Manage_resize(char *devname, int fd, long long size, int raid_disks); -+extern int Manage_reconfig(char *devname, int fd, int layout); -+extern int Manage_subdevs(char *devname, int fd, -+ mddev_dev_t devlist, int verbose); -+extern int autodetect(void); -+extern int Grow_Add_device(char *devname, int fd, char *newdev); -+extern int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int write_behind, int force); -+extern int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, -+ long long size, -+ int level, int layout, int chunksize, int raid_disks); -+extern int Grow_restart(struct supertype *st, struct mdinfo *info, -+ int *fdlist, int cnt, char *backup_file); -+ -+ -+extern int Assemble(struct supertype *st, char *mddev, int mdfd, -+ mddev_ident_t ident, -+ mddev_dev_t devlist, char *backup_file, -+ int readonly, int runstop, -+ char *update, char *homehost, -+ int verbose, int force); -+ -+extern int Build(char *mddev, int mdfd, int chunk, int level, int layout, -+ int raiddisks, -+ mddev_dev_t devlist, int assume_clean, -+ char *bitmap_file, int bitmap_chunk, int write_behind, int delay, int verbose); -+ -+ -+extern int Create(struct supertype *st, char *mddev, int mdfd, -+ int chunk, int level, int layout, unsigned long long size, int raiddisks, int sparedisks, -+ char *name, char *homehost, int *uuid, -+ int subdevs, mddev_dev_t devlist, -+ int runstop, int verbose, int force, int assume_clean, -+ char *bitmap_file, int bitmap_chunk, int write_behind, int delay); -+ -+extern int Detail(char *dev, int brief, int export, int test, char *homehost); -+extern int Query(char *dev); -+ -+extern int md_get_version(int fd); -+extern int get_linux_version(void); -+extern int parse_uuid(char *str, int uuid[4]); -+extern int check_ext2(int fd, char *name); -+extern int check_reiser(int fd, char *name); -+extern int check_raid(int fd, char *name); -+ -+extern int get_mdp_major(void); -+extern int dev_open(char *dev, int flags); -+extern int is_standard(char *dev, int *nump); -+ -+extern int parse_auto(char *str, char *msg, int config); -+extern mddev_ident_t conf_get_ident(char *dev); -+extern mddev_dev_t conf_get_devs(void); -+extern int conf_test_dev(char *devname); -+extern struct createinfo *conf_get_create_info(void); -+extern void set_conffile(char *file); -+extern char *conf_get_mailaddr(void); -+extern char *conf_get_mailfrom(void); -+extern char *conf_get_program(void); -+extern char *conf_get_homehost(void); -+extern char *conf_line(FILE *file); -+extern char *conf_word(FILE *file, int allow_key); -+extern void free_line(char *line); -+extern int match_oneof(char *devices, char *devname); -+extern void uuid_from_super(int uuid[4], mdp_super_t *super); -+extern int same_uuid(int a[4], int b[4], int swapuuid); -+extern void copy_uuid(void *a, int b[4], int swapuuid); -+/* extern int compare_super(mdp_super_t *first, mdp_super_t *second);*/ -+extern unsigned long calc_csum(void *super, int bytes); -+extern int enough(int level, int raid_disks, int layout, int clean, -+ char *avail, int avail_disks); -+extern int ask(char *mesg); -+extern unsigned long long get_component_size(int fd); -+extern void remove_partitions(int fd); -+ -+ -+extern char *human_size(long long bytes); -+char *human_size_brief(long long bytes); -+ -+extern void put_md_name(char *name); -+extern char *get_md_name(int dev); -+ -+extern char DefaultConfFile[]; -+ -+extern int open_mddev(char *dev, int autof); -+extern int open_mddev_devnum(char *devname, int devnum, char *name, -+ char *chosen_name); -+ -+ -+#define LEVEL_MULTIPATH (-4) -+#define LEVEL_LINEAR (-1) -+#define LEVEL_FAULTY (-5) -+ -+ -+/* faulty stuff */ -+ -+#define WriteTransient 0 -+#define ReadTransient 1 -+#define WritePersistent 2 -+#define ReadPersistent 3 -+#define WriteAll 4 /* doesn't go to device */ -+#define ReadFixable 5 -+#define Modes 6 -+ -+#define ClearErrors 31 -+#define ClearFaults 30 -+ -+#define AllPersist 100 /* internal use only */ -+#define NoPersist 101 -+ -+#define ModeMask 0x1f -+#define ModeShift 5 -+ -+ -+#ifdef __TINYC__ -+#undef minor -+#undef major -+#undef makedev -+#define minor(x) ((x)&0xff) -+#define major(x) (((x)>>8)&0xff) -+#define makedev(M,m) (((M)<<8) | (m)) -+#endif -+ -+/* for raid5 */ -+#define ALGORITHM_LEFT_ASYMMETRIC 0 -+#define ALGORITHM_RIGHT_ASYMMETRIC 1 -+#define ALGORITHM_LEFT_SYMMETRIC 2 -+#define ALGORITHM_RIGHT_SYMMETRIC 3 -diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/mdassemble.c busybox-1.7.4+gentoo+mdadm/mdadm/mdassemble.c ---- busybox-1.7.4+gentoo/mdadm/mdassemble.c 1969-12-31 16:00:00.000000000 -0800 -+++ busybox-1.7.4+gentoo+mdadm/mdadm/mdassemble.c 2008-03-11 10:31:00.000000000 -0700 -@@ -0,0 +1,908 @@ -+/* -+ * mdadm - manage Linux "md" devices aka RAID arrays. -+ * -+ * Copyright (C) 2001-2006 Neil Brown -+ * -+ * -+ * 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 -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Author: Neil Brown -+ * Email: -+ * Paper: Neil Brown -+ * School of Computer Science and Engineering -+ * The University of New South Wales -+ * Sydney, 2052 -+ * Australia -+ */ -+ -+#include "mdadm.h" -+#include -+ -+static int name_matches(char *found, char *required, char *homehost) -+{ -+ /* See if the name found matches the required name, possibly -+ * prefixed with 'homehost' -+ */ -+ char fnd[33]; -+ -+ strncpy(fnd, found, 32); -+ fnd[32] = 0; -+ if (strcmp(found, required)==0) -+ return 1; -+ if (homehost) { -+ int l = strlen(homehost); -+ if (l < 32 && fnd[l] == ':' && -+ strcmp(fnd+l+1, required)==0) -+ return 1; -+ } -+ return 0; -+} -+ -+int open_mddev(char *dev, int autof/*unused */) -+{ -+ int mdfd = open(dev, O_RDWR, 0); -+ if (mdfd < 0) -+ fprintf(stderr, Name ": error opening %s: %s\n", -+ dev, strerror(errno)); -+ else if (md_get_version(mdfd) <= 0) { -+ fprintf(stderr, Name ": %s does not appear to be an md device\n", -+ dev); -+ close(mdfd); -+ mdfd = -1; -+ } -+ return mdfd; -+} -+ -+int Assemble(struct supertype *st, char *mddev, int mdfd, -+ mddev_ident_t ident, -+ mddev_dev_t devlist, char *backup_file, -+ int readonly, int runstop, -+ char *update, char *homehost, -+ int verbose, int force) -+{ -+ /* -+ * The task of Assemble is to find a collection of -+ * devices that should (according to their superblocks) -+ * form an array, and to give this collection to the MD driver. -+ * In Linux-2.4 and later, this involves submitting a -+ * SET_ARRAY_INFO ioctl with no arg - to prepare -+ * the array - and then submit a number of -+ * ADD_NEW_DISK ioctls to add disks into -+ * the array. Finally RUN_ARRAY might -+ * be submitted to start the array. -+ * -+ * Much of the work of Assemble is in finding and/or -+ * checking the disks to make sure they look right. -+ * -+ * If mddev is not set, then scan must be set and we -+ * read through the config file for dev+uuid mapping -+ * We recurse, setting mddev, for each device that -+ * - isn't running -+ * - has a valid uuid (or any uuid if !uuidset) -+ * -+ * If mddev is set, we try to determine state of md. -+ * check version - must be at least 0.90.0 -+ * check kernel version. must be at least 2.4. -+ * If not, we can possibly fall back on START_ARRAY -+ * Try to GET_ARRAY_INFO. -+ * If possible, give up -+ * If not, try to STOP_ARRAY just to make sure -+ * -+ * If !uuidset and scan, look in conf-file for uuid -+ * If not found, give up -+ * If !devlist and scan and uuidset, get list of devs from conf-file -+ * -+ * For each device: -+ * Check superblock - discard if bad -+ * Check uuid (set if we don't have one) - discard if no match -+ * Check superblock similarity if we have a superblock - discard if different -+ * Record events, devicenum -+ * This should give us a list of devices for the array -+ * We should collect the most recent event number -+ * -+ * Count disks with recent enough event count -+ * While force && !enough disks -+ * Choose newest rejected disks, update event count -+ * mark clean and rewrite superblock -+ * If recent kernel: -+ * SET_ARRAY_INFO -+ * foreach device with recent events : ADD_NEW_DISK -+ * if runstop == 1 || "enough" disks and runstop==0 -> RUN_ARRAY -+ * If old kernel: -+ * Check the device numbers in superblock are right -+ * update superblock if any changes -+ * START_ARRAY -+ * -+ */ -+ int clean = 0; -+ int old_linux = 0; -+ int vers = 0; /* Keep gcc quite - it really is initialised */ -+ void *first_super = NULL, *super = NULL; -+ struct { -+ char *devname; -+ unsigned int major, minor; -+ unsigned int oldmajor, oldminor; -+ long long events; -+ int uptodate; -+ int state; -+ int raid_disk; -+ int disk_nr; -+ } *devices; -+ int *best = NULL; /* indexed by raid_disk */ -+ unsigned int bestcnt = 0; -+ int devcnt = 0; -+ unsigned int okcnt, sparecnt; -+ unsigned int req_cnt; -+ unsigned int i; -+ int most_recent = 0; -+ int chosen_drive; -+ int change = 0; -+ int inargv = 0; -+ int bitmap_done; -+ int start_partial_ok = (runstop >= 0) && (force || devlist==NULL || mdfd < 0); -+ unsigned int num_devs; -+ mddev_dev_t tmpdev; -+ struct mdinfo info; -+ char *avail; -+ int nextspare = 0; -+ -+ if (mdfd < 0) -+ return 2; -+ -+ if (get_linux_version() < 2004000) -+ old_linux = 1; -+ -+ if (mdfd >= 0) { -+ vers = md_get_version(mdfd); -+ if (vers <= 0) { -+ fprintf(stderr, Name ": %s appears not to be an md device.\n", mddev); -+ return 1; -+ } -+ if (vers < 9000) { -+ fprintf(stderr, Name ": Assemble requires driver version 0.90.0 or later.\n" -+ " Upgrade your kernel or try --build\n"); -+ return 1; -+ } -+ -+ if (ioctl(mdfd, GET_ARRAY_INFO, &info.array)>=0) { -+ fprintf(stderr, Name ": device %s already active - cannot assemble it\n", -+ mddev); -+ return 1; -+ } -+ ioctl(mdfd, STOP_ARRAY, NULL); /* just incase it was started but has no content */ -+ } -+ /* -+ * If any subdevs are listed, then any that don't -+ * match ident are discarded. Remainder must all match and -+ * become the array. -+ * If no subdevs, then we scan all devices in the config file, but -+ * there must be something in the identity -+ */ -+ -+ if (!devlist && -+ ident->uuid_set == 0 && -+ ident->super_minor < 0 && -+ ident->devices == NULL) { -+ fprintf(stderr, Name ": No identity information available for %s - cannot assemble.\n", -+ mddev ? mddev : "further assembly"); -+ return 1; -+ } -+ if (devlist == NULL) -+ devlist = conf_get_devs(); -+ else if (mdfd >= 0) -+ inargv = 1; -+ -+ tmpdev = devlist; num_devs = 0; -+ while (tmpdev) { -+ if (tmpdev->used) -+ tmpdev->used = 2; -+ else -+ num_devs++; -+ tmpdev = tmpdev->next; -+ } -+ devices = malloc(num_devs * sizeof(*devices)); -+ -+ if (!st && ident->st) st = ident->st; -+ -+ if (verbose>0) -+ fprintf(stderr, Name ": looking for devices for %s\n", -+ mddev ? mddev : "further assembly"); -+ -+ /* first walk the list of devices to find a consistent set -+ * that match the criterea, if that is possible. -+ * We flag the one we like with 'used'. -+ */ -+ for (tmpdev = devlist; -+ tmpdev; -+ tmpdev = tmpdev->next) { -+ char *devname = tmpdev->devname; -+ int dfd; -+ struct stat stb; -+ struct supertype *tst = st; -+ -+ if (tmpdev->used > 1) continue; -+ -+ if (ident->devices && -+ !match_oneof(ident->devices, devname)) { -+ if ((inargv && verbose>=0) || verbose > 0) -+ fprintf(stderr, Name ": %s is not one of %s\n", devname, ident->devices); -+ continue; -+ } -+ -+ if (super) { -+ free(super); -+ super = NULL; -+ } -+ -+ dfd = dev_open(devname, O_RDONLY|O_EXCL); -+ if (dfd < 0) { -+ if ((inargv && verbose >= 0) || verbose > 0) -+ fprintf(stderr, Name ": cannot open device %s: %s\n", -+ devname, strerror(errno)); -+ tmpdev->used = 2; -+ } else if (fstat(dfd, &stb)< 0) { -+ /* Impossible! */ -+ fprintf(stderr, Name ": fstat failed for %s: %s\n", -+ devname, strerror(errno)); -+ tmpdev->used = 2; -+ } else if ((stb.st_mode & S_IFMT) != S_IFBLK) { -+ fprintf(stderr, Name ": %s is not a block device.\n", -+ devname); -+ tmpdev->used = 2; -+ } else if (!tst && (tst = guess_super(dfd)) == NULL) { -+ if ((inargv && verbose >= 0) || verbose > 0) -+ fprintf(stderr, Name ": no recogniseable superblock on %s\n", -+ devname); -+ tmpdev->used = 2; -+ } else if (tst->ss->load_super(tst,dfd, &super, NULL)) { -+ if ((inargv && verbose >= 0) || verbose > 0) -+ fprintf( stderr, Name ": no RAID superblock on %s\n", -+ devname); -+ } else { -+ tst->ss->getinfo_super(&info, super); -+ } -+ if (dfd >= 0) close(dfd); -+ -+ if (ident->uuid_set && (!update || strcmp(update, "uuid")!= 0) && -+ (!super || same_uuid(info.uuid, ident->uuid, tst->ss->swapuuid)==0)) { -+ if ((inargv && verbose >= 0) || verbose > 0) -+ fprintf(stderr, Name ": %s has wrong uuid.\n", -+ devname); -+ continue; -+ } -+ if (ident->name[0] && (!update || strcmp(update, "name")!= 0) && -+ (!super || name_matches(info.name, ident->name, homehost)==0)) { -+ if ((inargv && verbose >= 0) || verbose > 0) -+ fprintf(stderr, Name ": %s has wrong name.\n", -+ devname); -+ continue; -+ } -+ if (ident->super_minor != UnSet && -+ (!super || ident->super_minor != info.array.md_minor)) { -+ if ((inargv && verbose >= 0) || verbose > 0) -+ fprintf(stderr, Name ": %s has wrong super-minor.\n", -+ devname); -+ continue; -+ } -+ if (ident->level != UnSet && -+ (!super|| ident->level != info.array.level)) { -+ if ((inargv && verbose >= 0) || verbose > 0) -+ fprintf(stderr, Name ": %s has wrong raid level.\n", -+ devname); -+ continue; -+ } -+ if (ident->raid_disks != UnSet && -+ (!super || ident->raid_disks!= info.array.raid_disks)) { -+ if ((inargv && verbose >= 0) || verbose > 0) -+ fprintf(stderr, Name ": %s requires wrong number of drives.\n", -+ devname); -+ continue; -+ } -+ if (mdfd < 0) { -+ if (tst == NULL || super == NULL) -+ continue; -+ if (update == NULL && -+ tst->ss->match_home(super, homehost)==0) { -+ if ((inargv && verbose >= 0) || verbose > 0) -+ fprintf(stderr, Name ": %s is not built for host %s.\n", -+ devname, homehost); -+ /* Auto-assemble, and this is not a usable host */ -+ /* if update != NULL, we are updating the host -+ * name... */ -+ continue; -+ } -+ } -+ /* If we are this far, then we are nearly commited to this device. -+ * If the super_block doesn't exist, or doesn't match others, -+ * then we probably cannot continue -+ * However if one of the arrays is for the homehost, and -+ * the other isn't that can disambiguate. -+ */ -+ -+ if (!super) { -+ fprintf(stderr, Name ": %s has no superblock - assembly aborted\n", -+ devname); -+ free(first_super); -+ return 1; -+ } -+ -+ if (st == NULL) -+ st = tst; -+ if (st->ss != tst->ss || -+ st->minor_version != tst->minor_version || -+ st->ss->compare_super(&first_super, super) != 0) { -+ /* Some mismatch. If exactly one array matches this host, -+ * we can resolve on that one. -+ * Or, if we are auto assembling, we just ignore the second -+ * for now. -+ */ -+ if (mdfd < 0) -+ continue; -+ if (homehost) { -+ int first = st->ss->match_home(first_super, homehost); -+ int last = tst->ss->match_home(super, homehost); -+ if (first+last == 1) { -+ /* We can do something */ -+ if (first) {/* just ignore this one */ -+ if ((inargv && verbose >= 0) || verbose > 0) -+ fprintf(stderr, Name ": %s misses out due to wrong homehost\n", -+ devname); -+ continue; -+ } else { /* reject all those sofar */ -+ mddev_dev_t td; -+ if ((inargv && verbose >= 0) || verbose > 0) -+ fprintf(stderr, Name ": %s overrides previous devices due to good homehost\n", -+ devname); -+ for (td=devlist; td != tmpdev; td=td->next) -+ if (td->used == 1) -+ td->used = 0; -+ tmpdev->used = 1; -+ continue; -+ } -+ } -+ } -+ fprintf(stderr, Name ": superblock on %s doesn't match others - assembly aborted\n", -+ devname); -+ free(super); -+ free(first_super); -+ return 1; -+ } -+ -+ tmpdev->used = 1; -+ } -+ -+ /* Ok, no bad inconsistancy, we can try updating etc */ -+ bitmap_done = 0; -+ for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) if (tmpdev->used == 1) { -+ char *devname = tmpdev->devname; -+ struct stat stb; -+ /* looks like a good enough match to update the super block if needed */ -+ { -+ int dfd; -+ dfd = dev_open(devname, O_RDWR|O_EXCL); -+ -+ remove_partitions(dfd); -+ -+ if (super) { -+ free(super); -+ super = NULL; -+ } -+ -+ st->ss->load_super(st, dfd, &super, NULL); -+ st->ss->getinfo_super(&info, super); -+ close(dfd); -+ } -+ -+ stat(devname, &stb); -+ -+ if (verbose > 0) -+ fprintf(stderr, Name ": %s is identified as a member of %s, slot %d.\n", -+ devname, mddev, info.disk.raid_disk); -+ devices[devcnt].devname = devname; -+ devices[devcnt].major = major(stb.st_rdev); -+ devices[devcnt].minor = minor(stb.st_rdev); -+ devices[devcnt].oldmajor = info.disk.major; -+ devices[devcnt].oldminor = info.disk.minor; -+ devices[devcnt].events = info.events; -+ devices[devcnt].raid_disk = info.disk.raid_disk; -+ devices[devcnt].disk_nr = info.disk.number; -+ devices[devcnt].uptodate = 0; -+ devices[devcnt].state = info.disk.state; -+ if (most_recent < devcnt) { -+ if (devices[devcnt].events -+ > devices[most_recent].events) -+ most_recent = devcnt; -+ } -+ if (info.array.level == -4) -+ /* with multipath, the raid_disk from the superblock is meaningless */ -+ i = devcnt; -+ else -+ i = devices[devcnt].raid_disk; -+ if (i+1 == 0) { -+ if (nextspare < info.array.raid_disks) -+ nextspare = info.array.raid_disks; -+ i = nextspare++; -+ } else { -+ if (i >= info.array.raid_disks && -+ i >= nextspare) -+ nextspare = i+1; -+ } -+ if (i < 10000) { -+ if (i >= bestcnt) { -+ unsigned int newbestcnt = i+10; -+ int *newbest = malloc(sizeof(int)*newbestcnt); -+ unsigned int c; -+ for (c=0; c < newbestcnt; c++) -+ if (c < bestcnt) -+ newbest[c] = best[c]; -+ else -+ newbest[c] = -1; -+ if (best)free(best); -+ best = newbest; -+ bestcnt = newbestcnt; -+ } -+ if (best[i] >=0 && -+ devices[best[i]].events == devices[devcnt].events && -+ devices[best[i]].minor != devices[devcnt].minor && -+ st->ss->major == 0 && -+ info.array.level != -4) { -+ /* two different devices with identical superblock. -+ * Could be a mis-detection caused by overlapping -+ * partitions. fail-safe. -+ */ -+ fprintf(stderr, Name ": WARNING %s and %s appear" -+ " to have very similar superblocks.\n" -+ " If they are really different, " -+ "please --zero the superblock on one\n" -+ " If they are the same or overlap," -+ " please remove one from %s.\n", -+ devices[best[i]].devname, devname, -+ inargv ? "the list" : -+ "the\n DEVICE list in mdadm.conf" -+ ); -+ return 1; -+ } -+ if (best[i] == -1 -+ || devices[best[i]].events < devices[devcnt].events) -+ best[i] = devcnt; -+ } -+ devcnt++; -+ } -+ -+ if (super) -+ free(super); -+ super = NULL; -+ -+ if (update && strcmp(update, "byteorder")==0) -+ st->minor_version = 90; -+ -+ if (devcnt == 0) { -+ fprintf(stderr, Name ": no devices found for %s\n", -+ mddev); -+ free(first_super); -+ return 1; -+ } -+ -+ st->ss->getinfo_super(&info, first_super); -+ clean = info.array.state & 1; -+ -+ /* now we have some devices that might be suitable. -+ * I wonder how many -+ */ -+ avail = malloc(info.array.raid_disks); -+ memset(avail, 0, info.array.raid_disks); -+ okcnt = 0; -+ sparecnt=0; -+ for (i=0; i< bestcnt ;i++) { -+ int j = best[i]; -+ int event_margin = 1; /* always allow a difference of '1' -+ * like the kernel does -+ */ -+ if (j < 0) continue; -+ /* note: we ignore error flags in multipath arrays -+ * as they don't make sense -+ */ -+ if (info.array.level != -4) -+ if (!(devices[j].state & (1<= -+ devices[most_recent].events) { -+ devices[j].uptodate = 1; -+ if (i < info.array.raid_disks) { -+ okcnt++; -+ avail[i]=1; -+ } else -+ sparecnt++; -+ } -+ } -+ while (force && !enough(info.array.level, info.array.raid_disks, -+ info.array.layout, 1, -+ avail, okcnt)) { -+ /* Choose the newest best drive which is -+ * not up-to-date, update the superblock -+ * and add it. -+ */ -+ int fd; -+ long long current_events; -+ chosen_drive = -1; -+ for (i=0; i=0 && -+ !devices[j].uptodate && -+ devices[j].events > 0 && -+ (chosen_drive < 0 || -+ devices[j].events > devices[chosen_drive].events)) -+ chosen_drive = j; -+ } -+ if (chosen_drive < 0) -+ break; -+ current_events = devices[chosen_drive].events; -+ add_another: -+ if (verbose >= 0) -+ fprintf(stderr, Name ": forcing event count in %s(%d) from %d upto %d\n", -+ devices[chosen_drive].devname, devices[chosen_drive].raid_disk, -+ (int)(devices[chosen_drive].events), -+ (int)(devices[most_recent].events)); -+ fd = dev_open(devices[chosen_drive].devname, O_RDWR|O_EXCL); -+ if (fd < 0) { -+ fprintf(stderr, Name ": Couldn't open %s for write - not updating\n", -+ devices[chosen_drive].devname); -+ devices[chosen_drive].events = 0; -+ continue; -+ } -+ if (st->ss->load_super(st,fd, &super, NULL)) { -+ close(fd); -+ fprintf(stderr, Name ": RAID superblock disappeared from %s - not updating.\n", -+ devices[chosen_drive].devname); -+ devices[chosen_drive].events = 0; -+ continue; -+ } -+ info.events = devices[most_recent].events; -+ st->ss->update_super(&info, super, "force-one", -+ devices[chosen_drive].devname, verbose, -+ 0, NULL); -+ -+ if (st->ss->store_super(st, fd, super)) { -+ close(fd); -+ fprintf(stderr, Name ": Could not re-write superblock on %s\n", -+ devices[chosen_drive].devname); -+ devices[chosen_drive].events = 0; -+ free(super); -+ continue; -+ } -+ close(fd); -+ devices[chosen_drive].events = devices[most_recent].events; -+ devices[chosen_drive].uptodate = 1; -+ avail[chosen_drive] = 1; -+ okcnt++; -+ free(super); -+ -+ /* If there are any other drives of the same vintage, -+ * add them in as well. We can't lose and we might gain -+ */ -+ for (i=0; i= 0 && -+ !devices[j].uptodate && -+ devices[j].events > 0 && -+ devices[j].events == current_events) { -+ chosen_drive = j; -+ goto add_another; -+ } -+ } -+ } -+ -+ /* Now we want to look at the superblock which the kernel will base things on -+ * and compare the devices that we think are working with the devices that the -+ * superblock thinks are working. -+ * If there are differences and --force is given, then update this chosen -+ * superblock. -+ */ -+ chosen_drive = -1; -+ super = NULL; -+ for (i=0; chosen_drive < 0 && iss->load_super(st,fd, &super, NULL)) { -+ close(fd); -+ fprintf(stderr, Name ": RAID superblock has disappeared from %s\n", -+ devices[j].devname); -+ return 1; -+ } -+ close(fd); -+ } -+ if (super == NULL) { -+ fprintf(stderr, Name ": No suitable drives found for %s\n", mddev); -+ return 1; -+ } -+ st->ss->getinfo_super(&info, super); -+ for (i=0; iss->update_super(&info, super, "assemble", NULL, verbose, 0, NULL)) { -+ if (force) { -+ if (verbose >= 0) -+ fprintf(stderr, Name ": " -+ "clearing FAULTY flag for device %d in %s for %s\n", -+ j, mddev, devices[j].devname); -+ change = 1; -+ } else { -+ if (verbose >= -1) -+ fprintf(stderr, Name ": " -+ "device %d in %s has wrong state in superblock, but %s seems ok\n", -+ i, mddev, devices[j].devname); -+ } -+ } -+#if 0 -+ if (!devices[j].uptodate && -+ !(super.disks[i].state & (1 << MD_DISK_FAULTY))) { -+ fprintf(stderr, Name ": devices %d of %s is not marked FAULTY in superblock, but cannot be found\n", -+ i, mddev); -+ } -+#endif -+ } -+ if (force && !clean && -+ !enough(info.array.level, info.array.raid_disks, -+ info.array.layout, clean, -+ avail, okcnt)) { -+ change += st->ss->update_super(&info, super, "force-array", -+ devices[chosen_drive].devname, verbose, -+ 0, NULL); -+ clean = 1; -+ } -+ -+ if (change) { -+ int fd; -+ fd = dev_open(devices[chosen_drive].devname, O_RDWR|O_EXCL); -+ if (fd < 0) { -+ fprintf(stderr, Name ": Could not open %s for write - cannot Assemble array.\n", -+ devices[chosen_drive].devname); -+ return 1; -+ } -+ if (st->ss->store_super(st, fd, super)) { -+ close(fd); -+ fprintf(stderr, Name ": Could not re-write superblock on %s\n", -+ devices[chosen_drive].devname); -+ return 1; -+ } -+ close(fd); -+ } -+ -+ /* count number of in-sync devices according to the superblock. -+ * We must have this number to start the array without -s or -R -+ */ -+ req_cnt = info.array.working_disks; -+ -+ /* Almost ready to actually *do* something */ -+ if (!old_linux) { -+ int rv; -+ if ((vers % 100) >= 1) { /* can use different versions */ -+ mdu_array_info_t inf; -+ memset(&inf, 0, sizeof(inf)); -+ inf.major_version = st->ss->major; -+ inf.minor_version = st->minor_version; -+ rv = ioctl(mdfd, SET_ARRAY_INFO, &inf); -+ } else -+ rv = ioctl(mdfd, SET_ARRAY_INFO, NULL); -+ -+ if (rv) { -+ fprintf(stderr, Name ": SET_ARRAY_INFO failed for %s: %s\n", -+ mddev, strerror(errno)); -+ return 1; -+ } -+ if (ident->bitmap_fd >= 0) { -+ if (ioctl(mdfd, SET_BITMAP_FILE, ident->bitmap_fd) != 0) { -+ fprintf(stderr, Name ": SET_BITMAP_FILE failed.\n"); -+ return 1; -+ } -+ } else if (ident->bitmap_file) { -+ /* From config file */ -+ int bmfd = open(ident->bitmap_file, O_RDWR); -+ if (bmfd < 0) { -+ fprintf(stderr, Name ": Could not open bitmap file %s\n", -+ ident->bitmap_file); -+ return 1; -+ } -+ if (ioctl(mdfd, SET_BITMAP_FILE, bmfd) != 0) { -+ fprintf(stderr, Name ": Failed to set bitmapfile for %s\n", mddev); -+ close(bmfd); -+ return 1; -+ } -+ close(bmfd); -+ } -+ -+ /* First, add the raid disks, but add the chosen one last */ -+ for (i=0; i<= bestcnt; i++) { -+ int j; -+ if (i < bestcnt) { -+ j = best[i]; -+ if (j == chosen_drive) -+ continue; -+ } else -+ j = chosen_drive; -+ -+ if (j >= 0 /* && devices[j].uptodate */) { -+ mdu_disk_info_t disk; -+ memset(&disk, 0, sizeof(disk)); -+ disk.major = devices[j].major; -+ disk.minor = devices[j].minor; -+ if (ioctl(mdfd, ADD_NEW_DISK, &disk)!=0) { -+ fprintf(stderr, Name ": failed to add %s to %s: %s\n", -+ devices[j].devname, -+ mddev, -+ strerror(errno)); -+ if (i < info.array.raid_disks || i == bestcnt) -+ okcnt--; -+ else -+ sparecnt--; -+ } else if (verbose > 0) -+ fprintf(stderr, Name ": added %s to %s as %d\n", -+ devices[j].devname, mddev, devices[j].raid_disk); -+ } else if (verbose > 0 && i < info.array.raid_disks) -+ fprintf(stderr, Name ": no uptodate device for slot %d of %s\n", -+ i, mddev); -+ } -+ -+ if (runstop == 1 || -+ (runstop <= 0 && -+ ( enough(info.array.level, info.array.raid_disks, -+ info.array.layout, clean, avail, okcnt) && -+ (okcnt >= req_cnt || start_partial_ok) -+ ))) { -+ if (ioctl(mdfd, RUN_ARRAY, NULL)==0) { -+ if (verbose >= 0) { -+ fprintf(stderr, Name ": %s has been started with %d drive%s", -+ mddev, okcnt, okcnt==1?"":"s"); -+ if (okcnt < info.array.raid_disks) -+ fprintf(stderr, " (out of %d)", info.array.raid_disks); -+ if (sparecnt) -+ fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s"); -+ fprintf(stderr, ".\n"); -+ } -+ return 0; -+ } -+ fprintf(stderr, Name ": failed to RUN_ARRAY %s: %s\n", -+ mddev, strerror(errno)); -+ -+ if (!enough(info.array.level, info.array.raid_disks, -+ info.array.layout, 1, avail, okcnt)) -+ fprintf(stderr, Name ": Not enough devices to " -+ "start the array.\n"); -+ else if (!enough(info.array.level, -+ info.array.raid_disks, -+ info.array.layout, clean, -+ avail, okcnt)) -+ fprintf(stderr, Name ": Not enough devices to " -+ "start the array while not clean " -+ "- consider --force.\n"); -+ -+ return 1; -+ } -+ if (runstop == -1) { -+ fprintf(stderr, Name ": %s assembled from %d drive%s", -+ mddev, okcnt, okcnt==1?"":"s"); -+ if (okcnt != info.array.raid_disks) -+ fprintf(stderr, " (out of %d)", info.array.raid_disks); -+ fprintf(stderr, ", but not started.\n"); -+ return 0; -+ } -+ if (verbose >= -1) { -+ fprintf(stderr, Name ": %s assembled from %d drive%s", mddev, okcnt, okcnt==1?"":"s"); -+ if (sparecnt) -+ fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s"); -+ if (!enough(info.array.level, info.array.raid_disks, -+ info.array.layout, 1, avail, okcnt)) -+ fprintf(stderr, " - not enough to start the array.\n"); -+ else if (!enough(info.array.level, -+ info.array.raid_disks, -+ info.array.layout, clean, -+ avail, okcnt)) -+ fprintf(stderr, " - not enough to start the " -+ "array while not clean - consider " -+ "--force.\n"); -+ else { -+ if (req_cnt == info.array.raid_disks) -+ fprintf(stderr, " - need all %d to start it", req_cnt); -+ else -+ fprintf(stderr, " - need %d of %d to start", req_cnt, info.array.raid_disks); -+ fprintf(stderr, " (use --run to insist).\n"); -+ } -+ } -+ return 1; -+ } else { -+ /* The "chosen_drive" is a good choice, and if necessary, the superblock has -+ * been updated to point to the current locations of devices. -+ * so we can just start the array -+ */ -+ unsigned long dev; -+ dev = makedev(devices[chosen_drive].major, -+ devices[chosen_drive].minor); -+ if (ioctl(mdfd, START_ARRAY, dev)) { -+ fprintf(stderr, Name ": Cannot start array: %s\n", -+ strerror(errno)); -+ } -+ -+ } -+ return 0; -+} -+ -+int mdfd = -1; -+int runstop = 0; -+int readonly = 0; -+int verbose = 0; -+int force = 0; -+ -+int mdassemble_main(int argc, char **argv) { -+ mddev_ident_t array_list = conf_get_ident(NULL); -+ int minor; -+ if (!array_list) { -+ fprintf(stderr, Name ": No arrays found in config file\n"); -+ return 1; -+ } else { -+ for (; array_list; array_list = array_list->next) { -+ mdu_array_info_t array; -+ if (!strncmp("/dev/md", array_list->devname, 7)) { -+ errno = 0; -+ minor = strtoul(array_list->devname + 7, NULL, 0); -+ if (!errno) { -+ mknod(array_list->devname, S_IFBLK|0600, makedev(MD_MAJOR, minor)); -+ } -+ } -+ mdfd = open_mddev(array_list->devname, array_list->autof); -+ if (mdfd < 0) { -+ -+ fprintf(stderr, Name ": failed to open array\n"); -+ continue; -+ } -+ if (ioctl(mdfd, GET_ARRAY_INFO, &array) < 0) { -+ Assemble(array_list->st, array_list->devname, mdfd, -+ array_list, NULL, NULL, -+ readonly, runstop, NULL, NULL, verbose, force); -+ } -+ close(mdfd); -+ } -+ } -+ return 0; -+} -+ -diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/mdexamine.c busybox-1.7.4+gentoo+mdadm/mdadm/mdexamine.c ---- busybox-1.7.4+gentoo/mdadm/mdexamine.c 1969-12-31 16:00:00.000000000 -0800 -+++ busybox-1.7.4+gentoo+mdadm/mdadm/mdexamine.c 2008-03-11 10:31:00.000000000 -0700 -@@ -0,0 +1,157 @@ -+/* -+ * mdadm - manage Linux "md" devices aka RAID arrays. -+ * -+ * Copyright (C) 2001-2006 Neil Brown -+ * -+ * -+ * 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 -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Author: Neil Brown -+ * Email: -+ * Paper: Neil Brown -+ * School of Computer Science and Engineering -+ * The University of New South Wales -+ * Sydney, 2052 -+ * Australia -+ */ -+ -+#include "mdadm.h" -+#include "dlink.h" -+ -+#if ! defined(__BIG_ENDIAN) && ! defined(__LITTLE_ENDIAN) -+#error no endian defined -+#endif -+#include "md_u.h" -+#include "md_p.h" -+ -+static int Examine(mddev_dev_t devlist, int brief, int scan, -+ int SparcAdjust, struct supertype *forcest, -+ char *homehost) -+{ -+ -+ /* Read the raid superblock from a device and -+ * display important content. -+ * -+ * If cannot be found, print reason: too small, bad magic -+ * -+ * Print: -+ * version, ctime, level, size, raid+spare+ -+ * prefered minor -+ * uuid -+ * -+ * utime, state etc -+ * -+ * If (brief) gather devices for same array and just print a mdadm.conf line including devices= -+ * if devlist==NULL, use conf_get_devs() -+ */ -+ int fd; -+ void *super = NULL; -+ int rv = 0; -+ int err = 0; -+ -+ struct array { -+ void *super; -+ struct supertype *st; -+ struct mdinfo info; -+ void *devs; -+ struct array *next; -+ int spares; -+ } *arrays = NULL; -+ -+ for (; devlist ; devlist=devlist->next) { -+ struct supertype *st = forcest; -+ -+ fd = dev_open(devlist->devname, O_RDONLY); -+ if (fd < 0) { -+ if (!scan) { -+ fprintf(stderr,Name ": cannot open %s: %s\n", -+ devlist->devname, strerror(errno)); -+ rv = 1; -+ } -+ err = 1; -+ } -+ else { -+ if (!st) -+ st = guess_super(fd); -+ if (st) -+ err = st->ss->load_super(st, fd, &super, (brief||scan)?NULL:devlist->devname); -+ else { -+ if (!brief) { -+ fprintf(stderr, Name ": No md superblock detected on %s.\n", devlist->devname); -+ rv = 1; -+ } -+ err = 1; -+ } -+ close(fd); -+ } -+ if (err) -+ continue; -+ -+ if (SparcAdjust) -+ st->ss->update_super(NULL, super, "sparc2.2", devlist->devname, 0, 0, NULL); -+ /* Ok, its good enough to try, though the checksum could be wrong */ -+ if (brief) { -+ struct array *ap; -+ char *d; -+ for (ap=arrays; ap; ap=ap->next) { -+ if (st->ss == ap->st->ss && st->ss->compare_super(&ap->super, super)==0) -+ break; -+ } -+ if (!ap) { -+ ap = malloc(sizeof(*ap)); -+ ap->super = super; -+ ap->devs = dl_head(); -+ ap->next = arrays; -+ ap->spares = 0; -+ ap->st = st; -+ arrays = ap; -+ st->ss->getinfo_super(&ap->info, super); -+ } else { -+ st->ss->getinfo_super(&ap->info, super); -+ free(super); -+ } -+ if (!(ap->info.disk.state & MD_DISK_SYNC)) -+ ap->spares++; -+ d = dl_strdup(devlist->devname); -+ dl_add(ap->devs, d); -+ } -+ } -+ if (brief) { -+ struct array *ap; -+ for (ap=arrays; ap; ap=ap->next) { -+ char sep='='; -+ char *d; -+ ap->st->ss->brief_examine_super(ap->super); -+ if (ap->spares) printf(" spares=%d", ap->spares); -+ if (brief > 1) { -+ printf(" devices"); -+ for (d=dl_next(ap->devs); d!= ap->devs; d=dl_next(d)) { -+ printf("%c%s", sep, d); -+ sep=','; -+ } -+ } -+ free(ap->super); -+ /* FIXME free ap */ -+ if (ap->spares || brief > 1) -+ printf("\n"); -+ } -+ } -+ return rv; -+} -+ -+int mdexamine_main(int argc, char **argv) { -+ return Examine(conf_get_devs(), 1, 0, 0, NULL, NULL); -+} -+ -diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/md_p.h busybox-1.7.4+gentoo+mdadm/mdadm/md_p.h ---- busybox-1.7.4+gentoo/mdadm/md_p.h 1969-12-31 16:00:00.000000000 -0800 -+++ busybox-1.7.4+gentoo+mdadm/mdadm/md_p.h 2008-03-11 10:31:00.000000000 -0700 -@@ -0,0 +1,194 @@ -+/* -+ md_p.h : physical layout of Linux RAID devices -+ Copyright (C) 1996-98 Ingo Molnar, Gadi Oxman -+ -+ 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 -+ the Free Software Foundation; either version 2, or (at your option) -+ any later version. -+ -+ You should have received a copy of the GNU General Public License -+ (for example /usr/src/linux/COPYING); if not, write to the Free -+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+*/ -+ -+#ifndef _MD_P_H -+#define _MD_P_H -+ -+/* -+ * RAID superblock. -+ * -+ * The RAID superblock maintains some statistics on each RAID configuration. -+ * Each real device in the RAID set contains it near the end of the device. -+ * Some of the ideas are copied from the ext2fs implementation. -+ * -+ * We currently use 4096 bytes as follows: -+ * -+ * word offset function -+ * -+ * 0 - 31 Constant generic RAID device information. -+ * 32 - 63 Generic state information. -+ * 64 - 127 Personality specific information. -+ * 128 - 511 12 32-words descriptors of the disks in the raid set. -+ * 512 - 911 Reserved. -+ * 912 - 1023 Disk specific descriptor. -+ */ -+ -+/* -+ * If x is the real device size in bytes, we return an apparent size of: -+ * -+ * y = (x & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES -+ * -+ * and place the 4kB superblock at offset y. -+ */ -+#define MD_RESERVED_BYTES (64 * 1024) -+#define MD_RESERVED_SECTORS (MD_RESERVED_BYTES / 512) -+#define MD_RESERVED_BLOCKS (MD_RESERVED_BYTES / BLOCK_SIZE) -+ -+#define MD_NEW_SIZE_SECTORS(x) ((x & ~(MD_RESERVED_SECTORS - 1)) - MD_RESERVED_SECTORS) -+#define MD_NEW_SIZE_BLOCKS(x) ((x & ~(MD_RESERVED_BLOCKS - 1)) - MD_RESERVED_BLOCKS) -+ -+#define MD_SB_BYTES 4096 -+#define MD_SB_WORDS (MD_SB_BYTES / 4) -+#define MD_SB_BLOCKS (MD_SB_BYTES / BLOCK_SIZE) -+#define MD_SB_SECTORS (MD_SB_BYTES / 512) -+ -+/* -+ * The following are counted in 32-bit words -+ */ -+#define MD_SB_GENERIC_OFFSET 0 -+#define MD_SB_PERSONALITY_OFFSET 64 -+#define MD_SB_DISKS_OFFSET 128 -+#define MD_SB_DESCRIPTOR_OFFSET 992 -+ -+#define MD_SB_GENERIC_CONSTANT_WORDS 32 -+#define MD_SB_GENERIC_STATE_WORDS 32 -+#define MD_SB_GENERIC_WORDS (MD_SB_GENERIC_CONSTANT_WORDS + MD_SB_GENERIC_STATE_WORDS) -+#define MD_SB_PERSONALITY_WORDS 64 -+#define MD_SB_DESCRIPTOR_WORDS 32 -+#define MD_SB_DISKS 27 -+#define MD_SB_DISKS_WORDS (MD_SB_DISKS*MD_SB_DESCRIPTOR_WORDS) -+#define MD_SB_RESERVED_WORDS (1024 - MD_SB_GENERIC_WORDS - MD_SB_PERSONALITY_WORDS - MD_SB_DISKS_WORDS - MD_SB_DESCRIPTOR_WORDS) -+#define MD_SB_EQUAL_WORDS (MD_SB_GENERIC_WORDS + MD_SB_PERSONALITY_WORDS + MD_SB_DISKS_WORDS) -+ -+/* -+ * Device "operational" state bits -+ */ -+#define MD_DISK_FAULTY 0 /* disk is faulty / operational */ -+#define MD_DISK_ACTIVE 1 /* disk is running or spare disk */ -+#define MD_DISK_SYNC 2 /* disk is in sync with the raid set */ -+#define MD_DISK_REMOVED 3 /* disk is in sync with the raid set */ -+ -+#define MD_DISK_WRITEMOSTLY 9 /* disk is "write-mostly" is RAID1 config. -+ * read requests will only be sent here in -+ * dire need -+ */ -+ -+typedef struct mdp_device_descriptor_s { -+ __u32 number; /* 0 Device number in the entire set */ -+ __u32 major; /* 1 Device major number */ -+ __u32 minor; /* 2 Device minor number */ -+ __u32 raid_disk; /* 3 The role of the device in the raid set */ -+ __u32 state; /* 4 Operational state */ -+ __u32 reserved[MD_SB_DESCRIPTOR_WORDS - 5]; -+} mdp_disk_t; -+ -+#define MD_SB_MAGIC 0xa92b4efc -+ -+/* -+ * Superblock state bits -+ */ -+#define MD_SB_CLEAN 0 -+#define MD_SB_ERRORS 1 -+ -+#define MD_SB_BITMAP_PRESENT 8 /* bitmap may be present nearby */ -+ -+typedef struct mdp_superblock_s { -+ /* -+ * Constant generic information -+ */ -+ __u32 md_magic; /* 0 MD identifier */ -+ __u32 major_version; /* 1 major version to which the set conforms */ -+ __u32 minor_version; /* 2 minor version ... */ -+ __u32 patch_version; /* 3 patchlevel version ... */ -+ __u32 gvalid_words; /* 4 Number of used words in this section */ -+ __u32 set_uuid0; /* 5 Raid set identifier */ -+ __u32 ctime; /* 6 Creation time */ -+ __u32 level; /* 7 Raid personality */ -+ __u32 size; /* 8 Apparent size of each individual disk */ -+ __u32 nr_disks; /* 9 total disks in the raid set */ -+ __u32 raid_disks; /* 10 disks in a fully functional raid set */ -+ __u32 md_minor; /* 11 preferred MD minor device number */ -+ __u32 not_persistent; /* 12 does it have a persistent superblock */ -+ __u32 set_uuid1; /* 13 Raid set identifier #2 */ -+ __u32 set_uuid2; /* 14 Raid set identifier #3 */ -+ __u32 set_uuid3; /* 15 Raid set identifier #4 */ -+ __u32 gstate_creserved[MD_SB_GENERIC_CONSTANT_WORDS - 16]; -+ -+ /* -+ * Generic state information -+ */ -+ __u32 utime; /* 0 Superblock update time */ -+ __u32 state; /* 1 State bits (clean, ...) */ -+ __u32 active_disks; /* 2 Number of currently active disks */ -+ __u32 working_disks; /* 3 Number of working disks */ -+ __u32 failed_disks; /* 4 Number of failed disks */ -+ __u32 spare_disks; /* 5 Number of spare disks */ -+ __u32 sb_csum; /* 6 checksum of the whole superblock */ -+#if __BYTE_ORDER == __BIG_ENDIAN -+ __u32 events_hi; /* 7 high-order of superblock update count */ -+ __u32 events_lo; /* 8 low-order of superblock update count */ -+ __u32 cp_events_hi; /* 9 high-order of checkpoint update count */ -+ __u32 cp_events_lo; /* 10 low-order of checkpoint update count */ -+#else -+ __u32 events_lo; /* 7 low-order of superblock update count */ -+ __u32 events_hi; /* 8 high-order of superblock update count */ -+ __u32 cp_events_lo; /* 9 low-order of checkpoint update count */ -+ __u32 cp_events_hi; /* 10 high-order of checkpoint update count */ -+#endif -+ __u32 recovery_cp; /* 11 recovery checkpoint sector count */ -+ /* There are only valid for minor_version > 90 */ -+ __u64 reshape_position; /* 12,13 next address in array-space for reshape */ -+ __u32 new_level; /* 14 new level we are reshaping to */ -+ __u32 delta_disks; /* 15 change in number of raid_disks */ -+ __u32 new_layout; /* 16 new layout */ -+ __u32 new_chunk; /* 17 new chunk size (bytes) */ -+ __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 18]; -+ -+ /* -+ * Personality information -+ */ -+ __u32 layout; /* 0 the array's physical layout */ -+ __u32 chunk_size; /* 1 chunk size in bytes */ -+ __u32 root_pv; /* 2 LV root PV */ -+ __u32 root_block; /* 3 LV root block */ -+ __u32 pstate_reserved[MD_SB_PERSONALITY_WORDS - 4]; -+ -+ /* -+ * Disks information -+ */ -+ mdp_disk_t disks[MD_SB_DISKS]; -+ -+ /* -+ * Reserved -+ */ -+ __u32 reserved[MD_SB_RESERVED_WORDS]; -+ -+ /* -+ * Active descriptor -+ */ -+ mdp_disk_t this_disk; -+ -+} mdp_super_t; -+ -+#ifdef __TINYC__ -+typedef unsigned long long __u64; -+#endif -+ -+static inline __u64 md_event(mdp_super_t *sb) { -+ __u64 ev = sb->events_hi; -+ return (ev<<32)| sb->events_lo; -+} -+ -+#endif -+ -diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/md_u.h busybox-1.7.4+gentoo+mdadm/mdadm/md_u.h ---- busybox-1.7.4+gentoo/mdadm/md_u.h 1969-12-31 16:00:00.000000000 -0800 -+++ busybox-1.7.4+gentoo+mdadm/mdadm/md_u.h 2008-03-11 10:31:00.000000000 -0700 -@@ -0,0 +1,123 @@ -+/* -+ md_u.h : user <=> kernel API between Linux raidtools and RAID drivers -+ Copyright (C) 1998 Ingo Molnar -+ -+ 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 -+ the Free Software Foundation; either version 2, or (at your option) -+ any later version. -+ -+ You should have received a copy of the GNU General Public License -+ (for example /usr/src/linux/COPYING); if not, write to the Free -+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+*/ -+ -+#ifndef _MD_U_H -+#define _MD_U_H -+ -+/* ioctls */ -+ -+/* status */ -+#define RAID_VERSION _IOR (MD_MAJOR, 0x10, mdu_version_t) -+#define GET_ARRAY_INFO _IOR (MD_MAJOR, 0x11, mdu_array_info_t) -+#define GET_DISK_INFO _IOR (MD_MAJOR, 0x12, mdu_disk_info_t) -+#define PRINT_RAID_DEBUG _IO (MD_MAJOR, 0x13) -+#define RAID_AUTORUN _IO (MD_MAJOR, 0x14) -+#define GET_BITMAP_FILE _IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t) -+ -+/* configuration */ -+#define CLEAR_ARRAY _IO (MD_MAJOR, 0x20) -+#define ADD_NEW_DISK _IOW (MD_MAJOR, 0x21, mdu_disk_info_t) -+#define HOT_REMOVE_DISK _IO (MD_MAJOR, 0x22) -+#define SET_ARRAY_INFO _IOW (MD_MAJOR, 0x23, mdu_array_info_t) -+#define SET_DISK_INFO _IO (MD_MAJOR, 0x24) -+#define WRITE_RAID_INFO _IO (MD_MAJOR, 0x25) -+#define UNPROTECT_ARRAY _IO (MD_MAJOR, 0x26) -+#define PROTECT_ARRAY _IO (MD_MAJOR, 0x27) -+#define HOT_ADD_DISK _IO (MD_MAJOR, 0x28) -+#define SET_DISK_FAULTY _IO (MD_MAJOR, 0x29) -+#define SET_BITMAP_FILE _IOW (MD_MAJOR, 0x2b, int) -+ -+/* usage */ -+#define RUN_ARRAY _IOW (MD_MAJOR, 0x30, mdu_param_t) -+#define START_ARRAY _IO (MD_MAJOR, 0x31) -+#define STOP_ARRAY _IO (MD_MAJOR, 0x32) -+#define STOP_ARRAY_RO _IO (MD_MAJOR, 0x33) -+#define RESTART_ARRAY_RW _IO (MD_MAJOR, 0x34) -+ -+typedef struct mdu_version_s { -+ int major; -+ int minor; -+ int patchlevel; -+} mdu_version_t; -+ -+typedef struct mdu_array_info_s { -+ /* -+ * Generic constant information -+ */ -+ int major_version; -+ int minor_version; -+ int patch_version; -+ int ctime; -+ int level; -+ int size; -+ int nr_disks; -+ int raid_disks; -+ int md_minor; -+ int not_persistent; -+ -+ /* -+ * Generic state information -+ */ -+ int utime; /* 0 Superblock update time */ -+ int state; /* 1 State bits (clean, ...) */ -+ int active_disks; /* 2 Number of currently active disks */ -+ int working_disks; /* 3 Number of working disks */ -+ int failed_disks; /* 4 Number of failed disks */ -+ int spare_disks; /* 5 Number of spare disks */ -+ -+ /* -+ * Personality information -+ */ -+ int layout; /* 0 the array's physical layout */ -+ int chunk_size; /* 1 chunk size in bytes */ -+ -+} mdu_array_info_t; -+ -+typedef struct mdu_disk_info_s { -+ /* -+ * configuration/status of one particular disk -+ */ -+ int number; -+ int major; -+ int minor; -+ int raid_disk; -+ int state; -+ -+} mdu_disk_info_t; -+ -+typedef struct mdu_start_info_s { -+ /* -+ * configuration/status of one particular disk -+ */ -+ int major; -+ int minor; -+ int raid_disk; -+ int state; -+ -+} mdu_start_info_t; -+ -+typedef struct mdu_bitmap_file_s -+{ -+ char pathname[4096]; -+} mdu_bitmap_file_t; -+ -+typedef struct mdu_param_s -+{ -+ int personality; /* 1,2,3,4 */ -+ int chunk_size; /* in bytes */ -+ int max_fault; /* unused for now */ -+} mdu_param_t; -+ -+#endif -+ -diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/sha1.c busybox-1.7.4+gentoo+mdadm/mdadm/sha1.c ---- busybox-1.7.4+gentoo/mdadm/sha1.c 1969-12-31 16:00:00.000000000 -0800 -+++ busybox-1.7.4+gentoo+mdadm/mdadm/sha1.c 2008-03-11 10:31:00.000000000 -0700 -@@ -0,0 +1,423 @@ -+/* sha1.c - Functions to compute SHA1 message digest of files or -+ memory blocks according to the NIST specification FIPS-180-1. -+ -+ Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc. -+ -+ 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 the -+ Free Software Foundation; either version 2, or (at your option) any -+ later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software Foundation, -+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -+ -+/* Written by Scott G. Miller -+ Credits: -+ Robert Klep -- Expansion function fix -+*/ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include "sha1.h" -+ -+#include -+#include -+ -+#if USE_UNLOCKED_IO -+# include "unlocked-io.h" -+#endif -+ -+/* SWAP does an endian swap on architectures that are little-endian, -+ as SHA1 needs some data in a big-endian form. */ -+ -+#ifdef WORDS_BIGENDIAN -+# define SWAP(n) (n) -+#else -+# define SWAP(n) \ -+ (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) -+#endif -+ -+#define BLOCKSIZE 4096 -+#if BLOCKSIZE % 64 != 0 -+# error "invalid BLOCKSIZE" -+#endif -+ -+/* This array contains the bytes used to pad the buffer to the next -+ 64-byte boundary. (RFC 1321, 3.1: Step 1) */ -+static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; -+ -+ -+/* -+ Takes a pointer to a 160 bit block of data (five 32 bit ints) and -+ intializes it to the start constants of the SHA1 algorithm. This -+ must be called before using hash in the call to sha1_hash. -+*/ -+void -+sha1_init_ctx (struct sha1_ctx *ctx) -+{ -+ ctx->A = 0x67452301; -+ ctx->B = 0xefcdab89; -+ ctx->C = 0x98badcfe; -+ ctx->D = 0x10325476; -+ ctx->E = 0xc3d2e1f0; -+ -+ ctx->total[0] = ctx->total[1] = 0; -+ ctx->buflen = 0; -+} -+ -+/* Put result from CTX in first 20 bytes following RESBUF. The result -+ must be in little endian byte order. -+ -+ IMPORTANT: On some systems it is required that RESBUF is correctly -+ aligned for a 32 bits value. */ -+void * -+sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf) -+{ -+ ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A); -+ ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B); -+ ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C); -+ ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D); -+ ((md5_uint32 *) resbuf)[4] = SWAP (ctx->E); -+ -+ return resbuf; -+} -+ -+/* Process the remaining bytes in the internal buffer and the usual -+ prolog according to the standard and write the result to RESBUF. -+ -+ IMPORTANT: On some systems it is required that RESBUF is correctly -+ aligned for a 32 bits value. */ -+void * -+sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf) -+{ -+ /* Take yet unprocessed bytes into account. */ -+ md5_uint32 bytes = ctx->buflen; -+ size_t pad; -+ -+ /* Now count remaining bytes. */ -+ ctx->total[0] += bytes; -+ if (ctx->total[0] < bytes) -+ ++ctx->total[1]; -+ -+ pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; -+ memcpy (&ctx->buffer[bytes], fillbuf, pad); -+ -+ /* Put the 64-bit file length in *bits* at the end of the buffer. */ -+ *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP (ctx->total[0] << 3); -+ *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP ((ctx->total[1] << 3) | -+ (ctx->total[0] >> 29)); -+ -+ /* Process last bytes. */ -+ sha1_process_block (ctx->buffer, bytes + pad + 8, ctx); -+ -+ return sha1_read_ctx (ctx, resbuf); -+} -+ -+/* Compute SHA1 message digest for bytes read from STREAM. The -+ resulting message digest number will be written into the 16 bytes -+ beginning at RESBLOCK. */ -+int -+sha1_stream (FILE *stream, void *resblock) -+{ -+ struct sha1_ctx ctx; -+ char buffer[BLOCKSIZE + 72]; -+ size_t sum; -+ -+ /* Initialize the computation context. */ -+ sha1_init_ctx (&ctx); -+ -+ /* Iterate over full file contents. */ -+ while (1) -+ { -+ /* We read the file in blocks of BLOCKSIZE bytes. One call of the -+ computation function processes the whole buffer so that with the -+ next round of the loop another block can be read. */ -+ size_t n; -+ sum = 0; -+ -+ /* Read block. Take care for partial reads. */ -+ while (1) -+ { -+ n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); -+ -+ sum += n; -+ -+ if (sum == BLOCKSIZE) -+ break; -+ -+ if (n == 0) -+ { -+ /* Check for the error flag IFF N == 0, so that we don't -+ exit the loop after a partial read due to e.g., EAGAIN -+ or EWOULDBLOCK. */ -+ if (ferror (stream)) -+ return 1; -+ goto process_partial_block; -+ } -+ -+ /* We've read at least one byte, so ignore errors. But always -+ check for EOF, since feof may be true even though N > 0. -+ Otherwise, we could end up calling fread after EOF. */ -+ if (feof (stream)) -+ goto process_partial_block; -+ } -+ -+ /* Process buffer with BLOCKSIZE bytes. Note that -+ BLOCKSIZE % 64 == 0 -+ */ -+ sha1_process_block (buffer, BLOCKSIZE, &ctx); -+ } -+ -+ process_partial_block:; -+ -+ /* Process any remaining bytes. */ -+ if (sum > 0) -+ sha1_process_bytes (buffer, sum, &ctx); -+ -+ /* Construct result in desired memory. */ -+ sha1_finish_ctx (&ctx, resblock); -+ return 0; -+} -+ -+/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The -+ result is always in little endian byte order, so that a byte-wise -+ output yields to the wanted ASCII representation of the message -+ digest. */ -+void * -+sha1_buffer (const char *buffer, size_t len, void *resblock) -+{ -+ struct sha1_ctx ctx; -+ -+ /* Initialize the computation context. */ -+ sha1_init_ctx (&ctx); -+ -+ /* Process whole buffer but last len % 64 bytes. */ -+ sha1_process_bytes (buffer, len, &ctx); -+ -+ /* Put result in desired memory area. */ -+ return sha1_finish_ctx (&ctx, resblock); -+} -+ -+void -+sha1_process_bytes (const void *buffer, size_t len, struct sha1_ctx *ctx) -+{ -+ /* When we already have some bits in our internal buffer concatenate -+ both inputs first. */ -+ if (ctx->buflen != 0) -+ { -+ size_t left_over = ctx->buflen; -+ size_t add = 128 - left_over > len ? len : 128 - left_over; -+ -+ memcpy (&ctx->buffer[left_over], buffer, add); -+ ctx->buflen += add; -+ -+ if (ctx->buflen > 64) -+ { -+ sha1_process_block (ctx->buffer, ctx->buflen & ~63, ctx); -+ -+ ctx->buflen &= 63; -+ /* The regions in the following copy operation cannot overlap. */ -+ memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], -+ ctx->buflen); -+ } -+ -+ buffer = (const char *) buffer + add; -+ len -= add; -+ } -+ -+ /* Process available complete blocks. */ -+ if (len >= 64) -+ { -+#if !_STRING_ARCH_unaligned -+# define alignof(type) offsetof (struct { char c; type x; }, x) -+# define UNALIGNED_P(p) (((size_t) p) % alignof (md5_uint32) != 0) -+ if (UNALIGNED_P (buffer)) -+ while (len > 64) -+ { -+ sha1_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); -+ buffer = (const char *) buffer + 64; -+ len -= 64; -+ } -+ else -+#endif -+ { -+ sha1_process_block (buffer, len & ~63, ctx); -+ buffer = (const char *) buffer + (len & ~63); -+ len &= 63; -+ } -+ } -+ -+ /* Move remaining bytes in internal buffer. */ -+ if (len > 0) -+ { -+ size_t left_over = ctx->buflen; -+ -+ memcpy (&ctx->buffer[left_over], buffer, len); -+ left_over += len; -+ if (left_over >= 64) -+ { -+ sha1_process_block (ctx->buffer, 64, ctx); -+ left_over -= 64; -+ memcpy (ctx->buffer, &ctx->buffer[64], left_over); -+ } -+ ctx->buflen = left_over; -+ } -+} -+ -+/* --- Code below is the primary difference between md5.c and sha1.c --- */ -+ -+/* SHA1 round constants */ -+#define K1 0x5a827999L -+#define K2 0x6ed9eba1L -+#define K3 0x8f1bbcdcL -+#define K4 0xca62c1d6L -+ -+/* Round functions. Note that F2 is the same as F4. */ -+#define F1(B,C,D) ( D ^ ( B & ( C ^ D ) ) ) -+#define F2(B,C,D) (B ^ C ^ D) -+#define F3(B,C,D) ( ( B & C ) | ( D & ( B | C ) ) ) -+#define F4(B,C,D) (B ^ C ^ D) -+ -+/* Process LEN bytes of BUFFER, accumulating context into CTX. -+ It is assumed that LEN % 64 == 0. -+ Most of this code comes from GnuPG's cipher/sha1.c. */ -+ -+void -+sha1_process_block (const void *buffer, size_t len, struct sha1_ctx *ctx) -+{ -+ const md5_uint32 *words = buffer; -+ size_t nwords = len / sizeof (md5_uint32); -+ const md5_uint32 *endp = words + nwords; -+ md5_uint32 x[16]; -+ md5_uint32 a = ctx->A; -+ md5_uint32 b = ctx->B; -+ md5_uint32 c = ctx->C; -+ md5_uint32 d = ctx->D; -+ md5_uint32 e = ctx->E; -+ -+ /* First increment the byte count. RFC 1321 specifies the possible -+ length of the file up to 2^64 bits. Here we only compute the -+ number of bytes. Do a double word increment. */ -+ ctx->total[0] += len; -+ if (ctx->total[0] < len) -+ ++ctx->total[1]; -+ -+#define rol(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) -+ -+#define M(I) ( tm = x[I&0x0f] ^ x[(I-14)&0x0f] \ -+ ^ x[(I-8)&0x0f] ^ x[(I-3)&0x0f] \ -+ , (x[I&0x0f] = rol(tm, 1)) ) -+ -+#define R(A,B,C,D,E,F,K,M) do { E += rol( A, 5 ) \ -+ + F( B, C, D ) \ -+ + K \ -+ + M; \ -+ B = rol( B, 30 ); \ -+ } while(0) -+ -+ while (words < endp) -+ { -+ md5_uint32 tm; -+ int t; -+ for (t = 0; t < 16; t++) -+ { -+ x[t] = SWAP (*words); -+ words++; -+ } -+ -+ R( a, b, c, d, e, F1, K1, x[ 0] ); -+ R( e, a, b, c, d, F1, K1, x[ 1] ); -+ R( d, e, a, b, c, F1, K1, x[ 2] ); -+ R( c, d, e, a, b, F1, K1, x[ 3] ); -+ R( b, c, d, e, a, F1, K1, x[ 4] ); -+ R( a, b, c, d, e, F1, K1, x[ 5] ); -+ R( e, a, b, c, d, F1, K1, x[ 6] ); -+ R( d, e, a, b, c, F1, K1, x[ 7] ); -+ R( c, d, e, a, b, F1, K1, x[ 8] ); -+ R( b, c, d, e, a, F1, K1, x[ 9] ); -+ R( a, b, c, d, e, F1, K1, x[10] ); -+ R( e, a, b, c, d, F1, K1, x[11] ); -+ R( d, e, a, b, c, F1, K1, x[12] ); -+ R( c, d, e, a, b, F1, K1, x[13] ); -+ R( b, c, d, e, a, F1, K1, x[14] ); -+ R( a, b, c, d, e, F1, K1, x[15] ); -+ R( e, a, b, c, d, F1, K1, M(16) ); -+ R( d, e, a, b, c, F1, K1, M(17) ); -+ R( c, d, e, a, b, F1, K1, M(18) ); -+ R( b, c, d, e, a, F1, K1, M(19) ); -+ R( a, b, c, d, e, F2, K2, M(20) ); -+ R( e, a, b, c, d, F2, K2, M(21) ); -+ R( d, e, a, b, c, F2, K2, M(22) ); -+ R( c, d, e, a, b, F2, K2, M(23) ); -+ R( b, c, d, e, a, F2, K2, M(24) ); -+ R( a, b, c, d, e, F2, K2, M(25) ); -+ R( e, a, b, c, d, F2, K2, M(26) ); -+ R( d, e, a, b, c, F2, K2, M(27) ); -+ R( c, d, e, a, b, F2, K2, M(28) ); -+ R( b, c, d, e, a, F2, K2, M(29) ); -+ R( a, b, c, d, e, F2, K2, M(30) ); -+ R( e, a, b, c, d, F2, K2, M(31) ); -+ R( d, e, a, b, c, F2, K2, M(32) ); -+ R( c, d, e, a, b, F2, K2, M(33) ); -+ R( b, c, d, e, a, F2, K2, M(34) ); -+ R( a, b, c, d, e, F2, K2, M(35) ); -+ R( e, a, b, c, d, F2, K2, M(36) ); -+ R( d, e, a, b, c, F2, K2, M(37) ); -+ R( c, d, e, a, b, F2, K2, M(38) ); -+ R( b, c, d, e, a, F2, K2, M(39) ); -+ R( a, b, c, d, e, F3, K3, M(40) ); -+ R( e, a, b, c, d, F3, K3, M(41) ); -+ R( d, e, a, b, c, F3, K3, M(42) ); -+ R( c, d, e, a, b, F3, K3, M(43) ); -+ R( b, c, d, e, a, F3, K3, M(44) ); -+ R( a, b, c, d, e, F3, K3, M(45) ); -+ R( e, a, b, c, d, F3, K3, M(46) ); -+ R( d, e, a, b, c, F3, K3, M(47) ); -+ R( c, d, e, a, b, F3, K3, M(48) ); -+ R( b, c, d, e, a, F3, K3, M(49) ); -+ R( a, b, c, d, e, F3, K3, M(50) ); -+ R( e, a, b, c, d, F3, K3, M(51) ); -+ R( d, e, a, b, c, F3, K3, M(52) ); -+ R( c, d, e, a, b, F3, K3, M(53) ); -+ R( b, c, d, e, a, F3, K3, M(54) ); -+ R( a, b, c, d, e, F3, K3, M(55) ); -+ R( e, a, b, c, d, F3, K3, M(56) ); -+ R( d, e, a, b, c, F3, K3, M(57) ); -+ R( c, d, e, a, b, F3, K3, M(58) ); -+ R( b, c, d, e, a, F3, K3, M(59) ); -+ R( a, b, c, d, e, F4, K4, M(60) ); -+ R( e, a, b, c, d, F4, K4, M(61) ); -+ R( d, e, a, b, c, F4, K4, M(62) ); -+ R( c, d, e, a, b, F4, K4, M(63) ); -+ R( b, c, d, e, a, F4, K4, M(64) ); -+ R( a, b, c, d, e, F4, K4, M(65) ); -+ R( e, a, b, c, d, F4, K4, M(66) ); -+ R( d, e, a, b, c, F4, K4, M(67) ); -+ R( c, d, e, a, b, F4, K4, M(68) ); -+ R( b, c, d, e, a, F4, K4, M(69) ); -+ R( a, b, c, d, e, F4, K4, M(70) ); -+ R( e, a, b, c, d, F4, K4, M(71) ); -+ R( d, e, a, b, c, F4, K4, M(72) ); -+ R( c, d, e, a, b, F4, K4, M(73) ); -+ R( b, c, d, e, a, F4, K4, M(74) ); -+ R( a, b, c, d, e, F4, K4, M(75) ); -+ R( e, a, b, c, d, F4, K4, M(76) ); -+ R( d, e, a, b, c, F4, K4, M(77) ); -+ R( c, d, e, a, b, F4, K4, M(78) ); -+ R( b, c, d, e, a, F4, K4, M(79) ); -+ -+ a = ctx->A += a; -+ b = ctx->B += b; -+ c = ctx->C += c; -+ d = ctx->D += d; -+ e = ctx->E += e; -+ } -+} -diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/sha1.h busybox-1.7.4+gentoo+mdadm/mdadm/sha1.h ---- busybox-1.7.4+gentoo/mdadm/sha1.h 1969-12-31 16:00:00.000000000 -0800 -+++ busybox-1.7.4+gentoo+mdadm/mdadm/sha1.h 2008-03-11 10:31:00.000000000 -0700 -@@ -0,0 +1,87 @@ -+/* Declarations of functions and data types used for SHA1 sum -+ library functions. -+ Copyright (C) 2000, 2001, 2003, 2005 Free Software Foundation, Inc. -+ -+ 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 the -+ Free Software Foundation; either version 2, or (at your option) any -+ later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software Foundation, -+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -+ -+#ifndef SHA1_H -+# define SHA1_H 1 -+ -+# include -+# include "md5.h" -+ -+/* Structure to save state of computation between the single steps. */ -+struct sha1_ctx -+{ -+ md5_uint32 A; -+ md5_uint32 B; -+ md5_uint32 C; -+ md5_uint32 D; -+ md5_uint32 E; -+ -+ md5_uint32 total[2]; -+ md5_uint32 buflen; -+ char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32)))); -+}; -+ -+ -+/* Initialize structure containing state of computation. */ -+extern void sha1_init_ctx (struct sha1_ctx *ctx); -+ -+/* Starting with the result of former calls of this function (or the -+ initialization function update the context for the next LEN bytes -+ starting at BUFFER. -+ It is necessary that LEN is a multiple of 64!!! */ -+extern void sha1_process_block (const void *buffer, size_t len, -+ struct sha1_ctx *ctx); -+ -+/* Starting with the result of former calls of this function (or the -+ initialization function update the context for the next LEN bytes -+ starting at BUFFER. -+ It is NOT required that LEN is a multiple of 64. */ -+extern void sha1_process_bytes (const void *buffer, size_t len, -+ struct sha1_ctx *ctx); -+ -+/* Process the remaining bytes in the buffer and put result from CTX -+ in first 20 bytes following RESBUF. The result is always in little -+ endian byte order, so that a byte-wise output yields to the wanted -+ ASCII representation of the message digest. -+ -+ IMPORTANT: On some systems it is required that RESBUF be correctly -+ aligned for a 32 bits value. */ -+extern void *sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf); -+ -+ -+/* Put result from CTX in first 20 bytes following RESBUF. The result is -+ always in little endian byte order, so that a byte-wise output yields -+ to the wanted ASCII representation of the message digest. -+ -+ IMPORTANT: On some systems it is required that RESBUF is correctly -+ aligned for a 32 bits value. */ -+extern void *sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf); -+ -+ -+/* Compute SHA1 message digest for bytes read from STREAM. The -+ resulting message digest number will be written into the 20 bytes -+ beginning at RESBLOCK. */ -+extern int sha1_stream (FILE *stream, void *resblock); -+ -+/* Compute SHA1 message digest for LEN bytes beginning at BUFFER. The -+ result is always in little endian byte order, so that a byte-wise -+ output yields to the wanted ASCII representation of the message -+ digest. */ -+extern void *sha1_buffer (const char *buffer, size_t len, void *resblock); -+ -+#endif -diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/super0.c busybox-1.7.4+gentoo+mdadm/mdadm/super0.c ---- busybox-1.7.4+gentoo/mdadm/super0.c 1969-12-31 16:00:00.000000000 -0800 -+++ busybox-1.7.4+gentoo+mdadm/mdadm/super0.c 2008-03-11 10:31:00.000000000 -0700 -@@ -0,0 +1,562 @@ -+/* -+ * mdadm - manage Linux "md" devices aka RAID arrays. -+ * -+ * Copyright (C) 2001-2006 Neil Brown -+ * -+ * -+ * 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 -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Author: Neil Brown -+ * Email: -+ * Paper: Neil Brown -+ * School of Computer Science and Engineering -+ * The University of New South Wales -+ * Sydney, 2052 -+ * Australia -+ */ -+ -+#define HAVE_STDINT_H 1 -+#include "mdadm.h" -+/* -+ * All handling for the 0.90.0 version superblock is in -+ * this file. -+ * This includes: -+ * - finding, loading, and writing the superblock. -+ * - initialising a new superblock -+ * - printing the superblock for --examine -+ * - printing part of the superblock for --detail -+ * .. other stuff -+ */ -+ -+ -+static unsigned long calc_sb0_csum(mdp_super_t *super) -+{ -+ unsigned long csum = super->sb_csum; -+ unsigned long newcsum; -+ super->sb_csum= 0 ; -+ newcsum = calc_csum(super, MD_SB_BYTES); -+ super->sb_csum = csum; -+ return newcsum; -+} -+ -+ -+void super0_swap_endian(struct mdp_superblock_s *sb) -+{ -+ /* as super0 superblocks are host-endian, it is sometimes -+ * useful to be able to swap the endianness -+ * as (almost) everything is u32's we byte-swap every 4byte -+ * number. -+ * We then also have to swap the events_hi and events_lo -+ */ -+ char *sbc = (char *)sb; -+ __u32 t32; -+ int i; -+ -+ for (i=0; i < MD_SB_BYTES ; i+=4) { -+ char t = sbc[i]; -+ sbc[i] = sbc[i+3]; -+ sbc[i+3] = t; -+ t=sbc[i+1]; -+ sbc[i+1]=sbc[i+2]; -+ sbc[i+2]=t; -+ } -+ t32 = sb->events_hi; -+ sb->events_hi = sb->events_lo; -+ sb->events_lo = t32; -+ -+ t32 = sb->cp_events_hi; -+ sb->cp_events_hi = sb->cp_events_lo; -+ sb->cp_events_lo = t32; -+ -+} -+ -+static void brief_examine_super0(void *sbv) -+{ -+ mdp_super_t *sb = sbv; -+ char *c=map_num(pers, sb->level); -+ char devname[20]; -+ -+ sprintf(devname, "/dev/md%d", sb->md_minor); -+ -+ printf("ARRAY %s level=%s num-devices=%d UUID=", -+ devname, -+ c?c:"-unknown-", sb->raid_disks); -+ if (sb->minor_version >= 90) -+ printf("%08x:%08x:%08x:%08x", sb->set_uuid0, sb->set_uuid1, -+ sb->set_uuid2, sb->set_uuid3); -+ else -+ printf("%08x", sb->set_uuid0); -+ printf("\n"); -+} -+ -+static int match_home0(void *sbv, char *homehost) -+{ -+ mdp_super_t *sb = sbv; -+ char buf[20]; -+ char *hash = sha1_buffer(homehost, -+ strlen(homehost), -+ buf); -+ -+ return (memcmp(&sb->set_uuid2, hash, 8)==0); -+} -+ -+static void uuid_from_super0(int uuid[4], void * sbv) -+{ -+ mdp_super_t *super = sbv; -+ uuid[0] = super->set_uuid0; -+ if (super->minor_version >= 90) { -+ uuid[1] = super->set_uuid1; -+ uuid[2] = super->set_uuid2; -+ uuid[3] = super->set_uuid3; -+ } else { -+ uuid[1] = 0; -+ uuid[2] = 0; -+ uuid[3] = 0; -+ } -+} -+ -+static void getinfo_super0(struct mdinfo *info, void *sbv) -+{ -+ mdp_super_t *sb = sbv; -+ int working = 0; -+ int i; -+ -+ info->array.major_version = sb->major_version; -+ info->array.minor_version = sb->minor_version; -+ info->array.patch_version = sb->patch_version; -+ info->array.raid_disks = sb->raid_disks; -+ info->array.level = sb->level; -+ info->array.layout = sb->layout; -+ info->array.md_minor = sb->md_minor; -+ info->array.ctime = sb->ctime; -+ info->array.utime = sb->utime; -+ info->array.chunk_size = sb->chunk_size; -+ info->array.state = sb->state; -+ info->component_size = sb->size*2; -+ -+ info->disk.state = sb->this_disk.state; -+ info->disk.major = sb->this_disk.major; -+ info->disk.minor = sb->this_disk.minor; -+ info->disk.raid_disk = sb->this_disk.raid_disk; -+ info->disk.number = sb->this_disk.number; -+ -+ info->events = md_event(sb); -+ info->data_offset = 0; -+ -+ uuid_from_super0(info->uuid, sbv); -+ -+ if (sb->minor_version > 90 && (sb->reshape_position+1) != 0) { -+ info->reshape_active = 1; -+ info->reshape_progress = sb->reshape_position; -+ info->new_level = sb->new_level; -+ info->delta_disks = sb->delta_disks; -+ info->new_layout = sb->new_layout; -+ info->new_chunk = sb->new_chunk; -+ } else -+ info->reshape_active = 0; -+ -+ sprintf(info->name, "%d", sb->md_minor); -+ /* work_disks is calculated rather than read directly */ -+ for (i=0; i < MD_SB_DISKS; i++) -+ if ((sb->disks[i].state & (1<disks[i].raid_disk < info->array.raid_disks) && -+ (sb->disks[i].state & (1<disks[i].state & (1<array.working_disks = working; -+} -+ -+ -+static int update_super0(struct mdinfo *info, void *sbv, char *update, -+ char *devname, int verbose, -+ int uuid_set, char *homehost) -+{ -+ /* NOTE: for 'assemble' and 'force' we need to return non-zero if any change was made. -+ * For others, the return value is ignored. -+ */ -+ int rv = 0; -+ mdp_super_t *sb = sbv; -+ if (strcmp(update, "sparc2.2")==0 ) { -+ /* 2.2 sparc put the events in the wrong place -+ * So we copy the tail of the superblock -+ * up 4 bytes before continuing -+ */ -+ __u32 *sb32 = (__u32*)sb; -+ memcpy(sb32+MD_SB_GENERIC_CONSTANT_WORDS+7, -+ sb32+MD_SB_GENERIC_CONSTANT_WORDS+7+1, -+ (MD_SB_WORDS - (MD_SB_GENERIC_CONSTANT_WORDS+7+1))*4); -+ if (verbose >= 0) -+ fprintf (stderr, Name ": adjusting superblock of %s for 2.2/sparc compatability.\n", -+ devname); -+ } -+ if (strcmp(update, "super-minor") ==0) { -+ sb->md_minor = info->array.md_minor; -+ if (verbose > 0) -+ fprintf(stderr, Name ": updating superblock of %s with minor number %d\n", -+ devname, info->array.md_minor); -+ } -+ if (strcmp(update, "summaries") == 0) { -+ int i; -+ /* set nr_disks, active_disks, working_disks, -+ * failed_disks, spare_disks based on disks[] -+ * array in superblock. -+ * Also make sure extra slots aren't 'failed' -+ */ -+ sb->nr_disks = sb->active_disks = -+ sb->working_disks = sb->failed_disks = -+ sb->spare_disks = 0; -+ for (i=0; i < MD_SB_DISKS ; i++) -+ if (sb->disks[i].major || -+ sb->disks[i].minor) { -+ int state = sb->disks[i].state; -+ if (state & (1<nr_disks++; -+ if (state & (1<active_disks++; -+ if (state & (1<failed_disks++; -+ else -+ sb->working_disks++; -+ if (state == 0) -+ sb->spare_disks++; -+ } else if (i >= sb->raid_disks && sb->disks[i].number == 0) -+ sb->disks[i].state = 0; -+ } -+ if (strcmp(update, "force-one")==0) { -+ /* Not enough devices for a working array, so -+ * bring this one up-to-date. -+ */ -+ __u32 ehi = sb->events_hi, elo = sb->events_lo; -+ sb->events_hi = (info->events>>32) & 0xFFFFFFFF; -+ sb->events_lo = (info->events) & 0xFFFFFFFF; -+ if (sb->events_hi != ehi || -+ sb->events_lo != elo) -+ rv = 1; -+ } -+ if (strcmp(update, "force-array")==0) { -+ /* degraded array and 'force' requested, so -+ * maybe need to mark it 'clean' -+ */ -+ if ((sb->level == 5 || sb->level == 4 || sb->level == 6) && -+ (sb->state & (1 << MD_SB_CLEAN)) == 0) { -+ /* need to force clean */ -+ sb->state |= (1 << MD_SB_CLEAN); -+ rv = 1; -+ } -+ } -+ if (strcmp(update, "assemble")==0) { -+ int d = info->disk.number; -+ int wonly = sb->disks[d].state & (1<disks[d].state & ~(1<disk.state) { -+ sb->disks[d].state = info->disk.state | wonly; -+ rv = 1; -+ } -+ } -+ if (strcmp(update, "linear-grow-new") == 0) { -+ memset(&sb->disks[info->disk.number], 0, sizeof(sb->disks[0])); -+ sb->disks[info->disk.number].number = info->disk.number; -+ sb->disks[info->disk.number].major = info->disk.major; -+ sb->disks[info->disk.number].minor = info->disk.minor; -+ sb->disks[info->disk.number].raid_disk = info->disk.raid_disk; -+ sb->disks[info->disk.number].state = info->disk.state; -+ sb->this_disk = sb->disks[info->disk.number]; -+ } -+ if (strcmp(update, "linear-grow-update") == 0) { -+ sb->raid_disks = info->array.raid_disks; -+ sb->nr_disks = info->array.nr_disks; -+ sb->active_disks = info->array.active_disks; -+ sb->working_disks = info->array.working_disks; -+ memset(&sb->disks[info->disk.number], 0, sizeof(sb->disks[0])); -+ sb->disks[info->disk.number].number = info->disk.number; -+ sb->disks[info->disk.number].major = info->disk.major; -+ sb->disks[info->disk.number].minor = info->disk.minor; -+ sb->disks[info->disk.number].raid_disk = info->disk.raid_disk; -+ sb->disks[info->disk.number].state = info->disk.state; -+ } -+ if (strcmp(update, "resync") == 0) { -+ /* make sure resync happens */ -+ sb->state &= ~(1<recovery_cp = 0; -+ } -+ if (strcmp(update, "homehost") == 0 && -+ homehost) { -+ uuid_set = 0; -+ update = "uuid"; -+ info->uuid[0] = sb->set_uuid0; -+ info->uuid[1] = sb->set_uuid1; -+ } -+ if (strcmp(update, "uuid") == 0) { -+ if (!uuid_set && homehost) { -+ char buf[20]; -+ char *hash = sha1_buffer(homehost, -+ strlen(homehost), -+ buf); -+ memcpy(info->uuid+2, hash, 8); -+ } -+ sb->set_uuid0 = info->uuid[0]; -+ sb->set_uuid1 = info->uuid[1]; -+ sb->set_uuid2 = info->uuid[2]; -+ sb->set_uuid3 = info->uuid[3]; -+ if (sb->state & (1<uuid, sbv); -+ } -+ } -+ if (strcmp(update, "_reshape_progress")==0) -+ sb->reshape_position = info->reshape_progress; -+ -+ sb->sb_csum = calc_sb0_csum(sb); -+ return rv; -+} -+ -+static int store_super0(struct supertype *st, int fd, void *sbv) -+{ -+ unsigned long long dsize; -+ unsigned long long offset; -+ mdp_super_t *super = sbv; -+ -+ if (!get_dev_size(fd, NULL, &dsize)) -+ return 1; -+ -+ if (dsize < MD_RESERVED_SECTORS*2*512) -+ return 2; -+ -+ offset = MD_NEW_SIZE_SECTORS(dsize>>9); -+ -+ offset *= 512; -+ -+ if (lseek64(fd, offset, 0)< 0LL) -+ return 3; -+ -+ if (write(fd, super, sizeof(*super)) != sizeof(*super)) -+ return 4; -+ -+ if (super->state & (1<magic) == BITMAP_MAGIC) -+ if (write(fd, bm, sizeof(*bm)) != sizeof(*bm)) -+ return 5; -+ } -+ -+ fsync(fd); -+ return 0; -+} -+ -+static int compare_super0(void **firstp, void *secondv) -+{ -+ /* -+ * return: -+ * 0 same, or first was empty, and second was copied -+ * 1 second had wrong number -+ * 2 wrong uuid -+ * 3 wrong other info -+ */ -+ mdp_super_t *first = *firstp; -+ mdp_super_t *second = secondv; -+ -+ int uuid1[4], uuid2[4]; -+ if (second->md_magic != MD_SB_MAGIC) -+ return 1; -+ if (!first) { -+ first = malloc(MD_SB_BYTES + sizeof(struct bitmap_super_s)); -+ memcpy(first, second, MD_SB_BYTES + sizeof(struct bitmap_super_s)); -+ *firstp = first; -+ return 0; -+ } -+ -+ uuid_from_super0(uuid1, first); -+ uuid_from_super0(uuid2, second); -+ if (!same_uuid(uuid1, uuid2, 0)) -+ return 2; -+ if (first->major_version != second->major_version || -+ first->minor_version != second->minor_version || -+ first->patch_version != second->patch_version || -+ first->gvalid_words != second->gvalid_words || -+ first->ctime != second->ctime || -+ first->level != second->level || -+ first->size != second->size || -+ first->raid_disks != second->raid_disks ) -+ return 3; -+ -+ return 0; -+} -+ -+ -+static int load_super0(struct supertype *st, int fd, void **sbp, char *devname) -+{ -+ /* try to read in the superblock -+ * Return: -+ * 0 on success -+ * 1 on cannot get superblock -+ * 2 on superblock meaningless -+ */ -+ unsigned long long dsize; -+ unsigned long long offset; -+ mdp_super_t *super; -+ int uuid[4]; -+ struct bitmap_super_s *bsb; -+ -+ if (!get_dev_size(fd, devname, &dsize)) -+ return 1; -+ -+ if (dsize < MD_RESERVED_SECTORS*512 * 2) { -+ if (devname) -+ fprintf(stderr, Name -+ ": %s is too small for md: size is %llu sectors.\n", -+ devname, dsize); -+ return 1; -+ } -+ -+ offset = MD_NEW_SIZE_SECTORS(dsize>>9); -+ -+ offset *= 512; -+ -+ ioctl(fd, BLKFLSBUF, 0); /* make sure we read current data */ -+ -+ if (lseek64(fd, offset, 0)< 0LL) { -+ if (devname) -+ fprintf(stderr, Name ": Cannot seek to superblock on %s: %s\n", -+ devname, strerror(errno)); -+ return 1; -+ } -+ -+ super = malloc(MD_SB_BYTES + sizeof(bitmap_super_t)); -+ -+ if (read(fd, super, sizeof(*super)) != MD_SB_BYTES) { -+ if (devname) -+ fprintf(stderr, Name ": Cannot read superblock on %s\n", -+ devname); -+ free(super); -+ return 1; -+ } -+ -+ if (st->ss && st->minor_version == 9) -+ super0_swap_endian(super); -+ -+ if (super->md_magic != MD_SB_MAGIC) { -+ if (devname) -+ fprintf(stderr, Name ": No super block found on %s (Expected magic %08x, got %08x)\n", -+ devname, MD_SB_MAGIC, super->md_magic); -+ free(super); -+ return 2; -+ } -+ -+ if (super->major_version != 0) { -+ if (devname) -+ fprintf(stderr, Name ": Cannot interpret superblock on %s - version is %d\n", -+ devname, super->major_version); -+ free(super); -+ return 2; -+ } -+ *sbp = super; -+ if (st->ss == NULL) { -+ st->ss = &super0; -+ st->minor_version = 90; -+ st->max_devs = MD_SB_DISKS; -+ } -+ -+ /* Now check on the bitmap superblock */ -+ if ((super->state & (1<magic) != BITMAP_MAGIC || -+ memcmp(bsb->uuid, uuid, 16) != 0) -+ goto no_bitmap; -+ return 0; -+ -+ no_bitmap: -+ super->state &= ~(1<ss = &super0; -+ st->minor_version = 90; -+ st->max_devs = MD_SB_DISKS; -+ if (strcmp(arg, "0") == 0 || -+ strcmp(arg, "0.90") == 0 || -+ strcmp(arg, "default") == 0 -+ ) -+ return st; -+ -+ st->minor_version = 9; /* flag for 'byte-swapped' */ -+ if (strcmp(arg, "0.swap")==0) -+ return st; -+ -+ free(st); -+ return NULL; -+} -+ -+void locate_bitmap0(struct supertype *st, int fd, void *sbv) -+{ -+ unsigned long long dsize; -+ unsigned long long offset; -+ -+ if (!get_dev_size(fd, NULL, &dsize)) -+ return; -+ -+ if (dsize < MD_RESERVED_SECTORS*512 * 2) -+ return; -+ -+ offset = MD_NEW_SIZE_SECTORS(dsize>>9); -+ -+ offset *= 512; -+ -+ offset += MD_SB_BYTES; -+ -+ lseek64(fd, offset, 0); -+} -+ -+struct superswitch super0 = { -+ .examine_super = NULL, -+ .brief_examine_super = brief_examine_super0, -+ .detail_super = NULL, -+ .brief_detail_super = NULL, -+ .export_super = NULL, -+ .match_home = match_home0, -+ .uuid_from_super = uuid_from_super0, -+ .getinfo_super = getinfo_super0, -+ .update_super = update_super0, -+ .init_super = NULL, -+ .add_to_super = NULL, -+ .store_super = store_super0, -+ .write_init_super = NULL, -+ .compare_super = compare_super0, -+ .load_super = load_super0, -+ .match_metadata_desc = match_metadata_desc0, -+ .avail_size = NULL, -+ .add_internal_bitmap = NULL, -+ .locate_bitmap = locate_bitmap0, -+ .write_bitmap = NULL, -+ .major = 0, -+ .swapuuid = 0, -+}; -diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/super1.c busybox-1.7.4+gentoo+mdadm/mdadm/super1.c ---- busybox-1.7.4+gentoo/mdadm/super1.c 1969-12-31 16:00:00.000000000 -0800 -+++ busybox-1.7.4+gentoo+mdadm/mdadm/super1.c 2008-03-11 10:31:00.000000000 -0700 -@@ -0,0 +1,731 @@ -+/* -+ * mdadm - manage Linux "md" devices aka RAID arrays. -+ * -+ * Copyright (C) 2001-2006 Neil Brown -+ * -+ * -+ * 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 -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Author: Neil Brown -+ * Email: -+ * Paper: Neil Brown -+ * School of Computer Science and Engineering -+ * The University of New South Wales -+ * Sydney, 2052 -+ * Australia -+ */ -+ -+#include "mdadm.h" -+/* -+ * The version-1 superblock : -+ * All numeric fields are little-endian. -+ * -+ * total size: 256 bytes plus 2 per device. -+ * 1K allows 384 devices. -+ */ -+struct mdp_superblock_1 { -+ /* constant array information - 128 bytes */ -+ __u32 magic; /* MD_SB_MAGIC: 0xa92b4efc - little endian */ -+ __u32 major_version; /* 1 */ -+ __u32 feature_map; /* 0 for now */ -+ __u32 pad0; /* always set to 0 when writing */ -+ -+ __u8 set_uuid[16]; /* user-space generated. */ -+ char set_name[32]; /* set and interpreted by user-space */ -+ -+ __u64 ctime; /* lo 40 bits are seconds, top 24 are microseconds or 0*/ -+ __u32 level; /* -4 (multipath), -1 (linear), 0,1,4,5 */ -+ __u32 layout; /* only for raid5 currently */ -+ __u64 size; /* used size of component devices, in 512byte sectors */ -+ -+ __u32 chunksize; /* in 512byte sectors */ -+ __u32 raid_disks; -+ __u32 bitmap_offset; /* sectors after start of superblock that bitmap starts -+ * NOTE: signed, so bitmap can be before superblock -+ * only meaningful of feature_map[0] is set. -+ */ -+ -+ /* These are only valid with feature bit '4' */ -+ __u32 new_level; /* new level we are reshaping to */ -+ __u64 reshape_position; /* next address in array-space for reshape */ -+ __u32 delta_disks; /* change in number of raid_disks */ -+ __u32 new_layout; /* new layout */ -+ __u32 new_chunk; /* new chunk size (bytes) */ -+ __u8 pad1[128-124]; /* set to 0 when written */ -+ -+ /* constant this-device information - 64 bytes */ -+ __u64 data_offset; /* sector start of data, often 0 */ -+ __u64 data_size; /* sectors in this device that can be used for data */ -+ __u64 super_offset; /* sector start of this superblock */ -+ __u64 recovery_offset;/* sectors before this offset (from data_offset) have been recovered */ -+ __u32 dev_number; /* permanent identifier of this device - not role in raid */ -+ __u32 cnt_corrected_read; /* number of read errors that were corrected by re-writing */ -+ __u8 device_uuid[16]; /* user-space setable, ignored by kernel */ -+ __u8 devflags; /* per-device flags. Only one defined...*/ -+#define WriteMostly1 1 /* mask for writemostly flag in above */ -+ __u8 pad2[64-57]; /* set to 0 when writing */ -+ -+ /* array state information - 64 bytes */ -+ __u64 utime; /* 40 bits second, 24 btes microseconds */ -+ __u64 events; /* incremented when superblock updated */ -+ __u64 resync_offset; /* data before this offset (from data_offset) known to be in sync */ -+ __u32 sb_csum; /* checksum upto devs[max_dev] */ -+ __u32 max_dev; /* size of devs[] array to consider */ -+ __u8 pad3[64-32]; /* set to 0 when writing */ -+ -+ /* device state information. Indexed by dev_number. -+ * 2 bytes per device -+ * Note there are no per-device state flags. State information is rolled -+ * into the 'roles' value. If a device is spare or faulty, then it doesn't -+ * have a meaningful role. -+ */ -+ __u16 dev_roles[0]; /* role in array, or 0xffff for a spare, or 0xfffe for faulty */ -+}; -+ -+struct misc_dev_info { -+ __u64 device_size; -+}; -+ -+/* feature_map bits */ -+#define MD_FEATURE_BITMAP_OFFSET 1 -+#define MD_FEATURE_RECOVERY_OFFSET 2 /* recovery_offset is present and -+ * must be honoured -+ */ -+#define MD_FEATURE_RESHAPE_ACTIVE 4 -+ -+#define MD_FEATURE_ALL (1|2|4) -+ -+#ifndef offsetof -+#define offsetof(t,f) ((size_t)&(((t*)0)->f)) -+#endif -+static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb) -+{ -+ unsigned int disk_csum, csum; -+ unsigned long long newcsum; -+ int size = sizeof(*sb) + __le32_to_cpu(sb->max_dev)*2; -+ unsigned int *isuper = (unsigned int*)sb; -+ int i; -+ -+/* make sure I can count... */ -+ if (offsetof(struct mdp_superblock_1,data_offset) != 128 || -+ offsetof(struct mdp_superblock_1, utime) != 192 || -+ sizeof(struct mdp_superblock_1) != 256) { -+ fprintf(stderr, "WARNING - superblock isn't sized correctly\n"); -+ } -+ -+ disk_csum = sb->sb_csum; -+ sb->sb_csum = 0; -+ newcsum = 0; -+ for (i=0; size>=4; size -= 4 ) { -+ newcsum += __le32_to_cpu(*isuper); -+ isuper++; -+ } -+ -+ if (size == 2) -+ newcsum += __le16_to_cpu(*(unsigned short*) isuper); -+ -+ csum = (newcsum & 0xffffffff) + (newcsum >> 32); -+ sb->sb_csum = disk_csum; -+ return __cpu_to_le32(csum); -+} -+ -+static void brief_examine_super1(void *sbv) -+{ -+ struct mdp_superblock_1 *sb = sbv; -+ int i; -+ unsigned long long sb_offset; -+ char *nm; -+ char *c=map_num(pers, __le32_to_cpu(sb->level)); -+ -+ nm = strchr(sb->set_name, ':'); -+ if (nm) -+ nm++; -+ else if (sb->set_name[0]) -+ nm = sb->set_name; -+ else -+ nm = "??"; -+ -+ printf("ARRAY /dev/md%s level=%s ", nm, c?c:"-unknown-"); -+ sb_offset = __le64_to_cpu(sb->super_offset); -+ if (sb_offset <= 4) -+ printf("metadata=1.1 "); -+ else if (sb_offset <= 8) -+ printf("metadata=1.2 "); -+ else -+ printf("metadata=1.0 "); -+ printf("num-devices=%d UUID=", __le32_to_cpu(sb->raid_disks)); -+ for (i=0; i<16; i++) { -+ if ((i&3)==0 && i != 0) printf(":"); -+ printf("%02x", sb->set_uuid[i]); -+ } -+ if (sb->set_name[0]) -+ printf(" name=%.32s", sb->set_name); -+ printf("\n"); -+} -+ -+static int match_home1(void *sbv, char *homehost) -+{ -+ struct mdp_superblock_1 *sb = sbv; -+ int l = homehost ? strlen(homehost) : 0; -+ -+ return (l > 0 && l < 32 && -+ sb->set_name[l] == ':' && -+ strncmp(sb->set_name, homehost, l) == 0); -+} -+ -+static void uuid_from_super1(int uuid[4], void * sbv) -+{ -+ struct mdp_superblock_1 *super = sbv; -+ char *cuuid = (char*)uuid; -+ int i; -+ for (i=0; i<16; i++) -+ cuuid[i] = super->set_uuid[i]; -+} -+ -+static void getinfo_super1(struct mdinfo *info, void *sbv) -+{ -+ struct mdp_superblock_1 *sb = sbv; -+ int working = 0; -+ int i; -+ int role; -+ -+ info->array.major_version = 1; -+ info->array.minor_version = __le32_to_cpu(sb->feature_map); -+ info->array.patch_version = 0; -+ info->array.raid_disks = __le32_to_cpu(sb->raid_disks); -+ info->array.level = __le32_to_cpu(sb->level); -+ info->array.layout = __le32_to_cpu(sb->layout); -+ info->array.md_minor = -1; -+ info->array.ctime = __le64_to_cpu(sb->ctime); -+ info->array.utime = __le64_to_cpu(sb->utime); -+ info->array.chunk_size = __le32_to_cpu(sb->chunksize)*512; -+ info->array.state = -+ (__le64_to_cpu(sb->resync_offset) >= __le64_to_cpu(sb->size)) -+ ? 1 : 0; -+ -+ info->data_offset = __le64_to_cpu(sb->data_offset); -+ info->component_size = __le64_to_cpu(sb->size); -+ -+ info->disk.major = 0; -+ info->disk.minor = 0; -+ info->disk.number = __le32_to_cpu(sb->dev_number); -+ if (__le32_to_cpu(sb->dev_number) >= __le32_to_cpu(sb->max_dev) || -+ __le32_to_cpu(sb->max_dev) > 512) -+ role = 0xfffe; -+ else -+ role = __le16_to_cpu(sb->dev_roles[__le32_to_cpu(sb->dev_number)]); -+ -+ info->disk.raid_disk = -1; -+ switch(role) { -+ case 0xFFFF: -+ info->disk.state = 2; /* spare: ACTIVE, not sync, not faulty */ -+ break; -+ case 0xFFFE: -+ info->disk.state = 1; /* faulty */ -+ break; -+ default: -+ info->disk.state = 6; /* active and in sync */ -+ info->disk.raid_disk = role; -+ } -+ info->events = __le64_to_cpu(sb->events); -+ -+ memcpy(info->uuid, sb->set_uuid, 16); -+ -+ strncpy(info->name, sb->set_name, 32); -+ info->name[32] = 0; -+ -+ if (sb->feature_map & __le32_to_cpu(MD_FEATURE_RESHAPE_ACTIVE)) { -+ info->reshape_active = 1; -+ info->reshape_progress = __le64_to_cpu(sb->reshape_position); -+ info->new_level = __le32_to_cpu(sb->new_level); -+ info->delta_disks = __le32_to_cpu(sb->delta_disks); -+ info->new_layout = __le32_to_cpu(sb->new_layout); -+ info->new_chunk = __le32_to_cpu(sb->new_chunk)<<9; -+ } else -+ info->reshape_active = 0; -+ -+ for (i=0; i< __le32_to_cpu(sb->max_dev); i++) { -+ role = __le16_to_cpu(sb->dev_roles[i]); -+ if (/*role == 0xFFFF || */role < info->array.raid_disks) -+ working++; -+ } -+ -+ info->array.working_disks = working; -+} -+ -+static int update_super1(struct mdinfo *info, void *sbv, char *update, -+ char *devname, int verbose, -+ int uuid_set, char *homehost) -+{ -+ /* NOTE: for 'assemble' and 'force' we need to return non-zero if any change was made. -+ * For others, the return value is ignored. -+ */ -+ int rv = 0; -+ struct mdp_superblock_1 *sb = sbv; -+ -+ if (strcmp(update, "force-one")==0) { -+ /* Not enough devices for a working array, -+ * so bring this one up-to-date -+ */ -+ if (sb->events != __cpu_to_le64(info->events)) -+ rv = 1; -+ sb->events = __cpu_to_le64(info->events); -+ } -+ if (strcmp(update, "force-array")==0) { -+ /* Degraded array and 'force' requests to -+ * maybe need to mark it 'clean'. -+ */ -+ switch(__le32_to_cpu(sb->level)) { -+ case 5: case 4: case 6: -+ /* need to force clean */ -+ if (sb->resync_offset != ~0ULL) -+ rv = 1; -+ sb->resync_offset = ~0ULL; -+ } -+ } -+ if (strcmp(update, "assemble")==0) { -+ int d = info->disk.number; -+ int want; -+ if (info->disk.state == 6) -+ want = __cpu_to_le32(info->disk.raid_disk); -+ else -+ want = 0xFFFF; -+ if (sb->dev_roles[d] != want) { -+ sb->dev_roles[d] = want; -+ rv = 1; -+ } -+ } -+ if (strcmp(update, "linear-grow-new") == 0) { -+ int i; -+ int rfd; -+ int max = __le32_to_cpu(sb->max_dev); -+ -+ for (i=0 ; i < max ; i++) -+ if (__le16_to_cpu(sb->dev_roles[i]) >= 0xfffe) -+ break; -+ sb->dev_number = __cpu_to_le32(i); -+ info->disk.number = i; -+ if (max >= __le32_to_cpu(sb->max_dev)) -+ sb->max_dev = __cpu_to_le32(max+1); -+ -+ if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 || -+ read(rfd, sb->device_uuid, 16) != 16) { -+ *(__u32*)(sb->device_uuid) = random(); -+ *(__u32*)(sb->device_uuid+4) = random(); -+ *(__u32*)(sb->device_uuid+8) = random(); -+ *(__u32*)(sb->device_uuid+12) = random(); -+ } -+ -+ sb->dev_roles[i] = -+ __cpu_to_le16(info->disk.raid_disk); -+ } -+ if (strcmp(update, "linear-grow-update") == 0) { -+ sb->raid_disks = __cpu_to_le32(info->array.raid_disks); -+ sb->dev_roles[info->disk.number] = -+ __cpu_to_le16(info->disk.raid_disk); -+ } -+ if (strcmp(update, "resync") == 0) { -+ /* make sure resync happens */ -+ sb->resync_offset = 0ULL; -+ } -+ if (strcmp(update, "uuid") == 0) { -+ copy_uuid(sb->set_uuid, info->uuid, super1.swapuuid); -+ -+ if (__le32_to_cpu(sb->feature_map)&MD_FEATURE_BITMAP_OFFSET) { -+ struct bitmap_super_s *bm; -+ bm = (struct bitmap_super_s*)(sbv+1024); -+ memcpy(bm->uuid, sb->set_uuid, 16); -+ } -+ } -+ if (strcmp(update, "homehost") == 0 && -+ homehost) { -+ char *c; -+ update = "name"; -+ c = strchr(sb->set_name, ':'); -+ if (c) -+ strncpy(info->name, c+1, 31 - (c-sb->set_name)); -+ else -+ strncpy(info->name, sb->set_name, 32); -+ info->name[32] = 0; -+ } -+ if (strcmp(update, "name") == 0) { -+ if (info->name[0] == 0) -+ sprintf(info->name, "%d", info->array.md_minor); -+ memset(sb->set_name, 0, sizeof(sb->set_name)); -+ if (homehost && -+ strchr(info->name, ':') == NULL && -+ strlen(homehost)+1+strlen(info->name) < 32) { -+ strcpy(sb->set_name, homehost); -+ strcat(sb->set_name, ":"); -+ strcat(sb->set_name, info->name); -+ } else -+ strcpy(sb->set_name, info->name); -+ } -+ if (strcmp(update, "devicesize") == 0 && -+ __le64_to_cpu(sb->super_offset) < -+ __le64_to_cpu(sb->data_offset)) { -+ /* set data_size to device size less data_offset */ -+ struct misc_dev_info *misc = (struct misc_dev_info*) -+ (sbv + 1024 + sizeof(struct bitmap_super_s)); -+ printf("Size was %llu\n", (unsigned long long) -+ __le64_to_cpu(sb->data_size)); -+ sb->data_size = __cpu_to_le64( -+ misc->device_size - __le64_to_cpu(sb->data_offset)); -+ printf("Size is %llu\n", (unsigned long long) -+ __le64_to_cpu(sb->data_size)); -+ } -+ if (strcmp(update, "_reshape_progress")==0) -+ sb->reshape_position = __cpu_to_le64(info->reshape_progress); -+ -+ sb->sb_csum = calc_sb_1_csum(sb); -+ return rv; -+} -+ -+static void locate_bitmap1(struct supertype *st, int fd, void *sbv); -+ -+static int store_super1(struct supertype *st, int fd, void *sbv) -+{ -+ struct mdp_superblock_1 *sb = sbv; -+ unsigned long long sb_offset; -+ int sbsize; -+ unsigned long long dsize; -+ -+ if (!get_dev_size(fd, NULL, &dsize)) -+ return 1; -+ -+ dsize >>= 9; -+ -+ if (dsize < 24) -+ return 2; -+ -+ /* -+ * Calculate the position of the superblock. -+ * It is always aligned to a 4K boundary and -+ * depending on minor_version, it can be: -+ * 0: At least 8K, but less than 12K, from end of device -+ * 1: At start of device -+ * 2: 4K from start of device. -+ */ -+ switch(st->minor_version) { -+ case 0: -+ sb_offset = dsize; -+ sb_offset -= 8*2; -+ sb_offset &= ~(4*2-1); -+ break; -+ case 1: -+ sb_offset = 0; -+ break; -+ case 2: -+ sb_offset = 4*2; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ -+ -+ if (sb_offset != __le64_to_cpu(sb->super_offset) && -+ 0 != __le64_to_cpu(sb->super_offset) -+ ) { -+ fprintf(stderr, Name ": internal error - sb_offset is wrong\n"); -+ abort(); -+ } -+ -+ if (lseek64(fd, sb_offset << 9, 0)< 0LL) -+ return 3; -+ -+ sbsize = sizeof(*sb) + 2 * __le32_to_cpu(sb->max_dev); -+ -+ if (write(fd, sb, sbsize) != sbsize) -+ return 4; -+ -+ if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) { -+ struct bitmap_super_s *bm = (struct bitmap_super_s*) -+ (((char*)sb)+1024); -+ if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC) { -+ locate_bitmap1(st, fd, sbv); -+ if (write(fd, bm, sizeof(*bm)) != sizeof(*bm)) -+ return 5; -+ } -+ } -+ fsync(fd); -+ return 0; -+} -+ -+static int load_super1(struct supertype *st, int fd, void **sbp, char *devname); -+ -+static int compare_super1(void **firstp, void *secondv) -+{ -+ /* -+ * return: -+ * 0 same, or first was empty, and second was copied -+ * 1 second had wrong number -+ * 2 wrong uuid -+ * 3 wrong other info -+ */ -+ struct mdp_superblock_1 *first = *firstp; -+ struct mdp_superblock_1 *second = secondv; -+ -+ if (second->magic != __cpu_to_le32(MD_SB_MAGIC)) -+ return 1; -+ if (second->major_version != __cpu_to_le32(1)) -+ return 1; -+ -+ if (!first) { -+ first = malloc(1024+sizeof(bitmap_super_t) + -+ sizeof(struct misc_dev_info)); -+ memcpy(first, second, 1024+sizeof(bitmap_super_t) + -+ sizeof(struct misc_dev_info)); -+ *firstp = first; -+ return 0; -+ } -+ if (memcmp(first->set_uuid, second->set_uuid, 16)!= 0) -+ return 2; -+ -+ if (first->ctime != second->ctime || -+ first->level != second->level || -+ first->layout != second->layout || -+ first->size != second->size || -+ first->chunksize != second->chunksize || -+ first->raid_disks != second->raid_disks) -+ return 3; -+ return 0; -+} -+ -+static int load_super1(struct supertype *st, int fd, void **sbp, char *devname) -+{ -+ unsigned long long dsize; -+ unsigned long long sb_offset; -+ struct mdp_superblock_1 *super; -+ int uuid[4]; -+ struct bitmap_super_s *bsb; -+ struct misc_dev_info *misc; -+ -+ -+ if (st->ss == NULL) { -+ int bestvers = -1; -+ __u64 bestctime = 0; -+ /* guess... choose latest ctime */ -+ st->ss = &super1; -+ for (st->minor_version = 0; st->minor_version <= 2 ; st->minor_version++) { -+ switch(load_super1(st, fd, sbp, devname)) { -+ case 0: super = *sbp; -+ if (bestvers == -1 || -+ bestctime < __le64_to_cpu(super->ctime)) { -+ bestvers = st->minor_version; -+ bestctime = __le64_to_cpu(super->ctime); -+ } -+ free(super); -+ *sbp = NULL; -+ break; -+ case 1: st->ss = NULL; return 1; /*bad device */ -+ case 2: break; /* bad, try next */ -+ } -+ } -+ if (bestvers != -1) { -+ int rv; -+ st->minor_version = bestvers; -+ st->ss = &super1; -+ st->max_devs = 384; -+ rv = load_super1(st, fd, sbp, devname); -+ if (rv) st->ss = NULL; -+ return rv; -+ } -+ st->ss = NULL; -+ return 2; -+ } -+ if (!get_dev_size(fd, devname, &dsize)) -+ return 1; -+ dsize >>= 9; -+ -+ if (dsize < 24) { -+ if (devname) -+ fprintf(stderr, Name ": %s is too small for md: size is %llu sectors.\n", -+ devname, dsize); -+ return 1; -+ } -+ -+ /* -+ * Calculate the position of the superblock. -+ * It is always aligned to a 4K boundary and -+ * depending on minor_version, it can be: -+ * 0: At least 8K, but less than 12K, from end of device -+ * 1: At start of device -+ * 2: 4K from start of device. -+ */ -+ switch(st->minor_version) { -+ case 0: -+ sb_offset = dsize; -+ sb_offset -= 8*2; -+ sb_offset &= ~(4*2-1); -+ break; -+ case 1: -+ sb_offset = 0; -+ break; -+ case 2: -+ sb_offset = 4*2; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ ioctl(fd, BLKFLSBUF, 0); /* make sure we read current data */ -+ -+ -+ if (lseek64(fd, sb_offset << 9, 0)< 0LL) { -+ if (devname) -+ fprintf(stderr, Name ": Cannot seek to superblock on %s: %s\n", -+ devname, strerror(errno)); -+ return 1; -+ } -+ -+ super = malloc(1024 + sizeof(bitmap_super_t) + -+ sizeof(struct misc_dev_info)); -+ -+ if (read(fd, super, 1024) != 1024) { -+ if (devname) -+ fprintf(stderr, Name ": Cannot read superblock on %s\n", -+ devname); -+ free(super); -+ return 1; -+ } -+ -+ if (__le32_to_cpu(super->magic) != MD_SB_MAGIC) { -+ if (devname) -+ fprintf(stderr, Name ": No super block found on %s (Expected magic %08x, got %08x)\n", -+ devname, MD_SB_MAGIC, __le32_to_cpu(super->magic)); -+ free(super); -+ return 2; -+ } -+ -+ if (__le32_to_cpu(super->major_version) != 1) { -+ if (devname) -+ fprintf(stderr, Name ": Cannot interpret superblock on %s - version is %d\n", -+ devname, __le32_to_cpu(super->major_version)); -+ free(super); -+ return 2; -+ } -+ if (__le64_to_cpu(super->super_offset) != sb_offset) { -+ if (devname) -+ fprintf(stderr, Name ": No superblock found on %s (super_offset is wrong)\n", -+ devname); -+ free(super); -+ return 2; -+ } -+ *sbp = super; -+ -+ bsb = (struct bitmap_super_s *)(((char*)super)+1024); -+ -+ misc = (struct misc_dev_info*) (bsb+1); -+ misc->device_size = dsize; -+ -+ /* Now check on the bitmap superblock */ -+ if ((__le32_to_cpu(super->feature_map)&MD_FEATURE_BITMAP_OFFSET) == 0) -+ return 0; -+ /* Read the bitmap superblock and make sure it looks -+ * valid. If it doesn't clear the bit. An --assemble --force -+ * should get that written out. -+ */ -+ locate_bitmap1(st, fd, super); -+ if (read(fd, ((char*)super)+1024, sizeof(struct bitmap_super_s)) -+ != sizeof(struct bitmap_super_s)) -+ goto no_bitmap; -+ -+ uuid_from_super1(uuid, super); -+ if (__le32_to_cpu(bsb->magic) != BITMAP_MAGIC || -+ memcmp(bsb->uuid, uuid, 16) != 0) -+ goto no_bitmap; -+ return 0; -+ -+ no_bitmap: -+ super->feature_map = __cpu_to_le32(__le32_to_cpu(super->feature_map) & ~1); -+ return 0; -+} -+ -+ -+static struct supertype *match_metadata_desc1(char *arg) -+{ -+ struct supertype *st = malloc(sizeof(*st)); -+ if (!st) return st; -+ -+ st->ss = &super1; -+ st->max_devs = 384; -+ if (strcmp(arg, "1") == 0 || -+ strcmp(arg, "1.0") == 0 || -+ strcmp(arg, "default/large") == 0) { -+ st->minor_version = 0; -+ return st; -+ } -+ if (strcmp(arg, "1.1") == 0) { -+ st->minor_version = 1; -+ return st; -+ } -+ if (strcmp(arg, "1.2") == 0) { -+ st->minor_version = 2; -+ return st; -+ } -+ -+ free(st); -+ return NULL; -+} -+ -+static void locate_bitmap1(struct supertype *st, int fd, void *sbv) -+{ -+ unsigned long long offset; -+ struct mdp_superblock_1 *sb; -+ int mustfree = 0; -+ -+ if (!sbv) { -+ if (st->ss->load_super(st, fd, &sbv, NULL)) -+ return; /* no error I hope... */ -+ mustfree = 1; -+ } -+ sb = sbv; -+ -+ offset = __le64_to_cpu(sb->super_offset); -+ offset += (int32_t) __le32_to_cpu(sb->bitmap_offset); -+ if (mustfree) -+ free(sb); -+ lseek64(fd, offset<<9, 0); -+} -+ -+struct superswitch super1 = { -+ .examine_super = NULL, -+ .brief_examine_super = brief_examine_super1, -+ .detail_super = NULL, -+ .brief_detail_super = NULL, -+ .export_super = NULL, -+ .match_home = match_home1, -+ .uuid_from_super = uuid_from_super1, -+ .getinfo_super = getinfo_super1, -+ .update_super = update_super1, -+ .init_super = NULL, -+ .add_to_super = NULL, -+ .store_super = store_super1, -+ .write_init_super = NULL, -+ .compare_super = compare_super1, -+ .load_super = load_super1, -+ .match_metadata_desc = match_metadata_desc1, -+ .avail_size = NULL, -+ .add_internal_bitmap = NULL, -+ .locate_bitmap = locate_bitmap1, -+ .write_bitmap = NULL, -+ .major = 1, -+#if __BYTE_ORDER == BIG_ENDIAN -+ .swapuuid = 0, -+#else -+ .swapuuid = 1, -+#endif -+}; -diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/util.c busybox-1.7.4+gentoo+mdadm/mdadm/util.c ---- busybox-1.7.4+gentoo/mdadm/util.c 1969-12-31 16:00:00.000000000 -0800 -+++ busybox-1.7.4+gentoo+mdadm/mdadm/util.c 2008-03-11 10:31:00.000000000 -0700 -@@ -0,0 +1,652 @@ -+/* -+ * mdadm - manage Linux "md" devices aka RAID arrays. -+ * -+ * Copyright (C) 2001-2006 Neil Brown -+ * -+ * -+ * 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 -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Author: Neil Brown -+ * Email: -+ * Paper: Neil Brown -+ * School of Computer Science and Engineering -+ * The University of New South Wales -+ * Sydney, 2052 -+ * Australia -+ */ -+ -+#include "mdadm.h" -+#include "md_p.h" -+#include -+#include -+ -+/* -+ * following taken from linux/blkpg.h because they aren't -+ * anywhere else and it isn't safe to #include linux/ * stuff. -+ */ -+ -+#define BLKPG _IO(0x12,105) -+ -+/* The argument structure */ -+struct blkpg_ioctl_arg { -+ int op; -+ int flags; -+ int datalen; -+ void *data; -+}; -+ -+/* The subfunctions (for the op field) */ -+#define BLKPG_ADD_PARTITION 1 -+#define BLKPG_DEL_PARTITION 2 -+ -+/* Sizes of name fields. Unused at present. */ -+#define BLKPG_DEVNAMELTH 64 -+#define BLKPG_VOLNAMELTH 64 -+ -+/* The data structure for ADD_PARTITION and DEL_PARTITION */ -+struct blkpg_partition { -+ long long start; /* starting offset in bytes */ -+ long long length; /* length in bytes */ -+ int pno; /* partition number */ -+ char devname[BLKPG_DEVNAMELTH]; /* partition name, like sda5 or c0d1p2, -+ to be used in kernel messages */ -+ char volname[BLKPG_VOLNAMELTH]; /* volume label */ -+}; -+ -+/* -+ * Parse a 128 bit uuid in 4 integers -+ * format is 32 hexx nibbles with options :. separator -+ * If not exactly 32 hex digits are found, return 0 -+ * else return 1 -+ */ -+int parse_uuid(char *str, int uuid[4]) -+{ -+ int hit = 0; /* number of Hex digIT */ -+ int i; -+ char c; -+ for (i=0; i<4; i++) uuid[i]=0; -+ -+ while ((c= *str++)) { -+ int n; -+ if (c>='0' && c<='9') -+ n = c-'0'; -+ else if (c>='a' && c <= 'f') -+ n = 10 + c - 'a'; -+ else if (c>='A' && c <= 'F') -+ n = 10 + c - 'A'; -+ else if (strchr(":. -", c)) -+ continue; -+ else return 0; -+ -+ if (hit<32) { -+ uuid[hit/8] <<= 4; -+ uuid[hit/8] += n; -+ } -+ hit++; -+ } -+ if (hit == 32) -+ return 1; -+ return 0; -+ -+} -+ -+ -+/* -+ * Get the md version number. -+ * We use the RAID_VERSION ioctl if it is supported -+ * If not, but we have a block device with major '9', we assume -+ * 0.36.0 -+ * -+ * Return version number as 24 but number - assume version parts -+ * always < 255 -+ */ -+ -+int md_get_version(int fd) -+{ -+ struct stat stb; -+ mdu_version_t vers; -+ -+ if (fstat(fd, &stb)<0) -+ return -1; -+ if ((S_IFMT&stb.st_mode) != S_IFBLK) -+ return -1; -+ -+ if (ioctl(fd, RAID_VERSION, &vers) == 0) -+ return (vers.major*10000) + (vers.minor*100) + vers.patchlevel; -+ if (errno == EACCES) -+ return -1; -+ if (major(stb.st_rdev) == MD_MAJOR) -+ return (3600); -+ return -1; -+} -+ -+ -+int get_linux_version() -+{ -+ struct utsname name; -+ char *cp; -+ int a,b,c; -+ if (uname(&name) <0) -+ return -1; -+ -+ cp = name.release; -+ a = strtoul(cp, &cp, 10); -+ if (*cp != '.') return -1; -+ b = strtoul(cp+1, &cp, 10); -+ if (*cp != '.') return -1; -+ c = strtoul(cp+1, NULL, 10); -+ -+ return (a*1000000)+(b*1000)+c; -+} -+ -+void remove_partitions(int fd) -+{ -+ /* remove partitions from this block devices. -+ * This is used for components added to an array -+ */ -+#ifdef BLKPG_DEL_PARTITION -+ struct blkpg_ioctl_arg a; -+ struct blkpg_partition p; -+ -+ a.op = BLKPG_DEL_PARTITION; -+ a.data = (void*)&p; -+ a.datalen = sizeof(p); -+ a.flags = 0; -+ memset(a.data, 0, a.datalen); -+ for (p.pno=0; p.pno < 16; p.pno++) -+ ioctl(fd, BLKPG, &a); -+#endif -+} -+ -+int enough(int level, int raid_disks, int layout, int clean, -+ char *avail, int avail_disks) -+{ -+ int copies, first; -+ switch (level) { -+ case 10: -+ /* This is the tricky one - we need to check -+ * which actual disks are present. -+ */ -+ copies = (layout&255)* ((layout>>8) & 255); -+ first=0; -+ do { -+ /* there must be one of the 'copies' form 'first' */ -+ int n = copies; -+ int cnt=0; -+ while (n--) { -+ if (avail[first]) -+ cnt++; -+ first = (first+1) % raid_disks; -+ } -+ if (cnt == 0) -+ return 0; -+ -+ } while (first != 0); -+ return 1; -+ -+ case -4: -+ return avail_disks>= 1; -+ case -1: -+ case 0: -+ return avail_disks == raid_disks; -+ case 1: -+ return avail_disks >= 1; -+ case 4: -+ case 5: -+ if (clean) -+ return avail_disks >= raid_disks-1; -+ else -+ return avail_disks >= raid_disks; -+ case 6: -+ if (clean) -+ return avail_disks >= raid_disks-2; -+ else -+ return avail_disks >= raid_disks; -+ default: -+ return 0; -+ } -+} -+ -+int same_uuid(int a[4], int b[4], int swapuuid) -+{ -+ if (swapuuid) { -+ /* parse uuids are hostendian. -+ * uuid's from some superblocks are big-ending -+ * if there is a difference, we need to swap.. -+ */ -+ unsigned char *ac = (unsigned char *)a; -+ unsigned char *bc = (unsigned char *)b; -+ int i; -+ for (i=0; i<16; i+= 4) { -+ if (ac[i+0] != bc[i+3] || -+ ac[i+1] != bc[i+2] || -+ ac[i+2] != bc[i+1] || -+ ac[i+3] != bc[i+0]) -+ return 0; -+ } -+ return 1; -+ } else { -+ if (a[0]==b[0] && -+ a[1]==b[1] && -+ a[2]==b[2] && -+ a[3]==b[3]) -+ return 1; -+ return 0; -+ } -+} -+void copy_uuid(void *a, int b[4], int swapuuid) -+{ -+ if (swapuuid) { -+ /* parse uuids are hostendian. -+ * uuid's from some superblocks are big-ending -+ * if there is a difference, we need to swap.. -+ */ -+ unsigned char *ac = (unsigned char *)a; -+ unsigned char *bc = (unsigned char *)b; -+ int i; -+ for (i=0; i<16; i+= 4) { -+ ac[i+0] = bc[i+3]; -+ ac[i+1] = bc[i+2]; -+ ac[i+2] = bc[i+1]; -+ ac[i+3] = bc[i+0]; -+ } -+ } else -+ memcpy(a, b, 16); -+} -+ -+char *map_num(mapping_t *map, int num) -+{ -+ while (map->name) { -+ if (map->num == num) -+ return map->name; -+ map++; -+ } -+ return NULL; -+} -+ -+int map_name(mapping_t *map, char *name) -+{ -+ while (map->name) { -+ if (strcmp(map->name, name)==0) -+ return map->num; -+ map++; -+ } -+ return UnSet; -+} -+ -+ -+int is_standard(char *dev, int *nump) -+{ -+ /* tests if dev is a "standard" md dev name. -+ * i.e if the last component is "/dNN" or "/mdNN", -+ * where NN is a string of digits -+ */ -+ char *d = strrchr(dev, '/'); -+ int type=0; -+ int num; -+ if (!d) -+ return 0; -+ if (strncmp(d, "/d",2)==0) -+ d += 2, type=1; /* /dev/md/dN{pM} */ -+ else if (strncmp(d, "/md_d", 5)==0) -+ d += 5, type=1; /* /dev/md_dNpM */ -+ else if (strncmp(d, "/md", 3)==0) -+ d += 3, type=-1; /* /dev/mdN */ -+ else if (d-dev > 3 && strncmp(d-2, "md/", 3)==0) -+ d += 1, type=-1; /* /dev/md/N */ -+ else -+ return 0; -+ if (!*d) -+ return 0; -+ num = atoi(d); -+ while (isdigit(*d)) -+ d++; -+ if (*d) -+ return 0; -+ if (nump) *nump = num; -+ -+ return type; -+} -+ -+ -+/* -+ * convert a major/minor pair for a block device into a name in /dev, if possible. -+ * On the first call, walk /dev collecting name. -+ * Put them in a simple linked listfor now. -+ */ -+struct devmap { -+ int major, minor; -+ char *name; -+ struct devmap *next; -+} *devlist = NULL; -+int devlist_ready = 0; -+ -+int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s) -+{ -+ struct stat st; -+ if (S_ISLNK(stb->st_mode)) { -+ stat(name, &st); -+ stb = &st; -+ } -+ -+ if ((stb->st_mode&S_IFMT)== S_IFBLK) { -+ char *n = strdup(name); -+ struct devmap *dm = malloc(sizeof(*dm)); -+ if (strncmp(n, "/dev/./", 7)==0) -+ strcpy(n+4, name+6); -+ if (dm) { -+ dm->major = major(stb->st_rdev); -+ dm->minor = minor(stb->st_rdev); -+ dm->name = n; -+ dm->next = devlist; -+ devlist = dm; -+ } -+ } -+ return 0; -+} -+ -+#ifndef HAVE_NFTW -+#ifdef HAVE_FTW -+int add_dev_1(const char *name, const struct stat *stb, int flag) -+{ -+ return add_dev(name, stb, flag, NULL); -+} -+int nftw(const char *path, int (*han)(const char *name, const struct stat *stb, int flag, struct FTW *s), int nopenfd, int flags) -+{ -+ return ftw(path, add_dev_1, nopenfd); -+} -+#else -+int nftw(const char *path, int (*han)(const char *name, const struct stat *stb, int flag, struct FTW *s), int nopenfd, int flags) -+{ -+ return 0; -+} -+#endif /* HAVE_FTW */ -+#endif /* HAVE_NFTW */ -+ -+/* -+ * Find a block device with the right major/minor number. -+ * If we find multiple names, choose the shortest. -+ * If we find a non-standard name, it is probably there -+ * deliberately so prefer it over a standard name. -+ * This applies only to names for MD devices. -+ */ -+char *map_dev(int major, int minor, int create) -+{ -+ struct devmap *p; -+ char *std = NULL, *nonstd=NULL; -+ int did_check = 0; -+ -+ if (major == 0 && minor == 0) -+ return NULL; -+ -+ retry: -+ if (!devlist_ready) { -+ char *dev = "/dev"; -+ struct stat stb; -+ while(devlist) { -+ struct devmap *d = devlist; -+ devlist = d->next; -+ free(d->name); -+ free(d); -+ } -+ if (lstat(dev, &stb)==0 && -+ S_ISLNK(stb.st_mode)) -+ dev = "/dev/."; -+ nftw(dev, add_dev, 10, FTW_PHYS); -+ devlist_ready=1; -+ did_check = 1; -+ } -+ -+ for (p=devlist; p; p=p->next) -+ if (p->major == major && -+ p->minor == minor) { -+ if (is_standard(p->name, NULL)) { -+ if (std == NULL || -+ strlen(p->name) < strlen(std)) -+ std = p->name; -+ } else { -+ if (nonstd == NULL || -+ strlen(p->name) < strlen(nonstd)) -+ nonstd = p->name; -+ } -+ } -+ if (!std && !nonstd && !did_check) { -+ devlist_ready = 0; -+ goto retry; -+ } -+ if (create && !std && !nonstd) { -+ static char buf[30]; -+ snprintf(buf, sizeof(buf), "%d:%d", major, minor); -+ nonstd = buf; -+ } -+ -+ return nonstd ? nonstd : std; -+} -+ -+unsigned long calc_csum(void *super, int bytes) -+{ -+ unsigned long long newcsum = 0; -+ int i; -+ unsigned int csum; -+ unsigned int *superc = (unsigned int*) super; -+ -+ for(i=0; i>32); -+#ifdef __alpha__ -+/* The in-kernel checksum calculation is always 16bit on -+ * the alpha, though it is 32 bit on i386... -+ * I wonder what it is elsewhere... (it uses and API in -+ * a way that it shouldn't). -+ */ -+ csum = (csum & 0xffff) + (csum >> 16); -+ csum = (csum & 0xffff) + (csum >> 16); -+#endif -+ return csum; -+} -+ -+char *human_size(long long bytes) -+{ -+ static char buf[30]; -+ -+ /* We convert bytes to either centi-M{ega,ibi}bytes or -+ * centi-G{igi,ibi}bytes, with appropriate rounding, -+ * and then print 1/100th of those as a decimal. -+ * We allow upto 2048Megabytes before converting to -+ * gigabytes, as that shows more precision and isn't -+ * too large a number. -+ * Terrabytes are not yet handled. -+ */ -+ -+ if (bytes < 5000*1024) -+ buf[0]=0; -+ else if (bytes < 2*1024LL*1024LL*1024LL) { -+ long cMiB = (bytes / ( (1LL<<20) / 200LL ) +1) /2; -+ long cMB = (bytes / ( 1000000LL / 200LL ) +1) /2; -+ snprintf(buf, sizeof(buf), " (%ld.%02ld MiB %ld.%02ld MB)", -+ cMiB/100 , cMiB % 100, -+ cMB/100, cMB % 100); -+ } else { -+ long cGiB = (bytes / ( (1LL<<30) / 200LL ) +1) /2; -+ long cGB = (bytes / (1000000000LL/200LL ) +1) /2; -+ snprintf(buf, sizeof(buf), " (%ld.%02ld GiB %ld.%02ld GB)", -+ cGiB/100 , cGiB % 100, -+ cGB/100, cGB % 100); -+ } -+ return buf; -+} -+ -+char *human_size_brief(long long bytes) -+{ -+ static char buf[30]; -+ -+ -+ if (bytes < 5000*1024) -+ snprintf(buf, sizeof(buf), "%ld.%02ldKiB", -+ (long)(bytes>>10), (long)(((bytes&1023)*100+512)/1024) -+ ); -+ else if (bytes < 2*1024LL*1024LL*1024LL) -+ snprintf(buf, sizeof(buf), "%ld.%02ldMiB", -+ (long)(bytes>>20), -+ (long)((bytes&0xfffff)+0x100000/200)/(0x100000/100) -+ ); -+ else -+ snprintf(buf, sizeof(buf), "%ld.%02ldGiB", -+ (long)(bytes>>30), -+ (long)(((bytes>>10)&0xfffff)+0x100000/200)/(0x100000/100) -+ ); -+ return buf; -+} -+ -+int get_mdp_major(void) -+{ -+static int mdp_major = -1; -+ FILE *fl; -+ char *w; -+ int have_block = 0; -+ int have_devices = 0; -+ int last_num = -1; -+ -+ if (mdp_major != -1) -+ return mdp_major; -+ fl = fopen("/proc/devices", "r"); -+ if (!fl) -+ return -1; -+ while ((w = conf_word(fl, 1))) { -+ if (have_block && strcmp(w, "devices:")==0) -+ have_devices = 1; -+ have_block = (strcmp(w, "Block")==0); -+ if (isdigit(w[0])) -+ last_num = atoi(w); -+ if (have_devices && strcmp(w, "mdp")==0) -+ mdp_major = last_num; -+ free(w); -+ } -+ fclose(fl); -+ return mdp_major; -+} -+ -+int dev_open(char *dev, int flags) -+{ -+ /* like 'open', but if 'dev' matches %d:%d, create a temp -+ * block device and open that -+ */ -+ char *e; -+ int fd = -1; -+ char devname[32]; -+ int major; -+ int minor; -+ -+ if (!dev) return -1; -+ -+ major = strtoul(dev, &e, 0); -+ if (e > dev && *e == ':' && e[1] && -+ (minor = strtoul(e+1, &e, 0)) >= 0 && -+ *e == 0) { -+ snprintf(devname, sizeof(devname), "/dev/.tmp.md.%d:%d", major, minor); -+ if (mknod(devname, S_IFBLK|0600, makedev(major, minor))==0) { -+ fd = open(devname, flags); -+ unlink(devname); -+ } -+ } else -+ fd = open(dev, flags); -+ return fd; -+} -+ -+struct superswitch *superlist[] = { &super0, &super1, NULL }; -+ -+struct supertype *super_by_version(int vers, int minor) -+{ -+ struct supertype *st = malloc(sizeof(*st)); -+ if (!st) return st; -+ if (vers == 0) { -+ st->ss = &super0; -+ st->max_devs = MD_SB_DISKS; -+ } -+ -+ if (vers == 1) { -+ st->ss = &super1; -+ st->max_devs = 384; -+ } -+ st->minor_version = minor; -+ return st; -+} -+ -+struct supertype *guess_super(int fd) -+{ -+ /* try each load_super to find the best match, -+ * and return the best superswitch -+ */ -+ struct superswitch *ss; -+ struct supertype *st; -+ unsigned long besttime = 0; -+ int bestsuper = -1; -+ -+ void *sbp = NULL; -+ int i; -+ -+ st = malloc(sizeof(*st)); -+ memset(st, 0, sizeof(*st)); -+ for (i=0 ; superlist[i]; i++) { -+ int rv; -+ ss = superlist[i]; -+ st->ss = NULL; -+ rv = ss->load_super(st, fd, &sbp, NULL); -+ if (rv == 0) { -+ struct mdinfo info; -+ ss->getinfo_super(&info, sbp); -+ if (bestsuper == -1 || -+ besttime < info.array.ctime) { -+ bestsuper = i; -+ besttime = info.array.ctime; -+ } -+ free(sbp); -+ } -+ } -+ if (bestsuper != -1) { -+ int rv; -+ st->ss = NULL; -+ rv = superlist[bestsuper]->load_super(st, fd, &sbp, NULL); -+ if (rv == 0) { -+ free(sbp); -+ return st; -+ } -+ } -+ free(st); -+ return NULL; -+} -+ -+/* Return size of device in bytes */ -+int get_dev_size(int fd, char *dname, unsigned long long *sizep) -+{ -+ unsigned long long ldsize; -+#ifdef BLKGETSIZE64 -+ if (ioctl(fd, BLKGETSIZE64, &ldsize) != 0) -+#endif -+ { -+ unsigned long dsize; -+ if (ioctl(fd, BLKGETSIZE, &dsize) == 0) { -+ ldsize = dsize; -+ ldsize <<= 9; -+ } else { -+ if (dname) -+ fprintf(stderr, Name ": Cannot get size of %s: %s\b", -+ dname, strerror(errno)); -+ return 0; -+ } -+ } -+ *sizep = ldsize; -+ return 1; -+} ---- busybox-1.7.4+gentoo/mdadm/Kbuild 2008-03-01 18:44:05.526713152 -0800 -+++ busybox-1.7.4+gentoo+mdadm/mdadm/Kbuild 2008-03-11 12:19:18.000000000 -0700 -@@ -0,0 +1,9 @@ -+# Makefile for busybox -+# -+# Copyright (C) 1999-2005 by Erik Andersen -+# -+# Licensed under the GPL v2, see the file LICENSE in this tarball. -+ -+lib-y:= -+MDADM-y:= config.o util.o dlink.o sha1.o super0.o super1.o mdexamine.o mdassemble.o -+lib-$(CONFIG_MDADM) += mdadm.o $(MDADM-y) diff -pruN genkernel.a/patches/busybox/1.7.4/1.7.4-mdstart.diff genkernel.b/patches/busybox/1.7.4/1.7.4-mdstart.diff --- genkernel.a/patches/busybox/1.7.4/1.7.4-mdstart.diff 2011-01-12 21:05:44.000000000 +0200 +++ genkernel.b/patches/busybox/1.7.4/1.7.4-mdstart.diff 1970-01-01 03:00:00.000000000 +0300 @@ -1,122 +0,0 @@ -Forward-port the old mdstart tool from the Gentoo Busybox-1.1.3. -Only fires the RAID_AUTORUN ioctl on existing /dev/md nodes. - -Signed-off-by: Robin H. Johnson - -diff -Nuar --exclude '*.orig' busybox-1.7.4/include/applets.h busybox-1.7.4+gentoo/include/applets.h ---- busybox-1.7.4/include/applets.h 2007-09-03 04:48:46.000000000 -0700 -+++ busybox-1.7.4+gentoo/include/applets.h 2008-03-11 10:25:43.000000000 -0700 -@@ -222,6 +222,7 @@ - USE_MATCHPATHCON(APPLET(matchpathcon, _BB_DIR_USR_SBIN, _BB_SUID_NEVER)) - USE_MD5SUM(APPLET_ODDNAME(md5sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_NEVER, md5sum)) - USE_MDEV(APPLET(mdev, _BB_DIR_SBIN, _BB_SUID_NEVER)) -+USE_MDSTART(APPLET(mdstart, _BB_DIR_SBIN, _BB_SUID_NEVER)) - USE_MESG(APPLET(mesg, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) - USE_MKDIR(APPLET_NOFORK(mkdir, mkdir, _BB_DIR_BIN, _BB_SUID_NEVER, mkdir)) - //USE_MKE2FS(APPLET(mke2fs, _BB_DIR_SBIN, _BB_SUID_NEVER)) -diff -Nuar --exclude '*.orig' busybox-1.7.4/include/usage.h busybox-1.7.4+gentoo/include/usage.h ---- busybox-1.7.4/include/usage.h 2007-09-03 04:48:46.000000000 -0700 -+++ busybox-1.7.4+gentoo/include/usage.h 2008-03-11 10:19:04.000000000 -0700 -@@ -2072,6 +2072,11 @@ - "the last line match .* to override this.)\n\n" \ - ) - -+#define mdstart_trivial_usage \ -+ "{[PARTITION] MD-NODE}..." -+#define mdstart_full_usage \ -+ "Run the RAID_AUTORUN ioctl on the given MD number" -+ - #define mesg_trivial_usage \ - "[y|n]" - #define mesg_full_usage \ -diff -Nuar --exclude '*.orig' busybox-1.7.4/util-linux/Config.in busybox-1.7.4+gentoo/util-linux/Config.in ---- busybox-1.7.4/util-linux/Config.in 2007-09-03 04:48:56.000000000 -0700 -+++ busybox-1.7.4+gentoo/util-linux/Config.in 2008-03-11 10:26:20.000000000 -0700 -@@ -305,6 +305,13 @@ - /lib/firmware/ and if it exists, send it to the kernel for - loading into the hardware. - -+config MDSTART -+ bool "mdstart" -+ default n -+ help -+ Allows you to autostart /dev/md devices if using an initramfs to -+ boot. -+ - config MKSWAP - bool "mkswap" - default n -diff -Nuar --exclude '*.orig' busybox-1.7.4/util-linux/Kbuild busybox-1.7.4+gentoo/util-linux/Kbuild ---- busybox-1.7.4/util-linux/Kbuild 2007-09-03 04:48:56.000000000 -0700 -+++ busybox-1.7.4+gentoo/util-linux/Kbuild 2008-03-11 10:28:47.000000000 -0700 -@@ -18,6 +18,7 @@ - lib-$(CONFIG_IPCRM) +=ipcrm.o - lib-$(CONFIG_IPCS) +=ipcs.o - lib-$(CONFIG_LOSETUP) +=losetup.o -+lib-$(CONFIG_MDSTART) +=mdStart.o - lib-$(CONFIG_MDEV) +=mdev.o - lib-$(CONFIG_MKFS_MINIX) +=mkfs_minix.o - lib-$(CONFIG_MKSWAP) +=mkswap.o -diff -Nuar --exclude '*.orig' busybox-1.7.4/util-linux/mdStart.c busybox-1.7.4+gentoo/util-linux/mdStart.c ---- busybox-1.7.4/util-linux/mdStart.c 1969-12-31 16:00:00.000000000 -0800 -+++ busybox-1.7.4+gentoo/util-linux/mdStart.c 2008-03-11 10:19:04.000000000 -0700 -@@ -0,0 +1,59 @@ -+/* -+ * Linux 2.6(+) RAID Autostarter -+ * -+ * Copyright (C) 2005 by Tim Yamin -+ * -+ * 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 -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+extern int -+mdstart_main(int argc, char *argv[]) -+{ -+ int i, fd, part = 0, retval = 0; -+ -+ if(argc < 2) -+ { -+ bb_show_usage(); -+ } -+ -+ for(i = 1; i < argc; i++) -+ { -+ if(sscanf(argv[i], "%d", &part) == 1) -+ continue; -+ -+ fd = open(argv[i], 0, 0); -+ if (fd >= 0) -+ { -+ ioctl(fd, RAID_AUTORUN, part); -+ close(fd); -+ } else -+ { -+ printf("Error: Failed to open %s!\n", argv[i]); -+ retval=1; -+ } -+ -+ part = 0; -+ } -+ -+ return retval; -+} diff -pruN genkernel.a/patches/busybox/1.7.4/1.7.4-mount-umount-i-option.diff genkernel.b/patches/busybox/1.7.4/1.7.4-mount-umount-i-option.diff --- genkernel.a/patches/busybox/1.7.4/1.7.4-mount-umount-i-option.diff 2011-01-12 21:05:44.000000000 +0200 +++ genkernel.b/patches/busybox/1.7.4/1.7.4-mount-umount-i-option.diff 1970-01-01 03:00:00.000000000 +0300 @@ -1,24 +0,0 @@ -diff -ru busybox-1.7.4.orig/util-linux/mount.c busybox-1.7.4/util-linux/mount.c ---- busybox-1.7.4.orig/util-linux/mount.c 2007-09-03 06:48:56.000000000 -0500 -+++ busybox-1.7.4/util-linux/mount.c 2008-11-13 21:12:06.000000000 -0600 -@@ -1554,7 +1554,7 @@ - - // Parse remaining options - -- opt = getopt32(argv, "o:t:rwanfvs", &opt_o, &fstype); -+ opt = getopt32(argv, "o:t:rwanfvsi", &opt_o, &fstype); - if (opt & 0x1) append_mount_options(&cmdopts, opt_o); // -o - //if (opt & 0x2) // -t - if (opt & 0x4) append_mount_options(&cmdopts, "ro"); // -r -diff -ru busybox-1.7.4.orig/util-linux/umount.c busybox-1.7.4/util-linux/umount.c ---- busybox-1.7.4.orig/util-linux/umount.c 2007-09-03 06:48:56.000000000 -0500 -+++ busybox-1.7.4/util-linux/umount.c 2008-11-13 16:13:03.000000000 -0600 -@@ -12,7 +12,7 @@ - #include - #include "libbb.h" - --#define OPTION_STRING "flDnravdt:" -+#define OPTION_STRING "flDnravdt:i" - #define OPT_FORCE 1 - #define OPT_LAZY 2 - #define OPT_DONTFREELOOP 4 diff -pruN genkernel.a/patches/busybox/1.7.4/1.7.4-openvt.diff genkernel.b/patches/busybox/1.7.4/1.7.4-openvt.diff --- genkernel.a/patches/busybox/1.7.4/1.7.4-openvt.diff 2011-01-12 21:05:44.000000000 +0200 +++ genkernel.b/patches/busybox/1.7.4/1.7.4-openvt.diff 1970-01-01 03:00:00.000000000 +0300 @@ -1,20 +0,0 @@ -Allow a slightly wider range of valid vt numbers. Forward-ported from Gentoo -Busybox 1.1.3. - -The previous spin of this patch on 1.1.3 had a 'wait(NULL);' right before -return EXIT_SUCCESS. I don't think it's needed anymore, so I left it out. - -Signed-off-by: Robin H. Johnson - -diff -Nuar --exclude '*.orig' busybox-1.7.4/console-tools/openvt.c busybox-1.7.4+gentoo/console-tools/openvt.c ---- busybox-1.7.4/console-tools/openvt.c 2007-09-03 04:48:35.000000000 -0700 -+++ busybox-1.7.4+gentoo/console-tools/openvt.c 2008-03-10 10:00:55.000000000 -0700 -@@ -21,7 +21,7 @@ - bb_show_usage(); - - /* check for illegal vt number: < 1 or > 63 */ -- sprintf(vtname, VC_FORMAT, (int)xatou_range(argv[1], 1, 63)); -+ sprintf(vtname, VC_FORMAT, (int)xatou_range(argv[1], 0, 63)); - - bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv); - /* grab new one */ diff -pruN genkernel.a/patches/busybox/1.7.4/1.7.4-static-error.diff genkernel.b/patches/busybox/1.7.4/1.7.4-static-error.diff --- genkernel.a/patches/busybox/1.7.4/1.7.4-static-error.diff 2011-01-12 21:05:44.000000000 +0200 +++ genkernel.b/patches/busybox/1.7.4/1.7.4-static-error.diff 1970-01-01 03:00:00.000000000 +0300 @@ -1,23 +0,0 @@ -diff -ur busybox-1.7.4.orig/applets/applets.c busybox-1.7.4/applets/applets.c ---- busybox-1.7.4.orig/applets/applets.c 2007-09-16 13:48:10.000000000 -0500 -+++ busybox-1.7.4/applets/applets.c 2008-03-11 13:53:18.000000000 -0500 -@@ -23,7 +23,6 @@ - #warning Note that glibc is unsuitable for static linking anyway. - #warning If you still want to do it, remove -Wl,--gc-sections - #warning from top-level Makefile and remove this warning. --#error Aborting compilation. - #endif - - -diff -ur busybox-1.7.4.orig/Makefile busybox-1.7.4/Makefile ---- busybox-1.7.4.orig/Makefile 2007-11-23 22:34:41.000000000 -0600 -+++ busybox-1.7.4/Makefile 2008-03-12 06:35:25.000000000 -0500 -@@ -570,7 +570,7 @@ - quiet_cmd_busybox__ ?= LINK $@ - cmd_busybox__ ?= $(srctree)/scripts/trylink $(CC) $(LDFLAGS) \ - -o $@ -Wl,-Map -Wl,$@.map \ -- -Wl,--warn-common -Wl,--sort-common -Wl,--gc-sections \ -+ -Wl,--warn-common -Wl,--sort-common \ - -Wl,--start-group $(busybox-all) -Wl,--end-group \ - $(LDLIBS) - diff -pruN genkernel.a/patches/busybox/1.7.4/busybox-1.7.4-signal-hack.patch genkernel.b/patches/busybox/1.7.4/busybox-1.7.4-signal-hack.patch --- genkernel.a/patches/busybox/1.7.4/busybox-1.7.4-signal-hack.patch 2011-01-12 21:05:44.000000000 +0200 +++ genkernel.b/patches/busybox/1.7.4/busybox-1.7.4-signal-hack.patch 1970-01-01 03:00:00.000000000 +0300 @@ -1,28 +0,0 @@ -workaround while we get it fixed upstream - -http://bugs.gentoo.org/201114 - ---- libbb/u_signal_names.c -+++ libbb/u_signal_names.c -@@ -66,7 +66,7 @@ - #ifdef SIGTERM - [SIGTERM ] = "TERM", - #endif --#ifdef SIGSTKFLT -+#if defined(SIGSTKFLT) && SIGSTKFLT < 32 - [SIGSTKFLT] = "STKFLT", - #endif - #ifdef SIGCHLD -@@ -90,10 +90,10 @ - #ifdef SIGURG - [SIGURG ] = "URG", - #endif --#ifdef SIGXCPU -+#if defined(SIGXCPU) && SIGXCPU < 32 - [SIGXCPU ] = "XCPU", - #endif --#ifdef SIGXFSZ -+#if defined(SIGXFSZ) && SIGXFSZ < 32 - [SIGXFSZ ] = "XFSZ", - #endif - #ifdef SIGVTALRM diff -pruN genkernel.a/patches/busybox/1.7.4/README genkernel.b/patches/busybox/1.7.4/README --- genkernel.a/patches/busybox/1.7.4/README 2011-01-12 21:05:44.000000000 +0200 +++ genkernel.b/patches/busybox/1.7.4/README 1970-01-01 03:00:00.000000000 +0300 @@ -1,23 +0,0 @@ -1.7.4-ash-timeout.diff: -This patch adds support for the -t option to the 'read' command in ash. It's -used for prompting for the keymap. It originated with 1.1.3+gentoo or earlier. - -1.7.4-mdadm.diff: -This adds a minimal mdadm implementation to busybox for scanning for and -activating mdraid arrays. You can blame robbat2 for this one :) - -1.7.4-mdstart.diff: -This adds a 'mdstart' command to busybox, which is used for the activation of -individual mdraid arrays. It originated with 1.1.3+gentoo or earlier. - -1.7.4-openvt.diff: -It is unknown what problem this patch fixes. It may no longer be needed. - -1.7.4-static-error.diff: -This allows us to build busybox statically, even though upstream frowns upon it. -It's important that the removal of -Wl,--gc-sections remains, or ash will be -broken in the resulting busybox. This patch is based on the busybox ebuild. - -busybox-1.7.4-signal-hack.patch: -It is unknown what this patch does. It may no longer be needed. -