/package/pango/

' alt='cgit logo'/> index : busybox
BusyBox: The Swiss Army Knife of Embedded Linuxvda
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat
-rw-r--r--.gitignore2
-rw-r--r--Config.in138
-rw-r--r--Makefile34
-rw-r--r--Makefile.custom8
-rw-r--r--Makefile.flags1
-rw-r--r--README17
-rw-r--r--TEST_config_nommu (renamed from TODO_config_nommu)37
-rw-r--r--TEST_config_noprintf929
-rw-r--r--TEST_config_rh9 (renamed from scripts/defconfig)80
-rw-r--r--TODO121
-rw-r--r--TODO_unicode45
-rw-r--r--applets/Kbuild.src (renamed from applets/Kbuild)8
-rw-r--r--applets/applet_tables.c26
-rw-r--r--applets/applets.c2
-rw-r--r--applets/usage.c33
-rwxr-xr-xapplets/usage_compressed24
-rw-r--r--applets/usage_pod.c57
-rw-r--r--archival/Config.src (renamed from archival/Config.in)118
-rw-r--r--archival/Kbuild.src (renamed from archival/Kbuild)22
-rw-r--r--archival/ar.c222
-rw-r--r--archival/bbunzip.c193
-rw-r--r--archival/bz/bzlib.c8
-rw-r--r--archival/bzip2.c14
-rw-r--r--archival/cpio.c3
-rw-r--r--archival/dpkg.c161
-rw-r--r--archival/dpkg_deb.c9
-rw-r--r--archival/gzip.c24
-rw-r--r--archival/libunarchive/Kbuild.src (renamed from archival/libunarchive/Kbuild)5
-rw-r--r--archival/libunarchive/data_extract_all.c187
-rw-r--r--archival/libunarchive/data_extract_to_command.c134
-rw-r--r--archival/libunarchive/decompress_bunzip2.c6
-rw-r--r--archival/libunarchive/decompress_uncompress.c2
-rw-r--r--archival/libunarchive/decompress_unxz.c106
-rw-r--r--archival/libunarchive/decompress_unzip.c7
-rw-r--r--archival/libunarchive/get_header_ar.c13
-rw-r--r--archival/libunarchive/get_header_tar.c250
-rw-r--r--archival/libunarchive/header_verbose_list.c1
-rw-r--r--archival/libunarchive/open_transformer.c14
-rw-r--r--archival/libunarchive/unpack_ar_archive.c7
-rw-r--r--archival/libunarchive/unxz/README136
-rw-r--r--archival/libunarchive/unxz/xz.h271
-rw-r--r--archival/libunarchive/unxz/xz_config.h123
-rw-r--r--archival/libunarchive/unxz/xz_dec_bcj.c564
-rw-r--r--archival/libunarchive/unxz/xz_dec_lzma2.c1175
-rw-r--r--archival/libunarchive/unxz/xz_dec_stream.c822
-rw-r--r--archival/libunarchive/unxz/xz_lzma2.h204
-rw-r--r--archival/libunarchive/unxz/xz_private.h159
-rw-r--r--archival/libunarchive/unxz/xz_stream.h57
-rw-r--r--archival/lzo1x_9x.c166
-rw-r--r--archival/lzop.c25
-rw-r--r--archival/rpm.c115
-rw-r--r--archival/rpm.h38
-rw-r--r--archival/rpm2cpio.c81
-rw-r--r--archival/tar.c121
-rw-r--r--archival/unzip.c167
-rw-r--r--archival/unzip_doc.txt.bz2bin11359 -> 0 bytes
-rw-r--r--console-tools/Config.src (renamed from console-tools/Config.in)61
-rw-r--r--console-tools/Kbuild.src (renamed from console-tools/Kbuild)3
-rw-r--r--console-tools/clear.c7
-rw-r--r--console-tools/dumpkmap.c7
-rw-r--r--console-tools/fgconsole.c30
-rw-r--r--console-tools/loadfont.c315
-rw-r--r--console-tools/loadkmap.c7
-rw-r--r--console-tools/openvt.c3
-rw-r--r--console-tools/reset.c10
-rw-r--r--console-tools/resize.c10
-rw-r--r--console-tools/setkeycodes.c18
-rw-r--r--coreutils/Config.src (renamed from coreutils/Config.in)291
-rw-r--r--coreutils/Kbuild.src (renamed from coreutils/Kbuild)15
-rw-r--r--coreutils/basename.c22
-rw-r--r--coreutils/cal.c15
-rw-r--r--coreutils/cat.c12
-rw-r--r--coreutils/chmod.c2
-rw-r--r--coreutils/chown.c11
-rw-r--r--coreutils/chroot.c3
-rw-r--r--coreutils/date.c105
-rw-r--r--coreutils/dd.c9
-rw-r--r--coreutils/df.c19
-rw-r--r--coreutils/dos2unix.c2
-rw-r--r--coreutils/du.c2
-rw-r--r--coreutils/env.c7
-rw-r--r--coreutils/expand.c31
-rw-r--r--coreutils/expr.c2
-rw-r--r--coreutils/fsync.c3
-rw-r--r--coreutils/head.c8
-rw-r--r--coreutils/install.c27
-rw-r--r--coreutils/libcoreutils/Kbuild.src (renamed from coreutils/libcoreutils/Kbuild)2
-rw-r--r--coreutils/ls.c416
-rw-r--r--coreutils/md5_sha1_sum.c6
-rw-r--r--coreutils/nice.c6
-rw-r--r--coreutils/nohup.c4
-rw-r--r--coreutils/od_bloaty.c4
-rw-r--r--coreutils/realpath.c16
-rw-r--r--coreutils/sort.c2
-rw-r--r--coreutils/stat.c222
-rw-r--r--coreutils/stty.c2
-rw-r--r--coreutils/tail.c13
-rw-r--r--coreutils/test.c22
-rw-r--r--coreutils/touch.c4
-rw-r--r--coreutils/tr.c29
-rw-r--r--coreutils/wc.c2
-rw-r--r--coreutils/who.c46
-rw-r--r--coreutils/yes.c5
-rw-r--r--debianutils/Config.src (renamed from debianutils/Config.in)20
-rw-r--r--debianutils/Kbuild.src (renamed from debianutils/Kbuild)2
-rw-r--r--debianutils/mktemp.c22
-rw-r--r--debianutils/pipe_progress.c16
-rw-r--r--debianutils/run_parts.c7
-rw-r--r--debianutils/start_stop_daemon.c41
-rw-r--r--docs/keep_data_small.txt5
-rw-r--r--docs/mdev.txt16
-rw-r--r--docs/style-guide.txt2
-rw-r--r--docs/unicode.txt71
-rw-r--r--docs/unicode_UTF-8-test.txtbin0 -> 20334 bytes
-rw-r--r--docs/unicode_full-bmp.txt2079
-rw-r--r--e2fsprogs/Config.src (renamed from e2fsprogs/Config.in)28
-rw-r--r--e2fsprogs/Kbuild.src (renamed from e2fsprogs/Kbuild)5
-rw-r--r--e2fsprogs/fsck.c10
-rw-r--r--e2fsprogs/old_e2fsprogs/Config.src (renamed from e2fsprogs/old_e2fsprogs/Config.in)2
-rw-r--r--e2fsprogs/old_e2fsprogs/Kbuild.src (renamed from e2fsprogs/old_e2fsprogs/Kbuild)2
-rw-r--r--e2fsprogs/old_e2fsprogs/blkid/Kbuild.src (renamed from e2fsprogs/old_e2fsprogs/blkid/Kbuild)3
-rw-r--r--e2fsprogs/old_e2fsprogs/blkid/devname.c2
-rw-r--r--e2fsprogs/old_e2fsprogs/blkid/probe.c16
-rw-r--r--e2fsprogs/old_e2fsprogs/blkid/resolve.c2
-rw-r--r--e2fsprogs/old_e2fsprogs/blkid/tag.c2
-rw-r--r--e2fsprogs/old_e2fsprogs/e2fsck.c20
-rw-r--r--e2fsprogs/old_e2fsprogs/e2p/Kbuild.src (renamed from e2fsprogs/old_e2fsprogs/e2p/Kbuild)3
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/Kbuild.src (renamed from e2fsprogs/old_e2fsprogs/ext2fs/Kbuild)3
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/alloc.c2
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/bitops.h2
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/bmap.c2
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/closefs.c4
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/dirblock.c2
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/ext_attr.c2
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/finddev.c4
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/imager.c2
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/mkdir.c2
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/mkjournal.c2
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/namei.c4
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/rw_bitmaps.c2
-rw-r--r--e2fsprogs/old_e2fsprogs/fsck.c4
-rw-r--r--e2fsprogs/old_e2fsprogs/mke2fs.c4
-rw-r--r--e2fsprogs/old_e2fsprogs/util.c2
-rw-r--r--e2fsprogs/old_e2fsprogs/uuid/Kbuild.src (renamed from e2fsprogs/old_e2fsprogs/uuid/Kbuild)2
-rw-r--r--e2fsprogs/tune2fs.c (renamed from util-linux/tune2fs.c)7
-rw-r--r--editors/Config.src (renamed from editors/Config.in)34
-rw-r--r--editors/Kbuild.src (renamed from editors/Kbuild)2
-rw-r--r--editors/awk.c721
-rw-r--r--editors/cmp.c26
-rw-r--r--editors/diff.c111
-rw-r--r--editors/patch.c851
-rw-r--r--editors/patch_bbox.c306
-rw-r--r--editors/sed.c109
-rw-r--r--editors/vi.c277
-rw-r--r--examples/udhcp/udhcpd.conf94
-rw-r--r--findutils/.gitignore3
-rw-r--r--findutils/Config.in253
-rw-r--r--findutils/Config.src10
-rw-r--r--findutils/Kbuild.src (renamed from init/Kbuild)5
-rw-r--r--findutils/find.c284
-rw-r--r--findutils/grep.c120
-rw-r--r--findutils/xargs.c604
-rw-r--r--include/applets.src.h (renamed from include/applets.h)47
-rw-r--r--include/ar.h26
-rw-r--r--include/fix_u32.h33
-rw-r--r--include/grp_.h2
-rw-r--r--include/inet_common.h8
-rw-r--r--include/libbb.h164
-rw-r--r--include/platform.h64
-rw-r--r--include/pwd_.h10
-rw-r--r--include/shadow_.h5
-rw-r--r--include/unarchive.h79
-rw-r--r--include/unicode.h68
-rw-r--r--include/usage.src.h (renamed from include/usage.h)1178
-rw-r--r--init/Config.src (renamed from init/Config.in)22
-rw-r--r--init/Kbuild.src (renamed from findutils/Kbuild)9
-rw-r--r--init/bootchartd.c442
-rw-r--r--init/halt.c16
-rw-r--r--init/init.c8
-rw-r--r--libbb/Config.src (renamed from libbb/Config.in)16
-rw-r--r--libbb/Kbuild.src (renamed from libbb/Kbuild)16
-rw-r--r--libbb/appletlib.c132
-rw-r--r--libbb/bb_askpass.c42
-rw-r--r--libbb/compare_string_array.c23
-rw-r--r--libbb/copy_file.c4
-rw-r--r--libbb/copyfd.c26
-rw-r--r--libbb/die_if_bad_username.c12
-rw-r--r--libbb/dump.c4
-rw-r--r--libbb/error_msg.c19
-rw-r--r--libbb/error_msg_and_die.c20
-rw-r--r--libbb/execable.c8
-rw-r--r--libbb/get_line_from_file.c5
-rw-r--r--libbb/get_volsize.c48
-rw-r--r--libbb/getopt32.c15
-rw-r--r--libbb/herror_msg.c11
-rw-r--r--libbb/herror_msg_and_die.c20
-rw-r--r--libbb/info_msg.c12
-rw-r--r--libbb/lineedit.c699
-rw-r--r--libbb/loop.c55
-rw-r--r--libbb/md5.c12
-rw-r--r--libbb/parse_config.c20
-rw-r--r--libbb/perror_msg.c17
-rw-r--r--libbb/perror_msg_and_die.c26
-rw-r--r--libbb/platform.c27
-rw-r--r--libbb/print_flags.c3
-rw-r--r--libbb/printable_string.c65
-rw-r--r--libbb/progress.c3
-rw-r--r--libbb/read.c322
-rw-r--r--libbb/read_key.c32
-rw-r--r--libbb/read_printf.c372
-rw-r--r--libbb/restricted_shell.c46
-rw-r--r--libbb/run_shell.c20
-rw-r--r--libbb/safe_gethostname.c10
-rw-r--r--libbb/setup_environment.c13
-rw-r--r--libbb/skip_whitespace.c7
-rw-r--r--libbb/time.c24
-rw-r--r--libbb/udp_io.c12
-rw-r--r--libbb/unicode.c881
-rw-r--r--libbb/unicode_wcwidth.c473
-rw-r--r--libbb/utmp.c133
-rw-r--r--libbb/verror_msg.c32
-rw-r--r--libbb/vfork_daemon_rexec.c52
-rw-r--r--libbb/wfopen_input.c10
-rw-r--r--libbb/xconnect.c49
-rw-r--r--libbb/xfuncs.c238
-rw-r--r--libbb/xfuncs_printf.c90
-rw-r--r--libbb/xgethostbyname.c2
-rw-r--r--libbb/xreadlink.c6
-rw-r--r--libpwdgrp/Kbuild.src (renamed from libpwdgrp/Kbuild)0
-rw-r--r--libpwdgrp/pwd_grp.c342
-rw-r--r--loginutils/Config.src (renamed from loginutils/Config.in)58
-rw-r--r--loginutils/Kbuild.src (renamed from loginutils/Kbuild)2
-rw-r--r--loginutils/adduser.c18
-rw-r--r--loginutils/getty.c69
-rw-r--r--loginutils/login.c130
-rw-r--r--loginutils/su.c72
-rw-r--r--loginutils/sulogin.c11
-rw-r--r--mailutils/Config.src (renamed from mailutils/Config.in)12
-rw-r--r--mailutils/Kbuild.src (renamed from mailutils/Kbuild)2
-rw-r--r--mailutils/mail.c7
-rw-r--r--mailutils/mime.c5
-rw-r--r--miscutils/Config.src (renamed from miscutils/Config.in)133
-rw-r--r--miscutils/Kbuild.src (renamed from miscutils/Kbuild)3
-rw-r--r--miscutils/bbconfig.c2
-rw-r--r--miscutils/beep.c4
-rw-r--r--miscutils/chrt.c25
-rw-r--r--miscutils/conspy.c547
-rw-r--r--miscutils/crond.c15
-rw-r--r--miscutils/crontab.c30
-rw-r--r--miscutils/dc.c2
-rw-r--r--miscutils/devfsd.c16
-rw-r--r--miscutils/devmem.c21
-rw-r--r--miscutils/fbsplash.c78
-rw-r--r--miscutils/hdparm.c2
-rw-r--r--miscutils/inotifyd.c2
-rw-r--r--miscutils/ionice.c5
-rw-r--r--miscutils/last.c3
-rw-r--r--miscutils/less.c19
-rw-r--r--miscutils/makedevs.c2
-rw-r--r--miscutils/microcom.c6
-rw-r--r--miscutils/rfkill.c120
-rw-r--r--miscutils/setsid.c25
-rw-r--r--miscutils/taskset.c5
-rw-r--r--miscutils/time.c15
-rw-r--r--miscutils/timeout.c7
-rw-r--r--miscutils/ubi_attach_detach.c88
-rw-r--r--modutils/Config.src (renamed from modutils/Config.in)12
-rw-r--r--modutils/Kbuild.src (renamed from modutils/Kbuild)2
-rw-r--r--modutils/depmod.c84
-rw-r--r--modutils/insmod.c22
-rw-r--r--modutils/lsmod.c27
-rw-r--r--modutils/modinfo.c163
-rw-r--r--modutils/modprobe-small.c15
-rw-r--r--modutils/modprobe.c219
-rw-r--r--modutils/modutils-24.c30
-rw-r--r--modutils/modutils.h41
-rw-r--r--networking/Config.src (renamed from networking/Config.in)245
-rw-r--r--networking/Kbuild.src (renamed from networking/Kbuild)2
-rw-r--r--networking/arp.c2
-rw-r--r--networking/arping.c2
-rw-r--r--networking/brctl.c36
-rw-r--r--networking/dnsd.c124
-rw-r--r--networking/ether-wake.c8
-rw-r--r--networking/ftpd.c46
-rw-r--r--networking/ftpgetput.c2
-rw-r--r--networking/hostname.c10
-rw-r--r--networking/httpd.c18
-rw-r--r--networking/httpd_indexcgi.c2
-rw-r--r--networking/ifconfig.c2
-rw-r--r--networking/ifenslave.c2
-rw-r--r--networking/ifplugd.c226
-rw-r--r--networking/ifupdown.c19
-rw-r--r--networking/inetd.c6
-rw-r--r--networking/interface.c99
-rw-r--r--networking/ip.c62
-rw-r--r--networking/ipcalc.c69
-rw-r--r--networking/libiproute/Kbuild.src (renamed from networking/libiproute/Kbuild)2
-rw-r--r--networking/libiproute/ipaddress.c365
-rw-r--r--networking/libiproute/iplink.c193
-rw-r--r--networking/libiproute/iproute.c204
-rw-r--r--networking/libiproute/iprule.c48
-rw-r--r--networking/libiproute/iptunnel.c24
-rw-r--r--networking/libiproute/libnetlink.c6
-rw-r--r--networking/libiproute/ll_addr.c5
-rw-r--r--networking/nameif.c2
-rw-r--r--networking/nc.c95
-rw-r--r--networking/nc_bloaty.c46
-rw-r--r--networking/netstat.c55
-rw-r--r--networking/ntpd.c18
-rw-r--r--networking/ping.c106
-rw-r--r--networking/route.c2
-rw-r--r--networking/slattach.c2
-rw-r--r--networking/tc.c22
-rw-r--r--networking/tcpudp.c9
-rw-r--r--networking/telnet.c27
-rw-r--r--networking/telnetd.c54
-rw-r--r--networking/tftp.c15
-rw-r--r--networking/udhcp/Config.src (renamed from networking/udhcp/Config.in)21
-rw-r--r--networking/udhcp/Kbuild25
-rw-r--r--networking/udhcp/Kbuild.src21
-rw-r--r--networking/udhcp/arpping.c5
-rw-r--r--networking/udhcp/clientpacket.c272
-rw-r--r--networking/udhcp/clientsocket.c108
-rw-r--r--networking/udhcp/common.c512
-rw-r--r--networking/udhcp/common.h262
-rw-r--r--networking/udhcp/dhcpc.c769
-rw-r--r--networking/udhcp/dhcpc.h23
-rw-r--r--networking/udhcp/dhcpd.c531
-rw-r--r--networking/udhcp/dhcpd.h33
-rw-r--r--networking/udhcp/dhcprelay.c9
-rw-r--r--networking/udhcp/domain_codec.c131
-rw-r--r--networking/udhcp/dumpleases.c15
-rw-r--r--networking/udhcp/files.c281
-rw-r--r--networking/udhcp/leases.c46
-rw-r--r--networking/udhcp/options.c260
-rw-r--r--networking/udhcp/options.h118
-rw-r--r--networking/udhcp/packet.c109
-rw-r--r--networking/udhcp/script.c282
-rw-r--r--networking/udhcp/serverpacket.c283
-rw-r--r--networking/udhcp/signalpipe.c9
-rw-r--r--networking/udhcp/socket.c15
-rw-r--r--networking/udhcp/static_leases.c5
-rw-r--r--networking/wget.c15
-rw-r--r--networking/zcip.c6
-rw-r--r--printutils/Config.src (renamed from printutils/Config.in)8
-rw-r--r--printutils/Kbuild.src (renamed from printutils/Kbuild)0
-rw-r--r--printutils/lpd.c3
-rw-r--r--procps/Config.src (renamed from procps/Config.in)52
-rw-r--r--procps/Kbuild.src (renamed from procps/Kbuild)2
-rw-r--r--procps/free.c91
-rw-r--r--procps/fuser.c286
-rw-r--r--procps/kill.c2
-rw-r--r--procps/pgrep.c7
-rw-r--r--procps/ps.c75
-rw-r--r--procps/smemcap.c129
-rw-r--r--procps/sysctl.c4
-rw-r--r--procps/top.c173
-rw-r--r--procps/watch.c3
-rw-r--r--runit/Config.src (renamed from runit/Config.in)16
-rw-r--r--runit/Kbuild.src (renamed from runit/Kbuild)3
-rw-r--r--runit/chpst.c3
-rw-r--r--runit/runsv.c2
-rw-r--r--runit/runsvdir.c2
-rw-r--r--runit/sv.c2
-rw-r--r--runit/svlogd.c4
-rw-r--r--scripts/Kbuild.src (renamed from scripts/Kbuild)0
-rw-r--r--scripts/Makefile.IMA4
-rw-r--r--scripts/Makefile.build7
-rw-r--r--scripts/Makefile.clean2
-rw-r--r--scripts/basic/docproc.c24
-rw-r--r--scripts/basic/fixdep.c17
-rw-r--r--scripts/basic/split-include.c7
-rwxr-xr-xscripts/bloat-o-meter137
-rw-r--r--scripts/echo.c2
-rwxr-xr-xscripts/gen_build_files.sh96
-rw-r--r--scripts/kconfig/confdata.c5
-rw-r--r--scripts/kconfig/lxdialog/check-lxdialog.sh8
-rw-r--r--scripts/kconfig/mconf.c2
-rw-r--r--scripts/kconfig/util.c2
-rw-r--r--scripts/kconfig/zconf.l3
-rw-r--r--scripts/kconfig/zconf.y6
-rwxr-xr-xscripts/mkconfigs3
-rwxr-xr-xscripts/randomtest138
-rwxr-xr-xscripts/randomtest.loop36
-rwxr-xr-xscripts/test_make_O11
-rwxr-xr-xscripts/test_make_clean14
-rwxr-xr-xscripts/trylink55
-rw-r--r--selinux/Config.src (renamed from selinux/Config.in)2
-rw-r--r--selinux/Kbuild.src (renamed from selinux/Kbuild)2
-rw-r--r--selinux/chcon.c4
-rw-r--r--selinux/runcon.c9
-rw-r--r--selinux/setfiles.c3
-rw-r--r--shell/Config.src (renamed from shell/Config.in)145
-rw-r--r--shell/Kbuild.src (renamed from shell/Kbuild)7
-rw-r--r--shell/README190
-rw-r--r--shell/ash.c855
-rw-r--r--shell/ash_test/ash-misc/nulltick1.right3
-rwxr-xr-xshell/ash_test/ash-misc/nulltick1.tests3
-rw-r--r--shell/ash_test/ash-misc/source2.right1
-rwxr-xr-xshell/ash_test/ash-misc/source2.tests3
-rw-r--r--shell/ash_test/ash-quoting/dollar_repl_slash_bash1.right10
-rwxr-xr-xshell/ash_test/ash-quoting/dollar_repl_slash_bash1.tests21
-rwxr-xr-xshell/ash_test/ash-redir/redir3.tests2
-rwxr-xr-xshell/ash_test/ash-redir/redir7.tests2
-rwxr-xr-xshell/ash_test/ash-redir/redir8.tests2
-rw-r--r--shell/ash_test/ash-redir/redir9.right2
-rwxr-xr-xshell/ash_test/ash-redir/redir9.tests4
-rw-r--r--shell/ash_test/ash-signals/signal4.right4
-rwxr-xr-xshell/ash_test/ash-signals/signal4.tests5
-rw-r--r--shell/ash_test/ash-signals/signal5.right12
-rwxr-xr-xshell/ash_test/ash-signals/signal5.tests14
-rw-r--r--shell/ash_test/ash-signals/signal6.right2
-rwxr-xr-xshell/ash_test/ash-signals/signal6.tests2
-rw-r--r--shell/ash_test/ash-signals/signal7.right1
-rwxr-xr-xshell/ash_test/ash-signals/signal7.tests18
-rw-r--r--shell/ash_test/ash-standalone/var_standalone1.right1
-rwxr-xr-xshell/ash_test/ash-standalone/var_standalone1.tests2
-rw-r--r--shell/ash_test/ash-vars/var_leak.right2
-rwxr-xr-xshell/ash_test/ash-vars/var_leak.tests22
-rw-r--r--shell/builtin_read.c229
-rw-r--r--shell/builtin_read.h42
-rw-r--r--shell/cttyhack.c46
-rw-r--r--shell/hush.c797
-rw-r--r--shell/hush_test/hush-arith/arith.right9
-rwxr-xr-xshell/hush_test/hush-arith/arith.tests19
-rw-r--r--shell/hush_test/hush-parsing/group2.right2
-rwxr-xr-xshell/hush_test/hush-parsing/group2.tests3
-rw-r--r--shell/hush_test/hush-psubst/falsetick.right27
-rwxr-xr-xshell/hush_test/hush-psubst/falsetick.tests22
-rw-r--r--shell/hush_test/hush-trap/signal7.right1
-rwxr-xr-xshell/hush_test/hush-trap/signal7.tests18
-rw-r--r--shell/hush_test/hush-vars/param_expand_alt.right2
-rwxr-xr-xshell/hush_test/hush-vars/param_expand_alt.tests4
-rw-r--r--shell/hush_test/hush-vars/param_expand_bash_substring.right64
-rwxr-xr-xshell/hush_test/hush-vars/param_expand_bash_substring.tests83
-rw-r--r--shell/hush_test/hush-vars/param_expand_indicate_error.right15
-rwxr-xr-xshell/hush_test/hush-vars/param_expand_indicate_error.tests20
-rw-r--r--shell/hush_test/hush-vars/param_expand_len.right5
-rwxr-xr-xshell/hush_test/hush-vars/param_expand_len.tests7
-rw-r--r--shell/hush_test/hush-vars/var3.right2
-rw-r--r--shell/hush_test/hush-vars/var_posix1.right7
-rwxr-xr-xshell/hush_test/hush-vars/var_posix1.tests10
-rw-r--r--shell/hush_test/hush-vars/var_unbackslash.right9
-rwxr-xr-xshell/hush_test/hush-vars/var_unbackslash.tests20
-rw-r--r--shell/lash_unused.c1571
-rw-r--r--shell/msh_unused.c5335
-rw-r--r--shell/shell_common.c425
-rw-r--r--shell/shell_common.h20
-rw-r--r--sysklogd/Config.src (renamed from sysklogd/Config.in)28
-rw-r--r--sysklogd/Kbuild.src (renamed from sysklogd/Kbuild)2
-rw-r--r--sysklogd/logread.c2
-rw-r--r--sysklogd/syslogd.c90
-rwxr-xr-xtestsuite/ar.tests27
-rwxr-xr-xtestsuite/ash.tests83
-rwxr-xr-xtestsuite/awk.tests130
-rwxr-xr-xtestsuite/busybox.tests7
-rwxr-xr-xtestsuite/cal.tests38
-rw-r--r--testsuite/cp/cp-parents1
-rwxr-xr-xtestsuite/cpio.tests49
-rw-r--r--testsuite/cut/cut-cuts-a-field2
-rw-r--r--testsuite/date/date-R-works9
-rw-r--r--testsuite/date/date-works-12
-rwxr-xr-xtestsuite/diff.tests41
-rw-r--r--testsuite/du/du-h-works8
-rw-r--r--testsuite/du/du-k-works8
-rw-r--r--testsuite/du/du-l-works12
-rw-r--r--testsuite/du/du-m-works8
-rw-r--r--testsuite/du/du-s-works6
-rw-r--r--testsuite/du/du-works6
-rw-r--r--testsuite/echo/echo-does-not-print-newline2
-rw-r--r--testsuite/echo/echo-prints-slash-zero2
-rwxr-xr-xtestsuite/expand.tests9
-rw-r--r--testsuite/expand/expand-works-like-GNU10
-rw-r--r--testsuite/find/find-supports-minus-xdev2
-rwxr-xr-xtestsuite/fold.tests7
-rwxr-xr-xtestsuite/grep.tests10
-rw-r--r--testsuite/hostid/hostid-works10
-rw-r--r--testsuite/hostname/hostname-d-works5
-rw-r--r--testsuite/ls.mk_uni_tests111
-rwxr-xr-xtestsuite/ls.tests257
-rw-r--r--testsuite/ls/ls-1-works2
-rw-r--r--testsuite/ls/ls-h-works2
-rwxr-xr-xtestsuite/makedevs.tests2
-rw-r--r--testsuite/md5sum/md5sum-verifies-non-binary-file2
-rwxr-xr-xtestsuite/mdev.tests32
-rwxr-xr-xtestsuite/mount.tests15
-rwxr-xr-xtestsuite/od.tests2
-rwxr-xr-xtestsuite/patch.tests76
-rwxr-xr-xtestsuite/pidof.tests4
-rwxr-xr-xtestsuite/runtest17
-rwxr-xr-xtestsuite/rx.tests4
-rwxr-xr-xtestsuite/sed.tests52
-rwxr-xr-xtestsuite/sort.tests2
-rw-r--r--testsuite/tail/tail-works2
-rwxr-xr-xtestsuite/tar.tests89
-rw-r--r--testsuite/tar/tar_with_link_with_size2
-rw-r--r--testsuite/tar/tar_with_prefix_fields3
-rw-r--r--[-rwxr-xr-x]testsuite/testing.sh18
-rwxr-xr-xtestsuite/tr.tests6
-rw-r--r--testsuite/tr/tr-d-alnum-works2
-rw-r--r--testsuite/tr/tr-rejects-wrong-class2
-rw-r--r--testsuite/tr/tr-works4
-rwxr-xr-xtestsuite/unexpand.tests10
-rwxr-xr-xtestsuite/xargs.tests15
-rw-r--r--util-linux/Config.src (renamed from util-linux/Config.in)583
-rw-r--r--util-linux/Kbuild.src (renamed from util-linux/Kbuild)4
-rw-r--r--util-linux/acpid.c18
-rw-r--r--util-linux/fdisk.c412
-rw-r--r--util-linux/fdisk_sun.c2
-rw-r--r--util-linux/flock.c87
-rw-r--r--util-linux/fsck_minix.c9
-rw-r--r--util-linux/hexdump.c4
-rw-r--r--util-linux/hwclock.c119
-rw-r--r--util-linux/losetup.c61
-rw-r--r--util-linux/lspci.c14
-rw-r--r--util-linux/lsusb.c46
-rw-r--r--util-linux/mdev.c116
-rw-r--r--util-linux/mkfs_ext2.c40
-rw-r--r--util-linux/mkfs_minix.c2
-rw-r--r--util-linux/mkfs_reiser.c22
-rw-r--r--util-linux/mkfs_vfat.c28
-rw-r--r--util-linux/mkswap.c18
-rw-r--r--util-linux/more.c6
-rw-r--r--util-linux/mount.c49
-rw-r--r--util-linux/readprofile.c6
-rw-r--r--util-linux/rev.c121
-rw-r--r--util-linux/rtcwake.c5
-rw-r--r--util-linux/script.c9
-rw-r--r--util-linux/swaponoff.c19
-rw-r--r--util-linux/umount.c33
-rw-r--r--util-linux/volume_id/Kbuild.src (renamed from util-linux/volume_id/Kbuild)2
-rw-r--r--util-linux/volume_id/fat.c18
-rw-r--r--util-linux/volume_id/linux_raid.c3
-rw-r--r--util-linux/volume_id/linux_swap.c6
-rw-r--r--util-linux/volume_id/unused_msdos.c6
535 files changed, 26238 insertions, 19313 deletions
diff --git a/.gitignore b/.gitignore
index b7840e494..7d2cca67c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,12 +3,14 @@
#
.*
*.o
*.o.*
*.a
*.s
+Kbuild
+Config.in
#
# Never ignore these
#
!.gitignore
diff --git a/Config.in b/Config.in
index 8e751530c..fe64f2b3f 100644
--- a/Config.in
+++ b/Config.in
@@ -12,13 +12,13 @@ config HAVE_DOT_CONFIG
menu "Busybox Settings"
menu "General Configuration"
config DESKTOP
bool "Enable options for full-blown desktop systems"
- default n
+ default y
help
Enable options and features which are not essential.
Select this only if you plan to use busybox on full-blown
desktop machine with common Linux distro, not on an embedded box.
config EXTRA_COMPAT
@@ -79,14 +79,14 @@ config SHOW_USAGE
wrong arguments. You can turn off printing these terse usage
messages if you say no here.
This will save you up to 7k.
config FEATURE_VERBOSE_USAGE
bool "Show verbose applet usage messages"
- default n
- select SHOW_USAGE
+ default y
+ depends on SHOW_USAGE
help
All BusyBox applets will show more verbose help messages when
busybox is invoked with --help. This will add a lot of text to the
busybox binary. In the default configuration, this will add about
13k, but it can add much more depending on your configuration.
@@ -103,47 +103,141 @@ config FEATURE_COMPRESS_USAGE
be noticeable. Also, if you run executables directly from ROM
and have very little memory, this might not be a win. Otherwise,
you probably want this.
config FEATURE_INSTALLER
bool "Support --install [-s] to install applet links at runtime"
- default n
+ default y
help
Enable 'busybox --install [-s]' support. This will allow you to use
busybox at runtime to create hard links or symlinks for all the
applets that are compiled into busybox.
config LOCALE_SUPPORT
bool "Enable locale support (system needs locale for this to work)"
default n
help
Enable this if your system has locale support and you would like
busybox to support locale settings.
-config FEATURE_ASSUME_UNICODE
+config UNICODE_SUPPORT
bool "Support Unicode"
- default n
+ default y
help
This makes various applets aware that one byte is not
one character on screen.
Busybox aims to eventually work correctly with Unicode displays.
Any older encodings are not guaranteed to work.
Probably by the time when busybox will be fully Unicode-clean,
other encodings will be mainly of historic interest.
+config UNICODE_USING_LOCALE
+ bool "Use libc routines for Unicode (else uses internal ones)"
+ default n
+ depends on UNICODE_SUPPORT && LOCALE_SUPPORT
+ help
+ With this option on, Unicode support is implemented using libc
+ routines. Otherwise, internal implementation is used.
+ Internal implementation is smaller.
+
config FEATURE_CHECK_UNICODE_IN_ENV
bool "Check $LANG environment variable"
- default y
- depends on FEATURE_ASSUME_UNICODE && !LOCALE_SUPPORT
+ default n
+ depends on UNICODE_SUPPORT && !UNICODE_USING_LOCALE
help
With this option on, Unicode support is activated
only if LANG variable has the value of the form "xxxx.utf8"
Otherwise, Unicode support will be always enabled and active.
+config SUBST_WCHAR
+ int "Character code to substitute unprintable characters with"
+ depends on UNICODE_SUPPORT
+ default 63
+ help
+ Typical values are 63 for '?' (works with any output device),
+ 30 for ASCII substitute control code,
+ 65533 (0xfffd) for Unicode replacement character.
+
+config LAST_SUPPORTED_WCHAR
+ int "Range of supported Unicode characters"
+ depends on UNICODE_SUPPORT
+ default 767
+ help
+ Any character with Unicode value bigger than this is assumed
+ to be non-printable on output device. Many applets replace
+ such chars with substitution character.
+
+ The idea is that many valid printable Unicode chars are
+ nevertheless are not displayed correctly. Think about
+ combining charachers, double-wide hieroglyphs, obscure
+ characters in dozens of ancient scripts...
+ Many terminals, terminal emulators, xterms etc will fail
+ to handle them correctly. Choose the smallest value
+ which suits your needs.
+
+ Typical values are:
+ 126 - ASCII only
+ 767 (0x2ff) - there are no combining chars in [0..767] range
+ (the range includes Latin 1, Latin Ext. A and B),
+ code is ~700 bytes smaller for this case.
+ 4351 (0x10ff) - there are no double-wide chars in [0..4351] range,
+ code is ~300 bytes smaller for this case.
+ 12799 (0x31ff) - nearly all non-ideographic characters are
+ available in [0..12799] range, including
+ East Asian scripts like katakana, hiragana, hangul,
+ bopomofo...
+ 0 - off, any valid printable Unicode character will be printed.
+
+config UNICODE_COMBINING_WCHARS
+ bool "Allow zero-width Unicode characters on output"
+ default n
+ depends on UNICODE_SUPPORT
+ help
+ With this option off, any Unicode char with width of 0
+ is substituted on output.
+
+config UNICODE_WIDE_WCHARS
+ bool "Allow wide Unicode characters on output"
+ default n
+ depends on UNICODE_SUPPORT
+ help
+ With this option off, any Unicode char with width > 1
+ is substituted on output.
+
+config UNICODE_BIDI_SUPPORT
+ bool "Bidirectional character-aware line input"
+ default n
+ depends on UNICODE_SUPPORT && !UNICODE_USING_LOCALE
+ help
+ With this option on, right-to-left Unicode characters
+ are treated differently on input (e.g. cursor movement).
+
+config UNICODE_NEUTRAL_TABLE
+ bool "In bidi input, support non-ASCII neutral chars too"
+ default n
+ depends on UNICODE_BIDI_SUPPORT
+ help
+ In most cases it's enough to treat only ASCII non-letters
+ (i.e. punctuation, numbers and space) as characters
+ with neutral directionality.
+ With this option on, more extensive (and bigger) table
+ of neutral chars will be used.
+
+config UNICODE_PRESERVE_BROKEN
+ bool "Make it possible to enter sequences of chars which are not Unicode"
+ default n
+ depends on UNICODE_SUPPORT
+ help
+ With this option on, invalid UTF-8 bytes are not substituted
+ with the selected substitution character.
+ For example, this means that entering 'l', 's', ' ', 0xff, [Enter]
+ at shell prompt will list file named 0xff (single char name
+ with char value 255), not file named '?'.
+
config LONG_OPTS
bool "Support for --long-options"
default y
help
Enable this if you want busybox applets to use the gnu --long-option
style, in addition to single character -a -b -c style options.
@@ -167,22 +261,42 @@ config FEATURE_CLEAN_UP
space since the OS will clean up for us, but it can confuse debuggers
like valgrind, which report tons of memory and resource leaks.
Don't enable this unless you have a really good reason to clean
things up manually.
+config FEATURE_UTMP
+ bool "Support utmp file"
+ default y
+ help
+ The file /var/run/utmp is used to track who is currently logged in.
+ With this option on, certain applets (getty, login, telnetd etc)
+ will create and delete entries there.
+ "who" applet requires this option.
+
+config FEATURE_WTMP
+ bool "Support wtmp file"
+ default y
+ select FEATURE_UTMP
+ help
+ The file /var/run/wtmp is used to track when users have logged into
+ and logged out of the system.
+ With this option on, certain applets (getty, login, telnetd etc)
+ will append new entries there.
+ "last" applet requires this option.
+
config FEATURE_PIDFILE
bool "Support writing pidfiles"
- default n
+ default y
help
This option makes some applets (e.g. crond, syslogd, inetd) write
a pidfile in /var/run. Some applications rely on them.
config FEATURE_SUID
bool "Support for SUID/SGID handling"
- default n
+ default y
help
With this option you can install the busybox binary belonging
to root with the suid bit set, and it will automatically drop
priviledges for applets that don't need root access.
If you are really paranoid and don't want to do this, build two
@@ -193,13 +307,13 @@ config FEATURE_SUID
crontab, dnsd, findfs, ipcrm, ipcs, login, passwd, ping, su,
traceroute, vlock.
config FEATURE_SUID_CONFIG
bool "Runtime SUID/SGID configuration via /etc/busybox.conf"
- default n if FEATURE_SUID
+ default y if FEATURE_SUID
depends on FEATURE_SUID
help
Allow the SUID / SGID state of an applet to be determined at runtime
by checking /etc/busybox.conf. (This is sort of a poor man's sudo.)
The format of this file is as follows:
@@ -412,13 +526,13 @@ config FEATURE_SHARED_BUSYBOX
### such as gcc-4.1 and above.
###
### Say 'N' unless you know what you are doing.
config LFS
bool "Build with Large File Support (for accessing files > 2 GB)"
- default n
+ default y
select FDISK_SUPPORT_LARGE_DISKS
help
If you want to build BusyBox with large file support, then enable
this option. This will have no effect if your kernel or your C
library lacks large file support for large files. Some of the
programs that can benefit from large file support include dd, gzip,
diff --git a/Makefile b/Makefile
index 206555850..3562832e5 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,9 @@
VERSION = 1
-PATCHLEVEL = 16
-SUBLEVEL = 0
+PATCHLEVEL = 17
+SUBLEVEL = 4
EXTRAVERSION =
NAME = Unnamed
# *DOCUMENTATION*
# To see a list of typical targets execute "make help"
# More info can be located in ./README
@@ -355,17 +355,22 @@ PHONY += scripts_basic
scripts_basic:
$(Q)$(MAKE) $(build)=scripts/basic
# To avoid any implicit rule to kick in, define an empty command.
scripts/basic/%: scripts_basic ;
+# This target generates Kbuild's and Config.in's from *.c files
+PHONY += gen_build_files
+gen_build_files: $(wildcard $(srctree)/*/*.c) $(wildcard $(srctree)/*/*/*.c)
+ $(Q)$(srctree)/scripts/gen_build_files.sh $(srctree) $(objtree)
+
# bbox: we have helpers in applets/
# we depend on scripts_basic, since scripts/basic/fixdep
# must be built before any other host prog
PHONY += applets_dir
-applets_dir: scripts_basic
+applets_dir: scripts_basic gen_build_files
$(Q)$(MAKE) $(build)=applets
applets/%: applets_dir ;
PHONY += outputmakefile
# outputmakefile generates a Makefile in the output directory, if using a
@@ -425,28 +430,33 @@ ifeq ($(config-targets),1)
# Read arch specific Makefile to set KBUILD_DEFCONFIG as needed.
# KBUILD_DEFCONFIG may point out an alternative default configuration
# used for 'make defconfig'
-include $(srctree)/arch/$(ARCH)/Makefile
export KBUILD_DEFCONFIG
-config %config: scripts_basic outputmakefile FORCE
+config: scripts_basic outputmakefile gen_build_files FORCE
+ $(Q)mkdir -p include
+ $(Q)$(MAKE) $(build)=scripts/kconfig $@
+ $(Q)$(MAKE) -C $(srctree) KBUILD_SRC= .kernelrelease
+
+%config: scripts_basic outputmakefile gen_build_files FORCE
$(Q)mkdir -p include
$(Q)$(MAKE) $(build)=scripts/kconfig $@
$(Q)$(MAKE) -C $(srctree) KBUILD_SRC= .kernelrelease
else
# ===========================================================================
# Build targets only - this includes busybox, arch specific targets, clean
# targets and others. In general all targets except *config targets.
ifeq ($(KBUILD_EXTMOD),)
# Additional helpers built in scripts/
# Carefully list dependencies so we do not try to build scripts twice
-# in parrallel
+# in parallel
PHONY += scripts
-scripts: scripts_basic include/config/MARKER
+scripts: gen_build_files scripts_basic include/config/MARKER
$(Q)$(MAKE) $(build)=$(@)
scripts_basic: include/autoconf.h
# Objects we will link into busybox / subdirs we need to visit
core-y := \
@@ -501,15 +511,17 @@ ifeq ($(dot-config),1)
include $(srctree)/Makefile.flags
# If .config is newer than include/autoconf.h, someone tinkered
# with it and forgot to run make oldconfig.
# If kconfig.d is missing then we are probarly in a cleaned tree so
# we execute the config step to be sure to catch updated Kconfig files
-include/autoconf.h: .kconfig.d .config
+include/autoconf.h: .kconfig.d .config $(wildcard $(srctree)/*/*.c) $(wildcard $(srctree)/*/*/*.c) | gen_build_files
$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
+include/usage.h: gen_build_files
+
else
# Dummy target needed, because used as prerequisite
include/autoconf.h: ;
endif
# The all: target is the default when no target is given on the
@@ -993,12 +1005,14 @@ PHONY += $(mrproper-dirs) mrproper archmrproper
$(mrproper-dirs):
$(Q)$(MAKE) $(clean)=$(patsubst _mrproper_%,%,$@)
mrproper: clean archmrproper $(mrproper-dirs)
$(call cmd,rmdirs)
$(call cmd,rmfiles)
+ @find -name Config.src | sed 's/.src$$/.in/' | xargs -r rm -f
+ @find -name Kbuild.src | sed 's/.src$$//' | xargs -r rm -f
# distclean
#
PHONY += distclean
distclean: mrproper
@@ -1273,15 +1287,19 @@ endif
%.s: %.S prepare scripts FORCE
$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.o: %.S prepare scripts FORCE
$(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
$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
$(build)=$(build-dir) $(@:.ko=.o)
$(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
# FIXME Should go into a make.lib or something
diff --git a/Makefile.custom b/Makefile.custom
index fb9ec671c..01d69ddf8 100644
--- a/Makefile.custom
+++ b/Makefile.custom
@@ -1,11 +1,11 @@
# ==========================================================================
# Build system
# ==========================================================================
-busybox.links: $(srctree)/applets/busybox.mkll $(objtree)/include/autoconf.h $(srctree)/include/applets.h
+busybox.links: $(srctree)/applets/busybox.mkll $(objtree)/include/autoconf.h include/applets.h
$(Q)-$(SHELL) $^ >$@
.PHONY: install
ifeq ($(CONFIG_INSTALL_APPLET_SYMLINKS),y)
INSTALL_OPTS:= --symlinks
endif
@@ -61,12 +61,16 @@ release: distclean
rm -r -f busybox-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION); \
cp -pPR busybox busybox-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) && { \
find busybox-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)/ -type d \
-name .svn \
-print \
-exec rm -r -f {} \; ; \
+ find busybox-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)/ -type d \
+ -name .git \
+ -print \
+ -exec rm -r -f {} \; ; \
find busybox-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)/ -type f \
-name .\#* \
-print \
-exec rm -f {} \; ; \
tar -czf busybox-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION).tar.gz \
busybox-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)/ ; }
@@ -111,13 +115,13 @@ doc: docs/busybox.pod docs/BusyBox.txt docs/BusyBox.1 docs/BusyBox.html
silent_cmd_doc =
disp_doc = $($(quiet)cmd_doc)
# sed adds newlines after "Options:" etc,
# this is needed in order to get good BusyBox.{1,txt,html}
docs/busybox.pod: $(srctree)/docs/busybox_header.pod \
- $(srctree)/include/usage.h \
+ include/usage.h \
$(srctree)/docs/busybox_footer.pod \
applets/usage_pod
$(disp_doc)
$(Q)-mkdir -p docs
$(Q)-( \
cat $(srctree)/docs/busybox_header.pod; \
diff --git a/Makefile.flags b/Makefile.flags
index 032f6c135..60bb888d8 100644
--- a/Makefile.flags
+++ b/Makefile.flags
@@ -37,12 +37,13 @@ CFLAGS += $(call cc-option,-Werror,)
## const char *ptr; ... off_t v = *(off_t*)ptr; -> BOOM
## and no easy way to convince it to shut the hell up.
## We have a lot of such things all over the place.
## Classic *(off_t*)(void*)ptr does not work,
## and I am unwilling to do crazy gcc specific ({ void *ppp = ...; })
## stuff in macros. This would obfuscate the code too much.
+## Maybe try __attribute__((__may_alias__))?
#CFLAGS += $(call cc-ifversion, -eq, 0404, -fno-strict-aliasing)
endif
# gcc 3.x emits bogus "old style proto" warning on find.c:alloc_action()
CFLAGS += $(call cc-ifversion, -ge, 0400, -Wold-style-definition)
CFLAGS += $(call cc-option,-fno-builtin-strlen -finline-limit=0 -fomit-frame-pointer -ffunction-sections -fdata-sections,)
diff --git a/README b/README
index 318d44708..3a9d849a6 100644
--- a/README
+++ b/README
@@ -63,13 +63,13 @@ Downloading the current source code:
be downloaded from
http://busybox.net/downloads/
You can browse the up to the minute source code and change history online.
- http://www.busybox.net/cgi-bin/viewcvs.cgi/trunk/busybox/
+ http://git.busybox.net/busybox/
Anonymous GIT access is available. For instructions, check out:
http://www.busybox.net/source.html
For those that are actively contributing and would like to check files in,
@@ -80,25 +80,25 @@ Downloading the current source code:
The developers also have a bug and patch tracking system
(https://bugs.busybox.net) although posting a bug/patch to the mailing list
is generally a faster way of getting it fixed, and the complete archive of
what happened is the subversion changelog.
Note: if you want to compile busybox in a busybox environment you must
- select ENABLE_DESKTOP.
+ select CONFIG_DESKTOP.
----------------
-getting help:
+Getting help:
when you find you need help, you can check out the busybox mailing list
archives at http://busybox.net/lists/busybox/ or even join
the mailing list if you are interested.
----------------
-bugs:
+Bugs:
if you find bugs, please submit a detailed bug report to the busybox mailing
list at busybox@busybox.net. a well-written bug report should include a
transcript of a shell session that demonstrates the bad behavior and enables
anyone else to duplicate the bug on their own machine. the following is such
an example:
@@ -191,9 +191,14 @@ Supported hardware:
we believe 2.6.x kernel module loading support should work on all
architectures supported by the kernel.
----------------
Please feed suggestions, bug reports, insults, and bribes back to the busybox
-maintainer:
+mailing list:
+
+ busybox@busybox.net
+
+and/or maintainer:
+
Denys Vlasenko
- <vda.linux@googlemail.com>
+ <vda.linux@googlemail.com>
diff --git a/TODO_config_nommu b/TEST_config_nommu
index 804fc61c9..911f02f6b 100644
--- a/TODO_config_nommu
+++ b/TEST_config_nommu
@@ -1,31 +1,33 @@
#
# Automatically generated make config: don't edit
-# Busybox version: 1.15.0.svn
-# Fri Aug 21 00:13:18 2009
+# Busybox version: 1.16.0
+# Wed Jan 27 21:01:26 2010
#
CONFIG_HAVE_DOT_CONFIG=y
#
# Busybox Settings
#
#
# General Configuration
#
CONFIG_DESKTOP=y
CONFIG_EXTRA_COMPAT=y
+CONFIG_INCLUDE_SUSv2=y
+# CONFIG_USE_PORTABLE_CODE is not set
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=y
CONFIG_FEATURE_COMPRESS_USAGE=y
CONFIG_FEATURE_INSTALLER=y
# CONFIG_LOCALE_SUPPORT is not set
-# CONFIG_FEATURE_ASSUME_UNICODE is not set
+# CONFIG_UNICODE_SUPPORT is not set
# CONFIG_FEATURE_CHECK_UNICODE_IN_ENV is not set
CONFIG_LONG_OPTS=y
CONFIG_FEATURE_DEVPTS=y
# CONFIG_FEATURE_CLEAN_UP is not set
CONFIG_FEATURE_PIDFILE=y
CONFIG_FEATURE_SUID=y
@@ -56,13 +58,12 @@ CONFIG_EXTRA_CFLAGS=""
# 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=y
#
# Installation Options
#
# CONFIG_INSTALL_NO_USR is not set
CONFIG_INSTALL_APPLET_SYMLINKS=y
@@ -117,12 +118,13 @@ CONFIG_FEATURE_CPIO_O=y
CONFIG_FEATURE_CPIO_P=y
CONFIG_DPKG=y
CONFIG_DPKG_DEB=y
CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY=y
CONFIG_GUNZIP=y
CONFIG_GZIP=y
+CONFIG_FEATURE_GZIP_LONG_OPTIONS=y
CONFIG_LZOP=y
CONFIG_LZOP_COMPR_HIGH=y
CONFIG_RPM2CPIO=y
CONFIG_RPM=y
CONFIG_TAR=y
CONFIG_FEATURE_TAR_CREATE=y
@@ -130,12 +132,13 @@ CONFIG_FEATURE_TAR_AUTODETECT=y
CONFIG_FEATURE_TAR_FROM=y
CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY=y
CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY=y
CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y
CONFIG_FEATURE_TAR_LONG_OPTIONS=y
CONFIG_FEATURE_TAR_UNAME_GNAME=y
+CONFIG_FEATURE_TAR_NOPRESERVE_TIME=y
CONFIG_UNCOMPRESS=y
CONFIG_UNLZMA=y
CONFIG_FEATURE_LZMA_FAST=y
CONFIG_UNZIP=y
#
@@ -145,21 +148,25 @@ CONFIG_BASENAME=y
CONFIG_CAL=y
CONFIG_CAT=y
CONFIG_CATV=y
CONFIG_CHGRP=y
CONFIG_CHMOD=y
CONFIG_CHOWN=y
+CONFIG_FEATURE_CHOWN_LONG_OPTIONS=y
CONFIG_CHROOT=y
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_FEATURE_DATE_COMPAT=y
CONFIG_DD=y
CONFIG_FEATURE_DD_SIGNAL_HANDLING=y
+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
@@ -268,13 +275,13 @@ CONFIG_FEATURE_AUTOWIDTH=y
#
# Common options for df, du, ls
#
CONFIG_FEATURE_HUMAN_READABLE=y
#
-# Common options for md5sum, sha1sum
+# Common options for md5sum, sha1sum, sha256sum, sha512sum
#
CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y
#
# Console Utilities
#
@@ -315,15 +322,14 @@ CONFIG_WHICH=y
# Editors
#
CONFIG_AWK=y
CONFIG_FEATURE_AWK_LIBM=y
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=y
CONFIG_ED=y
CONFIG_PATCH=y
CONFIG_SED=y
CONFIG_VI=y
CONFIG_FEATURE_VI_MAX_LEN=4096
CONFIG_FEATURE_VI_8BIT=y
@@ -361,12 +367,13 @@ CONFIG_FEATURE_FIND_PAREN=y
CONFIG_FEATURE_FIND_SIZE=y
CONFIG_FEATURE_FIND_PRUNE=y
CONFIG_FEATURE_FIND_DELETE=y
CONFIG_FEATURE_FIND_PATH=y
CONFIG_FEATURE_FIND_REGEX=y
CONFIG_FEATURE_FIND_CONTEXT=y
+CONFIG_FEATURE_FIND_LINKS=y
CONFIG_GREP=y
CONFIG_FEATURE_GREP_EGREP_ALIAS=y
CONFIG_FEATURE_GREP_FGREP_ALIAS=y
CONFIG_FEATURE_GREP_CONTEXT=y
CONFIG_XARGS=y
CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION=y
@@ -450,12 +457,13 @@ CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=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 is not set
@@ -485,42 +493,47 @@ CONFIG_FEATURE_SGI_LABEL=y
CONFIG_FEATURE_SUN_LABEL=y
CONFIG_FEATURE_OSF_LABEL=y
CONFIG_FEATURE_FDISK_ADVANCED=y
CONFIG_FINDFS=y
CONFIG_FREERAMDISK=y
CONFIG_FSCK_MINIX=y
+CONFIG_MKFS_EXT2=y
CONFIG_MKFS_MINIX=y
#
# Minix filesystem support
#
CONFIG_FEATURE_MINIX2=y
+CONFIG_MKFS_REISER=y
CONFIG_MKFS_VFAT=y
CONFIG_GETOPT=y
CONFIG_FEATURE_GETOPT_LONG=y
CONFIG_HEXDUMP=y
CONFIG_FEATURE_HEXDUMP_REVERSE=y
CONFIG_HD=y
CONFIG_HWCLOCK=y
CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS=y
CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS=y
CONFIG_IPCRM=y
CONFIG_IPCS=y
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_MKSWAP=y
CONFIG_FEATURE_MKSWAP_UUID=y
CONFIG_MORE=y
CONFIG_FEATURE_USE_TERMIOS=y
CONFIG_VOLUMEID=y
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
@@ -592,12 +605,13 @@ CONFIG_FEATURE_DC_LIBM=y
# CONFIG_DEVFSD_VERBOSE is not set
# CONFIG_FEATURE_DEVFS is not set
CONFIG_DEVMEM=y
CONFIG_EJECT=y
CONFIG_FEATURE_EJECT_SCSI=y
CONFIG_FBSPLASH=y
+CONFIG_FLASHCP=y
# CONFIG_FLASH_LOCK is not set
# CONFIG_FLASH_UNLOCK is not set
# CONFIG_FLASH_ERASEALL is not set
CONFIG_IONICE=y
CONFIG_INOTIFYD=y
CONFIG_LAST=y
@@ -635,12 +649,13 @@ CONFIG_STRINGS=y
CONFIG_TASKSET=y
CONFIG_FEATURE_TASKSET_FANCY=y
CONFIG_TIME=y
CONFIG_TIMEOUT=y
CONFIG_TTYSIZE=y
CONFIG_VOLNAME=y
+CONFIG_WALL=y
CONFIG_WATCHDOG=y
#
# Networking Utilities
#
CONFIG_FEATURE_IPV6=y
@@ -654,12 +669,13 @@ CONFIG_FEATURE_BRCTL_FANCY=y
CONFIG_FEATURE_BRCTL_SHOW=y
CONFIG_DNSD=y
CONFIG_ETHER_WAKE=y
CONFIG_FAKEIDENTD=y
CONFIG_FTPD=y
CONFIG_FEATURE_FTP_WRITE=y
+CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST=y
CONFIG_FTPGET=y
CONFIG_FTPPUT=y
CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS=y
CONFIG_HOSTNAME=y
CONFIG_HTTPD=y
CONFIG_FEATURE_HTTPD_RANGES=y
@@ -719,30 +735,35 @@ CONFIG_NC=y
CONFIG_NC_SERVER=y
CONFIG_NC_EXTRA=y
CONFIG_NETSTAT=y
CONFIG_FEATURE_NETSTAT_WIDE=y
CONFIG_FEATURE_NETSTAT_PRG=y
CONFIG_NSLOOKUP=y
+CONFIG_NTPD=y
+CONFIG_FEATURE_NTPD_SERVER=y
CONFIG_PING=y
CONFIG_PING6=y
CONFIG_FEATURE_FANCY_PING=y
CONFIG_PSCAN=y
CONFIG_ROUTE=y
CONFIG_SLATTACH=y
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=y
CONFIG_TFTP=y
CONFIG_TFTPD=y
CONFIG_FEATURE_TFTP_GET=y
CONFIG_FEATURE_TFTP_PUT=y
CONFIG_FEATURE_TFTP_BLOCKSIZE=y
+CONFIG_FEATURE_TFTP_PROGRESS_BAR=y
CONFIG_TFTP_DEBUG=y
CONFIG_TRACEROUTE=y
+CONFIG_TRACEROUTE6=y
CONFIG_FEATURE_TRACEROUTE_VERBOSE=y
CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE=y
CONFIG_FEATURE_TRACEROUTE_USE_ICMP=y
CONFIG_UDHCPD=y
CONFIG_DHCPRELAY=y
CONFIG_DUMPLEASES=y
@@ -810,12 +831,13 @@ 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=y
CONFIG_FEATURE_TOP_SMP_PROCESS=y
CONFIG_FEATURE_TOPMEM=y
+CONFIG_FEATURE_SHOW_THREADS=y
CONFIG_UPTIME=y
CONFIG_WATCH=y
#
# Runit Utilities
#
@@ -878,12 +900,13 @@ CONFIG_HUSH_TICK=y
CONFIG_HUSH_IF=y
CONFIG_HUSH_LOOPS=y
CONFIG_HUSH_CASE=y
CONFIG_HUSH_FUNCTIONS=y
CONFIG_HUSH_LOCAL=y
CONFIG_HUSH_EXPORT_N=y
+CONFIG_HUSH_RANDOM_SUPPORT=y
CONFIG_LASH=y
CONFIG_MSH=y
CONFIG_SH_MATH_SUPPORT=y
CONFIG_SH_MATH_SUPPORT_64=y
CONFIG_FEATURE_SH_EXTRA_QUIET=y
CONFIG_FEATURE_SH_STANDALONE=y
diff --git a/TEST_config_noprintf b/TEST_config_noprintf
new file mode 100644
index 000000000..ba003a1fb
--- /dev/null
+++ b/TEST_config_noprintf
@@ -0,0 +1,929 @@
+#
+# Automatically generated make config: don't edit
+# Busybox version: 1.17.0.git
+# Mon Jun 7 13:37:55 2010
+#
+CONFIG_HAVE_DOT_CONFIG=y
+
+#
+# Busybox Settings
+#
+
+#
+# General Configuration
+#
+CONFIG_DESKTOP=y
+CONFIG_EXTRA_COMPAT=y
+CONFIG_INCLUDE_SUSv2=y
+# CONFIG_USE_PORTABLE_CODE is not set
+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=y
+# CONFIG_FEATURE_COMPRESS_USAGE is not set
+# CONFIG_FEATURE_INSTALLER is not set
+# CONFIG_LOCALE_SUPPORT is not set
+CONFIG_UNICODE_SUPPORT=y
+# CONFIG_UNICODE_USING_LOCALE is not set
+CONFIG_FEATURE_CHECK_UNICODE_IN_ENV=y
+CONFIG_SUBST_WCHAR=63
+CONFIG_LAST_SUPPORTED_WCHAR=65535
+CONFIG_UNICODE_COMBINING_WCHARS=y
+CONFIG_UNICODE_WIDE_WCHARS=y
+CONFIG_UNICODE_BIDI_SUPPORT=y
+# CONFIG_UNICODE_NEUTRAL_TABLE is not set
+CONFIG_UNICODE_PRESERVE_BROKEN=y
+CONFIG_LONG_OPTS=y
+CONFIG_FEATURE_DEVPTS=y
+# CONFIG_FEATURE_CLEAN_UP is not set
+CONFIG_FEATURE_UTMP=y
+CONFIG_FEATURE_WTMP=y
+CONFIG_FEATURE_PIDFILE=y
+# CONFIG_FEATURE_SUID is not set
+# CONFIG_FEATURE_SUID_CONFIG is not set
+# CONFIG_FEATURE_SUID_CONFIG_QUIET is not set
+# CONFIG_SELINUX is not set
+# CONFIG_FEATURE_PREFER_APPLETS is not set
+CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe"
+# CONFIG_FEATURE_SYSLOG is not set
+# CONFIG_FEATURE_HAVE_RPC is not set
+
+#
+# Build Options
+#
+CONFIG_STATIC=y
+# CONFIG_PIE is not set
+# CONFIG_NOMMU is not set
+# CONFIG_BUILD_LIBBUSYBOX is not set
+# CONFIG_FEATURE_INDIVIDUAL is not set
+# CONFIG_FEATURE_SHARED_BUSYBOX is not set
+CONFIG_LFS=y
+CONFIG_CROSS_COMPILER_PREFIX="i486-linux-uclibc-"
+CONFIG_EXTRA_CFLAGS=""
+
+#
+# Debugging Options
+#
+# CONFIG_DEBUG is not set
+# CONFIG_DEBUG_PESSIMIZE is not set
+CONFIG_WERROR=y
+CONFIG_NO_DEBUG_LIB=y
+# CONFIG_DMALLOC is not set
+# CONFIG_EFENCE is not set
+
+#
+# Installation Options
+#
+# 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"
+
+#
+# Busybox Library Tuning
+#
+CONFIG_PASSWORD_MINLEN=6
+CONFIG_MD5_SIZE_VS_SPEED=2
+CONFIG_FEATURE_FAST_TOP=y
+# CONFIG_FEATURE_ETC_NETWORKS is not set
+CONFIG_FEATURE_EDITING=y
+CONFIG_FEATURE_EDITING_MAX_LEN=1024
+CONFIG_FEATURE_EDITING_VI=y
+CONFIG_FEATURE_EDITING_HISTORY=15
+# CONFIG_FEATURE_EDITING_SAVEHISTORY is not set
+CONFIG_FEATURE_TAB_COMPLETION=y
+CONFIG_FEATURE_USERNAME_COMPLETION=y
+CONFIG_FEATURE_EDITING_FANCY_PROMPT=y
+CONFIG_FEATURE_EDITING_ASK_TERMINAL=y
+CONFIG_FEATURE_NON_POSIX_CP=y
+# CONFIG_FEATURE_VERBOSE_CP_MESSAGE is not set
+CONFIG_FEATURE_COPYBUF_KB=64
+CONFIG_MONOTONIC_SYSCALL=y
+# CONFIG_IOCTL_HEX2STR_ERROR is not set
+CONFIG_FEATURE_HWIB=y
+
+#
+# Applets
+#
+
+#
+# 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_FEATURE_AR_CREATE is not set
+# CONFIG_BUNZIP2 is not set
+# CONFIG_BZIP2 is not set
+# 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 is not set
+# CONFIG_GZIP is not set
+# CONFIG_FEATURE_GZIP_LONG_OPTIONS is not set
+# CONFIG_LZOP is not set
+# CONFIG_LZOP_COMPR_HIGH is not set
+# CONFIG_RPM2CPIO is not set
+# CONFIG_RPM is not set
+# CONFIG_TAR is not set
+# CONFIG_FEATURE_TAR_CREATE is not set
+# CONFIG_FEATURE_TAR_AUTODETECT is not set
+# CONFIG_FEATURE_TAR_FROM is not set
+# CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set
+# CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY is not set
+# CONFIG_FEATURE_TAR_GNU_EXTENSIONS is not set
+# CONFIG_FEATURE_TAR_LONG_OPTIONS is not set
+# CONFIG_FEATURE_TAR_UNAME_GNAME is not set
+# CONFIG_FEATURE_TAR_NOPRESERVE_TIME is not set
+# 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
+
+#
+# Coreutils
+#
+CONFIG_BASENAME=y
+# CONFIG_CAT is not set
+# CONFIG_DATE is not set
+# CONFIG_FEATURE_DATE_ISOFMT is not set
+# CONFIG_FEATURE_DATE_NANO is not set
+# CONFIG_FEATURE_DATE_COMPAT is not set
+# CONFIG_TEST is not set
+# 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_CAL is not set
+# CONFIG_CATV is not set
+# CONFIG_CHGRP is not set
+# CONFIG_CHMOD is not set
+# CONFIG_CHOWN is not set
+# CONFIG_FEATURE_CHOWN_LONG_OPTIONS is not set
+# CONFIG_CHROOT is not set
+# CONFIG_CKSUM is not set
+# CONFIG_COMM is not set
+# CONFIG_CP is not set
+# CONFIG_FEATURE_CP_LONG_OPTIONS is not set
+# CONFIG_CUT is not set
+# CONFIG_DD is not set
+# CONFIG_FEATURE_DD_SIGNAL_HANDLING is not set
+# CONFIG_FEATURE_DD_THIRD_STATUS_LINE is not set
+# CONFIG_FEATURE_DD_IBS_OBS is not set
+# CONFIG_DF is not set
+# CONFIG_FEATURE_DF_FANCY is not set
+# CONFIG_DIRNAME is not set
+# CONFIG_DOS2UNIX is not set
+# CONFIG_UNIX2DOS is not set
+# CONFIG_DU is not set
+# CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K is not set
+# CONFIG_ECHO is not set
+# CONFIG_FEATURE_FANCY_ECHO is not set
+# CONFIG_ENV is not set
+# CONFIG_FEATURE_ENV_LONG_OPTIONS is not set
+# CONFIG_EXPAND is not set
+# CONFIG_FEATURE_EXPAND_LONG_OPTIONS is not set
+# CONFIG_EXPR is not set
+# CONFIG_EXPR_MATH_SUPPORT_64 is not set
+CONFIG_FALSE=y
+# CONFIG_FOLD is not set
+# CONFIG_FSYNC is not set
+# CONFIG_HEAD is not set
+# CONFIG_FEATURE_FANCY_HEAD is not set
+# CONFIG_HOSTID is not set
+# CONFIG_ID is not set
+# CONFIG_INSTALL is not set
+# CONFIG_FEATURE_INSTALL_LONG_OPTIONS is not set
+# CONFIG_LENGTH is not set
+# CONFIG_LN is not set
+# CONFIG_LOGNAME is not set
+# CONFIG_LS is not set
+# CONFIG_FEATURE_LS_FILETYPES is not set
+# CONFIG_FEATURE_LS_FOLLOWLINKS is not set
+# CONFIG_FEATURE_LS_RECURSIVE is not set
+# CONFIG_FEATURE_LS_SORTFILES is not set
+# CONFIG_FEATURE_LS_TIMESTAMPS is not set
+# CONFIG_FEATURE_LS_USERNAME is not set
+# CONFIG_FEATURE_LS_COLOR is not set
+# CONFIG_FEATURE_LS_COLOR_IS_DEFAULT is not set
+# CONFIG_MD5SUM is not set
+# CONFIG_MKDIR is not set
+# CONFIG_FEATURE_MKDIR_LONG_OPTIONS is not set
+# CONFIG_MKFIFO is not set
+# CONFIG_MKNOD is not set
+# CONFIG_MV is not set
+# CONFIG_FEATURE_MV_LONG_OPTIONS is not set
+# CONFIG_NICE is not set
+# CONFIG_NOHUP is not set
+# CONFIG_OD is not set
+# CONFIG_PRINTENV is not set
+# CONFIG_PRINTF is not set
+# CONFIG_PWD is not set
+# CONFIG_READLINK is not set
+# CONFIG_FEATURE_READLINK_FOLLOW is not set
+# CONFIG_REALPATH is not set
+# CONFIG_RM is not set
+# CONFIG_RMDIR is not set
+# CONFIG_FEATURE_RMDIR_LONG_OPTIONS is not set
+# CONFIG_SEQ is not set
+# CONFIG_SHA1SUM is not set
+# CONFIG_SHA256SUM is not set
+# CONFIG_SHA512SUM is not set
+# CONFIG_SLEEP is not set
+# CONFIG_FEATURE_FANCY_SLEEP is not set
+# CONFIG_FEATURE_FLOAT_SLEEP is not set
+# CONFIG_SORT is not set
+# CONFIG_FEATURE_SORT_BIG is not set
+# CONFIG_SPLIT is not set
+# CONFIG_FEATURE_SPLIT_FANCY is not set
+# CONFIG_STAT is not set
+# CONFIG_FEATURE_STAT_FORMAT is not set
+# CONFIG_STTY is not set
+# CONFIG_SUM is not set
+# CONFIG_SYNC is not set
+# CONFIG_TAC is not set
+# CONFIG_TAIL is not set
+# CONFIG_FEATURE_FANCY_TAIL is not set
+# CONFIG_TEE is not set
+# CONFIG_FEATURE_TEE_USE_BLOCK_IO is not set
+# CONFIG_TOUCH is not set
+CONFIG_TRUE=y
+# CONFIG_TTY is not set
+# CONFIG_UNAME is not set
+# CONFIG_UNEXPAND is not set
+# CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS is not set
+# CONFIG_UNIQ is not set
+# CONFIG_USLEEP is not set
+# CONFIG_UUDECODE is not set
+# CONFIG_UUENCODE is not set
+# CONFIG_WC is not set
+# CONFIG_FEATURE_WC_LARGE is not set
+# CONFIG_WHO is not set
+# CONFIG_WHOAMI is not set
+# CONFIG_YES is not set
+# CONFIG_FEATURE_PRESERVE_HARDLINKS is not set
+# CONFIG_FEATURE_AUTOWIDTH is not set
+# CONFIG_FEATURE_HUMAN_READABLE is not set
+# CONFIG_FEATURE_MD5_SHA1_SUM_CHECK is not set
+
+#
+# Console Utilities
+#
+# CONFIG_CHVT is not set
+# CONFIG_FGCONSOLE is not set
+# CONFIG_CLEAR is not set
+# CONFIG_DEALLOCVT is not set
+# CONFIG_DUMPKMAP is not set
+# CONFIG_KBD_MODE is not set
+# CONFIG_LOADFONT is not set
+# CONFIG_LOADKMAP is not set
+# CONFIG_OPENVT is not set
+# CONFIG_RESET is not set
+# CONFIG_RESIZE is not set
+# CONFIG_FEATURE_RESIZE_PRINT is not set
+# CONFIG_SETCONSOLE is not set
+# CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set
+# CONFIG_SETFONT is not set
+# CONFIG_FEATURE_SETFONT_TEXTUAL_MAP is not set
+CONFIG_DEFAULT_SETFONT_DIR=""
+# CONFIG_SETKEYCODES is not set
+# CONFIG_SETLOGCONS is not set
+# CONFIG_SHOWKEY is not set
+# CONFIG_FEATURE_LOADFONT_PSF2 is not set
+# CONFIG_FEATURE_LOADFONT_RAW is not set
+
+#
+# Debian Utilities
+#
+# CONFIG_MKTEMP is not set
+CONFIG_PIPE_PROGRESS=y
+# CONFIG_RUN_PARTS is not set
+# CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS is not set
+# CONFIG_FEATURE_RUN_PARTS_FANCY is not set
+# CONFIG_START_STOP_DAEMON is not set
+# CONFIG_FEATURE_START_STOP_DAEMON_FANCY is not set
+# CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set
+# CONFIG_WHICH is not set
+
+#
+# Editors
+#
+# CONFIG_AWK is not set
+# CONFIG_FEATURE_AWK_LIBM is not set
+# CONFIG_CMP is not set
+# CONFIG_DIFF is not set
+# CONFIG_FEATURE_DIFF_LONG_OPTIONS is not set
+# CONFIG_FEATURE_DIFF_DIR is not set
+# CONFIG_ED is not set
+# CONFIG_PATCH is not set
+# CONFIG_SED is not set
+# CONFIG_VI is not set
+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
+# CONFIG_FEATURE_VI_USE_SIGNALS is not set
+# CONFIG_FEATURE_VI_DOT_CMD is not set
+# CONFIG_FEATURE_VI_READONLY is not set
+# 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
+
+#
+# Finding Utilities
+#
+# CONFIG_FIND is not set
+# CONFIG_FEATURE_FIND_PRINT0 is not set
+# CONFIG_FEATURE_FIND_MTIME is not set
+# CONFIG_FEATURE_FIND_MMIN is not set
+# CONFIG_FEATURE_FIND_PERM is not set
+# CONFIG_FEATURE_FIND_TYPE is not set
+# CONFIG_FEATURE_FIND_XDEV is not set
+# CONFIG_FEATURE_FIND_MAXDEPTH is not set
+# CONFIG_FEATURE_FIND_NEWER is not set
+# CONFIG_FEATURE_FIND_INUM is not set
+# CONFIG_FEATURE_FIND_EXEC is not set
+# CONFIG_FEATURE_FIND_USER is not set
+# CONFIG_FEATURE_FIND_GROUP is not set
+# CONFIG_FEATURE_FIND_NOT is not set
+# CONFIG_FEATURE_FIND_DEPTH is not set
+# CONFIG_FEATURE_FIND_PAREN is not set
+# CONFIG_FEATURE_FIND_SIZE is not set
+# CONFIG_FEATURE_FIND_PRUNE is not set
+# CONFIG_FEATURE_FIND_DELETE is not set
+# 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 is not set
+# CONFIG_GREP is not set
+# CONFIG_FEATURE_GREP_EGREP_ALIAS is not set
+# CONFIG_FEATURE_GREP_FGREP_ALIAS is not set
+# CONFIG_FEATURE_GREP_CONTEXT is not set
+# CONFIG_XARGS is not set
+# CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION is not set
+# CONFIG_FEATURE_XARGS_SUPPORT_QUOTES is not set
+# CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT is not set
+# CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM is not set
+
+#
+# Init Utilities
+#
+# CONFIG_INIT is not set
+# CONFIG_FEATURE_USE_INITTAB is not set
+# 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 is not set
+# CONFIG_HALT is not set
+# CONFIG_FEATURE_CALL_TELINIT is not set
+CONFIG_TELINIT_PATH=""
+# CONFIG_MESG is not set
+# CONFIG_BOOTCHARTD is not set
+
+#
+# Login/Password Management Utilities
+#
+# CONFIG_FEATURE_SHADOWPASSWDS 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_ADDGROUP is not set
+# CONFIG_FEATURE_ADDGROUP_LONG_OPTIONS is not set
+# CONFIG_FEATURE_ADDUSER_TO_GROUP is not set
+# CONFIG_DELGROUP is not set
+# CONFIG_FEATURE_DEL_USER_FROM_GROUP is not set
+# CONFIG_FEATURE_CHECK_NAMES is not set
+# CONFIG_ADDUSER is not set
+# CONFIG_FEATURE_ADDUSER_LONG_OPTIONS is not set
+CONFIG_FIRST_SYSTEM_ID=0
+CONFIG_LAST_SYSTEM_ID=0
+# CONFIG_DELUSER is not set
+# CONFIG_GETTY is not set
+# CONFIG_LOGIN is not set
+# CONFIG_PAM is not set
+# CONFIG_LOGIN_SCRIPTS is not set
+# CONFIG_FEATURE_NOLOGIN is not set
+# CONFIG_FEATURE_SECURETTY is not set
+# CONFIG_PASSWD is not set
+# CONFIG_FEATURE_PASSWD_WEAK_CHECK is not set
+# CONFIG_CRYPTPW is not set
+# CONFIG_CHPASSWD is not set
+# CONFIG_SU is not set
+# CONFIG_FEATURE_SU_SYSLOG is not set
+# CONFIG_FEATURE_SU_CHECKS_SHELLS is not set
+# CONFIG_SULOGIN is not set
+# CONFIG_VLOCK is not set
+
+#
+# Linux Ext2 FS Progs
+#
+# CONFIG_CHATTR is not set
+# CONFIG_FSCK is not set
+# CONFIG_LSATTR is not set
+# CONFIG_TUNE2FS is not set
+
+#
+# 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 is not set
+# CONFIG_RMMOD is not set
+# CONFIG_LSMOD is not set
+# CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set
+# CONFIG_MODPROBE is not set
+# CONFIG_FEATURE_MODPROBE_BLACKLIST is not set
+# CONFIG_DEPMOD is not set
+
+#
+# Options common to multiple modutils
+#
+# CONFIG_FEATURE_2_4_MODULES is not set
+# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set
+# 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 is not set
+# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set
+CONFIG_DEFAULT_MODULES_DIR=""
+CONFIG_DEFAULT_DEPMOD_FILE=""
+
+#
+# Linux System Utilities
+#
+# CONFIG_ACPID is not set
+# CONFIG_FEATURE_ACPID_COMPAT is not set
+# CONFIG_BLKID is not set
+# CONFIG_DMESG is not set
+# CONFIG_FEATURE_DMESG_PRETTY is not set
+# CONFIG_FBSET is not set
+# CONFIG_FEATURE_FBSET_FANCY is not set
+# CONFIG_FEATURE_FBSET_READMODE is not set
+# CONFIG_FDFLUSH is not set
+# CONFIG_FDFORMAT is not set
+# CONFIG_FDISK is not set
+CONFIG_FDISK_SUPPORT_LARGE_DISKS=y
+# CONFIG_FEATURE_FDISK_WRITABLE is not set
+# CONFIG_FEATURE_AIX_LABEL is not set
+# CONFIG_FEATURE_SGI_LABEL is not set
+# CONFIG_FEATURE_SUN_LABEL is not set
+# CONFIG_FEATURE_OSF_LABEL is not set
+# CONFIG_FEATURE_FDISK_ADVANCED is not set
+# CONFIG_FINDFS is not set
+# CONFIG_FLOCK is not set
+# CONFIG_FREERAMDISK is not set
+# CONFIG_FSCK_MINIX is not set
+# CONFIG_MKFS_EXT2 is not set
+# CONFIG_MKFS_MINIX is not set
+# CONFIG_FEATURE_MINIX2 is not set
+# CONFIG_MKFS_REISER is not set
+# CONFIG_MKFS_VFAT is not set
+# CONFIG_GETOPT is not set
+# CONFIG_FEATURE_GETOPT_LONG is not set
+# CONFIG_HEXDUMP is not set
+# CONFIG_FEATURE_HEXDUMP_REVERSE is not set
+# CONFIG_HD is not set
+# 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 is not set
+# CONFIG_LSPCI is not set
+# CONFIG_LSUSB is not set
+# CONFIG_MDEV is not set
+# 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 is not set
+# CONFIG_MKSWAP is not set
+# CONFIG_FEATURE_MKSWAP_UUID is not set
+# CONFIG_MORE is not set
+# CONFIG_FEATURE_USE_TERMIOS is not set
+CONFIG_VOLUMEID=y
+# CONFIG_FEATURE_VOLUMEID_EXT is not set
+# CONFIG_FEATURE_VOLUMEID_BTRFS is not set
+# CONFIG_FEATURE_VOLUMEID_REISERFS is not set
+# CONFIG_FEATURE_VOLUMEID_FAT is not set
+# CONFIG_FEATURE_VOLUMEID_HFS is not set
+# CONFIG_FEATURE_VOLUMEID_JFS is not set
+# CONFIG_FEATURE_VOLUMEID_XFS is not set
+# CONFIG_FEATURE_VOLUMEID_NTFS is not set
+# CONFIG_FEATURE_VOLUMEID_ISO9660 is not set
+# CONFIG_FEATURE_VOLUMEID_UDF is not set
+# CONFIG_FEATURE_VOLUMEID_LUKS is not set
+# CONFIG_FEATURE_VOLUMEID_LINUXSWAP is not set
+# CONFIG_FEATURE_VOLUMEID_CRAMFS is not set
+# CONFIG_FEATURE_VOLUMEID_ROMFS is not set
+# CONFIG_FEATURE_VOLUMEID_SYSV is not set
+# CONFIG_FEATURE_VOLUMEID_OCFS2 is not set
+# CONFIG_FEATURE_VOLUMEID_LINUXRAID is not set
+# CONFIG_MOUNT is not set
+# CONFIG_FEATURE_MOUNT_FAKE is not set
+# CONFIG_FEATURE_MOUNT_VERBOSE is not set
+# CONFIG_FEATURE_MOUNT_HELPERS is not set
+# CONFIG_FEATURE_MOUNT_LABEL is not set
+# CONFIG_FEATURE_MOUNT_NFS is not set
+# CONFIG_FEATURE_MOUNT_CIFS is not set
+# CONFIG_FEATURE_MOUNT_FLAGS is not set
+# CONFIG_FEATURE_MOUNT_FSTAB is not set
+# CONFIG_PIVOT_ROOT is not set
+# CONFIG_RDATE is not set
+# CONFIG_RDEV is not set
+# CONFIG_READPROFILE is not set
+# CONFIG_RTCWAKE is not set
+# CONFIG_SCRIPT is not set
+# CONFIG_SCRIPTREPLAY is not set
+# CONFIG_SETARCH is not set
+# CONFIG_SWAPONOFF is not set
+# CONFIG_FEATURE_SWAPON_PRI is not set
+# CONFIG_SWITCH_ROOT is not set
+# CONFIG_UMOUNT is not set
+# CONFIG_FEATURE_UMOUNT_ALL is not set
+# CONFIG_FEATURE_MOUNT_LOOP is not set
+# CONFIG_FEATURE_MOUNT_LOOP_CREATE is not set
+# CONFIG_FEATURE_MTAB_SUPPORT is not set
+
+#
+# Miscellaneous Utilities
+#
+# CONFIG_ADJTIMEX is not set
+CONFIG_BBCONFIG=y
+# 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_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 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 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=0
+# CONFIG_FEATURE_LESS_BRACKETS is not set
+# CONFIG_FEATURE_LESS_FLAGS 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
+# CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set
+# CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set
+# CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set
+# CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA is not set
+# CONFIG_MAKEDEVS is not set
+# CONFIG_FEATURE_MAKEDEVS_LEAF is not set
+# CONFIG_FEATURE_MAKEDEVS_TABLE is not set
+# CONFIG_MAN is not set
+# CONFIG_MICROCOM is not set
+# CONFIG_MOUNTPOINT is not set
+# CONFIG_MT is not set
+# CONFIG_RAIDAUTORUN is not set
+# CONFIG_READAHEAD is not set
+# CONFIG_RFKILL is not set
+# CONFIG_RUNLEVEL is not set
+# CONFIG_RX 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_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 is not set
+# CONFIG_HTTPD is not set
+# CONFIG_FEATURE_HTTPD_RANGES is not set
+# CONFIG_FEATURE_HTTPD_USE_SENDFILE 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_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_IFCONFIG is not set
+# CONFIG_FEATURE_IFCONFIG_STATUS is not set
+# CONFIG_FEATURE_IFCONFIG_SLIP is not set
+# CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set
+# CONFIG_FEATURE_IFCONFIG_HW is not set
+# 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=""
+# CONFIG_FEATURE_IFUPDOWN_IP is not set
+# CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN is not set
+# CONFIG_FEATURE_IFUPDOWN_IFCONFIG_BUILTIN is not set
+# CONFIG_FEATURE_IFUPDOWN_IPV4 is not set
+# CONFIG_FEATURE_IFUPDOWN_IPV6 is not set
+# CONFIG_FEATURE_IFUPDOWN_MAPPING is not set
+# CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP is not set
+# CONFIG_INETD is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set
+# CONFIG_FEATURE_INETD_RPC is not set
+# CONFIG_IP is not set
+# CONFIG_FEATURE_IP_ADDRESS is not set
+# CONFIG_FEATURE_IP_LINK is not set
+# CONFIG_FEATURE_IP_ROUTE is not set
+# 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
+# CONFIG_IPTUNNEL is not set
+# CONFIG_IPRULE is not set
+# CONFIG_IPCALC is not set
+# CONFIG_FEATURE_IPCALC_FANCY is not set
+# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set
+# CONFIG_NAMEIF is not set
+# CONFIG_FEATURE_NAMEIF_EXTENDED is not set
+# CONFIG_NC is not set
+# CONFIG_NC_SERVER is not set
+# CONFIG_NC_EXTRA 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 is not set
+# CONFIG_PING6 is not set
+# CONFIG_FEATURE_FANCY_PING is not set
+# CONFIG_PSCAN is not set
+# CONFIG_ROUTE is not set
+# 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_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_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_DHCPD_LEASES_FILE=""
+# CONFIG_UDHCPC is not set
+# CONFIG_FEATURE_UDHCPC_ARPING is not set
+# CONFIG_FEATURE_UDHCP_PORT is not set
+CONFIG_UDHCP_DEBUG=0
+# CONFIG_FEATURE_UDHCP_RFC3397 is not set
+CONFIG_UDHCPC_DEFAULT_SCRIPT=""
+CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=0
+CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS=""
+# CONFIG_UDPSVD is not set
+# CONFIG_VCONFIG is not set
+# CONFIG_WGET is not set
+# CONFIG_FEATURE_WGET_STATUSBAR is not set
+# CONFIG_FEATURE_WGET_AUTHENTICATION is not set
+# CONFIG_FEATURE_WGET_LONG_OPTIONS is not set
+# 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_FREE is not set
+# CONFIG_FUSER is not set
+# CONFIG_KILL is not set
+# CONFIG_KILLALL is not set
+# 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 is not set
+# 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_FEATURE_TOP_SMP_PROCESS is not set
+# CONFIG_FEATURE_TOPMEM is not set
+# CONFIG_FEATURE_SHOW_THREADS is not set
+# CONFIG_UPTIME is not set
+# CONFIG_WATCH is not set
+
+#
+# Runit Utilities
+#
+# 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
+
+#
+# Shells
+#
+# CONFIG_ASH is not set
+# CONFIG_ASH_BASH_COMPAT is not set
+# CONFIG_ASH_JOB_CONTROL is not set
+# CONFIG_ASH_ALIAS 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 is not set
+# CONFIG_ASH_CMDCMD is not set
+# CONFIG_ASH_MAIL is not set
+# CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_ASH_RANDOM_SUPPORT is not set
+# CONFIG_ASH_EXPAND_PRMT is not set
+# CONFIG_HUSH is not set
+# CONFIG_HUSH_BASH_COMPAT is not set
+# CONFIG_HUSH_HELP is not set
+# CONFIG_HUSH_INTERACTIVE 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_HUSH_CASE is not set
+# CONFIG_HUSH_FUNCTIONS is not set
+# CONFIG_HUSH_LOCAL is not set
+# CONFIG_HUSH_EXPORT_N is not set
+# CONFIG_HUSH_RANDOM_SUPPORT is not set
+# CONFIG_FEATURE_SH_IS_ASH is not set
+# CONFIG_FEATURE_SH_IS_HUSH is not set
+CONFIG_FEATURE_SH_IS_NONE=y
+# CONFIG_FEATURE_BASH_IS_ASH is not set
+# CONFIG_FEATURE_BASH_IS_HUSH is not set
+CONFIG_FEATURE_BASH_IS_NONE=y
+# CONFIG_LASH is not set
+# CONFIG_MSH is not set
+# CONFIG_SH_MATH_SUPPORT is not set
+# CONFIG_SH_MATH_SUPPORT_64 is not set
+# CONFIG_FEATURE_SH_EXTRA_QUIET is not set
+# CONFIG_FEATURE_SH_STANDALONE is not set
+# CONFIG_FEATURE_SH_NOFORK is not set
+# CONFIG_CTTYHACK is not set
+
+#
+# System Logging Utilities
+#
+# 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=0
+# CONFIG_LOGREAD is not set
+# CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set
+# CONFIG_KLOGD is not set
+# CONFIG_LOGGER is not set
diff --git a/scripts/defconfig b/TEST_config_rh9
index 3a3d08260..f376cd439 100644
--- a/scripts/defconfig
+++ b/TEST_config_rh9
@@ -1,35 +1,46 @@
#
# Automatically generated make config: don't edit
-# Busybox version: 1.15.0.svn
-# Fri Aug 21 00:14:11 2009
+# Busybox version: 1.17.0.git
+# Fri Apr 16 22:25:22 2010
#
CONFIG_HAVE_DOT_CONFIG=y
#
# Busybox Settings
#
#
# General Configuration
#
# CONFIG_DESKTOP is not set
# CONFIG_EXTRA_COMPAT is not set
+CONFIG_INCLUDE_SUSv2=y
+# CONFIG_USE_PORTABLE_CODE is not set
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=y
CONFIG_FEATURE_COMPRESS_USAGE=y
CONFIG_FEATURE_INSTALLER=y
CONFIG_LOCALE_SUPPORT=y
-# CONFIG_FEATURE_ASSUME_UNICODE is not set
+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_LONG_OPTS=y
CONFIG_FEATURE_DEVPTS=y
# CONFIG_FEATURE_CLEAN_UP is not set
+CONFIG_FEATURE_UTMP=y
+CONFIG_FEATURE_WTMP=y
CONFIG_FEATURE_PIDFILE=y
CONFIG_FEATURE_SUID=y
CONFIG_FEATURE_SUID_CONFIG=y
CONFIG_FEATURE_SUID_CONFIG_QUIET=y
# CONFIG_SELINUX is not set
# CONFIG_FEATURE_PREFER_APPLETS is not set
@@ -56,13 +67,12 @@ CONFIG_EXTRA_CFLAGS=""
# 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=y
#
# Installation Options
#
# CONFIG_INSTALL_NO_USR is not set
CONFIG_INSTALL_APPLET_SYMLINKS=y
@@ -92,13 +102,13 @@ CONFIG_FEATURE_TAB_COMPLETION=y
# 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 is not set
CONFIG_IOCTL_HEX2STR_ERROR=y
-CONFIG_FEATURE_HWIB=y
+# CONFIG_FEATURE_HWIB is not set
#
# Applets
#
#
@@ -107,35 +117,39 @@ CONFIG_FEATURE_HWIB=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 is not set
# CONFIG_DPKG_DEB is not set
# CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY is not set
CONFIG_GUNZIP=y
CONFIG_GZIP=y
+CONFIG_FEATURE_GZIP_LONG_OPTIONS=y
CONFIG_LZOP=y
# CONFIG_LZOP_COMPR_HIGH is not set
-# CONFIG_RPM2CPIO is not set
-# CONFIG_RPM is not set
+CONFIG_RPM2CPIO=y
+CONFIG_RPM=y
CONFIG_TAR=y
CONFIG_FEATURE_TAR_CREATE=y
CONFIG_FEATURE_TAR_AUTODETECT=y
CONFIG_FEATURE_TAR_FROM=y
CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY=y
CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY=y
CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y
CONFIG_FEATURE_TAR_LONG_OPTIONS=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_UNZIP=y
#
@@ -145,21 +159,25 @@ CONFIG_BASENAME=y
CONFIG_CAL=y
CONFIG_CAT=y
CONFIG_CATV=y
CONFIG_CHGRP=y
CONFIG_CHMOD=y
CONFIG_CHOWN=y
+CONFIG_FEATURE_CHOWN_LONG_OPTIONS=y
CONFIG_CHROOT=y
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_FEATURE_DATE_COMPAT=y
CONFIG_DD=y
CONFIG_FEATURE_DD_SIGNAL_HANDLING=y
+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
@@ -268,13 +286,13 @@ CONFIG_FEATURE_AUTOWIDTH=y
#
# Common options for df, du, ls
#
CONFIG_FEATURE_HUMAN_READABLE=y
#
-# Common options for md5sum, sha1sum
+# Common options for md5sum, sha1sum, sha256sum, sha512sum
#
CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y
#
# Console Utilities
#
@@ -296,12 +314,18 @@ CONFIG_FEATURE_SETFONT_TEXTUAL_MAP=y
CONFIG_DEFAULT_SETFONT_DIR=""
CONFIG_SETKEYCODES=y
CONFIG_SETLOGCONS=y
CONFIG_SHOWKEY=y
#
+# Common options for loadfont and setfont
+#
+# CONFIG_FEATURE_LOADFONT_PSF2 is not set
+# CONFIG_FEATURE_LOADFONT_RAW is not set
+
+#
# Debian Utilities
#
CONFIG_MKTEMP=y
CONFIG_PIPE_PROGRESS=y
CONFIG_RUN_PARTS=y
CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS=y
@@ -315,15 +339,14 @@ CONFIG_WHICH=y
# Editors
#
CONFIG_AWK=y
CONFIG_FEATURE_AWK_LIBM=y
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=y
CONFIG_ED=y
CONFIG_PATCH=y
CONFIG_SED=y
CONFIG_VI=y
CONFIG_FEATURE_VI_MAX_LEN=4096
# CONFIG_FEATURE_VI_8BIT is not set
@@ -361,12 +384,13 @@ CONFIG_FEATURE_FIND_PAREN=y
CONFIG_FEATURE_FIND_SIZE=y
CONFIG_FEATURE_FIND_PRUNE=y
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
CONFIG_FEATURE_GREP_CONTEXT=y
CONFIG_XARGS=y
CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION=y
@@ -408,14 +432,12 @@ CONFIG_FEATURE_DEL_USER_FROM_GROUP=y
CONFIG_ADDUSER=y
CONFIG_FEATURE_ADDUSER_LONG_OPTIONS=y
CONFIG_FIRST_SYSTEM_ID=100
CONFIG_LAST_SYSTEM_ID=999
CONFIG_DELUSER=y
CONFIG_GETTY=y
-CONFIG_FEATURE_UTMP=y
-CONFIG_FEATURE_WTMP=y
CONFIG_LOGIN=y
# CONFIG_PAM is not set
CONFIG_LOGIN_SCRIPTS=y
CONFIG_FEATURE_NOLOGIN=y
CONFIG_FEATURE_SECURETTY=y
CONFIG_PASSWD=y
@@ -450,12 +472,13 @@ CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y
# CONFIG_DEPMOD is not set
#
# Options common to multiple modutils
#
# CONFIG_FEATURE_2_4_MODULES is not set
+# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set
# 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
@@ -483,44 +506,50 @@ CONFIG_FEATURE_FDISK_WRITABLE=y
# CONFIG_FEATURE_AIX_LABEL is not set
# CONFIG_FEATURE_SGI_LABEL is not set
# CONFIG_FEATURE_SUN_LABEL is not set
# CONFIG_FEATURE_OSF_LABEL is not set
CONFIG_FEATURE_FDISK_ADVANCED=y
CONFIG_FINDFS=y
+# CONFIG_FLOCK is not set
CONFIG_FREERAMDISK=y
CONFIG_FSCK_MINIX=y
+# CONFIG_MKFS_EXT2 is not set
CONFIG_MKFS_MINIX=y
#
# Minix filesystem support
#
CONFIG_FEATURE_MINIX2=y
+# CONFIG_MKFS_REISER is not set
CONFIG_MKFS_VFAT=y
CONFIG_GETOPT=y
CONFIG_FEATURE_GETOPT_LONG=y
CONFIG_HEXDUMP=y
CONFIG_FEATURE_HEXDUMP_REVERSE=y
CONFIG_HD=y
CONFIG_HWCLOCK=y
CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS=y
CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS=y
CONFIG_IPCRM=y
CONFIG_IPCS=y
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_MKSWAP=y
CONFIG_FEATURE_MKSWAP_UUID=y
CONFIG_MORE=y
CONFIG_FEATURE_USE_TERMIOS=y
CONFIG_VOLUMEID=y
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
@@ -557,12 +586,13 @@ CONFIG_UMOUNT=y
CONFIG_FEATURE_UMOUNT_ALL=y
#
# Common options for mount/umount
#
CONFIG_FEATURE_MOUNT_LOOP=y
+# CONFIG_FEATURE_MOUNT_LOOP_CREATE is not set
# CONFIG_FEATURE_MTAB_SUPPORT is not set
#
# Miscellaneous Utilities
#
CONFIG_ADJTIMEX=y
@@ -592,16 +622,17 @@ CONFIG_FEATURE_DC_LIBM=y
# CONFIG_DEVFSD_VERBOSE is not set
# CONFIG_FEATURE_DEVFS is not set
CONFIG_DEVMEM=y
CONFIG_EJECT=y
CONFIG_FEATURE_EJECT_SCSI=y
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=y
+# CONFIG_IONICE is not set
# CONFIG_INOTIFYD is not set
CONFIG_LAST=y
# CONFIG_FEATURE_LAST_SMALL is not set
CONFIG_FEATURE_LAST_FANCY=y
CONFIG_LESS=y
CONFIG_FEATURE_LESS_MAXLINES=9999999
@@ -624,25 +655,25 @@ CONFIG_MAKEDEVS=y
CONFIG_FEATURE_MAKEDEVS_TABLE=y
CONFIG_MAN=y
CONFIG_MICROCOM=y
CONFIG_MOUNTPOINT=y
CONFIG_MT=y
CONFIG_RAIDAUTORUN=y
-CONFIG_READAHEAD=y
+# CONFIG_READAHEAD is not set
CONFIG_RUNLEVEL=y
CONFIG_RX=y
CONFIG_SETSID=y
CONFIG_STRINGS=y
# CONFIG_TASKSET is not set
# CONFIG_FEATURE_TASKSET_FANCY is not set
CONFIG_TIME=y
CONFIG_TIMEOUT=y
CONFIG_TTYSIZE=y
CONFIG_VOLNAME=y
CONFIG_WALL=y
-CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG is not set
#
# Networking Utilities
#
CONFIG_FEATURE_IPV6=y
# CONFIG_FEATURE_UNIX_LOCAL is not set
@@ -655,12 +686,13 @@ CONFIG_FEATURE_BRCTL_FANCY=y
CONFIG_FEATURE_BRCTL_SHOW=y
CONFIG_DNSD=y
CONFIG_ETHER_WAKE=y
CONFIG_FAKEIDENTD=y
CONFIG_FTPD=y
CONFIG_FEATURE_FTP_WRITE=y
+CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST=y
CONFIG_FTPGET=y
CONFIG_FTPPUT=y
CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS=y
CONFIG_HOSTNAME=y
CONFIG_HTTPD=y
CONFIG_FEATURE_HTTPD_RANGES=y
@@ -677,13 +709,13 @@ CONFIG_FEATURE_HTTPD_PROXY=y
CONFIG_IFCONFIG=y
CONFIG_FEATURE_IFCONFIG_STATUS=y
CONFIG_FEATURE_IFCONFIG_SLIP=y
CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ=y
CONFIG_FEATURE_IFCONFIG_HW=y
CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS=y
-CONFIG_IFENSLAVE=y
+# CONFIG_IFENSLAVE is not set
CONFIG_IFPLUGD=y
CONFIG_IFUPDOWN=y
CONFIG_IFUPDOWN_IFSTATE_PATH="/var/run/ifstate"
CONFIG_FEATURE_IFUPDOWN_IP=y
CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN=y
# CONFIG_FEATURE_IFUPDOWN_IFCONFIG_BUILTIN is not set
@@ -720,33 +752,41 @@ CONFIG_NC=y
CONFIG_NC_SERVER=y
CONFIG_NC_EXTRA=y
CONFIG_NETSTAT=y
CONFIG_FEATURE_NETSTAT_WIDE=y
CONFIG_FEATURE_NETSTAT_PRG=y
CONFIG_NSLOOKUP=y
+CONFIG_NTPD=y
+CONFIG_FEATURE_NTPD_SERVER=y
CONFIG_PING=y
CONFIG_PING6=y
CONFIG_FEATURE_FANCY_PING=y
CONFIG_PSCAN=y
CONFIG_ROUTE=y
CONFIG_SLATTACH=y
+CONFIG_TCPSVD=y
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=y
CONFIG_TFTP=y
CONFIG_TFTPD=y
CONFIG_FEATURE_TFTP_GET=y
CONFIG_FEATURE_TFTP_PUT=y
CONFIG_FEATURE_TFTP_BLOCKSIZE=y
+CONFIG_FEATURE_TFTP_PROGRESS_BAR=y
# CONFIG_TFTP_DEBUG is not set
CONFIG_TRACEROUTE=y
+CONFIG_TRACEROUTE6=y
CONFIG_FEATURE_TRACEROUTE_VERBOSE=y
# CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE is not set
# CONFIG_FEATURE_TRACEROUTE_USE_ICMP is not set
+CONFIG_TUNCTL=y
+CONFIG_FEATURE_TUNCTL_UG=y
CONFIG_UDHCPD=y
CONFIG_DHCPRELAY=y
CONFIG_DUMPLEASES=y
CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY=y
CONFIG_DHCPD_LEASES_FILE="/var/lib/misc/udhcpd.leases"
CONFIG_UDHCPC=y
@@ -754,22 +794,19 @@ 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="-R -n"
+CONFIG_UDPSVD=y
CONFIG_VCONFIG=y
CONFIG_WGET=y
CONFIG_FEATURE_WGET_STATUSBAR=y
CONFIG_FEATURE_WGET_AUTHENTICATION=y
CONFIG_FEATURE_WGET_LONG_OPTIONS=y
CONFIG_ZCIP=y
-CONFIG_TCPSVD=y
-CONFIG_TUNCTL=y
-CONFIG_FEATURE_TUNCTL_UG=y
-CONFIG_UDPSVD=y
#
# Print Utilities
#
CONFIG_LPD=y
CONFIG_LPR=y
@@ -811,12 +848,13 @@ 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=y
CONFIG_FEATURE_TOP_SMP_PROCESS=y
CONFIG_FEATURE_TOPMEM=y
+CONFIG_FEATURE_SHOW_THREADS=y
CONFIG_UPTIME=y
CONFIG_WATCH=y
#
# Runit Utilities
#
@@ -875,12 +913,13 @@ CONFIG_HUSH_TICK=y
CONFIG_HUSH_IF=y
CONFIG_HUSH_LOOPS=y
CONFIG_HUSH_CASE=y
CONFIG_HUSH_FUNCTIONS=y
CONFIG_HUSH_LOCAL=y
CONFIG_HUSH_EXPORT_N=y
+CONFIG_HUSH_RANDOM_SUPPORT=y
# CONFIG_LASH is not set
CONFIG_MSH=y
CONFIG_SH_MATH_SUPPORT=y
CONFIG_SH_MATH_SUPPORT_64=y
CONFIG_FEATURE_SH_EXTRA_QUIET=y
# CONFIG_FEATURE_SH_STANDALONE is not set
@@ -891,12 +930,13 @@ CONFIG_CTTYHACK=y
# System Logging Utilities
#
CONFIG_SYSLOGD=y
CONFIG_FEATURE_ROTATE_LOGFILE=y
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=y
CONFIG_KLOGD=y
CONFIG_LOGGER=y
diff --git a/TODO b/TODO
index 9be1b07e2..6f8cd8a32 100644
--- a/TODO
+++ b/TODO
@@ -1,20 +1,20 @@
Busybox TODO
+Harvest patches from
+http://git.openembedded.org/cgit.cgi/openembedded/tree/recipes/busybox/
+
Stuff that needs to be done. This is organized by who plans to get around to
doing it eventually, but that doesn't mean they "own" the item. If you want to
do one of these bounce an email off the person it's listed under to see if they
have any suggestions how they plan to go about it, and to minimize conflicts
between your work and theirs. But otherwise, all of these are fair game.
Rob Landley suggested this:
Implement bb_realpath() that can handle NULL on non-glibc.
- Remove obsolete _() wrapper crud for internationalization we don't do.
- Figure out where we need utf8 support, and add it.
-
sh
The command shell situation is a mess. We have two different
shells that don't really share any code, and the "standalone shell" doesn't
work all that well (especially not in a chroot environment), due to apps not
being reentrant.
@@ -28,13 +28,13 @@ Rob Landley suggested this:
exercises each command line option and the various corner cases.
Internationalization
How much internationalization should we do?
The low hanging fruit is UTF-8 character set support. We should do this.
- (Vodz pointed out the shell's cmdedit as needing work here. What else?)
+ See TODO_unicode file.
We also have lots of hardwired english text messages. Consolidating this
into some kind of message table not only makes translation easier, but
also allows us to consolidate redundant (or close) strings.
We probably don't want to be bloated with locale support. (Not unless we
@@ -56,12 +56,13 @@ Rob Landley suggested this:
utils (or simply with less political baggage), but without it being one big
executable.
Turning libbb into a real dll is another possibility, especially if libbb
could export some of the other library interfaces we've already more or less
got the code for (like zlib).
+
buildroot - Make a "dogfood" option
Busybox 1.1 will be capable of replacing most gnu packages for real world
use, such as developing software or in a live CD. It needs wider testing.
Busybox should now be able to replace bzip2, coreutils, e2fsprogs, file,
findutils, gawk, grep, inetutils, less, modutils, net-tools, patch, procps,
@@ -75,28 +76,31 @@ Rob Landley suggested this:
packages. Anything that's wrong with the resulting system, we can fix. (It
would be nice to be able to upgrade busybox to be able to replace bash and
diffutils as well, but we're not there yet.)
One example of an existing system that does this already is Firmware Linux:
http://www.landley.net/code/firmware
+
initramfs
Busybox should have a sample initramfs build script. This depends on
bbsh, mdev, and switch_root.
+
mkdep
Write a mkdep that doesn't segfault if there's a directory it doesn't
have permission to read, isn't based on manually editing the output of
lexx and yacc, doesn't make such a mess under include/config, etc.
+
Group globals into unions of structures.
Go through and turn all the global and static variables into structures,
and have all those structures be in a big union shared between processes,
so busybox uses less bss. (This is a big win on nommu machines.) See
sed.c and mdev.c for examples.
+
Go through bugs.busybox.net and close out all of that somehow.
This one's open to everybody, but I'll wind up doing it...
-
Bernhard Reutner-Fischer <busybox@busybox.net> suggests to look at these:
New debug options:
-Wlarger-than-127
Cleanup any big users
Collate BUFSIZ IOBUF_SIZE MY_BUF_SIZE PIPE_PROGRESS_SIZE BUFSIZE PIPESIZE
make bb_common_bufsiz1 configurable, size wise.
@@ -119,15 +123,12 @@ patch
Should have simple fuzz factor support to apply patches at an offset which
shouldn't take up too much space.
And while we're at it, a new patch filename quoting format is apparently
coming soon: http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2
---
-ar
- Write support!
----
stty / catv
stty's visible() function and catv's guts are identical. Merge them into
an appropriate libbb function.
---
struct suffix_mult
Several duplicate users of: grep -r "1024\*1024" * -B2 -A1
@@ -177,46 +178,12 @@ Memory Allocation
And while we're at it, many of the CONFIG_FEATURE_CLEAN_UP #ifdefs will be
optimized out by the compiler in the stack allocation case (since there's no
free for an alloca()), and this means that various cleanup loops that just
call free might also be optimized out by the compiler if written right, so
we can yank those #ifdefs too, and generally clean up the code.
---
-Switch CONFIG_SYMBOLS to ENABLE_SYMBOLS
-
- In busybox 1.0 and earlier, configuration was done by CONFIG_SYMBOLS
- that were either defined or undefined to indicate whether the symbol was
- selected in the .config file. They were used with #ifdefs, ala:
-
- #ifdef CONFIG_SYMBOL
- if (other_test) {
- do_code();
- }
- #endif
-
- In 1.1, we have new ENABLE_SYMBOLS which are always defined (as 0 or 1),
- meaning you can still use them for preprocessor tests by replacing
- "#ifdef CONFIG_SYMBOL" with "#if ENABLE_SYMBOL". But more importantly, we
- can use them as a true or false test in normal C code:
-
- if (ENABLE_SYMBOL && other_test) {
- do_code();
- }
-
- (Optimizing away if() statements that resolve to a constant value
- is known as "dead code elimination", an optimization so old and simple that
- Turbo Pascal for DOS did it twenty years ago. Even modern mini-compilers
- like the Tiny C Compiler (tcc) and the Small Device C Compiler (SDCC)
- perform dead code elimination.)
-
- Right now, busybox.h is #including both "config.h" (defining the
- CONFIG_SYMBOLS) and "bb_config.h" (defining the ENABLE_SYMBOLS). At some
- point in the future, it would be nice to wean ourselves off of the
- CONFIG versions. (Among other things, some defective build environments
- leak the Linux kernel's CONFIG_SYMBOLS into the system's standard #include
- files. We've experienced collisions before.)
----
FEATURE_CLEAN_UP
This is more an unresolved issue than a to-do item. More thought is needed.
Normally we rely on exit() to free memory, close files and unmap segments
for us. This makes most calls to free(), close(), and unmap() optional in
busybox applets that don't intend to run for very long, and optional stuff
@@ -266,18 +233,13 @@ Minor stuff:
Alot of duplication that wants cleanup.
---
in_ether duplicated in network/{interface,ifconfig}.c
---
unify progress_meter. wget, flash_eraseall, pipe_progress, fbsplash, setfiles.
---
- support start-stop-daemon -d <chdir-path>
-
-Code cleanup:
-
-Replace deprecated functions.
-
+ support start-stop-daemon -d <chdir-path>
---
vdprintf() -> similar sized functionality
---
(TODO list after discussion 11.05.2009)
@@ -296,14 +258,12 @@ vdprintf() -> similar sized functionality
http://www.opengroup.org/onlinepubs/9699919799/
and the complete list of all utilities that POSIX covers:
http://www.opengroup.org/onlinepubs/9699919799/idx/utilities.html
The first step would to generate a file/matrix what is already archived
(also IPV6)
-* ntpdate/ntpd (see ntpclient and openntp for examples)
-
* implement 'at'
* rpcbind (former portmap) or equivalent
so that we don't have to use -o nolock on nfs mounts
* check IPV6 compliance
@@ -311,67 +271,6 @@ vdprintf() -> similar sized functionality
* generate a mini example using kernel+busybox only (+libc) for example
* more support for advanced linux 2.6.x features, see: iotop
most likely there is more
* even more support for statistics: mpstat, iostat, powertop....
-
-
-Unicode work needed:
-
-Unicode support uses libc multibyte functions if LOCALE_SUPPORT is on
-(in this case, the code will also support many more encodings),
-or uses a limited subset of re-implemented multibyte functions
-which only understand "one byte == one char" and unicode.
-This is useful if you build against uclibc with locale support disabled.
-
-Unicode-dependent applets must call check_unicode_in_env() when they
-begin executing.
-
-Applet code may conditionalize on FEATURE_ASSUME_UNICODE
-in order to use more efficient code if unicode support is not requested.
-
-Available functions (if you need more, implement them in libbb/unicode.c
-so that they work without LOCALE_SUPPORT too):
-
-int bb_mbstrlen(str) - multibyte-aware strlen
-size_t mbstowcs(wdest, src, n)
-size_t wcstombs(dest, wsrc, n)
-size_t wcrtomb(str, wc, wstate)
-int iswspace(wc)
-int iswalnum(wc)
-int iswpunct(wc)
-
-Applets which only need to align columns on screen correctly:
-
-ls - already done, use source as an example
-df
-dumpleases
-lsmod
-
-Applets which need to account for Unicode chars
-while processing the output:
-
-[un]expand
-fold
-man
-watch
-cut (-b and -c are currently the same, needs fixing)
-
-These applets need to ensure that unicode input
-is handled correctly (say, <unicode><backspace> sequence):
-
-getty, login
-rm -i
-unzip (overwrite prompt)
-
-Viewers/editors are more difficult (many cases to get right).
-libbb/lineedit.c is an example how to do it:
-
-less, most, ed, vi
-awk
-[ef]grep
-sed
-
-Probably needs some specialized work:
-
-loadkeys
diff --git a/TODO_unicode b/TODO_unicode
new file mode 100644
index 000000000..b310e8d4d
--- /dev/null
+++ b/TODO_unicode
@@ -0,0 +1,45 @@
+Already fixed applets:
+cal
+lsmod
+df
+dumpleases
+
+Applets which may need unicode handling (more extensive than sanitizing
+of filenames in error messages):
+
+ls - work in progress
+expand, unexpand - uses unicode_strlen, not scrlen
+ash, hush through lineedit - uses unicode_strlen, not scrlen
+top - need to sanitize process args
+ps - need to sanitize process args
+less
+more
+vi
+ed
+cut
+awk
+sed
+tr
+grep egrep fgrep
+fold
+sort
+head, tail
+catv - "display nonprinting chars" - what this could mean for unicode?
+wc
+chat
+dumpkmap
+last - just line up columns
+man
+microcom
+strings
+watch
+
+Unsure, may need fixing:
+
+hostname - do we really want to protect against bad chars in it?
+patch
+addgroup, adduser, delgroup, deluser
+telnet
+telnetd
+od
+printf
diff --git a/applets/Kbuild b/applets/Kbuild.src
index a6b0cf6fb..31fee8d1e 100644
--- a/applets/Kbuild
+++ b/applets/Kbuild.src
@@ -24,21 +24,21 @@ endif
HOSTCFLAGS_usage.o = -I$(srctree_slash)include -Iinclude
HOSTCFLAGS_usage_pod.o = -I$(srctree_slash)include -Iinclude
applets/applets.o: include/usage_compressed.h include/applet_tables.h
-applets/applet_tables: .config $(srctree_slash)include/applets.h
-applets/usage: .config $(srctree_slash)include/applets.h
-applets/usage_pod: .config include/applet_tables.h $(srctree_slash)include/applets.h
+applets/applet_tables: .config include/applets.h
+applets/usage: .config include/applets.h
+applets/usage_pod: .config include/applet_tables.h include/applets.h
quiet_cmd_gen_usage_compressed = GEN include/usage_compressed.h
cmd_gen_usage_compressed = $(srctree_slash)applets/usage_compressed include/usage_compressed.h applets
include/usage_compressed.h: applets/usage $(srctree_slash)applets/usage_compressed
$(call cmd,gen_usage_compressed)
quiet_cmd_gen_applet_tables = GEN include/applet_tables.h
- cmd_gen_applet_tables = applets/applet_tables include/applet_tables.h
+ cmd_gen_applet_tables = applets/applet_tables include/applet_tables.h include/NUM_APPLETS.h
include/applet_tables.h: applets/applet_tables
$(call cmd,gen_applet_tables)
diff --git a/applets/applet_tables.c b/applets/applet_tables.c
index e67f017e7..338dc20f9 100644
--- a/applets/applet_tables.c
+++ b/applets/applet_tables.c
@@ -76,12 +76,13 @@ int main(int argc, char **argv)
if (NUM_APPLETS == 1) {
printf("#define SINGLE_APPLET_STR \"%s\"\n", applets[0].name);
printf("#define SINGLE_APPLET_MAIN %s_main\n", applets[0].name);
}
printf("\n");
+ //printf("#ifndef SKIP_definitions\n");
printf("const char applet_names[] ALIGN1 = \"\"\n");
for (i = 0; i < NUM_APPLETS; i++) {
printf("\"%s\" \"\\0\"\n", applets[i].name);
if (MAX_APPLET_NAME_LEN < strlen(applets[i].name))
MAX_APPLET_NAME_LEN = strlen(applets[i].name);
}
@@ -117,13 +118,34 @@ int main(int argc, char **argv)
int v = applets[i].install_loc; /* 3 bits */
if (++i < NUM_APPLETS)
v |= applets[i].install_loc << 4; /* 3 bits */
printf("0x%02x,\n", v);
i++;
}
- printf("};\n\n");
+ printf("};\n");
#endif
-
+ //printf("#endif /* SKIP_definitions */\n");
+ printf("\n");
printf("#define MAX_APPLET_NAME_LEN %u\n", MAX_APPLET_NAME_LEN);
+ if (argv[2]) {
+ char line_old[80];
+ char line_new[80];
+ FILE *fp;
+
+ line_old[0] = 0;
+ fp = fopen(argv[2], "r");
+ if (fp) {
+ fgets(line_old, sizeof(line_old), fp);
+ fclose(fp);
+ }
+ sprintf(line_new, "#define NUM_APPLETS %u\n", NUM_APPLETS);
+ if (strcmp(line_old, line_new) != 0) {
+ fp = fopen(argv[2], "w");
+ if (!fp)
+ return 1;
+ fputs(line_new, fp);
+ }
+ }
+
return 0;
}
diff --git a/applets/applets.c b/applets/applets.c
index 133a21575..6a3996272 100644
--- a/applets/applets.c
+++ b/applets/applets.c
@@ -3,14 +3,12 @@
* Stub for linking busybox binary against libbusybox.
*
* Copyright (C) 2007 Denys Vlasenko <vda.linux@googlemail.com>
*
* Licensed under GPLv2, see file License in this tarball for details.
*/
-
-#include <assert.h>
#include "busybox.h"
#if ENABLE_BUILD_LIBBUSYBOX
int main(int argc UNUSED_PARAM, char **argv)
{
return lbb_main(argv);
diff --git a/applets/usage.c b/applets/usage.c
index d4fd12f9b..46adbf475 100644
--- a/applets/usage.c
+++ b/applets/usage.c
@@ -2,15 +2,15 @@
/*
* Copyright (C) 2008 Denys Vlasenko.
*
* Licensed under GPLv2, see file LICENSE in this tarball for details.
*/
#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
-/* Just #include "autoconf.h" doesn't work for builds in separate
- * object directory */
#include "autoconf.h"
/* Since we can't use platform.h, have to do this again by hand: */
#if ENABLE_NOMMU
# define BB_MMU 0
# define USE_FOR_NOMMU(...) __VA_ARGS__
@@ -18,17 +18,38 @@
#else
# define BB_MMU 1
# define USE_FOR_NOMMU(...)
# define USE_FOR_MMU(...) __VA_ARGS__
#endif
-static const char usage_messages[] = ""
-#define MAKE_USAGE
#include "usage.h"
+#define MAKE_USAGE(aname, usage) { aname, usage },
+static struct usage_data {
+ const char *aname;
+ const char *usage;
+} usage_array[] = {
#include "applets.h"
-;
+};
+
+static int compare_func(const void *a, const void *b)
+{
+ const struct usage_data *ua = a;
+ const struct usage_data *ub = b;
+ return strcmp(ua->aname, ub->aname);
+}
int main(void)
{
- write(STDOUT_FILENO, usage_messages, sizeof(usage_messages));
+ int i;
+ int num_messages = sizeof(usage_array) / sizeof(usage_array[0]);
+
+ if (num_messages == 0)
+ return 0;
+
+ qsort(usage_array,
+ num_messages, sizeof(usage_array[0]),
+ compare_func);
+ for (i = 0; i < num_messages; i++)
+ write(STDOUT_FILENO, usage_array[i].usage, strlen(usage_array[i].usage) + 1);
+
return 0;
}
diff --git a/applets/usage_compressed b/applets/usage_compressed
index 8d343529d..e1fd0d94d 100755
--- a/applets/usage_compressed
+++ b/applets/usage_compressed
@@ -6,30 +6,38 @@ loc="$2"
test "$target" || exit 1
test "$loc" || loc=.
test -x "$loc/usage" || exit 1
test "$SED" || SED=sed
test "$DD" || DD=dd
-sz=`"$loc/usage" | wc -c` || exit 1
+exec >"$target.$$"
-exec >"$target"
-
-echo 'static const char packed_usage[] ALIGN1 = {'
+echo '#define UNPACKED_USAGE "" \'
+"$loc/usage" | od -v -t x1 \
+| $SED -e 's/^[^ ]*//' \
+ -e 's/ //g' \
+ -e '/^$/d' \
+ -e 's/\(..\)/\\x\1/g' \
+ -e 's/^/"/' \
+ -e 's/$/" \\/'
+echo ''
+echo '#define PACKED_USAGE \'
## Breaks on big-endian systems!
## # Extra effort to avoid using "od -t x1": -t is not available
## # in non-CONFIG_DESKTOPed busybox od
##
## "$loc/usage" | bzip2 -1 | od -v -x \
## | $SED -e 's/^[^ ]*//' \
## -e 's/ //g' \
## -e '/^$/d' \
## -e 's/\(..\)\(..\)/0x\2,0x\1,/g'
-
+## -e 's/$/ \\/'
"$loc/usage" | bzip2 -1 | $DD bs=2 skip=1 2>/dev/null | od -v -t x1 \
| $SED -e 's/^[^ ]*//' \
-e 's/ //g' \
-e '/^$/d' \
- -e 's/\(..\)/0x\1,/g'
+ -e 's/\(..\)/0x\1,/g' \
+ -e 's/$/ \\/'
+echo ''
-echo '};'
-echo '#define SIZEOF_usage_messages' `expr 0 + $sz`
+mv -- "$target.$$" "$target"
diff --git a/applets/usage_pod.c b/applets/usage_pod.c
index ee3729d7b..85a2a8ec4 100644
--- a/applets/usage_pod.c
+++ b/applets/usage_pod.c
@@ -3,17 +3,16 @@
* Copyright (C) 2009 Denys Vlasenko.
*
* Licensed under GPLv2, see file LICENSE in this tarball for details.
*/
#include <unistd.h>
#include <stdint.h>
+#include <stdlib.h>
#include <string.h>
#include <stdio.h>
-/* Just #include "autoconf.h" doesn't work for builds in separate
- * object directory */
#include "autoconf.h"
#define SKIP_applet_main
#define ALIGN1 /* nothing, just to placate applet_tables.h */
#define ALIGN2 /* nothing, just to placate applet_tables.h */
#include "applet_tables.h"
@@ -26,61 +25,73 @@
#else
# define BB_MMU 1
# define USE_FOR_NOMMU(...)
# define USE_FOR_MMU(...) __VA_ARGS__
#endif
-static const char usage_messages[] = ""
-#define MAKE_USAGE
#include "usage.h"
+#define MAKE_USAGE(aname, usage) { aname, usage },
+static struct usage_data {
+ const char *aname;
+ const char *usage;
+} usage_array[] = {
#include "applets.h"
-;
+};
+
+static int compare_func(const void *a, const void *b)
+{
+ const struct usage_data *ua = a;
+ const struct usage_data *ub = b;
+ return strcmp(ua->aname, ub->aname);
+}
int main(void)
{
- const char *names;
- const char *usage;
int col, len2;
+ int i;
+ int num_messages = sizeof(usage_array) / sizeof(usage_array[0]);
+
+ if (num_messages == 0)
+ return 0;
+
+ qsort(usage_array,
+ num_messages, sizeof(usage_array[0]),
+ compare_func);
+
col = 0;
- names = applet_names;
- while (*names) {
- len2 = strlen(names) + 2;
+ for (i = 0; i < num_messages; i++) {
+ len2 = strlen(usage_array[i].aname) + 2;
if (col >= 76 - len2) {
printf(",\n");
col = 0;
}
if (col == 0) {
col = 6;
printf("\t");
} else {
printf(", ");
}
- printf(names);
+ printf(usage_array[i].aname);
col += len2;
- names += len2 - 1;
}
printf("\n\n");
printf("=head1 COMMAND DESCRIPTIONS\n\n");
printf("=over 4\n\n");
- names = applet_names;
- usage = usage_messages;
- while (*names) {
- if (*names >= 'a' && *names <= 'z'
- && *usage != NOUSAGE_STR[0]
+ for (i = 0; i < num_messages; i++) {
+ if (usage_array[i].aname[0] >= 'a' && usage_array[i].aname[0] <= 'z'
+ && usage_array[i].usage[0] != NOUSAGE_STR[0]
) {
- printf("=item B<%s>\n\n", names);
- if (*usage)
- printf("%s %s\n\n", names, usage);
+ printf("=item B<%s>\n\n", usage_array[i].aname);
+ if (usage_array[i].usage[0])
+ printf("%s %s\n\n", usage_array[i].aname, usage_array[i].usage);
else
- printf("%s\n\n", names);
+ printf("%s\n\n", usage_array[i].aname);
}
- names += strlen(names) + 1;
- usage += strlen(usage) + 1;
}
return 0;
}
/* TODO: we used to make options bold with B<> and output an example too:
diff --git a/archival/Config.in b/archival/Config.src
index fb79c7bca..9a84fd6c6 100644
--- a/archival/Config.in
+++ b/archival/Config.src
@@ -2,39 +2,47 @@
# For a description of the syntax of this configuration file,
# see scripts/kbuild/config-language.txt.
#
menu "Archival Utilities"
+INSERT
+
+config FEATURE_SEAMLESS_XZ
+ bool "Make tar, rpm, modprobe etc understand .xz data"
+ default y
+ help
+ Make tar, rpm, modprobe etc understand .xz data.
+
config FEATURE_SEAMLESS_LZMA
bool "Make tar, rpm, modprobe etc understand .lzma data"
- default n
+ default y
help
Make tar, rpm, modprobe etc understand .lzma data.
config FEATURE_SEAMLESS_BZ2
bool "Make tar, rpm, modprobe etc understand .bz2 data"
- default n
+ default y
help
Make tar, rpm, modprobe etc understand .bz2 data.
config FEATURE_SEAMLESS_GZ
bool "Make tar, rpm, modprobe etc understand .gz data"
- default n
+ default y
help
Make tar, rpm, modprobe etc understand .gz data.
config FEATURE_SEAMLESS_Z
bool "Make tar and gunzip understand .Z data"
default n
help
Make tar and gunzip understand .Z data.
config AR
bool "ar"
- default n
+ default n # needs to be improved to be able to replace binutils ar
help
ar is an archival utility program used to create, modify, and
extract contents from archives. An archive is a single file holding
a collection of other files in a structure that makes it possible to
retrieve the original individual files (called archive members).
The original files' contents, mode (permissions), timestamp, owner,
@@ -51,49 +59,56 @@ config AR
Unless you have a specific application which requires ar, you should
probably say N here.
config FEATURE_AR_LONG_FILENAMES
bool "Support for long filenames (not needed for debs)"
- default n
+ default y
depends on AR
help
By default the ar format can only store the first 15 characters
of the filename, this option removes that limitation.
It supports the GNU ar long filename method which moves multiple long
filenames into a the data section of a new ar entry.
+config FEATURE_AR_CREATE
+ bool "Support archive creation"
+ default y
+ depends on AR
+ help
+ This enables archive creation (-c and -r) with busybox ar.
+
config BUNZIP2
bool "bunzip2"
- default n
+ default y
help
bunzip2 is a compression utility using the Burrows-Wheeler block
sorting text compression algorithm, and Huffman coding. Compression
is generally considerably better than that achieved by more
conventional LZ77/LZ78-based compressors, and approaches the
performance of the PPM family of statistical compressors.
Unless you have a specific application which requires bunzip2, you
should probably say N here.
config BZIP2
bool "bzip2"
- default n
+ default y
help
bzip2 is a compression utility using the Burrows-Wheeler block
sorting text compression algorithm, and Huffman coding. Compression
is generally considerably better than that achieved by more
conventional LZ77/LZ78-based compressors, and approaches the
performance of the PPM family of statistical compressors.
Unless you have a specific application which requires bzip2, you
should probably say N here.
config CPIO
bool "cpio"
- default n
+ default y
help
cpio is an archival utility program used to create, modify, and
extract contents from archives.
cpio has 110 bytes of overheads for every stored file.
This implementation of cpio can extract cpio archives created in the
@@ -101,21 +116,21 @@ config CPIO
Unless you have a specific application which requires cpio, you
should probably say N here.
config FEATURE_CPIO_O
bool "Support for archive creation"
- default n
+ default y
depends on CPIO
help
This implementation of cpio can create cpio archives in the "newc"
format only.
config FEATURE_CPIO_P
bool "Support for passthrough mode"
- default n
+ default y
depends on FEATURE_CPIO_O
help
Passthrough mode. Rarely used.
config DPKG
bool "dpkg"
@@ -149,35 +164,35 @@ config FEATURE_DPKG_DEB_EXTRACT_ONLY
"ar -p <deb> data.tar.gz | tar -zx". However it saves space as none
of the extra dpkg-deb, ar or tar options are needed, they are linked
to internally.
config GUNZIP
bool "gunzip"
- default n
+ default y
help
gunzip is used to decompress archives created by gzip.
You can use the `-t' option to test the integrity of
an archive, without decompressing it.
config GZIP
bool "gzip"
- default n
+ default y
help
gzip is used to compress files.
It's probably the most widely used UNIX compression program.
config FEATURE_GZIP_LONG_OPTIONS
bool "Enable long options"
- default n
+ default y
depends on GZIP && LONG_OPTS
help
Enable use of long options, increases size by about 106 Bytes
config LZOP
bool "lzop"
- default n
+ default y
help
Lzop compression/decompresion.
config LZOP_COMPR_HIGH
bool "lzop complession levels 7,8,9 (not very useful)"
default n
@@ -186,119 +201,132 @@ config LZOP_COMPR_HIGH
High levels (7,8,9) of lzop compression. These levels
are actually slower than gzip at equivalent compression ratios
and take up 3.2K of code.
config RPM2CPIO
bool "rpm2cpio"
- default n
+ default y
help
Converts an RPM file into a CPIO archive.
config RPM
bool "rpm"
- default n
+ default y
help
Mini RPM applet - queries and extracts RPM packages.
config TAR
bool "tar"
- default n
+ default y
help
tar is an archiving program. It's commonly used with gzip to
create compressed archives. It's probably the most widely used
UNIX archive program.
-if TAR
-
config FEATURE_TAR_CREATE
bool "Enable archive creation"
default y
depends on TAR
help
If you enable this option you'll be able to create
tar archives using the `-c' option.
config FEATURE_TAR_AUTODETECT
bool "Autodetect compressed tarballs"
- default n
- depends on FEATURE_SEAMLESS_Z || FEATURE_SEAMLESS_GZ || FEATURE_SEAMLESS_BZ2 || FEATURE_SEAMLESS_LZMA
+ default y
+ depends on TAR && (FEATURE_SEAMLESS_Z || FEATURE_SEAMLESS_GZ || FEATURE_SEAMLESS_BZ2 || FEATURE_SEAMLESS_LZMA || FEATURE_SEAMLESS_XZ)
help
With this option tar can automatically detect compressed
tarballs. Currently it works only on files (not pipes etc).
config FEATURE_TAR_FROM
bool "Enable -X (exclude from) and -T (include from) options)"
- default n
+ default y
depends on TAR
help
If you enable this option you'll be able to specify
a list of files to include or exclude from an archive.
config FEATURE_TAR_OLDGNU_COMPATIBILITY
bool "Support for old tar header format"
- default N
- depends on TAR
+ default y
+ depends on TAR || DPKG
help
This option is required to unpack archives created in
the old GNU format; help to kill this old format by
repacking your ancient archives with the new format.
config FEATURE_TAR_OLDSUN_COMPATIBILITY
bool "Enable untarring of tarballs with checksums produced by buggy Sun tar"
- default N
- depends on TAR
+ default y
+ depends on TAR || DPKG
help
This option is required to unpack archives created by some old
version of Sun's tar (it was calculating checksum using signed
arithmetic). It is said to be fixed in newer Sun tar, but "old"
tarballs still exist.
config FEATURE_TAR_GNU_EXTENSIONS
bool "Support for GNU tar extensions (long filenames)"
default y
- depends on TAR
+ depends on TAR || DPKG
help
With this option busybox supports GNU long filenames and
linknames.
config FEATURE_TAR_LONG_OPTIONS
bool "Enable long options"
- default n
+ default y
depends on TAR && LONG_OPTS
help
Enable use of long options, increases size by about 400 Bytes
+config FEATURE_TAR_TO_COMMAND
+ bool "Support for writing to an external program"
+ default y
+ depends on TAR && FEATURE_TAR_LONG_OPTIONS
+ help
+ If you enable this option you'll be able to instruct tar to send
+ the contents of each extracted file to the standard input of an
+ external program.
+
config FEATURE_TAR_UNAME_GNAME
bool "Enable use of user and group names"
- default n
+ default y
depends on TAR
help
Enables use of user and group names in tar. This affects contents
listings (-t) and preserving permissions when unpacking (-p).
+200 bytes.
config FEATURE_TAR_NOPRESERVE_TIME
bool "Enable -m (do not preserve time) option"
- default n
+ default y
depends on TAR
help
With this option busybox supports GNU tar -m
(do not preserve time) option.
-endif #tar
+config FEATURE_TAR_SELINUX
+ bool "Support for extracting SELinux labels"
+ default n
+ depends on TAR && SELINUX
+ help
+ With this option busybox supports restoring SELinux labels
+ when extracting files from tar archives.
config UNCOMPRESS
bool "uncompress"
default n
help
uncompress is used to decompress archives created by compress.
Not much used anymore, replaced by gzip/gunzip.
config UNLZMA
bool "unlzma"
- default n
+ default y
help
unlzma is a compression utility using the Lempel-Ziv-Markov chain
compression algorithm, and range coding. Compression
is generally considerably better than that achieved by the bzip2
compressors.
@@ -307,21 +335,43 @@ config UNLZMA
Unless you have a specific application which requires unlzma, you
should probably say N here.
config FEATURE_LZMA_FAST
bool "Optimize unlzma for speed"
- default n
+ default y
depends on UNLZMA
help
This option reduces decompression time by about 25% at the cost of
a 1K bigger binary.
+config LZMA
+ bool "Provide lzma alias which supports only unpacking"
+ default y
+ depends on UNLZMA
+ help
+ Enable this option if you want commands like "lzma -d" to work.
+ IOW: you'll get lzma applet, but it will always require -d option.
+
+config UNXZ
+ bool "unxz"
+ default y
+ help
+ unxz is a unlzma successor.
+
+config XZ
+ bool "Provide xz alias which supports only unpacking"
+ default y
+ depends on UNXZ
+ help
+ Enable this option if you want commands like "xz -d" to work.
+ IOW: you'll get xz applet, but it will always require -d option.
+
config UNZIP
bool "unzip"
- default n
+ default y
help
unzip will list or extract files from a ZIP archive,
commonly found on DOS/WIN systems. The default behavior
(with no options) is to extract the archive into the
current directory. Use the `-d' option to extract to a
directory of your choice.
diff --git a/archival/Kbuild b/archival/Kbuild.src
index 53bd7e21e..076e58278 100644
--- a/archival/Kbuild
+++ b/archival/Kbuild.src
@@ -4,22 +4,28 @@
#
# Licensed under the GPL v2, see the file LICENSE in this tarball.
libs-y += libunarchive/
lib-y:=
+
+INSERT
+
lib-$(CONFIG_AR) += ar.o
-lib-$(CONFIG_BUNZIP2) += bbunzip.o
-lib-$(CONFIG_BZIP2) += bzip2.o bbunzip.o
-lib-$(CONFIG_UNLZMA) += bbunzip.o
lib-$(CONFIG_CPIO) += cpio.o
lib-$(CONFIG_DPKG) += dpkg.o
lib-$(CONFIG_DPKG_DEB) += dpkg_deb.o
-lib-$(CONFIG_GUNZIP) += bbunzip.o
-lib-$(CONFIG_GZIP) += gzip.o bbunzip.o
-lib-$(CONFIG_LZOP) += lzop.o lzo1x_1.o lzo1x_1o.o lzo1x_d.o bbunzip.o
-lib-$(CONFIG_LZOP_COMPR_HIGH) += lzo1x_9x.o
lib-$(CONFIG_RPM2CPIO) += rpm2cpio.o
lib-$(CONFIG_RPM) += rpm.o
lib-$(CONFIG_TAR) += tar.o
-lib-$(CONFIG_UNCOMPRESS) += bbunzip.o
lib-$(CONFIG_UNZIP) += unzip.o
+
+lib-$(CONFIG_LZOP) += lzop.o lzo1x_1.o lzo1x_1o.o lzo1x_d.o bbunzip.o
+lib-$(CONFIG_LZOP_COMPR_HIGH) += lzo1x_9x.o
+lib-$(CONFIG_GZIP) += gzip.o bbunzip.o
+lib-$(CONFIG_BZIP2) += bzip2.o bbunzip.o
+
+lib-$(CONFIG_UNXZ) += bbunzip.o
+lib-$(CONFIG_UNLZMA) += bbunzip.o
+lib-$(CONFIG_BUNZIP2) += bbunzip.o
+lib-$(CONFIG_GUNZIP) += bbunzip.o
+lib-$(CONFIG_UNCOMPRESS) += bbunzip.o
diff --git a/archival/ar.c b/archival/ar.c
index fd7f8e4db..1b7b66a57 100644
--- a/archival/ar.c
+++ b/archival/ar.c
@@ -5,84 +5,248 @@
* Copyright (C) 2000 by Glenn McGrath
*
* Based in part on BusyBox tar, Debian dpkg-deb and GNU ar.
*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*
+ * Archive creation support:
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ * Written by Alexander Shishkin.
+ *
* There is no single standard to adhere to so ar may not portable
* between different systems
* http://www.unix-systems.org/single_unix_specification_v2/xcu/ar.html
*/
#include "libbb.h"
#include "unarchive.h"
+#include "ar.h"
+
+#if ENABLE_FEATURE_AR_CREATE
+/* filter out entries with same names as specified on the command line */
+static char FAST_FUNC filter_replaceable(archive_handle_t *handle)
+{
+ if (find_list_entry(handle->accept, handle->file_header->name))
+ return EXIT_FAILURE;
+
+ return EXIT_SUCCESS;
+}
+
+static void output_ar_header(archive_handle_t *handle)
+{
+ /* GNU ar 2.19.51.0.14 creates malformed archives
+ * if input files are >10G. It also truncates files >4GB
+ * (uses "size mod 4G"). We abort in this case:
+ * We could add support for up to 10G files, but this is unlikely to be useful.
+ * Note that unpacking side limits all fields to "unsigned int" data type,
+ * and treats "all ones" as an error indicator. Thus max we allow here is UINT_MAX-1.
+ */
+ enum {
+ /* for 2nd field: mtime */
+ MAX11CHARS = UINT_MAX > 0xffffffff ? (unsigned)99999999999 : UINT_MAX-1,
+ /* for last field: filesize */
+ MAX10CHARS = UINT_MAX > 0xffffffff ? (unsigned)9999999999 : UINT_MAX-1,
+ };
+
+ struct file_header_t *fh = handle->file_header;
+
+ if (handle->offset & 1) {
+ xwrite(handle->src_fd, "\n", 1);
+ handle->offset++;
+ }
+
+ /* Careful! The widths should be exact. Fields must be separated */
+ if (sizeof(off_t) > 4 && fh->size > (off_t)MAX10CHARS) {
+ bb_error_msg_and_die("'%s' is bigger than ar can handle", fh->name);
+ }
+ fdprintf(handle->src_fd, "%-16.16s%-12lu%-6u%-6u%-8o%-10"OFF_FMT"u`\n",
+ fh->name,
+ (sizeof(time_t) > 4 && fh->mtime > MAX11CHARS) ? (long)0 : (long)fh->mtime,
+ fh->uid > 99999 ? 0 : (int)fh->uid,
+ fh->gid > 99999 ? 0 : (int)fh->gid,
+ (int)fh->mode & 07777777,
+ fh->size
+ );
+
+ handle->offset += AR_HEADER_LEN;
+}
+
+/*
+ * when replacing files in an existing archive, copy from the the
+ * original archive those files that are to be left intact
+ */
+static void FAST_FUNC copy_data(archive_handle_t *handle)
+{
+ archive_handle_t *out_handle = handle->ar__out;
+ struct file_header_t *fh = handle->file_header;
+
+ out_handle->file_header = fh;
+ output_ar_header(out_handle);
+
+ bb_copyfd_exact_size(handle->src_fd, out_handle->src_fd, fh->size);
+ out_handle->offset += fh->size;
+}
+
+static int write_ar_header(archive_handle_t *handle)
+{
+ char *fn;
+ char fn_h[17]; /* 15 + "/" + NUL */
+ struct stat st;
+ int fd;
+
+ fn = llist_pop(&handle->accept);
+ if (!fn)
+ return -1;
+
+ xstat(fn, &st);
+
+ handle->file_header->mtime = st.st_mtime;
+ handle->file_header->uid = st.st_uid;
+ handle->file_header->gid = st.st_gid;
+ handle->file_header->mode = st.st_mode;
+ handle->file_header->size = st.st_size;
+ handle->file_header->name = fn_h;
+//TODO: if ENABLE_FEATURE_AR_LONG_FILENAMES...
+ sprintf(fn_h, "%.15s/", bb_basename(fn));
+
+ output_ar_header(handle);
+
+ fd = xopen(fn, O_RDONLY);
+ bb_copyfd_exact_size(fd, handle->src_fd, st.st_size);
+ close(fd);
+ handle->offset += st.st_size;
+
+ return 0;
+}
+
+static int write_ar_archive(archive_handle_t *handle)
+{
+ struct stat st;
+ archive_handle_t *out_handle;
+
+ if (fstat(handle->src_fd, &st) == -1)
+ bb_simple_perror_msg_and_die(handle->ar__name);
+
+ /* if archive exists, create a new handle for output.
+ * we create it in place of the old one.
+ */
+ if (st.st_size != 0) {
+ out_handle = init_handle();
+ xunlink(handle->ar__name);
+ out_handle->src_fd = xopen(handle->ar__name, O_WRONLY | O_CREAT | O_TRUNC);
+ out_handle->accept = handle->accept;
+ } else {
+ out_handle = handle;
+ }
+
+ handle->ar__out = out_handle;
+
+ xwrite(out_handle->src_fd, AR_MAGIC "\n", AR_MAGIC_LEN + 1);
+ out_handle->offset += AR_MAGIC_LEN + 1;
+
+ /* skip to the end of the archive if we have to append stuff */
+ if (st.st_size != 0) {
+ handle->filter = filter_replaceable;
+ handle->action_data = copy_data;
+ unpack_ar_archive(handle);
+ }
+
+ while (write_ar_header(out_handle) == 0)
+ continue;
+
+ /* optional, since we exit right after we return */
+ if (ENABLE_FEATURE_CLEAN_UP) {
+ close(handle->src_fd);
+ if (out_handle->src_fd != handle->src_fd)
+ close(out_handle->src_fd);
+ }
+
+ return EXIT_SUCCESS;
+}
+#endif /* FEATURE_AR_CREATE */
static void FAST_FUNC header_verbose_list_ar(const file_header_t *file_header)
{
const char *mode = bb_mode_string(file_header->mode);
char *mtime;
mtime = ctime(&file_header->mtime);
mtime[16] = ' ';
memmove(&mtime[17], &mtime[20], 4);
mtime[21] = '\0';
- printf("%s %d/%d%7d %s %s\n", &mode[1], file_header->uid, file_header->gid,
- (int) file_header->size, &mtime[4], file_header->name);
+ printf("%s %u/%u%7"OFF_FMT"u %s %s\n", &mode[1],
+ (int)file_header->uid, (int)file_header->gid,
+ file_header->size,
+ &mtime[4], file_header->name
+ );
}
-#define AR_CTX_PRINT 0x01
-#define AR_CTX_LIST 0x02
-#define AR_CTX_EXTRACT 0x04
-#define AR_OPT_PRESERVE_DATE 0x08
-#define AR_OPT_VERBOSE 0x10
-#define AR_OPT_CREATE 0x20
-#define AR_OPT_INSERT 0x40
+#define AR_OPT_VERBOSE (1 << 0)
+#define AR_OPT_PRESERVE_DATE (1 << 1)
+/* "ar r" implies create, but warns about it. c suppresses warning.
+ * bbox accepts but ignores it: */
+#define AR_OPT_CREATE (1 << 2)
+
+#define AR_CMD_PRINT (1 << 3)
+#define FIRST_CMD AR_CMD_PRINT
+#define AR_CMD_LIST (1 << 4)
+#define AR_CMD_EXTRACT (1 << 5)
+#define AR_CMD_INSERT (1 << 6)
int ar_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int ar_main(int argc UNUSED_PARAM, char **argv)
{
- static const char msg_unsupported_err[] ALIGN1 =
- "archive %s is not supported";
-
archive_handle_t *archive_handle;
- unsigned opt;
+ unsigned opt, t;
archive_handle = init_handle();
- /* Prepend '-' to the first argument if required */
- opt_complementary = "--:p:t:x:-1:p--tx:t--px:x--pt";
- opt = getopt32(argv, "ptxovcr");
+ /* --: prepend '-' to the first argument if required */
+ /* -1: at least one param is reqd */
+ /* one of p,t,x[,r] is required */
+ opt_complementary = "--:-1:p:t:x"IF_FEATURE_AR_CREATE(":r");
+ opt = getopt32(argv, "voc""ptx"IF_FEATURE_AR_CREATE("r"));
argv += optind;
- if (opt & AR_CTX_PRINT) {
+ t = opt / FIRST_CMD;
+ if (t & (t-1)) /* more than one of p,t,x[,r] are specified */
+ bb_show_usage();
+
+ if (opt & AR_CMD_PRINT) {
archive_handle->action_data = data_extract_to_stdout;
}
- if (opt & AR_CTX_LIST) {
+ if (opt & AR_CMD_LIST) {
archive_handle->action_header = header_list;
}
- if (opt & AR_CTX_EXTRACT) {
+ if (opt & AR_CMD_EXTRACT) {
archive_handle->action_data = data_extract_all;
}
if (opt & AR_OPT_PRESERVE_DATE) {
archive_handle->ah_flags |= ARCHIVE_RESTORE_DATE;
}
if (opt & AR_OPT_VERBOSE) {
archive_handle->action_header = header_verbose_list_ar;
}
- if (opt & AR_OPT_CREATE) {
- bb_error_msg_and_die(msg_unsupported_err, "creation");
- }
- if (opt & AR_OPT_INSERT) {
- bb_error_msg_and_die(msg_unsupported_err, "insertion");
- }
-
- archive_handle->src_fd = xopen(*argv++, O_RDONLY);
+#if ENABLE_FEATURE_AR_CREATE
+ archive_handle->ar__name = *argv;
+#endif
+ archive_handle->src_fd = xopen(*argv++,
+ (opt & AR_CMD_INSERT)
+ ? O_RDWR | O_CREAT
+ : O_RDONLY
+ );
- while (*argv) {
+ if (*argv)
archive_handle->filter = filter_accept_list;
- llist_add_to(&archive_handle->accept, *argv++);
+ while (*argv) {
+ llist_add_to_end(&archive_handle->accept, *argv++);
}
+#if ENABLE_FEATURE_AR_CREATE
+ if (opt & AR_CMD_INSERT)
+ return write_ar_archive(archive_handle);
+#endif
+
unpack_ar_archive(archive_handle);
return EXIT_SUCCESS;
}
diff --git a/archival/bbunzip.c b/archival/bbunzip.c
index df674bc6c..c1259ac46 100644
--- a/archival/bbunzip.c
+++ b/archival/bbunzip.c
@@ -1,23 +1,22 @@
/* vi: set sw=4 ts=4: */
/*
* Common code for gunzip-like applets
*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
-
#include "libbb.h"
#include "unarchive.h"
enum {
- OPT_STDOUT = 0x1,
- OPT_FORCE = 0x2,
-/* gunzip and bunzip2 only: */
- OPT_VERBOSE = 0x4,
- OPT_DECOMPRESS = 0x8,
- OPT_TEST = 0x10,
+ OPT_STDOUT = 1 << 0,
+ OPT_FORCE = 1 << 1,
+ /* only some decompressors: */
+ OPT_VERBOSE = 1 << 2,
+ OPT_DECOMPRESS = 1 << 3,
+ OPT_TEST = 1 << 4,
};
static
int open_to_or_warn(int to_fd, const char *filename, int flags, int mode)
{
int fd = open3_or_warn(filename, flags, mode);
@@ -25,15 +24,21 @@ int open_to_or_warn(int to_fd, const char *filename, int flags, int mode)
return 1;
}
xmove_fd(fd, to_fd);
return 0;
}
+char* FAST_FUNC append_ext(char *filename, const char *expected_ext)
+{
+ return xasprintf("%s.%s", filename, expected_ext);
+}
+
int FAST_FUNC bbunpack(char **argv,
- char* (*make_new_name)(char *filename),
- IF_DESKTOP(long long) int (*unpacker)(unpack_info_t *info)
+ IF_DESKTOP(long long) int FAST_FUNC (*unpacker)(unpack_info_t *info),
+ char* FAST_FUNC (*make_new_name)(char *filename, const char *expected_ext),
+ const char *expected_ext
)
{
struct stat stat_buf;
IF_DESKTOP(long long) int status;
char *filename, *new_name;
smallint exitcode = 0;
@@ -66,13 +71,13 @@ int FAST_FUNC bbunpack(char **argv,
goto err;
filename = NULL;
}
/* Open dst if we are going to unpack to file */
if (filename) {
- new_name = make_new_name(filename);
+ new_name = make_new_name(filename, expected_ext);
if (!new_name) {
bb_error_msg("%s: unknown suffix - ignored", filename);
goto err;
}
/* -f: overwrite existing output files */
@@ -138,62 +143,54 @@ int FAST_FUNC bbunpack(char **argv,
}
} while (*argv && *++argv);
return exitcode;
}
-#if ENABLE_BUNZIP2 || ENABLE_UNLZMA || ENABLE_UNCOMPRESS
-
+#if ENABLE_UNCOMPRESS || ENABLE_BUNZIP2 || ENABLE_UNLZMA || ENABLE_UNXZ
static
-char* make_new_name_generic(char *filename, const char *expected_ext)
+char* FAST_FUNC make_new_name_generic(char *filename, const char *expected_ext)
{
char *extension = strrchr(filename, '.');
if (!extension || strcmp(extension + 1, expected_ext) != 0) {
/* Mimic GNU gunzip - "real" bunzip2 tries to */
/* unpack file anyway, to file.out */
return NULL;
}
*extension = '\0';
return filename;
}
-
#endif
/*
- * Modified for busybox by Glenn McGrath
- * Added support output to stdout by Thomas Lundquist <thomasez@zelow.no>
+ * Uncompress applet for busybox (c) 2002 Glenn McGrath
*
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
-
-#if ENABLE_BUNZIP2
-
+#if ENABLE_UNCOMPRESS
static
-char* make_new_name_bunzip2(char *filename)
+IF_DESKTOP(long long) int FAST_FUNC unpack_uncompress(unpack_info_t *info UNUSED_PARAM)
{
- return make_new_name_generic(filename, "bz2");
-}
+ IF_DESKTOP(long long) int status = -1;
-static
-IF_DESKTOP(long long) int unpack_bunzip2(unpack_info_t *info UNUSED_PARAM)
-{
- return unpack_bz2_stream_prime(STDIN_FILENO, STDOUT_FILENO);
+ if ((xread_char(STDIN_FILENO) != 0x1f) || (xread_char(STDIN_FILENO) != 0x9d)) {
+ bb_error_msg("invalid magic");
+ } else {
+ status = unpack_Z_stream(STDIN_FILENO, STDOUT_FILENO);
+ }
+ return status;
}
-
-int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int bunzip2_main(int argc UNUSED_PARAM, char **argv)
+int uncompress_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int uncompress_main(int argc UNUSED_PARAM, char **argv)
{
- getopt32(argv, "cfvdt");
+ getopt32(argv, "cf");
argv += optind;
- if (applet_name[2] == 'c')
- option_mask32 |= OPT_STDOUT;
- return bbunpack(argv, make_new_name_bunzip2, unpack_bunzip2);
+ return bbunpack(argv, unpack_uncompress, make_new_name_generic, "Z");
}
-
#endif
/*
* Gzip implementation for busybox
*
@@ -218,17 +215,15 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv)
* written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
* Ken Turkowski, Dave Mack and Peter Jannesen.
*
* See the license_msg below and the file COPYING for the software license.
* See the file algorithm.doc for the compression algorithms and file formats.
*/
-
#if ENABLE_GUNZIP
-
static
-char* make_new_name_gunzip(char *filename)
+char* FAST_FUNC make_new_name_gunzip(char *filename, const char *expected_ext UNUSED_PARAM)
{
char *extension = strrchr(filename, '.');
if (!extension)
return NULL;
@@ -246,15 +241,14 @@ char* make_new_name_gunzip(char *filename)
extension[3] = 'r';
} else {
return NULL;
}
return filename;
}
-
static
-IF_DESKTOP(long long) int unpack_gunzip(unpack_info_t *info)
+IF_DESKTOP(long long) int FAST_FUNC unpack_gunzip(unpack_info_t *info)
{
IF_DESKTOP(long long) int status = -1;
/* do the decompression, and cleanup */
if (xread_char(STDIN_FILENO) == 0x1f) {
unsigned char magic2;
@@ -274,13 +268,12 @@ IF_DESKTOP(long long) int unpack_gunzip(unpack_info_t *info)
bad_magic:
bb_error_msg("invalid magic");
/* status is still == -1 */
}
return status;
}
-
/*
* Linux kernel build uses gzip -d -n. We accept and ignore it.
* Man page says:
* -n --no-name
* gzip: do not save the original file name and time stamp.
* (The original name is always saved if the name had to be truncated.)
@@ -288,97 +281,123 @@ IF_DESKTOP(long long) int unpack_gunzip(unpack_info_t *info)
* (remove only the gzip suffix from the compressed file name).
* This option is the default when decompressing.
* -N --name
* gzip: always save the original file name and time stamp (this is the default)
* gunzip: restore the original file name and time stamp if present.
*/
-
int gunzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int gunzip_main(int argc UNUSED_PARAM, char **argv)
{
getopt32(argv, "cfvdtn");
argv += optind;
/* if called as zcat */
if (applet_name[1] == 'c')
option_mask32 |= OPT_STDOUT;
- return bbunpack(argv, make_new_name_gunzip, unpack_gunzip);
+ return bbunpack(argv, unpack_gunzip, make_new_name_gunzip, /*unused:*/ NULL);
}
+#endif
+
+/*
+ * Modified for busybox by Glenn McGrath
+ * Added support output to stdout by Thomas Lundquist <thomasez@zelow.no>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+//usage:#define bunzip2_trivial_usage
+//usage: "[OPTIONS] [FILE]..."
+//usage:#define bunzip2_full_usage "\n\n"
+//usage: "Decompress FILEs (or stdin)\n"
+//usage: "\nOptions:"
+//usage: "\n -c Write to stdout"
+//usage: "\n -f Force"
+//usage:#define bzcat_trivial_usage
+//usage: "FILE"
+//usage:#define bzcat_full_usage "\n\n"
+//usage: "Decompress to stdout"
+//applet:IF_BUNZIP2(APPLET(bunzip2, _BB_DIR_USR_BIN, _BB_SUID_DROP))
+//applet:IF_BUNZIP2(APPLET_ODDNAME(bzcat, bunzip2, _BB_DIR_USR_BIN, _BB_SUID_DROP, bzcat))
+#if ENABLE_BUNZIP2
+static
+IF_DESKTOP(long long) int FAST_FUNC unpack_bunzip2(unpack_info_t *info UNUSED_PARAM)
+{
+ return unpack_bz2_stream_prime(STDIN_FILENO, STDOUT_FILENO);
+}
+int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int bunzip2_main(int argc UNUSED_PARAM, char **argv)
+{
+ getopt32(argv, "cfvdt");
+ argv += optind;
+ if (applet_name[2] == 'c') /* bzcat */
+ option_mask32 |= OPT_STDOUT;
+
+ return bbunpack(argv, unpack_bunzip2, make_new_name_generic, "bz2");
+}
#endif
/*
* Small lzma deflate implementation.
* Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.org>
*
* Based on bunzip.c from busybox
*
* Licensed under GPL v2, see file LICENSE in this tarball for details.
*/
-
#if ENABLE_UNLZMA
-
-static
-char* make_new_name_unlzma(char *filename)
-{
- return make_new_name_generic(filename, "lzma");
-}
-
static
-IF_DESKTOP(long long) int unpack_unlzma(unpack_info_t *info UNUSED_PARAM)
+IF_DESKTOP(long long) int FAST_FUNC unpack_unlzma(unpack_info_t *info UNUSED_PARAM)
{
return unpack_lzma_stream(STDIN_FILENO, STDOUT_FILENO);
}
-
int unlzma_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int unlzma_main(int argc UNUSED_PARAM, char **argv)
{
- getopt32(argv, "cf");
- argv += optind;
- /* lzmacat? */
- if (applet_name[4] == 'c')
+ IF_LZMA(int opts =) getopt32(argv, "cfvdt");
+# if ENABLE_LZMA
+ /* lzma without -d or -t? */
+ if (applet_name[2] == 'm' && !(opts & (OPT_DECOMPRESS|OPT_TEST)))
+ bb_show_usage();
+# endif
+ /* lzcat? */
+ if (applet_name[2] == 'c')
option_mask32 |= OPT_STDOUT;
- return bbunpack(argv, make_new_name_unlzma, unpack_unlzma);
+ argv += optind;
+ return bbunpack(argv, unpack_unlzma, make_new_name_generic, "lzma");
}
-
#endif
-/*
- * Uncompress applet for busybox (c) 2002 Glenn McGrath
- *
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
- */
-
-#if ENABLE_UNCOMPRESS
-
-static
-char* make_new_name_uncompress(char *filename)
-{
- return make_new_name_generic(filename, "Z");
-}
-
+#if ENABLE_UNXZ
static
-IF_DESKTOP(long long) int unpack_uncompress(unpack_info_t *info UNUSED_PARAM)
+IF_DESKTOP(long long) int FAST_FUNC unpack_unxz(unpack_info_t *info UNUSED_PARAM)
{
- IF_DESKTOP(long long) int status = -1;
-
- if ((xread_char(STDIN_FILENO) != 0x1f) || (xread_char(STDIN_FILENO) != 0x9d)) {
+ struct {
+ uint32_t v1;
+ uint16_t v2;
+ } magic;
+ xread(STDIN_FILENO, &magic, 6);
+ if (magic.v1 != XZ_MAGIC1a || magic.v2 != XZ_MAGIC2a) {
bb_error_msg("invalid magic");
- } else {
- status = unpack_Z_stream(STDIN_FILENO, STDOUT_FILENO);
+ return -1;
}
- return status;
+ return unpack_xz_stream(STDIN_FILENO, STDOUT_FILENO);
}
-
-int uncompress_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int uncompress_main(int argc UNUSED_PARAM, char **argv)
+int unxz_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int unxz_main(int argc UNUSED_PARAM, char **argv)
{
- getopt32(argv, "cf");
- argv += optind;
+ IF_XZ(int opts =) getopt32(argv, "cfvdt");
+# if ENABLE_XZ
+ /* xz without -d or -t? */
+ if (applet_name[2] == '\0' && !(opts & (OPT_DECOMPRESS|OPT_TEST)))
+ bb_show_usage();
+# endif
+ /* xzcat? */
+ if (applet_name[2] == 'c')
+ option_mask32 |= OPT_STDOUT;
- return bbunpack(argv, make_new_name_uncompress, unpack_uncompress);
+ argv += optind;
+ return bbunpack(argv, unpack_unxz, make_new_name_generic, "xz");
}
-
#endif
diff --git a/archival/bz/bzlib.c b/archival/bz/bzlib.c
index 9957c2fbd..834179403 100644
--- a/archival/bz/bzlib.c
+++ b/archival/bz/bzlib.c
@@ -390,16 +390,18 @@ int BZ2_bzBuffToBuffCompress(char* dest,
unsigned int sourceLen,
int blockSize100k)
{
bz_stream strm;
int ret;
- if (dest == NULL || destLen == NULL ||
- source == NULL ||
- blockSize100k < 1 || blockSize100k > 9)
+ if (dest == NULL || destLen == NULL
+ || source == NULL
+ || blockSize100k < 1 || blockSize100k > 9
+ ) {
return BZ_PARAM_ERROR;
+ }
BZ2_bzCompressInit(&strm, blockSize100k);
strm.next_in = source;
strm.next_out = dest;
strm.avail_in = sourceLen;
diff --git a/archival/bzip2.c b/archival/bzip2.c
index bbaf56669..fdb8b9306 100644
--- a/archival/bzip2.c
+++ b/archival/bzip2.c
@@ -85,13 +85,13 @@ IF_DESKTOP(long long) int bz_write(bz_stream *strm, void* rbuf, ssize_t rlen, vo
n = IOBUF_SIZE - strm->avail_out;
if (n) {
n2 = full_write(STDOUT_FILENO, wbuf, n);
if (n2 != n) {
if (n2 >= 0)
errno = 0; /* prevent bogus error message */
- bb_perror_msg(n2 >= 0 ? "short write" : "write error");
+ bb_perror_msg(n2 >= 0 ? "short write" : bb_msg_write_error);
return -1;
}
}
if (ret == BZ_STREAM_END)
break;
@@ -99,13 +99,13 @@ IF_DESKTOP(long long) int bz_write(bz_stream *strm, void* rbuf, ssize_t rlen, vo
break;
}
return 0 IF_DESKTOP( + strm->total_out );
}
static
-IF_DESKTOP(long long) int compressStream(unpack_info_t *info UNUSED_PARAM)
+IF_DESKTOP(long long) int FAST_FUNC compressStream(unpack_info_t *info UNUSED_PARAM)
{
IF_DESKTOP(long long) int total;
ssize_t count;
bz_stream bzs; /* it's small */
#define strm (&bzs)
char *iobuf;
@@ -115,13 +115,13 @@ IF_DESKTOP(long long) int compressStream(unpack_info_t *info UNUSED_PARAM)
iobuf = xmalloc(2 * IOBUF_SIZE);
BZ2_bzCompressInit(strm, level);
while (1) {
count = full_read(STDIN_FILENO, rbuf, IOBUF_SIZE);
if (count < 0) {
- bb_perror_msg("read error");
+ bb_perror_msg(bb_msg_read_error);
total = -1;
break;
}
/* if count == 0, bz_write finalizes compression */
total = bz_write(strm, rbuf, count, wbuf);
if (count == 0 || total < 0)
@@ -132,18 +132,12 @@ IF_DESKTOP(long long) int compressStream(unpack_info_t *info UNUSED_PARAM)
BZ2_bzCompressEnd(strm);
free(iobuf);
#endif
return total;
}
-static
-char* make_new_name_bzip2(char *filename)
-{
- return xasprintf("%s.bz2", filename);
-}
-
int bzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int bzip2_main(int argc UNUSED_PARAM, char **argv)
{
unsigned opt;
/* standard bzip2 flags
@@ -178,8 +172,8 @@ int bzip2_main(int argc UNUSED_PARAM, char **argv)
level++;
opt >>= 1;
}
argv += optind;
option_mask32 &= 0x7; /* ignore all except -cfv */
- return bbunpack(argv, make_new_name_bzip2, compressStream);
+ return bbunpack(argv, compressStream, append_ext, "bz2");
}
diff --git a/archival/cpio.c b/archival/cpio.c
index 858e59b30..e0ca7fa5c 100644
--- a/archival/cpio.c
+++ b/archival/cpio.c
@@ -308,12 +308,13 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
/* -L makes sense only with -o or -p */
#if !ENABLE_FEATURE_CPIO_O
/* no parameters */
opt_complementary = "=0";
opt = getopt32(argv, OPTION_STR, &cpio_filename);
+ argv += optind;
if (opt & CPIO_OPT_FILE) { /* -F */
xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO);
}
#else
/* _exactly_ one parameter for -p, thus <= 1 param if -p is allowed */
opt_complementary = ENABLE_FEATURE_CPIO_P ? "?1" : "=0";
@@ -421,11 +422,11 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
while (get_header_cpio(archive_handle) == EXIT_SUCCESS)
continue;
if (archive_handle->cpio__blocks != (off_t)-1
&& !(opt & CPIO_OPT_QUIET)
) {
- printf("%"OFF_FMT"u blocks\n", archive_handle->cpio__blocks);
+ fprintf(stderr, "%"OFF_FMT"u blocks\n", archive_handle->cpio__blocks);
}
return EXIT_SUCCESS;
}
diff --git a/archival/dpkg.c b/archival/dpkg.c
index 9f58b54e6..219512b9a 100644
--- a/archival/dpkg.c
+++ b/archival/dpkg.c
@@ -242,13 +242,13 @@ static int version_compare_part(const char *val, const char *ref)
* if ver1 > ver2 return 1,
*/
static int version_compare(const unsigned ver1, const unsigned ver2)
{
char *ch_ver1 = name_hashtable[ver1];
char *ch_ver2 = name_hashtable[ver2];
- unsigned long epoch1 = 0, epoch2 = 0;
+ unsigned epoch1 = 0, epoch2 = 0;
char *colon;
char *deb_ver1, *deb_ver2;
char *upstream_ver1;
char *upstream_ver2;
int result;
@@ -275,23 +275,22 @@ static int version_compare(const unsigned ver1, const unsigned ver2)
upstream_ver2 = xstrdup(ch_ver2);
/* Chop off debian version, and store for later use */
deb_ver1 = strrchr(upstream_ver1, '-');
deb_ver2 = strrchr(upstream_ver2, '-');
if (deb_ver1) {
- deb_ver1[0] = '\0';
- deb_ver1++;
+ *deb_ver1++ = '\0';
}
if (deb_ver2) {
- deb_ver2[0] = '\0';
- deb_ver2++;
+ *deb_ver2++ = '\0';
}
result = version_compare_part(upstream_ver1, upstream_ver2);
- if (!result)
+ if (result == 0) {
/* Compare debian versions */
result = version_compare_part(deb_ver1, deb_ver2);
+ }
free(upstream_ver1);
free(upstream_ver2);
return result;
}
@@ -855,14 +854,15 @@ static void write_status_file(deb_file_t **deb_file)
char *field_name;
char *field_value;
field_start += read_package_field(&control_buffer[field_start], &field_name, &field_value);
if (field_name == NULL) {
break;
}
- if ((strcmp(field_name, "Priority") == 0) ||
- (strcmp(field_name, "Section") == 0)) {
+ if ((strcmp(field_name, "Priority") == 0)
+ || (strcmp(field_name, "Section") == 0)
+ ) {
fprintf(new_status_file, "%s: %s\n", field_name, field_value);
}
}
write_flag = TRUE;
fputs("\n", new_status_file);
}
@@ -1076,14 +1076,15 @@ static int check_deps(deb_file_t **deb_file, int deb_start /*, int dep_max_count
number_of_alternatives = 1;
root_of_alternatives = NULL;
}
package_num = search_package_hashtable(package_edge->name, package_edge->version, package_edge->operator);
- if (package_edge->type == EDGE_PRE_DEPENDS ||
- package_edge->type == EDGE_DEPENDS) {
+ if (package_edge->type == EDGE_PRE_DEPENDS
+ || package_edge->type == EDGE_DEPENDS
+ ) {
int result=1;
status_num = 0;
/* If we are inside an alternative then check
* this edge is the right type.
*
@@ -1303,13 +1304,13 @@ static void list_packages(const char *pattern)
int j;
stat_str = name_hashtable[status_hashtable[i]->status];
name_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->name];
vers_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->version];
- if (pattern && fnmatch(pattern, name_str, 0))
+ if (pattern && fnmatch(pattern, name_str, 0) != 0)
continue;
/* get abbreviation for status field 1 */
s1 = stat_str[0] == 'i' ? 'i' : 'r';
/* get abbreviation for status field 2 */
@@ -1486,52 +1487,131 @@ static char *deb_extract_control_file_to_buffer(archive_handle_t *ar_handle, lli
unpack_ar_archive(ar_handle);
close(ar_handle->src_fd);
return ar_handle->dpkg__sub_archive->dpkg__buffer;
}
+static void append_control_file_to_llist(const char *package_name, const char *control_name, llist_t **ll)
+{
+ FILE *fp;
+ char *filename, *line;
+
+ filename = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, control_name);
+ fp = fopen_for_read(filename);
+ free(filename);
+ if (fp != NULL) {
+ while ((line = xmalloc_fgetline(fp)) != NULL)
+ llist_add_to(ll, line);
+ fclose(fp);
+ }
+}
+
+static char FAST_FUNC filter_rename_config(archive_handle_t *archive_handle)
+{
+ int fd;
+ char *name_ptr = archive_handle->file_header->name + 1;
+
+ /* Is this file marked as config file? */
+ if (!find_list_entry(archive_handle->accept, name_ptr))
+ return EXIT_SUCCESS; /* no */
+
+ fd = open(name_ptr, O_RDONLY);
+ if (fd >= 0) {
+ md5_ctx_t md5;
+ char *md5line, *buf;
+ int count;
+
+ /* Calculate MD5 of existing file */
+ buf = xmalloc(4096);
+ md5_begin(&md5);
+ while ((count = safe_read(fd, buf, 4096)) > 0)
+ md5_hash(buf, count, &md5);
+ md5_end(buf, &md5); /* using buf as result storage */
+ close(fd);
+
+ md5line = xmalloc(16 * 2 + 2 + strlen(name_ptr) + 1);
+ sprintf(bin2hex(md5line, buf, 16), " %s", name_ptr);
+ free(buf);
+
+ /* Is it changed after install? */
+ if (find_list_entry(archive_handle->accept, md5line) == NULL) {
+ printf("Warning: Creating %s as %s.dpkg-new\n", name_ptr, name_ptr);
+ archive_handle->file_header->name = xasprintf("%s.dpkg-new", archive_handle->file_header->name);
+ }
+ free(md5line);
+ }
+ return EXIT_SUCCESS;
+}
+
static void FAST_FUNC data_extract_all_prefix(archive_handle_t *archive_handle)
{
char *name_ptr = archive_handle->file_header->name;
/* Skip all leading "/" */
while (*name_ptr == '/')
name_ptr++;
/* Skip all leading "./" and "../" */
while (name_ptr[0] == '.') {
- if (name_ptr[1] == '.' && name_ptr[2] == '/')
+ if (name_ptr[1] == '.')
name_ptr++;
if (name_ptr[1] != '/')
break;
name_ptr += 2;
}
if (name_ptr[0] != '\0') {
archive_handle->file_header->name = xasprintf("%s%s", archive_handle->dpkg__buffer, name_ptr);
data_extract_all(archive_handle);
+ if (fnmatch("*.dpkg-new", archive_handle->file_header->name, 0) == 0) {
+ /* remove .dpkg-new suffix */
+ archive_handle->file_header->name[strlen(archive_handle->file_header->name) - 9] = '\0';
+ }
}
}
+enum {
+ /* Commands */
+ OPT_configure = (1 << 0),
+ OPT_install = (1 << 1),
+ OPT_list_installed = (1 << 2),
+ OPT_purge = (1 << 3),
+ OPT_remove = (1 << 4),
+ OPT_unpack = (1 << 5),
+ OPTMASK_cmd = (1 << 6) - 1,
+ /* Options */
+ OPT_force = (1 << 6),
+ OPT_force_ignore_depends = (1 << 7),
+ OPT_force_confnew = (1 << 8),
+ OPT_force_confold = (1 << 9),
+};
+
static void unpack_package(deb_file_t *deb_file)
{
const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name];
const unsigned status_num = search_status_hashtable(package_name);
const unsigned status_package_num = status_hashtable[status_num]->package;
char *info_prefix;
char *list_filename;
archive_handle_t *archive_handle;
FILE *out_stream;
llist_t *accept_list;
+ llist_t *conffile_list;
int i;
/* If existing version, remove it first */
+ conffile_list = NULL;
if (strcmp(name_hashtable[get_status(status_num, 3)], "installed") == 0) {
/* Package is already installed, remove old version first */
printf("Preparing to replace %s %s (using %s)...\n", package_name,
name_hashtable[package_hashtable[status_package_num]->version],
deb_file->filename);
+
+ /* Read md5sums from old package */
+ if (!(option_mask32 & OPT_force_confold))
+ append_control_file_to_llist(package_name, "md5sums", &conffile_list);
+
remove_package(status_package_num, 0);
} else {
printf("Unpacking %s (from %s)...\n", package_name, deb_file->filename);
}
/* Extract control.tar.gz to /var/lib/dpkg/info/<package>.filename */
@@ -1553,15 +1633,21 @@ static void unpack_package(deb_file_t *deb_file)
archive_handle->dpkg__sub_archive->ah_flags |= ARCHIVE_UNLINK_OLD;
unpack_ar_archive(archive_handle);
/* Run the preinst prior to extracting */
run_package_script_or_die(package_name, "preinst");
+ /* Don't overwrite existing config files */
+ if (!(option_mask32 & OPT_force_confnew))
+ append_control_file_to_llist(package_name, "conffiles", &conffile_list);
+
/* Extract data.tar.gz to the root directory */
archive_handle = init_archive_deb_ar(deb_file->filename);
init_archive_deb_data(archive_handle);
+ archive_handle->dpkg__sub_archive->accept = conffile_list;
+ archive_handle->dpkg__sub_archive->filter = filter_rename_config;
archive_handle->dpkg__sub_archive->action_data = data_extract_all_prefix;
archive_handle->dpkg__sub_archive->dpkg__buffer = (char*)"/"; /* huh? */
archive_handle->dpkg__sub_archive->ah_flags |= ARCHIVE_UNLINK_OLD;
unpack_ar_archive(archive_handle);
/* Create the list file */
@@ -1609,46 +1695,63 @@ int dpkg_main(int argc UNUSED_PARAM, char **argv)
int opt;
int package_num;
int deb_count = 0;
int state_status;
int status_num;
int i;
- enum {
- OPT_configure = 0x1,
- OPT_force_ignore_depends = 0x2,
- OPT_install = 0x4,
- OPT_list_installed = 0x8,
- OPT_purge = 0x10,
- OPT_remove = 0x20,
- OPT_unpack = 0x40,
- };
+#if ENABLE_LONG_OPTS
+ static const char dpkg_longopts[] ALIGN1 =
+// FIXME: we use -C non-compatibly, should be:
+// "-C|--audit Check for broken package(s)"
+ "configure\0" No_argument "C"
+ "force\0" Required_argument "F"
+ "install\0" No_argument "i"
+ "list\0" No_argument "l"
+ "purge\0" No_argument "P"
+ "remove\0" No_argument "r"
+ "unpack\0" No_argument "u"
+ "force-depends\0" No_argument "\xff"
+ "force-confnew\0" No_argument "\xfe"
+ "force-confold\0" No_argument "\xfd"
+ ;
+#endif
INIT_G();
- opt = getopt32(argv, "CF:ilPru", &str_f);
+ IF_LONG_OPTS(applet_long_options = dpkg_longopts);
+ opt = getopt32(argv, "CilPruF:", &str_f);
+ argv += optind;
//if (opt & OPT_configure) ... // -C
- if (opt & OPT_force_ignore_depends) { // -F (--force in official dpkg)
- if (strcmp(str_f, "depends"))
- opt &= ~OPT_force_ignore_depends;
+ if (opt & OPT_force) { // -F (--force in official dpkg)
+ if (strcmp(str_f, "depends") == 0)
+ opt |= OPT_force_ignore_depends;
+ else if (strcmp(str_f, "confnew") == 0)
+ opt |= OPT_force_confnew;
+ else if (strcmp(str_f, "confold") == 0)
+ opt |= OPT_force_confold;
+ else
+ bb_show_usage();
+ option_mask32 = opt;
}
//if (opt & OPT_install) ... // -i
//if (opt & OPT_list_installed) ... // -l
//if (opt & OPT_purge) ... // -P
//if (opt & OPT_remove) ... // -r
//if (opt & OPT_unpack) ... // -u (--unpack in official dpkg)
- argv += optind;
- /* check for non-option argument if expected */
- if (!opt || (!argv[0] && !(opt && OPT_list_installed)))
+ if (!(opt & OPTMASK_cmd) /* no cmd */
+ || ((opt & OPTMASK_cmd) & ((opt & OPTMASK_cmd)-1)) /* more than one cmd */
+ ) {
bb_show_usage();
+ }
/* puts("(Reading database ... xxxxx files and directories installed.)"); */
index_status_file("/var/lib/dpkg/status");
/* if the list action was given print the installed packages and exit */
if (opt & OPT_list_installed) {
- list_packages(argv[0]);
+ list_packages(argv[0]); /* param can be NULL */
return EXIT_SUCCESS;
}
/* Read arguments and store relevant info in structs */
while (*argv) {
/* deb_count = nb_elem - 1 and we need nb_elem + 1 to allocate terminal node [NULL pointer] */
diff --git a/archival/dpkg_deb.c b/archival/dpkg_deb.c
index cfbd78420..45a791bba 100644
--- a/archival/dpkg_deb.c
+++ b/archival/dpkg_deb.c
@@ -29,20 +29,23 @@ int dpkg_deb_main(int argc, char **argv)
/* Setup an ar archive handle that refers to the gzip sub archive */
ar_archive = init_handle();
ar_archive->dpkg__sub_archive = tar_archive;
ar_archive->filter = filter_accept_list_reassign;
#if ENABLE_FEATURE_SEAMLESS_GZ
- llist_add_to(&(ar_archive->accept), (char*)"data.tar.gz");
+ llist_add_to(&ar_archive->accept, (char*)"data.tar.gz");
llist_add_to(&control_tar_llist, (char*)"control.tar.gz");
#endif
-
#if ENABLE_FEATURE_SEAMLESS_BZ2
- llist_add_to(&(ar_archive->accept), (char*)"data.tar.bz2");
+ llist_add_to(&ar_archive->accept, (char*)"data.tar.bz2");
llist_add_to(&control_tar_llist, (char*)"control.tar.bz2");
#endif
+#if ENABLE_FEATURE_SEAMLESS_LZMA
+ llist_add_to(&ar_archive->accept, (char*)"data.tar.lzma");
+ llist_add_to(&control_tar_llist, (char*)"control.tar.lzma");
+#endif
opt_complementary = "c--efXx:e--cfXx:f--ceXx:X--cefx:x--cefX";
opt = getopt32(argv, "cefXx");
argv += optind;
argc -= optind;
diff --git a/archival/gzip.c b/archival/gzip.c
index 139eaacea..620897b90 100644
--- a/archival/gzip.c
+++ b/archival/gzip.c
@@ -617,16 +617,18 @@ static int longest_match(IPos cur_match)
Assert(cur_match < G1.strstart, "no future");
match = G1.window + cur_match;
/* Skip to next match if the match length cannot increase
* or if the match length is less than 2:
*/
- if (match[best_len] != scan_end ||
- match[best_len - 1] != scan_end1 ||
- *match != *scan || *++match != scan[1])
+ if (match[best_len] != scan_end
+ || match[best_len - 1] != scan_end1
+ || *match != *scan || *++match != scan[1]
+ ) {
continue;
+ }
/* The check at best_len-1 can be removed because it will be made
* again later. (This heuristic is not always a win.)
* It is not necessary to compare scan[2] and match[2] since they
* are always equal when the other bytes match, given that
* the hash keys are equal and that HASH_BITS >= 8.
@@ -671,13 +673,13 @@ static void check_match(IPos start, IPos match, int length)
bb_error_msg(" start %d, match %d, length %d", start, match, length);
bb_error_msg("invalid match");
}
if (verbose > 1) {
bb_error_msg("\\[%d,%d]", start - match, length);
do {
- fputc(G1.window[start++], stderr);
+ bb_putchar_stderr(G1.window[start++]);
} while (--length != 0);
}
}
#else
# define check_match(start, match, length) ((void)0)
#endif
@@ -959,13 +961,13 @@ static void compress_block(ct_data * ltree, ct_data * dtree);
#ifndef DEBUG
/* Send a code of the given tree. c and tree must not have side effects */
# define SEND_CODE(c, tree) send_bits(tree[c].Code, tree[c].Len)
#else
# define SEND_CODE(c, tree) \
{ \
- if (verbose > 1) bb_error_msg("\ncd %3d ",(c)); \
+ if (verbose > 1) bb_error_msg("\ncd %3d ", (c)); \
send_bits(tree[c].Code, tree[c].Len); \
}
#endif
#define D_CODE(dist) \
((dist) < 256 ? G2.dist_code[dist] : G2.dist_code[256 + ((dist)>>7)])
@@ -1993,19 +1995,13 @@ static void zip(ulg time_stamp)
flush_outbuf();
}
/* ======================================================================== */
static
-char* make_new_name_gzip(char *filename)
-{
- return xasprintf("%s.gz", filename);
-}
-
-static
-IF_DESKTOP(long long) int pack_gzip(unpack_info_t *info UNUSED_PARAM)
+IF_DESKTOP(long long) int FAST_FUNC pack_gzip(unpack_info_t *info UNUSED_PARAM)
{
struct stat s;
/* Clear input and output buffers */
G1.outcnt = 0;
#ifdef DEBUG
@@ -2058,13 +2054,13 @@ static const char gzip_longopts[] ALIGN1 =
"fast\0" No_argument "1"
"best\0" No_argument "9"
;
#endif
/*
- * Linux kernel build uses gzip -d -n. We accept and ignore it.
+ * Linux kernel build uses gzip -d -n. We accept and ignore -n.
* Man page says:
* -n --no-name
* gzip: do not save the original file name and time stamp.
* (The original name is always saved if the name had to be truncated.)
* gunzip: do not restore the original file name/time even if present
* (remove only the gzip suffix from the compressed file name).
@@ -2108,8 +2104,8 @@ int gzip_main(int argc UNUSED_PARAM, char **argv)
ALLOC(uch, G1.window, 2L * WSIZE);
ALLOC(ush, G1.prev, 1L << BITS);
/* Initialise the CRC32 table */
G1.crc_32_tab = crc32_filltable(NULL, 0);
- return bbunpack(argv, make_new_name_gzip, pack_gzip);
+ return bbunpack(argv, pack_gzip, append_ext, "gz");
}
diff --git a/archival/libunarchive/Kbuild b/archival/libunarchive/Kbuild.src
index 11d23b25f..a8549570e 100644
--- a/archival/libunarchive/Kbuild
+++ b/archival/libunarchive/Kbuild.src
@@ -30,15 +30,18 @@ COMMON_FILES:= \
DPKG_FILES:= \
get_header_ar.o \
unpack_ar_archive.o \
get_header_tar.o \
filter_accept_list_reassign.o
+INSERT
+
lib-$(CONFIG_AR) += get_header_ar.o unpack_ar_archive.o
lib-$(CONFIG_BUNZIP2) += decompress_bunzip2.o
lib-$(CONFIG_UNLZMA) += decompress_unlzma.o
+lib-$(CONFIG_UNXZ) += decompress_unxz.o
lib-$(CONFIG_CPIO) += get_header_cpio.o
lib-$(CONFIG_DPKG) += $(DPKG_FILES)
lib-$(CONFIG_DPKG_DEB) += $(DPKG_FILES)
lib-$(CONFIG_GUNZIP) += decompress_unzip.o
lib-$(CONFIG_RPM2CPIO) += decompress_unzip.o get_header_cpio.o
lib-$(CONFIG_RPM) += open_transformer.o decompress_unzip.o get_header_cpio.o
@@ -46,11 +49,13 @@ lib-$(CONFIG_TAR) += get_header_tar.o
lib-$(CONFIG_UNCOMPRESS) += decompress_uncompress.o
lib-$(CONFIG_UNZIP) += decompress_unzip.o
lib-$(CONFIG_FEATURE_SEAMLESS_Z) += open_transformer.o decompress_uncompress.o
lib-$(CONFIG_FEATURE_SEAMLESS_GZ) += open_transformer.o decompress_unzip.o get_header_tar_gz.o
lib-$(CONFIG_FEATURE_SEAMLESS_BZ2) += open_transformer.o decompress_bunzip2.o get_header_tar_bz2.o
lib-$(CONFIG_FEATURE_SEAMLESS_LZMA) += open_transformer.o decompress_unlzma.o get_header_tar_lzma.o
+lib-$(CONFIG_FEATURE_SEAMLESS_XZ) += open_transformer.o decompress_unxz.o
lib-$(CONFIG_FEATURE_COMPRESS_USAGE) += decompress_bunzip2.o
+lib-$(CONFIG_FEATURE_TAR_TO_COMMAND) += data_extract_to_command.o
ifneq ($(lib-y),)
lib-y += $(COMMON_FILES)
endif
diff --git a/archival/libunarchive/data_extract_all.c b/archival/libunarchive/data_extract_all.c
index 58b05335b..00e67d405 100644
--- a/archival/libunarchive/data_extract_all.c
+++ b/archival/libunarchive/data_extract_all.c
@@ -9,29 +9,58 @@
void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
{
file_header_t *file_header = archive_handle->file_header;
int dst_fd;
int res;
+#if ENABLE_FEATURE_TAR_SELINUX
+ char *sctx = archive_handle->tar__next_file_sctx;
+ if (!sctx)
+ sctx = archive_handle->tar__global_sctx;
+ if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */
+ setfscreatecon(sctx);
+ free(archive_handle->tar__next_file_sctx);
+ archive_handle->tar__next_file_sctx = NULL;
+ }
+#endif
+
if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) {
char *slash = strrchr(file_header->name, '/');
if (slash) {
*slash = '\0';
bb_make_directory(file_header->name, -1, FILEUTILS_RECUR);
*slash = '/';
}
}
if (archive_handle->ah_flags & ARCHIVE_UNLINK_OLD) {
/* Remove the entry if it exists */
- if ((!S_ISDIR(file_header->mode))
- && (unlink(file_header->name) == -1)
- && (errno != ENOENT)
- ) {
- bb_perror_msg_and_die("can't remove old file %s",
- file_header->name);
+ if (!S_ISDIR(file_header->mode)) {
+ /* Is it hardlink?
+ * We encode hard links as regular files of size 0 with a symlink */
+ if (S_ISREG(file_header->mode)
+ && file_header->link_target
+ && file_header->size == 0
+ ) {
+ /* Ugly special case:
+ * tar cf t.tar hardlink1 hardlink2 hardlink1
+ * results in this tarball structure:
+ * hardlink1
+ * hardlink2 -> hardlink1
+ * hardlink1 -> hardlink1 <== !!!
+ */
+ if (strcmp(file_header->link_target, file_header->name) == 0)
+ goto ret;
+ }
+ /* Proceed with deleting */
+ if (unlink(file_header->name) == -1
+ && errno != ENOENT
+ ) {
+ bb_perror_msg_and_die("can't remove old file %s",
+ file_header->name);
+ }
}
}
else if (archive_handle->ah_flags & ARCHIVE_EXTRACT_NEWER) {
/* Remove the existing entry if its older than the extracted entry */
struct stat existing_sb;
if (lstat(file_header->name, &existing_sb) == -1) {
@@ -42,120 +71,128 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
else if (existing_sb.st_mtime >= file_header->mtime) {
if (!(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) {
bb_error_msg("%s not created: newer or "
"same age file exists", file_header->name);
}
data_skip(archive_handle);
- return;
+ goto ret;
}
else if ((unlink(file_header->name) == -1) && (errno != EISDIR)) {
bb_perror_msg_and_die("can't remove old file %s",
file_header->name);
}
}
/* Handle hard links separately
- * We identified hard links as regular files of size 0 with a symlink */
+ * We encode hard links as regular files of size 0 with a symlink */
if (S_ISREG(file_header->mode)
&& file_header->link_target
&& file_header->size == 0
) {
/* hard link */
res = link(file_header->link_target, file_header->name);
if ((res == -1) && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) {
bb_perror_msg("can't create %slink "
"from %s to %s", "hard",
file_header->name,
file_header->link_target);
}
- } else {
- /* Create the filesystem entry */
- switch (file_header->mode & S_IFMT) {
- case S_IFREG: {
- /* Regular file */
- int flags = O_WRONLY | O_CREAT | O_EXCL;
- if (archive_handle->ah_flags & ARCHIVE_O_TRUNC)
- flags = O_WRONLY | O_CREAT | O_TRUNC;
- dst_fd = xopen3(file_header->name,
- flags,
- file_header->mode
- );
- bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size);
- close(dst_fd);
- break;
+ /* Hardlinks have no separate mode/ownership, skip chown/chmod */
+ goto ret;
+ }
+
+ /* Create the filesystem entry */
+ switch (file_header->mode & S_IFMT) {
+ case S_IFREG: {
+ /* Regular file */
+ int flags = O_WRONLY | O_CREAT | O_EXCL;
+ if (archive_handle->ah_flags & ARCHIVE_O_TRUNC)
+ flags = O_WRONLY | O_CREAT | O_TRUNC;
+ dst_fd = xopen3(file_header->name,
+ flags,
+ file_header->mode
+ );
+ bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size);
+ close(dst_fd);
+ break;
+ }
+ case S_IFDIR:
+ res = mkdir(file_header->name, file_header->mode);
+ if ((res == -1)
+ && (errno != EISDIR) /* btw, Linux doesn't return this */
+ && (errno != EEXIST)
+ && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
+ ) {
+ bb_perror_msg("can't make dir %s", file_header->name);
}
- case S_IFDIR:
- res = mkdir(file_header->name, file_header->mode);
- if ((res == -1)
- && (errno != EISDIR) /* btw, Linux doesn't return this */
- && (errno != EEXIST)
- && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
- ) {
- bb_perror_msg("can't make dir %s", file_header->name);
- }
- break;
- case S_IFLNK:
- /* Symlink */
- res = symlink(file_header->link_target, file_header->name);
- if ((res == -1)
- && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
- ) {
- bb_perror_msg("can't create %slink "
- "from %s to %s", "sym",
- file_header->name,
- file_header->link_target);
- }
- break;
- case S_IFSOCK:
- case S_IFBLK:
- case S_IFCHR:
- case S_IFIFO:
- res = mknod(file_header->name, file_header->mode, file_header->device);
- if ((res == -1)
- && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
- ) {
- bb_perror_msg("can't create node %s", file_header->name);
- }
- break;
- default:
- bb_error_msg_and_die("unrecognized file type");
+ break;
+ case S_IFLNK:
+ /* Symlink */
+//TODO: what if file_header->link_target == NULL (say, corrupted tarball?)
+ res = symlink(file_header->link_target, file_header->name);
+ if ((res == -1)
+ && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
+ ) {
+ bb_perror_msg("can't create %slink "
+ "from %s to %s", "sym",
+ file_header->name,
+ file_header->link_target);
+ }
+ break;
+ case S_IFSOCK:
+ case S_IFBLK:
+ case S_IFCHR:
+ case S_IFIFO:
+ res = mknod(file_header->name, file_header->mode, file_header->device);
+ if ((res == -1)
+ && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
+ ) {
+ bb_perror_msg("can't create node %s", file_header->name);
}
+ break;
+ default:
+ bb_error_msg_and_die("unrecognized file type");
}
- if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_OWNER)) {
-#if ENABLE_FEATURE_TAR_UNAME_GNAME
- if (!(archive_handle->ah_flags & ARCHIVE_NUMERIC_OWNER)) {
+ if (!S_ISLNK(file_header->mode)) {
+ if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_OWNER)) {
uid_t uid = file_header->uid;
gid_t gid = file_header->gid;
-
- if (file_header->tar__uname) {
+#if ENABLE_FEATURE_TAR_UNAME_GNAME
+ if (!(archive_handle->ah_flags & ARCHIVE_NUMERIC_OWNER)) {
+ if (file_header->tar__uname) {
//TODO: cache last name/id pair?
- struct passwd *pwd = getpwnam(file_header->tar__uname);
- if (pwd) uid = pwd->pw_uid;
- }
- if (file_header->tar__gname) {
- struct group *grp = getgrnam(file_header->tar__gname);
- if (grp) gid = grp->gr_gid;
+ struct passwd *pwd = getpwnam(file_header->tar__uname);
+ if (pwd) uid = pwd->pw_uid;
+ }
+ if (file_header->tar__gname) {
+ struct group *grp = getgrnam(file_header->tar__gname);
+ if (grp) gid = grp->gr_gid;
+ }
}
+#endif
/* GNU tar 1.15.1 uses chown, not lchown */
chown(file_header->name, uid, gid);
- } else
-#endif
- chown(file_header->name, file_header->uid, file_header->gid);
- }
- if (!S_ISLNK(file_header->mode)) {
+ }
/* uclibc has no lchmod, glibc is even stranger -
* it has lchmod which seems to do nothing!
* so we use chmod... */
if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_PERM)) {
chmod(file_header->name, file_header->mode);
}
- /* same for utime */
if (archive_handle->ah_flags & ARCHIVE_RESTORE_DATE) {
struct timeval t[2];
t[1].tv_sec = t[0].tv_sec = file_header->mtime;
t[1].tv_usec = t[0].tv_usec = 0;
utimes(file_header->name, t);
}
}
+
+ ret: ;
+#if ENABLE_FEATURE_TAR_SELINUX
+ if (sctx) {
+ /* reset the context after creating an entry */
+ setfscreatecon(NULL);
+ }
+#endif
}
diff --git a/archival/libunarchive/data_extract_to_command.c b/archival/libunarchive/data_extract_to_command.c
new file mode 100644
index 000000000..95f5bc864
--- /dev/null
+++ b/archival/libunarchive/data_extract_to_command.c
@@ -0,0 +1,134 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+#include "unarchive.h"
+
+enum {
+ //TAR_FILETYPE,
+ TAR_MODE,
+ TAR_FILENAME,
+ TAR_REALNAME,
+#if ENABLE_FEATURE_TAR_UNAME_GNAME
+ TAR_UNAME,
+ TAR_GNAME,
+#endif
+ TAR_SIZE,
+ TAR_UID,
+ TAR_GID,
+ TAR_MAX,
+};
+
+static const char *const tar_var[] = {
+ // "FILETYPE",
+ "MODE",
+ "FILENAME",
+ "REALNAME",
+#if ENABLE_FEATURE_TAR_UNAME_GNAME
+ "UNAME",
+ "GNAME",
+#endif
+ "SIZE",
+ "UID",
+ "GID",
+};
+
+static void xputenv(char *str)
+{
+ if (putenv(str))
+ bb_error_msg_and_die(bb_msg_memory_exhausted);
+}
+
+static void str2env(char *env[], int idx, const char *str)
+{
+ env[idx] = xasprintf("TAR_%s=%s", tar_var[idx], str);
+ xputenv(env[idx]);
+}
+
+static void dec2env(char *env[], int idx, unsigned long long val)
+{
+ env[idx] = xasprintf("TAR_%s=%llu", tar_var[idx], val);
+ xputenv(env[idx]);
+}
+
+static void oct2env(char *env[], int idx, unsigned long val)
+{
+ env[idx] = xasprintf("TAR_%s=%lo", tar_var[idx], val);
+ xputenv(env[idx]);
+}
+
+void FAST_FUNC data_extract_to_command(archive_handle_t *archive_handle)
+{
+ file_header_t *file_header = archive_handle->file_header;
+
+#if 0 /* do we need this? ENABLE_FEATURE_TAR_SELINUX */
+ char *sctx = archive_handle->tar__next_file_sctx;
+ if (!sctx)
+ sctx = archive_handle->tar__global_sctx;
+ if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */
+ setfscreatecon(sctx);
+ free(archive_handle->tar__next_file_sctx);
+ archive_handle->tar__next_file_sctx = NULL;
+ }
+#endif
+
+ if ((file_header->mode & S_IFMT) == S_IFREG) {
+ pid_t pid;
+ int p[2], status;
+ char *tar_env[TAR_MAX];
+
+ memset(tar_env, 0, sizeof(tar_env));
+
+ xpipe(p);
+ pid = BB_MMU ? xfork() : xvfork();
+ if (pid == 0) {
+ /* Child */
+ /* str2env(tar_env, TAR_FILETYPE, "f"); - parent should do it once */
+ oct2env(tar_env, TAR_MODE, file_header->mode);
+ str2env(tar_env, TAR_FILENAME, file_header->name);
+ str2env(tar_env, TAR_REALNAME, file_header->name);
+#if ENABLE_FEATURE_TAR_UNAME_GNAME
+ str2env(tar_env, TAR_UNAME, file_header->tar__uname);
+ str2env(tar_env, TAR_GNAME, file_header->tar__gname);
+#endif
+ dec2env(tar_env, TAR_SIZE, file_header->size);
+ dec2env(tar_env, TAR_UID, file_header->uid);
+ dec2env(tar_env, TAR_GID, file_header->gid);
+ close(p[1]);
+ xdup2(p[0], STDIN_FILENO);
+ signal(SIGPIPE, SIG_DFL);
+ execl(DEFAULT_SHELL, DEFAULT_SHELL_SHORT_NAME, "-c", archive_handle->tar__to_command, NULL);
+ bb_perror_msg_and_die("can't execute '%s'", DEFAULT_SHELL);
+ }
+ close(p[0]);
+ /* Our caller is expected to do signal(SIGPIPE, SIG_IGN)
+ * so that we don't die if child don't read all the input: */
+ bb_copyfd_exact_size(archive_handle->src_fd, p[1], -file_header->size);
+ close(p[1]);
+
+ if (safe_waitpid(pid, &status, 0) == -1)
+ bb_perror_msg_and_die("waitpid");
+ if (WIFEXITED(status) && WEXITSTATUS(status))
+ bb_error_msg_and_die("'%s' returned status %d",
+ archive_handle->tar__to_command, WEXITSTATUS(status));
+ if (WIFSIGNALED(status))
+ bb_error_msg_and_die("'%s' terminated on signal %d",
+ archive_handle->tar__to_command, WTERMSIG(status));
+
+ if (!BB_MMU) {
+ int i;
+ for (i = 0; i < TAR_MAX; i++) {
+ if (tar_env[i])
+ bb_unsetenv_and_free(tar_env[i]);
+ }
+ }
+ }
+
+#if 0 /* ENABLE_FEATURE_TAR_SELINUX */
+ if (sctx)
+ /* reset the context after creating an entry */
+ setfscreatecon(NULL);
+#endif
+}
diff --git a/archival/libunarchive/decompress_bunzip2.c b/archival/libunarchive/decompress_bunzip2.c
index cd8df086e..bdbd39ac2 100644
--- a/archival/libunarchive/decompress_bunzip2.c
+++ b/archival/libunarchive/decompress_bunzip2.c
@@ -689,15 +689,15 @@ unpack_bz2_stream(int src_fd, int dst_fd)
return i ? i : IF_DESKTOP(total_written) + 0;
}
IF_DESKTOP(long long) int FAST_FUNC
unpack_bz2_stream_prime(int src_fd, int dst_fd)
{
- unsigned char magic[2];
- xread(src_fd, magic, 2);
- if (magic[0] != 'B' || magic[1] != 'Z') {
+ uint16_t magic2;
+ xread(src_fd, &magic2, 2);
+ if (magic2 != BZIP2_MAGIC) {
bb_error_msg_and_die("invalid magic");
}
return unpack_bz2_stream(src_fd, dst_fd);
}
#ifdef TESTING
diff --git a/archival/libunarchive/decompress_uncompress.c b/archival/libunarchive/decompress_uncompress.c
index 2877c8981..1ff89ce3c 100644
--- a/archival/libunarchive/decompress_uncompress.c
+++ b/archival/libunarchive/decompress_uncompress.c
@@ -226,13 +226,13 @@ unpack_Z_stream(int fd_in, int fd_out)
p = &inbuf[posbits >> 3];
bb_error_msg
("insize:%d posbits:%d inbuf:%02X %02X %02X %02X %02X (%d)",
insize, posbits, p[-1], p[0], p[1], p[2], p[3],
(posbits & 07));
- bb_error_msg("uncompress: corrupt input");
+ bb_error_msg("corrupted data");
goto err;
}
*--stackp = (unsigned char) finchar;
code = oldcode;
}
diff --git a/archival/libunarchive/decompress_unxz.c b/archival/libunarchive/decompress_unxz.c
new file mode 100644
index 000000000..721acd907
--- /dev/null
+++ b/archival/libunarchive/decompress_unxz.c
@@ -0,0 +1,106 @@
+/*
+ * This file uses XZ Embedded library code which is written
+ * by Lasse Collin <lasse.collin@tukaani.org>
+ * and Igor Pavlov <http://7-zip.org/>
+ *
+ * See README file in unxz/ directory for more information.
+ *
+ * This file is:
+ * Copyright (C) 2010 Denys Vlasenko <vda.linux@googlemail.com>
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
+ */
+#include "libbb.h"
+#include "unarchive.h"
+
+#define XZ_FUNC FAST_FUNC
+#define XZ_EXTERN static
+
+#define XZ_DEC_DYNALLOC
+
+/* Skip check (rather than fail) of unsupported hash functions */
+#define XZ_DEC_ANY_CHECK 1
+
+/* We use our own crc32 function */
+#define XZ_INTERNAL_CRC32 0
+static uint32_t *crc32_table;
+static uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc)
+{
+ crc = ~crc;
+
+ while (size != 0) {
+ crc = crc32_table[*buf++ ^ (crc & 0xFF)] ^ (crc >> 8);
+ --size;
+ }
+
+ return ~crc;
+}
+
+/* We use arch-optimized unaligned accessors */
+#define get_unaligned_le32(buf) ({ uint32_t v; move_from_unaligned32(v, buf); SWAP_LE32(v); })
+#define get_unaligned_be32(buf) ({ uint32_t v; move_from_unaligned32(v, buf); SWAP_BE32(v); })
+#define put_unaligned_le32(val, buf) move_to_unaligned16(buf, SWAP_LE32(val))
+#define put_unaligned_be32(val, buf) move_to_unaligned16(buf, SWAP_BE32(val))
+
+#include "unxz/xz_dec_bcj.c"
+#include "unxz/xz_dec_lzma2.c"
+#include "unxz/xz_dec_stream.c"
+
+IF_DESKTOP(long long) int FAST_FUNC
+unpack_xz_stream(int src_fd, int dst_fd)
+{
+ struct xz_buf iobuf;
+ struct xz_dec *state;
+ unsigned char *membuf;
+ IF_DESKTOP(long long) int total = 0;
+
+ if (!crc32_table)
+ crc32_table = crc32_filltable(NULL, /*endian:*/ 0);
+
+ memset(&iobuf, 0, sizeof(iobuf));
+ /* Preload XZ file signature */
+ membuf = (void*) strcpy(xmalloc(2 * BUFSIZ), HEADER_MAGIC);
+ iobuf.in = membuf;
+ iobuf.in_size = HEADER_MAGIC_SIZE;
+ iobuf.out = membuf + BUFSIZ;
+ iobuf.out_size = BUFSIZ;
+
+ /* Limit memory usage to about 64 MiB. */
+ state = xz_dec_init(XZ_DYNALLOC, 64*1024*1024);
+
+ while (1) {
+ enum xz_ret r;
+
+ if (iobuf.in_pos == iobuf.in_size) {
+ int rd = safe_read(src_fd, membuf, BUFSIZ);
+ if (rd < 0) {
+ bb_error_msg(bb_msg_read_error);
+ total = -1;
+ break;
+ }
+ iobuf.in_size = rd;
+ iobuf.in_pos = 0;
+ }
+// bb_error_msg(">in pos:%d size:%d out pos:%d size:%d",
+// iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size);
+ r = xz_dec_run(state, &iobuf);
+// bb_error_msg("<in pos:%d size:%d out pos:%d size:%d r:%d",
+// iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size, r);
+ if (iobuf.out_pos) {
+ xwrite(dst_fd, iobuf.out, iobuf.out_pos);
+ IF_DESKTOP(total += iobuf.out_pos;)
+ iobuf.out_pos = 0;
+ }
+ if (r == XZ_STREAM_END) {
+ break;
+ }
+ if (r != XZ_OK && r != XZ_UNSUPPORTED_CHECK) {
+ bb_error_msg("corrupted data");
+ total = -1;
+ break;
+ }
+ }
+ xz_dec_end(state);
+ free(membuf);
+
+ return total;
+}
diff --git a/archival/libunarchive/decompress_unzip.c b/archival/libunarchive/decompress_unzip.c
index feaa047bd..bccd0262e 100644
--- a/archival/libunarchive/decompress_unzip.c
+++ b/archival/libunarchive/decompress_unzip.c
@@ -572,19 +572,22 @@ static NOINLINE int inflate_codes(STATE_PARAM_ONLY)
/* do the copy */
do_copy:
do {
/* Was: nn -= (e = (e = GUNZIP_WSIZE - ((dd &= GUNZIP_WSIZE - 1) > w ? dd : w)) > nn ? nn : e); */
/* Who wrote THAT?? rewritten as: */
+ unsigned delta;
+
dd &= GUNZIP_WSIZE - 1;
e = GUNZIP_WSIZE - (dd > w ? dd : w);
+ delta = w > dd ? w - dd : dd - w;
if (e > nn) e = nn;
nn -= e;
/* copy to new buffer to prevent possible overwrite */
- if (w - dd >= e) { /* (this test assumes unsigned comparison) */
+ if (delta >= e) {
memcpy(gunzip_window + w, gunzip_window + dd, e);
w += e;
dd += e;
} else {
/* do it slow to avoid memcpy() overlap */
/* !NOMEMCPY */
@@ -1066,13 +1069,13 @@ static int top_up(STATE_PARAM unsigned n)
if (count < (int)n) {
memmove(bytebuffer, &bytebuffer[bytebuffer_offset], count);
bytebuffer_offset = 0;
bytebuffer_size = full_read(gunzip_src_fd, &bytebuffer[count], bytebuffer_max - count);
if ((int)bytebuffer_size < 0) {
- bb_error_msg("read error");
+ bb_error_msg(bb_msg_read_error);
return 0;
}
bytebuffer_size += count;
if (bytebuffer_size < n)
return 0;
}
diff --git a/archival/libunarchive/get_header_ar.c b/archival/libunarchive/get_header_ar.c
index 2f38279cc..dbc5ec004 100644
--- a/archival/libunarchive/get_header_ar.c
+++ b/archival/libunarchive/get_header_ar.c
@@ -3,12 +3,13 @@
*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
#include "libbb.h"
#include "unarchive.h"
+#include "ar.h"
static unsigned read_num(const char *str, int base)
{
/* This code works because
* on misformatted numbers bb_strtou returns all-ones */
int err = bb_strtou(str, NULL, base);
@@ -20,21 +21,13 @@ static unsigned read_num(const char *str, int base)
char FAST_FUNC get_header_ar(archive_handle_t *archive_handle)
{
file_header_t *typed = archive_handle->file_header;
unsigned size;
union {
char raw[60];
- struct {
- char name[16];
- char date[12];
- char uid[6];
- char gid[6];
- char mode[8];
- char size[10];
- char magic[2];
- } formatted;
+ struct ar_header formatted;
} ar;
#if ENABLE_FEATURE_AR_LONG_FILENAMES
static char *ar_long_names;
static unsigned ar_long_name_size;
#endif
@@ -52,19 +45,19 @@ char FAST_FUNC get_header_ar(archive_handle_t *archive_handle)
memmove(ar.raw, &ar.raw[1], 59);
ar.raw[59] = xread_char(archive_handle->src_fd);
archive_handle->offset++;
}
archive_handle->offset += 60;
- /* align the headers based on the header magic */
if (ar.formatted.magic[0] != '`' || ar.formatted.magic[1] != '\n')
bb_error_msg_and_die("invalid ar header");
/* FIXME: more thorough routine would be in order here
* (we have something like that in tar)
* but for now we are lax. */
+ ar.formatted.magic[0] = '\0'; /* else 4G-2 file will have size="4294967294`\n..." */
typed->size = size = read_num(ar.formatted.size, 10);
/* special filenames have '/' as the first character */
if (ar.formatted.name[0] == '/') {
if (ar.formatted.name[1] == ' ') {
/* This is the index of symbols in the file for compilers */
diff --git a/archival/libunarchive/get_header_tar.c b/archival/libunarchive/get_header_tar.c
index 982404d14..d5c92359c 100644
--- a/archival/libunarchive/get_header_tar.c
+++ b/archival/libunarchive/get_header_tar.c
@@ -11,125 +11,120 @@
* http://www.opengroup.org/onlinepubs/007904975/utilities/pax.html
*/
#include "libbb.h"
#include "unarchive.h"
-/*
- * GNU tar uses "base-256 encoding" for very large numbers (>8 billion).
- * Encoding is binary, with highest bit always set as a marker
- * and sign in next-highest bit:
- * 80 00 .. 00 - zero
- * bf ff .. ff - largest positive number
- * ff ff .. ff - minus 1
- * c0 00 .. 00 - smallest negative number
- *
- * We expect it only in size field, where negative numbers don't make sense.
- */
-static off_t getBase256_len12(const char *str)
-{
- off_t value;
- int len;
+typedef uint32_t aliased_uint32_t FIX_ALIASING;
+typedef off_t aliased_off_t FIX_ALIASING;
- /* if (*str & 0x40) error; - caller prevents this */
-
- if (sizeof(off_t) >= 12) {
- /* Probably 128-bit (16 byte) off_t. Can be optimized. */
- len = 12;
- value = *str++ & 0x3f;
- while (--len)
- value = (value << 8) + (unsigned char) *str++;
- return value;
- }
-
-#ifdef CHECK_FOR_OVERFLOW
- /* Can be optimized to eat 32-bit chunks */
- char c = *str++ & 0x3f;
- len = 12;
- while (1) {
- if (c)
- bb_error_msg_and_die("overflow in base-256 encoded file size");
- if (--len == sizeof(off_t))
- break;
- c = *str++;
- }
-#else
- str += (12 - sizeof(off_t));
-#endif
-
-/* Now str points to sizeof(off_t) least significant bytes.
- *
- * Example of tar file with 8914993153 (0x213600001) byte file.
- * Field starts at offset 7c:
- * 00070 30 30 30 00 30 30 30 30 30 30 30 00 80 00 00 00 |000.0000000.....|
- * 00080 00 00 00 02 13 60 00 01 31 31 31 32 30 33 33 36 |.....`..11120336|
- *
- * str is at offset 80 or 84 now (64-bit or 32-bit off_t).
- * We (ab)use the fact that value happens to be aligned,
- * and fetch it in one go:
- */
- if (sizeof(off_t) == 8) {
- value = *(off_t*)str;
- value = SWAP_BE64(value);
- } else if (sizeof(off_t) == 4) {
- value = *(off_t*)str;
- value = SWAP_BE32(value);
- } else {
- value = 0;
- len = sizeof(off_t);
- while (--len)
- value = (value << 8) + (unsigned char) *str++;
- }
- return value;
-}
/* NB: _DESTROYS_ str[len] character! */
static unsigned long long getOctal(char *str, int len)
{
unsigned long long v;
+ char *end;
/* NB: leading spaces are allowed. Using strtoull to handle that.
* The downside is that we accept e.g. "-123" too :(
*/
str[len] = '\0';
- v = strtoull(str, &str, 8);
+ v = strtoull(str, &end, 8);
/* std: "Each numeric field is terminated by one or more
* <space> or NUL characters". We must support ' '! */
- if (*str != '\0' && *str != ' ')
- bb_error_msg_and_die("corrupted octal value in tar header");
+ if (*end != '\0' && *end != ' ') {
+ int8_t first = str[0];
+ if (!(first & 0x80))
+ bb_error_msg_and_die("corrupted octal value in tar header");
+ /*
+ * GNU tar uses "base-256 encoding" for very large numbers.
+ * Encoding is binary, with highest bit always set as a marker
+ * and sign in next-highest bit:
+ * 80 00 .. 00 - zero
+ * bf ff .. ff - largest positive number
+ * ff ff .. ff - minus 1
+ * c0 00 .. 00 - smallest negative number
+ *
+ * Example of tar file with 8914993153 (0x213600001) byte file.
+ * Field starts at offset 7c:
+ * 00070 30 30 30 00 30 30 30 30 30 30 30 00 80 00 00 00 |000.0000000.....|
+ * 00080 00 00 00 02 13 60 00 01 31 31 31 32 30 33 33 36 |.....`..11120336|
+ *
+ * NB: tarballs with NEGATIVE unix times encoded that way were seen!
+ */
+ v = first;
+ /* Sign-extend using 6th bit: */
+ v <<= sizeof(unsigned long long)*8 - 7;
+ v = (long long)v >> (sizeof(unsigned long long)*8 - 7);
+ while (--len != 0)
+ v = (v << 8) + (unsigned char) *str++;
+ }
return v;
}
#define GET_OCTAL(a) getOctal((a), sizeof(a))
-void BUG_tar_header_size(void);
+#if ENABLE_FEATURE_TAR_SELINUX
+/* Scan a PAX header for SELinux contexts, via "RHT.security.selinux" keyword.
+ * This is what Red Hat's patched version of tar uses.
+ */
+# define SELINUX_CONTEXT_KEYWORD "RHT.security.selinux"
+static char *get_selinux_sctx_from_pax_hdr(archive_handle_t *archive_handle, unsigned sz)
+{
+ char *buf, *p;
+ char *result;
+
+ p = buf = xmalloc(sz + 1);
+ /* prevent bb_strtou from running off the buffer */
+ buf[sz] = '\0';
+ xread(archive_handle->src_fd, buf, sz);
+ archive_handle->offset += sz;
+
+ result = NULL;
+ while (sz != 0) {
+ char *end, *value;
+ unsigned len;
+
+ /* Every record has this format: "LEN NAME=VALUE\n" */
+ len = bb_strtou(p, &end, 10);
+ /* expect errno to be EINVAL, because the character
+ * following the digits should be a space
+ */
+ p += len;
+ sz -= len;
+ if ((int)sz < 0
+ || len == 0
+ || errno != EINVAL
+ || *end != ' '
+ ) {
+ bb_error_msg("malformed extended header, skipped");
+ // More verbose version:
+ //bb_error_msg("malformed extended header at %"OFF_FMT"d, skipped",
+ // archive_handle->offset - (sz + len));
+ break;
+ }
+ /* overwrite the terminating newline with NUL
+ * (we do not bother to check that it *was* a newline)
+ */
+ p[-1] = '\0';
+ /* Is it selinux security context? */
+ value = end + 1;
+ if (strncmp(value, SELINUX_CONTEXT_KEYWORD"=", sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1) == 0) {
+ value += sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1;
+ result = xstrdup(value);
+ break;
+ }
+ }
+
+ free(buf);
+ return result;
+}
+#endif
+
char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
{
file_header_t *file_header = archive_handle->file_header;
- struct {
- /* ustar header, Posix 1003.1 */
- char name[100]; /* 0-99 */
- char mode[8]; /* 100-107 */
- char uid[8]; /* 108-115 */
- char gid[8]; /* 116-123 */
- char size[12]; /* 124-135 */
- char mtime[12]; /* 136-147 */
- char chksum[8]; /* 148-155 */
- char typeflag; /* 156-156 */
- char linkname[100]; /* 157-256 */
- /* POSIX: "ustar" NUL "00" */
- /* GNU tar: "ustar " NUL */
- /* Normally it's defined as magic[6] followed by
- * version[2], but we put them together to simplify code
- */
- char magic[8]; /* 257-264 */
- char uname[32]; /* 265-296 */
- char gname[32]; /* 297-328 */
- char devmajor[8]; /* 329-336 */
- char devminor[8]; /* 337-344 */
- char prefix[155]; /* 345-499 */
- char padding[12]; /* 500-512 */
- } tar;
+ struct tar_header_t tar;
char *cp;
int i, sum_u, sum;
#if ENABLE_FEATURE_TAR_OLDSUN_COMPATIBILITY
int sum_s;
#endif
int parse_names;
@@ -140,26 +135,23 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
# define p_linkname (archive_handle->tar__linkname)
#else
# define p_longname 0
# define p_linkname 0
#endif
- if (sizeof(tar) != 512)
- BUG_tar_header_size();
-
-#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
+#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS || ENABLE_FEATURE_TAR_SELINUX
again:
#endif
/* Align header */
data_align(archive_handle, 512);
again_after_align:
#if ENABLE_DESKTOP || ENABLE_FEATURE_TAR_AUTODETECT
/* to prevent misdetection of bz2 sig */
- *(uint32_t*)(&tar) = 0;
+ *(aliased_uint32_t*)&tar = 0;
i = full_read(archive_handle->src_fd, &tar, 512);
/* If GNU tar sees EOF in above read, it says:
* "tar: A lone zero block at N", where N = kilobyte
* where EOF was met (not EOF block, actual EOF!),
* and exits with EXIT_SUCCESS.
* We will mimic exit(EXIT_SUCCESS), although we will not mimic
@@ -201,31 +193,37 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
if (strncmp(tar.magic, "ustar", 5) != 0
&& (!ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY
|| memcmp(tar.magic, "\0\0\0\0", 5) != 0)
) {
#if ENABLE_FEATURE_TAR_AUTODETECT
char FAST_FUNC (*get_header_ptr)(archive_handle_t *);
+ uint16_t magic2;
autodetect:
+ magic2 = *(uint16_t*)tar.name;
/* tar gz/bz autodetect: check for gz/bz2 magic.
* If we see the magic, and it is the very first block,
* we can switch to get_header_tar_gz/bz2/lzma().
* Needs seekable fd. I wish recv(MSG_PEEK) works
* on any fd... */
-#if ENABLE_FEATURE_SEAMLESS_GZ
- if (tar.name[0] == 0x1f && tar.name[1] == (char)0x8b) { /* gzip */
+# if ENABLE_FEATURE_SEAMLESS_GZ
+ if (magic2 == GZIP_MAGIC) {
get_header_ptr = get_header_tar_gz;
} else
-#endif
-#if ENABLE_FEATURE_SEAMLESS_BZ2
- if (tar.name[0] == 'B' && tar.name[1] == 'Z'
+# endif
+# if ENABLE_FEATURE_SEAMLESS_BZ2
+ if (magic2 == BZIP2_MAGIC
&& tar.name[2] == 'h' && isdigit(tar.name[3])
) { /* bzip2 */
get_header_ptr = get_header_tar_bz2;
} else
-#endif
+# endif
+# if ENABLE_FEATURE_SEAMLESS_XZ
+ //TODO: if (magic2 == XZ_MAGIC1)...
+ //else
+# endif
goto err;
/* Two different causes for lseek() != 0:
* unseekable fd (would like to support that too, but...),
* or not first block (false positive, it's not .gz/.bz2!) */
if (lseek(archive_handle->src_fd, -i, SEEK_CUR) != 0)
goto err;
@@ -294,21 +292,14 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
/* Will link_target be free()ed? */
}
#if ENABLE_FEATURE_TAR_UNAME_GNAME
file_header->tar__uname = tar.uname[0] ? xstrndup(tar.uname, sizeof(tar.uname)) : NULL;
file_header->tar__gname = tar.gname[0] ? xstrndup(tar.gname, sizeof(tar.gname)) : NULL;
#endif
- /* mtime: rudimentally handle GNU tar's "base256 encoding"
- * People report tarballs with NEGATIVE unix times encoded that way */
- file_header->mtime = (tar.mtime[0] & 0x80) /* base256? */
- ? 0 /* bogus */
- : GET_OCTAL(tar.mtime);
- /* size: handle GNU tar's "base256 encoding" */
- file_header->size = (tar.size[0] & 0xc0) == 0x80 /* positive base256? */
- ? getBase256_len12(tar.size)
- : GET_OCTAL(tar.size);
+ file_header->mtime = GET_OCTAL(tar.mtime);
+ file_header->size = GET_OCTAL(tar.size);
file_header->gid = GET_OCTAL(tar.gid);
file_header->uid = GET_OCTAL(tar.uid);
/* Set bits 0-11 of the files mode */
file_header->mode = 07777 & GET_OCTAL(tar.mode);
file_header->name = NULL;
@@ -385,24 +376,41 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
case 'D': /* GNU dump dir */
case 'M': /* Continuation of multi volume archive */
case 'N': /* Old GNU for names > 100 characters */
case 'S': /* Sparse file */
case 'V': /* Volume header */
#endif
+#if !ENABLE_FEATURE_TAR_SELINUX
case 'g': /* pax global header */
- case 'x': { /* pax extended header */
+ case 'x': /* pax extended header */
+#else
+ skip_ext_hdr:
+#endif
+ {
off_t sz;
bb_error_msg("warning: skipping header '%c'", tar.typeflag);
sz = (file_header->size + 511) & ~(off_t)511;
archive_handle->offset += sz;
sz >>= 9; /* sz /= 512 but w/o contortions for signed div */
while (sz--)
xread(archive_handle->src_fd, &tar, 512);
/* return get_header_tar(archive_handle); */
goto again_after_align;
}
+#if ENABLE_FEATURE_TAR_SELINUX
+ case 'g': /* pax global header */
+ case 'x': { /* pax extended header */
+ char **pp;
+ if ((uoff_t)file_header->size > 0xfffff) /* paranoia */
+ goto skip_ext_hdr;
+ pp = (tar.typeflag == 'g') ? &archive_handle->tar__global_sctx : &archive_handle->tar__next_file_sctx;
+ free(*pp);
+ *pp = get_selinux_sctx_from_pax_hdr(archive_handle, file_header->size);
+ goto again;
+ }
+#endif
default:
bb_error_msg_and_die("unknown typeflag: 0x%x", tar.typeflag);
}
#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
if (p_longname) {
@@ -426,24 +434,28 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
cp = last_char_is(file_header->name, '/');
if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
archive_handle->action_header(/*archive_handle->*/ file_header);
/* Note that we kill the '/' only after action_header() */
/* (like GNU tar 1.15.1: verbose mode outputs "dir/dir/") */
- if (cp) *cp = '\0';
- archive_handle->ah_flags |= ARCHIVE_EXTRACT_QUIET;
+ if (cp)
+ *cp = '\0';
archive_handle->action_data(archive_handle);
- llist_add_to(&(archive_handle->passed), file_header->name);
+ if (archive_handle->accept || archive_handle->reject)
+ llist_add_to(&archive_handle->passed, file_header->name);
+ else /* Caller isn't interested in list of unpacked files */
+ free(file_header->name);
} else {
data_skip(archive_handle);
free(file_header->name);
}
archive_handle->offset += file_header->size;
free(file_header->link_target);
- /* Do not free(file_header->name)! (why?) */
+ /* Do not free(file_header->name)!
+ * It might be inserted in archive_handle->passed - see above */
#if ENABLE_FEATURE_TAR_UNAME_GNAME
free(file_header->tar__uname);
free(file_header->tar__gname);
#endif
return EXIT_SUCCESS;
}
diff --git a/archival/libunarchive/header_verbose_list.c b/archival/libunarchive/header_verbose_list.c
index f6f04cfd5..3319e63a9 100644
--- a/archival/libunarchive/header_verbose_list.c
+++ b/archival/libunarchive/header_verbose_list.c
@@ -58,11 +58,12 @@ void FAST_FUNC header_verbose_list(const file_header_t *file_header)
ptm->tm_min,
ptm->tm_sec,
file_header->name);
#endif /* FEATURE_TAR_UNAME_GNAME */
+ /* NB: GNU tar shows "->" for symlinks and "link to" for hardlinks */
if (file_header->link_target) {
printf(" -> %s", file_header->link_target);
}
bb_putchar('\n');
}
diff --git a/archival/libunarchive/open_transformer.c b/archival/libunarchive/open_transformer.c
index 47c13e6f4..cba049f1f 100644
--- a/archival/libunarchive/open_transformer.c
+++ b/archival/libunarchive/open_transformer.c
@@ -16,25 +16,15 @@ void FAST_FUNC open_transformer(int fd,
const char *transform_prog)
{
struct fd_pair fd_pipe;
int pid;
xpiped_pair(fd_pipe);
-
-#if BB_MMU
- pid = fork();
- if (pid == -1)
- bb_perror_msg_and_die("vfork" + 1);
-#else
- pid = vfork();
- if (pid == -1)
- bb_perror_msg_and_die("vfork");
-#endif
-
+ pid = BB_MMU ? xfork() : xvfork();
if (pid == 0) {
- /* child process */
+ /* Child */
close(fd_pipe.rd); /* we don't want to read from the parent */
// FIXME: error check?
#if BB_MMU
transformer(fd, fd_pipe.wr);
if (ENABLE_FEATURE_CLEAN_UP) {
close(fd_pipe.wr); /* send EOF */
diff --git a/archival/libunarchive/unpack_ar_archive.c b/archival/libunarchive/unpack_ar_archive.c
index dc2eec223..300d10e48 100644
--- a/archival/libunarchive/unpack_ar_archive.c
+++ b/archival/libunarchive/unpack_ar_archive.c
@@ -2,20 +2,21 @@
/*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
#include "libbb.h"
#include "unarchive.h"
+#include "ar.h"
void FAST_FUNC unpack_ar_archive(archive_handle_t *ar_archive)
{
char magic[7];
- xread(ar_archive->src_fd, magic, 7);
- if (strncmp(magic, "!<arch>", 7) != 0) {
+ xread(ar_archive->src_fd, magic, AR_MAGIC_LEN);
+ if (strncmp(magic, AR_MAGIC, AR_MAGIC_LEN) != 0) {
bb_error_msg_and_die("invalid ar magic");
}
- ar_archive->offset += 7;
+ ar_archive->offset += AR_MAGIC_LEN;
while (get_header_ar(ar_archive) == EXIT_SUCCESS)
continue;
}
diff --git a/archival/libunarchive/unxz/README b/archival/libunarchive/unxz/README
new file mode 100644
index 000000000..f79b0a404
--- /dev/null
+++ b/archival/libunarchive/unxz/README
@@ -0,0 +1,136 @@
+
+XZ Embedded
+===========
+
+ XZ Embedded is a relatively small, limited implementation of the .xz
+ file format. Currently only decoding is implemented.
+
+ XZ Embedded was written for use in the Linux kernel, but the code can
+ be easily used in other environments too, including regular userspace
+ applications.
+
+ This README contains information that is useful only when the copy
+ of XZ Embedded isn't part of the Linux kernel tree. You should also
+ read linux/Documentation/xz.txt even if you aren't using XZ Embedded
+ as part of Linux; information in that file is not repeated in this
+ README.
+
+Compiling the Linux kernel module
+
+ The xz_dec module depends on crc32 module, so make sure that you have
+ it enabled (CONFIG_CRC32).
+
+ Building the xz_dec and xz_dec_test modules without support for BCJ
+ filters:
+
+ cd linux/lib/xz
+ make -C /path/to/kernel/source \
+ KCPPFLAGS=-I"$(pwd)/../../include" M="$(pwd)" \
+ CONFIG_XZ_DEC=m CONFIG_XZ_DEC_TEST=m
+
+ Building the xz_dec and xz_dec_test modules with support for BCJ
+ filters:
+
+ cd linux/lib/xz
+ make -C /path/to/kernel/source \
+ KCPPFLAGS=-I"$(pwd)/../../include" M="$(pwd)" \
+ CONFIG_XZ_DEC=m CONFIG_XZ_DEC_TEST=m CONFIG_XZ_DEC_BCJ=y \
+ CONFIG_XZ_DEC_X86=y CONFIG_XZ_DEC_POWERPC=y \
+ CONFIG_XZ_DEC_IA64=y CONFIG_XZ_DEC_ARM=y \
+ CONFIG_XZ_DEC_ARMTHUMB=y CONFIG_XZ_DEC_SPARC=y
+
+ If you want only one or a few of the BCJ filters, omit the appropriate
+ variables. CONFIG_XZ_DEC_BCJ=y is always required to build the support
+ code shared between all BCJ filters.
+
+ Most people don't need the xz_dec_test module. You can skip building
+ it by omitting CONFIG_XZ_DEC_TEST=m from the make command line.
+
+Compiler requirements
+
+ XZ Embedded should compile as either GNU-C89 (used in the Linux
+ kernel) or with any C99 compiler. Getting the code to compile with
+ non-GNU C89 compiler or a C++ compiler should be quite easy as
+ long as there is a data type for unsigned 64-bit integer (or the
+ code is modified not to support large files, which needs some more
+ care than just using 32-bit integer instead of 64-bit).
+
+ If you use GCC, try to use a recent version. For example, on x86,
+ xz_dec_lzma2.c compiled with GCC 3.3.6 is 15-25 % slower than when
+ compiled with GCC 4.3.3.
+
+Embedding into userspace applications
+
+ To embed the XZ decoder, copy the following files into a single
+ directory in your source code tree:
+
+ linux/include/linux/xz.h
+ linux/lib/xz/xz_crc32.c
+ linux/lib/xz/xz_dec_lzma2.c
+ linux/lib/xz/xz_dec_stream.c
+ linux/lib/xz/xz_lzma2.h
+ linux/lib/xz/xz_private.h
+ linux/lib/xz/xz_stream.h
+ userspace/xz_config.h
+
+ Alternatively, xz.h may be placed into a different directory but then
+ that directory must be in the compiler include path when compiling
+ the .c files.
+
+ Your code should use only the functions declared in xz.h. The rest of
+ the .h files are meant only for internal use in XZ Embedded.
+
+ You may want to modify xz_config.h to be more suitable for your build
+ environment. Probably you should at least skim through it even if the
+ default file works as is.
+
+BCJ filter support
+
+ If you want support for one or more BCJ filters, you need to copy also
+ linux/lib/xz/xz_dec_bcj.c into your application, and use appropriate
+ #defines in xz_config.h or in compiler flags. You don't need these
+ #defines in the code that just uses XZ Embedded via xz.h, but having
+ them always #defined doesn't hurt either.
+
+ #define Instruction set BCJ filter endianness
+ XZ_DEC_X86 x86 or x86-64 Little endian only
+ XZ_DEC_POWERPC PowerPC Big endian only
+ XZ_DEC_IA64 Itanium (IA-64) Big or little endian
+ XZ_DEC_ARM ARM Little endian only
+ XZ_DEC_ARMTHUMB ARM-Thumb Little endian only
+ XZ_DEC_SPARC SPARC Big or little endian
+
+ While some architectures are (partially) bi-endian, the endianness
+ setting doesn't change the endianness of the instructions on all
+ architectures. That's why Itanium and SPARC filters work for both big
+ and little endian executables (Itanium has little endian instructions
+ and SPARC has big endian instructions).
+
+ There currently is no filter for little endian PowerPC or big endian
+ ARM or ARM-Thumb. Implementing filters for them can be considered if
+ there is a need for such filters in real-world applications.
+
+Notes about shared libraries
+
+ If you are including XZ Embedded into a shared library, you very
+ probably should rename the xz_* functions to prevent symbol
+ conflicts in case your library is linked against some other library
+ or application that also has XZ Embedded in it (which may even be
+ a different version of XZ Embedded). TODO: Provide an easy way
+ to do this.
+
+ Please don't create a shared library of XZ Embedded itself unless
+ it is fine to rebuild everything depending on that shared library
+ everytime you upgrade to a newer version of XZ Embedded. There are
+ no API or ABI stability guarantees between different versions of
+ XZ Embedded.
+
+Specifying the calling convention
+
+ XZ_FUNC macro was included to support declaring functions with __init
+ in Linux. Outside Linux, it can be used to specify the calling
+ convention on systems that support multiple calling conventions.
+ For example, on Windows, you may make all functions use the stdcall
+ calling convention by defining XZ_FUNC=__stdcall when building and
+ using the functions from XZ Embedded.
+
diff --git a/archival/libunarchive/unxz/xz.h b/archival/libunarchive/unxz/xz.h
new file mode 100644
index 000000000..c6c071c4a
--- /dev/null
+++ b/archival/libunarchive/unxz/xz.h
@@ -0,0 +1,271 @@
+/*
+ * XZ decompressor
+ *
+ * Authors: Lasse Collin <lasse.collin@tukaani.org>
+ * Igor Pavlov <http://7-zip.org/>
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ */
+
+#ifndef XZ_H
+#define XZ_H
+
+#ifdef __KERNEL__
+# include <linux/stddef.h>
+# include <linux/types.h>
+#else
+# include <stddef.h>
+# include <stdint.h>
+#endif
+
+/* In Linux, this is used to make extern functions static when needed. */
+#ifndef XZ_EXTERN
+# define XZ_EXTERN extern
+#endif
+
+/* In Linux, this is used to mark the functions with __init when needed. */
+#ifndef XZ_FUNC
+# define XZ_FUNC
+#endif
+
+/**
+ * enum xz_mode - Operation mode
+ *
+ * @XZ_SINGLE: Single-call mode. This uses less RAM than
+ * than multi-call modes, because the LZMA2
+ * dictionary doesn't need to be allocated as
+ * part of the decoder state. All required data
+ * structures are allocated at initialization,
+ * so xz_dec_run() cannot return XZ_MEM_ERROR.
+ * @XZ_PREALLOC: Multi-call mode with preallocated LZMA2
+ * dictionary buffer. All data structures are
+ * allocated at initialization, so xz_dec_run()
+ * cannot return XZ_MEM_ERROR.
+ * @XZ_DYNALLOC: Multi-call mode. The LZMA2 dictionary is
+ * allocated once the required size has been
+ * parsed from the stream headers. If the
+ * allocation fails, xz_dec_run() will return
+ * XZ_MEM_ERROR.
+ *
+ * It is possible to enable support only for a subset of the above
+ * modes at compile time by defining XZ_DEC_SINGLE, XZ_DEC_PREALLOC,
+ * or XZ_DEC_DYNALLOC. The xz_dec kernel module is always compiled
+ * with support for all operation modes, but the preboot code may
+ * be built with fewer features to minimize code size.
+ */
+enum xz_mode {
+ XZ_SINGLE,
+ XZ_PREALLOC,
+ XZ_DYNALLOC
+};
+
+/**
+ * enum xz_ret - Return codes
+ * @XZ_OK: Everything is OK so far. More input or more
+ * output space is required to continue. This
+ * return code is possible only in multi-call mode
+ * (XZ_PREALLOC or XZ_DYNALLOC).
+ * @XZ_STREAM_END: Operation finished successfully.
+ * @XZ_UNSUPPORTED_CHECK: Integrity check type is not supported. Decoding
+ * is still possible in multi-call mode by simply
+ * calling xz_dec_run() again.
+ * NOTE: This return value is used only if
+ * XZ_DEC_ANY_CHECK was defined at build time,
+ * which is not used in the kernel. Unsupported
+ * check types return XZ_OPTIONS_ERROR if
+ * XZ_DEC_ANY_CHECK was not defined at build time.
+ * @XZ_MEM_ERROR: Allocating memory failed. This return code is
+ * possible only if the decoder was initialized
+ * with XZ_DYNALLOC. The amount of memory that was
+ * tried to be allocated was no more than the
+ * dict_max argument given to xz_dec_init().
+ * @XZ_MEMLIMIT_ERROR: A bigger LZMA2 dictionary would be needed than
+ * allowed by the dict_max argument given to
+ * xz_dec_init(). This return value is possible
+ * only in multi-call mode (XZ_PREALLOC or
+ * XZ_DYNALLOC); the single-call mode (XZ_SINGLE)
+ * ignores the dict_max argument.
+ * @XZ_FORMAT_ERROR: File format was not recognized (wrong magic
+ * bytes).
+ * @XZ_OPTIONS_ERROR: This implementation doesn't support the requested
+ * compression options. In the decoder this means
+ * that the header CRC32 matches, but the header
+ * itself specifies something that we don't support.
+ * @XZ_DATA_ERROR: Compressed data is corrupt.
+ * @XZ_BUF_ERROR: Cannot make any progress. Details are slightly
+ * different between multi-call and single-call
+ * mode; more information below.
+ *
+ * In multi-call mode, XZ_BUF_ERROR is returned when two consecutive calls
+ * to XZ code cannot consume any input and cannot produce any new output.
+ * This happens when there is no new input available, or the output buffer
+ * is full while at least one output byte is still pending. Assuming your
+ * code is not buggy, you can get this error only when decoding a compressed
+ * stream that is truncated or otherwise corrupt.
+ *
+ * In single-call mode, XZ_BUF_ERROR is returned only when the output buffer
+ * is too small, or the compressed input is corrupt in a way that makes the
+ * decoder produce more output than the caller expected. When it is
+ * (relatively) clear that the compressed input is truncated, XZ_DATA_ERROR
+ * is used instead of XZ_BUF_ERROR.
+ */
+enum xz_ret {
+ XZ_OK,
+ XZ_STREAM_END,
+ XZ_UNSUPPORTED_CHECK,
+ XZ_MEM_ERROR,
+ XZ_MEMLIMIT_ERROR,
+ XZ_FORMAT_ERROR,
+ XZ_OPTIONS_ERROR,
+ XZ_DATA_ERROR,
+ XZ_BUF_ERROR
+};
+
+/**
+ * struct xz_buf - Passing input and output buffers to XZ code
+ * @in: Beginning of the input buffer. This may be NULL if and only
+ * if in_pos is equal to in_size.
+ * @in_pos: Current position in the input buffer. This must not exceed
+ * in_size.
+ * @in_size: Size of the input buffer
+ * @out: Beginning of the output buffer. This may be NULL if and only
+ * if out_pos is equal to out_size.
+ * @out_pos: Current position in the output buffer. This must not exceed
+ * out_size.
+ * @out_size: Size of the output buffer
+ *
+ * Only the contents of the output buffer from out[out_pos] onward, and
+ * the variables in_pos and out_pos are modified by the XZ code.
+ */
+struct xz_buf {
+ const uint8_t *in;
+ size_t in_pos;
+ size_t in_size;
+
+ uint8_t *out;
+ size_t out_pos;
+ size_t out_size;
+};
+
+/**
+ * struct xz_dec - Opaque type to hold the XZ decoder state
+ */
+struct xz_dec;
+
+/**
+ * xz_dec_init() - Allocate and initialize a XZ decoder state
+ * @mode: Operation mode
+ * @dict_max: Maximum size of the LZMA2 dictionary (history buffer) for
+ * multi-call decoding. This is ignored in single-call mode
+ * (mode == XZ_SINGLE). LZMA2 dictionary is always 2^n bytes
+ * or 2^n + 2^(n-1) bytes (the latter sizes are less common
+ * in practice), so other values for dict_max don't make sense.
+ * In the kernel, dictionary sizes of 64 KiB, 128 KiB, 256 KiB,
+ * 512 KiB, and 1 MiB are probably the only reasonable values,
+ * except for kernel and initramfs images where a bigger
+ * dictionary can be fine and useful.
+ *
+ * Single-call mode (XZ_SINGLE): xz_dec_run() decodes the whole stream at
+ * once. The caller must provide enough output space or the decoding will
+ * fail. The output space is used as the dictionary buffer, which is why
+ * there is no need to allocate the dictionary as part of the decoder's
+ * internal state.
+ *
+ * Because the output buffer is used as the workspace, streams encoded using
+ * a big dictionary are not a problem in single-call mode. It is enough that
+ * the output buffer is big enough to hold the actual uncompressed data; it
+ * can be smaller than the dictionary size stored in the stream headers.
+ *
+ * Multi-call mode with preallocated dictionary (XZ_PREALLOC): dict_max bytes
+ * of memory is preallocated for the LZMA2 dictionary. This way there is no
+ * risk that xz_dec_run() could run out of memory, since xz_dec_run() will
+ * never allocate any memory. Instead, if the preallocated dictionary is too
+ * small for decoding the given input stream, xz_dec_run() will return
+ * XZ_MEMLIMIT_ERROR. Thus, it is important to know what kind of data will be
+ * decoded to avoid allocating excessive amount of memory for the dictionary.
+ *
+ * Multi-call mode with dynamically allocated dictionary (XZ_DYNALLOC):
+ * dict_max specifies the maximum allowed dictionary size that xz_dec_run()
+ * may allocate once it has parsed the dictionary size from the stream
+ * headers. This way excessive allocations can be avoided while still
+ * limiting the maximum memory usage to a sane value to prevent running the
+ * system out of memory when decompressing streams from untrusted sources.
+ *
+ * On success, xz_dec_init() returns a pointer to struct xz_dec, which is
+ * ready to be used with xz_dec_run(). If memory allocation fails,
+ * xz_dec_init() returns NULL.
+ */
+XZ_EXTERN struct xz_dec * XZ_FUNC xz_dec_init(
+ enum xz_mode mode, uint32_t dict_max);
+
+/**
+ * xz_dec_run() - Run the XZ decoder
+ * @s: Decoder state allocated using xz_dec_init()
+ * @b: Input and output buffers
+ *
+ * The possible return values depend on build options and operation mode.
+ * See enum xz_ret for details.
+ *
+ * NOTE: If an error occurs in single-call mode (return value is not
+ * XZ_STREAM_END), b->in_pos and b->out_pos are not modified, and the
+ * contents of the output buffer from b->out[b->out_pos] onward are
+ * undefined. This is true even after XZ_BUF_ERROR, because with some filter
+ * chains, there may be a second pass over the output buffer, and this pass
+ * cannot be properly done if the output buffer is truncated. Thus, you
+ * cannot give the single-call decoder a too small buffer and then expect to
+ * get that amount valid data from the beginning of the stream. You must use
+ * the multi-call decoder if you don't want to uncompress the whole stream.
+ */
+XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_run(struct xz_dec *s, struct xz_buf *b);
+
+/**
+ * xz_dec_reset() - Reset an already allocated decoder state
+ * @s: Decoder state allocated using xz_dec_init()
+ *
+ * This function can be used to reset the multi-call decoder state without
+ * freeing and reallocating memory with xz_dec_end() and xz_dec_init().
+ *
+ * In single-call mode, xz_dec_reset() is always called in the beginning of
+ * xz_dec_run(). Thus, explicit call to xz_dec_reset() is useful only in
+ * multi-call mode.
+ */
+XZ_EXTERN void XZ_FUNC xz_dec_reset(struct xz_dec *s);
+
+/**
+ * xz_dec_end() - Free the memory allocated for the decoder state
+ * @s: Decoder state allocated using xz_dec_init(). If s is NULL,
+ * this function does nothing.
+ */
+XZ_EXTERN void XZ_FUNC xz_dec_end(struct xz_dec *s);
+
+/*
+ * Standalone build (userspace build or in-kernel build for boot time use)
+ * needs a CRC32 implementation. For normal in-kernel use, kernel's own
+ * CRC32 module is used instead, and users of this module don't need to
+ * care about the functions below.
+ */
+#ifndef XZ_INTERNAL_CRC32
+# ifdef __KERNEL__
+# define XZ_INTERNAL_CRC32 0
+# else
+# define XZ_INTERNAL_CRC32 1
+# endif
+#endif
+
+#if XZ_INTERNAL_CRC32
+/*
+ * This must be called before any other xz_* function to initialize
+ * the CRC32 lookup table.
+ */
+XZ_EXTERN void XZ_FUNC xz_crc32_init(void);
+
+/*
+ * Update CRC32 value using the polynomial from IEEE-802.3. To start a new
+ * calculation, the third argument must be zero. To continue the calculation,
+ * the previously returned value is passed as the third argument.
+ */
+XZ_EXTERN uint32_t XZ_FUNC xz_crc32(
+ const uint8_t *buf, size_t size, uint32_t crc);
+#endif
+#endif
diff --git a/archival/libunarchive/unxz/xz_config.h b/archival/libunarchive/unxz/xz_config.h
new file mode 100644
index 000000000..187e1cbed
--- /dev/null
+++ b/archival/libunarchive/unxz/xz_config.h
@@ -0,0 +1,123 @@
+/*
+ * Private includes and definitions for userspace use of XZ Embedded
+ *
+ * Author: Lasse Collin <lasse.collin@tukaani.org>
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ */
+
+#ifndef XZ_CONFIG_H
+#define XZ_CONFIG_H
+
+/* Uncomment as needed to enable BCJ filter decoders. */
+/* #define XZ_DEC_X86 */
+/* #define XZ_DEC_POWERPC */
+/* #define XZ_DEC_IA64 */
+/* #define XZ_DEC_ARM */
+/* #define XZ_DEC_ARMTHUMB */
+/* #define XZ_DEC_SPARC */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xz.h"
+
+#define kmalloc(size, flags) malloc(size)
+#define kfree(ptr) free(ptr)
+#define vmalloc(size) malloc(size)
+#define vfree(ptr) free(ptr)
+
+#define memeq(a, b, size) (memcmp(a, b, size) == 0)
+#define memzero(buf, size) memset(buf, 0, size)
+
+#undef min
+#undef min_t
+#define min(x, y) ((x) < (y) ? (x) : (y))
+#define min_t(type, x, y) min(x, y)
+
+/*
+ * Some functions have been marked with __always_inline to keep the
+ * performance reasonable even when the compiler is optimizing for
+ * small code size. You may be able to save a few bytes by #defining
+ * __always_inline to plain inline, but don't complain if the code
+ * becomes slow.
+ *
+ * NOTE: System headers on GNU/Linux may #define this macro already,
+ * so if you want to change it, you need to #undef it first.
+ */
+#ifndef __always_inline
+# ifdef __GNUC__
+# define __always_inline \
+ inline __attribute__((__always_inline__))
+# else
+# define __always_inline inline
+# endif
+#endif
+
+/*
+ * Some functions are marked to never be inlined to reduce stack usage.
+ * If you don't care about stack usage, you may want to modify this so
+ * that noinline_for_stack is #defined to be empty even when using GCC.
+ * Doing so may save a few bytes in binary size.
+ */
+#ifndef noinline_for_stack
+# ifdef __GNUC__
+# define noinline_for_stack __attribute__((__noinline__))
+# else
+# define noinline_for_stack
+# endif
+#endif
+
+/* Inline functions to access unaligned unsigned 32-bit integers */
+#ifndef get_unaligned_le32
+static inline uint32_t XZ_FUNC get_unaligned_le32(const uint8_t *buf)
+{
+ return (uint32_t)buf[0]
+ | ((uint32_t)buf[1] << 8)
+ | ((uint32_t)buf[2] << 16)
+ | ((uint32_t)buf[3] << 24);
+}
+#endif
+
+#ifndef get_unaligned_be32
+static inline uint32_t XZ_FUNC get_unaligned_be32(const uint8_t *buf)
+{
+ return (uint32_t)(buf[0] << 24)
+ | ((uint32_t)buf[1] << 16)
+ | ((uint32_t)buf[2] << 8)
+ | (uint32_t)buf[3];
+}
+#endif
+
+#ifndef put_unaligned_le32
+static inline void XZ_FUNC put_unaligned_le32(uint32_t val, uint8_t *buf)
+{
+ buf[0] = (uint8_t)val;
+ buf[1] = (uint8_t)(val >> 8);
+ buf[2] = (uint8_t)(val >> 16);
+ buf[3] = (uint8_t)(val >> 24);
+}
+#endif
+
+#ifndef put_unaligned_be32
+static inline void XZ_FUNC put_unaligned_be32(uint32_t val, uint8_t *buf)
+{
+ buf[0] = (uint8_t)(val >> 24);
+ buf[1] = (uint8_t)(val >> 16);
+ buf[2] = (uint8_t)(val >> 8);
+ buf[3] = (uint8_t)val;
+}
+#endif
+
+/*
+ * Use get_unaligned_le32() also for aligned access for simplicity. On
+ * little endian systems, #define get_le32(ptr) (*(const uint32_t *)(ptr))
+ * could save a few bytes in code size.
+ */
+#ifndef get_le32
+# define get_le32 get_unaligned_le32
+#endif
+
+#endif
diff --git a/archival/libunarchive/unxz/xz_dec_bcj.c b/archival/libunarchive/unxz/xz_dec_bcj.c
new file mode 100644
index 000000000..09162b51f
--- /dev/null
+++ b/archival/libunarchive/unxz/xz_dec_bcj.c
@@ -0,0 +1,564 @@
+/*
+ * Branch/Call/Jump (BCJ) filter decoders
+ *
+ * Authors: Lasse Collin <lasse.collin@tukaani.org>
+ * Igor Pavlov <http://7-zip.org/>
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ */
+
+#include "xz_private.h"
+
+/*
+ * The rest of the file is inside this ifdef. It makes things a little more
+ * convenient when building without support for any BCJ filters.
+ */
+#ifdef XZ_DEC_BCJ
+
+struct xz_dec_bcj {
+ /* Type of the BCJ filter being used */
+ enum {
+ BCJ_X86 = 4, /* x86 or x86-64 */
+ BCJ_POWERPC = 5, /* Big endian only */
+ BCJ_IA64 = 6, /* Big or little endian */
+ BCJ_ARM = 7, /* Little endian only */
+ BCJ_ARMTHUMB = 8, /* Little endian only */
+ BCJ_SPARC = 9 /* Big or little endian */
+ } type;
+
+ /*
+ * Return value of the next filter in the chain. We need to preserve
+ * this information across calls, because we must not call the next
+ * filter anymore once it has returned XZ_STREAM_END.
+ */
+ enum xz_ret ret;
+
+ /* True if we are operating in single-call mode. */
+ bool single_call;
+
+ /*
+ * Absolute position relative to the beginning of the uncompressed
+ * data (in a single .xz Block). We care only about the lowest 32
+ * bits so this doesn't need to be uint64_t even with big files.
+ */
+ uint32_t pos;
+
+ /* x86 filter state */
+ uint32_t x86_prev_mask;
+
+ /* Temporary space to hold the variables from struct xz_buf */
+ uint8_t *out;
+ size_t out_pos;
+ size_t out_size;
+
+ struct {
+ /* Amount of already filtered data in the beginning of buf */
+ size_t filtered;
+
+ /* Total amount of data currently stored in buf */
+ size_t size;
+
+ /*
+ * Buffer to hold a mix of filtered and unfiltered data. This
+ * needs to be big enough to hold Alignment + 2 * Look-ahead:
+ *
+ * Type Alignment Look-ahead
+ * x86 1 4
+ * PowerPC 4 0
+ * IA-64 16 0
+ * ARM 4 0
+ * ARM-Thumb 2 2
+ * SPARC 4 0
+ */
+ uint8_t buf[16];
+ } temp;
+};
+
+#ifdef XZ_DEC_X86
+/*
+ * This is macro used to test the most significant byte of a memory address
+ * in an x86 instruction.
+ */
+#define bcj_x86_test_msbyte(b) ((b) == 0x00 || (b) == 0xFF)
+
+static noinline_for_stack size_t XZ_FUNC bcj_x86(
+ struct xz_dec_bcj *s, uint8_t *buf, size_t size)
+{
+ static const bool mask_to_allowed_status[8]
+ = { true, true, true, false, true, false, false, false };
+
+ static const uint8_t mask_to_bit_num[8] = { 0, 1, 2, 2, 3, 3, 3, 3 };
+
+ size_t i;
+ size_t prev_pos = (size_t)-1;
+ uint32_t prev_mask = s->x86_prev_mask;
+ uint32_t src;
+ uint32_t dest;
+ uint32_t j;
+ uint8_t b;
+
+ if (size <= 4)
+ return 0;
+
+ size -= 4;
+ for (i = 0; i < size; ++i) {
+ if ((buf[i] & 0xFE) != 0xE8)
+ continue;
+
+ prev_pos = i - prev_pos;
+ if (prev_pos > 3) {
+ prev_mask = 0;
+ } else {
+ prev_mask = (prev_mask << (prev_pos - 1)) & 7;
+ if (prev_mask != 0) {
+ b = buf[i + 4 - mask_to_bit_num[prev_mask]];
+ if (!mask_to_allowed_status[prev_mask]
+ || bcj_x86_test_msbyte(b)) {
+ prev_pos = i;
+ prev_mask = (prev_mask << 1) | 1;
+ continue;
+ }
+ }
+ }
+
+ prev_pos = i;
+
+ if (bcj_x86_test_msbyte(buf[i + 4])) {
+ src = get_unaligned_le32(buf + i + 1);
+ while (true) {
+ dest = src - (s->pos + (uint32_t)i + 5);
+ if (prev_mask == 0)
+ break;
+
+ j = mask_to_bit_num[prev_mask] * 8;
+ b = (uint8_t)(dest >> (24 - j));
+ if (!bcj_x86_test_msbyte(b))
+ break;
+
+ src = dest ^ (((uint32_t)1 << (32 - j)) - 1);
+ }
+
+ dest &= 0x01FFFFFF;
+ dest |= (uint32_t)0 - (dest & 0x01000000);
+ put_unaligned_le32(dest, buf + i + 1);
+ i += 4;
+ } else {
+ prev_mask = (prev_mask << 1) | 1;
+ }
+ }
+
+ prev_pos = i - prev_pos;
+ s->x86_prev_mask = prev_pos > 3 ? 0 : prev_mask << (prev_pos - 1);
+ return i;
+}
+#endif
+
+#ifdef XZ_DEC_POWERPC
+static noinline_for_stack size_t XZ_FUNC bcj_powerpc(
+ struct xz_dec_bcj *s, uint8_t *buf, size_t size)
+{
+ size_t i;
+ uint32_t instr;
+
+ for (i = 0; i + 4 <= size; i += 4) {
+ instr = get_unaligned_be32(buf + i);
+ if ((instr & 0xFC000003) == 0x48000001) {
+ instr &= 0x03FFFFFC;
+ instr -= s->pos + (uint32_t)i;
+ instr &= 0x03FFFFFC;
+ instr |= 0x48000001;
+ put_unaligned_be32(instr, buf + i);
+ }
+ }
+
+ return i;
+}
+#endif
+
+#ifdef XZ_DEC_IA64
+static noinline_for_stack size_t XZ_FUNC bcj_ia64(
+ struct xz_dec_bcj *s, uint8_t *buf, size_t size)
+{
+ static const uint8_t branch_table[32] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 6, 6, 0, 0, 7, 7,
+ 4, 4, 0, 0, 4, 4, 0, 0
+ };
+
+ /*
+ * The local variables take a little bit stack space, but it's less
+ * than what LZMA2 decoder takes, so it doesn't make sense to reduce
+ * stack usage here without doing that for the LZMA2 decoder too.
+ */
+
+ /* Loop counters */
+ size_t i;
+ size_t j;
+
+ /* Instruction slot (0, 1, or 2) in the 128-bit instruction word */
+ uint32_t slot;
+
+ /* Bitwise offset of the instruction indicated by slot */
+ uint32_t bit_pos;
+
+ /* bit_pos split into byte and bit parts */
+ uint32_t byte_pos;
+ uint32_t bit_res;
+
+ /* Address part of an instruction */
+ uint32_t addr;
+
+ /* Mask used to detect which instructions to convert */
+ uint32_t mask;
+
+ /* 41-bit instruction stored somewhere in the lowest 48 bits */
+ uint64_t instr;
+
+ /* Instruction normalized with bit_res for easier manipulation */
+ uint64_t norm;
+
+ for (i = 0; i + 16 <= size; i += 16) {
+ mask = branch_table[buf[i] & 0x1F];
+ for (slot = 0, bit_pos = 5; slot < 3; ++slot, bit_pos += 41) {
+ if (((mask >> slot) & 1) == 0)
+ continue;
+
+ byte_pos = bit_pos >> 3;
+ bit_res = bit_pos & 7;
+ instr = 0;
+ for (j = 0; j < 6; ++j)
+ instr |= (uint64_t)(buf[i + j + byte_pos])
+ << (8 * j);
+
+ norm = instr >> bit_res;
+
+ if (((norm >> 37) & 0x0F) == 0x05
+ && ((norm >> 9) & 0x07) == 0) {
+ addr = (norm >> 13) & 0x0FFFFF;
+ addr |= ((uint32_t)(norm >> 36) & 1) << 20;
+ addr <<= 4;
+ addr -= s->pos + (uint32_t)i;
+ addr >>= 4;
+
+ norm &= ~((uint64_t)0x8FFFFF << 13);
+ norm |= (uint64_t)(addr & 0x0FFFFF) << 13;
+ norm |= (uint64_t)(addr & 0x100000)
+ << (36 - 20);
+
+ instr &= (1 << bit_res) - 1;
+ instr |= norm << bit_res;
+
+ for (j = 0; j < 6; j++)
+ buf[i + j + byte_pos]
+ = (uint8_t)(instr >> (8 * j));
+ }
+ }
+ }
+
+ return i;
+}
+#endif
+
+#ifdef XZ_DEC_ARM
+static noinline_for_stack size_t XZ_FUNC bcj_arm(
+ struct xz_dec_bcj *s, uint8_t *buf, size_t size)
+{
+ size_t i;
+ uint32_t addr;
+
+ for (i = 0; i + 4 <= size; i += 4) {
+ if (buf[i + 3] == 0xEB) {
+ addr = (uint32_t)buf[i] | ((uint32_t)buf[i + 1] << 8)
+ | ((uint32_t)buf[i + 2] << 16);
+ addr <<= 2;
+ addr -= s->pos + (uint32_t)i + 8;
+ addr >>= 2;
+ buf[i] = (uint8_t)addr;
+ buf[i + 1] = (uint8_t)(addr >> 8);
+ buf[i + 2] = (uint8_t)(addr >> 16);
+ }
+ }
+
+ return i;
+}
+#endif
+
+#ifdef XZ_DEC_ARMTHUMB
+static noinline_for_stack size_t XZ_FUNC bcj_armthumb(
+ struct xz_dec_bcj *s, uint8_t *buf, size_t size)
+{
+ size_t i;
+ uint32_t addr;
+
+ for (i = 0; i + 4 <= size; i += 2) {
+ if ((buf[i + 1] & 0xF8) == 0xF0
+ && (buf[i + 3] & 0xF8) == 0xF8) {
+ addr = (((uint32_t)buf[i + 1] & 0x07) << 19)
+ | ((uint32_t)buf[i] << 11)
+ | (((uint32_t)buf[i + 3] & 0x07) << 8)
+ | (uint32_t)buf[i + 2];
+ addr <<= 1;
+ addr -= s->pos + (uint32_t)i + 4;
+ addr >>= 1;
+ buf[i + 1] = (uint8_t)(0xF0 | ((addr >> 19) & 0x07));
+ buf[i] = (uint8_t)(addr >> 11);
+ buf[i + 3] = (uint8_t)(0xF8 | ((addr >> 8) & 0x07));
+ buf[i + 2] = (uint8_t)addr;
+ i += 2;
+ }
+ }
+
+ return i;
+}
+#endif
+
+#ifdef XZ_DEC_SPARC
+static noinline_for_stack size_t XZ_FUNC bcj_sparc(
+ struct xz_dec_bcj *s, uint8_t *buf, size_t size)
+{
+ size_t i;
+ uint32_t instr;
+
+ for (i = 0; i + 4 <= size; i += 4) {
+ instr = get_unaligned_be32(buf + i);
+ if ((instr >> 22) == 0x100 || (instr >> 22) == 0x1FF) {
+ instr <<= 2;
+ instr -= s->pos + (uint32_t)i;
+ instr >>= 2;
+ instr = ((uint32_t)0x40000000 - (instr & 0x400000))
+ | 0x40000000 | (instr & 0x3FFFFF);
+ put_unaligned_be32(instr, buf + i);
+ }
+ }
+
+ return i;
+}
+#endif
+
+/*
+ * Apply the selected BCJ filter. Update *pos and s->pos to match the amount
+ * of data that got filtered.
+ *
+ * NOTE: This is implemented as a switch statement to avoid using function
+ * pointers, which could be problematic in the kernel boot code, which must
+ * avoid pointers to static data (at least on x86).
+ */
+static void XZ_FUNC bcj_apply(struct xz_dec_bcj *s,
+ uint8_t *buf, size_t *pos, size_t size)
+{
+ size_t filtered;
+
+ buf += *pos;
+ size -= *pos;
+
+ switch (s->type) {
+#ifdef XZ_DEC_X86
+ case BCJ_X86:
+ filtered = bcj_x86(s, buf, size);
+ break;
+#endif
+#ifdef XZ_DEC_POWERPC
+ case BCJ_POWERPC:
+ filtered = bcj_powerpc(s, buf, size);
+ break;
+#endif
+#ifdef XZ_DEC_IA64
+ case BCJ_IA64:
+ filtered = bcj_ia64(s, buf, size);
+ break;
+#endif
+#ifdef XZ_DEC_ARM
+ case BCJ_ARM:
+ filtered = bcj_arm(s, buf, size);
+ break;
+#endif
+#ifdef XZ_DEC_ARMTHUMB
+ case BCJ_ARMTHUMB:
+ filtered = bcj_armthumb(s, buf, size);
+ break;
+#endif
+#ifdef XZ_DEC_SPARC
+ case BCJ_SPARC:
+ filtered = bcj_sparc(s, buf, size);
+ break;
+#endif
+ default:
+ /* Never reached but silence compiler warnings. */
+ filtered = 0;
+ break;
+ }
+
+ *pos += filtered;
+ s->pos += filtered;
+}
+
+/*
+ * Flush pending filtered data from temp to the output buffer.
+ * Move the remaining mixture of possibly filtered and unfiltered
+ * data to the beginning of temp.
+ */
+static void XZ_FUNC bcj_flush(struct xz_dec_bcj *s, struct xz_buf *b)
+{
+ size_t copy_size;
+
+ copy_size = min_t(size_t, s->temp.filtered, b->out_size - b->out_pos);
+ memcpy(b->out + b->out_pos, s->temp.buf, copy_size);
+ b->out_pos += copy_size;
+
+ s->temp.filtered -= copy_size;
+ s->temp.size -= copy_size;
+ memmove(s->temp.buf, s->temp.buf + copy_size, s->temp.size);
+}
+
+/*
+ * The BCJ filter functions are primitive in sense that they process the
+ * data in chunks of 1-16 bytes. To hide this issue, this function does
+ * some buffering.
+ */
+XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_bcj_run(struct xz_dec_bcj *s,
+ struct xz_dec_lzma2 *lzma2, struct xz_buf *b)
+{
+ size_t out_start;
+
+ /*
+ * Flush pending already filtered data to the output buffer. Return
+ * immediatelly if we couldn't flush everything, or if the next
+ * filter in the chain had already returned XZ_STREAM_END.
+ */
+ if (s->temp.filtered > 0) {
+ bcj_flush(s, b);
+ if (s->temp.filtered > 0)
+ return XZ_OK;
+
+ if (s->ret == XZ_STREAM_END)
+ return XZ_STREAM_END;
+ }
+
+ /*
+ * If we have more output space than what is currently pending in
+ * temp, copy the unfiltered data from temp to the output buffer
+ * and try to fill the output buffer by decoding more data from the
+ * next filter in the chain. Apply the BCJ filter on the new data
+ * in the output buffer. If everything cannot be filtered, copy it
+ * to temp and rewind the output buffer position accordingly.
+ */
+ if (s->temp.size < b->out_size - b->out_pos) {
+ out_start = b->out_pos;
+ memcpy(b->out + b->out_pos, s->temp.buf, s->temp.size);
+ b->out_pos += s->temp.size;
+
+ s->ret = xz_dec_lzma2_run(lzma2, b);
+ if (s->ret != XZ_STREAM_END
+ && (s->ret != XZ_OK || s->single_call))
+ return s->ret;
+
+ bcj_apply(s, b->out, &out_start, b->out_pos);
+
+ /*
+ * As an exception, if the next filter returned XZ_STREAM_END,
+ * we can do that too, since the last few bytes that remain
+ * unfiltered are meant to remain unfiltered.
+ */
+ if (s->ret == XZ_STREAM_END)
+ return XZ_STREAM_END;
+
+ s->temp.size = b->out_pos - out_start;
+ b->out_pos -= s->temp.size;
+ memcpy(s->temp.buf, b->out + b->out_pos, s->temp.size);
+ }
+
+ /*
+ * If we have unfiltered data in temp, try to fill by decoding more
+ * data from the next filter. Apply the BCJ filter on temp. Then we
+ * hopefully can fill the actual output buffer by copying filtered
+ * data from temp. A mix of filtered and unfiltered data may be left
+ * in temp; it will be taken care on the next call to this function.
+ */
+ if (s->temp.size > 0) {
+ /* Make b->out{,_pos,_size} temporarily point to s->temp. */
+ s->out = b->out;
+ s->out_pos = b->out_pos;
+ s->out_size = b->out_size;
+ b->out = s->temp.buf;
+ b->out_pos = s->temp.size;
+ b->out_size = sizeof(s->temp.buf);
+
+ s->ret = xz_dec_lzma2_run(lzma2, b);
+
+ s->temp.size = b->out_pos;
+ b->out = s->out;
+ b->out_pos = s->out_pos;
+ b->out_size = s->out_size;
+
+ if (s->ret != XZ_OK && s->ret != XZ_STREAM_END)
+ return s->ret;
+
+ bcj_apply(s, s->temp.buf, &s->temp.filtered, s->temp.size);
+
+ /*
+ * If the next filter returned XZ_STREAM_END, we mark that
+ * everything is filtered, since the last unfiltered bytes
+ * of the stream are meant to be left as is.
+ */
+ if (s->ret == XZ_STREAM_END)
+ s->temp.filtered = s->temp.size;
+
+ bcj_flush(s, b);
+ if (s->temp.filtered > 0)
+ return XZ_OK;
+ }
+
+ return s->ret;
+}
+
+XZ_EXTERN struct xz_dec_bcj * XZ_FUNC xz_dec_bcj_create(bool single_call)
+{
+ struct xz_dec_bcj *s = kmalloc(sizeof(*s), GFP_KERNEL);
+ if (s != NULL)
+ s->single_call = single_call;
+
+ return s;
+}
+
+XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_bcj_reset(
+ struct xz_dec_bcj *s, uint8_t id)
+{
+ switch (id) {
+#ifdef XZ_DEC_X86
+ case BCJ_X86:
+#endif
+#ifdef XZ_DEC_POWERPC
+ case BCJ_POWERPC:
+#endif
+#ifdef XZ_DEC_IA64
+ case BCJ_IA64:
+#endif
+#ifdef XZ_DEC_ARM
+ case BCJ_ARM:
+#endif
+#ifdef XZ_DEC_ARMTHUMB
+ case BCJ_ARMTHUMB:
+#endif
+#ifdef XZ_DEC_SPARC
+ case BCJ_SPARC:
+#endif
+ break;
+
+ default:
+ /* Unsupported Filter ID */
+ return XZ_OPTIONS_ERROR;
+ }
+
+ s->type = id;
+ s->ret = XZ_OK;
+ s->pos = 0;
+ s->x86_prev_mask = 0;
+ s->temp.filtered = 0;
+ s->temp.size = 0;
+
+ return XZ_OK;
+}
+
+#endif
diff --git a/archival/libunarchive/unxz/xz_dec_lzma2.c b/archival/libunarchive/unxz/xz_dec_lzma2.c
new file mode 100644
index 000000000..da71cb4d4
--- /dev/null
+++ b/archival/libunarchive/unxz/xz_dec_lzma2.c
@@ -0,0 +1,1175 @@
+/*
+ * LZMA2 decoder
+ *
+ * Authors: Lasse Collin <lasse.collin@tukaani.org>
+ * Igor Pavlov <http://7-zip.org/>
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ */
+
+#include "xz_private.h"
+#include "xz_lzma2.h"
+
+/*
+ * Range decoder initialization eats the first five bytes of each LZMA chunk.
+ */
+#define RC_INIT_BYTES 5
+
+/*
+ * Minimum number of usable input buffer to safely decode one LZMA symbol.
+ * The worst case is that we decode 22 bits using probabilities and 26
+ * direct bits. This may decode at maximum of 20 bytes of input. However,
+ * lzma_main() does an extra normalization before returning, thus we
+ * need to put 21 here.
+ */
+#define LZMA_IN_REQUIRED 21
+
+/*
+ * Dictionary (history buffer)
+ *
+ * These are always true:
+ * start <= pos <= full <= end
+ * pos <= limit <= end
+ *
+ * In multi-call mode, also these are true:
+ * end == size
+ * size <= size_max
+ * allocated <= size
+ *
+ * Most of these variables are size_t to support single-call mode,
+ * in which the dictionary variables address the actual output
+ * buffer directly.
+ */
+struct dictionary {
+ /* Beginning of the history buffer */
+ uint8_t *buf;
+
+ /* Old position in buf (before decoding more data) */
+ size_t start;
+
+ /* Position in buf */
+ size_t pos;
+
+ /*
+ * How full dictionary is. This is used to detect corrupt input that
+ * would read beyond the beginning of the uncompressed stream.
+ */
+ size_t full;
+
+ /* Write limit; we don't write to buf[limit] or later bytes. */
+ size_t limit;
+
+ /*
+ * End of the dictionary buffer. In multi-call mode, this is
+ * the same as the dictionary size. In single-call mode, this
+ * indicates the size of the output buffer.
+ */
+ size_t end;
+
+ /*
+ * Size of the dictionary as specified in Block Header. This is used
+ * together with "full" to detect corrupt input that would make us
+ * read beyond the beginning of the uncompressed stream.
+ */
+ uint32_t size;
+
+ /*
+ * Maximum allowed dictionary size in multi-call mode.
+ * This is ignored in single-call mode.
+ */
+ uint32_t size_max;
+
+ /*
+ * Amount of memory currently allocated for the dictionary.
+ * This is used only with XZ_DYNALLOC. (With XZ_PREALLOC,
+ * size_max is always the same as the allocated size.)
+ */
+ uint32_t allocated;
+
+ /* Operation mode */
+ enum xz_mode mode;
+};
+
+/* Range decoder */
+struct rc_dec {
+ uint32_t range;
+ uint32_t code;
+
+ /*
+ * Number of initializing bytes remaining to be read
+ * by rc_read_init().
+ */
+ uint32_t init_bytes_left;
+
+ /*
+ * Buffer from which we read our input. It can be either
+ * temp.buf or the caller-provided input buffer.
+ */
+ const uint8_t *in;
+ size_t in_pos;
+ size_t in_limit;
+};
+
+/* Probabilities for a length decoder. */
+struct lzma_len_dec {
+ /* Probability of match length being at least 10 */
+ uint16_t choice;
+
+ /* Probability of match length being at least 18 */
+ uint16_t choice2;
+
+ /* Probabilities for match lengths 2-9 */
+ uint16_t low[POS_STATES_MAX][LEN_LOW_SYMBOLS];
+
+ /* Probabilities for match lengths 10-17 */
+ uint16_t mid[POS_STATES_MAX][LEN_MID_SYMBOLS];
+
+ /* Probabilities for match lengths 18-273 */
+ uint16_t high[LEN_HIGH_SYMBOLS];
+};
+
+struct lzma_dec {
+ /* Distances of latest four matches */
+ uint32_t rep0;
+ uint32_t rep1;
+ uint32_t rep2;
+ uint32_t rep3;
+
+ /* Types of the most recently seen LZMA symbols */
+ enum lzma_state state;
+
+ /*
+ * Length of a match. This is updated so that dict_repeat can
+ * be called again to finish repeating the whole match.
+ */
+ uint32_t len;
+
+ /*
+ * LZMA properties or related bit masks (number of literal
+ * context bits, a mask dervied from the number of literal
+ * position bits, and a mask dervied from the number
+ * position bits)
+ */
+ uint32_t lc;
+ uint32_t literal_pos_mask; /* (1 << lp) - 1 */
+ uint32_t pos_mask; /* (1 << pb) - 1 */
+
+ /* If 1, it's a match. Otherwise it's a single 8-bit literal. */
+ uint16_t is_match[STATES][POS_STATES_MAX];
+
+ /* If 1, it's a repeated match. The distance is one of rep0 .. rep3. */
+ uint16_t is_rep[STATES];
+
+ /*
+ * If 0, distance of a repeated match is rep0.
+ * Otherwise check is_rep1.
+ */
+ uint16_t is_rep0[STATES];
+
+ /*
+ * If 0, distance of a repeated match is rep1.
+ * Otherwise check is_rep2.
+ */
+ uint16_t is_rep1[STATES];
+
+ /* If 0, distance of a repeated match is rep2. Otherwise it is rep3. */
+ uint16_t is_rep2[STATES];
+
+ /*
+ * If 1, the repeated match has length of one byte. Otherwise
+ * the length is decoded from rep_len_decoder.
+ */
+ uint16_t is_rep0_long[STATES][POS_STATES_MAX];
+
+ /*
+ * Probability tree for the highest two bits of the match
+ * distance. There is a separate probability tree for match
+ * lengths of 2 (i.e. MATCH_LEN_MIN), 3, 4, and [5, 273].
+ */
+ uint16_t dist_slot[DIST_STATES][DIST_SLOTS];
+
+ /*
+ * Probility trees for additional bits for match distance
+ * when the distance is in the range [4, 127].
+ */
+ uint16_t dist_special[FULL_DISTANCES - DIST_MODEL_END];
+
+ /*
+ * Probability tree for the lowest four bits of a match
+ * distance that is equal to or greater than 128.
+ */
+ uint16_t dist_align[ALIGN_SIZE];
+
+ /* Length of a normal match */
+ struct lzma_len_dec match_len_dec;
+
+ /* Length of a repeated match */
+ struct lzma_len_dec rep_len_dec;
+
+ /* Probabilities of literals */
+ uint16_t literal[LITERAL_CODERS_MAX][LITERAL_CODER_SIZE];
+};
+
+struct lzma2_dec {
+ /* Position in xz_dec_lzma2_run(). */
+ enum lzma2_seq {
+ SEQ_CONTROL,
+ SEQ_UNCOMPRESSED_1,
+ SEQ_UNCOMPRESSED_2,
+ SEQ_COMPRESSED_0,
+ SEQ_COMPRESSED_1,
+ SEQ_PROPERTIES,
+ SEQ_LZMA_PREPARE,
+ SEQ_LZMA_RUN,
+ SEQ_COPY
+ } sequence;
+
+ /* Next position after decoding the compressed size of the chunk. */
+ enum lzma2_seq next_sequence;
+
+ /* Uncompressed size of LZMA chunk (2 MiB at maximum) */
+ uint32_t uncompressed;
+
+ /*
+ * Compressed size of LZMA chunk or compressed/uncompressed
+ * size of uncompressed chunk (64 KiB at maximum)
+ */
+ uint32_t compressed;
+
+ /*
+ * True if dictionary reset is needed. This is false before
+ * the first chunk (LZMA or uncompressed).
+ */
+ bool need_dict_reset;
+
+ /*
+ * True if new LZMA properties are needed. This is false
+ * before the first LZMA chunk.
+ */
+ bool need_props;
+};
+
+struct xz_dec_lzma2 {
+ /*
+ * The order below is important on x86 to reduce code size and
+ * it shouldn't hurt on other platforms. Everything up to and
+ * including lzma.pos_mask are in the first 128 bytes on x86-32,
+ * which allows using smaller instructions to access those
+ * variables. On x86-64, fewer variables fit into the first 128
+ * bytes, but this is still the best order without sacrificing
+ * the readability by splitting the structures.
+ */
+ struct rc_dec rc;
+ struct dictionary dict;
+ struct lzma2_dec lzma2;
+ struct lzma_dec lzma;
+
+ /*
+ * Temporary buffer which holds small number of input bytes between
+ * decoder calls. See lzma2_lzma() for details.
+ */
+ struct {
+ uint32_t size;
+ uint8_t buf[3 * LZMA_IN_REQUIRED];
+ } temp;
+};
+
+/**************
+ * Dictionary *
+ **************/
+
+/*
+ * Reset the dictionary state. When in single-call mode, set up the beginning
+ * of the dictionary to point to the actual output buffer.
+ */
+static void XZ_FUNC dict_reset(struct dictionary *dict, struct xz_buf *b)
+{
+ if (DEC_IS_SINGLE(dict->mode)) {
+ dict->buf = b->out + b->out_pos;
+ dict->end = b->out_size - b->out_pos;
+ }
+
+ dict->start = 0;
+ dict->pos = 0;
+ dict->limit = 0;
+ dict->full = 0;
+}
+
+/* Set dictionary write limit */
+static void XZ_FUNC dict_limit(struct dictionary *dict, size_t out_max)
+{
+ if (dict->end - dict->pos <= out_max)
+ dict->limit = dict->end;
+ else
+ dict->limit = dict->pos + out_max;
+}
+
+/* Return true if at least one byte can be written into the dictionary. */
+static __always_inline bool XZ_FUNC dict_has_space(const struct dictionary *dict)
+{
+ return dict->pos < dict->limit;
+}
+
+/*
+ * Get a byte from the dictionary at the given distance. The distance is
+ * assumed to valid, or as a special case, zero when the dictionary is
+ * still empty. This special case is needed for single-call decoding to
+ * avoid writing a '\0' to the end of the destination buffer.
+ */
+static __always_inline uint32_t XZ_FUNC dict_get(
+ const struct dictionary *dict, uint32_t dist)
+{
+ size_t offset = dict->pos - dist - 1;
+
+ if (dist >= dict->pos)
+ offset += dict->end;
+
+ return dict->full > 0 ? dict->buf[offset] : 0;
+}
+
+/*
+ * Put one byte into the dictionary. It is assumed that there is space for it.
+ */
+static inline void XZ_FUNC dict_put(struct dictionary *dict, uint8_t byte)
+{
+ dict->buf[dict->pos++] = byte;
+
+ if (dict->full < dict->pos)
+ dict->full = dict->pos;
+}
+
+/*
+ * Repeat given number of bytes from the given distance. If the distance is
+ * invalid, false is returned. On success, true is returned and *len is
+ * updated to indicate how many bytes were left to be repeated.
+ */
+static bool XZ_FUNC dict_repeat(
+ struct dictionary *dict, uint32_t *len, uint32_t dist)
+{
+ size_t back;
+ uint32_t left;
+
+ if (dist >= dict->full || dist >= dict->size)
+ return false;
+
+ left = min_t(size_t, dict->limit - dict->pos, *len);
+ *len -= left;
+
+ back = dict->pos - dist - 1;
+ if (dist >= dict->pos)
+ back += dict->end;
+
+ do {
+ dict->buf[dict->pos++] = dict->buf[back++];
+ if (back == dict->end)
+ back = 0;
+ } while (--left > 0);
+
+ if (dict->full < dict->pos)
+ dict->full = dict->pos;
+
+ return true;
+}
+
+/* Copy uncompressed data as is from input to dictionary and output buffers. */
+static void XZ_FUNC dict_uncompressed(
+ struct dictionary *dict, struct xz_buf *b, uint32_t *left)
+{
+ size_t copy_size;
+
+ while (*left > 0 && b->in_pos < b->in_size
+ && b->out_pos < b->out_size) {
+ copy_size = min(b->in_size - b->in_pos,
+ b->out_size - b->out_pos);
+ if (copy_size > dict->end - dict->pos)
+ copy_size = dict->end - dict->pos;
+ if (copy_size > *left)
+ copy_size = *left;
+
+ *left -= copy_size;
+
+ memcpy(dict->buf + dict->pos, b->in + b->in_pos, copy_size);
+ dict->pos += copy_size;
+
+ if (dict->full < dict->pos)
+ dict->full = dict->pos;
+
+ if (DEC_IS_MULTI(dict->mode)) {
+ if (dict->pos == dict->end)
+ dict->pos = 0;
+
+ memcpy(b->out + b->out_pos, b->in + b->in_pos,
+ copy_size);
+ }
+
+ dict->start = dict->pos;
+
+ b->out_pos += copy_size;
+ b->in_pos += copy_size;
+
+ }
+}
+
+/*
+ * Flush pending data from dictionary to b->out. It is assumed that there is
+ * enough space in b->out. This is guaranteed because caller uses dict_limit()
+ * before decoding data into the dictionary.
+ */
+static uint32_t XZ_FUNC dict_flush(struct dictionary *dict, struct xz_buf *b)
+{
+ size_t copy_size = dict->pos - dict->start;
+
+ if (DEC_IS_MULTI(dict->mode)) {
+ if (dict->pos == dict->end)
+ dict->pos = 0;
+
+ memcpy(b->out + b->out_pos, dict->buf + dict->start,
+ copy_size);
+ }
+
+ dict->start = dict->pos;
+ b->out_pos += copy_size;
+ return copy_size;
+}
+
+/*****************
+ * Range decoder *
+ *****************/
+
+/* Reset the range decoder. */
+static void XZ_FUNC rc_reset(struct rc_dec *rc)
+{
+ rc->range = (uint32_t)-1;
+ rc->code = 0;
+ rc->init_bytes_left = RC_INIT_BYTES;
+}
+
+/*
+ * Read the first five initial bytes into rc->code if they haven't been
+ * read already. (Yes, the first byte gets completely ignored.)
+ */
+static bool XZ_FUNC rc_read_init(struct rc_dec *rc, struct xz_buf *b)
+{
+ while (rc->init_bytes_left > 0) {
+ if (b->in_pos == b->in_size)
+ return false;
+
+ rc->code = (rc->code << 8) + b->in[b->in_pos++];
+ --rc->init_bytes_left;
+ }
+
+ return true;
+}
+
+/* Return true if there may not be enough input for the next decoding loop. */
+static inline bool XZ_FUNC rc_limit_exceeded(const struct rc_dec *rc)
+{
+ return rc->in_pos > rc->in_limit;
+}
+
+/*
+ * Return true if it is possible (from point of view of range decoder) that
+ * we have reached the end of the LZMA chunk.
+ */
+static inline bool XZ_FUNC rc_is_finished(const struct rc_dec *rc)
+{
+ return rc->code == 0;
+}
+
+/* Read the next input byte if needed. */
+static __always_inline void XZ_FUNC rc_normalize(struct rc_dec *rc)
+{
+ if (rc->range < RC_TOP_VALUE) {
+ rc->range <<= RC_SHIFT_BITS;
+ rc->code = (rc->code << RC_SHIFT_BITS) + rc->in[rc->in_pos++];
+ }
+}
+
+/*
+ * Decode one bit. In some versions, this function has been splitted in three
+ * functions so that the compiler is supposed to be able to more easily avoid
+ * an extra branch. In this particular version of the LZMA decoder, this
+ * doesn't seem to be a good idea (tested with GCC 3.3.6, 3.4.6, and 4.3.3
+ * on x86). Using a non-splitted version results in nicer looking code too.
+ *
+ * NOTE: This must return an int. Do not make it return a bool or the speed
+ * of the code generated by GCC 3.x decreases 10-15 %. (GCC 4.3 doesn't care,
+ * and it generates 10-20 % faster code than GCC 3.x from this file anyway.)
+ */
+static __always_inline int XZ_FUNC rc_bit(struct rc_dec *rc, uint16_t *prob)
+{
+ uint32_t bound;
+ int bit;
+
+ rc_normalize(rc);
+ bound = (rc->range >> RC_BIT_MODEL_TOTAL_BITS) * *prob;
+ if (rc->code < bound) {
+ rc->range = bound;
+ *prob += (RC_BIT_MODEL_TOTAL - *prob) >> RC_MOVE_BITS;
+ bit = 0;
+ } else {
+ rc->range -= bound;
+ rc->code -= bound;
+ *prob -= *prob >> RC_MOVE_BITS;
+ bit = 1;
+ }
+
+ return bit;
+}
+
+/* Decode a bittree starting from the most significant bit. */
+static __always_inline uint32_t XZ_FUNC rc_bittree(
+ struct rc_dec *rc, uint16_t *probs, uint32_t limit)
+{
+ uint32_t symbol = 1;
+
+ do {
+ if (rc_bit(rc, &probs[symbol]))
+ symbol = (symbol << 1) + 1;
+ else
+ symbol <<= 1;
+ } while (symbol < limit);
+
+ return symbol;
+}
+
+/* Decode a bittree starting from the least significant bit. */
+static __always_inline void XZ_FUNC rc_bittree_reverse(struct rc_dec *rc,
+ uint16_t *probs, uint32_t *dest, uint32_t limit)
+{
+ uint32_t symbol = 1;
+ uint32_t i = 0;
+
+ do {
+ if (rc_bit(rc, &probs[symbol])) {
+ symbol = (symbol << 1) + 1;
+ *dest += 1 << i;
+ } else {
+ symbol <<= 1;
+ }
+ } while (++i < limit);
+}
+
+/* Decode direct bits (fixed fifty-fifty probability) */
+static inline void XZ_FUNC rc_direct(
+ struct rc_dec *rc, uint32_t *dest, uint32_t limit)
+{
+ uint32_t mask;
+
+ do {
+ rc_normalize(rc);
+ rc->range >>= 1;
+ rc->code -= rc->range;
+ mask = (uint32_t)0 - (rc->code >> 31);
+ rc->code += rc->range & mask;
+ *dest = (*dest << 1) + (mask + 1);
+ } while (--limit > 0);
+}
+
+/********
+ * LZMA *
+ ********/
+
+/* Get pointer to literal coder probability array. */
+static uint16_t * XZ_FUNC lzma_literal_probs(struct xz_dec_lzma2 *s)
+{
+ uint32_t prev_byte = dict_get(&s->dict, 0);
+ uint32_t low = prev_byte >> (8 - s->lzma.lc);
+ uint32_t high = (s->dict.pos & s->lzma.literal_pos_mask) << s->lzma.lc;
+ return s->lzma.literal[low + high];
+}
+
+/* Decode a literal (one 8-bit byte) */
+static void XZ_FUNC lzma_literal(struct xz_dec_lzma2 *s)
+{
+ uint16_t *probs;
+ uint32_t symbol;
+ uint32_t match_byte;
+ uint32_t match_bit;
+ uint32_t offset;
+ uint32_t i;
+
+ probs = lzma_literal_probs(s);
+
+ if (lzma_state_is_literal(s->lzma.state)) {
+ symbol = rc_bittree(&s->rc, probs, 0x100);
+ } else {
+ symbol = 1;
+ match_byte = dict_get(&s->dict, s->lzma.rep0) << 1;
+ offset = 0x100;
+
+ do {
+ match_bit = match_byte & offset;
+ match_byte <<= 1;
+ i = offset + match_bit + symbol;
+
+ if (rc_bit(&s->rc, &probs[i])) {
+ symbol = (symbol << 1) + 1;
+ offset &= match_bit;
+ } else {
+ symbol <<= 1;
+ offset &= ~match_bit;
+ }
+ } while (symbol < 0x100);
+ }
+
+ dict_put(&s->dict, (uint8_t)symbol);
+ lzma_state_literal(&s->lzma.state);
+}
+
+/* Decode the length of the match into s->lzma.len. */
+static void XZ_FUNC lzma_len(struct xz_dec_lzma2 *s, struct lzma_len_dec *l,
+ uint32_t pos_state)
+{
+ uint16_t *probs;
+ uint32_t limit;
+
+ if (!rc_bit(&s->rc, &l->choice)) {
+ probs = l->low[pos_state];
+ limit = LEN_LOW_SYMBOLS;
+ s->lzma.len = MATCH_LEN_MIN;
+ } else {
+ if (!rc_bit(&s->rc, &l->choice2)) {
+ probs = l->mid[pos_state];
+ limit = LEN_MID_SYMBOLS;
+ s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS;
+ } else {
+ probs = l->high;
+ limit = LEN_HIGH_SYMBOLS;
+ s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS
+ + LEN_MID_SYMBOLS;
+ }
+ }
+
+ s->lzma.len += rc_bittree(&s->rc, probs, limit) - limit;
+}
+
+/* Decode a match. The distance will be stored in s->lzma.rep0. */
+static void XZ_FUNC lzma_match(struct xz_dec_lzma2 *s, uint32_t pos_state)
+{
+ uint16_t *probs;
+ uint32_t dist_slot;
+ uint32_t limit;
+
+ lzma_state_match(&s->lzma.state);
+
+ s->lzma.rep3 = s->lzma.rep2;
+ s->lzma.rep2 = s->lzma.rep1;
+ s->lzma.rep1 = s->lzma.rep0;
+
+ lzma_len(s, &s->lzma.match_len_dec, pos_state);
+
+ probs = s->lzma.dist_slot[lzma_get_dist_state(s->lzma.len)];
+ dist_slot = rc_bittree(&s->rc, probs, DIST_SLOTS) - DIST_SLOTS;
+
+ if (dist_slot < DIST_MODEL_START) {
+ s->lzma.rep0 = dist_slot;
+ } else {
+ limit = (dist_slot >> 1) - 1;
+ s->lzma.rep0 = 2 + (dist_slot & 1);
+
+ if (dist_slot < DIST_MODEL_END) {
+ s->lzma.rep0 <<= limit;
+ probs = s->lzma.dist_special + s->lzma.rep0
+ - dist_slot - 1;
+ rc_bittree_reverse(&s->rc, probs,
+ &s->lzma.rep0, limit);
+ } else {
+ rc_direct(&s->rc, &s->lzma.rep0, limit - ALIGN_BITS);
+ s->lzma.rep0 <<= ALIGN_BITS;
+ rc_bittree_reverse(&s->rc, s->lzma.dist_align,
+ &s->lzma.rep0, ALIGN_BITS);
+ }
+ }
+}
+
+/*
+ * Decode a repeated match. The distance is one of the four most recently
+ * seen matches. The distance will be stored in s->lzma.rep0.
+ */
+static void XZ_FUNC lzma_rep_match(struct xz_dec_lzma2 *s, uint32_t pos_state)
+{
+ uint32_t tmp;
+
+ if (!rc_bit(&s->rc, &s->lzma.is_rep0[s->lzma.state])) {
+ if (!rc_bit(&s->rc, &s->lzma.is_rep0_long[
+ s->lzma.state][pos_state])) {
+ lzma_state_short_rep(&s->lzma.state);
+ s->lzma.len = 1;
+ return;
+ }
+ } else {
+ if (!rc_bit(&s->rc, &s->lzma.is_rep1[s->lzma.state])) {
+ tmp = s->lzma.rep1;
+ } else {
+ if (!rc_bit(&s->rc, &s->lzma.is_rep2[s->lzma.state])) {
+ tmp = s->lzma.rep2;
+ } else {
+ tmp = s->lzma.rep3;
+ s->lzma.rep3 = s->lzma.rep2;
+ }
+
+ s->lzma.rep2 = s->lzma.rep1;
+ }
+
+ s->lzma.rep1 = s->lzma.rep0;
+ s->lzma.rep0 = tmp;
+ }
+
+ lzma_state_long_rep(&s->lzma.state);
+ lzma_len(s, &s->lzma.rep_len_dec, pos_state);
+}
+
+/* LZMA decoder core */
+static bool XZ_FUNC lzma_main(struct xz_dec_lzma2 *s)
+{
+ uint32_t pos_state;
+
+ /*
+ * If the dictionary was reached during the previous call, try to
+ * finish the possibly pending repeat in the dictionary.
+ */
+ if (dict_has_space(&s->dict) && s->lzma.len > 0)
+ dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0);
+
+ /*
+ * Decode more LZMA symbols. One iteration may consume up to
+ * LZMA_IN_REQUIRED - 1 bytes.
+ */
+ while (dict_has_space(&s->dict) && !rc_limit_exceeded(&s->rc)) {
+ pos_state = s->dict.pos & s->lzma.pos_mask;
+
+ if (!rc_bit(&s->rc, &s->lzma.is_match[
+ s->lzma.state][pos_state])) {
+ lzma_literal(s);
+ } else {
+ if (rc_bit(&s->rc, &s->lzma.is_rep[s->lzma.state]))
+ lzma_rep_match(s, pos_state);
+ else
+ lzma_match(s, pos_state);
+
+ if (!dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0))
+ return false;
+ }
+ }
+
+ /*
+ * Having the range decoder always normalized when we are outside
+ * this function makes it easier to correctly handle end of the chunk.
+ */
+ rc_normalize(&s->rc);
+
+ return true;
+}
+
+/*
+ * Reset the LZMA decoder and range decoder state. Dictionary is nore reset
+ * here, because LZMA state may be reset without resetting the dictionary.
+ */
+static void XZ_FUNC lzma_reset(struct xz_dec_lzma2 *s)
+{
+ uint16_t *probs;
+ size_t i;
+
+ s->lzma.state = STATE_LIT_LIT;
+ s->lzma.rep0 = 0;
+ s->lzma.rep1 = 0;
+ s->lzma.rep2 = 0;
+ s->lzma.rep3 = 0;
+
+ /*
+ * All probabilities are initialized to the same value. This hack
+ * makes the code smaller by avoiding a separate loop for each
+ * probability array.
+ *
+ * This could be optimized so that only that part of literal
+ * probabilities that are actually required. In the common case
+ * we would write 12 KiB less.
+ */
+ probs = s->lzma.is_match[0];
+ for (i = 0; i < PROBS_TOTAL; ++i)
+ probs[i] = RC_BIT_MODEL_TOTAL / 2;
+
+ rc_reset(&s->rc);
+}
+
+/*
+ * Decode and validate LZMA properties (lc/lp/pb) and calculate the bit masks
+ * from the decoded lp and pb values. On success, the LZMA decoder state is
+ * reset and true is returned.
+ */
+static bool XZ_FUNC lzma_props(struct xz_dec_lzma2 *s, uint8_t props)
+{
+ if (props > (4 * 5 + 4) * 9 + 8)
+ return false;
+
+ s->lzma.pos_mask = 0;
+ while (props >= 9 * 5) {
+ props -= 9 * 5;
+ ++s->lzma.pos_mask;
+ }
+
+ s->lzma.pos_mask = (1 << s->lzma.pos_mask) - 1;
+
+ s->lzma.literal_pos_mask = 0;
+ while (props >= 9) {
+ props -= 9;
+ ++s->lzma.literal_pos_mask;
+ }
+
+ s->lzma.lc = props;
+
+ if (s->lzma.lc + s->lzma.literal_pos_mask > 4)
+ return false;
+
+ s->lzma.literal_pos_mask = (1 << s->lzma.literal_pos_mask) - 1;
+
+ lzma_reset(s);
+
+ return true;
+}
+
+/*********
+ * LZMA2 *
+ *********/
+
+/*
+ * The LZMA decoder assumes that if the input limit (s->rc.in_limit) hasn't
+ * been exceeded, it is safe to read up to LZMA_IN_REQUIRED bytes. This
+ * wrapper function takes care of making the LZMA decoder's assumption safe.
+ *
+ * As long as there is plenty of input left to be decoded in the current LZMA
+ * chunk, we decode directly from the caller-supplied input buffer until
+ * there's LZMA_IN_REQUIRED bytes left. Those remaining bytes are copied into
+ * s->temp.buf, which (hopefully) gets filled on the next call to this
+ * function. We decode a few bytes from the temporary buffer so that we can
+ * continue decoding from the caller-supplied input buffer again.
+ */
+static bool XZ_FUNC lzma2_lzma(struct xz_dec_lzma2 *s, struct xz_buf *b)
+{
+ size_t in_avail;
+ uint32_t tmp;
+
+ in_avail = b->in_size - b->in_pos;
+ if (s->temp.size > 0 || s->lzma2.compressed == 0) {
+ tmp = 2 * LZMA_IN_REQUIRED - s->temp.size;
+ if (tmp > s->lzma2.compressed - s->temp.size)
+ tmp = s->lzma2.compressed - s->temp.size;
+ if (tmp > in_avail)
+ tmp = in_avail;
+
+ memcpy(s->temp.buf + s->temp.size, b->in + b->in_pos, tmp);
+
+ if (s->temp.size + tmp == s->lzma2.compressed) {
+ memzero(s->temp.buf + s->temp.size + tmp,
+ sizeof(s->temp.buf)
+ - s->temp.size - tmp);
+ s->rc.in_limit = s->temp.size + tmp;
+ } else if (s->temp.size + tmp < LZMA_IN_REQUIRED) {
+ s->temp.size += tmp;
+ b->in_pos += tmp;
+ return true;
+ } else {
+ s->rc.in_limit = s->temp.size + tmp - LZMA_IN_REQUIRED;
+ }
+
+ s->rc.in = s->temp.buf;
+ s->rc.in_pos = 0;
+
+ if (!lzma_main(s) || s->rc.in_pos > s->temp.size + tmp)
+ return false;
+
+ s->lzma2.compressed -= s->rc.in_pos;
+
+ if (s->rc.in_pos < s->temp.size) {
+ s->temp.size -= s->rc.in_pos;
+ memmove(s->temp.buf, s->temp.buf + s->rc.in_pos,
+ s->temp.size);
+ return true;
+ }
+
+ b->in_pos += s->rc.in_pos - s->temp.size;
+ s->temp.size = 0;
+ }
+
+ in_avail = b->in_size - b->in_pos;
+ if (in_avail >= LZMA_IN_REQUIRED) {
+ s->rc.in = b->in;
+ s->rc.in_pos = b->in_pos;
+
+ if (in_avail >= s->lzma2.compressed + LZMA_IN_REQUIRED)
+ s->rc.in_limit = b->in_pos + s->lzma2.compressed;
+ else
+ s->rc.in_limit = b->in_size - LZMA_IN_REQUIRED;
+
+ if (!lzma_main(s))
+ return false;
+
+ in_avail = s->rc.in_pos - b->in_pos;
+ if (in_avail > s->lzma2.compressed)
+ return false;
+
+ s->lzma2.compressed -= in_avail;
+ b->in_pos = s->rc.in_pos;
+ }
+
+ in_avail = b->in_size - b->in_pos;
+ if (in_avail < LZMA_IN_REQUIRED) {
+ if (in_avail > s->lzma2.compressed)
+ in_avail = s->lzma2.compressed;
+
+ memcpy(s->temp.buf, b->in + b->in_pos, in_avail);
+ s->temp.size = in_avail;
+ b->in_pos += in_avail;
+ }
+
+ return true;
+}
+
+/*
+ * Take care of the LZMA2 control layer, and forward the job of actual LZMA
+ * decoding or copying of uncompressed chunks to other functions.
+ */
+XZ_EXTERN NOINLINE enum xz_ret XZ_FUNC xz_dec_lzma2_run(
+ struct xz_dec_lzma2 *s, struct xz_buf *b)
+{
+ uint32_t tmp;
+
+ while (b->in_pos < b->in_size || s->lzma2.sequence == SEQ_LZMA_RUN) {
+ switch (s->lzma2.sequence) {
+ case SEQ_CONTROL:
+ /*
+ * LZMA2 control byte
+ *
+ * Exact values:
+ * 0x00 End marker
+ * 0x01 Dictionary reset followed by
+ * an uncompressed chunk
+ * 0x02 Uncompressed chunk (no dictionary reset)
+ *
+ * Highest three bits (s->control & 0xE0):
+ * 0xE0 Dictionary reset, new properties and state
+ * reset, followed by LZMA compressed chunk
+ * 0xC0 New properties and state reset, followed
+ * by LZMA compressed chunk (no dictionary
+ * reset)
+ * 0xA0 State reset using old properties,
+ * followed by LZMA compressed chunk (no
+ * dictionary reset)
+ * 0x80 LZMA chunk (no dictionary or state reset)
+ *
+ * For LZMA compressed chunks, the lowest five bits
+ * (s->control & 1F) are the highest bits of the
+ * uncompressed size (bits 16-20).
+ *
+ * A new LZMA2 stream must begin with a dictionary
+ * reset. The first LZMA chunk must set new
+ * properties and reset the LZMA state.
+ *
+ * Values that don't match anything described above
+ * are invalid and we return XZ_DATA_ERROR.
+ */
+ tmp = b->in[b->in_pos++];
+
+ if (tmp >= 0xE0 || tmp == 0x01) {
+ s->lzma2.need_props = true;
+ s->lzma2.need_dict_reset = false;
+ dict_reset(&s->dict, b);
+ } else if (s->lzma2.need_dict_reset) {
+ return XZ_DATA_ERROR;
+ }
+
+ if (tmp >= 0x80) {
+ s->lzma2.uncompressed = (tmp & 0x1F) << 16;
+ s->lzma2.sequence = SEQ_UNCOMPRESSED_1;
+
+ if (tmp >= 0xC0) {
+ /*
+ * When there are new properties,
+ * state reset is done at
+ * SEQ_PROPERTIES.
+ */
+ s->lzma2.need_props = false;
+ s->lzma2.next_sequence
+ = SEQ_PROPERTIES;
+
+ } else if (s->lzma2.need_props) {
+ return XZ_DATA_ERROR;
+
+ } else {
+ s->lzma2.next_sequence
+ = SEQ_LZMA_PREPARE;
+ if (tmp >= 0xA0)
+ lzma_reset(s);
+ }
+ } else {
+ if (tmp == 0x00)
+ return XZ_STREAM_END;
+
+ if (tmp > 0x02)
+ return XZ_DATA_ERROR;
+
+ s->lzma2.sequence = SEQ_COMPRESSED_0;
+ s->lzma2.next_sequence = SEQ_COPY;
+ }
+
+ break;
+
+ case SEQ_UNCOMPRESSED_1:
+ s->lzma2.uncompressed
+ += (uint32_t)b->in[b->in_pos++] << 8;
+ s->lzma2.sequence = SEQ_UNCOMPRESSED_2;
+ break;
+
+ case SEQ_UNCOMPRESSED_2:
+ s->lzma2.uncompressed
+ += (uint32_t)b->in[b->in_pos++] + 1;
+ s->lzma2.sequence = SEQ_COMPRESSED_0;
+ break;
+
+ case SEQ_COMPRESSED_0:
+ s->lzma2.compressed
+ = (uint32_t)b->in[b->in_pos++] << 8;
+ s->lzma2.sequence = SEQ_COMPRESSED_1;
+ break;
+
+ case SEQ_COMPRESSED_1:
+ s->lzma2.compressed
+ += (uint32_t)b->in[b->in_pos++] + 1;
+ s->lzma2.sequence = s->lzma2.next_sequence;
+ break;
+
+ case SEQ_PROPERTIES:
+ if (!lzma_props(s, b->in[b->in_pos++]))
+ return XZ_DATA_ERROR;
+
+ s->lzma2.sequence = SEQ_LZMA_PREPARE;
+
+ case SEQ_LZMA_PREPARE:
+ if (s->lzma2.compressed < RC_INIT_BYTES)
+ return XZ_DATA_ERROR;
+
+ if (!rc_read_init(&s->rc, b))
+ return XZ_OK;
+
+ s->lzma2.compressed -= RC_INIT_BYTES;
+ s->lzma2.sequence = SEQ_LZMA_RUN;
+
+ case SEQ_LZMA_RUN:
+ /*
+ * Set dictionary limit to indicate how much we want
+ * to be encoded at maximum. Decode new data into the
+ * dictionary. Flush the new data from dictionary to
+ * b->out. Check if we finished decoding this chunk.
+ * In case the dictionary got full but we didn't fill
+ * the output buffer yet, we may run this loop
+ * multiple times without changing s->lzma2.sequence.
+ */
+ dict_limit(&s->dict, min_t(size_t,
+ b->out_size - b->out_pos,
+ s->lzma2.uncompressed));
+ if (!lzma2_lzma(s, b))
+ return XZ_DATA_ERROR;
+
+ s->lzma2.uncompressed -= dict_flush(&s->dict, b);
+
+ if (s->lzma2.uncompressed == 0) {
+ if (s->lzma2.compressed > 0 || s->lzma.len > 0
+ || !rc_is_finished(&s->rc))
+ return XZ_DATA_ERROR;
+
+ rc_reset(&s->rc);
+ s->lzma2.sequence = SEQ_CONTROL;
+
+ } else if (b->out_pos == b->out_size
+ || (b->in_pos == b->in_size
+ && s->temp.size
+ < s->lzma2.compressed)) {
+ return XZ_OK;
+ }
+
+ break;
+
+ case SEQ_COPY:
+ dict_uncompressed(&s->dict, b, &s->lzma2.compressed);
+ if (s->lzma2.compressed > 0)
+ return XZ_OK;
+
+ s->lzma2.sequence = SEQ_CONTROL;
+ break;
+ }
+ }
+
+ return XZ_OK;
+}
+
+XZ_EXTERN struct xz_dec_lzma2 * XZ_FUNC xz_dec_lzma2_create(
+ enum xz_mode mode, uint32_t dict_max)
+{
+ struct xz_dec_lzma2 *s = kmalloc(sizeof(*s), GFP_KERNEL);
+ if (s == NULL)
+ return NULL;
+
+ s->dict.mode = mode;
+ s->dict.size_max = dict_max;
+
+ if (DEC_IS_PREALLOC(mode)) {
+ s->dict.buf = vmalloc(dict_max);
+ if (s->dict.buf == NULL) {
+ kfree(s);
+ return NULL;
+ }
+ } else if (DEC_IS_DYNALLOC(mode)) {
+ s->dict.buf = NULL;
+ s->dict.allocated = 0;
+ }
+
+ return s;
+}
+
+XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_lzma2_reset(
+ struct xz_dec_lzma2 *s, uint8_t props)
+{
+ /* This limits dictionary size to 3 GiB to keep parsing simpler. */
+ if (props > 39)
+ return XZ_OPTIONS_ERROR;
+
+ s->dict.size = 2 + (props & 1);
+ s->dict.size <<= (props >> 1) + 11;
+
+ if (DEC_IS_MULTI(s->dict.mode)) {
+ if (s->dict.size > s->dict.size_max)
+ return XZ_MEMLIMIT_ERROR;
+
+ s->dict.end = s->dict.size;
+
+ if (DEC_IS_DYNALLOC(s->dict.mode)) {
+ if (s->dict.allocated < s->dict.size) {
+ vfree(s->dict.buf);
+ s->dict.buf = vmalloc(s->dict.size);
+ if (s->dict.buf == NULL) {
+ s->dict.allocated = 0;
+ return XZ_MEM_ERROR;
+ }
+ }
+ }
+ }
+
+ s->lzma.len = 0;
+
+ s->lzma2.sequence = SEQ_CONTROL;
+ s->lzma2.need_dict_reset = true;
+
+ s->temp.size = 0;
+
+ return XZ_OK;
+}
+
+XZ_EXTERN void XZ_FUNC xz_dec_lzma2_end(struct xz_dec_lzma2 *s)
+{
+ if (DEC_IS_MULTI(s->dict.mode))
+ vfree(s->dict.buf);
+
+ kfree(s);
+}
diff --git a/archival/libunarchive/unxz/xz_dec_stream.c b/archival/libunarchive/unxz/xz_dec_stream.c
new file mode 100644
index 000000000..bdcbf1ba3
--- /dev/null
+++ b/archival/libunarchive/unxz/xz_dec_stream.c
@@ -0,0 +1,822 @@
+/*
+ * .xz Stream decoder
+ *
+ * Author: Lasse Collin <lasse.collin@tukaani.org>
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ */
+
+#include "xz_private.h"
+#include "xz_stream.h"
+
+/* Hash used to validate the Index field */
+struct xz_dec_hash {
+ vli_type unpadded;
+ vli_type uncompressed;
+ uint32_t crc32;
+};
+
+struct xz_dec {
+ /* Position in dec_main() */
+ enum {
+ SEQ_STREAM_HEADER,
+ SEQ_BLOCK_START,
+ SEQ_BLOCK_HEADER,
+ SEQ_BLOCK_UNCOMPRESS,
+ SEQ_BLOCK_PADDING,
+ SEQ_BLOCK_CHECK,
+ SEQ_INDEX,
+ SEQ_INDEX_PADDING,
+ SEQ_INDEX_CRC32,
+ SEQ_STREAM_FOOTER
+ } sequence;
+
+ /* Position in variable-length integers and Check fields */
+ uint32_t pos;
+
+ /* Variable-length integer decoded by dec_vli() */
+ vli_type vli;
+
+ /* Saved in_pos and out_pos */
+ size_t in_start;
+ size_t out_start;
+
+ /* CRC32 value in Block or Index */
+ uint32_t crc32;
+
+ /* Type of the integrity check calculated from uncompressed data */
+ enum xz_check check_type;
+
+ /* Operation mode */
+ enum xz_mode mode;
+
+ /*
+ * True if the next call to xz_dec_run() is allowed to return
+ * XZ_BUF_ERROR.
+ */
+ bool allow_buf_error;
+
+ /* Information stored in Block Header */
+ struct {
+ /*
+ * Value stored in the Compressed Size field, or
+ * VLI_UNKNOWN if Compressed Size is not present.
+ */
+ vli_type compressed;
+
+ /*
+ * Value stored in the Uncompressed Size field, or
+ * VLI_UNKNOWN if Uncompressed Size is not present.
+ */
+ vli_type uncompressed;
+
+ /* Size of the Block Header field */
+ uint32_t size;
+ } block_header;
+
+ /* Information collected when decoding Blocks */
+ struct {
+ /* Observed compressed size of the current Block */
+ vli_type compressed;
+
+ /* Observed uncompressed size of the current Block */
+ vli_type uncompressed;
+
+ /* Number of Blocks decoded so far */
+ vli_type count;
+
+ /*
+ * Hash calculated from the Block sizes. This is used to
+ * validate the Index field.
+ */
+ struct xz_dec_hash hash;
+ } block;
+
+ /* Variables needed when verifying the Index field */
+ struct {
+ /* Position in dec_index() */
+ enum {
+ SEQ_INDEX_COUNT,
+ SEQ_INDEX_UNPADDED,
+ SEQ_INDEX_UNCOMPRESSED
+ } sequence;
+
+ /* Size of the Index in bytes */
+ vli_type size;
+
+ /* Number of Records (matches block.count in valid files) */
+ vli_type count;
+
+ /*
+ * Hash calculated from the Records (matches block.hash in
+ * valid files).
+ */
+ struct xz_dec_hash hash;
+ } index;
+
+ /*
+ * Temporary buffer needed to hold Stream Header, Block Header,
+ * and Stream Footer. The Block Header is the biggest (1 KiB)
+ * so we reserve space according to that. buf[] has to be aligned
+ * to a multiple of four bytes; the size_t variables before it
+ * should guarantee this.
+ */
+ struct {
+ size_t pos;
+ size_t size;
+ uint8_t buf[1024];
+ } temp;
+
+ struct xz_dec_lzma2 *lzma2;
+
+#ifdef XZ_DEC_BCJ
+ struct xz_dec_bcj *bcj;
+ bool bcj_active;
+#endif
+};
+
+#ifdef XZ_DEC_ANY_CHECK
+/* Sizes of the Check field with different Check IDs */
+static const uint8_t check_sizes[16] = {
+ 0,
+ 4, 4, 4,
+ 8, 8, 8,
+ 16, 16, 16,
+ 32, 32, 32,
+ 64, 64, 64
+};
+#endif
+
+/*
+ * Fill s->temp by copying data starting from b->in[b->in_pos]. Caller
+ * must have set s->temp.pos to indicate how much data we are supposed
+ * to copy into s->temp.buf. Return true once s->temp.pos has reached
+ * s->temp.size.
+ */
+static bool XZ_FUNC fill_temp(struct xz_dec *s, struct xz_buf *b)
+{
+ size_t copy_size = min_t(size_t,
+ b->in_size - b->in_pos, s->temp.size - s->temp.pos);
+
+ memcpy(s->temp.buf + s->temp.pos, b->in + b->in_pos, copy_size);
+ b->in_pos += copy_size;
+ s->temp.pos += copy_size;
+
+ if (s->temp.pos == s->temp.size) {
+ s->temp.pos = 0;
+ return true;
+ }
+
+ return false;
+}
+
+/* Decode a variable-length integer (little-endian base-128 encoding) */
+static enum xz_ret XZ_FUNC dec_vli(struct xz_dec *s,
+ const uint8_t *in, size_t *in_pos, size_t in_size)
+{
+ uint8_t byte;
+
+ if (s->pos == 0)
+ s->vli = 0;
+
+ while (*in_pos < in_size) {
+ byte = in[*in_pos];
+ ++*in_pos;
+
+ s->vli |= (vli_type)(byte & 0x7F) << s->pos;
+
+ if ((byte & 0x80) == 0) {
+ /* Don't allow non-minimal encodings. */
+ if (byte == 0 && s->pos != 0)
+ return XZ_DATA_ERROR;
+
+ s->pos = 0;
+ return XZ_STREAM_END;
+ }
+
+ s->pos += 7;
+ if (s->pos == 7 * VLI_BYTES_MAX)
+ return XZ_DATA_ERROR;
+ }
+
+ return XZ_OK;
+}
+
+/*
+ * Decode the Compressed Data field from a Block. Update and validate
+ * the observed compressed and uncompressed sizes of the Block so that
+ * they don't exceed the values possibly stored in the Block Header
+ * (validation assumes that no integer overflow occurs, since vli_type
+ * is normally uint64_t). Update the CRC32 if presence of the CRC32
+ * field was indicated in Stream Header.
+ *
+ * Once the decoding is finished, validate that the observed sizes match
+ * the sizes possibly stored in the Block Header. Update the hash and
+ * Block count, which are later used to validate the Index field.
+ */
+static enum xz_ret XZ_FUNC dec_block(struct xz_dec *s, struct xz_buf *b)
+{
+ enum xz_ret ret;
+
+ s->in_start = b->in_pos;
+ s->out_start = b->out_pos;
+
+#ifdef XZ_DEC_BCJ
+ if (s->bcj_active)
+ ret = xz_dec_bcj_run(s->bcj, s->lzma2, b);
+ else
+#endif
+ ret = xz_dec_lzma2_run(s->lzma2, b);
+
+ s->block.compressed += b->in_pos - s->in_start;
+ s->block.uncompressed += b->out_pos - s->out_start;
+
+ /*
+ * There is no need to separately check for VLI_UNKNOWN, since
+ * the observed sizes are always smaller than VLI_UNKNOWN.
+ */
+ if (s->block.compressed > s->block_header.compressed
+ || s->block.uncompressed
+ > s->block_header.uncompressed)
+ return XZ_DATA_ERROR;
+
+ if (s->check_type == XZ_CHECK_CRC32)
+ s->crc32 = xz_crc32(b->out + s->out_start,
+ b->out_pos - s->out_start, s->crc32);
+
+ if (ret == XZ_STREAM_END) {
+ if (s->block_header.compressed != VLI_UNKNOWN
+ && s->block_header.compressed
+ != s->block.compressed)
+ return XZ_DATA_ERROR;
+
+ if (s->block_header.uncompressed != VLI_UNKNOWN
+ && s->block_header.uncompressed
+ != s->block.uncompressed)
+ return XZ_DATA_ERROR;
+
+ s->block.hash.unpadded += s->block_header.size
+ + s->block.compressed;
+
+#ifdef XZ_DEC_ANY_CHECK
+ s->block.hash.unpadded += check_sizes[s->check_type];
+#else
+ if (s->check_type == XZ_CHECK_CRC32)
+ s->block.hash.unpadded += 4;
+#endif
+
+ s->block.hash.uncompressed += s->block.uncompressed;
+ s->block.hash.crc32 = xz_crc32(
+ (const uint8_t *)&s->block.hash,
+ sizeof(s->block.hash), s->block.hash.crc32);
+
+ ++s->block.count;
+ }
+
+ return ret;
+}
+
+/* Update the Index size and the CRC32 value. */
+static void XZ_FUNC index_update(struct xz_dec *s, const struct xz_buf *b)
+{
+ size_t in_used = b->in_pos - s->in_start;
+ s->index.size += in_used;
+ s->crc32 = xz_crc32(b->in + s->in_start, in_used, s->crc32);
+}
+
+/*
+ * Decode the Number of Records, Unpadded Size, and Uncompressed Size
+ * fields from the Index field. That is, Index Padding and CRC32 are not
+ * decoded by this function.
+ *
+ * This can return XZ_OK (more input needed), XZ_STREAM_END (everything
+ * successfully decoded), or XZ_DATA_ERROR (input is corrupt).
+ */
+static enum xz_ret XZ_FUNC dec_index(struct xz_dec *s, struct xz_buf *b)
+{
+ enum xz_ret ret;
+
+ do {
+ ret = dec_vli(s, b->in, &b->in_pos, b->in_size);
+ if (ret != XZ_STREAM_END) {
+ index_update(s, b);
+ return ret;
+ }
+
+ switch (s->index.sequence) {
+ case SEQ_INDEX_COUNT:
+ s->index.count = s->vli;
+
+ /*
+ * Validate that the Number of Records field
+ * indicates the same number of Records as
+ * there were Blocks in the Stream.
+ */
+ if (s->index.count != s->block.count)
+ return XZ_DATA_ERROR;
+
+ s->index.sequence = SEQ_INDEX_UNPADDED;
+ break;
+
+ case SEQ_INDEX_UNPADDED:
+ s->index.hash.unpadded += s->vli;
+ s->index.sequence = SEQ_INDEX_UNCOMPRESSED;
+ break;
+
+ case SEQ_INDEX_UNCOMPRESSED:
+ s->index.hash.uncompressed += s->vli;
+ s->index.hash.crc32 = xz_crc32(
+ (const uint8_t *)&s->index.hash,
+ sizeof(s->index.hash),
+ s->index.hash.crc32);
+ --s->index.count;
+ s->index.sequence = SEQ_INDEX_UNPADDED;
+ break;
+ }
+ } while (s->index.count > 0);
+
+ return XZ_STREAM_END;
+}
+
+/*
+ * Validate that the next four input bytes match the value of s->crc32.
+ * s->pos must be zero when starting to validate the first byte.
+ */
+static enum xz_ret XZ_FUNC crc32_validate(struct xz_dec *s, struct xz_buf *b)
+{
+ do {
+ if (b->in_pos == b->in_size)
+ return XZ_OK;
+
+ if (((s->crc32 >> s->pos) & 0xFF) != b->in[b->in_pos++])
+ return XZ_DATA_ERROR;
+
+ s->pos += 8;
+
+ } while (s->pos < 32);
+
+ s->crc32 = 0;
+ s->pos = 0;
+
+ return XZ_STREAM_END;
+}
+
+#ifdef XZ_DEC_ANY_CHECK
+/*
+ * Skip over the Check field when the Check ID is not supported.
+ * Returns true once the whole Check field has been skipped over.
+ */
+static bool XZ_FUNC check_skip(struct xz_dec *s, struct xz_buf *b)
+{
+ while (s->pos < check_sizes[s->check_type]) {
+ if (b->in_pos == b->in_size)
+ return false;
+
+ ++b->in_pos;
+ ++s->pos;
+ }
+
+ s->pos = 0;
+
+ return true;
+}
+#endif
+
+/* Decode the Stream Header field (the first 12 bytes of the .xz Stream). */
+static enum xz_ret XZ_FUNC dec_stream_header(struct xz_dec *s)
+{
+ if (!memeq(s->temp.buf, HEADER_MAGIC, HEADER_MAGIC_SIZE))
+ return XZ_FORMAT_ERROR;
+
+ if (xz_crc32(s->temp.buf + HEADER_MAGIC_SIZE, 2, 0)
+ != get_le32(s->temp.buf + HEADER_MAGIC_SIZE + 2))
+ return XZ_DATA_ERROR;
+
+ if (s->temp.buf[HEADER_MAGIC_SIZE] != 0)
+ return XZ_OPTIONS_ERROR;
+
+ /*
+ * Of integrity checks, we support only none (Check ID = 0) and
+ * CRC32 (Check ID = 1). However, if XZ_DEC_ANY_CHECK is defined,
+ * we will accept other check types too, but then the check won't
+ * be verified and a warning (XZ_UNSUPPORTED_CHECK) will be given.
+ */
+ s->check_type = s->temp.buf[HEADER_MAGIC_SIZE + 1];
+
+#ifdef XZ_DEC_ANY_CHECK
+ if (s->check_type > XZ_CHECK_MAX)
+ return XZ_OPTIONS_ERROR;
+
+ if (s->check_type > XZ_CHECK_CRC32)
+ return XZ_UNSUPPORTED_CHECK;
+#else
+ if (s->check_type > XZ_CHECK_CRC32)
+ return XZ_OPTIONS_ERROR;
+#endif
+
+ return XZ_OK;
+}
+
+/* Decode the Stream Footer field (the last 12 bytes of the .xz Stream) */
+static enum xz_ret XZ_FUNC dec_stream_footer(struct xz_dec *s)
+{
+ if (!memeq(s->temp.buf + 10, FOOTER_MAGIC, FOOTER_MAGIC_SIZE))
+ return XZ_DATA_ERROR;
+
+ if (xz_crc32(s->temp.buf + 4, 6, 0) != get_le32(s->temp.buf))
+ return XZ_DATA_ERROR;
+
+ /*
+ * Validate Backward Size. Note that we never added the size of the
+ * Index CRC32 field to s->index.size, thus we use s->index.size / 4
+ * instead of s->index.size / 4 - 1.
+ */
+ if ((s->index.size >> 2) != get_le32(s->temp.buf + 4))
+ return XZ_DATA_ERROR;
+
+ if (s->temp.buf[8] != 0 || s->temp.buf[9] != s->check_type)
+ return XZ_DATA_ERROR;
+
+ /*
+ * Use XZ_STREAM_END instead of XZ_OK to be more convenient
+ * for the caller.
+ */
+ return XZ_STREAM_END;
+}
+
+/* Decode the Block Header and initialize the filter chain. */
+static enum xz_ret XZ_FUNC dec_block_header(struct xz_dec *s)
+{
+ enum xz_ret ret;
+
+ /*
+ * Validate the CRC32. We know that the temp buffer is at least
+ * eight bytes so this is safe.
+ */
+ s->temp.size -= 4;
+ if (xz_crc32(s->temp.buf, s->temp.size, 0)
+ != get_le32(s->temp.buf + s->temp.size))
+ return XZ_DATA_ERROR;
+
+ s->temp.pos = 2;
+
+ /*
+ * Catch unsupported Block Flags. We support only one or two filters
+ * in the chain, so we catch that with the same test.
+ */
+#ifdef XZ_DEC_BCJ
+ if (s->temp.buf[1] & 0x3E)
+#else
+ if (s->temp.buf[1] & 0x3F)
+#endif
+ return XZ_OPTIONS_ERROR;
+
+ /* Compressed Size */
+ if (s->temp.buf[1] & 0x40) {
+ if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size)
+ != XZ_STREAM_END)
+ return XZ_DATA_ERROR;
+
+ s->block_header.compressed = s->vli;
+ } else {
+ s->block_header.compressed = VLI_UNKNOWN;
+ }
+
+ /* Uncompressed Size */
+ if (s->temp.buf[1] & 0x80) {
+ if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size)
+ != XZ_STREAM_END)
+ return XZ_DATA_ERROR;
+
+ s->block_header.uncompressed = s->vli;
+ } else {
+ s->block_header.uncompressed = VLI_UNKNOWN;
+ }
+
+#ifdef XZ_DEC_BCJ
+ /* If there are two filters, the first one must be a BCJ filter. */
+ s->bcj_active = s->temp.buf[1] & 0x01;
+ if (s->bcj_active) {
+ if (s->temp.size - s->temp.pos < 2)
+ return XZ_OPTIONS_ERROR;
+
+ ret = xz_dec_bcj_reset(s->bcj, s->temp.buf[s->temp.pos++]);
+ if (ret != XZ_OK)
+ return ret;
+
+ /*
+ * We don't support custom start offset,
+ * so Size of Properties must be zero.
+ */
+ if (s->temp.buf[s->temp.pos++] != 0x00)
+ return XZ_OPTIONS_ERROR;
+ }
+#endif
+
+ /* Valid Filter Flags always take at least two bytes. */
+ if (s->temp.size - s->temp.pos < 2)
+ return XZ_DATA_ERROR;
+
+ /* Filter ID = LZMA2 */
+ if (s->temp.buf[s->temp.pos++] != 0x21)
+ return XZ_OPTIONS_ERROR;
+
+ /* Size of Properties = 1-byte Filter Properties */
+ if (s->temp.buf[s->temp.pos++] != 0x01)
+ return XZ_OPTIONS_ERROR;
+
+ /* Filter Properties contains LZMA2 dictionary size. */
+ if (s->temp.size - s->temp.pos < 1)
+ return XZ_DATA_ERROR;
+
+ ret = xz_dec_lzma2_reset(s->lzma2, s->temp.buf[s->temp.pos++]);
+ if (ret != XZ_OK)
+ return ret;
+
+ /* The rest must be Header Padding. */
+ while (s->temp.pos < s->temp.size)
+ if (s->temp.buf[s->temp.pos++] != 0x00)
+ return XZ_OPTIONS_ERROR;
+
+ s->temp.pos = 0;
+ s->block.compressed = 0;
+ s->block.uncompressed = 0;
+
+ return XZ_OK;
+}
+
+static enum xz_ret XZ_FUNC dec_main(struct xz_dec *s, struct xz_buf *b)
+{
+ enum xz_ret ret;
+
+ /*
+ * Store the start position for the case when we are in the middle
+ * of the Index field.
+ */
+ s->in_start = b->in_pos;
+
+ while (true) {
+ switch (s->sequence) {
+ case SEQ_STREAM_HEADER:
+ /*
+ * Stream Header is copied to s->temp, and then
+ * decoded from there. This way if the caller
+ * gives us only little input at a time, we can
+ * still keep the Stream Header decoding code
+ * simple. Similar approach is used in many places
+ * in this file.
+ */
+ if (!fill_temp(s, b))
+ return XZ_OK;
+
+ /*
+ * If dec_stream_header() returns
+ * XZ_UNSUPPORTED_CHECK, it is still possible
+ * to continue decoding if working in multi-call
+ * mode. Thus, update s->sequence before calling
+ * dec_stream_header().
+ */
+ s->sequence = SEQ_BLOCK_START;
+
+ ret = dec_stream_header(s);
+ if (ret != XZ_OK)
+ return ret;
+
+ case SEQ_BLOCK_START:
+ /* We need one byte of input to continue. */
+ if (b->in_pos == b->in_size)
+ return XZ_OK;
+
+ /* See if this is the beginning of the Index field. */
+ if (b->in[b->in_pos] == 0) {
+ s->in_start = b->in_pos++;
+ s->sequence = SEQ_INDEX;
+ break;
+ }
+
+ /*
+ * Calculate the size of the Block Header and
+ * prepare to decode it.
+ */
+ s->block_header.size
+ = ((uint32_t)b->in[b->in_pos] + 1) * 4;
+
+ s->temp.size = s->block_header.size;
+ s->temp.pos = 0;
+ s->sequence = SEQ_BLOCK_HEADER;
+
+ case SEQ_BLOCK_HEADER:
+ if (!fill_temp(s, b))
+ return XZ_OK;
+
+ ret = dec_block_header(s);
+ if (ret != XZ_OK)
+ return ret;
+
+ s->sequence = SEQ_BLOCK_UNCOMPRESS;
+
+ case SEQ_BLOCK_UNCOMPRESS:
+ ret = dec_block(s, b);
+ if (ret != XZ_STREAM_END)
+ return ret;
+
+ s->sequence = SEQ_BLOCK_PADDING;
+
+ case SEQ_BLOCK_PADDING:
+ /*
+ * Size of Compressed Data + Block Padding
+ * must be a multiple of four. We don't need
+ * s->block.compressed for anything else
+ * anymore, so we use it here to test the size
+ * of the Block Padding field.
+ */
+ while (s->block.compressed & 3) {
+ if (b->in_pos == b->in_size)
+ return XZ_OK;
+
+ if (b->in[b->in_pos++] != 0)
+ return XZ_DATA_ERROR;
+
+ ++s->block.compressed;
+ }
+
+ s->sequence = SEQ_BLOCK_CHECK;
+
+ case SEQ_BLOCK_CHECK:
+ if (s->check_type == XZ_CHECK_CRC32) {
+ ret = crc32_validate(s, b);
+ if (ret != XZ_STREAM_END)
+ return ret;
+ }
+#ifdef XZ_DEC_ANY_CHECK
+ else if (!check_skip(s, b)) {
+ return XZ_OK;
+ }
+#endif
+
+ s->sequence = SEQ_BLOCK_START;
+ break;
+
+ case SEQ_INDEX:
+ ret = dec_index(s, b);
+ if (ret != XZ_STREAM_END)
+ return ret;
+
+ s->sequence = SEQ_INDEX_PADDING;
+
+ case SEQ_INDEX_PADDING:
+ while ((s->index.size + (b->in_pos - s->in_start))
+ & 3) {
+ if (b->in_pos == b->in_size) {
+ index_update(s, b);
+ return XZ_OK;
+ }
+
+ if (b->in[b->in_pos++] != 0)
+ return XZ_DATA_ERROR;
+ }
+
+ /* Finish the CRC32 value and Index size. */
+ index_update(s, b);
+
+ /* Compare the hashes to validate the Index field. */
+ if (!memeq(&s->block.hash, &s->index.hash,
+ sizeof(s->block.hash)))
+ return XZ_DATA_ERROR;
+
+ s->sequence = SEQ_INDEX_CRC32;
+
+ case SEQ_INDEX_CRC32:
+ ret = crc32_validate(s, b);
+ if (ret != XZ_STREAM_END)
+ return ret;
+
+ s->temp.size = STREAM_HEADER_SIZE;
+ s->sequence = SEQ_STREAM_FOOTER;
+
+ case SEQ_STREAM_FOOTER:
+ if (!fill_temp(s, b))
+ return XZ_OK;
+
+ return dec_stream_footer(s);
+ }
+ }
+
+ /* Never reached */
+}
+
+/*
+ * xz_dec_run() is a wrapper for dec_main() to handle some special cases in
+ * multi-call and single-call decoding.
+ *
+ * In multi-call mode, we must return XZ_BUF_ERROR when it seems clear that we
+ * are not going to make any progress anymore. This is to prevent the caller
+ * from calling us infinitely when the input file is truncated or otherwise
+ * corrupt. Since zlib-style API allows that the caller fills the input buffer
+ * only when the decoder doesn't produce any new output, we have to be careful
+ * to avoid returning XZ_BUF_ERROR too easily: XZ_BUF_ERROR is returned only
+ * after the second consecutive call to xz_dec_run() that makes no progress.
+ *
+ * In single-call mode, if we couldn't decode everything and no error
+ * occurred, either the input is truncated or the output buffer is too small.
+ * Since we know that the last input byte never produces any output, we know
+ * that if all the input was consumed and decoding wasn't finished, the file
+ * must be corrupt. Otherwise the output buffer has to be too small or the
+ * file is corrupt in a way that decoding it produces too big output.
+ *
+ * If single-call decoding fails, we reset b->in_pos and b->out_pos back to
+ * their original values. This is because with some filter chains there won't
+ * be any valid uncompressed data in the output buffer unless the decoding
+ * actually succeeds (that's the price to pay of using the output buffer as
+ * the workspace).
+ */
+XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_run(struct xz_dec *s, struct xz_buf *b)
+{
+ size_t in_start;
+ size_t out_start;
+ enum xz_ret ret;
+
+ if (DEC_IS_SINGLE(s->mode))
+ xz_dec_reset(s);
+
+ in_start = b->in_pos;
+ out_start = b->out_pos;
+ ret = dec_main(s, b);
+
+ if (DEC_IS_SINGLE(s->mode)) {
+ if (ret == XZ_OK)
+ ret = b->in_pos == b->in_size
+ ? XZ_DATA_ERROR : XZ_BUF_ERROR;
+
+ if (ret != XZ_STREAM_END) {
+ b->in_pos = in_start;
+ b->out_pos = out_start;
+ }
+
+ } else if (ret == XZ_OK && in_start == b->in_pos
+ && out_start == b->out_pos) {
+ if (s->allow_buf_error)
+ ret = XZ_BUF_ERROR;
+
+ s->allow_buf_error = true;
+ } else {
+ s->allow_buf_error = false;
+ }
+
+ return ret;
+}
+
+XZ_EXTERN struct xz_dec * XZ_FUNC xz_dec_init(
+ enum xz_mode mode, uint32_t dict_max)
+{
+ struct xz_dec *s = kmalloc(sizeof(*s), GFP_KERNEL);
+ if (s == NULL)
+ return NULL;
+
+ s->mode = mode;
+
+#ifdef XZ_DEC_BCJ
+ s->bcj = xz_dec_bcj_create(DEC_IS_SINGLE(mode));
+ if (s->bcj == NULL)
+ goto error_bcj;
+#endif
+
+ s->lzma2 = xz_dec_lzma2_create(mode, dict_max);
+ if (s->lzma2 == NULL)
+ goto error_lzma2;
+
+ xz_dec_reset(s);
+ return s;
+
+error_lzma2:
+#ifdef XZ_DEC_BCJ
+ xz_dec_bcj_end(s->bcj);
+error_bcj:
+#endif
+ kfree(s);
+ return NULL;
+}
+
+XZ_EXTERN void XZ_FUNC xz_dec_reset(struct xz_dec *s)
+{
+ s->sequence = SEQ_STREAM_HEADER;
+ s->allow_buf_error = false;
+ s->pos = 0;
+ s->crc32 = 0;
+ memzero(&s->block, sizeof(s->block));
+ memzero(&s->index, sizeof(s->index));
+ s->temp.pos = 0;
+ s->temp.size = STREAM_HEADER_SIZE;
+}
+
+XZ_EXTERN void XZ_FUNC xz_dec_end(struct xz_dec *s)
+{
+ if (s != NULL) {
+ xz_dec_lzma2_end(s->lzma2);
+#ifdef XZ_DEC_BCJ
+ xz_dec_bcj_end(s->bcj);
+#endif
+ kfree(s);
+ }
+}
diff --git a/archival/libunarchive/unxz/xz_lzma2.h b/archival/libunarchive/unxz/xz_lzma2.h
new file mode 100644