Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/RMerl/asuswrt-merlin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Sauvageau <rmerl@lostrealm.ca>2016-12-18 21:29:44 +0300
committerEric Sauvageau <rmerl@lostrealm.ca>2016-12-18 21:29:44 +0300
commit9b6ef845c754ed272bab3b02bdc09584120a7959 (patch)
treed74629835d904aadbbfa08372419fb24779d44a1
parent0bbf16bea993f42792ee762b74c9f310450d724f (diff)
parent745ce33b05c04252bbb6b1580f252bf2dbd26e0b (diff)
Merge branch 'bb125' - Busybox upgrade to 1.25.1.
-rw-r--r--release/src/router/busybox/.gitignore31
-rw-r--r--release/src/router/busybox/.indent.pro33
-rw-r--r--release/src/router/busybox/Config.in77
-rw-r--r--release/src/router/busybox/Makefile47
-rw-r--r--release/src/router/busybox/Makefile.custom19
-rw-r--r--release/src/router/busybox/Makefile.flags46
-rw-r--r--release/src/router/busybox/Makefile.help4
-rw-r--r--release/src/router/busybox/README2
-rw-r--r--release/src/router/busybox/TODO18
-rw-r--r--release/src/router/busybox/VERSION1
-rw-r--r--release/src/router/busybox/applets/applet_tables.c118
-rwxr-xr-xrelease/src/router/busybox/applets/busybox.mksuid54
-rw-r--r--release/src/router/busybox/applets/individual.c2
-rwxr-xr-xrelease/src/router/busybox/applets/install.sh26
-rwxr-xr-xrelease/src/router/busybox/applets/usage_compressed21
-rw-r--r--release/src/router/busybox/archival/Config.src352
-rw-r--r--release/src/router/busybox/archival/Kbuild.src21
-rw-r--r--release/src/router/busybox/archival/ar.c33
-rw-r--r--release/src/router/busybox/archival/bbunzip.c276
-rw-r--r--release/src/router/busybox/archival/bzip2.c18
-rw-r--r--release/src/router/busybox/archival/cpio.c113
-rw-r--r--release/src/router/busybox/archival/dpkg.c54
-rw-r--r--release/src/router/busybox/archival/dpkg_deb.c33
-rw-r--r--release/src/router/busybox/archival/gzip.c185
-rw-r--r--release/src/router/busybox/archival/libarchive/Kbuild.src44
-rw-r--r--release/src/router/busybox/archival/libarchive/bz/compress.c17
-rw-r--r--release/src/router/busybox/archival/libarchive/common.c9
-rw-r--r--release/src/router/busybox/archival/libarchive/data_extract_all.c121
-rw-r--r--release/src/router/busybox/archival/libarchive/data_extract_to_command.c7
-rw-r--r--release/src/router/busybox/archival/libarchive/decompress_bunzip2.c38
-rw-r--r--release/src/router/busybox/archival/libarchive/decompress_gunzip.c89
-rw-r--r--release/src/router/busybox/archival/libarchive/decompress_uncompress.c47
-rw-r--r--release/src/router/busybox/archival/libarchive/decompress_unlzma.c64
-rw-r--r--release/src/router/busybox/archival/libarchive/decompress_unxz.c55
-rw-r--r--release/src/router/busybox/archival/libarchive/filter_accept_list_reassign.c10
-rw-r--r--release/src/router/busybox/archival/libarchive/filter_accept_reject_list.c8
-rw-r--r--release/src/router/busybox/archival/libarchive/get_header_ar.c35
-rw-r--r--release/src/router/busybox/archival/libarchive/get_header_cpio.c9
-rw-r--r--release/src/router/busybox/archival/libarchive/get_header_tar.c114
-rw-r--r--release/src/router/busybox/archival/libarchive/get_header_tar_bz2.c2
-rw-r--r--release/src/router/busybox/archival/libarchive/get_header_tar_gz.c2
-rw-r--r--release/src/router/busybox/archival/libarchive/get_header_tar_lzma.c2
-rw-r--r--release/src/router/busybox/archival/libarchive/get_header_tar_xz.c21
-rw-r--r--release/src/router/busybox/archival/libarchive/liblzo.h2
-rw-r--r--release/src/router/busybox/archival/libarchive/lzo1x_9x.c16
-rw-r--r--release/src/router/busybox/archival/libarchive/lzo1x_c.c2
-rw-r--r--release/src/router/busybox/archival/libarchive/lzo1x_d.c5
-rw-r--r--release/src/router/busybox/archival/libarchive/open_transformer.c261
-rw-r--r--release/src/router/busybox/archival/libarchive/unpack_ar_archive.c2
-rw-r--r--release/src/router/busybox/archival/libarchive/unsafe_prefix.c36
-rw-r--r--release/src/router/busybox/archival/libarchive/unxz/README6
-rw-r--r--release/src/router/busybox/archival/libarchive/unxz/xz.h17
-rw-r--r--release/src/router/busybox/archival/libarchive/unxz/xz_dec_bcj.c34
-rw-r--r--release/src/router/busybox/archival/libarchive/unxz/xz_dec_lzma2.c10
-rw-r--r--release/src/router/busybox/archival/libarchive/unxz/xz_dec_stream.c2
-rw-r--r--release/src/router/busybox/archival/libarchive/unxz/xz_stream.h11
-rw-r--r--release/src/router/busybox/archival/lzop.c85
-rw-r--r--release/src/router/busybox/archival/rpm.c317
-rw-r--r--release/src/router/busybox/archival/rpm2cpio.c11
-rw-r--r--release/src/router/busybox/archival/tar.c339
-rw-r--r--release/src/router/busybox/archival/unzip.c426
-rw-r--r--release/src/router/busybox/config_base249
-rw-r--r--release/src/router/busybox/configs/TEST_nommu_defconfig3
-rw-r--r--release/src/router/busybox/configs/TEST_noprintf_defconfig3
-rw-r--r--release/src/router/busybox/configs/TEST_rh9_defconfig3
-rw-r--r--release/src/router/busybox/configs/android2_defconfig4
-rw-r--r--release/src/router/busybox/configs/android_502_defconfig1142
-rw-r--r--release/src/router/busybox/configs/android_defconfig4
-rw-r--r--release/src/router/busybox/configs/android_ndk_defconfig209
-rw-r--r--release/src/router/busybox/configs/cygwin_defconfig4
-rw-r--r--release/src/router/busybox/configs/freebsd_defconfig3
-rw-r--r--release/src/router/busybox/console-tools/dumpkmap.c39
-rw-r--r--release/src/router/busybox/console-tools/loadfont.c2
-rw-r--r--release/src/router/busybox/console-tools/loadkmap.c34
-rw-r--r--release/src/router/busybox/console-tools/resize.c6
-rw-r--r--release/src/router/busybox/console-tools/setlogcons.c11
-rw-r--r--release/src/router/busybox/console-tools/showkey.c1
-rw-r--r--release/src/router/busybox/coreutils/Config.src95
-rw-r--r--release/src/router/busybox/coreutils/Kbuild.src4
-rw-r--r--release/src/router/busybox/coreutils/basename.c2
-rw-r--r--release/src/router/busybox/coreutils/cal.c17
-rw-r--r--release/src/router/busybox/coreutils/catv.c56
-rw-r--r--release/src/router/busybox/coreutils/chmod.c4
-rw-r--r--release/src/router/busybox/coreutils/chown.c14
-rw-r--r--release/src/router/busybox/coreutils/cksum.c4
-rw-r--r--release/src/router/busybox/coreutils/cp.c31
-rw-r--r--release/src/router/busybox/coreutils/cut.c2
-rw-r--r--release/src/router/busybox/coreutils/date.c6
-rw-r--r--release/src/router/busybox/coreutils/dd.c309
-rw-r--r--release/src/router/busybox/coreutils/df.c46
-rw-r--r--release/src/router/busybox/coreutils/dos2unix.c20
-rw-r--r--release/src/router/busybox/coreutils/du.c38
-rw-r--r--release/src/router/busybox/coreutils/echo.c2
-rw-r--r--release/src/router/busybox/coreutils/expand.c13
-rw-r--r--release/src/router/busybox/coreutils/expr.c5
-rw-r--r--release/src/router/busybox/coreutils/false.c8
-rw-r--r--release/src/router/busybox/coreutils/head.c157
-rw-r--r--release/src/router/busybox/coreutils/hostid.c3
-rw-r--r--release/src/router/busybox/coreutils/id.c6
-rw-r--r--release/src/router/busybox/coreutils/install.c53
-rw-r--r--release/src/router/busybox/coreutils/libcoreutils/getopt_mk_fifo_nod.c4
-rw-r--r--release/src/router/busybox/coreutils/ln.c29
-rw-r--r--release/src/router/busybox/coreutils/ls.c41
-rw-r--r--release/src/router/busybox/coreutils/md5_sha1_sum.c23
-rw-r--r--release/src/router/busybox/coreutils/mkdir.c13
-rw-r--r--release/src/router/busybox/coreutils/mknod.c2
-rw-r--r--release/src/router/busybox/coreutils/mv.c25
-rw-r--r--release/src/router/busybox/coreutils/od_bloaty.c262
-rw-r--r--release/src/router/busybox/coreutils/printf.c12
-rw-r--r--release/src/router/busybox/coreutils/readlink.c5
-rw-r--r--release/src/router/busybox/coreutils/rm.c3
-rw-r--r--release/src/router/busybox/coreutils/rmdir.c14
-rw-r--r--release/src/router/busybox/coreutils/shuf.c153
-rw-r--r--release/src/router/busybox/coreutils/sort.c102
-rw-r--r--release/src/router/busybox/coreutils/split.c14
-rw-r--r--release/src/router/busybox/coreutils/stat.c161
-rw-r--r--release/src/router/busybox/coreutils/stty.c116
-rw-r--r--release/src/router/busybox/coreutils/sum.c15
-rw-r--r--release/src/router/busybox/coreutils/sync.c78
-rw-r--r--release/src/router/busybox/coreutils/tail.c54
-rw-r--r--release/src/router/busybox/coreutils/tee.c4
-rw-r--r--release/src/router/busybox/coreutils/test.c82
-rw-r--r--release/src/router/busybox/coreutils/touch.c39
-rw-r--r--release/src/router/busybox/coreutils/tr.c23
-rw-r--r--release/src/router/busybox/coreutils/true.c8
-rw-r--r--release/src/router/busybox/coreutils/truncate.c87
-rw-r--r--release/src/router/busybox/coreutils/uname.c14
-rw-r--r--release/src/router/busybox/coreutils/uniq.c2
-rw-r--r--release/src/router/busybox/coreutils/unlink.c34
-rw-r--r--release/src/router/busybox/coreutils/uudecode.c19
-rw-r--r--release/src/router/busybox/coreutils/who.c10
-rw-r--r--release/src/router/busybox/debianutils/Config.src75
-rw-r--r--release/src/router/busybox/debianutils/Kbuild.src5
-rw-r--r--release/src/router/busybox/debianutils/mktemp.c49
-rw-r--r--release/src/router/busybox/debianutils/pipe_progress.c9
-rw-r--r--release/src/router/busybox/debianutils/run_parts.c104
-rw-r--r--release/src/router/busybox/debianutils/start_stop_daemon.c40
-rw-r--r--release/src/router/busybox/debianutils/which.c95
-rw-r--r--release/src/router/busybox/docs/.gitignore1
-rw-r--r--release/src/router/busybox/docs/cgi/env.html2
-rw-r--r--release/src/router/busybox/docs/ifupdown_design.txt2
-rw-r--r--release/src/router/busybox/docs/keep_data_small.txt25
-rw-r--r--release/src/router/busybox/docs/logging_and_backgrounding.txt2
-rw-r--r--release/src/router/busybox/docs/mdev.txt4
-rw-r--r--release/src/router/busybox/docs/new-applet-HOWTO.txt104
-rw-r--r--release/src/router/busybox/docs/posix_conformance.txt1
-rw-r--r--release/src/router/busybox/docs/tcp.txt93
-rw-r--r--release/src/router/busybox/docs/unit-tests.txt50
-rw-r--r--release/src/router/busybox/e2fsprogs/Config.src85
-rw-r--r--release/src/router/busybox/e2fsprogs/Kbuild.src9
-rw-r--r--release/src/router/busybox/e2fsprogs/README13
-rw-r--r--release/src/router/busybox/e2fsprogs/blkid/Kbuild.src26
-rw-r--r--release/src/router/busybox/e2fsprogs/blkid/blkid.h104
-rw-r--r--release/src/router/busybox/e2fsprogs/blkid/blkidP.h186
-rw-r--r--release/src/router/busybox/e2fsprogs/blkid/blkid_getsize.c179
-rw-r--r--release/src/router/busybox/e2fsprogs/blkid/cache.c125
-rw-r--r--release/src/router/busybox/e2fsprogs/blkid/dev.c213
-rw-r--r--release/src/router/busybox/e2fsprogs/blkid/devname.c367
-rw-r--r--release/src/router/busybox/e2fsprogs/blkid/devno.c222
-rw-r--r--release/src/router/busybox/e2fsprogs/blkid/list.c110
-rw-r--r--release/src/router/busybox/e2fsprogs/blkid/list.h73
-rw-r--r--release/src/router/busybox/e2fsprogs/blkid/probe.c726
-rw-r--r--release/src/router/busybox/e2fsprogs/blkid/probe.h374
-rw-r--r--release/src/router/busybox/e2fsprogs/blkid/read.c459
-rw-r--r--release/src/router/busybox/e2fsprogs/blkid/resolve.c139
-rw-r--r--release/src/router/busybox/e2fsprogs/blkid/save.c189
-rw-r--r--release/src/router/busybox/e2fsprogs/blkid/tag.c431
-rw-r--r--release/src/router/busybox/e2fsprogs/chattr.c245
-rw-r--r--release/src/router/busybox/e2fsprogs/e2fs_lib.c4
-rw-r--r--release/src/router/busybox/e2fsprogs/e2fs_lib.h5
-rw-r--r--release/src/router/busybox/e2fsprogs/e2fsbb.h43
-rw-r--r--release/src/router/busybox/e2fsprogs/e2fsck.c13521
-rw-r--r--release/src/router/busybox/e2fsprogs/e2fsck.h637
-rw-r--r--release/src/router/busybox/e2fsprogs/e2p/Kbuild.src18
-rw-r--r--release/src/router/busybox/e2fsprogs/e2p/e2p.h41
-rw-r--r--release/src/router/busybox/e2fsprogs/e2p/feature.c187
-rw-r--r--release/src/router/busybox/e2fsprogs/e2p/fgetsetflags.c70
-rw-r--r--release/src/router/busybox/e2fsprogs/e2p/fgetsetversion.c70
-rw-r--r--release/src/router/busybox/e2fsprogs/e2p/hashstr.c70
-rw-r--r--release/src/router/busybox/e2fsprogs/e2p/iod.c52
-rw-r--r--release/src/router/busybox/e2fsprogs/e2p/ls.c274
-rw-r--r--release/src/router/busybox/e2fsprogs/e2p/mntopts.c134
-rw-r--r--release/src/router/busybox/e2fsprogs/e2p/ostype.c72
-rw-r--r--release/src/router/busybox/e2fsprogs/e2p/parse_num.c65
-rw-r--r--release/src/router/busybox/e2fsprogs/e2p/pe.c32
-rw-r--r--release/src/router/busybox/e2fsprogs/e2p/pf.c74
-rw-r--r--release/src/router/busybox/e2fsprogs/e2p/ps.c27
-rw-r--r--release/src/router/busybox/e2fsprogs/e2p/uuid.c78
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/Kbuild.src26
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/alloc.c173
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/alloc_sb.c58
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/alloc_stats.c53
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/alloc_tables.c114
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/badblocks.c328
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/bb_compat.c64
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/bb_inode.c262
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/bitmaps.c211
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/bitops.c91
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/bitops.h105
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/block.c437
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/bmap.c261
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/bmove.c155
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/brel.h86
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/brel_ma.c196
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/check_desc.c69
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/closefs.c380
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/cmp_bitmaps.c72
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/dblist.c260
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/dblist_dir.c76
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/dir_iterate.c219
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/dirblock.c132
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/dirhash.c234
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/dupfs.c95
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/e2image.h39
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/expanddir.c127
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/ext2_err.h116
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/ext2_ext_attr.h52
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/ext2_fs.h569
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/ext2_io.h112
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/ext2_types.h2
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/ext2fs.h926
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/ext2fsP.h87
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/ext2fs_inline.c365
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/ext_attr.c101
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/fileio.c377
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/finddev.c199
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/flushb.c83
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/freefs.c127
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/gen_bitmap.c49
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/get_pathname.c156
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/getsectsize.c58
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/getsize.c292
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/icount.c467
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/imager.c377
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/ind_block.c69
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/initialize.c388
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/inline.c32
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/inode.c766
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/inode_io.c270
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/io_manager.c70
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/irel.h115
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/irel_ma.c367
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/ismounted.c356
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/jfs_dat.h63
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/kernel-jbd.h235
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/kernel-list.h113
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/link.c135
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/lookup.c68
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/mkdir.c139
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/mkjournal.c426
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/namei.c204
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/newdir.c72
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/openfs.c330
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/read_bb.c96
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/read_bb_file.c96
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/res_gdt.c220
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/rs_bitmap.c106
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/rw_bitmaps.c294
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/sparse.c79
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/swapfs.c234
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/test_io.c380
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/unix_io.c703
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/unlink.c99
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/valid_blk.c57
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/version.c51
-rw-r--r--release/src/router/busybox/e2fsprogs/ext2fs/write_bb_file.c35
-rw-r--r--release/src/router/busybox/e2fsprogs/fsck.c1564
-rw-r--r--release/src/router/busybox/e2fsprogs/fsck.h16
-rw-r--r--release/src/router/busybox/e2fsprogs/lsattr.c145
-rw-r--r--release/src/router/busybox/e2fsprogs/mke2fs.c1370
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/Config.src64
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/Kbuild.src18
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/README3
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/Kbuild.src26
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/blkid.h104
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/blkidP.h186
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/blkid_getsize.c179
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/cache.c125
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/dev.c213
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/devname.c367
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/devno.c222
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/list.c110
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/list.h73
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/probe.c726
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/probe.h374
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/read.c459
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/resolve.c139
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/save.c189
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/tag.c431
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/chattr.c220
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2fsbb.h43
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2fsck.c13521
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2fsck.h637
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/Kbuild.src18
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/e2p.h41
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/feature.c187
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/fgetsetflags.c70
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/fgetsetversion.c70
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/hashstr.c70
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/iod.c52
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/ls.c274
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/mntopts.c134
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/ostype.c72
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/parse_num.c65
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/pe.c32
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/pf.c74
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/ps.c27
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/uuid.c78
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/Kbuild.src26
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/alloc.c173
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/alloc_sb.c58
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/alloc_stats.c53
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/alloc_tables.c114
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/badblocks.c328
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bb_compat.c64
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bb_inode.c262
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bitmaps.c211
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bitops.c91
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bitops.h105
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/block.c437
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bmap.c261
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bmove.c155
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/brel.h86
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/brel_ma.c196
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/check_desc.c69
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/closefs.c380
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/cmp_bitmaps.c72
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dblist.c260
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dblist_dir.c76
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dir_iterate.c219
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dirblock.c132
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dirhash.c234
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dupfs.c95
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/e2image.h39
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/expanddir.c127
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_err.h116
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_ext_attr.h52
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_fs.h569
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_io.h112
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_types.h2
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs.h926
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2fsP.h87
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs_inline.c365
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext_attr.c101
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/fileio.c377
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/finddev.c199
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/flushb.c83
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/freefs.c127
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/gen_bitmap.c49
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/get_pathname.c156
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/getsectsize.c58
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/getsize.c292
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/icount.c467
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/imager.c377
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ind_block.c69
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/initialize.c388
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/inline.c32
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/inode.c766
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/inode_io.c270
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/io_manager.c70
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/irel.h115
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/irel_ma.c367
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ismounted.c356
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/jfs_dat.h63
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/kernel-jbd.h235
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/kernel-list.h113
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/link.c135
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/lookup.c68
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/mkdir.c139
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/mkjournal.c426
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/namei.c204
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/newdir.c72
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/openfs.c330
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/read_bb.c96
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/read_bb_file.c96
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/res_gdt.c220
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/rs_bitmap.c106
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/rw_bitmaps.c294
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/sparse.c79
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/swapfs.c234
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/test_io.c380
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/unix_io.c703
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/unlink.c99
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/valid_blk.c57
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/version.c51
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/write_bb_file.c35
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/fsck.c1376
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/fsck.h16
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/lsattr.c129
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/mke2fs.c1370
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/tune2fs.c727
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/util.c264
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/util.h22
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/Kbuild.src16
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/compare.c55
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/gen_uuid.c304
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/pack.c69
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/parse.c80
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/unpack.c63
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/unparse.c77
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/uuid.h103
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/uuidP.h60
-rw-r--r--release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/uuid_time.c161
-rw-r--r--release/src/router/busybox/e2fsprogs/tune2fs.c780
-rw-r--r--release/src/router/busybox/e2fsprogs/util.c264
-rw-r--r--release/src/router/busybox/e2fsprogs/util.h22
-rw-r--r--release/src/router/busybox/e2fsprogs/uuid/Kbuild.src16
-rw-r--r--release/src/router/busybox/e2fsprogs/uuid/compare.c55
-rw-r--r--release/src/router/busybox/e2fsprogs/uuid/gen_uuid.c304
-rw-r--r--release/src/router/busybox/e2fsprogs/uuid/pack.c69
-rw-r--r--release/src/router/busybox/e2fsprogs/uuid/parse.c80
-rw-r--r--release/src/router/busybox/e2fsprogs/uuid/unpack.c63
-rw-r--r--release/src/router/busybox/e2fsprogs/uuid/unparse.c77
-rw-r--r--release/src/router/busybox/e2fsprogs/uuid/uuid.h103
-rw-r--r--release/src/router/busybox/e2fsprogs/uuid/uuidP.h60
-rw-r--r--release/src/router/busybox/e2fsprogs/uuid/uuid_time.c161
-rw-r--r--release/src/router/busybox/editors/Config.src60
-rw-r--r--release/src/router/busybox/editors/Kbuild.src5
-rw-r--r--release/src/router/busybox/editors/awk.c305
-rw-r--r--release/src/router/busybox/editors/cmp.c11
-rw-r--r--release/src/router/busybox/editors/diff.c44
-rw-r--r--release/src/router/busybox/editors/ed.c21
-rw-r--r--release/src/router/busybox/editors/patch.c25
-rw-r--r--release/src/router/busybox/editors/patch_bbox.c4
-rw-r--r--release/src/router/busybox/editors/sed.c453
-rw-r--r--release/src/router/busybox/editors/vi.c1224
-rwxr-xr-xrelease/src/router/busybox/examples/android-build2
-rwxr-xr-xrelease/src/router/busybox/examples/depmod.pl4
-rw-r--r--release/src/router/busybox/examples/inittab8
-rw-r--r--release/src/router/busybox/examples/mdev.conf10
-rwxr-xr-xrelease/src/router/busybox/examples/mdev.conf.change_blockdev.sh29
-rw-r--r--release/src/router/busybox/examples/mdev_fat.conf50
-rwxr-xr-xrelease/src/router/busybox/examples/udhcp/sample.bound18
-rwxr-xr-xrelease/src/router/busybox/examples/udhcp/sample.renew18
-rwxr-xr-xrelease/src/router/busybox/examples/udhcp/simple.script15
-rwxr-xr-xrelease/src/router/busybox/examples/undeb74
-rwxr-xr-xrelease/src/router/busybox/examples/unrpm65
-rw-r--r--release/src/router/busybox/examples/var_service/README21
-rw-r--r--release/src/router/busybox/examples/var_service/dhcp_if/README5
-rwxr-xr-xrelease/src/router/busybox/examples/var_service/dhcp_if/convert2ntpconf2
-rwxr-xr-xrelease/src/router/busybox/examples/var_service/dhcp_if/dhcp_handler13
-rwxr-xr-xrelease/src/router/busybox/examples/var_service/dhcp_if/finish17
-rwxr-xr-xrelease/src/router/busybox/examples/var_service/dhcp_if/log/run2
-rw-r--r--release/src/router/busybox/examples/var_service/dhcp_if_pinger/README5
-rwxr-xr-xrelease/src/router/busybox/examples/var_service/dhcp_if_pinger/run44
-rw-r--r--release/src/router/busybox/examples/var_service/ftpd/README5
-rwxr-xr-xrelease/src/router/busybox/examples/var_service/ftpd/log/run2
-rw-r--r--release/src/router/busybox/examples/var_service/fw/README5
-rwxr-xr-xrelease/src/router/busybox/examples/var_service/fw/run2
-rw-r--r--release/src/router/busybox/examples/var_service/getty_tty1/README5
-rw-r--r--release/src/router/busybox/examples/var_service/gpm/README5
-rw-r--r--release/src/router/busybox/examples/var_service/httpd/README5
-rwxr-xr-xrelease/src/router/busybox/examples/var_service/httpd/log/run2
-rw-r--r--release/src/router/busybox/examples/var_service/ifplugd_if/README5
-rwxr-xr-xrelease/src/router/busybox/examples/var_service/ifplugd_if/log/run2
-rwxr-xr-xrelease/src/router/busybox/examples/var_service/ifplugd_if/run3
-rw-r--r--release/src/router/busybox/examples/var_service/inetd/README5
-rwxr-xr-xrelease/src/router/busybox/examples/var_service/inetd/log/run2
-rw-r--r--release/src/router/busybox/examples/var_service/nmeter/README5
-rw-r--r--release/src/router/busybox/examples/var_service/ntpd/README5
-rwxr-xr-xrelease/src/router/busybox/examples/var_service/ntpd/log/run2
-rwxr-xr-xrelease/src/router/busybox/examples/var_service/ntpd/ntp.script21
-rwxr-xr-xrelease/src/router/busybox/examples/var_service/ntpd/run2
-rw-r--r--release/src/router/busybox/examples/var_service/tftpd/README5
-rwxr-xr-xrelease/src/router/busybox/examples/var_service/tftpd/log/run2
-rw-r--r--release/src/router/busybox/examples/var_service/zcip_if/README5
-rwxr-xr-xrelease/src/router/busybox/examples/var_service/zcip_if/convert2ipconf24
-rwxr-xr-xrelease/src/router/busybox/examples/var_service/zcip_if/finish13
-rwxr-xr-xrelease/src/router/busybox/examples/var_service/zcip_if/log/run21
-rwxr-xr-xrelease/src/router/busybox/examples/var_service/zcip_if/p_log4
-rwxr-xr-xrelease/src/router/busybox/examples/var_service/zcip_if/run20
-rwxr-xr-xrelease/src/router/busybox/examples/var_service/zcip_if/w_log4
-rwxr-xr-xrelease/src/router/busybox/examples/var_service/zcip_if/zcip_handler47
-rw-r--r--release/src/router/busybox/findutils/.gitignore3
-rw-r--r--release/src/router/busybox/findutils/find.c345
-rw-r--r--release/src/router/busybox/findutils/grep.c111
-rw-r--r--release/src/router/busybox/findutils/xargs.c190
-rw-r--r--release/src/router/busybox/include/.gitignore1
-rw-r--r--release/src/router/busybox/include/applets.src.h176
-rw-r--r--release/src/router/busybox/include/bb_archive.h69
-rw-r--r--release/src/router/busybox/include/bb_e2fs_defs.h45
-rw-r--r--release/src/router/busybox/include/busybox.h19
-rw-r--r--release/src/router/busybox/include/grp_.h67
-rw-r--r--release/src/router/busybox/include/libbb.h420
-rw-r--r--release/src/router/busybox/include/liblzo_interface.h2
-rw-r--r--release/src/router/busybox/include/platform.h117
-rw-r--r--release/src/router/busybox/include/pwd_.h61
-rw-r--r--release/src/router/busybox/include/shadow_.h40
-rw-r--r--release/src/router/busybox/include/usage.src.h24
-rw-r--r--release/src/router/busybox/include/volume_id.h10
-rw-r--r--release/src/router/busybox/init/bootchartd.c13
-rw-r--r--release/src/router/busybox/init/halt.c6
-rw-r--r--release/src/router/busybox/init/init.c233
-rw-r--r--release/src/router/busybox/libbb/Config.src18
-rw-r--r--release/src/router/busybox/libbb/Kbuild.src15
-rw-r--r--release/src/router/busybox/libbb/appletlib.c267
-rw-r--r--release/src/router/busybox/libbb/auto_string.c23
-rw-r--r--release/src/router/busybox/libbb/bb_askpass.c15
-rw-r--r--release/src/router/busybox/libbb/bb_strtonum.c15
-rw-r--r--release/src/router/busybox/libbb/bbunit.c65
-rw-r--r--release/src/router/busybox/libbb/change_identity.c23
-rw-r--r--release/src/router/busybox/libbb/common_bufsiz.c74
-rw-r--r--release/src/router/busybox/libbb/compare_string_array.c82
-rw-r--r--release/src/router/busybox/libbb/copy_file.c25
-rw-r--r--release/src/router/busybox/libbb/copyfd.c87
-rw-r--r--release/src/router/busybox/libbb/correct_password.c110
-rw-r--r--release/src/router/busybox/libbb/create_icmp6_socket.c38
-rw-r--r--release/src/router/busybox/libbb/create_icmp_socket.c36
-rw-r--r--release/src/router/busybox/libbb/dump.c2
-rw-r--r--release/src/router/busybox/libbb/endofname.c26
-rw-r--r--release/src/router/busybox/libbb/executable.c (renamed from release/src/router/busybox/libbb/execable.c)51
-rw-r--r--release/src/router/busybox/libbb/fclose_nonstdin.c3
-rw-r--r--release/src/router/busybox/libbb/fflush_stdout_and_exit.c13
-rw-r--r--release/src/router/busybox/libbb/get_shell_name.c2
-rw-r--r--release/src/router/busybox/libbb/getpty.c2
-rw-r--r--release/src/router/busybox/libbb/hash_md5.c12
-rw-r--r--release/src/router/busybox/libbb/hash_md5_sha.c601
-rw-r--r--release/src/router/busybox/libbb/human_readable.c26
-rw-r--r--release/src/router/busybox/libbb/in_ether.c58
-rw-r--r--release/src/router/busybox/libbb/inet_common.c91
-rw-r--r--release/src/router/busybox/libbb/info_msg.c62
-rw-r--r--release/src/router/busybox/libbb/inode_hash.c36
-rw-r--r--release/src/router/busybox/libbb/kernel_version.c8
-rw-r--r--release/src/router/busybox/libbb/lineedit.c247
-rw-r--r--release/src/router/busybox/libbb/logenv.c24
-rw-r--r--release/src/router/busybox/libbb/login.c3
-rw-r--r--release/src/router/busybox/libbb/loop.c29
-rw-r--r--release/src/router/busybox/libbb/make_directory.c11
-rw-r--r--release/src/router/busybox/libbb/match_fstype.c7
-rw-r--r--release/src/router/busybox/libbb/messages.c9
-rw-r--r--release/src/router/busybox/libbb/missing_syscalls.c49
-rw-r--r--release/src/router/busybox/libbb/mode_string.c4
-rw-r--r--release/src/router/busybox/libbb/nuke_str.c21
-rw-r--r--release/src/router/busybox/libbb/obscure.c40
-rw-r--r--release/src/router/busybox/libbb/parse_mode.c16
-rw-r--r--release/src/router/busybox/libbb/platform.c37
-rw-r--r--release/src/router/busybox/libbb/printable.c24
-rw-r--r--release/src/router/busybox/libbb/printable_string.c10
-rw-r--r--release/src/router/busybox/libbb/procps.c34
-rw-r--r--release/src/router/busybox/libbb/progress.c20
-rw-r--r--release/src/router/busybox/libbb/pw_encrypt.c21
-rw-r--r--release/src/router/busybox/libbb/pw_encrypt_md5.c2
-rw-r--r--release/src/router/busybox/libbb/read_key.c15
-rw-r--r--release/src/router/busybox/libbb/read_printf.c8
-rw-r--r--release/src/router/busybox/libbb/remove_file.c10
-rw-r--r--release/src/router/busybox/libbb/replace.c45
-rw-r--r--release/src/router/busybox/libbb/rtc.c54
-rw-r--r--release/src/router/busybox/libbb/selinux_common.c2
-rw-r--r--release/src/router/busybox/libbb/setup_environment.c8
-rw-r--r--release/src/router/busybox/libbb/signals.c6
-rw-r--r--release/src/router/busybox/libbb/skip_whitespace.c2
-rw-r--r--release/src/router/busybox/libbb/speed_table.c5
-rw-r--r--release/src/router/busybox/libbb/strrstr.c19
-rw-r--r--release/src/router/busybox/libbb/sysconf.c30
-rw-r--r--release/src/router/busybox/libbb/systemd_support.c62
-rw-r--r--release/src/router/busybox/libbb/time.c63
-rw-r--r--release/src/router/busybox/libbb/u_signal_names.c2
-rw-r--r--release/src/router/busybox/libbb/ubi.c43
-rw-r--r--release/src/router/busybox/libbb/udp_io.c22
-rw-r--r--release/src/router/busybox/libbb/unicode.c38
-rw-r--r--release/src/router/busybox/libbb/update_passwd.c45
-rw-r--r--release/src/router/busybox/libbb/utmp.c58
-rw-r--r--release/src/router/busybox/libbb/verror_msg.c34
-rw-r--r--release/src/router/busybox/libbb/vfork_daemon_rexec.c42
-rw-r--r--release/src/router/busybox/libbb/xatonum.c28
-rw-r--r--release/src/router/busybox/libbb/xatonum_template.c2
-rw-r--r--release/src/router/busybox/libbb/xconnect.c27
-rw-r--r--release/src/router/busybox/libbb/xfunc_die.c26
-rw-r--r--release/src/router/busybox/libbb/xfuncs.c67
-rw-r--r--release/src/router/busybox/libbb/xfuncs_printf.c88
-rw-r--r--release/src/router/busybox/libbb/xreadlink.c14
-rw-r--r--release/src/router/busybox/libpwdgrp/pwd_grp.c1275
-rw-r--r--release/src/router/busybox/libpwdgrp/pwd_grp_internal.c61
-rw-r--r--release/src/router/busybox/libpwdgrp/uidgid_get.c44
-rw-r--r--release/src/router/busybox/loginutils/Config.src237
-rw-r--r--release/src/router/busybox/loginutils/Kbuild.src12
-rw-r--r--release/src/router/busybox/loginutils/add-remove-shell.c17
-rw-r--r--release/src/router/busybox/loginutils/addgroup.c42
-rw-r--r--release/src/router/busybox/loginutils/adduser.c104
-rw-r--r--release/src/router/busybox/loginutils/chpasswd.c51
-rw-r--r--release/src/router/busybox/loginutils/cryptpw.c59
-rw-r--r--release/src/router/busybox/loginutils/deluser.c75
-rw-r--r--release/src/router/busybox/loginutils/getty.c67
-rw-r--r--release/src/router/busybox/loginutils/login.c110
-rw-r--r--release/src/router/busybox/loginutils/passwd.c32
-rw-r--r--release/src/router/busybox/loginutils/su.c37
-rw-r--r--release/src/router/busybox/loginutils/sulogin.c84
-rw-r--r--release/src/router/busybox/loginutils/vlock.c18
-rw-r--r--release/src/router/busybox/mailutils/mail.c2
-rw-r--r--release/src/router/busybox/mailutils/reformime.c1
-rw-r--r--release/src/router/busybox/mailutils/sendmail.c178
-rw-r--r--release/src/router/busybox/miscutils/Config.src99
-rw-r--r--release/src/router/busybox/miscutils/Kbuild.src15
-rw-r--r--release/src/router/busybox/miscutils/adjtimex.c31
-rw-r--r--release/src/router/busybox/miscutils/beep.c2
-rw-r--r--release/src/router/busybox/miscutils/chat.c6
-rw-r--r--release/src/router/busybox/miscutils/chrt.c3
-rw-r--r--release/src/router/busybox/miscutils/conspy.c7
-rw-r--r--release/src/router/busybox/miscutils/crond.c340
-rw-r--r--release/src/router/busybox/miscutils/crontab.c28
-rw-r--r--release/src/router/busybox/miscutils/dc.c85
-rw-r--r--release/src/router/busybox/miscutils/devfsd.c105
-rw-r--r--release/src/router/busybox/miscutils/eject.c28
-rw-r--r--release/src/router/busybox/miscutils/ethreg.c62
-rw-r--r--release/src/router/busybox/miscutils/fbsplash.c43
-rw-r--r--release/src/router/busybox/miscutils/flash_eraseall.c17
-rw-r--r--release/src/router/busybox/miscutils/flashcp.c31
-rw-r--r--release/src/router/busybox/miscutils/hdparm.c83
-rw-r--r--release/src/router/busybox/miscutils/i2c_tools.c1343
-rw-r--r--release/src/router/busybox/miscutils/inotifyd.c10
-rw-r--r--release/src/router/busybox/miscutils/ionice.c2
-rw-r--r--release/src/router/busybox/miscutils/last.c21
-rw-r--r--release/src/router/busybox/miscutils/last_fancy.c41
-rw-r--r--release/src/router/busybox/miscutils/less.c460
-rw-r--r--release/src/router/busybox/miscutils/man.c117
-rw-r--r--release/src/router/busybox/miscutils/mdmm.c43
-rw-r--r--release/src/router/busybox/miscutils/microcom.c6
-rw-r--r--release/src/router/busybox/miscutils/nandwrite.c84
-rw-r--r--release/src/router/busybox/miscutils/rfkill.c17
-rw-r--r--release/src/router/busybox/miscutils/runlevel.c12
-rw-r--r--release/src/router/busybox/miscutils/rx.c4
-rw-r--r--release/src/router/busybox/miscutils/setserial.c12
-rw-r--r--release/src/router/busybox/miscutils/setsid.c33
-rw-r--r--release/src/router/busybox/miscutils/taskset.c127
-rw-r--r--release/src/router/busybox/miscutils/time.c3
-rw-r--r--release/src/router/busybox/miscutils/ubi_tools.c327
-rw-r--r--release/src/router/busybox/miscutils/ubirename.c94
-rw-r--r--release/src/router/busybox/miscutils/wall.c29
-rw-r--r--release/src/router/busybox/miscutils/watchdog.c3
-rw-r--r--release/src/router/busybox/modutils/Config.src3
-rw-r--r--release/src/router/busybox/modutils/depmod.c109
-rw-r--r--release/src/router/busybox/modutils/insmod.c64
-rw-r--r--release/src/router/busybox/modutils/modinfo.c128
-rw-r--r--release/src/router/busybox/modutils/modprobe-small.c386
-rw-r--r--release/src/router/busybox/modutils/modprobe.c156
-rw-r--r--release/src/router/busybox/modutils/modutils-24.c12
-rw-r--r--release/src/router/busybox/modutils/modutils.c70
-rw-r--r--release/src/router/busybox/modutils/modutils.h35
-rw-r--r--release/src/router/busybox/modutils/rmmod.c12
-rw-r--r--release/src/router/busybox/networking/Config.src92
-rw-r--r--release/src/router/busybox/networking/Kbuild.src1
-rw-r--r--release/src/router/busybox/networking/arp.c62
-rw-r--r--release/src/router/busybox/networking/arping.c47
-rw-r--r--release/src/router/busybox/networking/brctl.c80
-rw-r--r--release/src/router/busybox/networking/dnsd.c2
-rw-r--r--release/src/router/busybox/networking/ether-wake.c38
-rw-r--r--release/src/router/busybox/networking/ftpd.c184
-rw-r--r--release/src/router/busybox/networking/ftpgetput.c11
-rw-r--r--release/src/router/busybox/networking/hostname.c7
-rw-r--r--release/src/router/busybox/networking/httpd.c118
-rw-r--r--release/src/router/busybox/networking/httpd_indexcgi.c1
-rw-r--r--release/src/router/busybox/networking/httpd_ssi.c2
-rw-r--r--release/src/router/busybox/networking/ifconfig.c134
-rw-r--r--release/src/router/busybox/networking/ifenslave.c12
-rw-r--r--release/src/router/busybox/networking/ifplugd.c63
-rw-r--r--release/src/router/busybox/networking/ifupdown.c116
-rw-r--r--release/src/router/busybox/networking/inetd.c36
-rw-r--r--release/src/router/busybox/networking/interface.c133
-rw-r--r--release/src/router/busybox/networking/ip.c21
-rw-r--r--release/src/router/busybox/networking/ipcalc.c3
-rw-r--r--release/src/router/busybox/networking/isrv.c4
-rw-r--r--release/src/router/busybox/networking/isrv.h26
-rw-r--r--release/src/router/busybox/networking/isrv_identd.c41
-rw-r--r--release/src/router/busybox/networking/libiproute/Kbuild.src8
-rw-r--r--release/src/router/busybox/networking/libiproute/ip_common.h2
-rw-r--r--release/src/router/busybox/networking/libiproute/ip_parse_common_args.c2
-rw-r--r--release/src/router/busybox/networking/libiproute/ipaddress.c96
-rw-r--r--release/src/router/busybox/networking/libiproute/iplink.c338
-rw-r--r--release/src/router/busybox/networking/libiproute/ipneigh.c357
-rw-r--r--release/src/router/busybox/networking/libiproute/iproute.c148
-rw-r--r--release/src/router/busybox/networking/libiproute/iprule.c52
-rw-r--r--release/src/router/busybox/networking/libiproute/iptunnel.c41
-rw-r--r--release/src/router/busybox/networking/libiproute/libnetlink.c37
-rw-r--r--release/src/router/busybox/networking/libiproute/ll_map.c39
-rw-r--r--release/src/router/busybox/networking/libiproute/ll_map.h2
-rw-r--r--release/src/router/busybox/networking/libiproute/ll_proto.c108
-rw-r--r--release/src/router/busybox/networking/libiproute/ll_types.c4
-rw-r--r--release/src/router/busybox/networking/libiproute/rt_names.c93
-rw-r--r--release/src/router/busybox/networking/libiproute/rt_names.h11
-rw-r--r--release/src/router/busybox/networking/libiproute/rtm_map.c6
-rw-r--r--release/src/router/busybox/networking/libiproute/rtm_map.h2
-rw-r--r--release/src/router/busybox/networking/libiproute/utils.c48
-rw-r--r--release/src/router/busybox/networking/libiproute/utils.h12
-rw-r--r--release/src/router/busybox/networking/nameif.c23
-rw-r--r--release/src/router/busybox/networking/nbd-client.c7
-rw-r--r--release/src/router/busybox/networking/nc.c30
-rw-r--r--release/src/router/busybox/networking/nc_bloaty.c153
-rw-r--r--release/src/router/busybox/networking/netstat.c18
-rw-r--r--release/src/router/busybox/networking/nslookup.c15
-rw-r--r--release/src/router/busybox/networking/ntpd.c808
-rw-r--r--release/src/router/busybox/networking/ntpd.diff24
-rw-r--r--release/src/router/busybox/networking/ntpd_simple.c1007
-rw-r--r--release/src/router/busybox/networking/ping.c253
-rw-r--r--release/src/router/busybox/networking/pscan.c2
-rw-r--r--release/src/router/busybox/networking/route.c68
-rw-r--r--release/src/router/busybox/networking/slattach.c11
-rwxr-xr-xrelease/src/router/busybox/networking/ssl_helper-wolfssl/00cfg-wolfssl-3.6.822
-rw-r--r--release/src/router/busybox/networking/ssl_helper-wolfssl/README20
-rw-r--r--release/src/router/busybox/networking/ssl_helper-wolfssl/ssl_helper.c480
-rwxr-xr-xrelease/src/router/busybox/networking/ssl_helper-wolfssl/ssl_helper.sh12
-rw-r--r--release/src/router/busybox/networking/ssl_helper/README16
-rw-r--r--release/src/router/busybox/networking/ssl_helper/ssl_helper.c406
-rwxr-xr-xrelease/src/router/busybox/networking/ssl_helper/ssl_helper.sh11
-rw-r--r--release/src/router/busybox/networking/tc.c45
-rw-r--r--release/src/router/busybox/networking/tcpudp.c4
-rw-r--r--release/src/router/busybox/networking/telnet.c82
-rw-r--r--release/src/router/busybox/networking/telnetd.c22
-rw-r--r--release/src/router/busybox/networking/telnetd.ctrlSQ.patch4
-rw-r--r--release/src/router/busybox/networking/tftp.c92
-rw-r--r--release/src/router/busybox/networking/traceroute.c145
-rw-r--r--release/src/router/busybox/networking/tunctl.c2
-rw-r--r--release/src/router/busybox/networking/udhcp/Config.src36
-rw-r--r--release/src/router/busybox/networking/udhcp/Kbuild.src7
-rw-r--r--release/src/router/busybox/networking/udhcp/arpping.c2
-rw-r--r--release/src/router/busybox/networking/udhcp/common.c77
-rw-r--r--release/src/router/busybox/networking/udhcp/common.h15
-rw-r--r--release/src/router/busybox/networking/udhcp/d6_dhcpc.c140
-rw-r--r--release/src/router/busybox/networking/udhcp/d6_packet.c12
-rw-r--r--release/src/router/busybox/networking/udhcp/d6_socket.c2
-rw-r--r--release/src/router/busybox/networking/udhcp/dhcpc.c113
-rw-r--r--release/src/router/busybox/networking/udhcp/dhcpc.h6
-rw-r--r--release/src/router/busybox/networking/udhcp/dhcpd.c42
-rw-r--r--release/src/router/busybox/networking/udhcp/dhcpd.h8
-rw-r--r--release/src/router/busybox/networking/udhcp/dhcprelay.c5
-rw-r--r--release/src/router/busybox/networking/udhcp/domain_codec.c21
-rw-r--r--release/src/router/busybox/networking/udhcp/files.c54
-rw-r--r--release/src/router/busybox/networking/udhcp/leases.c8
-rw-r--r--release/src/router/busybox/networking/udhcp/packet.c27
-rw-r--r--release/src/router/busybox/networking/udhcp/socket.c6
-rw-r--r--release/src/router/busybox/networking/udhcp/static_leases.c2
-rw-r--r--release/src/router/busybox/networking/wget.c530
-rw-r--r--release/src/router/busybox/networking/zcip.c551
-rw-r--r--release/src/router/busybox/printutils/Config.src18
-rw-r--r--release/src/router/busybox/printutils/Kbuild.src4
-rw-r--r--release/src/router/busybox/printutils/lpd.c19
-rw-r--r--release/src/router/busybox/printutils/lpr.c53
-rw-r--r--release/src/router/busybox/procps/Config.src54
-rw-r--r--release/src/router/busybox/procps/free.c82
-rw-r--r--release/src/router/busybox/procps/fuser.c4
-rw-r--r--release/src/router/busybox/procps/iostat.c9
-rw-r--r--release/src/router/busybox/procps/kill.c43
-rw-r--r--release/src/router/busybox/procps/lsof.c9
-rw-r--r--release/src/router/busybox/procps/mpstat.c18
-rw-r--r--release/src/router/busybox/procps/nmeter.c213
-rw-r--r--release/src/router/busybox/procps/pgrep.c6
-rw-r--r--release/src/router/busybox/procps/pmap.c4
-rw-r--r--release/src/router/busybox/procps/powertop.c25
-rw-r--r--release/src/router/busybox/procps/ps.c67
-rw-r--r--release/src/router/busybox/procps/pstree.c15
-rw-r--r--release/src/router/busybox/procps/pwdx.c4
-rw-r--r--release/src/router/busybox/procps/renice.c13
-rw-r--r--release/src/router/busybox/procps/sysctl.c37
-rw-r--r--release/src/router/busybox/procps/top.c410
-rw-r--r--release/src/router/busybox/procps/uptime.c6
-rw-r--r--release/src/router/busybox/procps/watch.c14
-rw-r--r--release/src/router/busybox/qemu_multiarch_testing/README63
-rwxr-xr-xrelease/src/router/busybox/qemu_multiarch_testing/extract_od_binary.sh6
-rwxr-xr-xrelease/src/router/busybox/qemu_multiarch_testing/hdc.dir/build50
-rwxr-xr-xrelease/src/router/busybox/qemu_multiarch_testing/hdc.dir/init9
-rwxr-xr-xrelease/src/router/busybox/qemu_multiarch_testing/make-hdc-img.sh30
-rwxr-xr-xrelease/src/router/busybox/qemu_multiarch_testing/parallel-build-hdc-img.sh40
-rw-r--r--release/src/router/busybox/runit/Config.src79
-rw-r--r--release/src/router/busybox/runit/Kbuild.src11
-rw-r--r--release/src/router/busybox/runit/chpst.c54
-rw-r--r--release/src/router/busybox/runit/runsv.c38
-rw-r--r--release/src/router/busybox/runit/runsvdir.c95
-rw-r--r--release/src/router/busybox/runit/sv.c26
-rw-r--r--release/src/router/busybox/runit/svlogd.c32
-rw-r--r--release/src/router/busybox/scripts/Makefile.build3
-rw-r--r--release/src/router/busybox/scripts/basic/docproc.c4
-rw-r--r--release/src/router/busybox/scripts/basic/fixdep.c2
-rwxr-xr-xrelease/src/router/busybox/scripts/bloat-o-meter11
-rwxr-xr-xrelease/src/router/busybox/scripts/gen_build_files.sh16
-rwxr-xr-xrelease/src/router/busybox/scripts/generate_BUFSIZ.sh181
-rw-r--r--release/src/router/busybox/scripts/kconfig/Makefile2
-rw-r--r--release/src/router/busybox/scripts/kconfig/confdata.c27
-rwxr-xr-x[-rw-r--r--]release/src/router/busybox/scripts/kconfig/lxdialog/check-lxdialog.sh17
-rw-r--r--release/src/router/busybox/scripts/kconfig/mconf.c18
-rw-r--r--release/src/router/busybox/scripts/kconfig/util.c3
-rw-r--r--release/src/router/busybox/scripts/kconfig/zconf.hash.c_shipped14
-rwxr-xr-xrelease/src/router/busybox/scripts/mkconfigs4
-rwxr-xr-xrelease/src/router/busybox/scripts/randomtest26
-rwxr-xr-xrelease/src/router/busybox/scripts/trylink87
-rw-r--r--release/src/router/busybox/selinux/Config.src2
-rw-r--r--release/src/router/busybox/selinux/chcon.c20
-rw-r--r--release/src/router/busybox/selinux/runcon.c10
-rw-r--r--release/src/router/busybox/selinux/sestatus.c2
-rw-r--r--release/src/router/busybox/selinux/setfiles.c30
-rw-r--r--release/src/router/busybox/shell/ash.c1165
-rw-r--r--release/src/router/busybox/shell/ash_test/.gitignore7
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-glob/glob1.right2
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-glob/glob1.tests2
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-glob/glob2.right18
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-glob/glob2.tests27
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-glob/glob3.right2
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-glob/glob3.tests2
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-glob/glob_and_assign.right6
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-glob/glob_and_assign.tests10
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-glob/glob_redir.right2
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-glob/glob_redir.tests9
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc1.right1
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-heredoc/heredoc1.tests3
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc2.right2
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-heredoc/heredoc2.tests7
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc3.right1
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-heredoc/heredoc3.tests9
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc4.right1
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-heredoc/heredoc4.tests3
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-misc/command.right1
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-misc/command.tests1
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-misc/command2.right2
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-misc/command2.tests6
-rwxr-xr-x[-rw-r--r--]release/src/router/busybox/shell/ash_test/ash-misc/echo_write_error.tests0
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-misc/exec.right2
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-misc/exec.tests3
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-misc/for.right1
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-misc/for.tests5
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-misc/func1.right6
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-misc/func1.tests16
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-misc/func2.right5
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-misc/func2.tests9
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-misc/func3.right4
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-misc/func3.tests8
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-misc/func4.right2
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-misc/func4.tests7
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-misc/func5.right6
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-misc/func5.tests13
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-misc/func_args1.right5
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-misc/func_args1.tests8
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-misc/func_bash1.right12
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-misc/func_bash1.tests28
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-misc/func_local1.right3
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-misc/func_local1.tests5
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-misc/func_local2.right14
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-misc/func_local2.tests7
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-misc/local1.right4
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-misc/local1.tests11
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-misc/local2.right1
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-misc/local2.tests1
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-misc/tickquote1.right1
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-misc/tickquote1.tests1
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-quoting/dollar_squote_bash1.right1
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-quoting/dollar_squote_bash1.tests1
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-redir/redirA.right2
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-redir/redirA.tests11
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.right2
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.tests3
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.right1
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.tests2
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.right1
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.tests3
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-vars/var-expand-tilde-in-parameter-expansion.right1
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-vars/var-expand-tilde-in-parameter-expansion.tests2
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-1.right1
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-1.tests2
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-2.right1
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-2.tests2
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-3.right1
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-3.tests2
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-4.right1
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-4.tests2
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-5.right1
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-5.tests2
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-vars/var-runtime-quote-detection.right1
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-vars/var-runtime-quote-detection.tests1
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-vars/var-utf8-length.right1
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-vars/var-utf8-length.tests2
-rw-r--r--release/src/router/busybox/shell/ash_test/ash-vars/var3.right5
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/ash-vars/var3.tests1
-rw-r--r--release/src/router/busybox/shell/ash_test/printenv.c1
-rwxr-xr-xrelease/src/router/busybox/shell/ash_test/run-all6
-rw-r--r--release/src/router/busybox/shell/hush.c249
-rw-r--r--release/src/router/busybox/shell/hush_test/hush-bugs/var3.right5
-rwxr-xr-xrelease/src/router/busybox/shell/hush_test/hush-bugs/var3.tests1
-rw-r--r--release/src/router/busybox/shell/hush_test/hush-glob/glob3.right2
-rwxr-xr-xrelease/src/router/busybox/shell/hush_test/hush-glob/glob3.tests2
-rw-r--r--release/src/router/busybox/shell/hush_test/hush-misc/for.right1
-rwxr-xr-xrelease/src/router/busybox/shell/hush_test/hush-misc/for.tests5
-rwxr-xr-xrelease/src/router/busybox/shell/hush_test/hush-misc/func_args1.tests2
-rw-r--r--release/src/router/busybox/shell/hush_test/hush-misc/nommu3.right2
-rwxr-xr-xrelease/src/router/busybox/shell/hush_test/hush-misc/nommu3.tests15
-rw-r--r--release/src/router/busybox/shell/hush_test/hush-misc/source2.right4
-rwxr-xr-xrelease/src/router/busybox/shell/hush_test/hush-misc/source2.tests8
-rw-r--r--release/src/router/busybox/shell/hush_test/hush-misc/unicode1.right3
-rwxr-xr-xrelease/src/router/busybox/shell/hush_test/hush-misc/unicode1.tests13
-rw-r--r--release/src/router/busybox/shell/hush_test/hush-misc/while4.right1
-rwxr-xr-xrelease/src/router/busybox/shell/hush_test/hush-misc/while4.tests6
-rw-r--r--release/src/router/busybox/shell/hush_test/hush-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.right2
-rwxr-xr-xrelease/src/router/busybox/shell/hush_test/hush-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.tests3
-rw-r--r--release/src/router/busybox/shell/hush_test/hush-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.right1
-rwxr-xr-xrelease/src/router/busybox/shell/hush_test/hush-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.tests2
-rw-r--r--release/src/router/busybox/shell/hush_test/hush-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.right1
-rwxr-xr-xrelease/src/router/busybox/shell/hush_test/hush-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.tests3
-rw-r--r--release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-1.right1
-rwxr-xr-xrelease/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-1.tests2
-rw-r--r--release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-2.right1
-rwxr-xr-xrelease/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-2.tests2
-rw-r--r--release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-3.right1
-rwxr-xr-xrelease/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-3.tests2
-rw-r--r--release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-4.right1
-rwxr-xr-xrelease/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-4.tests2
-rw-r--r--release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-5.right1
-rwxr-xr-xrelease/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-5.tests2
-rw-r--r--release/src/router/busybox/shell/hush_test/hush-vars/var-runtime-quote-detection.right1
-rwxr-xr-xrelease/src/router/busybox/shell/hush_test/hush-vars/var-runtime-quote-detection.tests1
-rw-r--r--release/src/router/busybox/shell/math.c41
-rw-r--r--release/src/router/busybox/shell/math.h5
-rw-r--r--release/src/router/busybox/shell/random.c142
-rw-r--r--release/src/router/busybox/shell/random.h16
-rw-r--r--release/src/router/busybox/shell/shell_common.c8
-rw-r--r--release/src/router/busybox/shell/shell_common.h2
-rw-r--r--release/src/router/busybox/sysklogd/Config.src143
-rw-r--r--release/src/router/busybox/sysklogd/Kbuild.src4
-rw-r--r--release/src/router/busybox/sysklogd/klogd.c64
-rw-r--r--release/src/router/busybox/sysklogd/logger.c44
-rw-r--r--release/src/router/busybox/sysklogd/logread.c70
-rw-r--r--release/src/router/busybox/sysklogd/syslogd.c351
-rw-r--r--release/src/router/busybox/sysklogd/syslogd_and_logger.c1
-rwxr-xr-xrelease/src/router/busybox/testsuite/ar.tests2
-rwxr-xr-xrelease/src/router/busybox/testsuite/awk.tests119
-rwxr-xr-xrelease/src/router/busybox/testsuite/busybox.tests16
-rwxr-xr-xrelease/src/router/busybox/testsuite/bzcat.tests88
-rw-r--r--release/src/router/busybox/testsuite/date/date-works8
-rw-r--r--release/src/router/busybox/testsuite/date/date-works-16
-rwxr-xr-xrelease/src/router/busybox/testsuite/dc.tests56
-rwxr-xr-xrelease/src/router/busybox/testsuite/diff.tests23
-rw-r--r--release/src/router/busybox/testsuite/du/du-k-works7
-rw-r--r--release/src/router/busybox/testsuite/du/du-l-works1
-rw-r--r--release/src/router/busybox/testsuite/du/du-m-works2
-rwxr-xr-xrelease/src/router/busybox/testsuite/find.tests49
-rwxr-xr-xrelease/src/router/busybox/testsuite/grep.tests76
-rw-r--r--release/src/router/busybox/testsuite/hostid/hostid-works10
-rwxr-xr-xrelease/src/router/busybox/testsuite/makedevs.tests2
-rwxr-xr-xrelease/src/router/busybox/testsuite/md5sum.tests6
-rwxr-xr-xrelease/src/router/busybox/testsuite/mdev.tests2
-rwxr-xr-xrelease/src/router/busybox/testsuite/mkfs.minix.tests10
-rwxr-xr-xrelease/src/router/busybox/testsuite/mount.tests27
-rw-r--r--release/src/router/busybox/testsuite/pwd/pwd-prints-working-directory5
-rwxr-xr-xrelease/src/router/busybox/testsuite/readlink.tests11
-rwxr-xr-xrelease/src/router/busybox/testsuite/sed.tests90
-rwxr-xr-xrelease/src/router/busybox/testsuite/sha3sum.tests3
-rwxr-xr-xrelease/src/router/busybox/testsuite/sort.tests55
-rwxr-xr-xrelease/src/router/busybox/testsuite/tar.tests93
-rwxr-xr-xrelease/src/router/busybox/testsuite/test.tests20
-rw-r--r--release/src/router/busybox/testsuite/testing.sh8
-rwxr-xr-xrelease/src/router/busybox/testsuite/unzip.tests24
-rw-r--r--release/src/router/busybox/testsuite/which/which-uses-default-path2
-rw-r--r--release/src/router/busybox/util-linux/Config.src336
-rw-r--r--release/src/router/busybox/util-linux/Kbuild.src1
-rw-r--r--release/src/router/busybox/util-linux/acpid.c13
-rw-r--r--release/src/router/busybox/util-linux/blkdiscard.c83
-rw-r--r--release/src/router/busybox/util-linux/blkid.c2
-rw-r--r--release/src/router/busybox/util-linux/dmesg.c21
-rw-r--r--release/src/router/busybox/util-linux/fatattr.c104
-rw-r--r--release/src/router/busybox/util-linux/fbset.c49
-rw-r--r--release/src/router/busybox/util-linux/fdformat.c8
-rw-r--r--release/src/router/busybox/util-linux/fdisk.c102
-rw-r--r--release/src/router/busybox/util-linux/fdisk_gpt.c13
-rw-r--r--release/src/router/busybox/util-linux/fdisk_osf.c10
-rw-r--r--release/src/router/busybox/util-linux/fdisk_sgi.c29
-rw-r--r--release/src/router/busybox/util-linux/fdisk_sun.c10
-rw-r--r--release/src/router/busybox/util-linux/findfs.c2
-rw-r--r--release/src/router/busybox/util-linux/flock.c23
-rw-r--r--release/src/router/busybox/util-linux/fsck_minix.c85
-rw-r--r--release/src/router/busybox/util-linux/fstrim.c119
-rw-r--r--release/src/router/busybox/util-linux/getopt.c63
-rw-r--r--release/src/router/busybox/util-linux/hexdump.c14
-rw-r--r--release/src/router/busybox/util-linux/hwclock.c14
-rw-r--r--release/src/router/busybox/util-linux/ipcrm.c8
-rw-r--r--release/src/router/busybox/util-linux/ipcs.c258
-rw-r--r--release/src/router/busybox/util-linux/losetup.c125
-rw-r--r--release/src/router/busybox/util-linux/lspci.c6
-rw-r--r--release/src/router/busybox/util-linux/mdev.c570
-rw-r--r--release/src/router/busybox/util-linux/minix.h5
-rw-r--r--release/src/router/busybox/util-linux/mkfs_ext2.c14
-rw-r--r--release/src/router/busybox/util-linux/mkfs_minix.c89
-rw-r--r--release/src/router/busybox/util-linux/mkfs_reiser.c6
-rw-r--r--release/src/router/busybox/util-linux/mkfs_vfat.c4
-rw-r--r--release/src/router/busybox/util-linux/mkswap.c18
-rw-r--r--release/src/router/busybox/util-linux/more.c3
-rw-r--r--release/src/router/busybox/util-linux/mount.c290
-rw-r--r--release/src/router/busybox/util-linux/nsenter.c291
-rw-r--r--release/src/router/busybox/util-linux/rdate.c25
-rw-r--r--release/src/router/busybox/util-linux/readprofile.c28
-rw-r--r--release/src/router/busybox/util-linux/rtcwake.c69
-rw-r--r--release/src/router/busybox/util-linux/script.c17
-rw-r--r--release/src/router/busybox/util-linux/setarch.c54
-rw-r--r--release/src/router/busybox/util-linux/swaponoff.c253
-rw-r--r--release/src/router/busybox/util-linux/switch_root.c2
-rw-r--r--release/src/router/busybox/util-linux/uevent.c131
-rw-r--r--release/src/router/busybox/util-linux/umount.c23
-rw-r--r--release/src/router/busybox/util-linux/unshare.c380
-rw-r--r--release/src/router/busybox/util-linux/volume_id/Config.src15
-rw-r--r--release/src/router/busybox/util-linux/volume_id/Kbuild.src37
-rw-r--r--release/src/router/busybox/util-linux/volume_id/bcache.c110
-rw-r--r--release/src/router/busybox/util-linux/volume_id/btrfs.c12
-rw-r--r--release/src/router/busybox/util-linux/volume_id/cramfs.c11
-rw-r--r--release/src/router/busybox/util-linux/volume_id/exfat.c17
-rw-r--r--release/src/router/busybox/util-linux/volume_id/ext.c85
-rw-r--r--release/src/router/busybox/util-linux/volume_id/f2fs.c95
-rw-r--r--release/src/router/busybox/util-linux/volume_id/fat.c11
-rw-r--r--release/src/router/busybox/util-linux/volume_id/get_devname.c140
-rw-r--r--release/src/router/busybox/util-linux/volume_id/hfs.c38
-rw-r--r--release/src/router/busybox/util-linux/volume_id/iso9660.c11
-rw-r--r--release/src/router/busybox/util-linux/volume_id/jfs.c11
-rw-r--r--release/src/router/busybox/util-linux/volume_id/linux_raid.c17
-rw-r--r--release/src/router/busybox/util-linux/volume_id/linux_swap.c11
-rw-r--r--release/src/router/busybox/util-linux/volume_id/luks.c13
-rw-r--r--release/src/router/busybox/util-linux/volume_id/nilfs.c116
-rw-r--r--release/src/router/busybox/util-linux/volume_id/ntfs.c15
-rw-r--r--release/src/router/busybox/util-linux/volume_id/ocfs2.c11
-rw-r--r--release/src/router/busybox/util-linux/volume_id/reiserfs.c11
-rw-r--r--release/src/router/busybox/util-linux/volume_id/romfs.c11
-rw-r--r--release/src/router/busybox/util-linux/volume_id/squashfs.c61
-rw-r--r--release/src/router/busybox/util-linux/volume_id/sysv.c11
-rw-r--r--release/src/router/busybox/util-linux/volume_id/udf.c13
-rw-r--r--release/src/router/busybox/util-linux/volume_id/unused_highpoint.c11
-rw-r--r--release/src/router/busybox/util-linux/volume_id/unused_hpfs.c11
-rw-r--r--release/src/router/busybox/util-linux/volume_id/unused_isw_raid.c11
-rw-r--r--release/src/router/busybox/util-linux/volume_id/unused_lsi_raid.c11
-rw-r--r--release/src/router/busybox/util-linux/volume_id/unused_lvm.c11
-rw-r--r--release/src/router/busybox/util-linux/volume_id/unused_mac.c11
-rw-r--r--release/src/router/busybox/util-linux/volume_id/unused_minix.c11
-rw-r--r--release/src/router/busybox/util-linux/volume_id/unused_msdos.c15
-rw-r--r--release/src/router/busybox/util-linux/volume_id/unused_nvidia_raid.c11
-rw-r--r--release/src/router/busybox/util-linux/volume_id/unused_promise_raid.c11
-rw-r--r--release/src/router/busybox/util-linux/volume_id/unused_silicon_raid.c13
-rw-r--r--release/src/router/busybox/util-linux/volume_id/unused_ufs.c11
-rw-r--r--release/src/router/busybox/util-linux/volume_id/unused_via_raid.c11
-rw-r--r--release/src/router/busybox/util-linux/volume_id/util.c83
-rw-r--r--release/src/router/busybox/util-linux/volume_id/util2.c7
-rw-r--r--release/src/router/busybox/util-linux/volume_id/volume_id.c14
-rw-r--r--release/src/router/busybox/util-linux/volume_id/volume_id_internal.h73
-rw-r--r--release/src/router/busybox/util-linux/volume_id/xfs.c11
-rw-r--r--release/src/router/ipset_arm/m4/pkg.m4156
-rw-r--r--release/src/router/libdisk/Makefile15
-rw-r--r--release/src/router/libdisk/disk_initial.c57
-rw-r--r--release/src/router/libdisk/libbb_stub.c116
-rw-r--r--release/src/router/libdisk/test_disk2.c57
-rw-r--r--release/src/router/nano/m4/pkg.m4156
-rw-r--r--release/src/router/shared/Makefile40
-rw-r--r--release/src/router/shared/pids.c21
-rw-r--r--release/src/router/shared/usb.c83
-rw-r--r--release/src/router/shared/volume_id.c124
1044 files changed, 29701 insertions, 94362 deletions
diff --git a/release/src/router/busybox/.gitignore b/release/src/router/busybox/.gitignore
index fe579952e7..d197b4de52 100644
--- a/release/src/router/busybox/.gitignore
+++ b/release/src/router/busybox/.gitignore
@@ -8,7 +8,6 @@
*.s
Kbuild
Config.in
-+!/Config.in
#
# Never ignore these
@@ -19,6 +18,7 @@ Config.in
# Normal output
#
/busybox
+/busybox_old
/busybox_unstripped*
#
@@ -36,14 +36,23 @@ core
.gdb_history
.gdbinit
-# asuswrt test
-applets/usage_pod
-busybox.links
-docs/busybox.net/
-include/NUM_APPLETS.h
-include/usage.h
-include/usage_compressed.h.*
-include/applets.h
-config_current
-config_rt*
+#
+# testing output
+#
+/busybox.links
+/runtest-tempdir-links
+/testsuite/echo-ne
+#
+# cscope output
+#
+cscope.files
+cscope.in.out
+cscope.out
+cscope.po.out
+
+#
+# asuswrt
+#
+/config_*
+/!config_base*
diff --git a/release/src/router/busybox/.indent.pro b/release/src/router/busybox/.indent.pro
new file mode 100644
index 0000000000..492ecf1c7d
--- /dev/null
+++ b/release/src/router/busybox/.indent.pro
@@ -0,0 +1,33 @@
+--blank-lines-after-declarations
+--blank-lines-after-procedures
+--break-before-boolean-operator
+--no-blank-lines-after-commas
+--braces-on-if-line
+--braces-on-struct-decl-line
+--comment-indentation25
+--declaration-comment-column25
+--no-comment-delimiters-on-blank-lines
+--cuddle-else
+--continuation-indentation4
+--case-indentation0
+--else-endif-column33
+--space-after-cast
+--line-comments-indentation0
+--declaration-indentation1
+--dont-format-first-column-comments
+--dont-format-comments
+--honour-newlines
+--indent-level4
+/* changed from 0 to 4 */
+--parameter-indentation4
+--line-length78 /* changed from 75 */
+--continue-at-parentheses
+--no-space-after-function-call-names
+--dont-break-procedure-type
+--dont-star-comments
+--leave-optional-blank-lines
+--dont-space-special-semicolon
+--tab-size4
+/* additions by Mark */
+--case-brace-indentation0
+--leave-preprocessor-space
diff --git a/release/src/router/busybox/Config.in b/release/src/router/busybox/Config.in
index f9303420f5..3d18709666 100644
--- a/release/src/router/busybox/Config.in
+++ b/release/src/router/busybox/Config.in
@@ -116,9 +116,21 @@ config FEATURE_COMPRESS_USAGE
and have very little memory, this might not be a win. Otherwise,
you probably want this.
+config BUSYBOX
+ bool "Include busybox applet"
+ default y
+ help
+ The busybox applet provides general help regarding busybox and
+ allows the included applets to be listed. It's also required
+ if applet links are to be installed at runtime.
+
+ If you can live without these features disabling this will save
+ some space.
+
config FEATURE_INSTALLER
bool "Support --install [-s] to install applet links at runtime"
default y
+ depends on BUSYBOX
help
Enable 'busybox --install [-s]' support. This will allow you to use
busybox at runtime to create hard links or symlinks for all the
@@ -161,12 +173,13 @@ config UNICODE_USING_LOCALE
Internal implementation is smaller.
config FEATURE_CHECK_UNICODE_IN_ENV
- bool "Check $LANG environment variable"
+ bool "Check $LC_ALL, $LC_CTYPE and $LANG environment variables"
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"
+ only if locale-related variables have the value of the form
+ "xxxx.utf8"
Otherwise, Unicode support will be always enabled and active.
@@ -256,6 +269,26 @@ config UNICODE_PRESERVE_BROKEN
at shell prompt will list file named 0xff (single char name
with char value 255), not file named '?'.
+config PAM
+ bool "Support for PAM (Pluggable Authentication Modules)"
+ default n
+ help
+ Use PAM in some busybox applets (currently login and httpd) instead
+ of direct access to password database.
+
+config FEATURE_USE_SENDFILE
+ bool "Use sendfile system call"
+ default y
+ select PLATFORM_LINUX
+ help
+ When enabled, busybox will use the kernel sendfile() function
+ instead of read/write loops to copy data between file descriptors
+ (for example, cp command does this a lot).
+ If sendfile() doesn't work, copying code falls back to read/write
+ loop. sendfile() was originally implemented for faster I/O
+ from files to sockets, but since Linux 2.6.33 it was extended
+ to work for many more file types.
+
config LONG_OPTS
bool "Support for --long-options"
default y
@@ -310,7 +343,18 @@ config FEATURE_PIDFILE
default y
help
This option makes some applets (e.g. crond, syslogd, inetd) write
- a pidfile in /var/run. Some applications rely on them.
+ a pidfile at the configured PID_FILE_PATH. It has no effect
+ on applets which require pidfiles to run.
+
+config PID_FILE_PATH
+ string "Path to directory for pidfile"
+ default "/var/run"
+ depends on FEATURE_PIDFILE
+ help
+ This is the default path where pidfiles are created. Applets which
+ allow you to set the pidfile path on the command line will override
+ this value. The option has no effect on applets that require you to
+ specify a pidfile path.
config FEATURE_SUID
bool "Support for SUID/SGID handling"
@@ -321,7 +365,7 @@ config FEATURE_SUID
root-level operations even when run by ordinary users
(for example, mounting of user mounts in fstab needs this).
- Busybox will automatically drop priviledges for applets
+ Busybox will automatically drop privileges for applets
that don't need root access.
If you are really paranoid and don't want to do this, build two
@@ -404,10 +448,7 @@ config SELINUX
the option of compiling in SELinux applets.
If you do not have a complete SELinux userland installed, this stuff
- will not compile. Go visit
- http://www.nsa.gov/selinux/index.html
- to download the necessary stuff to allow busybox to compile with
- this option enabled. Specifially, libselinux 1.28 or better is
+ will not compile. Specifially, libselinux 1.28 or better is
directly required by busybox. If the installation is located in a
non-standard directory, provide it by invoking make as follows:
CFLAGS=-I<libselinux-include-path> \
@@ -659,6 +700,24 @@ config DEBUG_PESSIMIZE
in a much bigger executable that more closely matches the source
code.
+config DEBUG_SANITIZE
+ bool "Enable runtime sanitizers (ASAN/LSAN/USAN/etc...)"
+ default n
+ help
+ Say Y here if you want to enable runtime sanitizers. These help
+ catch bad memory accesses (e.g. buffer overflows), but will make
+ the executable larger and slow down runtime a bit.
+
+ If you aren't developing/testing busybox, say N here.
+
+config UNIT_TEST
+ bool "Build unit tests"
+ default n
+ help
+ Say Y here if you want to build unit tests (both the framework and
+ test cases) as a Busybox applet. This results in bigger code, so you
+ probably don't want this option in production builds.
+
config WERROR
bool "Abort compilation on any warning"
default n
@@ -793,7 +852,7 @@ source editors/Config.in
source findutils/Config.in
source init/Config.in
source loginutils/Config.in
-source e2fsprogs/old_e2fsprogs/Config.in
+source e2fsprogs/Config.in
source modutils/Config.in
source util-linux/Config.in
source miscutils/Config.in
diff --git a/release/src/router/busybox/Makefile b/release/src/router/busybox/Makefile
index 815d4f9dcf..a519f3a7e3 100644
--- a/release/src/router/busybox/Makefile
+++ b/release/src/router/busybox/Makefile
@@ -1,8 +1,6 @@
-include ../.config
-
VERSION = 1
-PATCHLEVEL = 20
-SUBLEVEL = 2
+PATCHLEVEL = 25
+SUBLEVEL = 1
EXTRAVERSION =
NAME = Unnamed
@@ -68,14 +66,6 @@ ifdef M
endif
-ifeq ($(RTCONFIG_BCMARM), y)
-CFLAGS += -DBCMARM
-endif
-
-ifeq ($(RTCONFIG_QCA), y)
-CFLAGS += -DQCA
-endif
-
# kbuild supports saving output files in a separate directory.
# To locate output files in a separate directory two syntaxes are supported.
# In both cases the working directory must be the root of the kernel src.
@@ -307,6 +297,7 @@ NM = $(CROSS_COMPILE)nm
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
+PKG_CONFIG ?= $(CROSS_COMPILE)pkg-config
AWK = awk
GENKSYMS = scripts/genksyms/genksyms
DEPMOD = /sbin/depmod
@@ -479,9 +470,7 @@ libs-y := \
coreutils/ \
coreutils/libcoreutils/ \
debianutils/ \
- e2fsprogs/old_e2fsprogs/ \
- e2fsprogs/old_e2fsprogs/e2p/ \
- e2fsprogs/old_e2fsprogs/ext2fs/ \
+ e2fsprogs/ \
editors/ \
findutils/ \
init/ \
@@ -563,7 +552,7 @@ export INSTALL_PATH ?= /boot
#
# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
# relocations required by build roots. This is not defined in the
-# makefile but the arguement can be passed to make if needed.
+# makefile but the argument can be passed to make if needed.
#
MODLIB = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
@@ -621,7 +610,8 @@ quiet_cmd_busybox__ ?= LINK $@
"$(LDFLAGS) $(EXTRA_LDFLAGS)" \
"$(core-y)" \
"$(libs-y)" \
- "$(LDLIBS)"
+ "$(LDLIBS)" \
+ && $(srctree)/scripts/generate_BUFSIZ.sh --post include/common_bufsiz.h
# Generate System.map
quiet_cmd_sysmap = SYSMAP
@@ -855,12 +845,15 @@ export CPPFLAGS_busybox.lds += -P -C -U$(ARCH)
# Split autoconf.h into include/linux/config/*
quiet_cmd_gen_bbconfigopts = GEN include/bbconfigopts.h
cmd_gen_bbconfigopts = $(srctree)/scripts/mkconfigs include/bbconfigopts.h include/bbconfigopts_bz2.h
+quiet_cmd_gen_common_bufsiz = GEN include/common_bufsiz.h
+ cmd_gen_common_bufsiz = $(srctree)/scripts/generate_BUFSIZ.sh include/common_bufsiz.h
quiet_cmd_split_autoconf = SPLIT include/autoconf.h -> include/config/*
cmd_split_autoconf = scripts/basic/split-include include/autoconf.h include/config
#bbox# piggybacked generation of few .h files
include/config/MARKER: scripts/basic/split-include include/autoconf.h
$(call cmd,split_autoconf)
$(call cmd,gen_bbconfigopts)
+ $(call cmd,gen_common_bufsiz)
@touch $@
# Generate some files
@@ -976,6 +969,7 @@ CLEAN_FILES += busybox busybox_unstripped* busybox.links \
MRPROPER_DIRS += include/config include2
MRPROPER_FILES += .config .config.old include/asm .version .old_version \
include/NUM_APPLETS.h \
+ include/common_bufsiz.h \
include/autoconf.h \
include/bbconfigopts.h \
include/bbconfigopts_bz2.h \
@@ -1176,24 +1170,7 @@ endif
ALLSOURCE_ARCHS := $(ARCH)
define all-sources
- ( find $(__srctree) $(RCS_FIND_IGNORE) \
- \( -name include -o -name arch \) -prune -o \
- -name '*.[chS]' -print; \
- for ARCH in $(ALLSOURCE_ARCHS) ; do \
- find $(__srctree)arch/$${ARCH} $(RCS_FIND_IGNORE) \
- -name '*.[chS]' -print; \
- done ; \
- find $(__srctree)security/selinux/include $(RCS_FIND_IGNORE) \
- -name '*.[chS]' -print; \
- find $(__srctree)include $(RCS_FIND_IGNORE) \
- \( -name config -o -name 'asm-*' \) -prune \
- -o -name '*.[chS]' -print; \
- for ARCH in $(ALLINCLUDE_ARCHS) ; do \
- find $(__srctree)include/asm-$${ARCH} $(RCS_FIND_IGNORE) \
- -name '*.[chS]' -print; \
- done ; \
- find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
- -name '*.[chS]' -print )
+ ( find -regex '.*\.[ch]$$' )
endef
quiet_cmd_cscope-file = FILELST cscope.files
diff --git a/release/src/router/busybox/Makefile.custom b/release/src/router/busybox/Makefile.custom
index 6da79e6e46..891c9ced7f 100644
--- a/release/src/router/busybox/Makefile.custom
+++ b/release/src/router/busybox/Makefile.custom
@@ -3,7 +3,12 @@
# ==========================================================================
busybox.links: $(srctree)/applets/busybox.mkll $(objtree)/include/autoconf.h include/applets.h
- $(Q)-$(SHELL) $^ >$@
+ $(Q)-$(SHELL) $^ > $@
+
+busybox.cfg.suid: $(srctree)/applets/busybox.mksuid $(objtree)/include/autoconf.h include/applets.h
+ $(Q)-SUID="yes" $(SHELL) $^ > $@
+busybox.cfg.nosuid: $(srctree)/applets/busybox.mksuid $(objtree)/include/autoconf.h include/applets.h
+ $(Q)-SUID="DROP" $(SHELL) $^ > $@
.PHONY: install
ifeq ($(CONFIG_INSTALL_APPLET_SYMLINKS),y)
@@ -23,6 +28,10 @@ ifeq ($(CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER),y)
INSTALL_OPTS:= --scriptwrapper
endif
endif
+ifeq ($(CONFIG_FEATURE_INDIVIDUAL),y)
+INSTALL_OPTS:= --binaries
+LIBBUSYBOX_SONAME:= 0_lib/libbusybox.so.$(BB_VER)
+endif
install: $(srctree)/applets/install.sh busybox busybox.links
$(Q)DO_INSTALL_LIBS="$(strip $(LIBBUSYBOX_SONAME) $(DO_INSTALL_LIBS))" \
$(SHELL) $< $(CONFIG_PREFIX) $(INSTALL_OPTS)
@@ -50,7 +59,11 @@ endif
# (cp -pPR is POSIX-compliant (cp -dpR or cp -a would not be))
.PHONY: check
.PHONY: test
+ifeq ($(CONFIG_UNIT_TEST),y)
+UNIT_CMD = ./busybox unit
+endif
check test: busybox busybox.links
+ $(UNIT_CMD)
test -d $(objtree)/testsuite || cp -pPR $(srctree)/testsuite $(objtree)
bindir=$(objtree) srcdir=$(srctree)/testsuite \
$(SHELL) -c "cd $(objtree)/testsuite && $(srctree)/testsuite/runtest $(if $(KBUILD_VERBOSE:0=),-v)"
@@ -69,6 +82,10 @@ release: distclean
-print \
-exec rm -r -f {} \; ; \
find busybox-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)/ -type f \
+ -name .gitignore \
+ -print \
+ -exec rm -f {} \; ; \
+ find busybox-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)/ -type f \
-name .\#* \
-print \
-exec rm -f {} \; ; \
diff --git a/release/src/router/busybox/Makefile.flags b/release/src/router/busybox/Makefile.flags
index e2ce6291e5..4a14f547f8 100644
--- a/release/src/router/busybox/Makefile.flags
+++ b/release/src/router/busybox/Makefile.flags
@@ -25,6 +25,7 @@ CFLAGS += $(call cc-option,-Wstrict-prototypes,)
CFLAGS += $(call cc-option,-Wunused -Wunused-parameter,)
CFLAGS += $(call cc-option,-Wunused-function -Wunused-value,)
CFLAGS += $(call cc-option,-Wmissing-prototypes -Wmissing-declarations,)
+CFLAGS += $(call cc-option,-Wno-format-security,)
# warn about C99 declaration after statement
CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
# If you want to add more -Wsomething above, make sure that it is
@@ -52,6 +53,12 @@ CFLAGS += $(call cc-option,-fno-builtin-strlen -finline-limit=0 -fomit-frame-poi
CFLAGS += $(call cc-option,-fno-guess-branch-probability,)
CFLAGS += $(call cc-option,-funsigned-char -shared-libgcc,)
CFLAGS += $(call cc-option,-falign-functions=1 -falign-jumps=1 -falign-labels=1 -falign-loops=1,)
+# Defeat .eh_frame bloat (gcc 4.6.3 x86-32 defconfig: 20% smaller busybox binary):
+CFLAGS += $(call cc-option,-fno-unwind-tables,)
+CFLAGS += $(call cc-option,-fno-asynchronous-unwind-tables,)
+# No automatic printf->puts,putchar conversions
+# (try disabling this and comparing assembly, it's instructive)
+CFLAGS += $(call cc-option,-fno-builtin-printf,)
# FIXME: These warnings are at least partially to be concerned about and should
# be fixed..
@@ -68,12 +75,23 @@ else
CFLAGS += $(call cc-option,-Os,$(call cc-option,-O2,))
endif
endif
+ifeq ($(CONFIG_DEBUG_SANITIZE),y)
+CFLAGS += $(call cc-option,-fsanitize=address,)
+CFLAGS += $(call cc-option,-fsanitize=leak,)
+CFLAGS += $(call cc-option,-fsanitize=undefined,)
+endif
# If arch/$(ARCH)/Makefile did not override it (with, say, -fPIC)...
ARCH_FPIC ?= -fpic
ARCH_FPIE ?= -fpie
ARCH_PIE ?= -pie
+# Usage: $(eval $(call pkg_check_modules,VARIABLE-PREFIX,MODULES))
+define pkg_check_modules
+$(1)_CFLAGS := $(shell $(PKG_CONFIG) $(PKG_CONFIG_FLAGS) --cflags $(2))
+$(1)_LIBS := $(shell $(PKG_CONFIG) $(PKG_CONFIG_FLAGS) --libs $(2))
+endef
+
ifeq ($(CONFIG_BUILD_LIBBUSYBOX),y)
# on i386: 14% smaller libbusybox.so
# (code itself is 9% bigger, we save on relocs/PLT/GOT)
@@ -85,6 +103,7 @@ endif
ifeq ($(CONFIG_STATIC),y)
CFLAGS_busybox += -static
+PKG_CONFIG_FLAGS += --static
endif
ifeq ($(CONFIG_PIE),y)
@@ -115,19 +134,26 @@ else
LDLIBS += m
endif
+# libpam may use libpthread, libdl and/or libaudit.
+# On some platforms that requires an explicit -lpthread, -ldl, -laudit.
+# However, on *other platforms* it fails when some of those flags
+# given needlessly. On some systems, crypt needs pthread.
+#
+# I even had a system where a runtime test for pthread
+# (similar to CRYPT_AVAILABLE test above) was not reliable.
+#
+# Do not propagate this mess by adding libraries to CONFIG_PAM/CRYPT_AVAILABLE blocks.
+# Add libraries you need to CONFIG_EXTRA_LDLIBS instead.
+
ifeq ($(CONFIG_PAM),y)
-# libpam uses libpthread, so for static builds busybox must be linked to
-# libpthread. On some platforms that requires an explicit -lpthread, so
-# it should be in LDLIBS. For non-static builds, scripts/trylink will
-# take care of removing -lpthread if possible. (Not bothering to check
-# CONFIG_STATIC because even in a non-static build it could be that the
-# only libpam available is libpam.a, so -lpthread could still be
-# needed.)
-LDLIBS += pam pam_misc pthread
+LDLIBS += pam pam_misc
endif
ifeq ($(CONFIG_SELINUX),y)
-LDLIBS += selinux sepol
+SELINUX_PC_MODULES = libselinux libsepol
+$(eval $(call pkg_check_modules,SELINUX,$(SELINUX_PC_MODULES)))
+CPPFLAGS += $(SELINUX_CFLAGS)
+LDLIBS += $(if $(SELINUX_LIBS),$(SELINUX_LIBS:-l%=%),$(SELINUX_PC_MODULES:lib%=%))
endif
ifeq ($(CONFIG_EFENCE),y)
@@ -149,7 +175,7 @@ SKIP_STRIP = y
endif
ifneq ($(CONFIG_EXTRA_LDFLAGS),)
-EXTRA_LDFLAGS += $(strip $(subst ",,$(CONFIG_EXTRA_LDFLAGS)))
+LDFLAGS += $(strip $(subst ",,$(CONFIG_EXTRA_LDFLAGS)))
#"))
endif
diff --git a/release/src/router/busybox/Makefile.help b/release/src/router/busybox/Makefile.help
index 119dd6f89d..6a23e2a807 100644
--- a/release/src/router/busybox/Makefile.help
+++ b/release/src/router/busybox/Makefile.help
@@ -21,10 +21,6 @@ help:
@echo ' defconfig - set .config to largest generic configuration'
@echo ' menuconfig - interactive curses-based configurator'
@echo ' oldconfig - resolve any unresolved symbols in .config'
- @echo ' hosttools - build sed for the host.'
- @echo ' You can use these commands if the commands on the host'
- @echo ' is unusable. Afterwards use it like:'
- @echo ' make SED="$(objtree)/sed"'
@$(if $(boards), \
$(foreach b, $(boards), \
printf " %-21s - Build for %s\\n" $(b) $(subst _defconfig,,$(b));) \
diff --git a/release/src/router/busybox/README b/release/src/router/busybox/README
index b940e357a7..ada5935b9a 100644
--- a/release/src/router/busybox/README
+++ b/release/src/router/busybox/README
@@ -185,7 +185,7 @@ Supported hardware:
Under 2.4 Linux kernels, kernel module loading was implemented in a
platform-specific manner. Busybox's insmod utility has been reported to
work under ARM, CRIS, H8/300, x86, ia64, x86_64, m68k, MIPS, PowerPC, S390,
- SH3/4/5, Sparc, v850e, and x86_64. Anything else probably won't work.
+ SH3/4/5, Sparc, and v850e. Anything else probably won't work.
The module loading mechanism for the 2.6 kernel is much more generic, and
we believe 2.6.x kernel module loading support should work on all
diff --git a/release/src/router/busybox/TODO b/release/src/router/busybox/TODO
index 44364690fa..8904b21358 100644
--- a/release/src/router/busybox/TODO
+++ b/release/src/router/busybox/TODO
@@ -127,20 +127,6 @@ patch
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
----
-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
- Merge to a single size_suffixes[] in libbb.
- Users: head tail od_bloaty hexdump and (partially as it wouldn't hurt) svlogd
----
-tail
- ./busybox tail -f foo.c~ TODO
- should not print fmt=header_fmt for subsequent date >> TODO; i.e. only
- fmt+ if another (not the current) file did change
Architectural issues:
@@ -234,8 +220,6 @@ Minor stuff:
See grep -r strtod
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>
@@ -274,5 +258,3 @@ vdprintf() -> similar sized functionality
* more support for advanced linux 2.6.x features, see: iotop
most likely there is more
-
-* even more support for statistics: mpstat, iostat, powertop....
diff --git a/release/src/router/busybox/VERSION b/release/src/router/busybox/VERSION
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/release/src/router/busybox/VERSION
@@ -0,0 +1 @@
+
diff --git a/release/src/router/busybox/applets/applet_tables.c b/release/src/router/busybox/applets/applet_tables.c
index 152d5f4418..843f2ec081 100644
--- a/release/src/router/busybox/applets/applet_tables.c
+++ b/release/src/router/busybox/applets/applet_tables.c
@@ -14,6 +14,7 @@
#include <string.h>
#include <stdio.h>
#include <unistd.h>
+#include <ctype.h>
#undef ARRAY_SIZE
#define ARRAY_SIZE(x) ((unsigned)(sizeof(x) / sizeof((x)[0])))
@@ -40,8 +41,6 @@ struct bb_applet {
enum { NUM_APPLETS = ARRAY_SIZE(applets) };
-static int offset[NUM_APPLETS];
-
static int cmp_name(const void *a, const void *b)
{
const struct bb_applet *aa = a;
@@ -49,26 +48,42 @@ static int cmp_name(const void *a, const void *b)
return strcmp(aa->name, bb->name);
}
+static int str_isalnum_(const char *s)
+{
+ while (*s) {
+ if (!isalnum(*s) && *s != '_')
+ return 0;
+ s++;
+ }
+ return 1;
+}
+
int main(int argc, char **argv)
{
- int i;
- int ofs;
- unsigned MAX_APPLET_NAME_LEN = 1;
+ int i, j;
+
+ // In find_applet_by_name(), before linear search, narrow it down
+ // by looking at N "equidistant" names. With ~350 applets:
+ // KNOWN_APPNAME_OFFSETS cycles
+ // 0 9057
+ // 2 4604 + ~100 bytes of code
+ // 4 2407 + 4 bytes
+ // 8 1342 + 8 bytes
+ // 16 908 + 16 bytes
+ // 32 884 + 32 bytes
+ // With 8, int16_t applet_nameofs[] table has 7 elements.
+ int KNOWN_APPNAME_OFFSETS = 8;
+ // With 128 applets we do two linear searches, with 1..7 strcmp's in the first one
+ // and 1..16 strcmp's in the second. With 256 apps, second search does 1..32 strcmp's.
+ if (NUM_APPLETS < 128)
+ KNOWN_APPNAME_OFFSETS = 4;
+ if (NUM_APPLETS < 32)
+ KNOWN_APPNAME_OFFSETS = 0;
qsort(applets, NUM_APPLETS, sizeof(applets[0]), cmp_name);
- ofs = 0;
- for (i = 0; i < NUM_APPLETS; i++) {
- offset[i] = ofs;
- ofs += strlen(applets[i].name) + 1;
- }
- /* We reuse 4 high-order bits of offset array for other purposes,
- * so if they are indeed needed, refuse to proceed */
- if (ofs > 0xfff)
- return 1;
if (!argv[1])
return 1;
-
i = open(argv[1], O_WRONLY | O_TRUNC | O_CREAT, 0666);
if (i < 0)
return 1;
@@ -83,17 +98,43 @@ int main(int argc, char **argv)
printf("#define SINGLE_APPLET_STR \"%s\"\n", applets[0].name);
printf("#define SINGLE_APPLET_MAIN %s_main\n", applets[0].main);
}
- printf("\n");
+
+ printf("#define KNOWN_APPNAME_OFFSETS %u\n\n", KNOWN_APPNAME_OFFSETS);
+ if (KNOWN_APPNAME_OFFSETS > 0) {
+ int ofs, offset[KNOWN_APPNAME_OFFSETS], index[KNOWN_APPNAME_OFFSETS];
+ for (i = 0; i < KNOWN_APPNAME_OFFSETS; i++)
+ index[i] = i * NUM_APPLETS / KNOWN_APPNAME_OFFSETS;
+ ofs = 0;
+ for (i = 0; i < NUM_APPLETS; i++) {
+ for (j = 0; j < KNOWN_APPNAME_OFFSETS; j++)
+ if (i == index[j])
+ offset[j] = ofs;
+ ofs += strlen(applets[i].name) + 1;
+ }
+ /* If the list of names is too long refuse to proceed */
+ if (ofs > 0xffff)
+ return 1;
+ printf("const uint16_t applet_nameofs[] ALIGN2 = {\n");
+ for (i = 1; i < KNOWN_APPNAME_OFFSETS; i++)
+ printf("%d,\n", offset[i]);
+ printf("};\n\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);
+// if (MAX_APPLET_NAME_LEN < strlen(applets[i].name))
+// MAX_APPLET_NAME_LEN = strlen(applets[i].name);
}
printf(";\n\n");
+ for (i = 0; i < NUM_APPLETS; i++) {
+ if (str_isalnum_(applets[i].name))
+ printf("#define APPLET_NO_%s %d\n", applets[i].name, i);
+ }
+ printf("\n");
+
printf("#ifndef SKIP_applet_main\n");
printf("int (*const applet_main[])(int argc, char **argv) = {\n");
for (i = 0; i < NUM_APPLETS; i++) {
@@ -102,20 +143,39 @@ int main(int argc, char **argv)
printf("};\n");
printf("#endif\n\n");
- printf("const uint16_t applet_nameofs[] ALIGN2 = {\n");
- for (i = 0; i < NUM_APPLETS; i++) {
- printf("0x%04x,\n",
- offset[i]
#if ENABLE_FEATURE_PREFER_APPLETS
- + (applets[i].nofork << 12)
- + (applets[i].noexec << 13)
+ printf("const uint8_t applet_flags[] ALIGN1 = {\n");
+ i = 0;
+ while (i < NUM_APPLETS) {
+ int v = applets[i].nofork + (applets[i].noexec << 1);
+ if (++i < NUM_APPLETS)
+ v |= (applets[i].nofork + (applets[i].noexec << 1)) << 2;
+ if (++i < NUM_APPLETS)
+ v |= (applets[i].nofork + (applets[i].noexec << 1)) << 4;
+ if (++i < NUM_APPLETS)
+ v |= (applets[i].nofork + (applets[i].noexec << 1)) << 6;
+ printf("0x%02x,\n", v);
+ i++;
+ }
+ printf("};\n\n");
#endif
+
#if ENABLE_FEATURE_SUID
- + (applets[i].need_suid << 14) /* 2 bits */
-#endif
- );
+ printf("const uint8_t applet_suid[] ALIGN1 = {\n");
+ i = 0;
+ while (i < NUM_APPLETS) {
+ int v = applets[i].need_suid; /* 2 bits */
+ if (++i < NUM_APPLETS)
+ v |= applets[i].need_suid << 2;
+ if (++i < NUM_APPLETS)
+ v |= applets[i].need_suid << 4;
+ if (++i < NUM_APPLETS)
+ v |= applets[i].need_suid << 6;
+ printf("0x%02x,\n", v);
+ i++;
}
printf("};\n\n");
+#endif
#if ENABLE_FEATURE_INSTALLER
printf("const uint8_t applet_install_loc[] ALIGN1 = {\n");
@@ -130,8 +190,8 @@ int main(int argc, char **argv)
printf("};\n");
#endif
//printf("#endif /* SKIP_definitions */\n");
- printf("\n");
- printf("#define MAX_APPLET_NAME_LEN %u\n", MAX_APPLET_NAME_LEN);
+// printf("\n");
+// printf("#define MAX_APPLET_NAME_LEN %u\n", MAX_APPLET_NAME_LEN);
if (argv[2]) {
char line_old[80];
diff --git a/release/src/router/busybox/applets/busybox.mksuid b/release/src/router/busybox/applets/busybox.mksuid
new file mode 100755
index 0000000000..6492c079a3
--- /dev/null
+++ b/release/src/router/busybox/applets/busybox.mksuid
@@ -0,0 +1,54 @@
+#!/bin/sh
+# Make list of configuration variables regarding suid handling
+
+# input $1: full path to autoconf.h
+# input $2: full path to applets.h
+# input $3: full path to .config
+# output (stdout): list of CONFIG_ that do or may require suid
+
+# If the environment variable SUID is not set or set to DROP,
+# lists all config options that do not require suid permissions.
+# Otherwise, lists all config options for applets that DO or MAY require
+# suid permissions.
+
+# Maintainer: Bernhard Reutner-Fischer
+
+export LC_ALL=POSIX
+export LC_CTYPE=POSIX
+
+CONFIG_H=${1:-include/autoconf.h}
+APPLETS_H=${2:-include/applets.h}
+DOT_CONFIG=${3:-.config}
+
+case ${SUID:-DROP} in
+[dD][rR][oO][pP]) USE="DROP" ;;
+*) USE="suid" ;;
+esac
+
+$HOSTCC -E -DMAKE_SUID -include $CONFIG_H $APPLETS_H |
+ awk -v USE=${USE} '
+ /^SUID[ \t]/{
+ if (USE == "DROP") {
+ if ($2 != "BB_SUID_DROP") next
+ } else {
+ if ($2 == "BB_SUID_DROP") next
+ }
+ cfg = $NF
+ gsub("\"", "", cfg)
+ cfg = substr(cfg, 8)
+ s[i++] = "CONFIG_" cfg
+ s[i++] = "CONFIG_FEATURE_" cfg "_.*"
+ }
+ END{
+ while (getline < ARGV[2]) {
+ for (j in s) {
+ if ($0 ~ "^" s[j] "=y$") {
+ sub(/=.*/, "")
+ print
+ if (s[j] !~ /\*$/) delete s[j] # can drop this applet now
+ }
+ }
+ }
+ }
+' - $DOT_CONFIG
+
diff --git a/release/src/router/busybox/applets/individual.c b/release/src/router/busybox/applets/individual.c
index 1e74e4ce58..4c468df06a 100644
--- a/release/src/router/busybox/applets/individual.c
+++ b/release/src/router/busybox/applets/individual.c
@@ -14,7 +14,7 @@ const char *applet_name;
int main(int argc, char **argv)
{
applet_name = argv[0];
- return APPLET_main(argc,argv);
+ return APPLET_main(argc, argv);
}
void bb_show_usage(void)
diff --git a/release/src/router/busybox/applets/install.sh b/release/src/router/busybox/applets/install.sh
index 95b4719d4b..f6c097e57e 100755
--- a/release/src/router/busybox/applets/install.sh
+++ b/release/src/router/busybox/applets/install.sh
@@ -5,19 +5,26 @@ export LC_CTYPE=POSIX
prefix=$1
if [ -z "$prefix" ]; then
- echo "usage: applets/install.sh DESTINATION [--symlinks/--hardlinks/--scriptwrapper]"
+ echo "usage: applets/install.sh DESTINATION [--symlinks/--hardlinks/--binaries/--scriptwrapper]"
exit 1
fi
+# Source the configuration
+. ./.config
+
h=`sort busybox.links | uniq`
+sharedlib_dir="0_lib"
+
linkopts=""
scriptwrapper="n"
+binaries="n"
cleanup="0"
noclobber="0"
case "$2" in
--hardlinks) linkopts="-f";;
--symlinks) linkopts="-fs";;
+ --binaries) binaries="y";;
--scriptwrapper) scriptwrapper="y";swrapall="y";;
--sw-sh-hard) scriptwrapper="y";linkopts="-f";;
--sw-sh-sym) scriptwrapper="y";linkopts="-fs";;
@@ -40,8 +47,9 @@ if [ -n "$DO_INSTALL_LIBS" ] && [ "$DO_INSTALL_LIBS" != "n" ]; then
for i in $DO_INSTALL_LIBS; do
rm -f "$prefix/$libdir/$i" || exit 1
if [ -f "$i" ]; then
+ echo " Installing $i to the target at $prefix/$libdir/"
cp -pPR "$i" "$prefix/$libdir/" || exit 1
- chmod 0644 "$prefix/$libdir/$i" || exit 1
+ chmod 0644 "$prefix/$libdir/`basename $i`" || exit 1
fi
done
fi
@@ -68,6 +76,7 @@ install -m 755 busybox "$prefix/bin/busybox" || exit 1
for i in $h; do
appdir=`dirname "$i"`
+ app=`basename "$i"`
mkdir -p "$prefix/$appdir" || exit 1
if [ "$scriptwrapper" = "y" ]; then
if [ "$swrapall" != "y" ] && [ "$i" = "/bin/sh" ]; then
@@ -78,6 +87,19 @@ for i in $h; do
chmod +x "$prefix/$i"
fi
echo " $prefix/$i"
+ elif [ "$binaries" = "y" ]; then
+ # Copy the binary over rather
+ if [ -e $sharedlib_dir/$app ]; then
+ if [ "$noclobber" = "0" ] || [ ! -e "$prefix/$i" ]; then
+ echo " Copying $sharedlib_dir/$app to $prefix/$i"
+ cp -pPR $sharedlib_dir/$app $prefix/$i || exit 1
+ else
+ echo " $prefix/$i already exists"
+ fi
+ else
+ echo "Error: Could not find $sharedlib_dir/$app"
+ exit 1
+ fi
else
if [ "$2" = "--hardlinks" ]; then
bb_path="$prefix/bin/busybox"
diff --git a/release/src/router/busybox/applets/usage_compressed b/release/src/router/busybox/applets/usage_compressed
index af66bc5dc2..186fcde774 100755
--- a/release/src/router/busybox/applets/usage_compressed
+++ b/release/src/router/busybox/applets/usage_compressed
@@ -10,23 +10,31 @@ test "$SED" || SED=sed
test "$DD" || DD=dd
# Some people were bitten by their system lacking a (proper) od
-od -v -t x1 </dev/null >/dev/null
+od -v -b </dev/null >/dev/null
if test $? != 0; then
- echo 'od tool is not installed or cannot accept "-v -t x1" options'
+ echo 'od tool is not installed or cannot accept "-v -b" options'
exit 1
fi
exec >"$target.$$"
echo '#define UNPACKED_USAGE "" \'
-"$loc/usage" | od -v -t x1 \
+"$loc/usage" | od -v -b \
+| grep -v '^ ' \
| $SED -e 's/^[^ ]*//' \
-e 's/ //g' \
-e '/^$/d' \
- -e 's/\(..\)/\\x\1/g' \
+ -e 's/\(...\)/\\\1/g' \
-e 's/^/"/' \
-e 's/$/" \\/'
echo ''
+# "grep -v '^ '" is for toybox's od bug: od -b prints some extra lines:
+#0000000 010 000 010 000 133 055 144 146 135 040 133 055 143 040 103 117
+# 000010 000010 026533 063144 020135 026533 020143 047503
+#0000020 116 106 104 111 122 135 040 133 055 154 040 114 117 107 106 111
+# 043116 044504 056522 055440 066055 046040 043517 044506
+#0000040 114 105 135 040 133 055 141 040 101 103 124 111 117 116 106 111
+# 042514 020135 026533 020141 041501 044524 047117 044506
echo '#define PACKED_USAGE \'
## Breaks on big-endian systems!
@@ -39,11 +47,12 @@ echo '#define PACKED_USAGE \'
## -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 \
+"$loc/usage" | bzip2 -1 | $DD bs=2 skip=1 2>/dev/null | od -v -b \
+| grep -v '^ ' \
| $SED -e 's/^[^ ]*//' \
-e 's/ //g' \
-e '/^$/d' \
- -e 's/\(..\)/0x\1,/g' \
+ -e 's/\(...\)/0\1,/g' \
-e 's/$/ \\/'
echo ''
diff --git a/release/src/router/busybox/archival/Config.src b/release/src/router/busybox/archival/Config.src
index ae1afc5942..a9afaea5b1 100644
--- a/release/src/router/busybox/archival/Config.src
+++ b/release/src/router/busybox/archival/Config.src
@@ -5,8 +5,6 @@
menu "Archival Utilities"
-INSERT
-
config FEATURE_SEAMLESS_XZ
bool "Make tar, rpm, modprobe etc understand .xz data"
default y
@@ -33,356 +31,10 @@ config FEATURE_SEAMLESS_GZ
config FEATURE_SEAMLESS_Z
bool "tar, rpm, modprobe etc understand .Z data"
- default n
+ default n # it is ancient
help
Make tar, rpm, modprobe etc understand .Z data.
-config AR
- bool "ar"
- 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,
- and group are preserved in the archive, and can be restored on
- extraction.
-
- The stored filename is limited to 15 characters. (for more information
- see long filename support).
- ar has 60 bytes of overheads for every stored file.
-
- This implementation of ar can extract archives, it cannot create or
- modify them.
- On an x86 system, the ar applet adds about 1K.
-
- 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 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 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 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 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
- "newc" or "crc" format, it cannot create or modify them.
-
- 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 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 y
- depends on FEATURE_CPIO_O
- help
- Passthrough mode. Rarely used.
-
-config DPKG
- bool "dpkg"
- default n
- select FEATURE_SEAMLESS_GZ
- help
- dpkg is a medium-level tool to install, build, remove and manage
- Debian packages.
-
- This implementation of dpkg has a number of limitations,
- you should use the official dpkg if possible.
-
-config DPKG_DEB
- bool "dpkg_deb"
- default n
- select FEATURE_SEAMLESS_GZ
- help
- dpkg-deb unpacks and provides information about Debian archives.
-
- This implementation of dpkg-deb cannot pack archives.
-
- Unless you have a specific application which requires dpkg-deb,
- say N here.
-
-config FEATURE_DPKG_DEB_EXTRACT_ONLY
- bool "Extract only (-x)"
- default n
- depends on DPKG_DEB
- help
- This reduces dpkg-deb to the equivalent of
- "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 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 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 y
- depends on GZIP && LONG_OPTS
- help
- Enable use of long options, increases size by about 106 Bytes
-
-config GZIP_FAST
- int "Trade memory for gzip speed (0:small,slow - 2:fast,big)"
- default 0
- range 0 2
- depends on GZIP
- help
- Enable big memory options for gzip.
- 0: small buffers, small hash-tables
- 1: larger buffers, larger hash-tables
- 2: larger buffers, largest hash-tables
- Larger models may give slightly better compression
-
-config LZOP
- bool "lzop"
- default y
- help
- Lzop compression/decompresion.
-
-config LZOP_COMPR_HIGH
- bool "lzop compression levels 7,8,9 (not very useful)"
- default n
- depends on LZOP
- help
- 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 y
- help
- Converts a RPM file into a CPIO archive.
-
-config RPM
- bool "rpm"
- default y
- help
- Mini RPM applet - queries and extracts RPM packages.
-
-config TAR
- bool "tar"
- 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.
-
-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 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 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 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 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 || DPKG
- help
- With this option busybox supports GNU long filenames and
- linknames.
-
-config FEATURE_TAR_LONG_OPTIONS
- bool "Enable long options"
- 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 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 y
- depends on TAR
- help
- With this option busybox supports GNU tar -m
- (do not preserve time) option.
-
-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 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.
-
- The BusyBox unlzma applet is limited to decompression only.
- On an x86 system, this applet adds about 4K.
-
-config FEATURE_LZMA_FAST
- bool "Optimize unlzma for speed"
- default n
- 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 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.
+INSERT
endmenu
diff --git a/release/src/router/busybox/archival/Kbuild.src b/release/src/router/busybox/archival/Kbuild.src
index 3466452f7a..b3a7d538f4 100644
--- a/release/src/router/busybox/archival/Kbuild.src
+++ b/release/src/router/busybox/archival/Kbuild.src
@@ -4,27 +4,8 @@
#
# Licensed under GPLv2, see file LICENSE in this source tree.
-libs-y += libarchive/
+libs-y += libarchive/
lib-y:=
INSERT
-
-lib-$(CONFIG_AR) += ar.o
-lib-$(CONFIG_CPIO) += cpio.o
-lib-$(CONFIG_DPKG) += dpkg.o
-lib-$(CONFIG_DPKG_DEB) += dpkg_deb.o
-lib-$(CONFIG_RPM2CPIO) += rpm2cpio.o
-lib-$(CONFIG_RPM) += rpm.o
-lib-$(CONFIG_TAR) += tar.o
-lib-$(CONFIG_UNZIP) += unzip.o
-
-lib-$(CONFIG_LZOP) += lzop.o bbunzip.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/release/src/router/busybox/archival/ar.c b/release/src/router/busybox/archival/ar.c
index 88236e878d..e49d5cb2bf 100644
--- a/release/src/router/busybox/archival/ar.c
+++ b/release/src/router/busybox/archival/ar.c
@@ -17,6 +17,39 @@
* http://www.unix-systems.org/single_unix_specification_v2/xcu/ar.html
*/
+//config:config AR
+//config: bool "ar"
+//config: default n # needs to be improved to be able to replace binutils ar
+//config: help
+//config: ar is an archival utility program used to create, modify, and
+//config: extract contents from archives. In practice, it is used exclusively
+//config: for object module archives used by compilers.
+//config:
+//config: On an x86 system, the ar applet adds about 1K.
+//config:
+//config: Unless you have a specific application which requires ar, you should
+//config: probably say N here: most compilers come with their own ar utility.
+//config:
+//config:config FEATURE_AR_LONG_FILENAMES
+//config: bool "Support for long filenames (not needed for debs)"
+//config: default y
+//config: depends on AR
+//config: help
+//config: By default the ar format can only store the first 15 characters
+//config: of the filename, this option removes that limitation.
+//config: It supports the GNU ar long filename method which moves multiple long
+//config: filenames into a the data section of a new ar entry.
+//config:
+//config:config FEATURE_AR_CREATE
+//config: bool "Support archive creation"
+//config: default y
+//config: depends on AR
+//config: help
+//config: This enables archive creation (-c and -r) with busybox ar.
+
+//applet:IF_AR(APPLET(ar, BB_DIR_USR_BIN, BB_SUID_DROP))
+//kbuild:lib-$(CONFIG_AR) += ar.o
+
//usage:#define ar_trivial_usage
//usage: "[-o] [-v] [-p] [-t] [-x] ARCHIVE FILES"
//usage:#define ar_full_usage "\n\n"
diff --git a/release/src/router/busybox/archival/bbunzip.c b/release/src/router/busybox/archival/bbunzip.c
index 94d8a81c94..07ef8617e3 100644
--- a/release/src/router/busybox/archival/bbunzip.c
+++ b/release/src/router/busybox/archival/bbunzip.c
@@ -7,13 +7,19 @@
#include "libbb.h"
#include "bb_archive.h"
+/* lzop_main() uses bbunpack(), need this: */
+//kbuild:lib-$(CONFIG_LZOP) += bbunzip.o
+
+/* Note: must be kept in sync with archival/lzop.c */
enum {
OPT_STDOUT = 1 << 0,
OPT_FORCE = 1 << 1,
/* only some decompressors: */
OPT_VERBOSE = 1 << 2,
- OPT_DECOMPRESS = 1 << 3,
- OPT_TEST = 1 << 4,
+ OPT_QUIET = 1 << 3,
+ OPT_DECOMPRESS = 1 << 4,
+ OPT_TEST = 1 << 5,
+ SEAMLESS_MAGIC = (1 << 31) * SEAMLESS_COMPRESSION,
};
static
@@ -33,16 +39,16 @@ char* FAST_FUNC append_ext(char *filename, const char *expected_ext)
}
int FAST_FUNC bbunpack(char **argv,
- IF_DESKTOP(long long) int FAST_FUNC (*unpacker)(transformer_aux_data_t *aux),
+ IF_DESKTOP(long long) int FAST_FUNC (*unpacker)(transformer_state_t *xstate),
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;
+ IF_DESKTOP(long long) int status = 0;
char *filename, *new_name;
smallint exitcode = 0;
- transformer_aux_data_t aux;
+ transformer_state_t xstate;
do {
/* NB: new_name is *maybe* malloc'ed! */
@@ -54,13 +60,28 @@ int FAST_FUNC bbunpack(char **argv,
/* Open src */
if (filename) {
- if (stat(filename, &stat_buf) != 0) {
- bb_simple_perror_msg(filename);
+ if (!(option_mask32 & SEAMLESS_MAGIC)) {
+ if (stat(filename, &stat_buf) != 0) {
+ err_name:
+ bb_simple_perror_msg(filename);
err:
- exitcode = 1;
- goto free_name;
+ exitcode = 1;
+ goto free_name;
+ }
+ if (open_to_or_warn(STDIN_FILENO, filename, O_RDONLY, 0))
+ goto err;
+ } else {
+ /* "clever zcat" with FILE */
+ /* fail_if_not_compressed because zcat refuses uncompressed input */
+ int fd = open_zipped(filename, /*fail_if_not_compressed:*/ 1);
+ if (fd < 0)
+ goto err_name;
+ xmove_fd(fd, STDIN_FILENO);
}
- if (open_to_or_warn(STDIN_FILENO, filename, O_RDONLY, 0))
+ } else
+ if (option_mask32 & SEAMLESS_MAGIC) {
+ /* "clever zcat" on stdin */
+ if (setup_unzip_on_fd(STDIN_FILENO, /*fail_if_not_compressed*/ 1))
goto err;
}
@@ -68,7 +89,7 @@ int FAST_FUNC bbunpack(char **argv,
if (option_mask32 & (OPT_STDOUT|OPT_TEST)) {
if (option_mask32 & OPT_TEST)
if (open_to_or_warn(STDOUT_FILENO, bb_dev_null, O_WRONLY, 0))
- goto err;
+ xfunc_die();
filename = NULL;
}
@@ -93,28 +114,39 @@ int FAST_FUNC bbunpack(char **argv,
}
/* Check that the input is sane */
- if (isatty(STDIN_FILENO) && (option_mask32 & OPT_FORCE) == 0) {
+ if (!(option_mask32 & OPT_FORCE) && isatty(STDIN_FILENO)) {
bb_error_msg_and_die("compressed data not read from terminal, "
"use -f to force it");
}
- init_transformer_aux_data(&aux);
- aux.check_signature = 1;
- status = unpacker(&aux);
- if (status < 0)
- exitcode = 1;
+ if (!(option_mask32 & SEAMLESS_MAGIC)) {
+ init_transformer_state(&xstate);
+ xstate.signature_skipped = 0;
+ /*xstate.src_fd = STDIN_FILENO; - already is */
+ xstate.dst_fd = STDOUT_FILENO;
+ status = unpacker(&xstate);
+ if (status < 0)
+ exitcode = 1;
+ } else {
+ if (bb_copyfd_eof(STDIN_FILENO, STDOUT_FILENO) < 0)
+ /* Disk full, tty closed, etc. No point in continuing */
+ xfunc_die();
+ }
if (!(option_mask32 & OPT_STDOUT))
xclose(STDOUT_FILENO); /* with error check! */
if (filename) {
char *del = new_name;
+
if (status >= 0) {
+ unsigned new_name_len;
+
/* TODO: restore other things? */
- if (aux.mtime != 0) {
+ if (xstate.mtime != 0) {
struct timeval times[2];
- times[1].tv_sec = times[0].tv_sec = aux.mtime;
+ times[1].tv_sec = times[0].tv_sec = xstate.mtime;
times[1].tv_usec = times[0].tv_usec = 0;
/* Note: we closed it first.
* On some systems calling utimes
@@ -123,22 +155,29 @@ int FAST_FUNC bbunpack(char **argv,
utimes(new_name, times); /* ignoring errors */
}
- /* Delete _compressed_ file */
+ if (ENABLE_DESKTOP)
+ new_name_len = strlen(new_name);
+ /* Restore source filename (unless tgz -> tar case) */
+ if (new_name == filename) {
+ new_name_len = strlen(filename);
+ filename[new_name_len] = '.';
+ }
+ /* Extreme bloat for gunzip compat */
+ /* Some users do want this info... */
+ if (ENABLE_DESKTOP && (option_mask32 & OPT_VERBOSE)) {
+ unsigned percent = status
+ ? ((uoff_t)stat_buf.st_size * 100u / (unsigned long long)status)
+ : 0;
+ fprintf(stderr, "%s: %u%% - replaced with %.*s\n",
+ filename,
+ 100u - percent,
+ new_name_len, new_name
+ );
+ }
+ /* Delete _source_ file */
del = filename;
- /* restore extension (unless tgz -> tar case) */
- if (new_name == filename)
- filename[strlen(filename)] = '.';
}
xunlink(del);
-
-#if 0 /* Currently buggy - wrong name: "a.gz: 261% - replaced with a.gz" */
- /* Extreme bloat for gunzip compat */
- if (ENABLE_DESKTOP && (option_mask32 & OPT_VERBOSE) && status >= 0) {
- fprintf(stderr, "%s: %u%% - replaced with %s\n",
- filename, (unsigned)(stat_buf.st_size*100 / (status+1)), new_name);
- }
-#endif
-
free_name:
if (new_name != filename)
free(new_name);
@@ -172,7 +211,6 @@ char* FAST_FUNC make_new_name_generic(char *filename, const char *expected_ext)
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
-
//usage:#define uncompress_trivial_usage
//usage: "[-cf] [FILE]..."
//usage:#define uncompress_full_usage "\n\n"
@@ -180,19 +218,23 @@ char* FAST_FUNC make_new_name_generic(char *filename, const char *expected_ext)
//usage: "\n -c Write to stdout"
//usage: "\n -f Overwrite"
+//config:config UNCOMPRESS
+//config: bool "uncompress"
+//config: default n # ancient
+//config: help
+//config: uncompress is used to decompress archives created by compress.
+//config: Not much used anymore, replaced by gzip/gunzip.
+
+//applet:IF_UNCOMPRESS(APPLET(uncompress, BB_DIR_BIN, BB_SUID_DROP))
+//kbuild:lib-$(CONFIG_UNCOMPRESS) += bbunzip.o
#if ENABLE_UNCOMPRESS
-static
-IF_DESKTOP(long long) int FAST_FUNC unpack_uncompress(transformer_aux_data_t *aux)
-{
- return unpack_Z_stream(aux, STDIN_FILENO, STDOUT_FILENO);
-}
int uncompress_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int uncompress_main(int argc UNUSED_PARAM, char **argv)
{
getopt32(argv, "cf");
argv += optind;
- return bbunpack(argv, unpack_uncompress, make_new_name_generic, "Z");
+ return bbunpack(argv, unpack_Z_stream, make_new_name_generic, "Z");
}
#endif
@@ -220,11 +262,7 @@ int uncompress_main(int argc UNUSED_PARAM, char **argv)
* Portions of the lzw code are derived from the public domain 'compress'
* 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.
*/
-
//usage:#define gunzip_trivial_usage
//usage: "[-cft] [FILE]..."
//usage:#define gunzip_full_usage "\n\n"
@@ -241,10 +279,29 @@ int uncompress_main(int argc UNUSED_PARAM, char **argv)
//usage: "-rw-rw-r-- 1 andersen andersen 1761280 Apr 14 17:47 /tmp/BusyBox-0.43.tar\n"
//usage:
//usage:#define zcat_trivial_usage
-//usage: "FILE"
+//usage: "[FILE]..."
//usage:#define zcat_full_usage "\n\n"
//usage: "Decompress to stdout"
+//config:config GUNZIP
+//config: bool "gunzip"
+//config: default y
+//config: help
+//config: gunzip is used to decompress archives created by gzip.
+//config: You can use the `-t' option to test the integrity of
+//config: an archive, without decompressing it.
+//config:
+//config:config FEATURE_GUNZIP_LONG_OPTIONS
+//config: bool "Enable long options"
+//config: default y
+//config: depends on GUNZIP && LONG_OPTS
+//config: help
+//config: Enable use of long options.
+
+//applet:IF_GUNZIP(APPLET(gunzip, BB_DIR_BIN, BB_SUID_DROP))
+//applet:IF_GUNZIP(APPLET_ODDNAME(zcat, gunzip, BB_DIR_BIN, BB_SUID_DROP, zcat))
+//kbuild:lib-$(CONFIG_GZIP) += bbunzip.o
+//kbuild:lib-$(CONFIG_GUNZIP) += bbunzip.o
#if ENABLE_GUNZIP
static
char* FAST_FUNC make_new_name_gunzip(char *filename, const char *expected_ext UNUSED_PARAM)
@@ -271,11 +328,17 @@ char* FAST_FUNC make_new_name_gunzip(char *filename, const char *expected_ext UN
}
return filename;
}
-static
-IF_DESKTOP(long long) int FAST_FUNC unpack_gunzip(transformer_aux_data_t *aux)
-{
- return unpack_gz_stream(aux, STDIN_FILENO, STDOUT_FILENO);
-}
+
+#if ENABLE_FEATURE_GUNZIP_LONG_OPTIONS
+static const char gunzip_longopts[] ALIGN1 =
+ "stdout\0" No_argument "c"
+ "to-stdout\0" No_argument "c"
+ "force\0" No_argument "f"
+ "test\0" No_argument "t"
+ "no-name\0" No_argument "n"
+ ;
+#endif
+
/*
* Linux kernel build uses gzip -d -n. We accept and ignore it.
* Man page says:
@@ -292,13 +355,20 @@ IF_DESKTOP(long long) int FAST_FUNC unpack_gunzip(transformer_aux_data_t *aux)
int gunzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int gunzip_main(int argc UNUSED_PARAM, char **argv)
{
- getopt32(argv, "cfvdtn");
+#if ENABLE_FEATURE_GUNZIP_LONG_OPTIONS
+ applet_long_options = gunzip_longopts;
+#endif
+ getopt32(argv, "cfvqdtn");
argv += optind;
- /* if called as zcat */
+
+ /* If called as zcat...
+ * Normally, "zcat" is just "gunzip -c".
+ * But if seamless magic is enabled, then we are much more clever.
+ */
if (applet_name[1] == 'c')
- option_mask32 |= OPT_STDOUT;
+ option_mask32 |= OPT_STDOUT | SEAMLESS_MAGIC;
- return bbunpack(argv, unpack_gunzip, make_new_name_gunzip, /*unused:*/ NULL);
+ return bbunpack(argv, unpack_gz_stream, make_new_name_gunzip, /*unused:*/ NULL);
}
#endif
@@ -316,26 +386,37 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv)
//usage: "\n -c Write to stdout"
//usage: "\n -f Force"
//usage:#define bzcat_trivial_usage
-//usage: "FILE"
+//usage: "[FILE]..."
//usage:#define bzcat_full_usage "\n\n"
//usage: "Decompress to stdout"
+
+//config:config BUNZIP2
+//config: bool "bunzip2"
+//config: default y
+//config: help
+//config: bunzip2 is a compression utility using the Burrows-Wheeler block
+//config: sorting text compression algorithm, and Huffman coding. Compression
+//config: is generally considerably better than that achieved by more
+//config: conventional LZ77/LZ78-based compressors, and approaches the
+//config: performance of the PPM family of statistical compressors.
+//config:
+//config: Unless you have a specific application which requires bunzip2, you
+//config: should probably say N here.
+
//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))
+//kbuild:lib-$(CONFIG_BZIP2) += bbunzip.o
+//kbuild:lib-$(CONFIG_BUNZIP2) += bbunzip.o
#if ENABLE_BUNZIP2
-static
-IF_DESKTOP(long long) int FAST_FUNC unpack_bunzip2(transformer_aux_data_t *aux)
-{
- return unpack_bz2_stream(aux, 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");
+ getopt32(argv, "cfvqdt");
argv += optind;
if (applet_name[2] == 'c') /* bzcat */
option_mask32 |= OPT_STDOUT;
- return bbunpack(argv, unpack_bunzip2, make_new_name_generic, "bz2");
+ return bbunpack(argv, unpack_bz2_stream, make_new_name_generic, "bz2");
}
#endif
@@ -348,7 +429,6 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv)
*
* Licensed under GPLv2, see file LICENSE in this source tree.
*/
-
//usage:#define unlzma_trivial_usage
//usage: "[-cf] [FILE]..."
//usage:#define unlzma_full_usage "\n\n"
@@ -365,7 +445,7 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv)
//usage: "\n -f Force"
//usage:
//usage:#define lzcat_trivial_usage
-//usage: "FILE"
+//usage: "[FILE]..."
//usage:#define lzcat_full_usage "\n\n"
//usage: "Decompress to stdout"
//usage:
@@ -385,20 +465,47 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv)
//usage: "\n -f Force"
//usage:
//usage:#define xzcat_trivial_usage
-//usage: "FILE"
+//usage: "[FILE]..."
//usage:#define xzcat_full_usage "\n\n"
//usage: "Decompress to stdout"
+//config:config UNLZMA
+//config: bool "unlzma"
+//config: default y
+//config: help
+//config: unlzma is a compression utility using the Lempel-Ziv-Markov chain
+//config: compression algorithm, and range coding. Compression
+//config: is generally considerably better than that achieved by the bzip2
+//config: compressors.
+//config:
+//config: The BusyBox unlzma applet is limited to decompression only.
+//config: On an x86 system, this applet adds about 4K.
+//config:
+//config:config FEATURE_LZMA_FAST
+//config: bool "Optimize unlzma for speed"
+//config: default n
+//config: depends on UNLZMA
+//config: help
+//config: This option reduces decompression time by about 25% at the cost of
+//config: a 1K bigger binary.
+//config:
+//config:config LZMA
+//config: bool "Provide lzma alias which supports only unpacking"
+//config: default y
+//config: depends on UNLZMA
+//config: help
+//config: Enable this option if you want commands like "lzma -d" to work.
+//config: IOW: you'll get lzma applet, but it will always require -d option.
+
+//applet:IF_UNLZMA(APPLET(unlzma, BB_DIR_USR_BIN, BB_SUID_DROP))
+//applet:IF_UNLZMA(APPLET_ODDNAME(lzcat, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzcat))
+//applet:IF_LZMA(APPLET_ODDNAME(lzma, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzma))
+//kbuild:lib-$(CONFIG_UNLZMA) += bbunzip.o
#if ENABLE_UNLZMA
-static
-IF_DESKTOP(long long) int FAST_FUNC unpack_unlzma(transformer_aux_data_t *aux)
-{
- return unpack_lzma_stream(aux, STDIN_FILENO, STDOUT_FILENO);
-}
int unlzma_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int unlzma_main(int argc UNUSED_PARAM, char **argv)
{
- IF_LZMA(int opts =) getopt32(argv, "cfvdt");
+ IF_LZMA(int opts =) getopt32(argv, "cfvqdt");
# if ENABLE_LZMA
/* lzma without -d or -t? */
if (applet_name[2] == 'm' && !(opts & (OPT_DECOMPRESS|OPT_TEST)))
@@ -409,21 +516,34 @@ int unlzma_main(int argc UNUSED_PARAM, char **argv)
option_mask32 |= OPT_STDOUT;
argv += optind;
- return bbunpack(argv, unpack_unlzma, make_new_name_generic, "lzma");
+ return bbunpack(argv, unpack_lzma_stream, make_new_name_generic, "lzma");
}
#endif
+//config:config UNXZ
+//config: bool "unxz"
+//config: default y
+//config: help
+//config: unxz is a unlzma successor.
+//config:
+//config:config XZ
+//config: bool "Provide xz alias which supports only unpacking"
+//config: default y
+//config: depends on UNXZ
+//config: help
+//config: Enable this option if you want commands like "xz -d" to work.
+//config: IOW: you'll get xz applet, but it will always require -d option.
+
+//applet:IF_UNXZ(APPLET(unxz, BB_DIR_USR_BIN, BB_SUID_DROP))
+//applet:IF_UNXZ(APPLET_ODDNAME(xzcat, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xzcat))
+//applet:IF_XZ(APPLET_ODDNAME(xz, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xz))
+//kbuild:lib-$(CONFIG_UNXZ) += bbunzip.o
#if ENABLE_UNXZ
-static
-IF_DESKTOP(long long) int FAST_FUNC unpack_unxz(transformer_aux_data_t *aux)
-{
- return unpack_xz_stream(aux, STDIN_FILENO, STDOUT_FILENO);
-}
int unxz_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int unxz_main(int argc UNUSED_PARAM, char **argv)
{
- IF_XZ(int opts =) getopt32(argv, "cfvdt");
+ IF_XZ(int opts =) getopt32(argv, "cfvqdt");
# if ENABLE_XZ
/* xz without -d or -t? */
if (applet_name[2] == '\0' && !(opts & (OPT_DECOMPRESS|OPT_TEST)))
@@ -434,6 +554,6 @@ int unxz_main(int argc UNUSED_PARAM, char **argv)
option_mask32 |= OPT_STDOUT;
argv += optind;
- return bbunpack(argv, unpack_unxz, make_new_name_generic, "xz");
+ return bbunpack(argv, unpack_xz_stream, make_new_name_generic, "xz");
}
#endif
diff --git a/release/src/router/busybox/archival/bzip2.c b/release/src/router/busybox/archival/bzip2.c
index dd77c8efcf..47fa29af3c 100644
--- a/release/src/router/busybox/archival/bzip2.c
+++ b/release/src/router/busybox/archival/bzip2.c
@@ -7,6 +7,22 @@
* about bzip2 library code.
*/
+//config:config BZIP2
+//config: bool "bzip2"
+//config: default y
+//config: help
+//config: bzip2 is a compression utility using the Burrows-Wheeler block
+//config: sorting text compression algorithm, and Huffman coding. Compression
+//config: is generally considerably better than that achieved by more
+//config: conventional LZ77/LZ78-based compressors, and approaches the
+//config: performance of the PPM family of statistical compressors.
+//config:
+//config: Unless you have a specific application which requires bzip2, you
+//config: should probably say N here.
+
+//applet:IF_BZIP2(APPLET(bzip2, BB_DIR_USR_BIN, BB_SUID_DROP))
+//kbuild:lib-$(CONFIG_BZIP2) += bzip2.o
+
//usage:#define bzip2_trivial_usage
//usage: "[OPTIONS] [FILE]..."
//usage:#define bzip2_full_usage "\n\n"
@@ -111,7 +127,7 @@ IF_DESKTOP(long long) int bz_write(bz_stream *strm, void* rbuf, ssize_t rlen, vo
}
static
-IF_DESKTOP(long long) int FAST_FUNC compressStream(transformer_aux_data_t *aux UNUSED_PARAM)
+IF_DESKTOP(long long) int FAST_FUNC compressStream(transformer_state_t *xstate UNUSED_PARAM)
{
IF_DESKTOP(long long) int total;
ssize_t count;
diff --git a/release/src/router/busybox/archival/cpio.c b/release/src/router/busybox/archival/cpio.c
index 98cc18fa07..3b15507200 100644
--- a/release/src/router/busybox/archival/cpio.c
+++ b/release/src/router/busybox/archival/cpio.c
@@ -9,13 +9,45 @@
* Limitations:
* Doesn't check CRC's
* Only supports new ASCII and CRC formats
- *
*/
#include "libbb.h"
+#include "common_bufsiz.h"
#include "bb_archive.h"
+//config:config CPIO
+//config: bool "cpio"
+//config: default y
+//config: help
+//config: cpio is an archival utility program used to create, modify, and
+//config: extract contents from archives.
+//config: cpio has 110 bytes of overheads for every stored file.
+//config:
+//config: This implementation of cpio can extract cpio archives created in the
+//config: "newc" or "crc" format, it cannot create or modify them.
+//config:
+//config: Unless you have a specific application which requires cpio, you
+//config: should probably say N here.
+//config:
+//config:config FEATURE_CPIO_O
+//config: bool "Support for archive creation"
+//config: default y
+//config: depends on CPIO
+//config: help
+//config: This implementation of cpio can create cpio archives in the "newc"
+//config: format only.
+//config:
+//config:config FEATURE_CPIO_P
+//config: bool "Support for passthrough mode"
+//config: default y
+//config: depends on FEATURE_CPIO_O
+//config: help
+//config: Passthrough mode. Rarely used.
+
+//applet:IF_CPIO(APPLET(cpio, BB_DIR_BIN, BB_SUID_DROP))
+//kbuild:lib-$(CONFIG_CPIO) += cpio.o
+
//usage:#define cpio_trivial_usage
-//usage: "[-dmvu] [-F FILE]" IF_FEATURE_CPIO_O(" [-H newc]")
+//usage: "[-dmvu] [-F FILE] [-R USER[:GRP]]" IF_FEATURE_CPIO_O(" [-H newc]")
//usage: " [-ti"IF_FEATURE_CPIO_O("o")"]" IF_FEATURE_CPIO_P(" [-p DIR]")
//usage: " [EXTR_FILE]..."
//usage:#define cpio_full_usage "\n\n"
@@ -34,11 +66,13 @@
//usage: IF_FEATURE_CPIO_P(
//usage: "\n -p DIR Copy files to DIR"
//usage: )
+//usage: "\nOptions:"
//usage: "\n -d Make leading directories"
//usage: "\n -m Preserve mtime"
//usage: "\n -v Verbose"
//usage: "\n -u Overwrite"
//usage: "\n -F FILE Input (-t,-i,-p) or output (-o) file"
+//usage: "\n -R USER[:GRP] Set owner of created files"
//usage: IF_FEATURE_CPIO_O(
//usage: "\n -H newc Archive format"
//usage: )
@@ -98,7 +132,7 @@
-I FILE File to use instead of standard input
-L, --dereference Dereference symbolic links (copy the files
that they point to instead of copying the links)
- -R, --owner=[USER][:.][GROUP] Set owner of created files
+ -R, --owner=[USER][:.][GRP] Set owner of created files
Options valid in --extract and --pass-through modes:
-d, --make-directories Create leading directories where needed
@@ -118,7 +152,8 @@ enum {
OPT_PRESERVE_MTIME = (1 << 6),
OPT_DEREF = (1 << 7),
OPT_FILE = (1 << 8),
- OPTBIT_FILE = 8,
+ OPT_OWNER = (1 << 9),
+ OPTBIT_OWNER = 9,
IF_FEATURE_CPIO_O(OPTBIT_CREATE ,)
IF_FEATURE_CPIO_O(OPTBIT_FORMAT ,)
IF_FEATURE_CPIO_P(OPTBIT_PASSTHROUGH,)
@@ -131,7 +166,18 @@ enum {
OPT_2STDOUT = IF_LONG_OPTS( (1 << OPTBIT_2STDOUT )) + 0,
};
-#define OPTION_STR "it0uvdmLF:"
+#define OPTION_STR "it0uvdmLF:R:"
+
+struct globals {
+ struct bb_uidgid_t owner_ugid;
+} FIX_ALIASING;
+#define G (*(struct globals*)bb_common_bufsiz1)
+void BUG_cpio_globals_too_big(void);
+#define INIT_G() do { \
+ setup_common_bufsiz(); \
+ G.owner_ugid.uid = -1L; \
+ G.owner_ugid.gid = -1L; \
+} while (0)
#if ENABLE_FEATURE_CPIO_O
static off_t cpio_pad4(off_t size)
@@ -149,7 +195,6 @@ static off_t cpio_pad4(off_t size)
* It's ok to exit instead of return. */
static NOINLINE int cpio_o(void)
{
- static const char trailer[] ALIGN1 = "TRAILER!!!";
struct name_s {
struct name_s *next;
char name[1];
@@ -191,6 +236,11 @@ static NOINLINE int cpio_o(void)
bb_simple_perror_msg_and_die(name);
}
+ if (G.owner_ugid.uid != (uid_t)-1L)
+ st.st_uid = G.owner_ugid.uid;
+ if (G.owner_ugid.gid != (gid_t)-1L)
+ st.st_gid = G.owner_ugid.gid;
+
if (!(S_ISLNK(st.st_mode) || S_ISREG(st.st_mode)))
st.st_size = 0; /* paranoia */
@@ -225,7 +275,6 @@ static NOINLINE int cpio_o(void)
free(line);
continue;
}
-
} else { /* line == NULL: EOF */
next_link:
if (links) {
@@ -244,7 +293,7 @@ static NOINLINE int cpio_o(void)
} else {
/* If no (more) hardlinks to output,
* output "trailer" entry */
- name = trailer;
+ name = cpio_TRAILER;
/* st.st_size == 0 is a must, but for uniformity
* in the output, we zero out everything */
memset(&st, 0, sizeof(st));
@@ -253,24 +302,24 @@ static NOINLINE int cpio_o(void)
}
bytes += printf("070701"
- "%08X%08X%08X%08X%08X%08X%08X"
- "%08X%08X%08X%08X" /* GNU cpio uses uppercase hex */
+ "%08X%08X%08X%08X%08X%08X%08X"
+ "%08X%08X%08X%08X" /* GNU cpio uses uppercase hex */
/* strlen+1: */ "%08X"
/* chksum: */ "00000000" /* (only for "070702" files) */
/* name,NUL: */ "%s%c",
- (unsigned)(uint32_t) st.st_ino,
- (unsigned)(uint32_t) st.st_mode,
- (unsigned)(uint32_t) st.st_uid,
- (unsigned)(uint32_t) st.st_gid,
- (unsigned)(uint32_t) st.st_nlink,
- (unsigned)(uint32_t) st.st_mtime,
- (unsigned)(uint32_t) st.st_size,
- (unsigned)(uint32_t) major(st.st_dev),
- (unsigned)(uint32_t) minor(st.st_dev),
- (unsigned)(uint32_t) major(st.st_rdev),
- (unsigned)(uint32_t) minor(st.st_rdev),
- (unsigned)(strlen(name) + 1),
- name, '\0');
+ (unsigned)(uint32_t) st.st_ino,
+ (unsigned)(uint32_t) st.st_mode,
+ (unsigned)(uint32_t) st.st_uid,
+ (unsigned)(uint32_t) st.st_gid,
+ (unsigned)(uint32_t) st.st_nlink,
+ (unsigned)(uint32_t) st.st_mtime,
+ (unsigned)(uint32_t) st.st_size,
+ (unsigned)(uint32_t) major(st.st_dev),
+ (unsigned)(uint32_t) minor(st.st_dev),
+ (unsigned)(uint32_t) major(st.st_rdev),
+ (unsigned)(uint32_t) minor(st.st_rdev),
+ (unsigned)(strlen(name) + 1),
+ name, '\0');
bytes = cpio_pad4(bytes);
if (st.st_size) {
@@ -292,7 +341,7 @@ static NOINLINE int cpio_o(void)
}
if (!line) {
- if (name != trailer)
+ if (name != cpio_TRAILER)
goto next_link;
/* TODO: GNU cpio pads trailer to 512 bytes, do we want that? */
return EXIT_SUCCESS;
@@ -308,6 +357,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
{
archive_handle_t *archive_handle;
char *cpio_filename;
+ char *cpio_owner;
IF_FEATURE_CPIO_O(const char *cpio_fmt = "";)
unsigned opt;
@@ -322,12 +372,14 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
"pass-through\0" No_argument "p"
#endif
#endif
+ "owner\0" Required_argument "R"
"verbose\0" No_argument "v"
"quiet\0" No_argument "\xff"
"to-stdout\0" No_argument "\xfe"
;
#endif
+ INIT_G();
archive_handle = init_handle();
/* archive_handle->src_fd = STDIN_FILENO; - done by init_handle */
archive_handle->ah_flags = ARCHIVE_EXTRACT_NEWER;
@@ -338,14 +390,21 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
/* -L makes sense only with -o or -p */
#if !ENABLE_FEATURE_CPIO_O
- opt = getopt32(argv, OPTION_STR, &cpio_filename);
+ opt = getopt32(argv, OPTION_STR, &cpio_filename, &cpio_owner);
+#else
+ opt = getopt32(argv, OPTION_STR "oH:" IF_FEATURE_CPIO_P("p"),
+ &cpio_filename, &cpio_owner, &cpio_fmt);
+#endif
argv += optind;
+ if (opt & OPT_OWNER) { /* -R */
+ parse_chown_usergroup_or_die(&G.owner_ugid, cpio_owner);
+ archive_handle->cpio__owner = G.owner_ugid;
+ }
+#if !ENABLE_FEATURE_CPIO_O
if (opt & OPT_FILE) { /* -F */
xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO);
}
#else
- opt = getopt32(argv, OPTION_STR "oH:" IF_FEATURE_CPIO_P("p"), &cpio_filename, &cpio_fmt);
- argv += optind;
if ((opt & (OPT_FILE|OPT_CREATE)) == OPT_FILE) { /* -F without -o */
xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO);
}
diff --git a/release/src/router/busybox/archival/dpkg.c b/release/src/router/busybox/archival/dpkg.c
index bf9e9992c1..df7a0db64f 100644
--- a/release/src/router/busybox/archival/dpkg.c
+++ b/release/src/router/busybox/archival/dpkg.c
@@ -14,7 +14,6 @@
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
-
/*
* known difference between busybox dpkg and the official dpkg that i don't
* consider important, its worth keeping a note of differences anyway, just to
@@ -25,9 +24,22 @@
*
* bugs that need to be fixed
* - (unknown, please let me know when you find any)
- *
*/
+//config:config DPKG
+//config: bool "dpkg"
+//config: default n
+//config: select FEATURE_SEAMLESS_GZ
+//config: help
+//config: dpkg is a medium-level tool to install, build, remove and manage
+//config: Debian packages.
+//config:
+//config: This implementation of dpkg has a number of limitations,
+//config: you should use the official dpkg if possible.
+
+//applet:IF_DPKG(APPLET(dpkg, BB_DIR_USR_BIN, BB_SUID_DROP))
+//kbuild:lib-$(CONFIG_DPKG) += dpkg.o
+
//usage:#define dpkg_trivial_usage
//usage: "[-ilCPru] [-F OPT] PACKAGE"
//usage:#define dpkg_full_usage "\n\n"
@@ -1026,8 +1038,8 @@ static int check_deps(deb_file_t **deb_file, int deb_start /*, int dep_max_count
if (package_edge->type == EDGE_CONFLICTS) {
const unsigned package_num =
search_package_hashtable(package_edge->name,
- package_edge->version,
- package_edge->operator);
+ package_edge->version,
+ package_edge->operator);
int result = 0;
if (package_hashtable[package_num] != NULL) {
status_num = search_status_hashtable(name_hashtable[package_hashtable[package_num]->name]);
@@ -1114,7 +1126,7 @@ static int check_deps(deb_file_t **deb_file, int deb_start /*, int dep_max_count
*/
if (root_of_alternatives && package_edge->type != root_of_alternatives->type - 1)
bb_error_msg_and_die("fatal error, package dependencies corrupt: %d != %d - 1",
- package_edge->type, root_of_alternatives->type);
+ package_edge->type, root_of_alternatives->type);
if (package_hashtable[package_num] != NULL)
result = !package_satisfies_dependency(package_num, package_edge->type);
@@ -1139,13 +1151,13 @@ static int check_deps(deb_file_t **deb_file, int deb_start /*, int dep_max_count
if (result && number_of_alternatives == 0) {
if (root_of_alternatives)
bb_error_msg_and_die(
- "package %s %sdepends on %s, "
- "which cannot be satisfied",
+ "package %s %sdepends on %s, which %s",
name_hashtable[package_node->name],
package_edge->type == EDGE_PRE_DEPENDS ? "pre-" : "",
- name_hashtable[root_of_alternatives->name]);
+ name_hashtable[root_of_alternatives->name],
+ "cannot be satisfied");
bb_error_msg_and_die(
- "package %s %sdepends on %s, which %s\n",
+ "package %s %sdepends on %s, which %s",
name_hashtable[package_node->name],
package_edge->type == EDGE_PRE_DEPENDS ? "pre-" : "",
name_hashtable[package_edge->name],
@@ -1460,12 +1472,16 @@ static void init_archive_deb_control(archive_handle_t *ar_handle)
tar_handle->src_fd = ar_handle->src_fd;
/* We don't care about data.tar.* or debian-binary, just control.tar.* */
+ llist_add_to(&(ar_handle->accept), (char*)"control.tar");
#if ENABLE_FEATURE_SEAMLESS_GZ
llist_add_to(&(ar_handle->accept), (char*)"control.tar.gz");
#endif
#if ENABLE_FEATURE_SEAMLESS_BZ2
llist_add_to(&(ar_handle->accept), (char*)"control.tar.bz2");
#endif
+#if ENABLE_FEATURE_SEAMLESS_XZ
+ llist_add_to(&(ar_handle->accept), (char*)"control.tar.xz");
+#endif
/* Assign the tar handle as a subarchive of the ar handle */
ar_handle->dpkg__sub_archive = tar_handle;
@@ -1480,12 +1496,19 @@ static void init_archive_deb_data(archive_handle_t *ar_handle)
tar_handle->src_fd = ar_handle->src_fd;
/* We don't care about control.tar.* or debian-binary, just data.tar.* */
+ llist_add_to(&(ar_handle->accept), (char*)"data.tar");
#if ENABLE_FEATURE_SEAMLESS_GZ
llist_add_to(&(ar_handle->accept), (char*)"data.tar.gz");
#endif
#if ENABLE_FEATURE_SEAMLESS_BZ2
llist_add_to(&(ar_handle->accept), (char*)"data.tar.bz2");
#endif
+#if ENABLE_FEATURE_SEAMLESS_LZMA
+ llist_add_to(&(ar_handle->accept), (char*)"data.tar.lzma");
+#endif
+#if ENABLE_FEATURE_SEAMLESS_XZ
+ llist_add_to(&(ar_handle->accept), (char*)"data.tar.xz");
+#endif
/* Assign the tar handle as a subarchive of the ar handle */
ar_handle->dpkg__sub_archive = tar_handle;
@@ -1665,20 +1688,25 @@ static void unpack_package(deb_file_t *deb_file)
archive_handle = init_archive_deb_ar(deb_file->filename);
init_archive_deb_data(archive_handle);
archive_handle->dpkg__sub_archive->accept = conffile_list;
+ /* Why ARCHIVE_REMEMBER_NAMES?
+ * We want names collected in ->passed list even if conffile_list
+ * is NULL (otherwise get_header_tar may optimize name saving out):
+ */
+ archive_handle->dpkg__sub_archive->ah_flags |= ARCHIVE_REMEMBER_NAMES | ARCHIVE_UNLINK_OLD;
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 */
list_filename = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "list");
out_stream = xfopen_for_write(list_filename);
+ archive_handle->dpkg__sub_archive->passed = llist_rev(archive_handle->dpkg__sub_archive->passed);
while (archive_handle->dpkg__sub_archive->passed) {
+ char *filename = llist_pop(&archive_handle->dpkg__sub_archive->passed);
/* the leading . has been stripped by data_extract_all_prefix already */
- fputs(archive_handle->dpkg__sub_archive->passed->data, out_stream);
- fputc('\n', out_stream);
- archive_handle->dpkg__sub_archive->passed = archive_handle->dpkg__sub_archive->passed->link;
+ fprintf(out_stream, "%s\n", filename);
+ free(filename);
}
fclose(out_stream);
diff --git a/release/src/router/busybox/archival/dpkg_deb.c b/release/src/router/busybox/archival/dpkg_deb.c
index a04ec94077..0285273fec 100644
--- a/release/src/router/busybox/archival/dpkg_deb.c
+++ b/release/src/router/busybox/archival/dpkg_deb.c
@@ -5,8 +5,33 @@
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//config:config DPKG_DEB
+//config: bool "dpkg_deb"
+//config: default n
+//config: select FEATURE_SEAMLESS_GZ
+//config: help
+//config: dpkg-deb unpacks and provides information about Debian archives.
+//config:
+//config: This implementation of dpkg-deb cannot pack archives.
+//config:
+//config: Unless you have a specific application which requires dpkg-deb,
+//config: say N here.
+//config:
+//config:config FEATURE_DPKG_DEB_EXTRACT_ONLY
+//config: bool "Extract only (-x)"
+//config: default n
+//config: depends on DPKG_DEB
+//config: help
+//config: This reduces dpkg-deb to the equivalent of
+//config: "ar -p <deb> data.tar.gz | tar -zx". However it saves space as none
+//config: of the extra dpkg-deb, ar or tar options are needed, they are linked
+//config: to internally.
+
+//applet:IF_DPKG_DEB(APPLET_ODDNAME(dpkg-deb, dpkg_deb, BB_DIR_USR_BIN, BB_SUID_DROP, dpkg_deb))
+//kbuild:lib-$(CONFIG_DPKG_DEB) += dpkg_deb.o
+
//usage:#define dpkg_deb_trivial_usage
-//usage: "[-cefxX] FILE [argument"
+//usage: "[-cefxX] FILE [argument]"
//usage:#define dpkg_deb_full_usage "\n\n"
//usage: "Perform actions on Debian packages (.debs)\n"
//usage: "\n -c List contents of filesystem tree"
@@ -45,6 +70,8 @@ int dpkg_deb_main(int argc, char **argv)
ar_archive->dpkg__sub_archive = tar_archive;
ar_archive->filter = filter_accept_list_reassign;
+ llist_add_to(&ar_archive->accept, (char*)"data.tar");
+ llist_add_to(&control_tar_llist, (char*)"control.tar");
#if ENABLE_FEATURE_SEAMLESS_GZ
llist_add_to(&ar_archive->accept, (char*)"data.tar.gz");
llist_add_to(&control_tar_llist, (char*)"control.tar.gz");
@@ -57,6 +84,10 @@ int dpkg_deb_main(int argc, char **argv)
llist_add_to(&ar_archive->accept, (char*)"data.tar.lzma");
llist_add_to(&control_tar_llist, (char*)"control.tar.lzma");
#endif
+#if ENABLE_FEATURE_SEAMLESS_XZ
+ llist_add_to(&ar_archive->accept, (char*)"data.tar.xz");
+ llist_add_to(&control_tar_llist, (char*)"control.tar.xz");
+#endif
opt_complementary = "c--efXx:e--cfXx:f--ceXx:X--cefx:x--cefX";
opt = getopt32(argv, "cefXx");
diff --git a/release/src/router/busybox/archival/gzip.c b/release/src/router/busybox/archival/gzip.c
index 80db4f9699..9e0bee8153 100644
--- a/release/src/router/busybox/archival/gzip.c
+++ b/release/src/router/busybox/archival/gzip.c
@@ -15,7 +15,6 @@
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
-
/* big objects in bss:
* 00000020 b bl_count
* 00000074 b base_length
@@ -31,7 +30,6 @@
* 00000480 b static_ltree
* 000008f4 b dyn_ltree
*/
-
/* TODO: full support for -v for DESKTOP
* "/usr/bin/gzip -v a bogus aa" should say:
a: 85.1% -- replaced with a.gz
@@ -39,11 +37,55 @@ gzip: bogus: No such file or directory
aa: 85.1% -- replaced with aa.gz
*/
+//config:config GZIP
+//config: bool "gzip"
+//config: default y
+//config: help
+//config: gzip is used to compress files.
+//config: It's probably the most widely used UNIX compression program.
+//config:
+//config:config FEATURE_GZIP_LONG_OPTIONS
+//config: bool "Enable long options"
+//config: default y
+//config: depends on GZIP && LONG_OPTS
+//config: help
+//config: Enable use of long options, increases size by about 106 Bytes
+//config:
+//config:config GZIP_FAST
+//config: int "Trade memory for gzip speed (0:small,slow - 2:fast,big)"
+//config: default 0
+//config: range 0 2
+//config: depends on GZIP
+//config: help
+//config: Enable big memory options for gzip.
+//config: 0: small buffers, small hash-tables
+//config: 1: larger buffers, larger hash-tables
+//config: 2: larger buffers, largest hash-tables
+//config: Larger models may give slightly better compression
+//config:
+//config:config FEATURE_GZIP_LEVELS
+//config: bool "Enable compression levels"
+//config: default n
+//config: depends on GZIP
+//config: help
+//config: Enable support for compression levels 4-9. The default level
+//config: is 6. If levels 1-3 are specified, 4 is used.
+//config: If this option is not selected, -N options are ignored and -9
+//config: is used.
+
+//applet:IF_GZIP(APPLET(gzip, BB_DIR_BIN, BB_SUID_DROP))
+//kbuild:lib-$(CONFIG_GZIP) += gzip.o
+
//usage:#define gzip_trivial_usage
-//usage: "[-cfd] [FILE]..."
+//usage: "[-cf" IF_GUNZIP("d") IF_FEATURE_GZIP_LEVELS("123456789") "] [FILE]..."
//usage:#define gzip_full_usage "\n\n"
//usage: "Compress FILEs (or stdin)\n"
+//usage: IF_FEATURE_GZIP_LEVELS(
+//usage: "\n -1..9 Compression level"
+//usage: )
+//usage: IF_GUNZIP(
//usage: "\n -d Decompress"
+//usage: )
//usage: "\n -c Write to stdout"
//usage: "\n -f Force"
//usage:
@@ -225,6 +267,8 @@ enum {
* input file length plus MIN_LOOKAHEAD.
*/
+#ifndef ENABLE_FEATURE_GZIP_LEVELS
+
max_chain_length = 4096,
/* To speed up deflation, hash chains are never searched beyond this length.
* A higher limit improves compression ratio but degrades the speed.
@@ -256,11 +300,23 @@ enum {
* For deflate_fast() (levels <= 3) good is ignored and lazy has a different
* meaning.
*/
+#endif /* ENABLE_FEATURE_GZIP_LEVELS */
};
struct globals {
+#ifdef ENABLE_FEATURE_GZIP_LEVELS
+ unsigned max_chain_length;
+ unsigned max_lazy_match;
+ unsigned good_match;
+ unsigned nice_match;
+#define max_chain_length (G1.max_chain_length)
+#define max_lazy_match (G1.max_lazy_match)
+#define good_match (G1.good_match)
+#define nice_match (G1.nice_match)
+#endif
+
lng block_start;
/* window position at the beginning of the current output block. Gets
@@ -390,19 +446,46 @@ static void flush_outbuf(void)
#define put_8bit(c) \
do { \
G1.outbuf[G1.outcnt++] = (c); \
- if (G1.outcnt == OUTBUFSIZ) flush_outbuf(); \
+ if (G1.outcnt == OUTBUFSIZ) \
+ flush_outbuf(); \
} while (0)
/* Output a 16 bit value, lsb first */
static void put_16bit(ush w)
{
- if (G1.outcnt < OUTBUFSIZ - 2) {
- G1.outbuf[G1.outcnt++] = w;
- G1.outbuf[G1.outcnt++] = w >> 8;
- } else {
- put_8bit(w);
- put_8bit(w >> 8);
+ /* GCC 4.2.1 won't optimize out redundant loads of G1.outcnt
+ * (probably because of fear of aliasing with G1.outbuf[]
+ * stores), do it explicitly:
+ */
+ unsigned outcnt = G1.outcnt;
+ uch *dst = &G1.outbuf[outcnt];
+
+#if BB_UNALIGNED_MEMACCESS_OK && BB_LITTLE_ENDIAN
+ if (outcnt < OUTBUFSIZ-2) {
+ /* Common case */
+ ush *dst16 = (void*) dst;
+ *dst16 = w; /* unalinged LSB 16-bit store */
+ G1.outcnt = outcnt + 2;
+ return;
}
+ *dst = (uch)w;
+ w >>= 8;
+#else
+ *dst = (uch)w;
+ w >>= 8;
+ if (outcnt < OUTBUFSIZ-2) {
+ /* Common case */
+ dst[1] = w;
+ G1.outcnt = outcnt + 2;
+ return;
+ }
+#endif
+
+ /* Slowpath: we will need to do flush_outbuf() */
+ G1.outcnt = ++outcnt;
+ if (outcnt == OUTBUFSIZ)
+ flush_outbuf();
+ put_8bit(w);
}
static void put_32bit(ulg n)
@@ -1179,7 +1262,7 @@ static void gen_codes(ct_data * tree, int max_code)
* must be all ones.
*/
Assert(code + G2.bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1,
- "inconsistent bit counts");
+ "inconsistent bit counts");
Tracev((stderr, "\ngen_codes: max_code %d ", max_code));
for (n = 0; n <= max_code; n++) {
@@ -1291,7 +1374,6 @@ static void build_tree(tree_desc * desc)
/* and insert the new node in the heap */
G2.heap[SMALLEST] = node++;
pqdownheap(tree, SMALLEST);
-
} while (G2.heap_len >= 2);
G2.heap[--G2.heap_max] = G2.heap[SMALLEST];
@@ -1527,9 +1609,9 @@ static int ct_tally(int dist, int lc)
}
out_length >>= 3;
Trace((stderr,
- "\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ",
- G2.last_lit, G2.last_dist, in_length, out_length,
- 100L - out_length * 100L / in_length));
+ "\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ",
+ G2.last_lit, G2.last_dist, in_length, out_length,
+ 100L - out_length * 100L / in_length));
if (G2.last_dist < G2.last_lit / 2 && out_length < in_length / 2)
return 1;
}
@@ -1621,9 +1703,9 @@ static ulg flush_block(char *buf, ulg stored_len, int eof)
static_lenb = (G2.static_len + 3 + 7) >> 3;
Trace((stderr,
- "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ",
- opt_lenb, G2.opt_len, static_lenb, G2.static_len, stored_len,
- G2.last_lit, G2.last_dist));
+ "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ",
+ opt_lenb, G2.opt_len, static_lenb, G2.static_len, stored_len,
+ G2.last_lit, G2.last_dist));
if (static_lenb <= opt_lenb)
opt_lenb = static_lenb;
@@ -1639,7 +1721,6 @@ static ulg flush_block(char *buf, ulg stored_len, int eof)
copy_block(buf, (unsigned) stored_len, 0); /* without header */
G2.compressed_len = stored_len << 3;
-
} else if (stored_len + 4 <= opt_lenb && buf != NULL) {
/* 4: two words for the lengths */
/* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
@@ -1653,7 +1734,6 @@ static ulg flush_block(char *buf, ulg stored_len, int eof)
G2.compressed_len += (stored_len + 4) << 3;
copy_block(buf, (unsigned) stored_len, 1); /* with header */
-
} else if (static_lenb == opt_lenb) {
send_bits((STATIC_TREES << 1) + eof, 3);
compress_block((ct_data *) G2.static_ltree, (ct_data *) G2.static_dtree);
@@ -1661,7 +1741,7 @@ static ulg flush_block(char *buf, ulg stored_len, int eof)
} else {
send_bits((DYN_TREES << 1) + eof, 3);
send_all_trees(G2.l_desc.max_code + 1, G2.d_desc.max_code + 1,
- max_blindex + 1);
+ max_blindex + 1);
compress_block((ct_data *) G2.dyn_ltree, (ct_data *) G2.dyn_dtree);
G2.compressed_len += 3 + G2.opt_len;
}
@@ -1980,7 +2060,7 @@ static void ct_init(void)
* IN assertions: the input and output buffers are cleared.
*/
-static void zip(ulg time_stamp)
+static void zip(void)
{
ush deflate_flags = 0; /* pkzip -es, -en or -ex equivalent */
@@ -1991,7 +2071,7 @@ static void zip(ulg time_stamp)
/* compression method: 8 (DEFLATED) */
/* general flags: 0 */
put_32bit(0x00088b1f);
- put_32bit(time_stamp);
+ put_32bit(0); /* Unix timestamp */
/* Write deflated file to zip file */
G1.crc = ~0;
@@ -2015,10 +2095,8 @@ static void zip(ulg time_stamp)
/* ======================================================================== */
static
-IF_DESKTOP(long long) int FAST_FUNC pack_gzip(transformer_aux_data_t *aux UNUSED_PARAM)
+IF_DESKTOP(long long) int FAST_FUNC pack_gzip(transformer_state_t *xstate UNUSED_PARAM)
{
- struct stat s;
-
/* Clear input and output buffers */
G1.outcnt = 0;
#ifdef DEBUG
@@ -2050,9 +2128,23 @@ IF_DESKTOP(long long) int FAST_FUNC pack_gzip(transformer_aux_data_t *aux UNUSED
G2.bl_desc.max_length = MAX_BL_BITS;
//G2.bl_desc.max_code = 0;
+#if 0
+ /* Saving of timestamp is disabled. Why?
+ * - it is not Y2038-safe.
+ * - some people want deterministic results
+ * (normally they'd use -n, but our -n is a nop).
+ * - it's bloat.
+ * Per RFC 1952, gzfile.time=0 is "no timestamp".
+ * If users will demand this to be reinstated,
+ * implement -n "don't save timestamp".
+ */
+ struct stat s;
s.st_ctime = 0;
fstat(STDIN_FILENO, &s);
zip(s.st_ctime);
+#else
+ zip();
+#endif
return 0;
}
@@ -2070,6 +2162,7 @@ static const char gzip_longopts[] ALIGN1 =
"quiet\0" No_argument "q"
"fast\0" No_argument "1"
"best\0" No_argument "9"
+ "no-name\0" No_argument "n"
;
#endif
@@ -2095,24 +2188,45 @@ int gzip_main(int argc UNUSED_PARAM, char **argv)
#endif
{
unsigned opt;
+#ifdef ENABLE_FEATURE_GZIP_LEVELS
+ static const struct {
+ uint8_t good;
+ uint8_t chain_shift;
+ uint8_t lazy2;
+ uint8_t nice2;
+ } gzip_level_config[6] = {
+ {4, 4, 4/2, 16/2}, /* Level 4 */
+ {8, 5, 16/2, 32/2}, /* Level 5 */
+ {8, 7, 16/2, 128/2}, /* Level 6 */
+ {8, 8, 32/2, 128/2}, /* Level 7 */
+ {32, 10, 128/2, 258/2}, /* Level 8 */
+ {32, 12, 258/2, 258/2}, /* Level 9 */
+ };
+#endif
+
+ SET_PTR_TO_GLOBALS((char *)xzalloc(sizeof(struct globals)+sizeof(struct globals2))
+ + sizeof(struct globals));
#if ENABLE_FEATURE_GZIP_LONG_OPTIONS
applet_long_options = gzip_longopts;
#endif
/* Must match bbunzip's constants OPT_STDOUT, OPT_FORCE! */
- opt = getopt32(argv, "cfv" IF_GUNZIP("dt") "q123456789n");
+ opt = getopt32(argv, "cfv" IF_GUNZIP("dt") "qn123456789");
#if ENABLE_GUNZIP /* gunzip_main may not be visible... */
if (opt & 0x18) // -d and/or -t
return gunzip_main(argc, argv);
#endif
- option_mask32 &= 0x7; /* ignore -q, -0..9 */
- //if (opt & 0x1) // -c
- //if (opt & 0x2) // -f
- //if (opt & 0x4) // -v
- argv += optind;
-
- SET_PTR_TO_GLOBALS((char *)xzalloc(sizeof(struct globals)+sizeof(struct globals2))
- + sizeof(struct globals));
+#ifdef ENABLE_FEATURE_GZIP_LEVELS
+ opt >>= ENABLE_GUNZIP ? 7 : 5; /* drop cfv[dt]qn bits */
+ if (opt == 0)
+ opt = 1 << 6; /* default: 6 */
+ opt = ffs(opt >> 4); /* Maps -1..-4 to [0], -5 to [1] ... -9 to [5] */
+ max_chain_length = 1 << gzip_level_config[opt].chain_shift;
+ good_match = gzip_level_config[opt].good;
+ max_lazy_match = gzip_level_config[opt].lazy2 * 2;
+ nice_match = gzip_level_config[opt].nice2 * 2;
+#endif
+ option_mask32 &= 0x7; /* retain only -cfv */
/* Allocate all global buffers (for DYN_ALLOC option) */
ALLOC(uch, G1.l_buf, INBUFSIZ);
@@ -2124,5 +2238,6 @@ int gzip_main(int argc UNUSED_PARAM, char **argv)
/* Initialize the CRC32 table */
global_crc32_table = crc32_filltable(NULL, 0);
+ argv += optind;
return bbunpack(argv, pack_gzip, append_ext, "gz");
}
diff --git a/release/src/router/busybox/archival/libarchive/Kbuild.src b/release/src/router/busybox/archival/libarchive/Kbuild.src
index 58457fc220..b159a786a4 100644
--- a/release/src/router/busybox/archival/libarchive/Kbuild.src
+++ b/release/src/router/busybox/archival/libarchive/Kbuild.src
@@ -4,7 +4,7 @@
#
# Licensed under GPLv2 or later, see file LICENSE in this source tree.
-lib-y:=
+lib-y:= common.o
COMMON_FILES:= \
\
@@ -30,39 +30,55 @@ COMMON_FILES:= \
DPKG_FILES:= \
unpack_ar_archive.o \
filter_accept_list_reassign.o \
+ unsafe_prefix.o \
get_header_ar.o \
get_header_tar.o \
get_header_tar_gz.o \
get_header_tar_bz2.o \
get_header_tar_lzma.o \
+ get_header_tar_xz.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) += open_transformer.o decompress_gunzip.o
-lib-$(CONFIG_RPM2CPIO) += decompress_gunzip.o get_header_cpio.o
-lib-$(CONFIG_RPM) += open_transformer.o decompress_gunzip.o get_header_cpio.o
-lib-$(CONFIG_TAR) += get_header_tar.o
-lib-$(CONFIG_UNCOMPRESS) += decompress_uncompress.o
-lib-$(CONFIG_UNZIP) += decompress_gunzip.o
+
+lib-$(CONFIG_AR) += get_header_ar.o unpack_ar_archive.o
+lib-$(CONFIG_CPIO) += get_header_cpio.o
+lib-$(CONFIG_TAR) += get_header_tar.o unsafe_prefix.o
+lib-$(CONFIG_FEATURE_TAR_TO_COMMAND) += data_extract_to_command.o
lib-$(CONFIG_LZOP) += lzo1x_1.o lzo1x_1o.o lzo1x_d.o
lib-$(CONFIG_LZOP_COMPR_HIGH) += lzo1x_9x.o
+lib-$(CONFIG_BUNZIP2) += open_transformer.o decompress_bunzip2.o
+lib-$(CONFIG_UNLZMA) += open_transformer.o decompress_unlzma.o
+lib-$(CONFIG_UNXZ) += open_transformer.o decompress_unxz.o
+lib-$(CONFIG_GUNZIP) += open_transformer.o decompress_gunzip.o
+lib-$(CONFIG_UNCOMPRESS) += open_transformer.o decompress_uncompress.o
+lib-$(CONFIG_UNZIP) += open_transformer.o decompress_gunzip.o unsafe_prefix.o
+lib-$(CONFIG_RPM2CPIO) += open_transformer.o decompress_gunzip.o get_header_cpio.o
+lib-$(CONFIG_RPM) += open_transformer.o decompress_gunzip.o get_header_cpio.o
+
+lib-$(CONFIG_GZIP) += open_transformer.o
+lib-$(CONFIG_BZIP2) += open_transformer.o
+lib-$(CONFIG_LZOP) += open_transformer.o
+lib-$(CONFIG_MAN) += open_transformer.o
+lib-$(CONFIG_SETFONT) += open_transformer.o
+lib-$(CONFIG_FEATURE_2_4_MODULES) += open_transformer.o
lib-$(CONFIG_MODINFO) += open_transformer.o
lib-$(CONFIG_INSMOD) += open_transformer.o
+lib-$(CONFIG_DEPMOD) += open_transformer.o
+lib-$(CONFIG_RMMOD) += open_transformer.o
+lib-$(CONFIG_LSMOD) += open_transformer.o
+lib-$(CONFIG_MODPROBE) += open_transformer.o
+lib-$(CONFIG_MODPROBE_SMALL) += open_transformer.o
+
lib-$(CONFIG_FEATURE_SEAMLESS_Z) += open_transformer.o decompress_uncompress.o
lib-$(CONFIG_FEATURE_SEAMLESS_GZ) += open_transformer.o decompress_gunzip.o
lib-$(CONFIG_FEATURE_SEAMLESS_BZ2) += open_transformer.o decompress_bunzip2.o
lib-$(CONFIG_FEATURE_SEAMLESS_LZMA) += open_transformer.o decompress_unlzma.o
lib-$(CONFIG_FEATURE_SEAMLESS_XZ) += open_transformer.o decompress_unxz.o
lib-$(CONFIG_FEATURE_COMPRESS_USAGE) += open_transformer.o decompress_bunzip2.o
-lib-$(CONFIG_FEATURE_COMPRESS_BBCONFIG) += decompress_bunzip2.o
-lib-$(CONFIG_FEATURE_TAR_TO_COMMAND) += data_extract_to_command.o
+lib-$(CONFIG_FEATURE_COMPRESS_BBCONFIG) += open_transformer.o decompress_bunzip2.o
ifneq ($(lib-y),)
lib-y += $(COMMON_FILES)
diff --git a/release/src/router/busybox/archival/libarchive/bz/compress.c b/release/src/router/busybox/archival/libarchive/bz/compress.c
index e9f1afdaf3..2d994685ce 100644
--- a/release/src/router/busybox/archival/libarchive/bz/compress.c
+++ b/release/src/router/busybox/archival/libarchive/bz/compress.c
@@ -249,7 +249,7 @@ void generateMTFValues(EState* s)
static NOINLINE
void sendMTFValues(EState* s)
{
- int32_t v, t, i, j, gs, ge, totc, bt, bc, iter;
+ int32_t v, t, i, j, gs, ge, bt, bc, iter;
int32_t nSelectors, alphaSize, minLen, maxLen, selCtr;
int32_t nGroups;
@@ -345,7 +345,6 @@ void sendMTFValues(EState* s)
}
#endif
nSelectors = 0;
- totc = 0;
gs = 0;
while (1) {
/*--- Set group start & end marks. --*/
@@ -386,7 +385,6 @@ void sendMTFValues(EState* s)
cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16;
cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16;
cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16;
-
} else
#endif
{
@@ -411,7 +409,6 @@ void sendMTFValues(EState* s)
bt = t;
}
}
- totc += bc;
fave[bt]++;
s->selector[nSelectors] = bt;
nSelectors++;
@@ -501,14 +498,14 @@ void sendMTFValues(EState* s)
for (i = 0; i < 16; i++) {
if (sizeof(long) <= 4) {
inUse16 = inUse16*2 +
- ((*(uint32_t*)&(s->inUse[i * 16 + 0])
- | *(uint32_t*)&(s->inUse[i * 16 + 4])
- | *(uint32_t*)&(s->inUse[i * 16 + 8])
- | *(uint32_t*)&(s->inUse[i * 16 + 12])) != 0);
+ ((*(bb__aliased_uint32_t*)&(s->inUse[i * 16 + 0])
+ | *(bb__aliased_uint32_t*)&(s->inUse[i * 16 + 4])
+ | *(bb__aliased_uint32_t*)&(s->inUse[i * 16 + 8])
+ | *(bb__aliased_uint32_t*)&(s->inUse[i * 16 + 12])) != 0);
} else { /* Our CPU can do better */
inUse16 = inUse16*2 +
- ((*(uint64_t*)&(s->inUse[i * 16 + 0])
- | *(uint64_t*)&(s->inUse[i * 16 + 8])) != 0);
+ ((*(bb__aliased_uint64_t*)&(s->inUse[i * 16 + 0])
+ | *(bb__aliased_uint64_t*)&(s->inUse[i * 16 + 8])) != 0);
}
}
diff --git a/release/src/router/busybox/archival/libarchive/common.c b/release/src/router/busybox/archival/libarchive/common.c
new file mode 100644
index 0000000000..389cb78566
--- /dev/null
+++ b/release/src/router/busybox/archival/libarchive/common.c
@@ -0,0 +1,9 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+#include "libbb.h"
+#include "bb_archive.h"
+
+const char cpio_TRAILER[] ALIGN1 = "TRAILER!!!";
diff --git a/release/src/router/busybox/archival/libarchive/data_extract_all.c b/release/src/router/busybox/archival/libarchive/data_extract_all.c
index 3f67b835fe..bd034afdca 100644
--- a/release/src/router/busybox/archival/libarchive/data_extract_all.c
+++ b/release/src/router/busybox/archival/libarchive/data_extract_all.c
@@ -11,6 +11,12 @@ 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;
+ char *hard_link;
+#if ENABLE_FEATURE_TAR_LONG_OPTIONS
+ char *dst_name;
+#else
+# define dst_name (file_header->name)
+#endif
#if ENABLE_FEATURE_TAR_SELINUX
char *sctx = archive_handle->tar__sctx[PAX_NEXT_FILE];
@@ -23,11 +29,49 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
}
#endif
+ /* Hard links are encoded as regular files of size 0
+ * with a nonempty link field */
+ hard_link = NULL;
+ if (S_ISREG(file_header->mode) && file_header->size == 0)
+ hard_link = file_header->link_target;
+
+#if ENABLE_FEATURE_TAR_LONG_OPTIONS
+ dst_name = file_header->name;
+ if (archive_handle->tar__strip_components) {
+ unsigned n = archive_handle->tar__strip_components;
+ do {
+ dst_name = strchr(dst_name, '/');
+ if (!dst_name || dst_name[1] == '\0') {
+ data_skip(archive_handle);
+ goto ret;
+ }
+ dst_name++;
+ /*
+ * Link target is shortened only for hardlinks:
+ * softlinks restored unchanged.
+ */
+ if (hard_link) {
+// GNU tar 1.26 does not check that we reached end of link name:
+// if "dir/hardlink" is hardlinked to "file",
+// tar xvf a.tar --strip-components=1 says:
+// tar: hardlink: Cannot hard link to '': No such file or directory
+// and continues processing. We silently skip such entries.
+ hard_link = strchr(hard_link, '/');
+ if (!hard_link || hard_link[1] == '\0') {
+ data_skip(archive_handle);
+ goto ret;
+ }
+ hard_link++;
+ }
+ } while (--n != 0);
+ }
+#endif
+
if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) {
- char *slash = strrchr(file_header->name, '/');
+ char *slash = strrchr(dst_name, '/');
if (slash) {
*slash = '\0';
- bb_make_directory(file_header->name, -1, FILEUTILS_RECUR);
+ bb_make_directory(dst_name, -1, FILEUTILS_RECUR);
*slash = '/';
}
}
@@ -35,12 +79,7 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
if (archive_handle->ah_flags & ARCHIVE_UNLINK_OLD) {
/* Remove the entry if it exists */
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
- ) {
+ if (hard_link) {
/* Ugly special case:
* tar cf t.tar hardlink1 hardlink2 hardlink1
* results in this tarball structure:
@@ -48,22 +87,22 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
* hardlink2 -> hardlink1
* hardlink1 -> hardlink1 <== !!!
*/
- if (strcmp(file_header->link_target, file_header->name) == 0)
+ if (strcmp(hard_link, dst_name) == 0)
goto ret;
}
/* Proceed with deleting */
- if (unlink(file_header->name) == -1
+ if (unlink(dst_name) == -1
&& errno != ENOENT
) {
bb_perror_msg_and_die("can't remove old file %s",
- file_header->name);
+ dst_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) {
+ if (lstat(dst_name, &existing_sb) == -1) {
if (errno != ENOENT) {
bb_perror_msg_and_die("can't stat old file");
}
@@ -73,30 +112,25 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
&& !S_ISDIR(file_header->mode)
) {
bb_error_msg("%s not created: newer or "
- "same age file exists", file_header->name);
+ "same age file exists", dst_name);
}
data_skip(archive_handle);
goto ret;
}
- else if ((unlink(file_header->name) == -1) && (errno != EISDIR)) {
+ else if ((unlink(dst_name) == -1) && (errno != EISDIR)) {
bb_perror_msg_and_die("can't remove old file %s",
- file_header->name);
+ dst_name);
}
}
- /* Handle hard links separately
- * 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)) {
+ /* Handle hard links separately */
+ if (hard_link) {
+ res = link(hard_link, dst_name);
+ if (res != 0 && !(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);
+ dst_name,
+ hard_link);
}
/* Hardlinks have no separate mode/ownership, skip chown/chmod */
goto ret;
@@ -106,37 +140,50 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
switch (file_header->mode & S_IFMT) {
case S_IFREG: {
/* Regular file */
+ char *dst_nameN;
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,
+ dst_nameN = dst_name;
+#ifdef ARCHIVE_REPLACE_VIA_RENAME
+ if (archive_handle->ah_flags & ARCHIVE_REPLACE_VIA_RENAME)
+ /* rpm-style temp file name */
+ dst_nameN = xasprintf("%s;%x", dst_name, (int)getpid());
+#endif
+ dst_fd = xopen3(dst_nameN,
flags,
file_header->mode
);
bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size);
close(dst_fd);
+#ifdef ARCHIVE_REPLACE_VIA_RENAME
+ if (archive_handle->ah_flags & ARCHIVE_REPLACE_VIA_RENAME) {
+ xrename(dst_nameN, dst_name);
+ free(dst_nameN);
+ }
+#endif
break;
}
case S_IFDIR:
- res = mkdir(file_header->name, file_header->mode);
+ res = mkdir(dst_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);
+ bb_perror_msg("can't make dir %s", dst_name);
}
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)
+ res = symlink(file_header->link_target, dst_name);
+ if (res != 0
&& !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
) {
bb_perror_msg("can't create %slink "
"from %s to %s", "sym",
- file_header->name,
+ dst_name,
file_header->link_target);
}
break;
@@ -144,11 +191,11 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
case S_IFBLK:
case S_IFCHR:
case S_IFIFO:
- res = mknod(file_header->name, file_header->mode, file_header->device);
+ res = mknod(dst_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);
+ bb_perror_msg("can't create node %s", dst_name);
}
break;
default:
@@ -173,20 +220,20 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
}
#endif
/* GNU tar 1.15.1 uses chown, not lchown */
- chown(file_header->name, uid, gid);
+ chown(dst_name, uid, gid);
}
/* 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);
+ chmod(dst_name, file_header->mode);
}
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);
+ utimes(dst_name, t);
}
}
diff --git a/release/src/router/busybox/archival/libarchive/data_extract_to_command.c b/release/src/router/busybox/archival/libarchive/data_extract_to_command.c
index a2ce33b51f..5d8769382f 100644
--- a/release/src/router/busybox/archival/libarchive/data_extract_to_command.c
+++ b/release/src/router/busybox/archival/libarchive/data_extract_to_command.c
@@ -103,7 +103,7 @@ void FAST_FUNC data_extract_to_command(archive_handle_t *archive_handle)
archive_handle->tar__to_command_shell,
"-c",
archive_handle->tar__to_command,
- NULL);
+ (char *)0);
bb_perror_msg_and_die("can't execute '%s'", archive_handle->tar__to_command_shell);
}
close(p[0]);
@@ -112,13 +112,12 @@ void FAST_FUNC data_extract_to_command(archive_handle_t *archive_handle)
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");
+ status = wait_for_exitstatus(pid);
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",
+ bb_error_msg_and_die("'%s' terminated by signal %d",
archive_handle->tar__to_command, WTERMSIG(status));
if (!BB_MMU) {
diff --git a/release/src/router/busybox/archival/libarchive/decompress_bunzip2.c b/release/src/router/busybox/archival/libarchive/decompress_bunzip2.c
index dc252bb822..fe5953da24 100644
--- a/release/src/router/busybox/archival/libarchive/decompress_bunzip2.c
+++ b/release/src/router/busybox/archival/libarchive/decompress_bunzip2.c
@@ -42,6 +42,12 @@
#include "libbb.h"
#include "bb_archive.h"
+#if 0
+# define dbg(...) bb_error_msg(__VA_ARGS__)
+#else
+# define dbg(...) ((void)0)
+#endif
+
/* Constants for Huffman coding */
#define MAX_GROUPS 6
#define GROUP_SIZE 50 /* 64 would have been more efficient */
@@ -52,13 +58,13 @@
/* Status return values */
#define RETVAL_OK 0
-#define RETVAL_LAST_BLOCK (-1)
-#define RETVAL_NOT_BZIP_DATA (-2)
-#define RETVAL_UNEXPECTED_INPUT_EOF (-3)
-#define RETVAL_SHORT_WRITE (-4)
-#define RETVAL_DATA_ERROR (-5)
-#define RETVAL_OUT_OF_MEMORY (-6)
-#define RETVAL_OBSOLETE_INPUT (-7)
+#define RETVAL_LAST_BLOCK (dbg("%d", __LINE__), -1)
+#define RETVAL_NOT_BZIP_DATA (dbg("%d", __LINE__), -2)
+#define RETVAL_UNEXPECTED_INPUT_EOF (dbg("%d", __LINE__), -3)
+#define RETVAL_SHORT_WRITE (dbg("%d", __LINE__), -4)
+#define RETVAL_DATA_ERROR (dbg("%d", __LINE__), -5)
+#define RETVAL_OUT_OF_MEMORY (dbg("%d", __LINE__), -6)
+#define RETVAL_OBSOLETE_INPUT (dbg("%d", __LINE__), -7)
/* Other housekeeping constants */
#define IOBUF_SIZE 4096
@@ -440,7 +446,11 @@ static int get_next_block(bunzip_data *bd)
literal used is the one at the head of the mtfSymbol array.) */
if (runPos != 0) {
uint8_t tmp_byte;
- if (dbufCount + runCnt >= dbufSize) return RETVAL_DATA_ERROR;
+ if (dbufCount + runCnt > dbufSize) {
+ dbg("dbufCount:%d+runCnt:%d %d > dbufSize:%d RETVAL_DATA_ERROR",
+ dbufCount, runCnt, dbufCount + runCnt, dbufSize);
+ return RETVAL_DATA_ERROR;
+ }
tmp_byte = symToByte[mtfSymbol[0]];
byteCount[tmp_byte] += runCnt;
while (--runCnt >= 0) dbuf[dbufCount++] = (uint32_t)tmp_byte;
@@ -721,7 +731,7 @@ void FAST_FUNC dealloc_bunzip(bunzip_data *bd)
/* Decompress src_fd to dst_fd. Stops at end of bzip data, not end of file. */
IF_DESKTOP(long long) int FAST_FUNC
-unpack_bz2_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
+unpack_bz2_stream(transformer_state_t *xstate)
{
IF_DESKTOP(long long total_written = 0;)
bunzip_data *bd;
@@ -729,14 +739,14 @@ unpack_bz2_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
int i;
unsigned len;
- if (check_signature16(aux, src_fd, BZIP2_MAGIC))
+ if (check_signature16(xstate, BZIP2_MAGIC))
return -1;
outbuf = xmalloc(IOBUF_SIZE);
len = 0;
while (1) { /* "Process one BZ... stream" loop */
- i = start_bunzip(&bd, src_fd, outbuf + 2, len);
+ i = start_bunzip(&bd, xstate->src_fd, outbuf + 2, len);
if (i == 0) {
while (1) { /* "Produce some output bytes" loop */
@@ -746,8 +756,7 @@ unpack_bz2_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
i = IOBUF_SIZE - i; /* number of bytes produced */
if (i == 0) /* EOF? */
break;
- if (i != full_write(dst_fd, outbuf, i)) {
- bb_error_msg("short write");
+ if (i != transformer_write(xstate, outbuf, i)) {
i = RETVAL_SHORT_WRITE;
goto release_mem;
}
@@ -780,7 +789,7 @@ unpack_bz2_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
len = bd->inbufCount - bd->inbufPos;
memcpy(outbuf, &bd->inbuf[bd->inbufPos], len);
if (len < 2) {
- if (safe_read(src_fd, outbuf + len, 2 - len) != 2 - len)
+ if (safe_read(xstate->src_fd, outbuf + len, 2 - len) != 2 - len)
break;
len = 2;
}
@@ -808,7 +817,6 @@ static char *const bunzip_errors[] = {
/* Dumb little test thing, decompress stdin to stdout */
int main(int argc, char **argv)
{
- int i;
char c;
int i = unpack_bz2_stream(0, 1);
diff --git a/release/src/router/busybox/archival/libarchive/decompress_gunzip.c b/release/src/router/busybox/archival/libarchive/decompress_gunzip.c
index 2d5ab3eb3f..c7fa5b5263 100644
--- a/release/src/router/busybox/archival/libarchive/decompress_gunzip.c
+++ b/release/src/router/busybox/archival/libarchive/decompress_gunzip.c
@@ -293,8 +293,8 @@ static unsigned fill_bitbuffer(STATE_PARAM unsigned bitbuffer, unsigned *current
* m: maximum lookup bits, returns actual
*/
static int huft_build(const unsigned *b, const unsigned n,
- const unsigned s, const unsigned short *d,
- const unsigned char *e, huft_t **t, unsigned *m)
+ const unsigned s, const unsigned short *d,
+ const unsigned char *e, huft_t **t, unsigned *m)
{
unsigned a; /* counter for codes of length k */
unsigned c[BMAX + 1]; /* bit length count table */
@@ -305,11 +305,11 @@ static int huft_build(const unsigned *b, const unsigned n,
unsigned i; /* counter, current code */
unsigned j; /* counter */
int k; /* number of bits in current code */
- unsigned *p; /* pointer into c[], b[], or v[] */
+ const unsigned *p; /* pointer into c[], b[], or v[] */
huft_t *q; /* points to current table */
huft_t r; /* table entry for structure assignment */
huft_t *u[BMAX]; /* table stack */
- unsigned v[N_MAX]; /* values in order of bit length */
+ unsigned v[N_MAX + 1]; /* values in order of bit length. last v[] is never used */
int ws[BMAX + 1]; /* bits decoded stack */
int w; /* bits decoded */
unsigned x[BMAX + 1]; /* bit offsets, then code stack */
@@ -324,7 +324,7 @@ static int huft_build(const unsigned *b, const unsigned n,
/* Generate counts for each bit length */
memset(c, 0, sizeof(c));
- p = (unsigned *) b; /* cast allows us to reuse p for pointing to b */
+ p = b;
i = n;
do {
c[*p]++; /* assume all entries <= BMAX */
@@ -336,7 +336,7 @@ static int huft_build(const unsigned *b, const unsigned n,
}
/* Find minimum and maximum length, bound *m by those */
- for (j = 1; (c[j] == 0) && (j <= BMAX); j++)
+ for (j = 1; (j <= BMAX) && (c[j] == 0); j++)
continue;
k = j; /* minimum code length */
for (i = BMAX; (c[i] == 0) && i; i--)
@@ -364,8 +364,12 @@ static int huft_build(const unsigned *b, const unsigned n,
*xp++ = j;
}
- /* Make a table of values in order of bit lengths */
- p = (unsigned *) b;
+ /* Make a table of values in order of bit lengths.
+ * To detect bad input, unused v[i]'s are set to invalid value UINT_MAX.
+ * In particular, last v[i] is never filled and must not be accessed.
+ */
+ memset(v, 0xff, sizeof(v));
+ p = b;
i = 0;
do {
j = *p++;
@@ -432,7 +436,9 @@ static int huft_build(const unsigned *b, const unsigned n,
/* set up table entry in r */
r.b = (unsigned char) (k - w);
- if (p >= v + n) {
+ if (/*p >= v + n || -- redundant, caught by the second check: */
+ *p == UINT_MAX /* do we access uninited v[i]? (see memset(v))*/
+ ) {
r.e = 99; /* out of values--invalid code */
} else if (*p < s) {
r.e = (unsigned char) (*p < 256 ? 16 : 15); /* 256 is EOB code */
@@ -517,8 +523,9 @@ static NOINLINE int inflate_codes(STATE_PARAM_ONLY)
e = t->e;
if (e > 16)
do {
- if (e == 99)
- abort_unzip(PASS_STATE_ONLY);;
+ if (e == 99) {
+ abort_unzip(PASS_STATE_ONLY);
+ }
bb >>= t->b;
k -= t->b;
e -= 16;
@@ -554,8 +561,9 @@ static NOINLINE int inflate_codes(STATE_PARAM_ONLY)
e = t->e;
if (e > 16)
do {
- if (e == 99)
+ if (e == 99) {
abort_unzip(PASS_STATE_ONLY);
+ }
bb >>= t->b;
k -= t->b;
e -= 16;
@@ -821,8 +829,9 @@ static int inflate_block(STATE_PARAM smallint *e)
b_dynamic >>= 4;
k_dynamic -= 4;
- if (nl > 286 || nd > 30)
+ if (nl > 286 || nd > 30) {
abort_unzip(PASS_STATE_ONLY); /* bad lengths */
+ }
/* read in bit-length-code lengths */
for (j = 0; j < nb; j++) {
@@ -903,12 +912,14 @@ static int inflate_block(STATE_PARAM smallint *e)
bl = lbits;
i = huft_build(ll, nl, 257, cplens, cplext, &inflate_codes_tl, &bl);
- if (i != 0)
+ if (i != 0) {
abort_unzip(PASS_STATE_ONLY);
+ }
bd = dbits;
i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &inflate_codes_td, &bd);
- if (i != 0)
+ if (i != 0) {
abort_unzip(PASS_STATE_ONLY);
+ }
/* set up data for inflate_codes() */
inflate_codes_setup(PASS_STATE bl, bd);
@@ -971,7 +982,7 @@ static int inflate_get_next_window(STATE_PARAM_ONLY)
/* Called from unpack_gz_stream() and inflate_unzip() */
static IF_DESKTOP(long long) int
-inflate_unzip_internal(STATE_PARAM int in, int out)
+inflate_unzip_internal(STATE_PARAM transformer_state_t *xstate)
{
IF_DESKTOP(long long) int n = 0;
ssize_t nwrote;
@@ -980,7 +991,7 @@ inflate_unzip_internal(STATE_PARAM int in, int out)
gunzip_window = xmalloc(GUNZIP_WSIZE);
gunzip_outbuf_count = 0;
gunzip_bytes_out = 0;
- gunzip_src_fd = in;
+ gunzip_src_fd = xstate->src_fd;
/* (re) initialize state */
method = -1;
@@ -996,15 +1007,15 @@ inflate_unzip_internal(STATE_PARAM int in, int out)
error_msg = "corrupted data";
if (setjmp(error_jmp)) {
/* Error from deep inside zip machinery */
+ bb_error_msg(error_msg);
n = -1;
goto ret;
}
while (1) {
int r = inflate_get_next_window(PASS_STATE_ONLY);
- nwrote = full_write(out, gunzip_window, gunzip_outbuf_count);
- if (nwrote != (ssize_t)gunzip_outbuf_count) {
- bb_perror_msg("write");
+ nwrote = transformer_write(xstate, gunzip_window, gunzip_outbuf_count);
+ if (nwrote == (ssize_t)-1) {
n = -1;
goto ret;
}
@@ -1034,22 +1045,22 @@ inflate_unzip_internal(STATE_PARAM int in, int out)
/* For unzip */
IF_DESKTOP(long long) int FAST_FUNC
-inflate_unzip(transformer_aux_data_t *aux, int in, int out)
+inflate_unzip(transformer_state_t *xstate)
{
IF_DESKTOP(long long) int n;
DECLARE_STATE;
ALLOC_STATE;
- to_read = aux->bytes_in;
+ to_read = xstate->bytes_in;
// bytebuffer_max = 0x8000;
bytebuffer_offset = 4;
bytebuffer = xmalloc(bytebuffer_max);
- n = inflate_unzip_internal(PASS_STATE in, out);
+ n = inflate_unzip_internal(PASS_STATE xstate);
free(bytebuffer);
- aux->crc32 = gunzip_crc;
- aux->bytes_out = gunzip_bytes_out;
+ xstate->crc32 = gunzip_crc;
+ xstate->bytes_out = gunzip_bytes_out;
DEALLOC_STATE;
return n;
}
@@ -1107,7 +1118,7 @@ static uint32_t buffer_read_le_u32(STATE_PARAM_ONLY)
return res;
}
-static int check_header_gzip(STATE_PARAM transformer_aux_data_t *aux)
+static int check_header_gzip(STATE_PARAM transformer_state_t *xstate)
{
union {
unsigned char raw[8];
@@ -1119,9 +1130,8 @@ static int check_header_gzip(STATE_PARAM transformer_aux_data_t *aux)
uint8_t os_flags_UNUSED;
} PACKED formatted;
} header;
- struct BUG_header {
- char BUG_header[sizeof(header) == 8 ? 1 : -1];
- };
+
+ BUILD_BUG_ON(sizeof(header) != 8);
/*
* Rewind bytebuffer. We use the beginning because the header has 8
@@ -1169,8 +1179,7 @@ static int check_header_gzip(STATE_PARAM transformer_aux_data_t *aux)
}
}
- if (aux)
- aux->mtime = SWAP_LE32(header.formatted.mtime);
+ xstate->mtime = SWAP_LE32(header.formatted.mtime);
/* Read the header checksum */
if (header.formatted.flags & 0x02) {
@@ -1182,27 +1191,27 @@ static int check_header_gzip(STATE_PARAM transformer_aux_data_t *aux)
}
IF_DESKTOP(long long) int FAST_FUNC
-unpack_gz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
+unpack_gz_stream(transformer_state_t *xstate)
{
uint32_t v32;
IF_DESKTOP(long long) int total, n;
DECLARE_STATE;
#if !ENABLE_FEATURE_SEAMLESS_Z
- if (check_signature16(aux, src_fd, GZIP_MAGIC))
+ if (check_signature16(xstate, GZIP_MAGIC))
return -1;
#else
- if (aux && aux->check_signature) {
+ if (!xstate->signature_skipped) {
uint16_t magic2;
- if (full_read(src_fd, &magic2, 2) != 2) {
+ if (full_read(xstate->src_fd, &magic2, 2) != 2) {
bad_magic:
bb_error_msg("invalid magic");
return -1;
}
if (magic2 == COMPRESS_MAGIC) {
- aux->check_signature = 0;
- return unpack_Z_stream(aux, src_fd, dst_fd);
+ xstate->signature_skipped = 2;
+ return unpack_Z_stream(xstate);
}
if (magic2 != GZIP_MAGIC)
goto bad_magic;
@@ -1215,16 +1224,16 @@ unpack_gz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
to_read = -1;
// bytebuffer_max = 0x8000;
bytebuffer = xmalloc(bytebuffer_max);
- gunzip_src_fd = src_fd;
+ gunzip_src_fd = xstate->src_fd;
again:
- if (!check_header_gzip(PASS_STATE aux)) {
+ if (!check_header_gzip(PASS_STATE xstate)) {
bb_error_msg("corrupted data");
total = -1;
goto ret;
}
- n = inflate_unzip_internal(PASS_STATE src_fd, dst_fd);
+ n = inflate_unzip_internal(PASS_STATE xstate);
if (n < 0) {
total = -1;
goto ret;
diff --git a/release/src/router/busybox/archival/libarchive/decompress_uncompress.c b/release/src/router/busybox/archival/libarchive/decompress_uncompress.c
index e9bbfb9bd8..034ed502d7 100644
--- a/release/src/router/busybox/archival/libarchive/decompress_uncompress.c
+++ b/release/src/router/busybox/archival/libarchive/decompress_uncompress.c
@@ -73,12 +73,11 @@
*/
IF_DESKTOP(long long) int FAST_FUNC
-unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
+unpack_Z_stream(transformer_state_t *xstate)
{
IF_DESKTOP(long long total_written = 0;)
IF_DESKTOP(long long) int retval = -1;
unsigned char *stackp;
- long code;
int finchar;
long oldcode;
long incode;
@@ -103,7 +102,7 @@ unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
/* block compress mode -C compatible with 2.0 */
int block_mode; /* = BLOCK_MODE; */
- if (check_signature16(aux, src_fd, COMPRESS_MAGIC))
+ if (check_signature16(xstate, COMPRESS_MAGIC))
return -1;
inbuf = xzalloc(IBUFSIZ + 64);
@@ -115,7 +114,7 @@ unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
/* xread isn't good here, we have to return - caller may want
* to do some cleanup (e.g. delete incomplete unpacked file etc) */
- if (full_read(src_fd, inbuf, 1) != 1) {
+ if (full_read(xstate->src_fd, inbuf, 1) != 1) {
bb_error_msg("short read");
goto err;
}
@@ -143,8 +142,10 @@ unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
/* As above, initialize the first 256 entries in the table. */
/*clear_tab_prefixof(); - done by xzalloc */
- for (code = 255; code >= 0; --code) {
- tab_suffixof(code) = (unsigned char) code;
+ {
+ int i;
+ for (i = 255; i >= 0; --i)
+ tab_suffixof(i) = (unsigned char) i;
}
do {
@@ -165,7 +166,7 @@ unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
}
if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) {
- rsize = safe_read(src_fd, inbuf + insize, IBUFSIZ);
+ rsize = safe_read(xstate->src_fd, inbuf + insize, IBUFSIZ);
if (rsize < 0)
bb_error_msg_and_die(bb_msg_read_error);
insize += rsize;
@@ -175,6 +176,8 @@ unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
(insize << 3) - (n_bits - 1));
while (inbits > posbits) {
+ long code;
+
if (free_ent > maxcode) {
posbits =
((posbits - 1) +
@@ -191,13 +194,12 @@ unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
}
{
unsigned char *p = &inbuf[posbits >> 3];
-
- code = ((((long) (p[0])) | ((long) (p[1]) << 8) |
- ((long) (p[2]) << 16)) >> (posbits & 0x7)) & bitmask;
+ code = ((p[0]
+ | ((long) (p[1]) << 8)
+ | ((long) (p[2]) << 16)) >> (posbits & 0x7)) & bitmask;
}
posbits += n_bits;
-
if (oldcode == -1) {
if (code >= 256)
bb_error_msg_and_die("corrupted data"); /* %ld", code); */
@@ -226,15 +228,16 @@ unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
/* Special case for KwKwK string. */
if (code >= free_ent) {
if (code > free_ent) {
+/*
unsigned char *p;
posbits -= n_bits;
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));
+ insize, posbits, p[-1], p[0], p[1], p[2], p[3],
+ (posbits & 07));
+*/
bb_error_msg("corrupted data");
goto err;
}
@@ -244,7 +247,7 @@ unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
}
/* Generate output characters in reverse order */
- while ((long) code >= (long) 256) {
+ while (code >= 256) {
if (stackp <= &htabof(0))
bb_error_msg_and_die("corrupted data");
*--stackp = tab_suffixof(code);
@@ -271,7 +274,7 @@ unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
}
if (outpos >= OBUFSIZ) {
- xwrite(dst_fd, outbuf, outpos);
+ xtransformer_write(xstate, outbuf, outpos);
IF_DESKTOP(total_written += outpos;)
outpos = 0;
}
@@ -285,21 +288,19 @@ unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
}
/* Generate the new entry. */
- code = free_ent;
- if (code < maxmaxcode) {
- tab_prefixof(code) = (unsigned short) oldcode;
- tab_suffixof(code) = (unsigned char) finchar;
- free_ent = code + 1;
+ if (free_ent < maxmaxcode) {
+ tab_prefixof(free_ent) = (unsigned short) oldcode;
+ tab_suffixof(free_ent) = (unsigned char) finchar;
+ free_ent++;
}
/* Remember previous code. */
oldcode = incode;
}
-
} while (rsize > 0);
if (outpos > 0) {
- xwrite(dst_fd, outbuf, outpos);
+ xtransformer_write(xstate, outbuf, outpos);
IF_DESKTOP(total_written += outpos;)
}
diff --git a/release/src/router/busybox/archival/libarchive/decompress_unlzma.c b/release/src/router/busybox/archival/libarchive/decompress_unlzma.c
index cfde8ea56e..c8622f97b3 100644
--- a/release/src/router/busybox/archival/libarchive/decompress_unlzma.c
+++ b/release/src/router/busybox/archival/libarchive/decompress_unlzma.c
@@ -45,16 +45,16 @@ typedef struct {
#define RC_MODEL_TOTAL_BITS 11
-/* Called twice: once at startup (LZMA_FAST only) and once in rc_normalize() */
-static size_inline void rc_read(rc_t *rc)
+/* Called once in rc_do_normalize() */
+static void rc_read(rc_t *rc)
{
int buffer_size = safe_read(rc->fd, RC_BUFFER, RC_BUFFER_SIZE);
//TODO: return -1 instead
//This will make unlzma delete broken unpacked file on unpack errors
if (buffer_size <= 0)
bb_error_msg_and_die("unexpected EOF");
- rc->ptr = RC_BUFFER;
rc->buffer_end = RC_BUFFER + buffer_size;
+ rc->ptr = RC_BUFFER;
}
/* Called twice, but one callsite is in speed_inline'd rc_is_bit_1() */
@@ -65,6 +65,12 @@ static void rc_do_normalize(rc_t *rc)
rc->range <<= 8;
rc->code = (rc->code << 8) | *rc->ptr++;
}
+static ALWAYS_INLINE void rc_normalize(rc_t *rc)
+{
+ if (rc->range < (1 << RC_TOP_BITS)) {
+ rc_do_normalize(rc);
+ }
+}
/* Called once */
static ALWAYS_INLINE rc_t* rc_init(int fd) /*, int buffer_size) */
@@ -78,15 +84,9 @@ static ALWAYS_INLINE rc_t* rc_init(int fd) /*, int buffer_size) */
/* rc->ptr = rc->buffer_end; */
for (i = 0; i < 5; i++) {
-#if ENABLE_FEATURE_LZMA_FAST
- if (rc->ptr >= rc->buffer_end)
- rc_read(rc);
- rc->code = (rc->code << 8) | *rc->ptr++;
-#else
rc_do_normalize(rc);
-#endif
}
- rc->range = 0xFFFFFFFF;
+ rc->range = 0xffffffff;
return rc;
}
@@ -96,13 +96,6 @@ static ALWAYS_INLINE void rc_free(rc_t *rc)
free(rc);
}
-static ALWAYS_INLINE void rc_normalize(rc_t *rc)
-{
- if (rc->range < (1 << RC_TOP_BITS)) {
- rc_do_normalize(rc);
- }
-}
-
/* rc_is_bit_1 is called 9 times */
static speed_inline int rc_is_bit_1(rc_t *rc, uint16_t *p)
{
@@ -120,7 +113,7 @@ static speed_inline int rc_is_bit_1(rc_t *rc, uint16_t *p)
}
/* Called 4 times in unlzma loop */
-static speed_inline int rc_get_bit(rc_t *rc, uint16_t *p, int *symbol)
+static ALWAYS_INLINE int rc_get_bit(rc_t *rc, uint16_t *p, int *symbol)
{
int ret = rc_is_bit_1(rc, p);
*symbol = *symbol * 2 + ret;
@@ -213,7 +206,7 @@ enum {
IF_DESKTOP(long long) int FAST_FUNC
-unpack_lzma_stream(transformer_aux_data_t *aux UNUSED_PARAM, int src_fd, int dst_fd)
+unpack_lzma_stream(transformer_state_t *xstate)
{
IF_DESKTOP(long long total_written = 0;)
lzma_header_t header;
@@ -221,8 +214,6 @@ unpack_lzma_stream(transformer_aux_data_t *aux UNUSED_PARAM, int src_fd, int dst
uint32_t pos_state_mask;
uint32_t literal_pos_mask;
uint16_t *p;
- int num_bits;
- int num_probs;
rc_t *rc;
int i;
uint8_t *buffer;
@@ -232,7 +223,7 @@ unpack_lzma_stream(transformer_aux_data_t *aux UNUSED_PARAM, int src_fd, int dst
int state = 0;
uint32_t rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
- if (full_read(src_fd, &header, sizeof(header)) != sizeof(header)
+ if (full_read(xstate->src_fd, &header, sizeof(header)) != sizeof(header)
|| header.pos >= (9 * 5 * 5)
) {
bb_error_msg("bad lzma header");
@@ -246,6 +237,9 @@ unpack_lzma_stream(transformer_aux_data_t *aux UNUSED_PARAM, int src_fd, int dst
pos_state_mask = (1 << pb) - 1;
literal_pos_mask = (1 << lp) - 1;
+ /* Example values from linux-3.3.4.tar.lzma:
+ * dict_size: 64M, dst_size: 2^64-1
+ */
header.dict_size = SWAP_LE32(header.dict_size);
header.dst_size = SWAP_LE64(header.dst_size);
@@ -254,13 +248,17 @@ unpack_lzma_stream(transformer_aux_data_t *aux UNUSED_PARAM, int src_fd, int dst
buffer = xmalloc(MIN(header.dst_size, header.dict_size));
- num_probs = LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp));
- p = xmalloc(num_probs * sizeof(*p));
- num_probs += LZMA_LITERAL - LZMA_BASE_SIZE;
- for (i = 0; i < num_probs; i++)
- p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1;
+ {
+ int num_probs;
+
+ num_probs = LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp));
+ p = xmalloc(num_probs * sizeof(*p));
+ num_probs += LZMA_LITERAL - LZMA_BASE_SIZE;
+ for (i = 0; i < num_probs; i++)
+ p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1;
+ }
- rc = rc_init(src_fd); /*, RC_BUFFER_SIZE); */
+ rc = rc_init(xstate->src_fd); /*, RC_BUFFER_SIZE); */
while (global_pos + buffer_pos < header.dst_size) {
int pos_state = (buffer_pos + global_pos) & pos_state_mask;
@@ -308,7 +306,7 @@ unpack_lzma_stream(transformer_aux_data_t *aux UNUSED_PARAM, int src_fd, int dst
if (buffer_pos == header.dict_size) {
buffer_pos = 0;
global_pos += header.dict_size;
- if (full_write(dst_fd, buffer, header.dict_size) != (ssize_t)header.dict_size)
+ if (transformer_write(xstate, buffer, header.dict_size) != (ssize_t)header.dict_size)
goto bad;
IF_DESKTOP(total_written += header.dict_size;)
}
@@ -317,6 +315,7 @@ unpack_lzma_stream(transformer_aux_data_t *aux UNUSED_PARAM, int src_fd, int dst
goto one_byte2;
#endif
} else {
+ int num_bits;
int offset;
uint16_t *prob2;
#define prob_len prob2
@@ -441,19 +440,22 @@ unpack_lzma_stream(transformer_aux_data_t *aux UNUSED_PARAM, int src_fd, int dst
if (buffer_pos == header.dict_size) {
buffer_pos = 0;
global_pos += header.dict_size;
- if (full_write(dst_fd, buffer, header.dict_size) != (ssize_t)header.dict_size)
+ if (transformer_write(xstate, buffer, header.dict_size) != (ssize_t)header.dict_size)
goto bad;
IF_DESKTOP(total_written += header.dict_size;)
}
len--;
} while (len != 0 && buffer_pos < header.dst_size);
+ /* FIXME: ...........^^^^^
+ * shouldn't it be "global_pos + buffer_pos < header.dst_size"?
+ */
}
}
{
IF_NOT_DESKTOP(int total_written = 0; /* success */)
IF_DESKTOP(total_written += buffer_pos;)
- if (full_write(dst_fd, buffer, buffer_pos) != (ssize_t)buffer_pos) {
+ if (transformer_write(xstate, buffer, buffer_pos) != (ssize_t)buffer_pos) {
bad:
total_written = -1; /* failure */
}
diff --git a/release/src/router/busybox/archival/libarchive/decompress_unxz.c b/release/src/router/busybox/archival/libarchive/decompress_unxz.c
index 79b48a152e..cd32cc745c 100644
--- a/release/src/router/busybox/archival/libarchive/decompress_unxz.c
+++ b/release/src/router/busybox/archival/libarchive/decompress_unxz.c
@@ -30,16 +30,17 @@ static uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t 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))
+#define put_unaligned_le32(val, buf) move_to_unaligned32(buf, SWAP_LE32(val))
+#define put_unaligned_be32(val, buf) move_to_unaligned32(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(transformer_aux_data_t *aux, int src_fd, int dst_fd)
+unpack_xz_stream(transformer_state_t *xstate)
{
+ enum xz_ret xz_result;
struct xz_buf iobuf;
struct xz_dec *state;
unsigned char *membuf;
@@ -54,7 +55,7 @@ unpack_xz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
iobuf.out = membuf + BUFSIZ;
iobuf.out_size = BUFSIZ;
- if (!aux || aux->check_signature == 0) {
+ if (!xstate || xstate->signature_skipped) {
/* Preload XZ file signature */
strcpy((char*)membuf, HEADER_MAGIC);
iobuf.in_size = HEADER_MAGIC_SIZE;
@@ -63,38 +64,66 @@ unpack_xz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
/* Limit memory usage to about 64 MiB. */
state = xz_dec_init(XZ_DYNALLOC, 64*1024*1024);
+ xz_result = X_OK;
while (1) {
- enum xz_ret r;
-
if (iobuf.in_pos == iobuf.in_size) {
- int rd = safe_read(src_fd, membuf, BUFSIZ);
+ int rd = safe_read(xstate->src_fd, membuf, BUFSIZ);
if (rd < 0) {
bb_error_msg(bb_msg_read_error);
total = -1;
break;
}
+ if (rd == 0 && xz_result == XZ_STREAM_END)
+ break;
iobuf.in_size = rd;
iobuf.in_pos = 0;
}
+ if (xz_result == XZ_STREAM_END) {
+ /*
+ * Try to start decoding next concatenated stream.
+ * Stream padding must always be a multiple of four
+ * bytes to preserve four-byte alignment. To keep the
+ * code slightly smaller, we aren't as strict here as
+ * the .xz spec requires. We just skip all zero-bytes
+ * without checking the alignment and thus can accept
+ * files that aren't valid, e.g. the XZ utils test
+ * files bad-0pad-empty.xz and bad-0catpad-empty.xz.
+ */
+ do {
+ if (membuf[iobuf.in_pos] != 0) {
+ xz_dec_reset(state);
+ goto do_run;
+ }
+ iobuf.in_pos++;
+ } while (iobuf.in_pos < iobuf.in_size);
+ }
+ do_run:
// 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);
+ xz_result = 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);
+// iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size, xz_result);
if (iobuf.out_pos) {
- xwrite(dst_fd, iobuf.out, iobuf.out_pos);
+ xtransformer_write(xstate, iobuf.out, iobuf.out_pos);
IF_DESKTOP(total += iobuf.out_pos;)
iobuf.out_pos = 0;
}
- if (r == XZ_STREAM_END) {
- break;
+ if (xz_result == XZ_STREAM_END) {
+ /*
+ * Can just "break;" here, if not for concatenated
+ * .xz streams.
+ * Checking for padding may require buffer
+ * replenishment. Can't do it here.
+ */
+ continue;
}
- if (r != XZ_OK && r != XZ_UNSUPPORTED_CHECK) {
+ if (xz_result != XZ_OK && xz_result != XZ_UNSUPPORTED_CHECK) {
bb_error_msg("corrupted data");
total = -1;
break;
}
}
+
xz_dec_end(state);
free(membuf);
diff --git a/release/src/router/busybox/archival/libarchive/filter_accept_list_reassign.c b/release/src/router/busybox/archival/libarchive/filter_accept_list_reassign.c
index 3d19abe448..b9acfbc054 100644
--- a/release/src/router/busybox/archival/libarchive/filter_accept_list_reassign.c
+++ b/release/src/router/busybox/archival/libarchive/filter_accept_list_reassign.c
@@ -28,6 +28,10 @@ char FAST_FUNC filter_accept_list_reassign(archive_handle_t *archive_handle)
name_ptr++;
/* Modify the subarchive handler based on the extension */
+ if (strcmp(name_ptr, "tar") == 0) {
+ archive_handle->dpkg__action_data_subarchive = get_header_tar;
+ return EXIT_SUCCESS;
+ }
if (ENABLE_FEATURE_SEAMLESS_GZ
&& strcmp(name_ptr, "gz") == 0
) {
@@ -46,6 +50,12 @@ char FAST_FUNC filter_accept_list_reassign(archive_handle_t *archive_handle)
archive_handle->dpkg__action_data_subarchive = get_header_tar_lzma;
return EXIT_SUCCESS;
}
+ if (ENABLE_FEATURE_SEAMLESS_XZ
+ && strcmp(name_ptr, "xz") == 0
+ ) {
+ archive_handle->dpkg__action_data_subarchive = get_header_tar_xz;
+ return EXIT_SUCCESS;
+ }
}
return EXIT_FAILURE;
}
diff --git a/release/src/router/busybox/archival/libarchive/filter_accept_reject_list.c b/release/src/router/busybox/archival/libarchive/filter_accept_reject_list.c
index 39c811337e..2483749417 100644
--- a/release/src/router/busybox/archival/libarchive/filter_accept_reject_list.c
+++ b/release/src/router/busybox/archival/libarchive/filter_accept_reject_list.c
@@ -24,11 +24,13 @@ char FAST_FUNC filter_accept_reject_list(archive_handle_t *archive_handle)
if (reject_entry) {
return EXIT_FAILURE;
}
- accept_entry = find_list_entry2(archive_handle->accept, key);
/* Fail if an accept list was specified and the key wasnt in there */
- if ((accept_entry == NULL) && archive_handle->accept) {
- return EXIT_FAILURE;
+ if (archive_handle->accept) {
+ accept_entry = find_list_entry2(archive_handle->accept, key);
+ if (!accept_entry) {
+ return EXIT_FAILURE;
+ }
}
/* Accepted */
diff --git a/release/src/router/busybox/archival/libarchive/get_header_ar.c b/release/src/router/busybox/archival/libarchive/get_header_ar.c
index 23c4124963..c66bb3ee73 100644
--- a/release/src/router/busybox/archival/libarchive/get_header_ar.c
+++ b/release/src/router/busybox/archival/libarchive/get_header_ar.c
@@ -8,11 +8,19 @@
#include "bb_archive.h"
#include "ar.h"
-static unsigned read_num(const char *str, int base)
+/* WARNING: Clobbers str[len], so fields must be read in reverse order! */
+static unsigned read_num(char *str, int base, int len)
{
+ int err;
+
+ /* ar fields are fixed length text strings (padded with spaces).
+ * Ensure bb_strtou doesn't read past the field in case the full
+ * width is used. */
+ str[len] = 0;
+
/* This code works because
* on misformatted numbers bb_strtou returns all-ones */
- int err = bb_strtou(str, NULL, base);
+ err = bb_strtou(str, NULL, base);
if (err == -1)
bb_error_msg_and_die("invalid ar header");
return err;
@@ -51,11 +59,13 @@ char FAST_FUNC get_header_ar(archive_handle_t *archive_handle)
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);
+ /*
+ * Note that the fields MUST be read in reverse order as
+ * read_num() clobbers the next byte after the field!
+ * Order is: name, date, uid, gid, mode, size, magic.
+ */
+ typed->size = size = read_num(ar.formatted.size, 10,
+ sizeof(ar.formatted.size));
/* special filenames have '/' as the first character */
if (ar.formatted.name[0] == '/') {
@@ -87,10 +97,10 @@ char FAST_FUNC get_header_ar(archive_handle_t *archive_handle)
* long filename pseudo file. Thus we decode the rest
* after dealing with long filename pseudo file.
*/
- typed->mode = read_num(ar.formatted.mode, 8);
- typed->mtime = read_num(ar.formatted.date, 10);
- typed->uid = read_num(ar.formatted.uid, 10);
- typed->gid = read_num(ar.formatted.gid, 10);
+ typed->mode = read_num(ar.formatted.mode, 8, sizeof(ar.formatted.mode));
+ typed->gid = read_num(ar.formatted.gid, 10, sizeof(ar.formatted.gid));
+ typed->uid = read_num(ar.formatted.uid, 10, sizeof(ar.formatted.uid));
+ typed->mtime = read_num(ar.formatted.date, 10, sizeof(ar.formatted.date));
#if ENABLE_FEATURE_AR_LONG_FILENAMES
if (ar.formatted.name[0] == '/') {
@@ -98,7 +108,8 @@ char FAST_FUNC get_header_ar(archive_handle_t *archive_handle)
/* The number after the '/' indicates the offset in the ar data section
* (saved in ar_long_names) that conatains the real filename */
- long_offset = read_num(&ar.formatted.name[1], 10);
+ long_offset = read_num(&ar.formatted.name[1], 10,
+ sizeof(ar.formatted.name) - 1);
if (long_offset >= ar_long_name_size) {
bb_error_msg_and_die("can't resolve long filename");
}
diff --git a/release/src/router/busybox/archival/libarchive/get_header_cpio.c b/release/src/router/busybox/archival/libarchive/get_header_cpio.c
index 1a0058b63a..badd4a8416 100644
--- a/release/src/router/busybox/archival/libarchive/get_header_cpio.c
+++ b/release/src/router/busybox/archival/libarchive/get_header_cpio.c
@@ -37,7 +37,7 @@ char FAST_FUNC get_header_cpio(archive_handle_t *archive_handle)
}
archive_handle->offset += 110;
- if (strncmp(&cpio_header[0], "07070", 5) != 0
+ if (!is_prefixed_with(&cpio_header[0], "07070")
|| (cpio_header[5] != '1' && cpio_header[5] != '2')
) {
bb_error_msg_and_die("unsupported cpio format, use newc or crc");
@@ -52,6 +52,11 @@ char FAST_FUNC get_header_cpio(archive_handle_t *archive_handle)
&major, &minor, &namesize) != 10)
bb_error_msg_and_die("damaged cpio file");
file_header->mode = mode;
+ /* "cpio -R USER:GRP" support: */
+ if (archive_handle->cpio__owner.uid != (uid_t)-1L)
+ uid = archive_handle->cpio__owner.uid;
+ if (archive_handle->cpio__owner.gid != (gid_t)-1L)
+ gid = archive_handle->cpio__owner.gid;
file_header->uid = uid;
file_header->gid = gid;
file_header->mtime = mtime;
@@ -75,7 +80,7 @@ char FAST_FUNC get_header_cpio(archive_handle_t *archive_handle)
/* Update offset amount and skip padding before file contents */
data_align(archive_handle, 4);
- if (strcmp(file_header->name, "TRAILER!!!") == 0) {
+ if (strcmp(file_header->name, cpio_TRAILER) == 0) {
/* Always round up. ">> 9" divides by 512 */
archive_handle->cpio__blocks = (uoff_t)(archive_handle->offset + 511) >> 9;
goto create_hardlinks;
diff --git a/release/src/router/busybox/archival/libarchive/get_header_tar.c b/release/src/router/busybox/archival/libarchive/get_header_tar.c
index b168653d80..ea91a883e0 100644
--- a/release/src/router/busybox/archival/libarchive/get_header_tar.c
+++ b/release/src/router/busybox/archival/libarchive/get_header_tar.c
@@ -17,36 +17,6 @@
typedef uint32_t aliased_uint32_t FIX_ALIASING;
typedef off_t aliased_off_t FIX_ALIASING;
-
-const char* FAST_FUNC strip_unsafe_prefix(const char *str)
-{
- const char *cp = str;
- while (1) {
- char *cp2;
- if (*cp == '/') {
- cp++;
- continue;
- }
- if (strncmp(cp, "/../"+1, 3) == 0) {
- cp += 3;
- continue;
- }
- cp2 = strstr(cp, "/../");
- if (!cp2)
- break;
- cp = cp2 + 4;
- }
- if (cp != str) {
- static smallint warned = 0;
- if (!warned) {
- warned = 1;
- bb_error_msg("removing leading '%.*s' from member names",
- (int)(cp - str), str);
- }
- }
- return cp;
-}
-
/* NB: _DESTROYS_ str[len] character! */
static unsigned long long getOctal(char *str, int len)
{
@@ -90,13 +60,21 @@ static unsigned long long getOctal(char *str, int len)
}
#define GET_OCTAL(a) getOctal((a), sizeof(a))
+#define TAR_EXTD (ENABLE_FEATURE_TAR_GNU_EXTENSIONS || ENABLE_FEATURE_TAR_SELINUX)
+#if !TAR_EXTD
+#define process_pax_hdr(archive_handle, sz, global) \
+ process_pax_hdr(archive_handle, sz)
+#endif
/* "global" is 0 or 1 */
static void process_pax_hdr(archive_handle_t *archive_handle, unsigned sz, int global)
{
+#if !TAR_EXTD
+ unsigned blk_sz = (sz + 511) & (~511);
+ seek_by_read(archive_handle->src_fd, blk_sz);
+#else
+ unsigned blk_sz = (sz + 511) & (~511);
char *buf, *p;
- unsigned blk_sz;
- blk_sz = (sz + 511) & (~511);
p = buf = xmalloc(blk_sz + 1);
xread(archive_handle->src_fd, buf, blk_sz);
archive_handle->offset += blk_sz;
@@ -115,7 +93,9 @@ static void process_pax_hdr(archive_handle_t *archive_handle, unsigned sz, int g
*/
p += len;
sz -= len;
- if ((int)sz < 0
+ if (
+ /** (int)sz < 0 - not good enough for huge malicious VALUE of 2^32-1 */
+ (int)(sz|len) < 0 /* this works */
|| len == 0
|| errno != EINVAL
|| *end != ' '
@@ -132,30 +112,31 @@ static void process_pax_hdr(archive_handle_t *archive_handle, unsigned sz, int g
p[-1] = '\0';
value = end + 1;
-#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
- if (!global && strncmp(value, "path=", sizeof("path=") - 1) == 0) {
+# if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
+ if (!global && is_prefixed_with(value, "path=")) {
value += sizeof("path=") - 1;
free(archive_handle->tar__longname);
archive_handle->tar__longname = xstrdup(value);
continue;
}
-#endif
+# endif
-#if ENABLE_FEATURE_TAR_SELINUX
+# if ENABLE_FEATURE_TAR_SELINUX
/* Scan 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"
- if (strncmp(value, SELINUX_CONTEXT_KEYWORD"=", sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1) == 0) {
+# define SELINUX_CONTEXT_KEYWORD "RHT.security.selinux"
+ if (is_prefixed_with(value, SELINUX_CONTEXT_KEYWORD"=")) {
value += sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1;
free(archive_handle->tar__sctx[global]);
archive_handle->tar__sctx[global] = xstrdup(value);
continue;
}
-#endif
+# endif
}
free(buf);
+#endif
}
char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
@@ -198,13 +179,13 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
* the message and we don't check whether we indeed
* saw zero block directly before this. */
if (i == 0) {
- xfunc_error_retval = 0;
- short_read:
- bb_error_msg_and_die("short read");
+ bb_error_msg("short read");
+ /* this merely signals end of archive, not exit(1): */
+ return EXIT_FAILURE;
}
if (i != 512) {
IF_FEATURE_TAR_AUTODETECT(goto autodetect;)
- goto short_read;
+ bb_error_msg_and_die("short read");
}
#else
@@ -221,16 +202,16 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
*/
while (full_read(archive_handle->src_fd, &tar, 512) == 512)
continue;
- return EXIT_FAILURE;
+ return EXIT_FAILURE; /* "end of archive" */
}
archive_handle->tar__end = 1;
- return EXIT_SUCCESS;
+ return EXIT_SUCCESS; /* "decoded one header" */
}
archive_handle->tar__end = 0;
/* Check header has valid magic, "ustar" is for the proper tar,
* five NULs are for the old tar format */
- if (strncmp(tar.magic, "ustar", 5) != 0
+ if (!is_prefixed_with(tar.magic, "ustar")
&& (!ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY
|| memcmp(tar.magic, "\0\0\0\0", 5) != 0)
) {
@@ -241,7 +222,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
* or not first block (false positive, it's not .gz/.bz2!) */
if (lseek(archive_handle->src_fd, -i, SEEK_CUR) != 0)
goto err;
- if (setup_unzip_on_fd(archive_handle->src_fd, /*fail_if_not_detected:*/ 0) != 0)
+ if (setup_unzip_on_fd(archive_handle->src_fd, /*fail_if_not_compressed:*/ 0) != 0)
err:
bb_error_msg_and_die("invalid tar magic");
archive_handle->offset = 0;
@@ -378,7 +359,14 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
case '6':
file_header->mode |= S_IFIFO;
goto size0;
+ case 'g': /* pax global header */
+ case 'x': { /* pax extended header */
+ if ((uoff_t)file_header->size > 0xfffff) /* paranoia */
+ goto skip_ext_hdr;
+ process_pax_hdr(archive_handle, file_header->size, (tar.typeflag == 'g'));
+ goto again_after_align;
#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
+/* See http://www.gnu.org/software/tar/manual/html_node/Extensions.html */
case 'L':
/* free: paranoia: tar with several consecutive longnames */
free(p_longname);
@@ -398,18 +386,17 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
archive_handle->offset += file_header->size;
/* return get_header_tar(archive_handle); */
goto again;
- 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 */
+/*
+ * case 'S': // Sparse file
+ * Was seen in the wild. Not supported (yet?).
+ * See https://www.gnu.org/software/tar/manual/html_section/tar_92.html
+ * for the format. (An "Old GNU Format" was seen, not PAX formats).
+ */
+// case 'D': /* GNU dump dir */
+// case 'M': /* Continuation of multi volume archive */
+// case 'N': /* Old GNU for names > 100 characters */
+// case 'V': /* Volume header */
#endif
- case 'g': /* pax global header */
- case 'x': { /* pax extended header */
- if ((uoff_t)file_header->size > 0xfffff) /* paranoia */
- goto skip_ext_hdr;
- process_pax_hdr(archive_handle, file_header->size, (tar.typeflag == 'g'));
- goto again_after_align;
}
skip_ext_hdr:
{
@@ -440,6 +427,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
/* Everything up to and including last ".." component is stripped */
overlapping_strcpy(file_header->name, strip_unsafe_prefix(file_header->name));
+//TODO: do the same for file_header->link_target?
/* Strip trailing '/' in directories */
/* Must be done after mode is set as '/' is used to check if it's a directory */
@@ -452,9 +440,11 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
if (cp)
*cp = '\0';
archive_handle->action_data(archive_handle);
- if (archive_handle->accept || archive_handle->reject)
+ if (archive_handle->accept || archive_handle->reject
+ || (archive_handle->ah_flags & ARCHIVE_REMEMBER_NAMES)
+ ) {
llist_add_to(&archive_handle->passed, file_header->name);
- else /* Caller isn't interested in list of unpacked files */
+ } else /* Caller isn't interested in list of unpacked files */
free(file_header->name);
} else {
data_skip(archive_handle);
@@ -469,5 +459,5 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
free(file_header->tar__uname);
free(file_header->tar__gname);
#endif
- return EXIT_SUCCESS;
+ return EXIT_SUCCESS; /* "decoded one header" */
}
diff --git a/release/src/router/busybox/archival/libarchive/get_header_tar_bz2.c b/release/src/router/busybox/archival/libarchive/get_header_tar_bz2.c
index 0ee00df53d..78f78a858c 100644
--- a/release/src/router/busybox/archival/libarchive/get_header_tar_bz2.c
+++ b/release/src/router/busybox/archival/libarchive/get_header_tar_bz2.c
@@ -11,7 +11,7 @@ char FAST_FUNC get_header_tar_bz2(archive_handle_t *archive_handle)
/* Can't lseek over pipes */
archive_handle->seek = seek_by_read;
- open_transformer_with_sig(archive_handle->src_fd, unpack_bz2_stream, "bunzip2");
+ fork_transformer_with_sig(archive_handle->src_fd, unpack_bz2_stream, "bunzip2");
archive_handle->offset = 0;
while (get_header_tar(archive_handle) == EXIT_SUCCESS)
continue;
diff --git a/release/src/router/busybox/archival/libarchive/get_header_tar_gz.c b/release/src/router/busybox/archival/libarchive/get_header_tar_gz.c
index 03284342b1..b11f503dc6 100644
--- a/release/src/router/busybox/archival/libarchive/get_header_tar_gz.c
+++ b/release/src/router/busybox/archival/libarchive/get_header_tar_gz.c
@@ -11,7 +11,7 @@ char FAST_FUNC get_header_tar_gz(archive_handle_t *archive_handle)
/* Can't lseek over pipes */
archive_handle->seek = seek_by_read;
- open_transformer_with_sig(archive_handle->src_fd, unpack_gz_stream, "gunzip");
+ fork_transformer_with_sig(archive_handle->src_fd, unpack_gz_stream, "gunzip");
archive_handle->offset = 0;
while (get_header_tar(archive_handle) == EXIT_SUCCESS)
continue;
diff --git a/release/src/router/busybox/archival/libarchive/get_header_tar_lzma.c b/release/src/router/busybox/archival/libarchive/get_header_tar_lzma.c
index d565a217d9..d228cbc138 100644
--- a/release/src/router/busybox/archival/libarchive/get_header_tar_lzma.c
+++ b/release/src/router/busybox/archival/libarchive/get_header_tar_lzma.c
@@ -14,7 +14,7 @@ char FAST_FUNC get_header_tar_lzma(archive_handle_t *archive_handle)
/* Can't lseek over pipes */
archive_handle->seek = seek_by_read;
- open_transformer_with_sig(archive_handle->src_fd, unpack_lzma_stream, "unlzma");
+ fork_transformer_with_sig(archive_handle->src_fd, unpack_lzma_stream, "unlzma");
archive_handle->offset = 0;
while (get_header_tar(archive_handle) == EXIT_SUCCESS)
continue;
diff --git a/release/src/router/busybox/archival/libarchive/get_header_tar_xz.c b/release/src/router/busybox/archival/libarchive/get_header_tar_xz.c
new file mode 100644
index 0000000000..7bf3b3b56d
--- /dev/null
+++ b/release/src/router/busybox/archival/libarchive/get_header_tar_xz.c
@@ -0,0 +1,21 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+#include "libbb.h"
+#include "bb_archive.h"
+
+char FAST_FUNC get_header_tar_xz(archive_handle_t *archive_handle)
+{
+ /* Can't lseek over pipes */
+ archive_handle->seek = seek_by_read;
+
+ fork_transformer_with_sig(archive_handle->src_fd, unpack_xz_stream, "unxz");
+ archive_handle->offset = 0;
+ while (get_header_tar(archive_handle) == EXIT_SUCCESS)
+ continue;
+
+ /* Can only do one file at a time */
+ return EXIT_FAILURE;
+}
diff --git a/release/src/router/busybox/archival/libarchive/liblzo.h b/release/src/router/busybox/archival/libarchive/liblzo.h
index 843997cb9c..4596620fee 100644
--- a/release/src/router/busybox/archival/libarchive/liblzo.h
+++ b/release/src/router/busybox/archival/libarchive/liblzo.h
@@ -76,11 +76,13 @@
# define TEST_IP (ip < ip_end)
# define NEED_IP(x) \
if ((unsigned)(ip_end - ip) < (unsigned)(x)) goto input_overrun
+# define TEST_IV(x) if ((x) > (unsigned)0 - (511)) goto input_overrun
# undef TEST_OP /* don't need both of the tests here */
# define TEST_OP 1
# define NEED_OP(x) \
if ((unsigned)(op_end - op) < (unsigned)(x)) goto output_overrun
+# define TEST_OV(x) if ((x) > (unsigned)0 - (511)) goto output_overrun
#define HAVE_ANY_OP 1
diff --git a/release/src/router/busybox/archival/libarchive/lzo1x_9x.c b/release/src/router/busybox/archival/libarchive/lzo1x_9x.c
index 4832051559..09ee4ba5c3 100644
--- a/release/src/router/busybox/archival/libarchive/lzo1x_9x.c
+++ b/release/src/router/busybox/archival/libarchive/lzo1x_9x.c
@@ -71,7 +71,6 @@ typedef struct {
uint8_t *out;
unsigned r1_lit;
-
} lzo1x_999_t;
#define getbyte(c) ((c).ip < (c).in_end ? *((c).ip)++ : (-1))
@@ -94,7 +93,7 @@ typedef struct {
( ((0x9f5f * ((((b[p]<<5)^b[p+1])<<5) ^ b[p+2])) >> 5) & (SWD_HSIZE-1) )
#if defined(LZO_UNALIGNED_OK_2)
-# define HEAD2(b,p) (* (uint16_t *) &(b[p]))
+# define HEAD2(b,p) (* (bb__aliased_uint16_t *) &(b[p]))
#else
# define HEAD2(b,p) (b[p] ^ ((unsigned)b[p+1]<<8))
#endif
@@ -466,7 +465,6 @@ static int find_match(lzo1x_999_t *c, lzo_swd_p s,
}
s->m_len = 1;
- s->m_len = 1;
#ifdef SWD_BEST_OFF
if (s->use_best_off)
memset(s->best_pos, 0, sizeof(s->best_pos));
@@ -644,7 +642,7 @@ static int len_of_coded_match(unsigned m_len, unsigned m_off, unsigned lit)
static int min_gain(unsigned ahead, unsigned lit1,
- unsigned lit2, int l1, int l2, int l3)
+ unsigned lit2, int l1, int l2, int l3)
{
int lazy_match_min_gain = 0;
@@ -673,7 +671,7 @@ static int min_gain(unsigned ahead, unsigned lit1,
#if defined(SWD_BEST_OFF)
static void better_match(const lzo_swd_p swd,
- unsigned *m_len, unsigned *m_off)
+ unsigned *m_len, unsigned *m_off)
{
if (*m_len <= M2_MIN_LEN)
return;
@@ -914,8 +912,8 @@ int lzo1x_999_compress_level(const uint8_t *in, unsigned in_len,
compression_level -= 7;
return lzo1x_999_compress_internal(in, in_len, out, out_len, wrkmem,
- c[compression_level].good_length,
- c[compression_level].max_lazy,
- c[compression_level].max_chain,
- c[compression_level].use_best_off);
+ c[compression_level].good_length,
+ c[compression_level].max_lazy,
+ c[compression_level].max_chain,
+ c[compression_level].use_best_off);
}
diff --git a/release/src/router/busybox/archival/libarchive/lzo1x_c.c b/release/src/router/busybox/archival/libarchive/lzo1x_c.c
index cc86f74b10..8c77072ab8 100644
--- a/release/src/router/busybox/archival/libarchive/lzo1x_c.c
+++ b/release/src/router/busybox/archival/libarchive/lzo1x_c.c
@@ -15,7 +15,7 @@
The LZO library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
diff --git a/release/src/router/busybox/archival/libarchive/lzo1x_d.c b/release/src/router/busybox/archival/libarchive/lzo1x_d.c
index 348a85510b..40b167e688 100644
--- a/release/src/router/busybox/archival/libarchive/lzo1x_d.c
+++ b/release/src/router/busybox/archival/libarchive/lzo1x_d.c
@@ -15,7 +15,7 @@
The LZO library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
@@ -92,6 +92,7 @@ int lzo1x_decompress_safe(const uint8_t* in, unsigned in_len,
ip++;
NEED_IP(1);
}
+ TEST_IV(t);
t += 15 + *ip++;
}
/* copy literals */
@@ -224,6 +225,7 @@ int lzo1x_decompress_safe(const uint8_t* in, unsigned in_len,
ip++;
NEED_IP(1);
}
+ TEST_IV(t);
t += 31 + *ip++;
}
#if defined(COPY_DICT)
@@ -265,6 +267,7 @@ int lzo1x_decompress_safe(const uint8_t* in, unsigned in_len,
ip++;
NEED_IP(1);
}
+ TEST_IV(t);
t += 7 + *ip++;
}
#if defined(COPY_DICT)
diff --git a/release/src/router/busybox/archival/libarchive/open_transformer.c b/release/src/router/busybox/archival/libarchive/open_transformer.c
index dae04aa575..ac7e5db95f 100644
--- a/release/src/router/busybox/archival/libarchive/open_transformer.c
+++ b/release/src/router/busybox/archival/libarchive/open_transformer.c
@@ -6,27 +6,65 @@
#include "libbb.h"
#include "bb_archive.h"
-void FAST_FUNC init_transformer_aux_data(transformer_aux_data_t *aux)
+void FAST_FUNC init_transformer_state(transformer_state_t *xstate)
{
- memset(aux, 0, sizeof(*aux));
+ memset(xstate, 0, sizeof(*xstate));
}
-int FAST_FUNC check_signature16(transformer_aux_data_t *aux, int src_fd, unsigned magic16)
+int FAST_FUNC check_signature16(transformer_state_t *xstate, unsigned magic16)
{
- if (aux && aux->check_signature) {
+ if (!xstate->signature_skipped) {
uint16_t magic2;
- if (full_read(src_fd, &magic2, 2) != 2 || magic2 != magic16) {
+ if (full_read(xstate->src_fd, &magic2, 2) != 2 || magic2 != magic16) {
bb_error_msg("invalid magic");
-#if 0 /* possible future extension */
- if (aux->check_signature > 1)
- xfunc_die();
-#endif
return -1;
}
+ xstate->signature_skipped = 2;
}
return 0;
}
+ssize_t FAST_FUNC transformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize)
+{
+ ssize_t nwrote;
+
+ if (xstate->mem_output_size_max != 0) {
+ size_t pos = xstate->mem_output_size;
+ size_t size;
+
+ size = (xstate->mem_output_size += bufsize);
+ if (size > xstate->mem_output_size_max) {
+ free(xstate->mem_output_buf);
+ xstate->mem_output_buf = NULL;
+ bb_perror_msg("buffer %u too small", (unsigned)xstate->mem_output_size_max);
+ nwrote = -1;
+ goto ret;
+ }
+ xstate->mem_output_buf = xrealloc(xstate->mem_output_buf, size + 1);
+ memcpy(xstate->mem_output_buf + pos, buf, bufsize);
+ xstate->mem_output_buf[size] = '\0';
+ nwrote = bufsize;
+ } else {
+ nwrote = full_write(xstate->dst_fd, buf, bufsize);
+ if (nwrote != (ssize_t)bufsize) {
+ bb_perror_msg("write");
+ nwrote = -1;
+ goto ret;
+ }
+ }
+ ret:
+ return nwrote;
+}
+
+ssize_t FAST_FUNC xtransformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize)
+{
+ ssize_t nwrote = transformer_write(xstate, buf, bufsize);
+ if (nwrote != (ssize_t)bufsize) {
+ xfunc_die();
+ }
+ return nwrote;
+}
+
void check_errors_in_children(int signo)
{
int status;
@@ -34,6 +72,7 @@ void check_errors_in_children(int signo)
if (!signo) {
/* block waiting for any child */
if (wait(&status) < 0)
+//FIXME: check EINTR?
return; /* probably there are no children */
goto check_status;
}
@@ -41,26 +80,30 @@ void check_errors_in_children(int signo)
/* Wait for any child without blocking */
for (;;) {
if (wait_any_nohang(&status) < 0)
+//FIXME: check EINTR?
/* wait failed?! I'm confused... */
return;
check_status:
- if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
+ /*if (WIFEXITED(status) && WEXITSTATUS(status) == 0)*/
+ /* On Linux, the above can be checked simply as: */
+ if (status == 0)
/* this child exited with 0 */
continue;
- /* Cannot happen?
- if (!WIFSIGNALED(status) && !WIFEXITED(status)) ???; */
+ /* Cannot happen:
+ if (!WIFSIGNALED(status) && !WIFEXITED(status)) ???;
+ */
bb_got_signal = 1;
}
}
/* transformer(), more than meets the eye */
#if BB_MMU
-void FAST_FUNC open_transformer(int fd,
- int check_signature,
- IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_aux_data_t *aux, int src_fd, int dst_fd)
+void FAST_FUNC fork_transformer(int fd,
+ int signature_skipped,
+ IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate)
)
#else
-void FAST_FUNC open_transformer(int fd, const char *transform_prog)
+void FAST_FUNC fork_transformer(int fd, const char *transform_prog)
#endif
{
struct fd_pair fd_pipe;
@@ -74,16 +117,19 @@ void FAST_FUNC open_transformer(int fd, const char *transform_prog)
// FIXME: error check?
#if BB_MMU
{
- transformer_aux_data_t aux;
- init_transformer_aux_data(&aux);
- aux.check_signature = check_signature;
- transformer(&aux, fd, fd_pipe.wr);
+ IF_DESKTOP(long long) int r;
+ transformer_state_t xstate;
+ init_transformer_state(&xstate);
+ xstate.signature_skipped = signature_skipped;
+ xstate.src_fd = fd;
+ xstate.dst_fd = fd_pipe.wr;
+ r = transformer(&xstate);
if (ENABLE_FEATURE_CLEAN_UP) {
close(fd_pipe.wr); /* send EOF */
close(fd);
}
/* must be _exit! bug was actually seen here */
- _exit(EXIT_SUCCESS);
+ _exit(/*error if:*/ r < 0);
}
#else
{
@@ -112,16 +158,18 @@ void FAST_FUNC open_transformer(int fd, const char *transform_prog)
/* Used by e.g. rpm which gives us a fd without filename,
* thus we can't guess the format from filename's extension.
*/
-int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_detected)
+static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_compressed)
{
union {
uint8_t b[4];
uint16_t b16[2];
uint32_t b32[1];
} magic;
- int offset = -2;
- USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_aux_data_t *aux, int src_fd, int dst_fd);)
- USE_FOR_NOMMU(const char *xformer_prog;)
+ transformer_state_t *xstate;
+
+ xstate = xzalloc(sizeof(*xstate));
+ xstate->src_fd = fd;
+ xstate->signature_skipped = 2;
/* .gz and .bz2 both have 2-byte signature, and their
* unpack_XXX_stream wants this header skipped. */
@@ -129,86 +177,177 @@ int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_detected)
if (ENABLE_FEATURE_SEAMLESS_GZ
&& magic.b16[0] == GZIP_MAGIC
) {
- USE_FOR_MMU(xformer = unpack_gz_stream;)
- USE_FOR_NOMMU(xformer_prog = "gunzip";)
+ xstate->xformer = unpack_gz_stream;
+ USE_FOR_NOMMU(xstate->xformer_prog = "gunzip";)
+ goto found_magic;
+ }
+ if (ENABLE_FEATURE_SEAMLESS_Z
+ && magic.b16[0] == COMPRESS_MAGIC
+ ) {
+ xstate->xformer = unpack_Z_stream;
+ USE_FOR_NOMMU(xstate->xformer_prog = "uncompress";)
goto found_magic;
}
if (ENABLE_FEATURE_SEAMLESS_BZ2
&& magic.b16[0] == BZIP2_MAGIC
) {
- USE_FOR_MMU(xformer = unpack_bz2_stream;)
- USE_FOR_NOMMU(xformer_prog = "bunzip2";)
+ xstate->xformer = unpack_bz2_stream;
+ USE_FOR_NOMMU(xstate->xformer_prog = "bunzip2";)
goto found_magic;
}
if (ENABLE_FEATURE_SEAMLESS_XZ
&& magic.b16[0] == XZ_MAGIC1
) {
- offset = -6;
+ xstate->signature_skipped = 6;
xread(fd, magic.b32, sizeof(magic.b32[0]));
if (magic.b32[0] == XZ_MAGIC2) {
- USE_FOR_MMU(xformer = unpack_xz_stream;)
- USE_FOR_NOMMU(xformer_prog = "unxz";)
+ xstate->xformer = unpack_xz_stream;
+ USE_FOR_NOMMU(xstate->xformer_prog = "unxz";)
goto found_magic;
}
}
/* No known magic seen */
- if (fail_if_not_detected)
+ if (fail_if_not_compressed)
bb_error_msg_and_die("no gzip"
IF_FEATURE_SEAMLESS_BZ2("/bzip2")
IF_FEATURE_SEAMLESS_XZ("/xz")
" magic");
- xlseek(fd, offset, SEEK_CUR);
- return 1;
+
+ /* Some callers expect this function to "consume" fd
+ * even if data is not compressed. In this case,
+ * we return a state with trivial transformer.
+ */
+// USE_FOR_MMU(xstate->xformer = copy_stream;)
+// USE_FOR_NOMMU(xstate->xformer_prog = "cat";)
found_magic:
+ return xstate;
+}
+
+/* Used by e.g. rpm which gives us a fd without filename,
+ * thus we can't guess the format from filename's extension.
+ */
+int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed)
+{
+ transformer_state_t *xstate = setup_transformer_on_fd(fd, fail_if_not_compressed);
+
+ if (!xstate || !xstate->xformer) {
+ free(xstate);
+ return 1;
+ }
+
# if BB_MMU
- open_transformer_with_no_sig(fd, xformer);
+ fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer);
# else
- /* NOMMU version of open_transformer execs
+ /* NOMMU version of fork_transformer execs
* an external unzipper that wants
- * file position at the start of the file */
- xlseek(fd, offset, SEEK_CUR);
- open_transformer_with_sig(fd, xformer, xformer_prog);
+ * file position at the start of the file.
+ */
+ xlseek(fd, - xstate->signature_skipped, SEEK_CUR);
+ xstate->signature_skipped = 0;
+ fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog);
# endif
+ free(xstate);
return 0;
}
-int FAST_FUNC open_zipped(const char *fname)
+static transformer_state_t *open_transformer(const char *fname, int fail_if_not_compressed)
{
- char *sfx;
+ transformer_state_t *xstate;
int fd;
fd = open(fname, O_RDONLY);
if (fd < 0)
- return fd;
-
- sfx = strrchr(fname, '.');
- if (sfx) {
- sfx++;
- if (ENABLE_FEATURE_SEAMLESS_LZMA && strcmp(sfx, "lzma") == 0)
- /* .lzma has no header/signature, just trust it */
- open_transformer_with_sig(fd, unpack_lzma_stream, "unlzma");
- else
- if ((ENABLE_FEATURE_SEAMLESS_GZ && strcmp(sfx, "gz") == 0)
- || (ENABLE_FEATURE_SEAMLESS_BZ2 && strcmp(sfx, "bz2") == 0)
- || (ENABLE_FEATURE_SEAMLESS_XZ && strcmp(sfx, "xz") == 0)
- ) {
- setup_unzip_on_fd(fd, /*fail_if_not_detected:*/ 1);
+ return NULL;
+
+ if (ENABLE_FEATURE_SEAMLESS_LZMA) {
+ /* .lzma has no header/signature, can only detect it by extension */
+ char *sfx = strrchr(fname, '.');
+ if (sfx && strcmp(sfx+1, "lzma") == 0) {
+ xstate = xzalloc(sizeof(*xstate));
+ xstate->src_fd = fd;
+ xstate->xformer = unpack_lzma_stream;
+ USE_FOR_NOMMU(xstate->xformer_prog = "unlzma";)
+ return xstate;
}
}
- return fd;
+ xstate = setup_transformer_on_fd(fd, fail_if_not_compressed);
+
+ return xstate;
}
-#endif /* SEAMLESS_COMPRESSION */
+int FAST_FUNC open_zipped(const char *fname, int fail_if_not_compressed)
+{
+ int fd;
+ transformer_state_t *xstate;
+
+ xstate = open_transformer(fname, fail_if_not_compressed);
+ if (!xstate)
+ return -1;
+
+ fd = xstate->src_fd;
+# if BB_MMU
+ if (xstate->xformer) {
+ fork_transformer_with_no_sig(fd, xstate->xformer);
+ } else {
+ /* the file is not compressed */
+ xlseek(fd, - xstate->signature_skipped, SEEK_CUR);
+ xstate->signature_skipped = 0;
+ }
+# else
+ /* NOMMU can't avoid the seek :( */
+ xlseek(fd, - xstate->signature_skipped, SEEK_CUR);
+ xstate->signature_skipped = 0;
+ if (xstate->xformer) {
+ fork_transformer_with_sig(fd, xstate->xformer, xstate->xformer_prog);
+ } /* else: the file is not compressed */
+# endif
+
+ free(xstate);
+ return fd;
+}
void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p)
{
+# if 1
+ transformer_state_t *xstate;
+ char *image;
+
+ xstate = open_transformer(fname, /*fail_if_not_compressed:*/ 0);
+ if (!xstate) /* file open error */
+ return NULL;
+
+ image = NULL;
+ if (xstate->xformer) {
+ /* In-memory decompression */
+ xstate->mem_output_size_max = maxsz_p ? *maxsz_p : (size_t)(INT_MAX - 4095);
+ xstate->xformer(xstate);
+ if (xstate->mem_output_buf) {
+ image = xstate->mem_output_buf;
+ if (maxsz_p)
+ *maxsz_p = xstate->mem_output_size;
+ }
+ } else {
+ /* File is not compressed */
+//FIXME: avoid seek
+ xlseek(xstate->src_fd, - xstate->signature_skipped, SEEK_CUR);
+ xstate->signature_skipped = 0;
+ image = xmalloc_read(xstate->src_fd, maxsz_p);
+ }
+
+ if (!image)
+ bb_perror_msg("read error from '%s'", fname);
+ close(xstate->src_fd);
+ free(xstate);
+ return image;
+# else
+ /* This version forks a subprocess - much more expensive */
int fd;
char *image;
- fd = open_zipped(fname);
+ fd = open_zipped(fname, /*fail_if_not_compressed:*/ 0);
if (fd < 0)
return NULL;
@@ -216,6 +355,8 @@ void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_
if (!image)
bb_perror_msg("read error from '%s'", fname);
close(fd);
-
return image;
+# endif
}
+
+#endif /* SEAMLESS_COMPRESSION */
diff --git a/release/src/router/busybox/archival/libarchive/unpack_ar_archive.c b/release/src/router/busybox/archival/libarchive/unpack_ar_archive.c
index 214d17e23a..0bc030349f 100644
--- a/release/src/router/busybox/archival/libarchive/unpack_ar_archive.c
+++ b/release/src/router/busybox/archival/libarchive/unpack_ar_archive.c
@@ -12,7 +12,7 @@ void FAST_FUNC unpack_ar_archive(archive_handle_t *ar_archive)
char magic[7];
xread(ar_archive->src_fd, magic, AR_MAGIC_LEN);
- if (strncmp(magic, AR_MAGIC, AR_MAGIC_LEN) != 0) {
+ if (!is_prefixed_with(magic, AR_MAGIC)) {
bb_error_msg_and_die("invalid ar magic");
}
ar_archive->offset += AR_MAGIC_LEN;
diff --git a/release/src/router/busybox/archival/libarchive/unsafe_prefix.c b/release/src/router/busybox/archival/libarchive/unsafe_prefix.c
new file mode 100644
index 0000000000..9994f4d94e
--- /dev/null
+++ b/release/src/router/busybox/archival/libarchive/unsafe_prefix.c
@@ -0,0 +1,36 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+#include "libbb.h"
+#include "bb_archive.h"
+
+const char* FAST_FUNC strip_unsafe_prefix(const char *str)
+{
+ const char *cp = str;
+ while (1) {
+ char *cp2;
+ if (*cp == '/') {
+ cp++;
+ continue;
+ }
+ if (is_prefixed_with(cp, "/../"+1)) {
+ cp += 3;
+ continue;
+ }
+ cp2 = strstr(cp, "/../");
+ if (!cp2)
+ break;
+ cp = cp2 + 4;
+ }
+ if (cp != str) {
+ static smallint warned = 0;
+ if (!warned) {
+ warned = 1;
+ bb_error_msg("removing leading '%.*s' from member names",
+ (int)(cp - str), str);
+ }
+ }
+ return cp;
+}
diff --git a/release/src/router/busybox/archival/libarchive/unxz/README b/release/src/router/busybox/archival/libarchive/unxz/README
index c5972f6b82..a849120357 100644
--- a/release/src/router/busybox/archival/libarchive/unxz/README
+++ b/release/src/router/busybox/archival/libarchive/unxz/README
@@ -7,7 +7,7 @@ XZ Embedded
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.
+ applications. See userspace/xzminidec.c for an example program.
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
@@ -55,7 +55,7 @@ Compiler requirements
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,
+ If you use GCC, try to use a recent version. For example, on x86-32,
xz_dec_lzma2.c compiled with GCC 3.3.6 is 15-25 % slower than when
compiled with GCC 4.3.3.
@@ -93,7 +93,7 @@ BCJ filter support
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_X86 x86-32 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
diff --git a/release/src/router/busybox/archival/libarchive/unxz/xz.h b/release/src/router/busybox/archival/libarchive/unxz/xz.h
index c6c071c4af..e0b22db56d 100644
--- a/release/src/router/busybox/archival/libarchive/unxz/xz.h
+++ b/release/src/router/busybox/archival/libarchive/unxz/xz.h
@@ -19,6 +19,10 @@
# include <stdint.h>
#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* In Linux, this is used to make extern functions static when needed. */
#ifndef XZ_EXTERN
# define XZ_EXTERN extern
@@ -70,7 +74,7 @@ enum xz_mode {
* @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
+ * Note that 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
@@ -105,7 +109,7 @@ enum xz_mode {
* 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
+ * 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.
@@ -207,8 +211,8 @@ XZ_EXTERN struct xz_dec * XZ_FUNC xz_dec_init(
* 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
+ * Note that 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
@@ -268,4 +272,9 @@ XZ_EXTERN void XZ_FUNC xz_crc32_init(void);
XZ_EXTERN uint32_t XZ_FUNC xz_crc32(
const uint8_t *buf, size_t size, uint32_t crc);
#endif
+
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/release/src/router/busybox/archival/libarchive/unxz/xz_dec_bcj.c b/release/src/router/busybox/archival/libarchive/unxz/xz_dec_bcj.c
index 09162b51f6..e0f913a946 100644
--- a/release/src/router/busybox/archival/libarchive/unxz/xz_dec_bcj.c
+++ b/release/src/router/busybox/archival/libarchive/unxz/xz_dec_bcj.c
@@ -77,10 +77,13 @@ struct xz_dec_bcj {
#ifdef XZ_DEC_X86
/*
- * This is macro used to test the most significant byte of a memory address
+ * This is 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 inline int bcj_x86_test_msbyte(uint8_t b)
+{
+ return 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)
@@ -443,8 +446,12 @@ XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_bcj_run(struct xz_dec_bcj *s,
* 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.
+ *
+ * This needs to be always run when temp.size == 0 to handle a special
+ * case where the output buffer is full and the next filter has no
+ * more output coming but hasn't returned XZ_STREAM_END yet.
*/
- if (s->temp.size < b->out_size - b->out_pos) {
+ if (s->temp.size < b->out_size - b->out_pos || s->temp.size == 0) {
out_start = b->out_pos;
memcpy(b->out + b->out_pos, s->temp.buf, s->temp.size);
b->out_pos += s->temp.size;
@@ -467,16 +474,25 @@ XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_bcj_run(struct xz_dec_bcj *s,
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 there wasn't enough input to the next filter to fill
+ * the output buffer with unfiltered data, there's no point
+ * to try decoding more data to temp.
+ */
+ if (b->out_pos + s->temp.size < b->out_size)
+ return XZ_OK;
}
/*
- * 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.
+ * We have unfiltered data in temp. If the output buffer isn't full
+ * yet, try to fill the temp buffer 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) {
+ if (b->out_pos < b->out_size) {
/* Make b->out{,_pos,_size} temporarily point to s->temp. */
s->out = b->out;
s->out_pos = b->out_pos;
diff --git a/release/src/router/busybox/archival/libarchive/unxz/xz_dec_lzma2.c b/release/src/router/busybox/archival/libarchive/unxz/xz_dec_lzma2.c
index da71cb4d42..351251f7c1 100644
--- a/release/src/router/busybox/archival/libarchive/unxz/xz_dec_lzma2.c
+++ b/release/src/router/busybox/archival/libarchive/unxz/xz_dec_lzma2.c
@@ -407,7 +407,6 @@ static void XZ_FUNC dict_uncompressed(
b->out_pos += copy_size;
b->in_pos += copy_size;
-
}
}
@@ -972,6 +971,9 @@ XZ_EXTERN NOINLINE enum xz_ret XZ_FUNC xz_dec_lzma2_run(
*/
tmp = b->in[b->in_pos++];
+ if (tmp == 0x00)
+ return XZ_STREAM_END;
+
if (tmp >= 0xE0 || tmp == 0x01) {
s->lzma2.need_props = true;
s->lzma2.need_dict_reset = false;
@@ -993,10 +995,8 @@ XZ_EXTERN NOINLINE enum xz_ret XZ_FUNC xz_dec_lzma2_run(
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;
@@ -1004,9 +1004,6 @@ XZ_EXTERN NOINLINE enum xz_ret XZ_FUNC xz_dec_lzma2_run(
lzma_reset(s);
}
} else {
- if (tmp == 0x00)
- return XZ_STREAM_END;
-
if (tmp > 0x02)
return XZ_DATA_ERROR;
@@ -1081,7 +1078,6 @@ XZ_EXTERN NOINLINE enum xz_ret XZ_FUNC xz_dec_lzma2_run(
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
diff --git a/release/src/router/busybox/archival/libarchive/unxz/xz_dec_stream.c b/release/src/router/busybox/archival/libarchive/unxz/xz_dec_stream.c
index bdcbf1ba39..bf791055b5 100644
--- a/release/src/router/busybox/archival/libarchive/unxz/xz_dec_stream.c
+++ b/release/src/router/busybox/archival/libarchive/unxz/xz_dec_stream.c
@@ -353,7 +353,6 @@ static enum xz_ret XZ_FUNC crc32_validate(struct xz_dec *s, struct xz_buf *b)
return XZ_DATA_ERROR;
s->pos += 8;
-
} while (s->pos < 32);
s->crc32 = 0;
@@ -753,7 +752,6 @@ XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_run(struct xz_dec *s, struct xz_buf *b)
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)
diff --git a/release/src/router/busybox/archival/libarchive/unxz/xz_stream.h b/release/src/router/busybox/archival/libarchive/unxz/xz_stream.h
index 36f2a7cbfa..66cb5a7055 100644
--- a/release/src/router/busybox/archival/libarchive/unxz/xz_stream.h
+++ b/release/src/router/busybox/archival/libarchive/unxz/xz_stream.h
@@ -25,15 +25,20 @@
#define STREAM_HEADER_SIZE 12
-#define HEADER_MAGIC "\3757zXZ\0"
+#define HEADER_MAGIC "\3757zXZ"
#define HEADER_MAGIC_SIZE 6
#define FOOTER_MAGIC "YZ"
#define FOOTER_MAGIC_SIZE 2
/*
- * Variable-length integer can hold a 63-bit unsigned integer, or a special
- * value to indicate that the value is unknown.
+ * Variable-length integer can hold a 63-bit unsigned integer or a special
+ * value indicating that the value is unknown.
+ *
+ * Experimental: vli_type can be defined to uint32_t to save a few bytes
+ * in code size (no effect on speed). Doing so limits the uncompressed and
+ * compressed size of the file to less than 256 MiB and may also weaken
+ * error detection slightly.
*/
typedef uint64_t vli_type;
diff --git a/release/src/router/busybox/archival/lzop.c b/release/src/router/busybox/archival/lzop.c
index fbe08417df..202de4d039 100644
--- a/release/src/router/busybox/archival/lzop.c
+++ b/release/src/router/busybox/archival/lzop.c
@@ -14,7 +14,7 @@
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
@@ -25,6 +25,26 @@
"Minimalized" for busybox by Alain Knaff
*/
+//config:config LZOP
+//config: bool "lzop"
+//config: default y
+//config: help
+//config: Lzop compression/decompresion.
+//config:
+//config:config LZOP_COMPR_HIGH
+//config: bool "lzop compression levels 7,8,9 (not very useful)"
+//config: default n
+//config: depends on LZOP
+//config: help
+//config: High levels (7,8,9) of lzop compression. These levels
+//config: are actually slower than gzip at equivalent compression ratios
+//config: and take up 3.2K of code.
+
+//applet:IF_LZOP(APPLET(lzop, BB_DIR_BIN, BB_SUID_DROP))
+//applet:IF_LZOP(APPLET_ODDNAME(lzopcat, lzop, BB_DIR_USR_BIN, BB_SUID_DROP, lzopcat))
+//applet:IF_LZOP(APPLET_ODDNAME(unlzop, lzop, BB_DIR_USR_BIN, BB_SUID_DROP, unlzop))
+//kbuild:lib-$(CONFIG_LZOP) += lzop.o
+
//usage:#define lzop_trivial_usage
//usage: "[-cfvd123456789CF] [FILE]..."
//usage:#define lzop_full_usage "\n\n"
@@ -51,6 +71,7 @@
//usage: "\n -F Don't store or verify checksum"
#include "libbb.h"
+#include "common_bufsiz.h"
#include "bb_archive.h"
#include "liblzo_interface.h"
@@ -116,7 +137,7 @@ static NOINLINE int lzo1x_optimize(uint8_t *in, unsigned in_len,
unsigned nl;
unsigned long o_m1_a = 0, o_m1_b = 0, o_m2 = 0, o_m3_a = 0, o_m3_b = 0;
-// LZO_UNUSED(wrkmem);
+// LZO_UNUSED(wrkmem);
*out_len = 0;
@@ -346,11 +367,11 @@ static NOINLINE int lzo1x_optimize(uint8_t *in, unsigned in_len,
return LZO_E_EOF_NOT_FOUND;
eof_found:
-// LZO_UNUSED(o_m1_a); LZO_UNUSED(o_m1_b); LZO_UNUSED(o_m2);
-// LZO_UNUSED(o_m3_a); LZO_UNUSED(o_m3_b);
+// LZO_UNUSED(o_m1_a); LZO_UNUSED(o_m1_b); LZO_UNUSED(o_m2);
+// LZO_UNUSED(o_m3_a); LZO_UNUSED(o_m3_b);
*out_len = pd(op, out);
return (ip == ip_end ? LZO_E_OK :
- (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
+ (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
}
/**********************************************************************/
@@ -423,8 +444,8 @@ struct globals {
chksum_t chksum_in;
chksum_t chksum_out;
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
-#define INIT_G() do { } while (0)
+#define G (*(struct globals*)bb_common_bufsiz1)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
//#define G (*ptr_to_globals)
//#define INIT_G() do {
// SET_PTR_TO_GLOBALS(xzalloc(sizeof(G)));
@@ -436,25 +457,27 @@ struct globals {
//#define LZOP_VERSION_STRING "1.01"
//#define LZOP_VERSION_DATE "Apr 27th 2003"
-#define OPTION_STRING "cfvdt123456789CF"
+#define OPTION_STRING "cfvqdt123456789CF"
+/* Note: must be kept in sync with archival/bbunzip.c */
enum {
OPT_STDOUT = (1 << 0),
OPT_FORCE = (1 << 1),
OPT_VERBOSE = (1 << 2),
- OPT_DECOMPRESS = (1 << 3),
- OPT_TEST = (1 << 4),
- OPT_1 = (1 << 5),
- OPT_2 = (1 << 6),
- OPT_3 = (1 << 7),
- OPT_4 = (1 << 8),
- OPT_5 = (1 << 9),
- OPT_6 = (1 << 10),
- OPT_789 = (7 << 11),
- OPT_7 = (1 << 11),
- OPT_8 = (1 << 12),
- OPT_C = (1 << 14),
- OPT_F = (1 << 15),
+ OPT_QUIET = (1 << 3),
+ OPT_DECOMPRESS = (1 << 4),
+ OPT_TEST = (1 << 5),
+ OPT_1 = (1 << 6),
+ OPT_2 = (1 << 7),
+ OPT_3 = (1 << 8),
+ OPT_4 = (1 << 9),
+ OPT_5 = (1 << 10),
+ OPT_6 = (1 << 11),
+ OPT_789 = (7 << 12),
+ OPT_7 = (1 << 13),
+ OPT_8 = (1 << 14),
+ OPT_C = (1 << 15),
+ OPT_F = (1 << 16),
};
/**********************************************************************/
@@ -618,7 +641,7 @@ static int lzo_get_method(header_t *h)
/**********************************************************************/
// compress a file
/**********************************************************************/
-static NOINLINE smallint lzo_compress(const header_t *h)
+static NOINLINE int lzo_compress(const header_t *h)
{
unsigned block_size = LZO_BLOCK_SIZE;
int r = 0; /* LZO_E_OK */
@@ -628,7 +651,6 @@ static NOINLINE smallint lzo_compress(const header_t *h)
uint32_t d_adler32 = ADLER32_INIT_VALUE;
uint32_t d_crc32 = CRC32_INIT_VALUE;
int l;
- smallint ok = 1;
uint8_t *wrk_mem = NULL;
if (h->method == M_LZO1X_1)
@@ -710,7 +732,7 @@ static NOINLINE smallint lzo_compress(const header_t *h)
free(wrk_mem);
free(b1);
free(b2);
- return ok;
+ return 1;
}
static FAST_FUNC void lzo_check(
@@ -731,7 +753,7 @@ static FAST_FUNC void lzo_check(
/**********************************************************************/
// decompress a file
/**********************************************************************/
-static NOINLINE smallint lzo_decompress(const header_t *h)
+static NOINLINE int lzo_decompress(const header_t *h)
{
unsigned block_size = LZO_BLOCK_SIZE;
int r;
@@ -739,7 +761,6 @@ static NOINLINE smallint lzo_decompress(const header_t *h)
uint32_t c_adler32 = ADLER32_INIT_VALUE;
uint32_t d_adler32 = ADLER32_INIT_VALUE;
uint32_t c_crc32 = CRC32_INIT_VALUE, d_crc32 = CRC32_INIT_VALUE;
- smallint ok = 1;
uint8_t *b1;
uint32_t mcs_block_size = MAX_COMPRESSED_SIZE(block_size);
uint8_t *b2 = NULL;
@@ -843,7 +864,7 @@ static NOINLINE smallint lzo_decompress(const header_t *h)
}
free(b2);
- return ok;
+ return 1;
}
/**********************************************************************/
@@ -875,7 +896,7 @@ static NOINLINE smallint lzo_decompress(const header_t *h)
* chksum_out
* The rest is identical.
*/
-static const unsigned char lzop_magic[9] = {
+static const unsigned char lzop_magic[9] ALIGN1 = {
0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a
};
@@ -1028,7 +1049,7 @@ static void lzo_set_method(header_t *h)
h->level = level;
}
-static smallint do_lzo_compress(void)
+static int do_lzo_compress(void)
{
header_t header;
@@ -1056,7 +1077,7 @@ static smallint do_lzo_compress(void)
/**********************************************************************/
// decompress
/**********************************************************************/
-static smallint do_lzo_decompress(void)
+static int do_lzo_decompress(void)
{
header_t header;
@@ -1077,7 +1098,7 @@ static char* FAST_FUNC make_new_name_lzop(char *filename, const char *expected_e
return xasprintf("%s.lzo", filename);
}
-static IF_DESKTOP(long long) int FAST_FUNC pack_lzop(transformer_aux_data_t *aux UNUSED_PARAM)
+static IF_DESKTOP(long long) int FAST_FUNC pack_lzop(transformer_state_t *xstate UNUSED_PARAM)
{
if (option_mask32 & OPT_DECOMPRESS)
return do_lzo_decompress();
@@ -1093,7 +1114,7 @@ int lzop_main(int argc UNUSED_PARAM, char **argv)
if (applet_name[4] == 'c')
option_mask32 |= (OPT_STDOUT | OPT_DECOMPRESS);
/* unlzop? */
- if (applet_name[0] == 'u')
+ if (applet_name[4] == 'o')
option_mask32 |= OPT_DECOMPRESS;
global_crc32_table = crc32_filltable(NULL, 0);
diff --git a/release/src/router/busybox/archival/rpm.c b/release/src/router/busybox/archival/rpm.c
index 6757a6cebf..83160f975e 100644
--- a/release/src/router/busybox/archival/rpm.c
+++ b/release/src/router/busybox/archival/rpm.c
@@ -7,6 +7,15 @@
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//config:config RPM
+//config: bool "rpm"
+//config: default y
+//config: help
+//config: Mini RPM applet - queries and extracts RPM packages.
+
+//applet:IF_RPM(APPLET(rpm, BB_DIR_BIN, BB_SUID_DROP))
+//kbuild:lib-$(CONFIG_RPM) += rpm.o
+
//usage:#define rpm_trivial_usage
//usage: "-i PACKAGE.rpm; rpm -qp[ildc] PACKAGE.rpm"
//usage:#define rpm_full_usage "\n\n"
@@ -14,12 +23,13 @@
//usage: "\nCommands:"
//usage: "\n -i Install package"
//usage: "\n -qp Query package"
-//usage: "\n -i Show information"
-//usage: "\n -l List contents"
-//usage: "\n -d List documents"
-//usage: "\n -c List config files"
+//usage: "\n -qpi Show information"
+//usage: "\n -qpl List contents"
+//usage: "\n -qpd List documents"
+//usage: "\n -qpc List config files"
#include "libbb.h"
+#include "common_bufsiz.h"
#include "bb_archive.h"
#include "rpm.h"
@@ -79,136 +89,13 @@ typedef struct {
uint32_t count; /* 4 byte count */
} rpm_index;
-static void *map;
-static rpm_index **mytags;
-static int tagcount;
-
-static void extract_cpio(int fd, const char *source_rpm);
-static rpm_index **rpm_gettags(int fd, int *num_tags);
-static int bsearch_rpmtag(const void *key, const void *item);
-static char *rpm_getstr(int tag, int itemindex);
-static int rpm_getint(int tag, int itemindex);
-static int rpm_getcount(int tag);
-static void fileaction_dobackup(char *filename, int fileref);
-static void fileaction_setowngrp(char *filename, int fileref);
-static void loop_through_files(int filetag, void (*fileaction)(char *filename, int fileref));
-
-int rpm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int rpm_main(int argc, char **argv)
-{
- int opt = 0, func = 0, rpm_fd, offset;
- const int pagesize = getpagesize();
-
- while ((opt = getopt(argc, argv, "iqpldc")) != -1) {
- switch (opt) {
- case 'i': /* First arg: Install mode, with q: Information */
- if (!func) func = rpm_install;
- else func |= rpm_query_info;
- break;
- case 'q': /* First arg: Query mode */
- if (func) bb_show_usage();
- func = rpm_query;
- break;
- case 'p': /* Query a package */
- func |= rpm_query_package;
- break;
- case 'l': /* List files in a package */
- func |= rpm_query_list;
- break;
- case 'd': /* List doc files in a package (implies list) */
- func |= rpm_query_list;
- func |= rpm_query_list_doc;
- break;
- case 'c': /* List config files in a package (implies list) */
- func |= rpm_query_list;
- func |= rpm_query_list_config;
- break;
- default:
- bb_show_usage();
- }
- }
- argv += optind;
- //argc -= optind;
- if (!argv[0]) {
- bb_show_usage();
- }
-
- while (*argv) {
- const char *source_rpm;
-
- rpm_fd = xopen(*argv++, O_RDONLY);
- mytags = rpm_gettags(rpm_fd, &tagcount);
- if (!mytags)
- bb_error_msg_and_die("error reading rpm header");
- offset = xlseek(rpm_fd, 0, SEEK_CUR);
- /* Mimimum is one page */
- map = mmap(0, offset > pagesize ? (offset + offset % pagesize) : pagesize, PROT_READ, MAP_PRIVATE, rpm_fd, 0);
-
- source_rpm = rpm_getstr(TAG_SOURCERPM, 0);
-
- if (func & rpm_install) {
- /* Backup any config files */
- loop_through_files(TAG_BASENAMES, fileaction_dobackup);
- /* Extact the archive */
- extract_cpio(rpm_fd, source_rpm);
- /* Set the correct file uid/gid's */
- loop_through_files(TAG_BASENAMES, fileaction_setowngrp);
- }
- else if ((func & (rpm_query|rpm_query_package)) == (rpm_query|rpm_query_package)) {
- if (!(func & (rpm_query_info|rpm_query_list))) {
- /* If just a straight query, just give package name */
- printf("%s-%s-%s\n", rpm_getstr(TAG_NAME, 0), rpm_getstr(TAG_VERSION, 0), rpm_getstr(TAG_RELEASE, 0));
- }
- if (func & rpm_query_info) {
- /* Do the nice printout */
- time_t bdate_time;
- struct tm *bdate_ptm;
- char bdatestring[50];
- const char *p;
-
- p = rpm_getstr(TAG_PREFIXS, 0);
- if (!p) p = "(not relocateable)";
- printf("Name : %-29sRelocations: %s\n", rpm_getstr(TAG_NAME, 0), p);
- p = rpm_getstr(TAG_VENDOR, 0);
- if (!p) p = "(none)";
- printf("Version : %-34sVendor: %s\n", rpm_getstr(TAG_VERSION, 0), p);
- bdate_time = rpm_getint(TAG_BUILDTIME, 0);
- bdate_ptm = localtime(&bdate_time);
- strftime(bdatestring, 50, "%a %d %b %Y %T %Z", bdate_ptm);
- printf("Release : %-30sBuild Date: %s\n", rpm_getstr(TAG_RELEASE, 0), bdatestring);
- printf("Install date: %-30sBuild Host: %s\n", "(not installed)", rpm_getstr(TAG_BUILDHOST, 0));
- printf("Group : %-30sSource RPM: %s\n", rpm_getstr(TAG_GROUP, 0), source_rpm);
- printf("Size : %-33dLicense: %s\n", rpm_getint(TAG_SIZE, 0), rpm_getstr(TAG_LICENSE, 0));
- printf("URL : %s\n", rpm_getstr(TAG_URL, 0));
- printf("Summary : %s\n", rpm_getstr(TAG_SUMMARY, 0));
- printf("Description :\n%s\n", rpm_getstr(TAG_DESCRIPTION, 0));
- }
- if (func & rpm_query_list) {
- int count, it, flags;
- count = rpm_getcount(TAG_BASENAMES);
- for (it = 0; it < count; it++) {
- flags = rpm_getint(TAG_FILEFLAGS, it);
- switch (func & (rpm_query_list_doc|rpm_query_list_config)) {
- case rpm_query_list_doc:
- if (!(flags & RPMFILE_DOC)) continue;
- break;
- case rpm_query_list_config:
- if (!(flags & RPMFILE_CONFIG)) continue;
- break;
- case rpm_query_list_doc|rpm_query_list_config:
- if (!(flags & (RPMFILE_CONFIG|RPMFILE_DOC))) continue;
- break;
- }
- printf("%s%s\n",
- rpm_getstr(TAG_DIRNAMES, rpm_getint(TAG_DIRINDEXES, it)),
- rpm_getstr(TAG_BASENAMES, it));
- }
- }
- }
- free(mytags);
- }
- return 0;
-}
+struct globals {
+ void *map;
+ rpm_index **mytags;
+ int tagcount;
+} FIX_ALIASING;
+#define G (*(struct globals*)bb_common_bufsiz1)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
static void extract_cpio(int fd, const char *source_rpm)
{
@@ -231,12 +118,12 @@ static void extract_cpio(int fd, const char *source_rpm)
/* compat: overwrite existing files.
* try "rpm -i foo.src.rpm" few times in a row -
* standard rpm will not complain.
- * (TODO? real rpm creates "file;1234" and then renames it) */
- | ARCHIVE_UNLINK_OLD;
+ */
+ | ARCHIVE_REPLACE_VIA_RENAME;
archive_handle->src_fd = fd;
/*archive_handle->offset = 0; - init_handle() did it */
- setup_unzip_on_fd(archive_handle->src_fd, /*fail_if_not_detected:*/ 1);
+ setup_unzip_on_fd(archive_handle->src_fd, /*fail_if_not_compressed:*/ 1);
while (get_header_cpio(archive_handle) == EXIT_SUCCESS)
continue;
}
@@ -294,7 +181,7 @@ static int bsearch_rpmtag(const void *key, const void *item)
static int rpm_getcount(int tag)
{
rpm_index **found;
- found = bsearch(&tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag);
+ found = bsearch(&tag, G.mytags, G.tagcount, sizeof(struct rpmtag *), bsearch_rpmtag);
if (!found)
return 0;
return found[0]->count;
@@ -303,7 +190,7 @@ static int rpm_getcount(int tag)
static char *rpm_getstr(int tag, int itemindex)
{
rpm_index **found;
- found = bsearch(&tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag);
+ found = bsearch(&tag, G.mytags, G.tagcount, sizeof(struct rpmtag *), bsearch_rpmtag);
if (!found || itemindex >= found[0]->count)
return NULL;
if (found[0]->type == RPM_STRING_TYPE
@@ -311,7 +198,7 @@ static char *rpm_getstr(int tag, int itemindex)
|| found[0]->type == RPM_STRING_ARRAY_TYPE
) {
int n;
- char *tmpstr = (char *) map + found[0]->offset;
+ char *tmpstr = (char *) G.map + found[0]->offset;
for (n = 0; n < itemindex; n++)
tmpstr = tmpstr + strlen(tmpstr) + 1;
return tmpstr;
@@ -322,32 +209,25 @@ static char *rpm_getstr(int tag, int itemindex)
static int rpm_getint(int tag, int itemindex)
{
rpm_index **found;
- int *tmpint; /* NB: using int8_t* would be easier to code */
+ char *tmpint;
/* gcc throws warnings here when sizeof(void*)!=sizeof(int) ...
* it's ok to ignore it because tag won't be used as a pointer */
- found = bsearch(&tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag);
+ found = bsearch(&tag, G.mytags, G.tagcount, sizeof(struct rpmtag *), bsearch_rpmtag);
if (!found || itemindex >= found[0]->count)
return -1;
- tmpint = (int *) ((char *) map + found[0]->offset);
-
+ tmpint = (char *) G.map + found[0]->offset;
if (found[0]->type == RPM_INT32_TYPE) {
- tmpint = (int *) ((char *) tmpint + itemindex*4);
- /*return ntohl(*tmpint);*/
- /* int can be != int32_t */
+ tmpint += itemindex*4;
return ntohl(*(int32_t*)tmpint);
}
if (found[0]->type == RPM_INT16_TYPE) {
- tmpint = (int *) ((char *) tmpint + itemindex*2);
- /* ??? read int, and THEN ntohs() it?? */
- /*return ntohs(*tmpint);*/
+ tmpint += itemindex*2;
return ntohs(*(int16_t*)tmpint);
}
if (found[0]->type == RPM_INT8_TYPE) {
- tmpint = (int *) ((char *) tmpint + itemindex);
- /* ??? why we don't read byte here??? */
- /*return ntohs(*tmpint);*/
+ tmpint += itemindex;
return *(int8_t*)tmpint;
}
return -1;
@@ -392,3 +272,134 @@ static void loop_through_files(int filetag, void (*fileaction)(char *filename, i
free(filename);
}
}
+
+int rpm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int rpm_main(int argc, char **argv)
+{
+ int opt, func = 0;
+ const unsigned pagesize = getpagesize();
+
+ while ((opt = getopt(argc, argv, "iqpldc")) != -1) {
+ switch (opt) {
+ case 'i': /* First arg: Install mode, with q: Information */
+ if (!func) func = rpm_install;
+ else func |= rpm_query_info;
+ break;
+ case 'q': /* First arg: Query mode */
+ if (func) bb_show_usage();
+ func = rpm_query;
+ break;
+ case 'p': /* Query a package */
+ func |= rpm_query_package;
+ break;
+ case 'l': /* List files in a package */
+ func |= rpm_query_list;
+ break;
+ case 'd': /* List doc files in a package (implies list) */
+ func |= rpm_query_list;
+ func |= rpm_query_list_doc;
+ break;
+ case 'c': /* List config files in a package (implies list) */
+ func |= rpm_query_list;
+ func |= rpm_query_list_config;
+ break;
+ default:
+ bb_show_usage();
+ }
+ }
+ argv += optind;
+ //argc -= optind;
+ if (!argv[0]) {
+ bb_show_usage();
+ }
+
+ while (*argv) {
+ int rpm_fd;
+ unsigned mapsize;
+ const char *source_rpm;
+
+ rpm_fd = xopen(*argv++, O_RDONLY);
+ G.mytags = rpm_gettags(rpm_fd, &G.tagcount);
+ if (!G.mytags)
+ bb_error_msg_and_die("error reading rpm header");
+ mapsize = xlseek(rpm_fd, 0, SEEK_CUR);
+ mapsize = (mapsize + pagesize) & -(int)pagesize;
+ /* Some NOMMU systems prefer MAP_PRIVATE over MAP_SHARED */
+ G.map = mmap(0, mapsize, PROT_READ, MAP_PRIVATE, rpm_fd, 0);
+//FIXME: error check?
+
+ source_rpm = rpm_getstr(TAG_SOURCERPM, 0);
+
+ if (func & rpm_install) {
+ /* Backup any config files */
+ loop_through_files(TAG_BASENAMES, fileaction_dobackup);
+ /* Extact the archive */
+ extract_cpio(rpm_fd, source_rpm);
+ /* Set the correct file uid/gid's */
+ loop_through_files(TAG_BASENAMES, fileaction_setowngrp);
+ }
+ else if ((func & (rpm_query|rpm_query_package)) == (rpm_query|rpm_query_package)) {
+ if (!(func & (rpm_query_info|rpm_query_list))) {
+ /* If just a straight query, just give package name */
+ printf("%s-%s-%s\n", rpm_getstr(TAG_NAME, 0), rpm_getstr(TAG_VERSION, 0), rpm_getstr(TAG_RELEASE, 0));
+ }
+ if (func & rpm_query_info) {
+ /* Do the nice printout */
+ time_t bdate_time;
+ struct tm *bdate_ptm;
+ char bdatestring[50];
+ const char *p;
+
+ printf("%-12s: %s\n", "Name" , rpm_getstr(TAG_NAME, 0));
+ /* TODO compat: add "Epoch" here */
+ printf("%-12s: %s\n", "Version" , rpm_getstr(TAG_VERSION, 0));
+ printf("%-12s: %s\n", "Release" , rpm_getstr(TAG_RELEASE, 0));
+ /* add "Architecture" */
+ printf("%-12s: %s\n", "Install Date", "(not installed)");
+ printf("%-12s: %s\n", "Group" , rpm_getstr(TAG_GROUP, 0));
+ printf("%-12s: %d\n", "Size" , rpm_getint(TAG_SIZE, 0));
+ printf("%-12s: %s\n", "License" , rpm_getstr(TAG_LICENSE, 0));
+ /* add "Signature" */
+ printf("%-12s: %s\n", "Source RPM" , source_rpm ? source_rpm : "(none)");
+ bdate_time = rpm_getint(TAG_BUILDTIME, 0);
+ bdate_ptm = localtime(&bdate_time);
+ strftime(bdatestring, 50, "%a %d %b %Y %T %Z", bdate_ptm);
+ printf("%-12s: %s\n", "Build Date" , bdatestring);
+ printf("%-12s: %s\n", "Build Host" , rpm_getstr(TAG_BUILDHOST, 0));
+ p = rpm_getstr(TAG_PREFIXS, 0);
+ printf("%-12s: %s\n", "Relocations" , p ? p : "(not relocatable)");
+ /* add "Packager" */
+ p = rpm_getstr(TAG_VENDOR, 0);
+ printf("%-12s: %s\n", "Vendor" , p ? p : "(none)");
+ printf("%-12s: %s\n", "URL" , rpm_getstr(TAG_URL, 0));
+ printf("%-12s: %s\n", "Summary" , rpm_getstr(TAG_SUMMARY, 0));
+ printf("Description :\n%s\n", rpm_getstr(TAG_DESCRIPTION, 0));
+ }
+ if (func & rpm_query_list) {
+ int count, it, flags;
+ count = rpm_getcount(TAG_BASENAMES);
+ for (it = 0; it < count; it++) {
+ flags = rpm_getint(TAG_FILEFLAGS, it);
+ switch (func & (rpm_query_list_doc|rpm_query_list_config)) {
+ case rpm_query_list_doc:
+ if (!(flags & RPMFILE_DOC)) continue;
+ break;
+ case rpm_query_list_config:
+ if (!(flags & RPMFILE_CONFIG)) continue;
+ break;
+ case rpm_query_list_doc|rpm_query_list_config:
+ if (!(flags & (RPMFILE_CONFIG|RPMFILE_DOC))) continue;
+ break;
+ }
+ printf("%s%s\n",
+ rpm_getstr(TAG_DIRNAMES, rpm_getint(TAG_DIRINDEXES, it)),
+ rpm_getstr(TAG_BASENAMES, it));
+ }
+ }
+ }
+ munmap(G.map, mapsize);
+ free(G.mytags);
+ close(rpm_fd);
+ }
+ return 0;
+}
diff --git a/release/src/router/busybox/archival/rpm2cpio.c b/release/src/router/busybox/archival/rpm2cpio.c
index f3dfa51594..7057570f51 100644
--- a/release/src/router/busybox/archival/rpm2cpio.c
+++ b/release/src/router/busybox/archival/rpm2cpio.c
@@ -7,6 +7,15 @@
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//config:config RPM2CPIO
+//config: bool "rpm2cpio"
+//config: default y
+//config: help
+//config: Converts a RPM file into a CPIO archive.
+
+//applet:IF_RPM2CPIO(APPLET(rpm2cpio, BB_DIR_USR_BIN, BB_SUID_DROP))
+//kbuild:lib-$(CONFIG_RPM2CPIO) += rpm2cpio.o
+
//usage:#define rpm2cpio_trivial_usage
//usage: "package.rpm"
//usage:#define rpm2cpio_full_usage "\n\n"
@@ -71,7 +80,7 @@ int rpm2cpio_main(int argc UNUSED_PARAM, char **argv)
// signal(SIGCHLD, check_errors_in_children);
/* This works, but doesn't report uncompress errors (they happen in child) */
- setup_unzip_on_fd(rpm_fd, /*fail_if_not_detected:*/ 1);
+ setup_unzip_on_fd(rpm_fd, /*fail_if_not_compressed:*/ 1);
if (bb_copyfd_eof(rpm_fd, STDOUT_FILENO) < 0)
bb_error_msg_and_die("error unpacking");
diff --git a/release/src/router/busybox/archival/tar.c b/release/src/router/busybox/archival/tar.c
index cf972c24c6..7434e22e40 100644
--- a/release/src/router/busybox/archival/tar.c
+++ b/release/src/router/busybox/archival/tar.c
@@ -22,7 +22,6 @@
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
-
/* TODO: security with -C DESTDIR option can be enhanced.
* Consider tar file created via:
* $ tar cvf bug.tar anything.txt
@@ -42,27 +41,128 @@
* This doesn't feel right, and IIRC GNU tar doesn't do that.
*/
+//config:config TAR
+//config: bool "tar"
+//config: default y
+//config: help
+//config: tar is an archiving program. It's commonly used with gzip to
+//config: create compressed archives. It's probably the most widely used
+//config: UNIX archive program.
+//config:
+//config:config FEATURE_TAR_CREATE
+//config: bool "Enable archive creation"
+//config: default y
+//config: depends on TAR
+//config: help
+//config: If you enable this option you'll be able to create
+//config: tar archives using the `-c' option.
+//config:
+//config:config FEATURE_TAR_AUTODETECT
+//config: bool "Autodetect compressed tarballs"
+//config: default y
+//config: depends on TAR && (FEATURE_SEAMLESS_Z || FEATURE_SEAMLESS_GZ || FEATURE_SEAMLESS_BZ2 || FEATURE_SEAMLESS_LZMA || FEATURE_SEAMLESS_XZ)
+//config: help
+//config: With this option tar can automatically detect compressed
+//config: tarballs. Currently it works only on files (not pipes etc).
+//config:
+//config:config FEATURE_TAR_FROM
+//config: bool "Enable -X (exclude from) and -T (include from) options)"
+//config: default y
+//config: depends on TAR
+//config: help
+//config: If you enable this option you'll be able to specify
+//config: a list of files to include or exclude from an archive.
+//config:
+//config:config FEATURE_TAR_OLDGNU_COMPATIBILITY
+//config: bool "Support for old tar header format"
+//config: default y
+//config: depends on TAR || DPKG
+//config: help
+//config: This option is required to unpack archives created in
+//config: the old GNU format; help to kill this old format by
+//config: repacking your ancient archives with the new format.
+//config:
+//config:config FEATURE_TAR_OLDSUN_COMPATIBILITY
+//config: bool "Enable untarring of tarballs with checksums produced by buggy Sun tar"
+//config: default y
+//config: depends on TAR || DPKG
+//config: help
+//config: This option is required to unpack archives created by some old
+//config: version of Sun's tar (it was calculating checksum using signed
+//config: arithmetic). It is said to be fixed in newer Sun tar, but "old"
+//config: tarballs still exist.
+//config:
+//config:config FEATURE_TAR_GNU_EXTENSIONS
+//config: bool "Support for GNU tar extensions (long filenames)"
+//config: default y
+//config: depends on TAR || DPKG
+//config: help
+//config: With this option busybox supports GNU long filenames and
+//config: linknames.
+//config:
+//config:config FEATURE_TAR_LONG_OPTIONS
+//config: bool "Enable long options"
+//config: default y
+//config: depends on TAR && LONG_OPTS
+//config: help
+//config: Enable use of long options, increases size by about 400 Bytes
+//config:
+//config:config FEATURE_TAR_TO_COMMAND
+//config: bool "Support for writing to an external program"
+//config: default y
+//config: depends on TAR && FEATURE_TAR_LONG_OPTIONS
+//config: help
+//config: If you enable this option you'll be able to instruct tar to send
+//config: the contents of each extracted file to the standard input of an
+//config: external program.
+//config:
+//config:config FEATURE_TAR_UNAME_GNAME
+//config: bool "Enable use of user and group names"
+//config: default y
+//config: depends on TAR
+//config: help
+//config: Enables use of user and group names in tar. This affects contents
+//config: listings (-t) and preserving permissions when unpacking (-p).
+//config: +200 bytes.
+//config:
+//config:config FEATURE_TAR_NOPRESERVE_TIME
+//config: bool "Enable -m (do not preserve time) option"
+//config: default y
+//config: depends on TAR
+//config: help
+//config: With this option busybox supports GNU tar -m
+//config: (do not preserve time) option.
+//config:
+//config:config FEATURE_TAR_SELINUX
+//config: bool "Support for extracting SELinux labels"
+//config: default n
+//config: depends on TAR && SELINUX
+//config: help
+//config: With this option busybox supports restoring SELinux labels
+//config: when extracting files from tar archives.
+
+//applet:IF_TAR(APPLET(tar, BB_DIR_BIN, BB_SUID_DROP))
+//kbuild:lib-$(CONFIG_TAR) += tar.o
+
#include <fnmatch.h>
#include "libbb.h"
+#include "common_bufsiz.h"
#include "bb_archive.h"
/* FIXME: Stop using this non-standard feature */
#ifndef FNM_LEADING_DIR
# define FNM_LEADING_DIR 0
#endif
-
-//#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__)
-#define DBG(...) ((void)0)
+#if 0
+# define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__)
+#else
+# define DBG(...) ((void)0)
+#endif
+#define DBG_OPTION_PARSING 0
#define block_buf bb_common_bufsiz1
-
-
-#if !ENABLE_FEATURE_SEAMLESS_GZ && !ENABLE_FEATURE_SEAMLESS_BZ2
-/* Do not pass gzip flag to writeTarFile() */
-#define writeTarFile(tar_fd, verboseFlag, dereferenceFlag, include, exclude, gzip) \
- writeTarFile(tar_fd, verboseFlag, dereferenceFlag, include, exclude)
-#endif
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
#if ENABLE_FEATURE_TAR_CREATE
@@ -333,13 +433,13 @@ static int writeTarHeader(struct TarBallInfo *tbInfo,
&& (filesize <= 0x3fffffffffffffffffffffffLL)
#endif
) {
- /* 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
+ /* 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
*/
char *p8 = header.size + sizeof(header.size);
do {
@@ -519,21 +619,12 @@ static int FAST_FUNC writeFileToTarball(const char *fileName, struct stat *statb
return TRUE;
}
-#if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
-# if !(ENABLE_FEATURE_SEAMLESS_GZ && ENABLE_FEATURE_SEAMLESS_BZ2)
-# define vfork_compressor(tar_fd, gzip) vfork_compressor(tar_fd)
-# endif
+#if SEAMLESS_COMPRESSION
/* Don't inline: vfork scares gcc and pessimizes code */
-static void NOINLINE vfork_compressor(int tar_fd, int gzip)
+static void NOINLINE vfork_compressor(int tar_fd, const char *gzip)
{
pid_t gzipPid;
-# if ENABLE_FEATURE_SEAMLESS_GZ && ENABLE_FEATURE_SEAMLESS_BZ2
- const char *zip_exec = (gzip == 1) ? "gzip" : "bzip2";
-# elif ENABLE_FEATURE_SEAMLESS_GZ
- const char *zip_exec = "gzip";
-# else /* only ENABLE_FEATURE_SEAMLESS_BZ2 */
- const char *zip_exec = "bzip2";
-# endif
+
// On Linux, vfork never unpauses parent early, although standard
// allows for that. Do we want to waste bytes checking for it?
# define WAIT_FOR_CHILD 0
@@ -547,11 +638,6 @@ static void NOINLINE vfork_compressor(int tar_fd, int gzip)
signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */
-# if defined(__GNUC__) && __GNUC__
- /* Avoid vfork clobbering */
- (void) &zip_exec;
-# endif
-
gzipPid = xvfork();
if (gzipPid == 0) {
@@ -567,7 +653,7 @@ static void NOINLINE vfork_compressor(int tar_fd, int gzip)
xmove_fd(gzipDataPipe.rd, 0);
xmove_fd(tar_fd, 1);
/* exec gzip/bzip2 program/applet */
- BB_EXECLP(zip_exec, zip_exec, "-f", NULL);
+ BB_EXECLP(gzip, gzip, "-f", (char *)0);
vfork_exec_errno = errno;
_exit(EXIT_FAILURE);
}
@@ -590,16 +676,21 @@ static void NOINLINE vfork_compressor(int tar_fd, int gzip)
# endif
if (vfork_exec_errno) {
errno = vfork_exec_errno;
- bb_perror_msg_and_die("can't execute '%s'", zip_exec);
+ bb_perror_msg_and_die("can't execute '%s'", gzip);
}
}
-#endif /* ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2 */
+#endif /* SEAMLESS_COMPRESSION */
+#if !SEAMLESS_COMPRESSION
+/* Do not pass gzip flag to writeTarFile() */
+#define writeTarFile(tar_fd, verboseFlag, recurseFlags, include, exclude, gzip) \
+ writeTarFile(tar_fd, verboseFlag, recurseFlags, include, exclude)
+#endif
/* gcc 4.2.1 inlines it, making code bigger */
static NOINLINE int writeTarFile(int tar_fd, int verboseFlag,
- int dereferenceFlag, const llist_t *include,
- const llist_t *exclude, int gzip)
+ int recurseFlags, const llist_t *include,
+ const llist_t *exclude, const char *gzip)
{
int errorFlag = FALSE;
struct TarBallInfo tbInfo;
@@ -612,7 +703,7 @@ static NOINLINE int writeTarFile(int tar_fd, int verboseFlag,
* can avoid including the tarball into itself.... */
xfstat(tbInfo.tarFd, &tbInfo.tarFileStatBuf, "can't stat tar file");
-#if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
+#if SEAMLESS_COMPRESSION
if (gzip)
vfork_compressor(tbInfo.tarFd, gzip);
#endif
@@ -621,8 +712,7 @@ static NOINLINE int writeTarFile(int tar_fd, int verboseFlag,
/* Read the directory/files and iterate over them one at a time */
while (include) {
- if (!recursive_action(include->data, ACTION_RECURSE |
- (dereferenceFlag ? ACTION_FOLLOWLINKS : 0),
+ if (!recursive_action(include->data, recurseFlags,
writeFileToTarball, writeFileToTarball, &tbInfo, 0)
) {
errorFlag = TRUE;
@@ -648,7 +738,7 @@ static NOINLINE int writeTarFile(int tar_fd, int verboseFlag,
if (errorFlag)
bb_error_msg("error exit delayed from previous errors");
-#if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
+#if SEAMLESS_COMPRESSION
if (gzip) {
int status;
if (safe_waitpid(-1, &status, 0) == -1)
@@ -660,11 +750,9 @@ static NOINLINE int writeTarFile(int tar_fd, int verboseFlag,
#endif
return errorFlag;
}
-#else
-int writeTarFile(int tar_fd, int verboseFlag,
- int dereferenceFlag, const llist_t *include,
- const llist_t *exclude, int gzip);
-#endif /* FEATURE_TAR_CREATE */
+#else /* !FEATURE_TAR_CREATE */
+# define writeTarFile(...) 0
+#endif
#if ENABLE_FEATURE_TAR_FROM
static llist_t *append_file_list_to_list(llist_t *list)
@@ -680,20 +768,19 @@ static llist_t *append_file_list_to_list(llist_t *list)
char *cp = last_char_is(line, '/');
if (cp > line)
*cp = '\0';
- llist_add_to(&newlist, line);
+ llist_add_to_end(&newlist, line);
}
fclose(src_stream);
}
return newlist;
}
-#else
-# define append_file_list_to_list(x) 0
#endif
//usage:#define tar_trivial_usage
//usage: "-[" IF_FEATURE_TAR_CREATE("c") "xt"
//usage: IF_FEATURE_SEAMLESS_Z("Z")
//usage: IF_FEATURE_SEAMLESS_GZ("z")
+//usage: IF_FEATURE_SEAMLESS_XZ("J")
//usage: IF_FEATURE_SEAMLESS_BZ2("j")
//usage: IF_FEATURE_SEAMLESS_LZMA("a")
//usage: IF_FEATURE_TAR_CREATE("h")
@@ -720,6 +807,9 @@ static llist_t *append_file_list_to_list(llist_t *list)
//usage: IF_FEATURE_SEAMLESS_GZ(
//usage: "\n z (De)compress using gzip"
//usage: )
+//usage: IF_FEATURE_SEAMLESS_XZ(
+//usage: "\n J (De)compress using xz"
+//usage: )
//usage: IF_FEATURE_SEAMLESS_BZ2(
//usage: "\n j (De)compress using bzip2"
//usage: )
@@ -749,6 +839,7 @@ static llist_t *append_file_list_to_list(llist_t *list)
// o no-same-owner
// p same-permissions
// k keep-old
+// no-recursion
// numeric-owner
// no-same-permissions
// overwrite
@@ -765,9 +856,12 @@ enum {
IF_FEATURE_TAR_FROM( OPTBIT_INCLUDE_FROM,)
IF_FEATURE_TAR_FROM( OPTBIT_EXCLUDE_FROM,)
IF_FEATURE_SEAMLESS_GZ( OPTBIT_GZIP ,)
- IF_FEATURE_SEAMLESS_Z( OPTBIT_COMPRESS ,) // 16th bit
+ IF_FEATURE_SEAMLESS_XZ( OPTBIT_XZ ,) // 16th bit
+ IF_FEATURE_SEAMLESS_Z( OPTBIT_COMPRESS ,)
IF_FEATURE_TAR_NOPRESERVE_TIME(OPTBIT_NOPRESERVE_TIME,)
#if ENABLE_FEATURE_TAR_LONG_OPTIONS
+ OPTBIT_STRIP_COMPONENTS,
+ OPTBIT_NORECURSION,
IF_FEATURE_TAR_TO_COMMAND(OPTBIT_2COMMAND ,)
OPTBIT_NUMERIC_OWNER,
OPTBIT_NOPRESERVE_PERM,
@@ -789,14 +883,17 @@ enum {
OPT_INCLUDE_FROM = IF_FEATURE_TAR_FROM( (1 << OPTBIT_INCLUDE_FROM)) + 0, // T
OPT_EXCLUDE_FROM = IF_FEATURE_TAR_FROM( (1 << OPTBIT_EXCLUDE_FROM)) + 0, // X
OPT_GZIP = IF_FEATURE_SEAMLESS_GZ( (1 << OPTBIT_GZIP )) + 0, // z
+ OPT_XZ = IF_FEATURE_SEAMLESS_XZ( (1 << OPTBIT_XZ )) + 0, // J
OPT_COMPRESS = IF_FEATURE_SEAMLESS_Z( (1 << OPTBIT_COMPRESS )) + 0, // Z
- OPT_NOPRESERVE_TIME = IF_FEATURE_TAR_NOPRESERVE_TIME((1 << OPTBIT_NOPRESERVE_TIME)) + 0, // m
- OPT_2COMMAND = IF_FEATURE_TAR_TO_COMMAND( (1 << OPTBIT_2COMMAND )) + 0, // to-command
- OPT_NUMERIC_OWNER = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NUMERIC_OWNER )) + 0, // numeric-owner
- OPT_NOPRESERVE_PERM = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NOPRESERVE_PERM)) + 0, // no-same-permissions
- OPT_OVERWRITE = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_OVERWRITE )) + 0, // overwrite
-
- OPT_ANY_COMPRESS = (OPT_BZIP2 | OPT_LZMA | OPT_GZIP | OPT_COMPRESS),
+ OPT_NOPRESERVE_TIME = IF_FEATURE_TAR_NOPRESERVE_TIME((1 << OPTBIT_NOPRESERVE_TIME)) + 0, // m
+ OPT_STRIP_COMPONENTS = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_STRIP_COMPONENTS)) + 0, // strip-components
+ OPT_NORECURSION = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NORECURSION )) + 0, // no-recursion
+ OPT_2COMMAND = IF_FEATURE_TAR_TO_COMMAND( (1 << OPTBIT_2COMMAND )) + 0, // to-command
+ OPT_NUMERIC_OWNER = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NUMERIC_OWNER )) + 0, // numeric-owner
+ OPT_NOPRESERVE_PERM = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NOPRESERVE_PERM)) + 0, // no-same-permissions
+ OPT_OVERWRITE = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_OVERWRITE )) + 0, // overwrite
+
+ OPT_ANY_COMPRESS = (OPT_BZIP2 | OPT_LZMA | OPT_GZIP | OPT_XZ | OPT_COMPRESS),
};
#if ENABLE_FEATURE_TAR_LONG_OPTIONS
static const char tar_longopts[] ALIGN1 =
@@ -829,12 +926,17 @@ static const char tar_longopts[] ALIGN1 =
# if ENABLE_FEATURE_SEAMLESS_GZ
"gzip\0" No_argument "z"
# endif
+# if ENABLE_FEATURE_SEAMLESS_XZ
+ "xz\0" No_argument "J"
+# endif
# if ENABLE_FEATURE_SEAMLESS_Z
"compress\0" No_argument "Z"
# endif
# if ENABLE_FEATURE_TAR_NOPRESERVE_TIME
"touch\0" No_argument "m"
# endif
+ "strip-components\0" Required_argument "\xf9"
+ "no-recursion\0" No_argument "\xfa"
# if ENABLE_FEATURE_TAR_TO_COMMAND
"to-command\0" Required_argument "\xfb"
# endif
@@ -863,6 +965,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
#if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM
llist_t *excludes = NULL;
#endif
+ INIT_G();
/* Initialise default values */
tar_handle = init_handle();
@@ -879,15 +982,28 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
"tt:vv:" // count -t,-v
IF_FEATURE_TAR_FROM("X::T::") // cumulative lists
#if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM
- "\xff::" // cumulative lists for --exclude
+ "\xff::" // --exclude=PATTERN is a list
#endif
IF_FEATURE_TAR_CREATE("c:") "t:x:" // at least one of these is reqd
IF_FEATURE_TAR_CREATE("c--tx:t--cx:x--ct") // mutually exclusive
- IF_NOT_FEATURE_TAR_CREATE("t--x:x--t"); // mutually exclusive
+ IF_NOT_FEATURE_TAR_CREATE("t--x:x--t") // mutually exclusive
+#if ENABLE_FEATURE_TAR_LONG_OPTIONS
+ ":\xf9+" // --strip-components=NUM
+#endif
+ ;
#if ENABLE_FEATURE_TAR_LONG_OPTIONS
applet_long_options = tar_longopts;
#endif
#if ENABLE_DESKTOP
+ /* Lie to buildroot when it starts asking stupid questions. */
+ if (argv[1] && strcmp(argv[1], "--version") == 0) {
+ // Output of 'tar --version' examples:
+ // tar (GNU tar) 1.15.1
+ // tar (GNU tar) 1.25
+ // bsdtar 2.8.3 - libarchive 2.8.3
+ puts("tar (busybox) " BB_VER);
+ return 0;
+ }
if (argv[1] && argv[1][0] != '-') {
/* Compat:
* 1st argument without dash handles options with parameters
@@ -921,12 +1037,17 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
IF_FEATURE_SEAMLESS_LZMA("a" )
IF_FEATURE_TAR_FROM( "T:X:")
IF_FEATURE_SEAMLESS_GZ( "z" )
+ IF_FEATURE_SEAMLESS_XZ( "J" )
IF_FEATURE_SEAMLESS_Z( "Z" )
IF_FEATURE_TAR_NOPRESERVE_TIME("m")
+ IF_FEATURE_TAR_LONG_OPTIONS("\xf9:") // --strip-components
, &base_dir // -C dir
, &tar_filename // -f filename
IF_FEATURE_TAR_FROM(, &(tar_handle->accept)) // T
IF_FEATURE_TAR_FROM(, &(tar_handle->reject)) // X
+#if ENABLE_FEATURE_TAR_LONG_OPTIONS
+ , &tar_handle->tar__strip_components // --strip-components
+#endif
IF_FEATURE_TAR_TO_COMMAND(, &(tar_handle->tar__to_command)) // --to-command
#if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM
, &excludes // --exclude
@@ -934,11 +1055,49 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
, &verboseFlag // combined count for -t and -v
, &verboseFlag // combined count for -t and -v
);
- //bb_error_msg("opt:%08x", opt);
+#if DBG_OPTION_PARSING
+ bb_error_msg("opt: 0x%08x", opt);
+# define showopt(o) bb_error_msg("opt & %s(%x): %x", #o, o, opt & o);
+ showopt(OPT_TEST );
+ showopt(OPT_EXTRACT );
+ showopt(OPT_BASEDIR );
+ showopt(OPT_TARNAME );
+ showopt(OPT_2STDOUT );
+ showopt(OPT_NOPRESERVE_OWNER);
+ showopt(OPT_P );
+ showopt(OPT_VERBOSE );
+ showopt(OPT_KEEP_OLD );
+ showopt(OPT_CREATE );
+ showopt(OPT_DEREFERENCE );
+ showopt(OPT_BZIP2 );
+ showopt(OPT_LZMA );
+ showopt(OPT_INCLUDE_FROM );
+ showopt(OPT_EXCLUDE_FROM );
+ showopt(OPT_GZIP );
+ showopt(OPT_XZ );
+ showopt(OPT_COMPRESS );
+ showopt(OPT_NOPRESERVE_TIME );
+ showopt(OPT_STRIP_COMPONENTS);
+ showopt(OPT_NORECURSION );
+ showopt(OPT_2COMMAND );
+ showopt(OPT_NUMERIC_OWNER );
+ showopt(OPT_NOPRESERVE_PERM );
+ showopt(OPT_OVERWRITE );
+ showopt(OPT_ANY_COMPRESS );
+ bb_error_msg("base_dir:'%s'", base_dir);
+ bb_error_msg("tar_filename:'%s'", tar_filename);
+ bb_error_msg("verboseFlag:%d", verboseFlag);
+ bb_error_msg("tar_handle->tar__to_command:'%s'", tar_handle->tar__to_command);
+ bb_error_msg("tar_handle->tar__strip_components:%u", tar_handle->tar__strip_components);
+ return 0;
+# undef showopt
+#endif
argv += optind;
- if (verboseFlag) tar_handle->action_header = header_verbose_list;
- if (verboseFlag == 1) tar_handle->action_header = header_list;
+ if (verboseFlag)
+ tar_handle->action_header = header_verbose_list;
+ if (verboseFlag == 1)
+ tar_handle->action_header = header_list;
if (opt & OPT_EXTRACT)
tar_handle->action_data = data_extract_all;
@@ -1024,7 +1183,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
&& flags == O_RDONLY
&& !(opt & OPT_ANY_COMPRESS)
) {
- tar_handle->src_fd = open_zipped(tar_filename);
+ tar_handle->src_fd = open_zipped(tar_filename, /*fail_if_not_compressed:*/ 0);
if (tar_handle->src_fd < 0)
bb_perror_msg_and_die("can't open '%s'", tar_filename);
} else {
@@ -1036,27 +1195,37 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
if (base_dir)
xchdir(base_dir);
- //if (SEAMLESS_COMPRESSION || OPT_COMPRESS)
+ //if (SEAMLESS_COMPRESSION)
// /* We need to know whether child (gzip/bzip/etc) exits abnormally */
// signal(SIGCHLD, check_errors_in_children);
+#if ENABLE_FEATURE_TAR_CREATE
/* Create an archive */
if (opt & OPT_CREATE) {
-#if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
- int zipMode = 0;
- if (ENABLE_FEATURE_SEAMLESS_GZ && (opt & OPT_GZIP))
- zipMode = 1;
- if (ENABLE_FEATURE_SEAMLESS_BZ2 && (opt & OPT_BZIP2))
- zipMode = 2;
-#endif
+# if SEAMLESS_COMPRESSION
+ const char *zipMode = NULL;
+ if (opt & OPT_COMPRESS)
+ zipMode = "compress";
+ if (opt & OPT_GZIP)
+ zipMode = "gzip";
+ if (opt & OPT_BZIP2)
+ zipMode = "bzip2";
+ if (opt & OPT_LZMA)
+ zipMode = "lzma";
+ if (opt & OPT_XZ)
+ zipMode = "xz";
+# endif
/* NB: writeTarFile() closes tar_handle->src_fd */
- return writeTarFile(tar_handle->src_fd, verboseFlag, opt & OPT_DEREFERENCE,
+ return writeTarFile(tar_handle->src_fd, verboseFlag,
+ (opt & OPT_DEREFERENCE ? ACTION_FOLLOWLINKS : 0)
+ | (opt & OPT_NORECURSION ? 0 : ACTION_RECURSE),
tar_handle->accept,
tar_handle->reject, zipMode);
}
+#endif
if (opt & OPT_ANY_COMPRESS) {
- USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_aux_data_t *aux, int src_fd, int dst_fd);)
+ USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_state_t *xstate);)
USE_FOR_NOMMU(const char *xformer_prog;)
if (opt & OPT_COMPRESS)
@@ -1071,15 +1240,24 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
if (opt & OPT_LZMA)
USE_FOR_MMU(xformer = unpack_lzma_stream;)
USE_FOR_NOMMU(xformer_prog = "unlzma";)
+ if (opt & OPT_XZ)
+ USE_FOR_MMU(xformer = unpack_xz_stream;)
+ USE_FOR_NOMMU(xformer_prog = "unxz";)
- open_transformer_with_sig(tar_handle->src_fd, xformer, xformer_prog);
+ fork_transformer_with_sig(tar_handle->src_fd, xformer, xformer_prog);
/* Can't lseek over pipes */
tar_handle->seek = seek_by_read;
/*tar_handle->offset = 0; - already is */
}
+ /* Zero processed headers (== empty file) is not a valid tarball.
+ * We (ab)use bb_got_signal as exitcode here,
+ * because check_errors_in_children() uses _it_ as error indicator.
+ */
+ bb_got_signal = EXIT_FAILURE;
+
while (get_header_tar(tar_handle) == EXIT_SUCCESS)
- continue;
+ bb_got_signal = EXIT_SUCCESS; /* saw at least one header, good */
/* Check that every file that should have been extracted was */
while (tar_handle->accept) {
@@ -1095,8 +1273,9 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
close(tar_handle->src_fd);
if (SEAMLESS_COMPRESSION || OPT_COMPRESS) {
+ /* Set bb_got_signal to 1 if a child died with !0 exitcode */
check_errors_in_children(0);
- return bb_got_signal;
}
- return EXIT_SUCCESS;
+
+ return bb_got_signal;
}
diff --git a/release/src/router/busybox/archival/unzip.c b/release/src/router/busybox/archival/unzip.c
index 3c76cdafcf..c540485ac9 100644
--- a/release/src/router/busybox/archival/unzip.c
+++ b/release/src/router/busybox/archival/unzip.c
@@ -9,31 +9,48 @@
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
-
/* For reference see
* http://www.pkware.com/company/standards/appnote/
* http://www.info-zip.org/pub/infozip/doc/appnote-iz-latest.zip
- */
-
-/* TODO
+ *
+ * TODO
* Zip64 + other methods
*/
+//config:config UNZIP
+//config: bool "unzip"
+//config: default y
+//config: help
+//config: unzip will list or extract files from a ZIP archive,
+//config: commonly found on DOS/WIN systems. The default behavior
+//config: (with no options) is to extract the archive into the
+//config: current directory. Use the `-d' option to extract to a
+//config: directory of your choice.
+
+//applet:IF_UNZIP(APPLET(unzip, BB_DIR_USR_BIN, BB_SUID_DROP))
+//kbuild:lib-$(CONFIG_UNZIP) += unzip.o
+
//usage:#define unzip_trivial_usage
-//usage: "[-opts[modifiers]] FILE[.zip] [LIST] [-x XLIST] [-d DIR]"
+//usage: "[-lnopq] FILE[.zip] [FILE]... [-x FILE...] [-d DIR]"
//usage:#define unzip_full_usage "\n\n"
-//usage: "Extract files from ZIP archives\n"
-//usage: "\n -l List archive contents (with -q for short form)"
-//usage: "\n -n Never overwrite files (default)"
+//usage: "Extract FILEs from ZIP archive\n"
+//usage: "\n -l List contents (with -q for short form)"
+//usage: "\n -n Never overwrite files (default: ask)"
//usage: "\n -o Overwrite"
-//usage: "\n -p Send output to stdout"
+//usage: "\n -p Print to stdout"
//usage: "\n -q Quiet"
-//usage: "\n -x XLST Exclude these files"
-//usage: "\n -d DIR Extract files into DIR"
+//usage: "\n -x FILE Exclude FILEs"
+//usage: "\n -d DIR Extract into DIR"
#include "libbb.h"
#include "bb_archive.h"
+#if 0
+# define dbg(...) bb_error_msg(__VA_ARGS__)
+#else
+# define dbg(...) ((void)0)
+#endif
+
enum {
#if BB_BIG_ENDIAN
ZIP_FILEHEADER_MAGIC = 0x504b0304,
@@ -163,7 +180,17 @@ enum { zip_fd = 3 };
#if ENABLE_DESKTOP
-#define PEEK_FROM_END 16384
+/* Seen in the wild:
+ * Self-extracting PRO2K3XP_32.exe contains 19078464 byte zip archive,
+ * where CDE was nearly 48 kbytes before EOF.
+ * (Surprisingly, it also apparently has *another* CDE structure
+ * closer to the end, with bogus cdf_offset).
+ * To make extraction work, bumped PEEK_FROM_END from 16k to 64k.
+ */
+#define PEEK_FROM_END (64*1024)
+
+/* This value means that we failed to find CDF */
+#define BAD_CDF_OFFSET ((uint32_t)0xffffffff)
/* NB: does not preserve file position! */
static uint32_t find_cdf_offset(void)
@@ -172,14 +199,17 @@ static uint32_t find_cdf_offset(void)
unsigned char *p;
off_t end;
unsigned char *buf = xzalloc(PEEK_FROM_END);
+ uint32_t found;
end = xlseek(zip_fd, 0, SEEK_END);
end -= PEEK_FROM_END;
if (end < 0)
end = 0;
- xlseek(zip_fd, end, SEEK_SET);
+ dbg("Looking for cdf_offset starting from 0x%"OFF_FMT"x", end);
+ xlseek(zip_fd, end, SEEK_SET);
full_read(zip_fd, buf, PEEK_FROM_END);
+ found = BAD_CDF_OFFSET;
p = buf;
while (p <= buf + PEEK_FROM_END - CDE_HEADER_LEN - 4) {
if (*p != 'P') {
@@ -195,11 +225,28 @@ static uint32_t find_cdf_offset(void)
/* we found CDE! */
memcpy(cde_header.raw, p + 1, CDE_HEADER_LEN);
FIX_ENDIANNESS_CDE(cde_header);
- free(buf);
- return cde_header.formatted.cdf_offset;
+ /*
+ * I've seen .ZIP files with seemingly valid CDEs
+ * where cdf_offset points past EOF - ??
+ * This check ignores such CDEs:
+ */
+ if (cde_header.formatted.cdf_offset < end + (p - buf)) {
+ found = cde_header.formatted.cdf_offset;
+ dbg("Possible cdf_offset:0x%x at 0x%"OFF_FMT"x",
+ (unsigned)found, end + (p-3 - buf));
+ dbg(" cdf_offset+cdf_size:0x%x",
+ (unsigned)(found + SWAP_LE32(cde_header.formatted.cdf_size)));
+ /*
+ * We do not "break" here because only the last CDE is valid.
+ * I've seen a .zip archive which contained a .zip file,
+ * uncompressed, and taking the first CDE was using
+ * the CDE inside that file!
+ */
+ }
}
- //free(buf);
- bb_error_msg_and_die("can't find file table");
+ free(buf);
+ dbg("Found cdf_offset:0x%x", (unsigned)found);
+ return found;
};
static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr)
@@ -211,14 +258,23 @@ static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr)
if (!cdf_offset)
cdf_offset = find_cdf_offset();
- xlseek(zip_fd, cdf_offset + 4, SEEK_SET);
- xread(zip_fd, cdf_ptr->raw, CDF_HEADER_LEN);
- FIX_ENDIANNESS_CDF(*cdf_ptr);
- cdf_offset += 4 + CDF_HEADER_LEN
- + cdf_ptr->formatted.file_name_length
- + cdf_ptr->formatted.extra_field_length
- + cdf_ptr->formatted.file_comment_length;
+ if (cdf_offset != BAD_CDF_OFFSET) {
+ dbg("Reading CDF at 0x%x", (unsigned)cdf_offset);
+ xlseek(zip_fd, cdf_offset + 4, SEEK_SET);
+ xread(zip_fd, cdf_ptr->raw, CDF_HEADER_LEN);
+ FIX_ENDIANNESS_CDF(*cdf_ptr);
+ dbg(" file_name_length:%u extra_field_length:%u file_comment_length:%u",
+ (unsigned)cdf_ptr->formatted.file_name_length,
+ (unsigned)cdf_ptr->formatted.extra_field_length,
+ (unsigned)cdf_ptr->formatted.file_comment_length
+ );
+ cdf_offset += 4 + CDF_HEADER_LEN
+ + cdf_ptr->formatted.file_name_length
+ + cdf_ptr->formatted.extra_field_length
+ + cdf_ptr->formatted.file_comment_length;
+ }
+ dbg("Returning file position to 0x%"OFF_FMT"x", org);
xlseek(zip_fd, org, SEEK_SET);
return cdf_offset;
};
@@ -226,8 +282,9 @@ static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr)
static void unzip_skip(off_t skip)
{
- if (lseek(zip_fd, skip, SEEK_CUR) == (off_t)-1)
- bb_copyfd_exact_size(zip_fd, -1, skip);
+ if (skip != 0)
+ if (lseek(zip_fd, skip, SEEK_CUR) == (off_t)-1)
+ bb_copyfd_exact_size(zip_fd, -1, skip);
}
static void unzip_create_leading_dirs(const char *fn)
@@ -249,17 +306,19 @@ static void unzip_extract(zip_header_t *zip_header, int dst_fd)
bb_copyfd_exact_size(zip_fd, dst_fd, size);
} else {
/* Method 8 - inflate */
- transformer_aux_data_t aux;
- init_transformer_aux_data(&aux);
- aux.bytes_in = zip_header->formatted.cmpsize;
- if (inflate_unzip(&aux, zip_fd, dst_fd) < 0)
+ transformer_state_t xstate;
+ init_transformer_state(&xstate);
+ xstate.bytes_in = zip_header->formatted.cmpsize;
+ xstate.src_fd = zip_fd;
+ xstate.dst_fd = dst_fd;
+ if (inflate_unzip(&xstate) < 0)
bb_error_msg_and_die("inflate error");
/* Validate decompression - crc */
- if (zip_header->formatted.crc32 != (aux.crc32 ^ 0xffffffffL)) {
+ if (zip_header->formatted.crc32 != (xstate.crc32 ^ 0xffffffffL)) {
bb_error_msg_and_die("crc error");
}
/* Validate decompression - size */
- if (zip_header->formatted.ucmpsize != aux.bytes_out) {
+ if (zip_header->formatted.ucmpsize != xstate.bytes_out) {
/* Don't die. Who knows, maybe len calculation
* was botched somewhere. After all, crc matched! */
bb_error_msg("bad length");
@@ -267,6 +326,14 @@ static void unzip_extract(zip_header_t *zip_header, int dst_fd)
}
}
+static void my_fgets80(char *buf80)
+{
+ fflush_all();
+ if (!fgets(buf80, 80, stdin)) {
+ bb_perror_msg_and_die("can't read standard input");
+ }
+}
+
int unzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int unzip_main(int argc, char **argv)
{
@@ -277,6 +344,7 @@ int unzip_main(int argc, char **argv)
IF_NOT_DESKTOP(const) smallint verbose = 0;
smallint listing = 0;
smallint overwrite = O_PROMPT;
+ smallint x_opt_seen;
#if ENABLE_DESKTOP
uint32_t cdf_offset;
#endif
@@ -290,8 +358,7 @@ int unzip_main(int argc, char **argv)
llist_t *zreject = NULL;
char *base_dir = NULL;
int i, opt;
- int opt_range = 0;
- char key_buf[80];
+ char key_buf[80]; /* must match size used by my_fgets80 */
struct stat stat_buf;
/* -q, -l and -v: UnZip 5.52 of 28 February 2005, by Info-ZIP:
@@ -335,81 +402,81 @@ int unzip_main(int argc, char **argv)
* 204372 1 file
*/
+ x_opt_seen = 0;
/* '-' makes getopt return 1 for non-options */
while ((opt = getopt(argc, argv, "-d:lnopqxv")) != -1) {
- switch (opt_range) {
- case 0: /* Options */
- switch (opt) {
- case 'l': /* List */
- listing = 1;
- break;
+ switch (opt) {
+ case 'd': /* Extract to base directory */
+ base_dir = optarg;
+ break;
- case 'n': /* Never overwrite existing files */
- overwrite = O_NEVER;
- break;
+ case 'l': /* List */
+ listing = 1;
+ break;
- case 'o': /* Always overwrite existing files */
- overwrite = O_ALWAYS;
- break;
+ case 'n': /* Never overwrite existing files */
+ overwrite = O_NEVER;
+ break;
- case 'p': /* Extract files to stdout and fall through to set verbosity */
- dst_fd = STDOUT_FILENO;
+ case 'o': /* Always overwrite existing files */
+ overwrite = O_ALWAYS;
+ break;
- case 'q': /* Be quiet */
- quiet++;
- break;
+ case 'p': /* Extract files to stdout and fall through to set verbosity */
+ dst_fd = STDOUT_FILENO;
- case 'v': /* Verbose list */
- IF_DESKTOP(verbose++;)
- listing = 1;
- break;
+ case 'q': /* Be quiet */
+ quiet++;
+ break;
- case 1: /* The zip file */
- /* +5: space for ".zip" and NUL */
- src_fn = xmalloc(strlen(optarg) + 5);
- strcpy(src_fn, optarg);
- opt_range++;
- break;
+ case 'v': /* Verbose list */
+ IF_DESKTOP(verbose++;)
+ listing = 1;
+ break;
- default:
- bb_show_usage();
- }
+ case 'x':
+ x_opt_seen = 1;
break;
- case 1: /* Include files */
- if (opt == 1) {
+ case 1:
+ if (!src_fn) {
+ /* The zip file */
+ /* +5: space for ".zip" and NUL */
+ src_fn = xmalloc(strlen(optarg) + 5);
+ strcpy(src_fn, optarg);
+ } else if (!x_opt_seen) {
+ /* Include files */
llist_add_to(&zaccept, optarg);
- break;
- }
- if (opt == 'd') {
- base_dir = optarg;
- opt_range += 2;
- break;
- }
- if (opt == 'x') {
- opt_range++;
- break;
- }
- bb_show_usage();
-
- case 2 : /* Exclude files */
- if (opt == 1) {
+ } else {
+ /* Exclude files */
llist_add_to(&zreject, optarg);
- break;
}
- if (opt == 'd') { /* Extract to base directory */
- base_dir = optarg;
- opt_range++;
- break;
- }
- /* fall through */
+ break;
default:
bb_show_usage();
}
}
- if (src_fn == NULL) {
+#ifndef __GLIBC__
+ /*
+ * This code is needed for non-GNU getopt
+ * which doesn't understand "-" in option string.
+ * The -x option won't work properly in this case:
+ * "unzip a.zip q -x w e" will be interpreted as
+ * "unzip a.zip q w e -x" = "unzip a.zip q w e"
+ */
+ argv += optind;
+ if (argv[0]) {
+ /* +5: space for ".zip" and NUL */
+ src_fn = xmalloc(strlen(argv[0]) + 5);
+ strcpy(src_fn, argv[0]);
+ while (*++argv)
+ llist_add_to(&zaccept, *argv);
+ }
+#endif
+
+ if (!src_fn) {
bb_show_usage();
}
@@ -420,17 +487,20 @@ int unzip_main(int argc, char **argv)
if (overwrite == O_PROMPT)
overwrite = O_NEVER;
} else {
- static const char extn[][5] = {"", ".zip", ".ZIP"};
- int orig_src_fn_len = strlen(src_fn);
- int src_fd = -1;
+ static const char extn[][5] ALIGN1 = { ".zip", ".ZIP" };
+ char *ext = src_fn + strlen(src_fn);
+ int src_fd;
- for (i = 0; (i < 3) && (src_fd == -1); i++) {
- strcpy(src_fn + orig_src_fn_len, extn[i]);
+ i = 0;
+ for (;;) {
src_fd = open(src_fn, O_RDONLY);
- }
- if (src_fd == -1) {
- src_fn[orig_src_fn_len] = '\0';
- bb_error_msg_and_die("can't open %s, %s.zip, %s.ZIP", src_fn, src_fn, src_fn);
+ if (src_fd >= 0)
+ break;
+ if (++i > 2) {
+ *ext = '\0';
+ bb_error_msg_and_die("can't open %s[.zip]", src_fn);
+ }
+ strcpy(ext, extn[i - 1]);
}
xmove_fd(src_fd, zip_fd);
}
@@ -444,11 +514,11 @@ int unzip_main(int argc, char **argv)
printf("Archive: %s\n", src_fn);
if (listing) {
puts(verbose ?
- " Length Method Size Ratio Date Time CRC-32 Name\n"
- "-------- ------ ------- ----- ---- ---- ------ ----"
+ " Length Method Size Cmpr Date Time CRC-32 Name\n"
+ "-------- ------ ------- ---- ---------- ----- -------- ----"
:
- " Length Date Time Name\n"
- " -------- ---- ---- ----"
+ " Length Date Time Name\n"
+ "--------- ---------- ----- ----"
);
}
}
@@ -488,11 +558,14 @@ int unzip_main(int argc, char **argv)
/* Check magic number */
xread(zip_fd, &magic, 4);
/* Central directory? It's at the end, so exit */
- if (magic == ZIP_CDF_MAGIC)
+ if (magic == ZIP_CDF_MAGIC) {
+ dbg("got ZIP_CDF_MAGIC");
break;
+ }
#if ENABLE_DESKTOP
/* Data descriptor? It was a streaming file, go on */
if (magic == ZIP_DD_MAGIC) {
+ dbg("got ZIP_DD_MAGIC");
/* skip over duplicate crc32, cmpsize and ucmpsize */
unzip_skip(3 * 4);
continue;
@@ -500,6 +573,7 @@ int unzip_main(int argc, char **argv)
#endif
if (magic != ZIP_FILEHEADER_MAGIC)
bb_error_msg_and_die("invalid zip magic %08X", (int)magic);
+ dbg("got ZIP_FILEHEADER_MAGIC");
/* Read the file header */
xread(zip_fd, zip_header.raw, ZIP_HEADER_LEN);
@@ -517,22 +591,37 @@ int unzip_main(int argc, char **argv)
bb_error_msg_and_die("zip flag 1 (encryption) is not supported");
}
- {
+ if (cdf_offset != BAD_CDF_OFFSET) {
cdf_header_t cdf_header;
cdf_offset = read_next_cdf(cdf_offset, &cdf_header);
+ /*
+ * Note: cdf_offset can become BAD_CDF_OFFSET after the above call.
+ */
if (zip_header.formatted.zip_flags & SWAP_LE16(0x0008)) {
/* 0x0008 - streaming. [u]cmpsize can be reliably gotten
- * only from Central Directory. See unzip_doc.txt */
+ * only from Central Directory. See unzip_doc.txt
+ */
zip_header.formatted.crc32 = cdf_header.formatted.crc32;
zip_header.formatted.cmpsize = cdf_header.formatted.cmpsize;
zip_header.formatted.ucmpsize = cdf_header.formatted.ucmpsize;
}
if ((cdf_header.formatted.version_made_by >> 8) == 3) {
- /* this archive is created on Unix */
+ /* This archive is created on Unix */
dir_mode = file_mode = (cdf_header.formatted.external_file_attributes >> 16);
}
}
+ if (cdf_offset == BAD_CDF_OFFSET
+ && (zip_header.formatted.zip_flags & SWAP_LE16(0x0008))
+ ) {
+ /* If it's a streaming zip, we _require_ CDF */
+ bb_error_msg_and_die("can't find file table");
+ }
#endif
+ dbg("File cmpsize:0x%x extra_len:0x%x ucmpsize:0x%x",
+ (unsigned)zip_header.formatted.cmpsize,
+ (unsigned)zip_header.formatted.extra_len,
+ (unsigned)zip_header.formatted.ucmpsize
+ );
/* Read filename */
free(dst_fn);
@@ -542,52 +631,72 @@ int unzip_main(int argc, char **argv)
/* Skip extra header bytes */
unzip_skip(zip_header.formatted.extra_len);
+ /* Guard against "/abspath", "/../" and similar attacks */
+ overlapping_strcpy(dst_fn, strip_unsafe_prefix(dst_fn));
+
/* Filter zip entries */
if (find_list_entry(zreject, dst_fn)
|| (zaccept && !find_list_entry(zaccept, dst_fn))
) { /* Skip entry */
i = 'n';
-
- } else { /* Extract entry */
- if (listing) { /* List entry */
- unsigned dostime = zip_header.formatted.modtime | (zip_header.formatted.moddate << 16);
+ } else {
+ if (listing) {
+ /* List entry */
+ char dtbuf[sizeof("mm-dd-yyyy hh:mm")];
+ sprintf(dtbuf, "%02u-%02u-%04u %02u:%02u",
+ (zip_header.formatted.moddate >> 5) & 0xf, // mm: 0x01e0
+ (zip_header.formatted.moddate) & 0x1f, // dd: 0x001f
+ (zip_header.formatted.moddate >> 9) + 1980, // yy: 0xfe00
+ (zip_header.formatted.modtime >> 11), // hh: 0xf800
+ (zip_header.formatted.modtime >> 5) & 0x3f // mm: 0x07e0
+ // seconds/2 are not shown, encoded in ----------- 0x001f
+ );
if (!verbose) {
- // " Length Date Time Name\n"
- // " -------- ---- ---- ----"
- printf( "%9u %02u-%02u-%02u %02u:%02u %s\n",
+ // " Length Date Time Name\n"
+ // "--------- ---------- ----- ----"
+ printf( "%9u " "%s " "%s\n",
(unsigned)zip_header.formatted.ucmpsize,
- (dostime & 0x01e00000) >> 21,
- (dostime & 0x001f0000) >> 16,
- (((dostime & 0xfe000000) >> 25) + 1980) % 100,
- (dostime & 0x0000f800) >> 11,
- (dostime & 0x000007e0) >> 5,
+ dtbuf,
dst_fn);
- total_usize += zip_header.formatted.ucmpsize;
} else {
unsigned long percents = zip_header.formatted.ucmpsize - zip_header.formatted.cmpsize;
+ if ((int32_t)percents < 0)
+ percents = 0; /* happens if ucmpsize < cmpsize */
percents = percents * 100;
if (zip_header.formatted.ucmpsize)
percents /= zip_header.formatted.ucmpsize;
- // " Length Method Size Ratio Date Time CRC-32 Name\n"
- // "-------- ------ ------- ----- ---- ---- ------ ----"
- printf( "%8u Defl:N" "%9u%4u%% %02u-%02u-%02u %02u:%02u %08x %s\n",
+ // " Length Method Size Cmpr Date Time CRC-32 Name\n"
+ // "-------- ------ ------- ---- ---------- ----- -------- ----"
+ printf( "%8u %s" "%9u%4u%% " "%s " "%08x " "%s\n",
(unsigned)zip_header.formatted.ucmpsize,
+ zip_header.formatted.method == 0 ? "Stored" : "Defl:N", /* Defl is method 8 */
+/* TODO: show other methods?
+ * 1 - Shrunk
+ * 2 - Reduced with compression factor 1
+ * 3 - Reduced with compression factor 2
+ * 4 - Reduced with compression factor 3
+ * 5 - Reduced with compression factor 4
+ * 6 - Imploded
+ * 7 - Reserved for Tokenizing compression algorithm
+ * 9 - Deflate64
+ * 10 - PKWARE Data Compression Library Imploding
+ * 11 - Reserved by PKWARE
+ * 12 - BZIP2
+ */
(unsigned)zip_header.formatted.cmpsize,
(unsigned)percents,
- (dostime & 0x01e00000) >> 21,
- (dostime & 0x001f0000) >> 16,
- (((dostime & 0xfe000000) >> 25) + 1980) % 100,
- (dostime & 0x0000f800) >> 11,
- (dostime & 0x000007e0) >> 5,
+ dtbuf,
zip_header.formatted.crc32,
dst_fn);
- total_usize += zip_header.formatted.ucmpsize;
total_size += zip_header.formatted.cmpsize;
}
+ total_usize += zip_header.formatted.ucmpsize;
i = 'n';
- } else if (dst_fd == STDOUT_FILENO) { /* Extracting to STDOUT */
+ } else if (dst_fd == STDOUT_FILENO) {
+ /* Extracting to STDOUT */
i = -1;
- } else if (last_char_is(dst_fn, '/')) { /* Extract directory */
+ } else if (last_char_is(dst_fn, '/')) {
+ /* Extract directory */
if (stat(dst_fn, &stat_buf) == -1) {
if (errno != ENOENT) {
bb_perror_msg_and_die("can't stat '%s'", dst_fn);
@@ -596,39 +705,42 @@ int unzip_main(int argc, char **argv)
printf(" creating: %s\n", dst_fn);
}
unzip_create_leading_dirs(dst_fn);
- if (bb_make_directory(dst_fn, dir_mode, 0)) {
+ if (bb_make_directory(dst_fn, dir_mode, FILEUTILS_IGNORE_CHMOD_ERR)) {
xfunc_die();
}
} else {
if (!S_ISDIR(stat_buf.st_mode)) {
- bb_error_msg_and_die("'%s' exists but is not directory", dst_fn);
+ bb_error_msg_and_die("'%s' exists but is not a %s",
+ dst_fn, "directory");
}
}
i = 'n';
-
- } else { /* Extract file */
+ } else {
+ /* Extract file */
check_file:
- if (stat(dst_fn, &stat_buf) == -1) { /* File does not exist */
+ if (stat(dst_fn, &stat_buf) == -1) {
+ /* File does not exist */
if (errno != ENOENT) {
bb_perror_msg_and_die("can't stat '%s'", dst_fn);
}
i = 'y';
- } else { /* File already exists */
+ } else {
+ /* File already exists */
if (overwrite == O_NEVER) {
i = 'n';
- } else if (S_ISREG(stat_buf.st_mode)) { /* File is regular file */
+ } else if (S_ISREG(stat_buf.st_mode)) {
+ /* File is regular file */
if (overwrite == O_ALWAYS) {
i = 'y';
} else {
printf("replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ", dst_fn);
- fflush_all();
- if (!fgets(key_buf, sizeof(key_buf), stdin)) {
- bb_perror_msg_and_die("can't read input");
- }
+ my_fgets80(key_buf);
i = key_buf[0];
}
- } else { /* File is not regular file */
- bb_error_msg_and_die("'%s' exists but is not regular file", dst_fn);
+ } else {
+ /* File is not regular file */
+ bb_error_msg_and_die("'%s' exists but is not a %s",
+ dst_fn, "regular file");
}
}
}
@@ -665,9 +777,7 @@ int unzip_main(int argc, char **argv)
case 'r':
/* Prompt for new name */
printf("new name: ");
- if (!fgets(key_buf, sizeof(key_buf), stdin)) {
- bb_perror_msg_and_die("can't read input");
- }
+ my_fgets80(key_buf);
free(dst_fn);
dst_fn = xstrdup(key_buf);
chomp(dst_fn);
@@ -683,21 +793,25 @@ int unzip_main(int argc, char **argv)
if (listing && quiet <= 1) {
if (!verbose) {
- // " Length Date Time Name\n"
- // " -------- ---- ---- ----"
- printf( " -------- -------\n"
- "%9lu" " %u files\n",
- total_usize, total_entries);
+ // " Length Date Time Name\n"
+ // "--------- ---------- ----- ----"
+ printf( " --------%21s" "-------\n"
+ "%9lu%21s" "%u files\n",
+ "",
+ total_usize, "", total_entries);
} else {
unsigned long percents = total_usize - total_size;
+ if ((long)percents < 0)
+ percents = 0; /* happens if usize < size */
percents = percents * 100;
if (total_usize)
percents /= total_usize;
- // " Length Method Size Ratio Date Time CRC-32 Name\n"
- // "-------- ------ ------- ----- ---- ---- ------ ----"
- printf( "-------- ------- --- -------\n"
- "%8lu" "%17lu%4u%% %u files\n",
- total_usize, total_size, (unsigned)percents,
+ // " Length Method Size Cmpr Date Time CRC-32 Name\n"
+ // "-------- ------ ------- ---- ---------- ----- -------- ----"
+ printf( "-------- ------- ----%28s" "----\n"
+ "%8lu" "%17lu%4u%%%28s" "%u files\n",
+ "",
+ total_usize, total_size, (unsigned)percents, "",
total_entries);
}
}
diff --git a/release/src/router/busybox/config_base b/release/src/router/busybox/config_base
index e782291778..d202d3ea81 100644
--- a/release/src/router/busybox/config_base
+++ b/release/src/router/busybox/config_base
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Busybox version: 1.20.2
-# Thu Oct 29 01:56:16 2015
+# Busybox version: 1.25.1
+# Fri Dec 9 22:38:05 2016
#
CONFIG_HAVE_DOT_CONFIG=y
@@ -23,6 +23,7 @@ CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
CONFIG_SHOW_USAGE=y
CONFIG_FEATURE_VERBOSE_USAGE=y
# CONFIG_FEATURE_COMPRESS_USAGE is not set
+# CONFIG_BUSYBOX is not set
# CONFIG_FEATURE_INSTALLER is not set
# CONFIG_INSTALL_NO_USR is not set
# CONFIG_LOCALE_SUPPORT is not set
@@ -36,12 +37,15 @@ CONFIG_LAST_SUPPORTED_WCHAR=0
# CONFIG_UNICODE_BIDI_SUPPORT is not set
# CONFIG_UNICODE_NEUTRAL_TABLE is not set
# CONFIG_UNICODE_PRESERVE_BROKEN is not set
+# CONFIG_PAM is not set
+# CONFIG_FEATURE_USE_SENDFILE is not set
CONFIG_LONG_OPTS=y
CONFIG_FEATURE_DEVPTS=y
# CONFIG_FEATURE_CLEAN_UP is not set
# CONFIG_FEATURE_UTMP is not set
# CONFIG_FEATURE_WTMP is not set
CONFIG_FEATURE_PIDFILE=y
+CONFIG_PID_FILE_PATH="/var/run"
CONFIG_FEATURE_SUID=y
# CONFIG_FEATURE_SUID_CONFIG is not set
# CONFIG_FEATURE_SUID_CONFIG_QUIET is not set
@@ -72,6 +76,8 @@ CONFIG_EXTRA_LDLIBS=""
#
# CONFIG_DEBUG is not set
# CONFIG_DEBUG_PESSIMIZE is not set
+# CONFIG_DEBUG_SANITIZE is not set
+# CONFIG_UNIT_TEST is not set
# CONFIG_WERROR is not set
CONFIG_NO_DEBUG_LIB=y
# CONFIG_DMALLOC is not set
@@ -92,10 +98,11 @@ CONFIG_PREFIX="./_install"
#
# Busybox Library Tuning
#
-# CONFIG_FEATURE_SYSTEMD is not set
+# CONFIG_FEATURE_USE_BSS_TAIL is not set
# CONFIG_FEATURE_RTMINMAX is not set
CONFIG_PASSWORD_MINLEN=6
CONFIG_MD5_SMALL=1
+CONFIG_SHA3_SMALL=1
CONFIG_FEATURE_FAST_TOP=y
# CONFIG_FEATURE_ETC_NETWORKS is not set
CONFIG_FEATURE_USE_TERMIOS=y
@@ -133,7 +140,15 @@ CONFIG_FEATURE_SEAMLESS_GZ=y
# CONFIG_AR is not set
# CONFIG_FEATURE_AR_LONG_FILENAMES is not set
# CONFIG_FEATURE_AR_CREATE is not set
+# CONFIG_UNCOMPRESS is not set
+CONFIG_GUNZIP=y
+# CONFIG_FEATURE_GUNZIP_LONG_OPTIONS is not set
# CONFIG_BUNZIP2 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_BZIP2 is not set
# CONFIG_CPIO is not set
# CONFIG_FEATURE_CPIO_O is not set
@@ -141,14 +156,14 @@ CONFIG_FEATURE_SEAMLESS_GZ=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 is not set
CONFIG_GZIP_FAST=0
+# CONFIG_FEATURE_GZIP_LEVELS 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_RPM2CPIO is not set
CONFIG_TAR=y
CONFIG_FEATURE_TAR_CREATE=y
# CONFIG_FEATURE_TAR_AUTODETECT is not set
@@ -161,12 +176,6 @@ CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y
# 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=y
#
@@ -178,16 +187,30 @@ CONFIG_DATE=y
CONFIG_FEATURE_DATE_ISOFMT=y
# CONFIG_FEATURE_DATE_NANO is not set
CONFIG_FEATURE_DATE_COMPAT=y
+CONFIG_DD=y
+CONFIG_FEATURE_DD_SIGNAL_HANDLING=y
+# CONFIG_FEATURE_DD_THIRD_STATUS_LINE is not set
+CONFIG_FEATURE_DD_IBS_OBS=y
+# CONFIG_FEATURE_DD_STATUS is not set
# CONFIG_HOSTID is not set
# CONFIG_ID is not set
# CONFIG_GROUPS is not set
+# CONFIG_SHUF is not set
+# CONFIG_STAT is not set
+# CONFIG_FEATURE_STAT_FORMAT is not set
+# CONFIG_FEATURE_STAT_FILESYSTEM is not set
+CONFIG_SYNC=y
+# CONFIG_FEATURE_SYNC_FANCY is not set
CONFIG_TEST=y
CONFIG_FEATURE_TEST_64=y
CONFIG_TOUCH=y
+# CONFIG_FEATURE_TOUCH_NODEREF is not set
# CONFIG_FEATURE_TOUCH_SUSV3 is not set
CONFIG_TR=y
# CONFIG_FEATURE_TR_CLASSES is not set
# CONFIG_FEATURE_TR_EQUIV is not set
+# CONFIG_TRUNCATE is not set
+# CONFIG_UNLINK is not set
# CONFIG_BASE64 is not set
# CONFIG_WHO is not set
# CONFIG_USERS is not set
@@ -203,10 +226,6 @@ CONFIG_CHROOT=y
CONFIG_CP=y
# CONFIG_FEATURE_CP_LONG_OPTIONS is not set
CONFIG_CUT=y
-CONFIG_DD=y
-CONFIG_FEATURE_DD_SIGNAL_HANDLING=y
-# CONFIG_FEATURE_DD_THIRD_STATUS_LINE is not set
-CONFIG_FEATURE_DD_IBS_OBS=y
CONFIG_DF=y
# CONFIG_FEATURE_DF_FANCY is not set
CONFIG_DIRNAME=y
@@ -263,6 +282,7 @@ CONFIG_RMDIR=y
# CONFIG_SHA1SUM is not set
# CONFIG_SHA256SUM is not set
# CONFIG_SHA512SUM is not set
+# CONFIG_SHA3SUM is not set
CONFIG_SLEEP=y
CONFIG_FEATURE_FANCY_SLEEP=y
# CONFIG_FEATURE_FLOAT_SLEEP is not set
@@ -270,11 +290,8 @@ CONFIG_SORT=y
CONFIG_FEATURE_SORT_BIG=y
# 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=y
# CONFIG_TAC is not set
CONFIG_TAIL=y
CONFIG_FEATURE_FANCY_TAIL=y
@@ -283,6 +300,7 @@ CONFIG_FEATURE_TEE_USE_BLOCK_IO=y
CONFIG_TRUE=y
# CONFIG_TTY is not set
CONFIG_UNAME=y
+CONFIG_UNAME_OSNAME="ASUSWRT-Merlin"
# CONFIG_UNEXPAND is not set
# CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS is not set
# CONFIG_UNIQ is not set
@@ -295,6 +313,11 @@ CONFIG_FEATURE_WC_LARGE=y
# CONFIG_YES is not set
#
+# Common options
+#
+CONFIG_FEATURE_VERBOSE=y
+
+#
# Common options for cp and mv
#
CONFIG_FEATURE_PRESERVE_HARDLINKS=y
@@ -310,7 +333,7 @@ CONFIG_FEATURE_AUTOWIDTH=y
CONFIG_FEATURE_HUMAN_READABLE=y
#
-# Common options for md5sum, sha1sum, sha256sum, sha512sum
+# Common options for md5sum, sha1sum, sha256sum, sha512sum, sha3sum
#
CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y
@@ -356,7 +379,16 @@ CONFIG_WHICH=y
#
# Editors
#
+CONFIG_AWK=y
+CONFIG_FEATURE_AWK_LIBM=y
+CONFIG_FEATURE_AWK_GNU_EXTENSIONS=y
+CONFIG_CMP=y
+CONFIG_DIFF=y
+CONFIG_FEATURE_DIFF_LONG_OPTIONS=y
+CONFIG_FEATURE_DIFF_DIR=y
+# CONFIG_ED is not set
# CONFIG_PATCH is not set
+CONFIG_SED=y
CONFIG_VI=y
CONFIG_FEATURE_VI_MAX_LEN=4096
CONFIG_FEATURE_VI_8BIT=y
@@ -371,15 +403,9 @@ CONFIG_FEATURE_VI_SETOPTS=y
CONFIG_FEATURE_VI_SET=y
CONFIG_FEATURE_VI_WIN_RESIZE=y
CONFIG_FEATURE_VI_ASK_TERMINAL=y
-CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y
-CONFIG_AWK=y
-CONFIG_FEATURE_AWK_LIBM=y
-CONFIG_CMP=y
-CONFIG_DIFF=y
-CONFIG_FEATURE_DIFF_LONG_OPTIONS=y
-CONFIG_FEATURE_DIFF_DIR=y
-# CONFIG_ED is not set
-CONFIG_SED=y
+# CONFIG_FEATURE_VI_UNDO is not set
+# CONFIG_FEATURE_VI_UNDO_QUEUE is not set
+CONFIG_FEATURE_VI_UNDO_QUEUE_MAX=0
CONFIG_FEATURE_ALLOW_EXEC=y
#
@@ -396,6 +422,7 @@ CONFIG_FEATURE_FIND_MTIME=y
# CONFIG_FEATURE_FIND_NEWER is not set
# CONFIG_FEATURE_FIND_INUM is not set
CONFIG_FEATURE_FIND_EXEC=y
+# CONFIG_FEATURE_FIND_EXEC_PLUS is not set
# CONFIG_FEATURE_FIND_USER is not set
# CONFIG_FEATURE_FIND_GROUP is not set
CONFIG_FEATURE_FIND_NOT=y
@@ -417,6 +444,7 @@ CONFIG_FEATURE_GREP_CONTEXT=y
# 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
+# CONFIG_FEATURE_XARGS_SUPPORT_REPL_STR is not set
#
# Init Utilities
@@ -428,6 +456,7 @@ CONFIG_FEATURE_GREP_CONTEXT=y
# CONFIG_FEATURE_CALL_TELINIT is not set
CONFIG_TELINIT_PATH=""
# CONFIG_INIT is not set
+# CONFIG_LINUXRC is not set
# CONFIG_FEATURE_USE_INITTAB is not set
# CONFIG_FEATURE_KILL_REMOVED is not set
CONFIG_FEATURE_KILL_DELAY=0
@@ -435,44 +464,45 @@ CONFIG_FEATURE_KILL_DELAY=0
# 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_INIT_TERMINAL_TYPE=""
+# CONFIG_FEATURE_INIT_MODIFY_CMDLINE is not set
# CONFIG_MESG is not set
# CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP is not set
#
# Login/Password Management Utilities
#
-# CONFIG_ADD_SHELL is not set
-# CONFIG_REMOVE_SHELL is not set
CONFIG_FEATURE_SHADOWPASSWDS=y
CONFIG_USE_BB_PWD_GRP=y
CONFIG_USE_BB_SHADOW=y
# CONFIG_USE_BB_CRYPT is not set
# CONFIG_USE_BB_CRYPT_SHA is not set
+# CONFIG_ADD_SHELL is not set
+# CONFIG_REMOVE_SHELL 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_ADDUSER is not set
# CONFIG_FEATURE_ADDUSER_LONG_OPTIONS is not set
# CONFIG_FEATURE_CHECK_NAMES is not set
+CONFIG_LAST_ID=0
CONFIG_FIRST_SYSTEM_ID=0
CONFIG_LAST_SYSTEM_ID=0
-# CONFIG_ADDGROUP is not set
-# CONFIG_FEATURE_ADDGROUP_LONG_OPTIONS is not set
-# CONFIG_FEATURE_ADDUSER_TO_GROUP is not set
+CONFIG_CHPASSWD=y
+CONFIG_FEATURE_DEFAULT_PASSWD_ALGO=""
+# CONFIG_CRYPTPW is not set
+# CONFIG_MKPASSWD is not set
# CONFIG_DELUSER is not set
# CONFIG_DELGROUP is not set
# CONFIG_FEATURE_DEL_USER_FROM_GROUP is not set
# CONFIG_GETTY is not set
CONFIG_LOGIN=y
# CONFIG_LOGIN_SESSION_AS_CHILD 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=y
-CONFIG_FEATURE_DEFAULT_PASSWD_ALGO=""
# CONFIG_SU is not set
# CONFIG_FEATURE_SU_SYSLOG is not set
# CONFIG_FEATURE_SU_CHECKS_SHELLS is not set
@@ -483,12 +513,9 @@ CONFIG_FEATURE_DEFAULT_PASSWD_ALGO=""
# Linux Ext2 FS Progs
#
# CONFIG_CHATTR is not set
-# CONFIG_E2FSCK is not set
# CONFIG_FSCK is not set
# CONFIG_LSATTR is not set
-# CONFIG_MKE2FS is not set
# CONFIG_TUNE2FS is not set
-# CONFIG_E2LABEL is not set
#
# Linux Module Utilities
@@ -524,14 +551,32 @@ CONFIG_DEFAULT_DEPMOD_FILE="/lib/modules/modules.dep"
#
# Linux System Utilities
#
+# CONFIG_BLKDISCARD is not set
# CONFIG_BLOCKDEV is not set
+# CONFIG_FATATTR is not set
+# CONFIG_FSTRIM is not set
CONFIG_MDEV=y
# CONFIG_FEATURE_MDEV_CONF is not set
# CONFIG_FEATURE_MDEV_RENAME is not set
# CONFIG_FEATURE_MDEV_RENAME_REGEXP is not set
# CONFIG_FEATURE_MDEV_EXEC is not set
# CONFIG_FEATURE_MDEV_LOAD_FIRMWARE is not set
+CONFIG_MOUNT=y
+# CONFIG_FEATURE_MOUNT_FAKE is not set
+# CONFIG_FEATURE_MOUNT_VERBOSE is not set
+CONFIG_FEATURE_MOUNT_HELPERS=y
+CONFIG_FEATURE_MOUNT_LABEL=y
+CONFIG_FEATURE_MOUNT_NFS=y
+CONFIG_FEATURE_MOUNT_CIFS=y
+CONFIG_FEATURE_MOUNT_FLAGS=y
+CONFIG_FEATURE_MOUNT_FSTAB=y
+# CONFIG_FEATURE_MOUNT_OTHERTAB is not set
+# CONFIG_NSENTER is not set
+# CONFIG_FEATURE_NSENTER_LONG_OPTS is not set
# CONFIG_REV is not set
+# CONFIG_SETARCH is not set
+# CONFIG_UEVENT is not set
+# CONFIG_UNSHARE is not set
# CONFIG_ACPID is not set
# CONFIG_FEATURE_ACPID_COMPAT is not set
CONFIG_BLKID=y
@@ -577,15 +622,6 @@ CONFIG_LSUSB=y
CONFIG_MKSWAP=y
CONFIG_FEATURE_MKSWAP_UUID=y
CONFIG_MORE=y
-CONFIG_MOUNT=y
-# CONFIG_FEATURE_MOUNT_FAKE is not set
-# CONFIG_FEATURE_MOUNT_VERBOSE is not set
-CONFIG_FEATURE_MOUNT_HELPERS=y
-CONFIG_FEATURE_MOUNT_LABEL=y
-CONFIG_FEATURE_MOUNT_NFS=y
-CONFIG_FEATURE_MOUNT_CIFS=y
-CONFIG_FEATURE_MOUNT_FLAGS=y
-CONFIG_FEATURE_MOUNT_FSTAB=y
# CONFIG_PIVOT_ROOT is not set
# CONFIG_RDATE is not set
# CONFIG_RDEV is not set
@@ -593,8 +629,8 @@ CONFIG_FEATURE_MOUNT_FSTAB=y
# CONFIG_RTCWAKE is not set
# CONFIG_SCRIPT is not set
# CONFIG_SCRIPTREPLAY is not set
-# CONFIG_SETARCH is not set
CONFIG_SWAPONOFF=y
+# CONFIG_FEATURE_SWAPON_DISCARD is not set
# CONFIG_FEATURE_SWAPON_PRI is not set
# CONFIG_SWITCH_ROOT is not set
CONFIG_UMOUNT=y
@@ -611,48 +647,68 @@ CONFIG_VOLUMEID=y
#
# Filesystem/Volume identification
#
-CONFIG_FEATURE_VOLUMEID_EXT=y
+# CONFIG_FEATURE_VOLUMEID_BCACHE is not set
# CONFIG_FEATURE_VOLUMEID_BTRFS is not set
-# CONFIG_FEATURE_VOLUMEID_REISERFS is not set
-CONFIG_FEATURE_VOLUMEID_FAT=y
+# CONFIG_FEATURE_VOLUMEID_CRAMFS is not set
# CONFIG_FEATURE_VOLUMEID_EXFAT is not set
+CONFIG_FEATURE_VOLUMEID_EXT=y
+# CONFIG_FEATURE_VOLUMEID_F2FS is not set
+CONFIG_FEATURE_VOLUMEID_FAT=y
CONFIG_FEATURE_VOLUMEID_HFS=y
-# CONFIG_FEATURE_VOLUMEID_JFS is not set
-# CONFIG_FEATURE_VOLUMEID_XFS is not set
-CONFIG_FEATURE_VOLUMEID_NTFS=y
# CONFIG_FEATURE_VOLUMEID_ISO9660 is not set
-# CONFIG_FEATURE_VOLUMEID_UDF is not set
-# CONFIG_FEATURE_VOLUMEID_LUKS is not set
+# CONFIG_FEATURE_VOLUMEID_JFS is not set
+# CONFIG_FEATURE_VOLUMEID_LINUXRAID is not set
CONFIG_FEATURE_VOLUMEID_LINUXSWAP=y
-# CONFIG_FEATURE_VOLUMEID_CRAMFS is not set
+# CONFIG_FEATURE_VOLUMEID_LUKS is not set
+# CONFIG_FEATURE_VOLUMEID_NILFS is not set
+CONFIG_FEATURE_VOLUMEID_NTFS=y
+# CONFIG_FEATURE_VOLUMEID_OCFS2 is not set
+# CONFIG_FEATURE_VOLUMEID_REISERFS is not set
# CONFIG_FEATURE_VOLUMEID_ROMFS is not set
+# CONFIG_FEATURE_VOLUMEID_SQUASHFS 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_FEATURE_VOLUMEID_UDF is not set
+# CONFIG_FEATURE_VOLUMEID_XFS is not set
#
# Miscellaneous Utilities
#
# CONFIG_CONSPY is not set
+CONFIG_CROND=y
+# CONFIG_FEATURE_CROND_D is not set
+# CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set
+CONFIG_FEATURE_CROND_DIR="/var/spool/cron"
+# CONFIG_ETHREG is not set
+# CONFIG_I2CGET is not set
+# CONFIG_I2CSET is not set
+# CONFIG_I2CDUMP is not set
+# CONFIG_I2CDETECT is not set
CONFIG_LESS=y
CONFIG_FEATURE_LESS_MAXLINES=9999999
# CONFIG_FEATURE_LESS_BRACKETS is not set
# CONFIG_FEATURE_LESS_FLAGS is not set
+# CONFIG_FEATURE_LESS_TRUNCATE 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_ASK_TERMINAL is not set
# CONFIG_FEATURE_LESS_DASHCMD is not set
# CONFIG_FEATURE_LESS_LINENUMS is not set
+# CONFIG_MDMM is not set
# CONFIG_NANDWRITE is not set
# CONFIG_NANDDUMP is not set
+# CONFIG_RFKILL is not set
# CONFIG_SETSERIAL is not set
+# CONFIG_TASKSET is not set
+# CONFIG_FEATURE_TASKSET_FANCY is not set
# CONFIG_UBIATTACH is not set
# CONFIG_UBIDETACH is not set
# CONFIG_UBIMKVOL is not set
# CONFIG_UBIRMVOL is not set
# CONFIG_UBIRSVOL is not set
# CONFIG_UBIUPDATEVOL is not set
+# CONFIG_UBIRENAME is not set
+# CONFIG_WALL is not set
# CONFIG_ADJTIMEX is not set
# CONFIG_BBCONFIG is not set
# CONFIG_FEATURE_COMPRESS_BBCONFIG is not set
@@ -668,10 +724,6 @@ CONFIG_FEATURE_BEEP_LENGTH_MS=0
# CONFIG_FEATURE_CHAT_VAR_ABORT_LEN is not set
# CONFIG_FEATURE_CHAT_CLR_ABORT is not set
# CONFIG_CHRT is not set
-CONFIG_CROND=y
-# CONFIG_FEATURE_CROND_D is not set
-# CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set
-CONFIG_FEATURE_CROND_DIR="/var/spool/cron"
CONFIG_CRONTAB=y
# CONFIG_DC is not set
# CONFIG_FEATURE_DC_LIBM is not set
@@ -691,7 +743,6 @@ CONFIG_CRONTAB=y
CONFIG_IONICE=y
# CONFIG_INOTIFYD is not set
# CONFIG_LAST is not set
-# CONFIG_FEATURE_LAST_SMALL is not set
# CONFIG_FEATURE_LAST_FANCY is not set
# CONFIG_HDPARM is not set
# CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set
@@ -709,21 +760,15 @@ CONFIG_IONICE=y
# 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=y
-# 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
-# CONFIG_MDMM is not set
-# CONFIG_ETHREG is not set
#
# Networking Utilities
@@ -738,6 +783,13 @@ CONFIG_NC_EXTRA=y
CONFIG_PING=y
CONFIG_PING6=y
CONFIG_FEATURE_FANCY_PING=y
+CONFIG_WGET=y
+CONFIG_FEATURE_WGET_STATUSBAR=y
+CONFIG_FEATURE_WGET_AUTHENTICATION=y
+CONFIG_FEATURE_WGET_LONG_OPTIONS=y
+CONFIG_FEATURE_WGET_TIMEOUT=y
+# CONFIG_FEATURE_WGET_OPENSSL is not set
+# CONFIG_FEATURE_WGET_SSL_HELPER is not set
# CONFIG_WHOIS is not set
CONFIG_FEATURE_IPV6=y
# CONFIG_FEATURE_UNIX_LOCAL is not set
@@ -754,13 +806,13 @@ CONFIG_ETHER_WAKE=y
# CONFIG_FTPD is not set
# CONFIG_FEATURE_FTP_WRITE is not set
# CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST is not set
+# CONFIG_FEATURE_FTP_AUTHENTICATION is not set
CONFIG_FTPGET=y
CONFIG_FTPPUT=y
# 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
@@ -799,8 +851,10 @@ CONFIG_IFUPDOWN_IFSTATE_PATH=""
# CONFIG_FEATURE_IP_ADDRESS is not set
# CONFIG_FEATURE_IP_LINK is not set
# CONFIG_FEATURE_IP_ROUTE is not set
+CONFIG_FEATURE_IP_ROUTE_DIR=""
# CONFIG_FEATURE_IP_TUNNEL is not set
# CONFIG_FEATURE_IP_RULE is not set
+# CONFIG_FEATURE_IP_NEIGH is not set
# CONFIG_FEATURE_IP_SHORT_FORMS is not set
# CONFIG_FEATURE_IP_RARE_PROTOCOLS is not set
# CONFIG_IPADDR is not set
@@ -808,6 +862,7 @@ CONFIG_IFUPDOWN_IFSTATE_PATH=""
# CONFIG_IPROUTE is not set
# CONFIG_IPTUNNEL is not set
# CONFIG_IPRULE is not set
+# CONFIG_IPNEIGH is not set
# CONFIG_IPCALC is not set
# CONFIG_FEATURE_IPCALC_FANCY is not set
# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set
@@ -817,6 +872,7 @@ CONFIG_FEATURE_NETSTAT_WIDE=y
CONFIG_NSLOOKUP=y
# CONFIG_NTPD is not set
# CONFIG_FEATURE_NTPD_SERVER is not set
+# CONFIG_FEATURE_NTPD_CONF is not set
CONFIG_PSCAN=y
CONFIG_ROUTE=y
# CONFIG_SLATTACH is not set
@@ -857,21 +913,14 @@ CONFIG_FEATURE_UDHCPC_ARPING=y
# CONFIG_FEATURE_UDHCPC_SANITIZEOPT is not set
# CONFIG_FEATURE_UDHCP_PORT is not set
CONFIG_UDHCP_DEBUG=0
+CONFIG_FEATURE_UDHCP_RFC5969=y
# CONFIG_FEATURE_UDHCP_RFC3397 is not set
# CONFIG_FEATURE_UDHCP_8021Q is not set
CONFIG_UDHCPC_DEFAULT_SCRIPT="/tmp/udhcpc"
CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=924
-# CONFIG_DHCP6C is not set
-# CONFIG_FEATURE_DHCP6_AUTH is not set
-# CONFIG_DHCP6RELAY is not set
CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS=""
# CONFIG_UDPSVD is not set
CONFIG_VCONFIG=y
-CONFIG_WGET=y
-CONFIG_FEATURE_WGET_STATUSBAR=y
-CONFIG_FEATURE_WGET_AUTHENTICATION=y
-CONFIG_FEATURE_WGET_LONG_OPTIONS=y
-CONFIG_FEATURE_WGET_TIMEOUT=y
CONFIG_ZCIP=y
#
@@ -904,6 +953,13 @@ CONFIG_SENDMAIL=y
# CONFIG_PSTREE is not set
# CONFIG_PWDX is not set
# CONFIG_SMEMCAP is not set
+CONFIG_TOP=y
+CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y
+CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS=y
+CONFIG_FEATURE_TOP_SMP_CPU=y
+CONFIG_FEATURE_TOP_DECIMALS=y
+CONFIG_FEATURE_TOP_SMP_PROCESS=y
+CONFIG_FEATURE_TOPMEM=y
CONFIG_UPTIME=y
# CONFIG_FEATURE_UPTIME_UTMP_SUPPORT is not set
CONFIG_FREE=y
@@ -924,30 +980,23 @@ CONFIG_FEATURE_PS_WIDE=y
# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set
CONFIG_RENICE=y
# CONFIG_BB_SYSCTL is not set
-CONFIG_TOP=y
-CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y
-CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS=y
-CONFIG_FEATURE_TOP_SMP_CPU=y
-CONFIG_FEATURE_TOP_DECIMALS=y
-CONFIG_FEATURE_TOP_SMP_PROCESS=y
-CONFIG_FEATURE_TOPMEM=y
CONFIG_FEATURE_SHOW_THREADS=y
CONFIG_WATCH=y
#
# Runit Utilities
#
+# 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_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
@@ -976,6 +1025,7 @@ CONFIG_ASH_ALIAS=y
# CONFIG_ASH_BUILTIN_ECHO is not set
# CONFIG_ASH_BUILTIN_PRINTF is not set
# CONFIG_ASH_BUILTIN_TEST is not set
+# CONFIG_ASH_HELP is not set
# CONFIG_ASH_CMDCMD is not set
# CONFIG_ASH_MAIL is not set
CONFIG_ASH_OPTIMIZE_FOR_SIZE=y
@@ -1015,6 +1065,11 @@ CONFIG_FEATURE_SH_EXTRA_QUIET=y
#
# System Logging Utilities
#
+CONFIG_KLOGD=y
+# CONFIG_FEATURE_KLOGD_KLOGCTL is not set
+CONFIG_LOGGER=y
+# CONFIG_LOGREAD is not set
+# CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set
CONFIG_SYSLOGD=y
CONFIG_FEATURE_ROTATE_LOGFILE=y
CONFIG_FEATURE_REMOTE_LOG=y
@@ -1023,8 +1078,4 @@ CONFIG_FEATURE_REMOTE_LOG=y
CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=512
# 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=y
-# CONFIG_FEATURE_KLOGD_KLOGCTL is not set
-CONFIG_LOGGER=y
+# CONFIG_FEATURE_KMSG_SYSLOG is not set
diff --git a/release/src/router/busybox/configs/TEST_nommu_defconfig b/release/src/router/busybox/configs/TEST_nommu_defconfig
index 15e12b1d26..5f822e5982 100644
--- a/release/src/router/busybox/configs/TEST_nommu_defconfig
+++ b/release/src/router/busybox/configs/TEST_nommu_defconfig
@@ -341,7 +341,6 @@ CONFIG_FEATURE_VI_READONLY=y
CONFIG_FEATURE_VI_SETOPTS=y
CONFIG_FEATURE_VI_SET=y
CONFIG_FEATURE_VI_WIN_RESIZE=y
-CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y
CONFIG_FEATURE_ALLOW_EXEC=y
#
@@ -391,7 +390,7 @@ CONFIG_FEATURE_INIT_SCTTY=y
CONFIG_FEATURE_INIT_SYSLOG=y
CONFIG_FEATURE_EXTRA_QUIET=y
CONFIG_FEATURE_INIT_COREDUMPS=y
-CONFIG_FEATURE_INITRD=y
+CONFIG_LINUXRC=y
CONFIG_HALT=y
# CONFIG_FEATURE_CALL_TELINIT is not set
CONFIG_TELINIT_PATH=""
diff --git a/release/src/router/busybox/configs/TEST_noprintf_defconfig b/release/src/router/busybox/configs/TEST_noprintf_defconfig
index f4338df711..c56781e32f 100644
--- a/release/src/router/busybox/configs/TEST_noprintf_defconfig
+++ b/release/src/router/busybox/configs/TEST_noprintf_defconfig
@@ -346,7 +346,6 @@ CONFIG_FEATURE_VI_MAX_LEN=0
# 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
#
@@ -396,7 +395,7 @@ CONFIG_FEATURE_KILL_DELAY=0
# 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_LINUXRC is not set
# CONFIG_HALT is not set
# CONFIG_FEATURE_CALL_TELINIT is not set
CONFIG_TELINIT_PATH=""
diff --git a/release/src/router/busybox/configs/TEST_rh9_defconfig b/release/src/router/busybox/configs/TEST_rh9_defconfig
index 193d8f615e..28daa62732 100644
--- a/release/src/router/busybox/configs/TEST_rh9_defconfig
+++ b/release/src/router/busybox/configs/TEST_rh9_defconfig
@@ -358,7 +358,6 @@ CONFIG_FEATURE_VI_READONLY=y
CONFIG_FEATURE_VI_SETOPTS=y
CONFIG_FEATURE_VI_SET=y
CONFIG_FEATURE_VI_WIN_RESIZE=y
-CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y
CONFIG_FEATURE_ALLOW_EXEC=y
#
@@ -408,7 +407,7 @@ CONFIG_FEATURE_INIT_SCTTY=y
CONFIG_FEATURE_INIT_SYSLOG=y
CONFIG_FEATURE_EXTRA_QUIET=y
CONFIG_FEATURE_INIT_COREDUMPS=y
-CONFIG_FEATURE_INITRD=y
+CONFIG_LINUXRC=y
CONFIG_HALT=y
# CONFIG_FEATURE_CALL_TELINIT is not set
CONFIG_TELINIT_PATH=""
diff --git a/release/src/router/busybox/configs/android2_defconfig b/release/src/router/busybox/configs/android2_defconfig
index b5166e0fc5..fbc0da091c 100644
--- a/release/src/router/busybox/configs/android2_defconfig
+++ b/release/src/router/busybox/configs/android2_defconfig
@@ -89,7 +89,6 @@ CONFIG_PREFIX="./_install"
#
# Busybox Library Tuning
#
-# CONFIG_FEATURE_SYSTEMD is not set
# CONFIG_FEATURE_RTMINMAX is not set
CONFIG_PASSWORD_MINLEN=6
CONFIG_MD5_SMALL=1
@@ -363,7 +362,6 @@ CONFIG_FEATURE_VI_MAX_LEN=0
# 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_AWK is not set
# CONFIG_FEATURE_AWK_LIBM is not set
CONFIG_CMP=y
@@ -427,7 +425,7 @@ CONFIG_FEATURE_INIT_SCTTY=y
CONFIG_FEATURE_INIT_SYSLOG=y
CONFIG_FEATURE_EXTRA_QUIET=y
CONFIG_FEATURE_INIT_COREDUMPS=y
-CONFIG_FEATURE_INITRD=y
+CONFIG_LINUXRC=y
CONFIG_INIT_TERMINAL_TYPE="linux"
CONFIG_MESG=y
CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP=y
diff --git a/release/src/router/busybox/configs/android_502_defconfig b/release/src/router/busybox/configs/android_502_defconfig
new file mode 100644
index 0000000000..7ef1585fb7
--- /dev/null
+++ b/release/src/router/busybox/configs/android_502_defconfig
@@ -0,0 +1,1142 @@
+## This config was successfully used to build busybox on
+## Samsung SM-T700 tablet
+## Android 5.0.2
+## gcc/toolchain from https://termux.com/
+## binutils 2.26.20160125
+## gcc 4.9.3
+## bionic ANDROID_API 21
+##
+## Static build did not work (static libraries not installed?):
+## # CONFIG_STATIC is not set
+## syslog() requires an additional library:
+## CONFIG_EXTRA_LDLIBS="log"
+## Bionic's botched off_t:
+## # CONFIG_LFS is not set
+##
+## Incompatible password database API:
+## # CONFIG_FEATURE_SHADOWPASSWDS is not set
+## # CONFIG_USE_BB_PWD_GRP is not set
+## # CONFIG_USE_BB_SHADOW is not set
+## # CONFIG_ADDUSER is not set
+## # CONFIG_ADDGROUP is not set
+## # CONFIG_DELUSER is not set
+## # CONFIG_DELGROUP is not set
+##
+## No utmp/wtmp:
+## # CONFIG_FEATURE_UTMP is not set
+## # CONFIG_FEATURE_WTMP is not set
+## # CONFIG_WHO is not set
+## # CONFIG_LAST is not set
+## # CONFIG_USERS is not set
+## # CONFIG_WALL is not set
+##
+## Assorted header problems:
+## # CONFIG_HOSTID is not set
+## # CONFIG_FEATURE_SYNC_FANCY is not set - syncfs()
+## # CONFIG_FEATURE_TOUCH_NODEREF is not set - lutimes()
+## # CONFIG_LOGNAME is not set - getlogin_r()
+## # CONFIG_LOADFONT is not set
+## # CONFIG_SETFONT is not set
+## # CONFIG_MDEV is not set
+## # CONFIG_FSCK_MINIX is not set
+## # CONFIG_MKFS_MINIX is not set
+## # CONFIG_IPCRM is not set
+## # CONFIG_IPCS is not set
+## # CONFIG_SWAPONOFF is not set
+## # CONFIG_CONSPY is not set
+## # CONFIG_NANDWRITE is not set
+## # CONFIG_NANDDUMP is not set
+## # CONFIG_RFKILL is not set
+## # CONFIG_UBIATTACH is not set
+## # CONFIG_UBIDETACH is not set
+## # CONFIG_UBIMKVOL is not set
+## # CONFIG_UBIRMVOL is not set
+## # CONFIG_UBIRSVOL is not set
+## # CONFIG_UBIUPDATEVOL is not set
+## # CONFIG_FEATURE_EJECT_SCSI is not set - scsi headers
+## # CONFIG_ARP is not set
+## # CONFIG_ARPING is not set
+## # CONFIG_ETHER_WAKE is not set
+## # CONFIG_IFCONFIG is not set
+## # CONFIG_IFENSLAVE is not set
+## # CONFIG_NSLOOKUP is not set
+## # CONFIG_ROUTE is not set
+## # CONFIG_ZCIP is not set
+## # CONFIG_HUSH is not set - glob.h
+## # CONFIG_KLOGD is not set
+## # CONFIG_LOGGER is not set
+## # CONFIG_LOGREAD is not set
+## # CONFIG_SYSLOGD is not set
+##-----------------------------------------------
+
+#
+# Automatically generated make config: don't edit
+# Busybox version: 1.25.0.git
+# Mon Mar 14 20:43:42 2016
+#
+CONFIG_HAVE_DOT_CONFIG=y
+
+#
+# Busybox Settings
+#
+
+#
+# General Configuration
+#
+CONFIG_DESKTOP=y
+# CONFIG_EXTRA_COMPAT is not set
+CONFIG_INCLUDE_SUSv2=y
+# CONFIG_USE_PORTABLE_CODE is not set
+CONFIG_PLATFORM_LINUX=y
+CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
+# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
+# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
+CONFIG_SHOW_USAGE=y
+CONFIG_FEATURE_VERBOSE_USAGE=y
+CONFIG_FEATURE_COMPRESS_USAGE=y
+CONFIG_FEATURE_INSTALLER=y
+# CONFIG_INSTALL_NO_USR 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 is not set
+CONFIG_SUBST_WCHAR=63
+CONFIG_LAST_SUPPORTED_WCHAR=767
+# CONFIG_UNICODE_COMBINING_WCHARS is not set
+# CONFIG_UNICODE_WIDE_WCHARS is not set
+# CONFIG_UNICODE_BIDI_SUPPORT is not set
+# CONFIG_UNICODE_NEUTRAL_TABLE is not set
+# CONFIG_UNICODE_PRESERVE_BROKEN is not set
+# CONFIG_PAM is not set
+CONFIG_FEATURE_USE_SENDFILE=y
+CONFIG_LONG_OPTS=y
+CONFIG_FEATURE_DEVPTS=y
+# CONFIG_FEATURE_CLEAN_UP is not set
+# CONFIG_FEATURE_UTMP is not set
+# CONFIG_FEATURE_WTMP is not set
+CONFIG_FEATURE_PIDFILE=y
+CONFIG_PID_FILE_PATH="/var/run"
+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
+CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe"
+CONFIG_FEATURE_SYSLOG=y
+# CONFIG_FEATURE_HAVE_RPC is not set
+
+#
+# Build Options
+#
+# CONFIG_STATIC is not set
+# 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 is not set
+CONFIG_CROSS_COMPILER_PREFIX=""
+CONFIG_SYSROOT=""
+CONFIG_EXTRA_CFLAGS=""
+CONFIG_EXTRA_LDFLAGS=""
+CONFIG_EXTRA_LDLIBS="log"
+
+#
+# Debugging Options
+#
+# CONFIG_DEBUG is not set
+# CONFIG_DEBUG_PESSIMIZE is not set
+# CONFIG_DEBUG_SANITIZE is not set
+# CONFIG_UNIT_TEST is not set
+# CONFIG_WERROR is not set
+CONFIG_NO_DEBUG_LIB=y
+# CONFIG_DMALLOC is not set
+# CONFIG_EFENCE is not set
+
+#
+# Installation Options ("make install" behavior)
+#
+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_FEATURE_RTMINMAX=y
+CONFIG_PASSWORD_MINLEN=6
+CONFIG_MD5_SMALL=1
+CONFIG_SHA3_SMALL=1
+# CONFIG_FEATURE_FAST_TOP is not set
+# CONFIG_FEATURE_ETC_NETWORKS is not set
+CONFIG_FEATURE_USE_TERMIOS=y
+CONFIG_FEATURE_EDITING=y
+CONFIG_FEATURE_EDITING_MAX_LEN=1024
+# CONFIG_FEATURE_EDITING_VI is not set
+CONFIG_FEATURE_EDITING_HISTORY=255
+CONFIG_FEATURE_EDITING_SAVEHISTORY=y
+# CONFIG_FEATURE_EDITING_SAVE_ON_EXIT is not set
+CONFIG_FEATURE_REVERSE_SEARCH=y
+CONFIG_FEATURE_TAB_COMPLETION=y
+# CONFIG_FEATURE_USERNAME_COMPLETION is not set
+CONFIG_FEATURE_EDITING_FANCY_PROMPT=y
+# CONFIG_FEATURE_EDITING_ASK_TERMINAL is not set
+CONFIG_FEATURE_NON_POSIX_CP=y
+# CONFIG_FEATURE_VERBOSE_CP_MESSAGE is not set
+CONFIG_FEATURE_COPYBUF_KB=4
+CONFIG_FEATURE_SKIP_ROOTFS=y
+CONFIG_MONOTONIC_SYSCALL=y
+CONFIG_IOCTL_HEX2STR_ERROR=y
+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 is not set
+# CONFIG_AR is not set
+# CONFIG_FEATURE_AR_LONG_FILENAMES is not set
+# CONFIG_FEATURE_AR_CREATE is not set
+# CONFIG_UNCOMPRESS is not set
+CONFIG_GUNZIP=y
+CONFIG_FEATURE_GUNZIP_LONG_OPTIONS=y
+CONFIG_BUNZIP2=y
+CONFIG_UNLZMA=y
+# CONFIG_FEATURE_LZMA_FAST is not set
+CONFIG_LZMA=y
+CONFIG_UNXZ=y
+CONFIG_XZ=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_GZIP=y
+CONFIG_FEATURE_GZIP_LONG_OPTIONS=y
+CONFIG_GZIP_FAST=0
+# CONFIG_FEATURE_GZIP_LEVELS is not set
+CONFIG_LZOP=y
+# CONFIG_LZOP_COMPR_HIGH is not set
+CONFIG_RPM=y
+CONFIG_RPM2CPIO=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_TO_COMMAND=y
+CONFIG_FEATURE_TAR_UNAME_GNAME=y
+CONFIG_FEATURE_TAR_NOPRESERVE_TIME=y
+# CONFIG_FEATURE_TAR_SELINUX is not set
+CONFIG_UNZIP=y
+
+#
+# Coreutils
+#
+CONFIG_BASENAME=y
+CONFIG_CAT=y
+CONFIG_DATE=y
+CONFIG_FEATURE_DATE_ISOFMT=y
+# CONFIG_FEATURE_DATE_NANO is not set
+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_FEATURE_DD_STATUS=y
+# CONFIG_HOSTID is not set
+CONFIG_ID=y
+CONFIG_GROUPS=y
+CONFIG_SHUF=y
+CONFIG_STAT=y
+CONFIG_FEATURE_STAT_FORMAT=y
+CONFIG_FEATURE_STAT_FILESYSTEM=y
+CONFIG_SYNC=y
+# CONFIG_FEATURE_SYNC_FANCY is not set
+CONFIG_TEST=y
+CONFIG_FEATURE_TEST_64=y
+CONFIG_TOUCH=y
+# CONFIG_FEATURE_TOUCH_NODEREF is not set
+CONFIG_FEATURE_TOUCH_SUSV3=y
+CONFIG_TR=y
+CONFIG_FEATURE_TR_CLASSES=y
+CONFIG_FEATURE_TR_EQUIV=y
+CONFIG_TRUNCATE=y
+CONFIG_UNLINK=y
+CONFIG_BASE64=y
+# CONFIG_WHO is not set
+# CONFIG_USERS is not set
+CONFIG_CAL=y
+CONFIG_CATV=y
+CONFIG_CHGRP=y
+CONFIG_CHMOD=y
+CONFIG_CHOWN=y
+CONFIG_FEATURE_CHOWN_LONG_OPTIONS=y
+CONFIG_CHROOT=y
+CONFIG_CKSUM=y
+CONFIG_COMM=y
+CONFIG_CP=y
+CONFIG_FEATURE_CP_LONG_OPTIONS=y
+CONFIG_CUT=y
+CONFIG_DF=y
+CONFIG_FEATURE_DF_FANCY=y
+CONFIG_DIRNAME=y
+CONFIG_DOS2UNIX=y
+CONFIG_UNIX2DOS=y
+CONFIG_DU=y
+CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K=y
+CONFIG_ECHO=y
+CONFIG_FEATURE_FANCY_ECHO=y
+CONFIG_ENV=y
+CONFIG_FEATURE_ENV_LONG_OPTIONS=y
+CONFIG_EXPAND=y
+CONFIG_FEATURE_EXPAND_LONG_OPTIONS=y
+CONFIG_EXPR=y
+CONFIG_EXPR_MATH_SUPPORT_64=y
+CONFIG_FALSE=y
+CONFIG_FOLD=y
+CONFIG_FSYNC=y
+CONFIG_HEAD=y
+CONFIG_FEATURE_FANCY_HEAD=y
+CONFIG_INSTALL=y
+CONFIG_FEATURE_INSTALL_LONG_OPTIONS=y
+CONFIG_LN=y
+# CONFIG_LOGNAME is not set
+CONFIG_LS=y
+CONFIG_FEATURE_LS_FILETYPES=y
+CONFIG_FEATURE_LS_FOLLOWLINKS=y
+CONFIG_FEATURE_LS_RECURSIVE=y
+CONFIG_FEATURE_LS_SORTFILES=y
+CONFIG_FEATURE_LS_TIMESTAMPS=y
+CONFIG_FEATURE_LS_USERNAME=y
+CONFIG_FEATURE_LS_COLOR=y
+CONFIG_FEATURE_LS_COLOR_IS_DEFAULT=y
+CONFIG_MD5SUM=y
+CONFIG_MKDIR=y
+CONFIG_FEATURE_MKDIR_LONG_OPTIONS=y
+CONFIG_MKFIFO=y
+CONFIG_MKNOD=y
+CONFIG_MV=y
+CONFIG_FEATURE_MV_LONG_OPTIONS=y
+CONFIG_NICE=y
+CONFIG_NOHUP=y
+CONFIG_OD=y
+CONFIG_PRINTENV=y
+CONFIG_PRINTF=y
+CONFIG_PWD=y
+CONFIG_READLINK=y
+CONFIG_FEATURE_READLINK_FOLLOW=y
+CONFIG_REALPATH=y
+CONFIG_RM=y
+CONFIG_RMDIR=y
+CONFIG_FEATURE_RMDIR_LONG_OPTIONS=y
+CONFIG_SEQ=y
+CONFIG_SHA1SUM=y
+CONFIG_SHA256SUM=y
+CONFIG_SHA512SUM=y
+CONFIG_SHA3SUM=y
+CONFIG_SLEEP=y
+CONFIG_FEATURE_FANCY_SLEEP=y
+CONFIG_FEATURE_FLOAT_SLEEP=y
+CONFIG_SORT=y
+CONFIG_FEATURE_SORT_BIG=y
+CONFIG_SPLIT=y
+CONFIG_FEATURE_SPLIT_FANCY=y
+CONFIG_STTY=y
+CONFIG_SUM=y
+CONFIG_TAC=y
+CONFIG_TAIL=y
+CONFIG_FEATURE_FANCY_TAIL=y
+CONFIG_TEE=y
+CONFIG_FEATURE_TEE_USE_BLOCK_IO=y
+CONFIG_TRUE=y
+CONFIG_TTY=y
+CONFIG_UNAME=y
+CONFIG_UNAME_OSNAME="GNU/Linux"
+CONFIG_UNEXPAND=y
+CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS=y
+CONFIG_UNIQ=y
+CONFIG_USLEEP=y
+CONFIG_UUDECODE=y
+CONFIG_UUENCODE=y
+CONFIG_WC=y
+CONFIG_FEATURE_WC_LARGE=y
+CONFIG_WHOAMI=y
+CONFIG_YES=y
+
+#
+# Common options
+#
+CONFIG_FEATURE_VERBOSE=y
+
+#
+# Common options for cp and mv
+#
+CONFIG_FEATURE_PRESERVE_HARDLINKS=y
+
+#
+# Common options for ls, more and telnet
+#
+CONFIG_FEATURE_AUTOWIDTH=y
+
+#
+# Common options for df, du, ls
+#
+CONFIG_FEATURE_HUMAN_READABLE=y
+
+#
+# Common options for md5sum, sha1sum, sha256sum, sha512sum, sha3sum
+#
+CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y
+
+#
+# Console Utilities
+#
+CONFIG_CHVT=y
+CONFIG_FGCONSOLE=y
+CONFIG_CLEAR=y
+CONFIG_DEALLOCVT=y
+CONFIG_DUMPKMAP=y
+CONFIG_KBD_MODE=y
+# CONFIG_LOADFONT is not set
+CONFIG_LOADKMAP=y
+CONFIG_OPENVT=y
+CONFIG_RESET=y
+CONFIG_RESIZE=y
+CONFIG_FEATURE_RESIZE_PRINT=y
+CONFIG_SETCONSOLE=y
+CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS=y
+# CONFIG_SETFONT is not set
+# CONFIG_FEATURE_SETFONT_TEXTUAL_MAP is not set
+CONFIG_DEFAULT_SETFONT_DIR=""
+CONFIG_SETKEYCODES=y
+CONFIG_SETLOGCONS=y
+CONFIG_SHOWKEY=y
+# 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
+CONFIG_FEATURE_RUN_PARTS_FANCY=y
+CONFIG_START_STOP_DAEMON=y
+CONFIG_FEATURE_START_STOP_DAEMON_FANCY=y
+CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS=y
+CONFIG_WHICH=y
+
+#
+# Editors
+#
+CONFIG_AWK=y
+CONFIG_FEATURE_AWK_LIBM=y
+CONFIG_FEATURE_AWK_GNU_EXTENSIONS=y
+CONFIG_CMP=y
+CONFIG_DIFF=y
+CONFIG_FEATURE_DIFF_LONG_OPTIONS=y
+CONFIG_FEATURE_DIFF_DIR=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
+CONFIG_FEATURE_VI_COLON=y
+CONFIG_FEATURE_VI_YANKMARK=y
+CONFIG_FEATURE_VI_SEARCH=y
+# CONFIG_FEATURE_VI_REGEX_SEARCH is not set
+CONFIG_FEATURE_VI_USE_SIGNALS=y
+CONFIG_FEATURE_VI_DOT_CMD=y
+CONFIG_FEATURE_VI_READONLY=y
+CONFIG_FEATURE_VI_SETOPTS=y
+CONFIG_FEATURE_VI_SET=y
+CONFIG_FEATURE_VI_WIN_RESIZE=y
+CONFIG_FEATURE_VI_ASK_TERMINAL=y
+CONFIG_FEATURE_VI_UNDO=y
+CONFIG_FEATURE_VI_UNDO_QUEUE=y
+CONFIG_FEATURE_VI_UNDO_QUEUE_MAX=256
+CONFIG_FEATURE_ALLOW_EXEC=y
+
+#
+# Finding Utilities
+#
+CONFIG_FIND=y
+CONFIG_FEATURE_FIND_PRINT0=y
+CONFIG_FEATURE_FIND_MTIME=y
+CONFIG_FEATURE_FIND_MMIN=y
+CONFIG_FEATURE_FIND_PERM=y
+CONFIG_FEATURE_FIND_TYPE=y
+CONFIG_FEATURE_FIND_XDEV=y
+CONFIG_FEATURE_FIND_MAXDEPTH=y
+CONFIG_FEATURE_FIND_NEWER=y
+CONFIG_FEATURE_FIND_INUM=y
+CONFIG_FEATURE_FIND_EXEC=y
+CONFIG_FEATURE_FIND_EXEC_PLUS=y
+CONFIG_FEATURE_FIND_USER=y
+CONFIG_FEATURE_FIND_GROUP=y
+CONFIG_FEATURE_FIND_NOT=y
+CONFIG_FEATURE_FIND_DEPTH=y
+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
+CONFIG_FEATURE_XARGS_SUPPORT_QUOTES=y
+CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT=y
+CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y
+CONFIG_FEATURE_XARGS_SUPPORT_REPL_STR=y
+
+#
+# Init Utilities
+#
+CONFIG_BOOTCHARTD=y
+CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER=y
+CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE=y
+CONFIG_HALT=y
+# CONFIG_FEATURE_CALL_TELINIT is not set
+CONFIG_TELINIT_PATH=""
+CONFIG_INIT=y
+CONFIG_FEATURE_USE_INITTAB=y
+# CONFIG_FEATURE_KILL_REMOVED is not set
+CONFIG_FEATURE_KILL_DELAY=0
+CONFIG_FEATURE_INIT_SCTTY=y
+CONFIG_FEATURE_INIT_SYSLOG=y
+CONFIG_FEATURE_EXTRA_QUIET=y
+CONFIG_FEATURE_INIT_COREDUMPS=y
+CONFIG_LINUXRC=y
+CONFIG_INIT_TERMINAL_TYPE="linux"
+CONFIG_FEATURE_INIT_MODIFY_CMDLINE=y
+CONFIG_MESG=y
+CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP=y
+
+#
+# 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=y
+CONFIG_USE_BB_CRYPT_SHA=y
+CONFIG_ADD_SHELL=y
+CONFIG_REMOVE_SHELL=y
+# CONFIG_ADDGROUP is not set
+# CONFIG_FEATURE_ADDGROUP_LONG_OPTIONS is not set
+# CONFIG_FEATURE_ADDUSER_TO_GROUP is not set
+# CONFIG_ADDUSER is not set
+# CONFIG_FEATURE_ADDUSER_LONG_OPTIONS is not set
+# CONFIG_FEATURE_CHECK_NAMES is not set
+CONFIG_LAST_ID=0
+CONFIG_FIRST_SYSTEM_ID=0
+CONFIG_LAST_SYSTEM_ID=0
+CONFIG_CHPASSWD=y
+CONFIG_FEATURE_DEFAULT_PASSWD_ALGO="des"
+CONFIG_CRYPTPW=y
+# CONFIG_DELUSER is not set
+# CONFIG_DELGROUP is not set
+# CONFIG_FEATURE_DEL_USER_FROM_GROUP is not set
+CONFIG_GETTY=y
+CONFIG_LOGIN=y
+# CONFIG_LOGIN_SESSION_AS_CHILD is not set
+CONFIG_LOGIN_SCRIPTS=y
+CONFIG_FEATURE_NOLOGIN=y
+CONFIG_FEATURE_SECURETTY=y
+CONFIG_PASSWD=y
+CONFIG_FEATURE_PASSWD_WEAK_CHECK=y
+CONFIG_SU=y
+CONFIG_FEATURE_SU_SYSLOG=y
+CONFIG_FEATURE_SU_CHECKS_SHELLS=y
+CONFIG_SULOGIN=y
+CONFIG_VLOCK=y
+
+#
+# Linux Ext2 FS Progs
+#
+CONFIG_CHATTR=y
+CONFIG_FSCK=y
+CONFIG_LSATTR=y
+# CONFIG_TUNE2FS is not set
+
+#
+# Linux Module Utilities
+#
+CONFIG_MODINFO=y
+CONFIG_MODPROBE_SMALL=y
+CONFIG_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE=y
+CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y
+# 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="/lib/modules"
+CONFIG_DEFAULT_DEPMOD_FILE="modules.dep"
+
+#
+# Linux System Utilities
+#
+CONFIG_BLKDISCARD=y
+CONFIG_BLOCKDEV=y
+CONFIG_FATATTR=y
+CONFIG_FSTRIM=y
+# 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_MOUNT=y
+CONFIG_FEATURE_MOUNT_FAKE=y
+CONFIG_FEATURE_MOUNT_VERBOSE=y
+# CONFIG_FEATURE_MOUNT_HELPERS is not set
+CONFIG_FEATURE_MOUNT_LABEL=y
+# CONFIG_FEATURE_MOUNT_NFS is not set
+CONFIG_FEATURE_MOUNT_CIFS=y
+CONFIG_FEATURE_MOUNT_FLAGS=y
+CONFIG_FEATURE_MOUNT_FSTAB=y
+CONFIG_FEATURE_MOUNT_OTHERTAB=y
+CONFIG_REV=y
+CONFIG_SETARCH=y
+CONFIG_UEVENT=y
+CONFIG_ACPID=y
+CONFIG_FEATURE_ACPID_COMPAT=y
+CONFIG_BLKID=y
+# CONFIG_FEATURE_BLKID_TYPE is not set
+CONFIG_DMESG=y
+CONFIG_FEATURE_DMESG_PRETTY=y
+CONFIG_FBSET=y
+CONFIG_FEATURE_FBSET_FANCY=y
+CONFIG_FEATURE_FBSET_READMODE=y
+CONFIG_FDFLUSH=y
+CONFIG_FDFORMAT=y
+CONFIG_FDISK=y
+CONFIG_FDISK_SUPPORT_LARGE_DISKS=y
+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_GPT_LABEL is not set
+CONFIG_FEATURE_FDISK_ADVANCED=y
+CONFIG_FINDFS=y
+CONFIG_FLOCK=y
+CONFIG_FREERAMDISK=y
+# CONFIG_FSCK_MINIX is not set
+CONFIG_MKFS_EXT2=y
+# CONFIG_MKFS_MINIX is not set
+# CONFIG_FEATURE_MINIX2 is not set
+# CONFIG_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 is not set
+# CONFIG_IPCRM is not set
+# CONFIG_IPCS is not set
+CONFIG_LOSETUP=y
+CONFIG_LSPCI=y
+CONFIG_LSUSB=y
+CONFIG_MKSWAP=y
+CONFIG_FEATURE_MKSWAP_UUID=y
+CONFIG_MORE=y
+CONFIG_PIVOT_ROOT=y
+CONFIG_RDATE=y
+CONFIG_RDEV=y
+CONFIG_READPROFILE=y
+CONFIG_RTCWAKE=y
+CONFIG_SCRIPT=y
+CONFIG_SCRIPTREPLAY=y
+# CONFIG_SWAPONOFF is not set
+# CONFIG_FEATURE_SWAPON_DISCARD is not set
+# CONFIG_FEATURE_SWAPON_PRI is not set
+CONFIG_SWITCH_ROOT=y
+CONFIG_UMOUNT=y
+CONFIG_FEATURE_UMOUNT_ALL=y
+
+#
+# Common options for mount/umount
+#
+CONFIG_FEATURE_MOUNT_LOOP=y
+CONFIG_FEATURE_MOUNT_LOOP_CREATE=y
+# CONFIG_FEATURE_MTAB_SUPPORT is not set
+CONFIG_VOLUMEID=y
+
+#
+# Filesystem/Volume identification
+#
+CONFIG_FEATURE_VOLUMEID_BCACHE=y
+CONFIG_FEATURE_VOLUMEID_BTRFS=y
+CONFIG_FEATURE_VOLUMEID_CRAMFS=y
+CONFIG_FEATURE_VOLUMEID_EXFAT=y
+CONFIG_FEATURE_VOLUMEID_EXT=y
+CONFIG_FEATURE_VOLUMEID_F2FS=y
+CONFIG_FEATURE_VOLUMEID_FAT=y
+CONFIG_FEATURE_VOLUMEID_HFS=y
+CONFIG_FEATURE_VOLUMEID_ISO9660=y
+CONFIG_FEATURE_VOLUMEID_JFS=y
+CONFIG_FEATURE_VOLUMEID_LINUXRAID=y
+CONFIG_FEATURE_VOLUMEID_LINUXSWAP=y
+CONFIG_FEATURE_VOLUMEID_LUKS=y
+CONFIG_FEATURE_VOLUMEID_NILFS=y
+CONFIG_FEATURE_VOLUMEID_NTFS=y
+CONFIG_FEATURE_VOLUMEID_OCFS2=y
+CONFIG_FEATURE_VOLUMEID_REISERFS=y
+CONFIG_FEATURE_VOLUMEID_ROMFS=y
+# CONFIG_FEATURE_VOLUMEID_SQUASHFS is not set
+CONFIG_FEATURE_VOLUMEID_SYSV=y
+CONFIG_FEATURE_VOLUMEID_UDF=y
+CONFIG_FEATURE_VOLUMEID_XFS=y
+
+#
+# Miscellaneous Utilities
+#
+# CONFIG_CONSPY is not set
+CONFIG_CROND=y
+CONFIG_FEATURE_CROND_D=y
+CONFIG_FEATURE_CROND_CALL_SENDMAIL=y
+CONFIG_FEATURE_CROND_DIR="/var/spool/cron"
+CONFIG_I2CGET=y
+CONFIG_I2CSET=y
+CONFIG_I2CDUMP=y
+CONFIG_I2CDETECT=y
+CONFIG_LESS=y
+CONFIG_FEATURE_LESS_MAXLINES=9999999
+CONFIG_FEATURE_LESS_BRACKETS=y
+CONFIG_FEATURE_LESS_FLAGS=y
+CONFIG_FEATURE_LESS_TRUNCATE=y
+CONFIG_FEATURE_LESS_MARKS=y
+CONFIG_FEATURE_LESS_REGEXP=y
+CONFIG_FEATURE_LESS_WINCH=y
+CONFIG_FEATURE_LESS_ASK_TERMINAL=y
+CONFIG_FEATURE_LESS_DASHCMD=y
+CONFIG_FEATURE_LESS_LINENUMS=y
+# CONFIG_NANDWRITE is not set
+# CONFIG_NANDDUMP is not set
+# CONFIG_RFKILL is not set
+CONFIG_SETSERIAL=y
+CONFIG_TASKSET=y
+CONFIG_FEATURE_TASKSET_FANCY=y
+# CONFIG_UBIATTACH is not set
+# CONFIG_UBIDETACH is not set
+# CONFIG_UBIMKVOL is not set
+# CONFIG_UBIRMVOL is not set
+# CONFIG_UBIRSVOL is not set
+# CONFIG_UBIUPDATEVOL is not set
+# CONFIG_WALL is not set
+CONFIG_ADJTIMEX=y
+# CONFIG_BBCONFIG is not set
+# CONFIG_FEATURE_COMPRESS_BBCONFIG is not set
+CONFIG_BEEP=y
+CONFIG_FEATURE_BEEP_FREQ=4000
+CONFIG_FEATURE_BEEP_LENGTH_MS=30
+CONFIG_CHAT=y
+CONFIG_FEATURE_CHAT_NOFAIL=y
+# CONFIG_FEATURE_CHAT_TTY_HIFI is not set
+CONFIG_FEATURE_CHAT_IMPLICIT_CR=y
+CONFIG_FEATURE_CHAT_SWALLOW_OPTS=y
+CONFIG_FEATURE_CHAT_SEND_ESCAPES=y
+CONFIG_FEATURE_CHAT_VAR_ABORT_LEN=y
+CONFIG_FEATURE_CHAT_CLR_ABORT=y
+CONFIG_CHRT=y
+CONFIG_CRONTAB=y
+CONFIG_DC=y
+CONFIG_FEATURE_DC_LIBM=y
+# CONFIG_DEVFSD is not set
+# CONFIG_DEVFSD_MODLOAD is not set
+# CONFIG_DEVFSD_FG_NP is not set
+# CONFIG_DEVFSD_VERBOSE is not set
+# CONFIG_FEATURE_DEVFS is not set
+CONFIG_DEVMEM=y
+CONFIG_EJECT=y
+# CONFIG_FEATURE_EJECT_SCSI is not set
+CONFIG_FBSPLASH=y
+# CONFIG_FLASHCP is not set
+# CONFIG_FLASH_LOCK is not set
+# CONFIG_FLASH_UNLOCK is not set
+# CONFIG_FLASH_ERASEALL is not set
+CONFIG_IONICE=y
+# CONFIG_INOTIFYD is not set
+# CONFIG_LAST is not set
+# CONFIG_FEATURE_LAST_FANCY is not set
+CONFIG_HDPARM=y
+CONFIG_FEATURE_HDPARM_GET_IDENTITY=y
+CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF=y
+CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF=y
+CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET=y
+CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF=y
+CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA=y
+CONFIG_MAKEDEVS=y
+# CONFIG_FEATURE_MAKEDEVS_LEAF is not set
+CONFIG_FEATURE_MAKEDEVS_TABLE=y
+CONFIG_MAN=y
+CONFIG_MICROCOM=y
+CONFIG_MOUNTPOINT=y
+# CONFIG_MT is not set
+CONFIG_RAIDAUTORUN=y
+# CONFIG_READAHEAD is not set
+# CONFIG_RUNLEVEL is not set
+CONFIG_RX=y
+CONFIG_SETSID=y
+CONFIG_STRINGS=y
+CONFIG_TIME=y
+CONFIG_TIMEOUT=y
+CONFIG_TTYSIZE=y
+CONFIG_VOLNAME=y
+CONFIG_WATCHDOG=y
+
+#
+# Networking Utilities
+#
+CONFIG_NAMEIF=y
+CONFIG_FEATURE_NAMEIF_EXTENDED=y
+CONFIG_NBDCLIENT=y
+CONFIG_NC=y
+CONFIG_NC_SERVER=y
+CONFIG_NC_EXTRA=y
+# CONFIG_NC_110_COMPAT is not set
+CONFIG_PING=y
+CONFIG_PING6=y
+CONFIG_FEATURE_FANCY_PING=y
+CONFIG_WGET=y
+CONFIG_FEATURE_WGET_STATUSBAR=y
+CONFIG_FEATURE_WGET_AUTHENTICATION=y
+CONFIG_FEATURE_WGET_LONG_OPTIONS=y
+CONFIG_FEATURE_WGET_TIMEOUT=y
+CONFIG_FEATURE_WGET_OPENSSL=y
+CONFIG_FEATURE_WGET_SSL_HELPER=y
+CONFIG_WHOIS=y
+CONFIG_FEATURE_IPV6=y
+# CONFIG_FEATURE_UNIX_LOCAL is not set
+CONFIG_FEATURE_PREFER_IPV4_ADDRESS=y
+# CONFIG_VERBOSE_RESOLUTION_ERRORS is not set
+# CONFIG_ARP is not set
+# CONFIG_ARPING is not set
+CONFIG_BRCTL=y
+CONFIG_FEATURE_BRCTL_FANCY=y
+CONFIG_FEATURE_BRCTL_SHOW=y
+CONFIG_DNSD=y
+# CONFIG_ETHER_WAKE is not set
+CONFIG_FAKEIDENTD=y
+CONFIG_FTPD=y
+CONFIG_FEATURE_FTP_WRITE=y
+CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST=y
+CONFIG_FEATURE_FTP_AUTHENTICATION=y
+CONFIG_FTPGET=y
+CONFIG_FTPPUT=y
+CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS=y
+CONFIG_HOSTNAME=y
+CONFIG_HTTPD=y
+CONFIG_FEATURE_HTTPD_RANGES=y
+CONFIG_FEATURE_HTTPD_SETUID=y
+CONFIG_FEATURE_HTTPD_BASIC_AUTH=y
+CONFIG_FEATURE_HTTPD_AUTH_MD5=y
+CONFIG_FEATURE_HTTPD_CGI=y
+CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR=y
+CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV=y
+CONFIG_FEATURE_HTTPD_ENCODE_URL_STR=y
+CONFIG_FEATURE_HTTPD_ERROR_PAGES=y
+CONFIG_FEATURE_HTTPD_PROXY=y
+CONFIG_FEATURE_HTTPD_GZIP=y
+# 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=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
+CONFIG_FEATURE_IFUPDOWN_IPV4=y
+CONFIG_FEATURE_IFUPDOWN_IPV6=y
+CONFIG_FEATURE_IFUPDOWN_MAPPING=y
+# CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP is not set
+CONFIG_INETD=y
+CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO=y
+CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD=y
+CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME=y
+CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME=y
+CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN=y
+# CONFIG_FEATURE_INETD_RPC is not set
+CONFIG_IP=y
+CONFIG_FEATURE_IP_ADDRESS=y
+CONFIG_FEATURE_IP_LINK=y
+CONFIG_FEATURE_IP_ROUTE=y
+CONFIG_FEATURE_IP_ROUTE_DIR="/etc/iproute2"
+CONFIG_FEATURE_IP_TUNNEL=y
+CONFIG_FEATURE_IP_RULE=y
+CONFIG_FEATURE_IP_NEIGH=y
+CONFIG_FEATURE_IP_SHORT_FORMS=y
+# CONFIG_FEATURE_IP_RARE_PROTOCOLS is not set
+CONFIG_IPADDR=y
+CONFIG_IPLINK=y
+CONFIG_IPROUTE=y
+CONFIG_IPTUNNEL=y
+CONFIG_IPRULE=y
+CONFIG_IPNEIGH=y
+CONFIG_IPCALC=y
+CONFIG_FEATURE_IPCALC_FANCY=y
+CONFIG_FEATURE_IPCALC_LONG_OPTIONS=y
+CONFIG_NETSTAT=y
+CONFIG_FEATURE_NETSTAT_WIDE=y
+CONFIG_FEATURE_NETSTAT_PRG=y
+# CONFIG_NSLOOKUP is not set
+CONFIG_NTPD=y
+CONFIG_FEATURE_NTPD_SERVER=y
+CONFIG_FEATURE_NTPD_CONF=y
+CONFIG_PSCAN=y
+# CONFIG_ROUTE is not set
+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
+
+#
+# Common options for tftp/tftpd
+#
+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_UDHCPC6 is not set
+CONFIG_UDHCPD=y
+CONFIG_DHCPRELAY=y
+CONFIG_DUMPLEASES=y
+CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY=y
+# CONFIG_FEATURE_UDHCPD_BASE_IP_ON_MAC is not set
+CONFIG_DHCPD_LEASES_FILE="/var/lib/misc/udhcpd.leases"
+CONFIG_UDHCPC=y
+CONFIG_FEATURE_UDHCPC_ARPING=y
+CONFIG_FEATURE_UDHCPC_SANITIZEOPT=y
+# CONFIG_FEATURE_UDHCP_PORT is not set
+CONFIG_UDHCP_DEBUG=9
+CONFIG_FEATURE_UDHCP_RFC3397=y
+CONFIG_FEATURE_UDHCP_8021Q=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_ZCIP is not set
+
+#
+# Print Utilities
+#
+CONFIG_LPD=y
+CONFIG_LPR=y
+CONFIG_LPQ=y
+
+#
+# Mail Utilities
+#
+CONFIG_MAKEMIME=y
+CONFIG_FEATURE_MIME_CHARSET="us-ascii"
+CONFIG_POPMAILDIR=y
+CONFIG_FEATURE_POPMAILDIR_DELIVERY=y
+CONFIG_REFORMIME=y
+CONFIG_FEATURE_REFORMIME_COMPAT=y
+CONFIG_SENDMAIL=y
+
+#
+# Process Utilities
+#
+CONFIG_IOSTAT=y
+CONFIG_LSOF=y
+CONFIG_MPSTAT=y
+CONFIG_NMETER=y
+CONFIG_PMAP=y
+CONFIG_POWERTOP=y
+CONFIG_PSTREE=y
+CONFIG_PWDX=y
+CONFIG_SMEMCAP=y
+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_UPTIME=y
+# CONFIG_FEATURE_UPTIME_UTMP_SUPPORT is not set
+CONFIG_FREE=y
+CONFIG_FUSER=y
+CONFIG_KILL=y
+CONFIG_KILLALL=y
+CONFIG_KILLALL5=y
+CONFIG_PGREP=y
+CONFIG_PIDOF=y
+CONFIG_FEATURE_PIDOF_SINGLE=y
+CONFIG_FEATURE_PIDOF_OMIT=y
+CONFIG_PKILL=y
+CONFIG_PS=y
+# CONFIG_FEATURE_PS_WIDE is not set
+# CONFIG_FEATURE_PS_LONG is not set
+CONFIG_FEATURE_PS_TIME=y
+CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS=y
+# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set
+CONFIG_RENICE=y
+CONFIG_BB_SYSCTL=y
+CONFIG_FEATURE_SHOW_THREADS=y
+CONFIG_WATCH=y
+
+#
+# Runit Utilities
+#
+CONFIG_CHPST=y
+CONFIG_SETUIDGID=y
+CONFIG_ENVUIDGID=y
+CONFIG_ENVDIR=y
+CONFIG_SOFTLIMIT=y
+CONFIG_RUNSV=y
+CONFIG_RUNSVDIR=y
+# CONFIG_FEATURE_RUNSVDIR_LOG is not set
+CONFIG_SV=y
+CONFIG_SV_DEFAULT_SERVICE_DIR="/var/service"
+CONFIG_SVLOGD=y
+# 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=y
+CONFIG_ASH_BASH_COMPAT=y
+# CONFIG_ASH_IDLE_TIMEOUT is not set
+CONFIG_ASH_JOB_CONTROL=y
+CONFIG_ASH_ALIAS=y
+CONFIG_ASH_GETOPTS=y
+CONFIG_ASH_BUILTIN_ECHO=y
+CONFIG_ASH_BUILTIN_PRINTF=y
+CONFIG_ASH_BUILTIN_TEST=y
+CONFIG_ASH_HELP=y
+CONFIG_ASH_CMDCMD=y
+# CONFIG_ASH_MAIL is not set
+CONFIG_ASH_OPTIMIZE_FOR_SIZE=y
+CONFIG_ASH_RANDOM_SUPPORT=y
+CONFIG_ASH_EXPAND_PRMT=y
+CONFIG_CTTYHACK=y
+# CONFIG_HUSH is not set
+# CONFIG_HUSH_BASH_COMPAT is not set
+# CONFIG_HUSH_BRACE_EXPANSION is not set
+# CONFIG_HUSH_HELP is not set
+# CONFIG_HUSH_INTERACTIVE is not set
+# CONFIG_HUSH_SAVEHISTORY is not set
+# CONFIG_HUSH_JOB is not set
+# CONFIG_HUSH_TICK is not set
+# CONFIG_HUSH_IF is not set
+# CONFIG_HUSH_LOOPS is not set
+# CONFIG_HUSH_CASE is not set
+# CONFIG_HUSH_FUNCTIONS is not set
+# CONFIG_HUSH_LOCAL is not set
+# CONFIG_HUSH_RANDOM_SUPPORT is not set
+# CONFIG_HUSH_EXPORT_N is not set
+# CONFIG_HUSH_MODE_X is not set
+# CONFIG_MSH is not set
+CONFIG_FEATURE_SH_IS_ASH=y
+# CONFIG_FEATURE_SH_IS_HUSH is not set
+# CONFIG_FEATURE_SH_IS_NONE is not set
+# CONFIG_FEATURE_BASH_IS_ASH is not set
+# CONFIG_FEATURE_BASH_IS_HUSH is not set
+CONFIG_FEATURE_BASH_IS_NONE=y
+CONFIG_SH_MATH_SUPPORT=y
+CONFIG_SH_MATH_SUPPORT_64=y
+CONFIG_FEATURE_SH_EXTRA_QUIET=y
+# CONFIG_FEATURE_SH_STANDALONE is not set
+# CONFIG_FEATURE_SH_NOFORK is not set
+CONFIG_FEATURE_SH_HISTFILESIZE=y
+
+#
+# System Logging Utilities
+#
+# CONFIG_KLOGD is not set
+# CONFIG_FEATURE_KLOGD_KLOGCTL is not set
+# CONFIG_LOGGER is not set
+# CONFIG_LOGREAD is not set
+# CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set
+# 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_CFG 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_FEATURE_KMSG_SYSLOG is not set
diff --git a/release/src/router/busybox/configs/android_defconfig b/release/src/router/busybox/configs/android_defconfig
index a9a8d5e1f1..4e0224207e 100644
--- a/release/src/router/busybox/configs/android_defconfig
+++ b/release/src/router/busybox/configs/android_defconfig
@@ -107,7 +107,6 @@ CONFIG_PREFIX="./_install"
#
# Busybox Library Tuning
#
-# CONFIG_FEATURE_SYSTEMD is not set
# CONFIG_FEATURE_RTMINMAX is not set
CONFIG_PASSWORD_MINLEN=6
CONFIG_MD5_SMALL=1
@@ -386,7 +385,6 @@ CONFIG_FEATURE_VI_SETOPTS=y
CONFIG_FEATURE_VI_SET=y
CONFIG_FEATURE_VI_WIN_RESIZE=y
CONFIG_FEATURE_VI_ASK_TERMINAL=y
-CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y
CONFIG_AWK=y
CONFIG_FEATURE_AWK_LIBM=y
CONFIG_CMP=y
@@ -450,7 +448,7 @@ CONFIG_FEATURE_INIT_SCTTY=y
CONFIG_FEATURE_INIT_SYSLOG=y
CONFIG_FEATURE_EXTRA_QUIET=y
CONFIG_FEATURE_INIT_COREDUMPS=y
-CONFIG_FEATURE_INITRD=y
+CONFIG_LINUXRC=y
CONFIG_INIT_TERMINAL_TYPE="linux"
CONFIG_MESG=y
CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP=y
diff --git a/release/src/router/busybox/configs/android_ndk_defconfig b/release/src/router/busybox/configs/android_ndk_defconfig
index bf8827a584..d657d33e94 100644
--- a/release/src/router/busybox/configs/android_ndk_defconfig
+++ b/release/src/router/busybox/configs/android_ndk_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Busybox version: 1.20.0.git
-# Fri Mar 2 16:53:26 2012
+# Busybox version: 1.24.0.git
+# Fri Sep 18 20:39:29 2015
#
CONFIG_HAVE_DOT_CONFIG=y
@@ -20,11 +20,11 @@ CONFIG_PLATFORM_LINUX=y
CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
-# CONFIG_SHOW_USAGE is not set
-# CONFIG_FEATURE_VERBOSE_USAGE is not set
-# CONFIG_FEATURE_COMPRESS_USAGE is not set
-# CONFIG_FEATURE_INSTALLER is not set
-# CONFIG_INSTALL_NO_USR is not set
+CONFIG_SHOW_USAGE=y
+CONFIG_FEATURE_VERBOSE_USAGE=y
+CONFIG_FEATURE_COMPRESS_USAGE=y
+CONFIG_FEATURE_INSTALLER=y
+CONFIG_INSTALL_NO_USR=y
# CONFIG_LOCALE_SUPPORT is not set
# CONFIG_UNICODE_SUPPORT is not set
# CONFIG_UNICODE_USING_LOCALE is not set
@@ -36,12 +36,15 @@ CONFIG_LAST_SUPPORTED_WCHAR=0
# CONFIG_UNICODE_BIDI_SUPPORT is not set
# CONFIG_UNICODE_NEUTRAL_TABLE is not set
# CONFIG_UNICODE_PRESERVE_BROKEN is not set
-# CONFIG_LONG_OPTS is not set
+# CONFIG_PAM is not set
+CONFIG_FEATURE_USE_SENDFILE=y
+CONFIG_LONG_OPTS=y
# CONFIG_FEATURE_DEVPTS is not set
# CONFIG_FEATURE_CLEAN_UP is not set
# CONFIG_FEATURE_UTMP is not set
# CONFIG_FEATURE_WTMP is not set
# CONFIG_FEATURE_PIDFILE is not set
+CONFIG_PID_FILE_PATH=""
# CONFIG_FEATURE_SUID is not set
# CONFIG_FEATURE_SUID_CONFIG is not set
# CONFIG_FEATURE_SUID_CONFIG_QUIET is not set
@@ -63,16 +66,16 @@ CONFIG_FEATURE_SYSLOG=y
# CONFIG_LFS is not set
CONFIG_CROSS_COMPILER_PREFIX="arm-linux-androideabi-"
CONFIG_SYSROOT="/opt/android-ndk/platforms/android-9/arch-arm"
-CONFIG_EXTRA_CFLAGS="-DANDROID -D__ANDROID__ -DSK_RELEASE -nostdlib -march=armv7-a -msoft-float -mfloat-abi=softfp -mfpu=neon -mthumb -mthumb-interwork -fpic -fno-short-enums -fgcse-after-reload -frename-registers"
+CONFIG_EXTRA_CFLAGS="-DANDROID -D__ANDROID__ -DSK_RELEASE -nostdlib -march=armv7-a -msoft-float -mfloat-abi=softfp -mfpu=neon -mthumb -mthumb-interwork -fpic -fno-short-enums -fgcse-after-reload -frename-registers -fuse-ld=bfd"
CONFIG_EXTRA_LDFLAGS="-Xlinker -z -Xlinker muldefs -nostdlib -Bdynamic -Xlinker -dynamic-linker -Xlinker /system/bin/linker -Xlinker -z -Xlinker nocopyreloc -Xlinker --no-undefined ${SYSROOT}/usr/lib/crtbegin_dynamic.o ${SYSROOT}/usr/lib/crtend_android.o"
CONFIG_EXTRA_LDLIBS="dl m c gcc"
-
#
# Debugging Options
#
# CONFIG_DEBUG is not set
# CONFIG_DEBUG_PESSIMIZE is not set
+# CONFIG_UNIT_TEST is not set
# CONFIG_WERROR is not set
CONFIG_NO_DEBUG_LIB=y
# CONFIG_DMALLOC is not set
@@ -93,10 +96,10 @@ CONFIG_PREFIX="./_install"
#
# Busybox Library Tuning
#
-# CONFIG_FEATURE_SYSTEMD is not set
# CONFIG_FEATURE_RTMINMAX is not set
CONFIG_PASSWORD_MINLEN=6
CONFIG_MD5_SMALL=1
+CONFIG_SHA3_SMALL=1
# CONFIG_FEATURE_FAST_TOP is not set
# CONFIG_FEATURE_ETC_NETWORKS is not set
CONFIG_FEATURE_USE_TERMIOS=y
@@ -112,7 +115,7 @@ CONFIG_FEATURE_EDITING_HISTORY=0
# CONFIG_FEATURE_EDITING_FANCY_PROMPT is not set
# CONFIG_FEATURE_EDITING_ASK_TERMINAL is not set
# CONFIG_FEATURE_NON_POSIX_CP is not set
-# CONFIG_FEATURE_VERBOSE_CP_MESSAGE is not set
+CONFIG_FEATURE_VERBOSE_CP_MESSAGE=y
CONFIG_FEATURE_COPYBUF_KB=4
# CONFIG_FEATURE_SKIP_ROOTFS is not set
# CONFIG_MONOTONIC_SYSCALL is not set
@@ -134,7 +137,14 @@ CONFIG_FEATURE_SEAMLESS_Z=y
CONFIG_AR=y
CONFIG_FEATURE_AR_LONG_FILENAMES=y
CONFIG_FEATURE_AR_CREATE=y
+CONFIG_UNCOMPRESS=y
+CONFIG_GUNZIP=y
CONFIG_BUNZIP2=y
+CONFIG_UNLZMA=y
+CONFIG_FEATURE_LZMA_FAST=y
+CONFIG_LZMA=y
+CONFIG_UNXZ=y
+CONFIG_XZ=y
CONFIG_BZIP2=y
CONFIG_CPIO=y
CONFIG_FEATURE_CPIO_O=y
@@ -142,14 +152,14 @@ CONFIG_FEATURE_CPIO_P=y
CONFIG_DPKG=y
CONFIG_DPKG_DEB=y
# CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY is not set
-CONFIG_GUNZIP=y
CONFIG_GZIP=y
# CONFIG_FEATURE_GZIP_LONG_OPTIONS is not set
CONFIG_GZIP_FAST=0
+# CONFIG_FEATURE_GZIP_LEVELS is not set
CONFIG_LZOP=y
CONFIG_LZOP_COMPR_HIGH=y
-CONFIG_RPM2CPIO=y
CONFIG_RPM=y
+CONFIG_RPM2CPIO=y
CONFIG_TAR=y
CONFIG_FEATURE_TAR_CREATE=y
CONFIG_FEATURE_TAR_AUTODETECT=y
@@ -162,12 +172,6 @@ CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y
CONFIG_FEATURE_TAR_UNAME_GNAME=y
CONFIG_FEATURE_TAR_NOPRESERVE_TIME=y
# CONFIG_FEATURE_TAR_SELINUX is not set
-CONFIG_UNCOMPRESS=y
-CONFIG_UNLZMA=y
-CONFIG_FEATURE_LZMA_FAST=y
-CONFIG_LZMA=y
-CONFIG_UNXZ=y
-CONFIG_XZ=y
CONFIG_UNZIP=y
#
@@ -179,16 +183,27 @@ CONFIG_CAT=y
# CONFIG_FEATURE_DATE_ISOFMT is not set
# CONFIG_FEATURE_DATE_NANO is not set
# CONFIG_FEATURE_DATE_COMPAT is not set
+CONFIG_DD=y
+CONFIG_FEATURE_DD_SIGNAL_HANDLING=y
+CONFIG_FEATURE_DD_THIRD_STATUS_LINE=y
+CONFIG_FEATURE_DD_IBS_OBS=y
+CONFIG_FEATURE_DD_STATUS=y
# CONFIG_HOSTID is not set
# CONFIG_ID is not set
# CONFIG_GROUPS is not set
+CONFIG_SHUF=y
+CONFIG_SYNC=y
+# CONFIG_FEATURE_SYNC_FANCY is not set
CONFIG_TEST=y
CONFIG_FEATURE_TEST_64=y
CONFIG_TOUCH=y
+# CONFIG_FEATURE_TOUCH_NODEREF is not set
CONFIG_FEATURE_TOUCH_SUSV3=y
CONFIG_TR=y
CONFIG_FEATURE_TR_CLASSES=y
CONFIG_FEATURE_TR_EQUIV=y
+CONFIG_TRUNCATE=y
+CONFIG_UNLINK=y
CONFIG_BASE64=y
# CONFIG_WHO is not set
# CONFIG_USERS is not set
@@ -204,10 +219,6 @@ CONFIG_COMM=y
CONFIG_CP=y
# CONFIG_FEATURE_CP_LONG_OPTIONS is not set
CONFIG_CUT=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 is not set
# CONFIG_FEATURE_DF_FANCY is not set
CONFIG_DIRNAME=y
@@ -239,7 +250,7 @@ CONFIG_FEATURE_LS_RECURSIVE=y
CONFIG_FEATURE_LS_SORTFILES=y
CONFIG_FEATURE_LS_TIMESTAMPS=y
CONFIG_FEATURE_LS_USERNAME=y
-# CONFIG_FEATURE_LS_COLOR is not set
+CONFIG_FEATURE_LS_COLOR=y
# CONFIG_FEATURE_LS_COLOR_IS_DEFAULT is not set
CONFIG_MD5SUM=y
CONFIG_MKDIR=y
@@ -264,6 +275,7 @@ CONFIG_SEQ=y
CONFIG_SHA1SUM=y
CONFIG_SHA256SUM=y
CONFIG_SHA512SUM=y
+CONFIG_SHA3SUM=y
CONFIG_SLEEP=y
CONFIG_FEATURE_FANCY_SLEEP=y
CONFIG_FEATURE_FLOAT_SLEEP=y
@@ -275,7 +287,6 @@ CONFIG_FEATURE_SPLIT_FANCY=y
# CONFIG_FEATURE_STAT_FORMAT is not set
CONFIG_STTY=y
CONFIG_SUM=y
-CONFIG_SYNC=y
CONFIG_TAC=y
CONFIG_TAIL=y
CONFIG_FEATURE_FANCY_TAIL=y
@@ -284,6 +295,7 @@ CONFIG_FEATURE_TEE_USE_BLOCK_IO=y
CONFIG_TRUE=y
# CONFIG_TTY is not set
CONFIG_UNAME=y
+CONFIG_UNAME_OSNAME="GNU/Linux"
CONFIG_UNEXPAND=y
# CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS is not set
CONFIG_UNIQ=y
@@ -296,6 +308,11 @@ CONFIG_WHOAMI=y
CONFIG_YES=y
#
+# Common options
+#
+CONFIG_FEATURE_VERBOSE=y
+
+#
# Common options for cp and mv
#
CONFIG_FEATURE_PRESERVE_HARDLINKS=y
@@ -311,7 +328,7 @@ CONFIG_FEATURE_AUTOWIDTH=y
CONFIG_FEATURE_HUMAN_READABLE=y
#
-# Common options for md5sum, sha1sum, sha256sum, sha512sum
+# Common options for md5sum, sha1sum, sha256sum, sha512sum, sha3sum
#
CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y
@@ -357,7 +374,16 @@ CONFIG_WHICH=y
#
# Editors
#
+CONFIG_AWK=y
+CONFIG_FEATURE_AWK_LIBM=y
+CONFIG_FEATURE_AWK_GNU_EXTENSIONS=y
+CONFIG_CMP=y
+CONFIG_DIFF=y
+# CONFIG_FEATURE_DIFF_LONG_OPTIONS is not set
+CONFIG_FEATURE_DIFF_DIR=y
+CONFIG_ED=y
CONFIG_PATCH=y
+CONFIG_SED=y
CONFIG_VI=y
CONFIG_FEATURE_VI_MAX_LEN=4096
CONFIG_FEATURE_VI_8BIT=y
@@ -372,15 +398,9 @@ CONFIG_FEATURE_VI_SETOPTS=y
CONFIG_FEATURE_VI_SET=y
CONFIG_FEATURE_VI_WIN_RESIZE=y
CONFIG_FEATURE_VI_ASK_TERMINAL=y
-CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y
-CONFIG_AWK=y
-CONFIG_FEATURE_AWK_LIBM=y
-CONFIG_CMP=y
-CONFIG_DIFF=y
-# CONFIG_FEATURE_DIFF_LONG_OPTIONS is not set
-CONFIG_FEATURE_DIFF_DIR=y
-CONFIG_ED=y
-CONFIG_SED=y
+CONFIG_FEATURE_VI_UNDO=y
+CONFIG_FEATURE_VI_UNDO_QUEUE=y
+CONFIG_FEATURE_VI_UNDO_QUEUE_MAX=256
CONFIG_FEATURE_ALLOW_EXEC=y
#
@@ -397,6 +417,7 @@ CONFIG_FEATURE_FIND_MAXDEPTH=y
CONFIG_FEATURE_FIND_NEWER=y
CONFIG_FEATURE_FIND_INUM=y
CONFIG_FEATURE_FIND_EXEC=y
+CONFIG_FEATURE_FIND_EXEC_PLUS=y
CONFIG_FEATURE_FIND_USER=y
CONFIG_FEATURE_FIND_GROUP=y
CONFIG_FEATURE_FIND_NOT=y
@@ -418,6 +439,7 @@ CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION=y
CONFIG_FEATURE_XARGS_SUPPORT_QUOTES=y
CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT=y
CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y
+CONFIG_FEATURE_XARGS_SUPPORT_REPL_STR=y
#
# Init Utilities
@@ -436,7 +458,7 @@ CONFIG_FEATURE_INIT_SCTTY=y
CONFIG_FEATURE_INIT_SYSLOG=y
CONFIG_FEATURE_EXTRA_QUIET=y
CONFIG_FEATURE_INIT_COREDUMPS=y
-CONFIG_FEATURE_INITRD=y
+CONFIG_LINUXRC=y
CONFIG_INIT_TERMINAL_TYPE="linux"
CONFIG_MESG=y
CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP=y
@@ -449,11 +471,12 @@ CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP=y
# 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_USE_BB_CRYPT=y
+CONFIG_USE_BB_CRYPT_SHA=y
# CONFIG_ADDUSER is not set
# CONFIG_FEATURE_ADDUSER_LONG_OPTIONS is not set
# CONFIG_FEATURE_CHECK_NAMES is not set
+CONFIG_LAST_ID=0
CONFIG_FIRST_SYSTEM_ID=0
CONFIG_LAST_SYSTEM_ID=0
# CONFIG_ADDGROUP is not set
@@ -465,7 +488,6 @@ CONFIG_LAST_SYSTEM_ID=0
# CONFIG_GETTY is not set
# CONFIG_LOGIN is not set
# CONFIG_LOGIN_SESSION_AS_CHILD 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
@@ -516,20 +538,33 @@ CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y
# 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="/lib/modules"
+CONFIG_DEFAULT_MODULES_DIR="/system/lib/modules"
CONFIG_DEFAULT_DEPMOD_FILE="modules.dep"
#
# Linux System Utilities
#
CONFIG_BLOCKDEV=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_FATATTR=y
+CONFIG_FSTRIM=y
+# 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_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_FEATURE_MOUNT_OTHERTAB is not set
CONFIG_REV=y
+CONFIG_UEVENT=y
# CONFIG_ACPID is not set
# CONFIG_FEATURE_ACPID_COMPAT is not set
CONFIG_BLKID=y
@@ -575,15 +610,6 @@ CONFIG_LSUSB=y
CONFIG_MKSWAP=y
CONFIG_FEATURE_MKSWAP_UUID=y
CONFIG_MORE=y
-# 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=y
@@ -593,6 +619,7 @@ CONFIG_SCRIPT=y
CONFIG_SCRIPTREPLAY=y
# CONFIG_SETARCH is not set
# CONFIG_SWAPONOFF is not set
+# CONFIG_FEATURE_SWAPON_DISCARD is not set
# CONFIG_FEATURE_SWAPON_PRI is not set
CONFIG_SWITCH_ROOT=y
# CONFIG_UMOUNT is not set
@@ -605,32 +632,45 @@ CONFIG_VOLUMEID=y
#
# Filesystem/Volume identification
#
-CONFIG_FEATURE_VOLUMEID_EXT=y
CONFIG_FEATURE_VOLUMEID_BTRFS=y
-CONFIG_FEATURE_VOLUMEID_REISERFS=y
+CONFIG_FEATURE_VOLUMEID_CRAMFS=y
+CONFIG_FEATURE_VOLUMEID_EXFAT=y
+CONFIG_FEATURE_VOLUMEID_EXT=y
+CONFIG_FEATURE_VOLUMEID_F2FS=y
CONFIG_FEATURE_VOLUMEID_FAT=y
CONFIG_FEATURE_VOLUMEID_HFS=y
-CONFIG_FEATURE_VOLUMEID_JFS=y
-CONFIG_FEATURE_VOLUMEID_XFS=y
-CONFIG_FEATURE_VOLUMEID_NTFS=y
CONFIG_FEATURE_VOLUMEID_ISO9660=y
-CONFIG_FEATURE_VOLUMEID_UDF=y
-CONFIG_FEATURE_VOLUMEID_LUKS=y
+CONFIG_FEATURE_VOLUMEID_JFS=y
+CONFIG_FEATURE_VOLUMEID_LINUXRAID=y
CONFIG_FEATURE_VOLUMEID_LINUXSWAP=y
-CONFIG_FEATURE_VOLUMEID_CRAMFS=y
+CONFIG_FEATURE_VOLUMEID_LUKS=y
+CONFIG_FEATURE_VOLUMEID_NILFS=y
+CONFIG_FEATURE_VOLUMEID_NTFS=y
+CONFIG_FEATURE_VOLUMEID_OCFS2=y
+CONFIG_FEATURE_VOLUMEID_REISERFS=y
CONFIG_FEATURE_VOLUMEID_ROMFS=y
+CONFIG_FEATURE_VOLUMEID_SQUASHFS=y
CONFIG_FEATURE_VOLUMEID_SYSV=y
-CONFIG_FEATURE_VOLUMEID_OCFS2=y
-CONFIG_FEATURE_VOLUMEID_LINUXRAID=y
+CONFIG_FEATURE_VOLUMEID_UDF=y
+CONFIG_FEATURE_VOLUMEID_XFS=y
#
# Miscellaneous Utilities
#
# CONFIG_CONSPY is not set
+CONFIG_CROND=y
+CONFIG_FEATURE_CROND_D=y
+CONFIG_FEATURE_CROND_CALL_SENDMAIL=y
+CONFIG_FEATURE_CROND_DIR="/var/spool/cron"
+CONFIG_I2CGET=y
+CONFIG_I2CSET=y
+CONFIG_I2CDUMP=y
+CONFIG_I2CDETECT=y
CONFIG_LESS=y
CONFIG_FEATURE_LESS_MAXLINES=9999999
CONFIG_FEATURE_LESS_BRACKETS=y
CONFIG_FEATURE_LESS_FLAGS=y
+CONFIG_FEATURE_LESS_TRUNCATE=y
CONFIG_FEATURE_LESS_MARKS=y
CONFIG_FEATURE_LESS_REGEXP=y
CONFIG_FEATURE_LESS_WINCH=y
@@ -639,16 +679,20 @@ CONFIG_FEATURE_LESS_DASHCMD=y
CONFIG_FEATURE_LESS_LINENUMS=y
# CONFIG_NANDWRITE is not set
CONFIG_NANDDUMP=y
+# CONFIG_RFKILL is not set
CONFIG_SETSERIAL=y
+# CONFIG_TASKSET is not set
+# CONFIG_FEATURE_TASKSET_FANCY is not set
# CONFIG_UBIATTACH is not set
# CONFIG_UBIDETACH is not set
# CONFIG_UBIMKVOL is not set
# CONFIG_UBIRMVOL is not set
# CONFIG_UBIRSVOL is not set
# CONFIG_UBIUPDATEVOL is not set
+# CONFIG_WALL is not set
# CONFIG_ADJTIMEX is not set
-# CONFIG_BBCONFIG is not set
-# CONFIG_FEATURE_COMPRESS_BBCONFIG is not set
+CONFIG_BBCONFIG=y
+CONFIG_FEATURE_COMPRESS_BBCONFIG=y
CONFIG_BEEP=y
CONFIG_FEATURE_BEEP_FREQ=4000
CONFIG_FEATURE_BEEP_LENGTH_MS=30
@@ -661,10 +705,6 @@ CONFIG_FEATURE_CHAT_SEND_ESCAPES=y
CONFIG_FEATURE_CHAT_VAR_ABORT_LEN=y
CONFIG_FEATURE_CHAT_CLR_ABORT=y
CONFIG_CHRT=y
-CONFIG_CROND=y
-CONFIG_FEATURE_CROND_D=y
-CONFIG_FEATURE_CROND_CALL_SENDMAIL=y
-CONFIG_FEATURE_CROND_DIR="/var/spool/cron"
CONFIG_CRONTAB=y
CONFIG_DC=y
CONFIG_FEATURE_DC_LIBM=y
@@ -702,18 +742,14 @@ CONFIG_MAN=y
# CONFIG_MT is not set
CONFIG_RAIDAUTORUN=y
# CONFIG_READAHEAD is not set
-# CONFIG_RFKILL is not set
# CONFIG_RUNLEVEL is not set
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 is not set
# CONFIG_WATCHDOG is not set
#
@@ -745,13 +781,13 @@ CONFIG_FAKEIDENTD=y
CONFIG_FTPD=y
CONFIG_FEATURE_FTP_WRITE=y
CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST=y
+CONFIG_FEATURE_FTP_AUTHENTICATION=y
CONFIG_FTPGET=y
CONFIG_FTPPUT=y
# CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set
# CONFIG_HOSTNAME is not set
CONFIG_HTTPD=y
CONFIG_FEATURE_HTTPD_RANGES=y
-CONFIG_FEATURE_HTTPD_USE_SENDFILE=y
CONFIG_FEATURE_HTTPD_SETUID=y
CONFIG_FEATURE_HTTPD_BASIC_AUTH=y
# CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set
@@ -808,6 +844,7 @@ CONFIG_FEATURE_NETSTAT_PRG=y
# CONFIG_NSLOOKUP is not set
# CONFIG_NTPD is not set
# CONFIG_FEATURE_NTPD_SERVER is not set
+# CONFIG_FEATURE_NTPD_CONF is not set
CONFIG_PSCAN=y
CONFIG_ROUTE=y
# CONFIG_SLATTACH is not set
@@ -845,6 +882,7 @@ CONFIG_FEATURE_TUNCTL_UG=y
CONFIG_DHCPD_LEASES_FILE=""
CONFIG_UDHCPC=y
CONFIG_FEATURE_UDHCPC_ARPING=y
+CONFIG_FEATURE_UDHCPC_SANITIZEOPT=y
CONFIG_FEATURE_UDHCP_PORT=y
CONFIG_UDHCP_DEBUG=9
CONFIG_FEATURE_UDHCP_RFC3397=y
@@ -883,6 +921,7 @@ CONFIG_SENDMAIL=y
# Process Utilities
#
CONFIG_IOSTAT=y
+CONFIG_LSOF=y
CONFIG_MPSTAT=y
CONFIG_NMETER=y
CONFIG_PMAP=y
@@ -890,6 +929,13 @@ CONFIG_POWERTOP=y
CONFIG_PSTREE=y
CONFIG_PWDX=y
CONFIG_SMEMCAP=y
+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_UPTIME=y
# CONFIG_FEATURE_UPTIME_UTMP_SUPPORT is not set
CONFIG_FREE=y
@@ -910,13 +956,6 @@ CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS=y
# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set
CONFIG_RENICE=y
CONFIG_BB_SYSCTL=y
-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_WATCH=y
@@ -962,6 +1001,7 @@ CONFIG_SOFTLIMIT=y
# CONFIG_ASH_BUILTIN_ECHO is not set
# CONFIG_ASH_BUILTIN_PRINTF is not set
# CONFIG_ASH_BUILTIN_TEST is not set
+# CONFIG_ASH_HELP is not set
# CONFIG_ASH_CMDCMD is not set
# CONFIG_ASH_MAIL is not set
# CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set
@@ -1011,6 +1051,7 @@ CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=0
CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=0
# CONFIG_LOGREAD is not set
# CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set
+# CONFIG_FEATURE_KMSG_SYSLOG is not set
CONFIG_KLOGD=y
CONFIG_FEATURE_KLOGD_KLOGCTL=y
# CONFIG_LOGGER is not set
diff --git a/release/src/router/busybox/configs/cygwin_defconfig b/release/src/router/busybox/configs/cygwin_defconfig
index bdd0d66d0a..38d580ad11 100644
--- a/release/src/router/busybox/configs/cygwin_defconfig
+++ b/release/src/router/busybox/configs/cygwin_defconfig
@@ -89,7 +89,6 @@ CONFIG_PREFIX="./_install"
#
# Busybox Library Tuning
#
-# CONFIG_FEATURE_SYSTEMD is not set
CONFIG_FEATURE_RTMINMAX=y
CONFIG_PASSWORD_MINLEN=6
CONFIG_MD5_SMALL=1
@@ -363,7 +362,6 @@ CONFIG_FEATURE_VI_SETOPTS=y
CONFIG_FEATURE_VI_SET=y
CONFIG_FEATURE_VI_WIN_RESIZE=y
CONFIG_FEATURE_VI_ASK_TERMINAL=y
-CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y
CONFIG_AWK=y
CONFIG_FEATURE_AWK_LIBM=y
CONFIG_CMP=y
@@ -427,7 +425,7 @@ CONFIG_FEATURE_KILL_DELAY=0
# 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_LINUXRC is not set
CONFIG_INIT_TERMINAL_TYPE=""
CONFIG_MESG=y
CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP=y
diff --git a/release/src/router/busybox/configs/freebsd_defconfig b/release/src/router/busybox/configs/freebsd_defconfig
index dcb5d953c2..ae62f13898 100644
--- a/release/src/router/busybox/configs/freebsd_defconfig
+++ b/release/src/router/busybox/configs/freebsd_defconfig
@@ -367,7 +367,6 @@ CONFIG_FEATURE_VI_SETOPTS=y
CONFIG_FEATURE_VI_SET=y
CONFIG_FEATURE_VI_WIN_RESIZE=y
CONFIG_FEATURE_VI_ASK_TERMINAL=y
-CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y
CONFIG_FEATURE_ALLOW_EXEC=y
#
@@ -423,7 +422,7 @@ CONFIG_FEATURE_KILL_DELAY=0
# 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_LINUXRC is not set
CONFIG_INIT_TERMINAL_TYPE=""
# CONFIG_MESG is not set
diff --git a/release/src/router/busybox/console-tools/dumpkmap.c b/release/src/router/busybox/console-tools/dumpkmap.c
index 6b923d2d47..b6fd466dc8 100644
--- a/release/src/router/busybox/console-tools/dumpkmap.c
+++ b/release/src/router/busybox/console-tools/dumpkmap.c
@@ -18,6 +18,7 @@
//usage: "$ dumpkmap > keymap\n"
#include "libbb.h"
+#include "common_bufsiz.h"
/* From <linux/kd.h> */
struct kbentry {
@@ -36,47 +37,57 @@ int dumpkmap_main(int argc UNUSED_PARAM, char **argv)
{
struct kbentry ke;
int i, j, fd;
- RESERVE_CONFIG_BUFFER(flags, MAX_NR_KEYMAPS);
+#define flags bb_common_bufsiz1
+ setup_common_bufsiz();
/* When user accidentally runs "dumpkmap FILE"
* instead of "dumpkmap >FILE", we'd dump binary stuff to tty.
- * Let's prevent it: */
+ * Let's prevent it:
+ */
if (argv[1])
bb_show_usage();
/* bb_warn_ignoring_args(argv[1]);*/
fd = get_console_fd_or_die();
+#if 0
write(STDOUT_FILENO, "bkeymap", 7);
-
/* Here we want to set everything to 0 except for indexes:
- * [0-2] [4-6] [8-10] [12] */
- memset(flags, 0x00, MAX_NR_KEYMAPS);
+ * [0-2] [4-6] [8-10] [12]
+ */
+ /*memset(flags, 0x00, MAX_NR_KEYMAPS); - already is */
memset(flags, 0x01, 13);
flags[3] = flags[7] = flags[11] = 0;
-
/* dump flags */
write(STDOUT_FILENO, flags, MAX_NR_KEYMAPS);
+#define flags7 flags
+#else
+ /* Same effect */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c=12 */
+ memcpy(flags, "bkeymap\1\1\1\0\1\1\1\0\1\1\1\0\1",
+ /* Can use sizeof, or sizeof-1. sizeof is even, using that */
+ /****/ sizeof("bkeymap\1\1\1\0\1\1\1\0\1\1\1\0\1")
+ );
+ write(STDOUT_FILENO, flags, 7 + MAX_NR_KEYMAPS);
+#define flags7 (flags + 7)
+#endif
- for (i = 0; i < MAX_NR_KEYMAPS; i++) {
- if (flags[i] == 1) {
+ for (i = 0; i < 13; i++) {
+ if (flags7[i]) {
for (j = 0; j < NR_KEYS; j++) {
ke.kb_index = j;
ke.kb_table = i;
if (!ioctl_or_perror(fd, KDGKBENT, &ke,
- "ioctl failed with %s, %s, %p",
- (char *)&ke.kb_index,
- (char *)&ke.kb_table,
- &ke.kb_value)
+ "ioctl(KDGKBENT{%d,%d}) failed",
+ j, i)
) {
- write(STDOUT_FILENO, (void*)&ke.kb_value, 2);
+ write(STDOUT_FILENO, &ke.kb_value, 2);
}
}
}
}
if (ENABLE_FEATURE_CLEAN_UP) {
close(fd);
- RELEASE_CONFIG_BUFFER(flags);
}
return EXIT_SUCCESS;
}
diff --git a/release/src/router/busybox/console-tools/loadfont.c b/release/src/router/busybox/console-tools/loadfont.c
index 9e887f2566..032506d6da 100644
--- a/release/src/router/busybox/console-tools/loadfont.c
+++ b/release/src/router/busybox/console-tools/loadfont.c
@@ -229,7 +229,7 @@ static void do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize,
}
/* Note: after PIO_UNIMAPCLR and before PIO_UNIMAP
- this printf did not work on many kernels */
+ * this printf did not work on many kernels */
advice.advised_hashsize = 0;
advice.advised_hashstep = 0;
diff --git a/release/src/router/busybox/console-tools/loadkmap.c b/release/src/router/busybox/console-tools/loadkmap.c
index bcffe16b12..f525ee5d11 100644
--- a/release/src/router/busybox/console-tools/loadkmap.c
+++ b/release/src/router/busybox/console-tools/loadkmap.c
@@ -10,8 +10,9 @@
//usage:#define loadkmap_trivial_usage
//usage: "< keymap"
//usage:#define loadkmap_full_usage "\n\n"
-//usage: "Load a binary keyboard translation table from stdin\n"
-/* //usage: "\n -C TTY Affect TTY instead of /dev/tty" */
+//usage: "Load a binary keyboard translation table from stdin"
+////usage: "\n"
+////usage: "\n -C TTY Affect TTY instead of /dev/tty"
//usage:
//usage:#define loadkmap_example_usage
//usage: "$ loadkmap < /etc/i18n/lang-keymap\n"
@@ -48,6 +49,7 @@ int loadkmap_main(int argc UNUSED_PARAM, char **argv)
if (argv[1])
bb_show_usage();
/* bb_warn_ignoring_args(argv[1]); */
+
fd = get_console_fd_or_die();
/* or maybe:
opt = getopt32(argv, "C:", &tty_name);
@@ -55,20 +57,30 @@ int loadkmap_main(int argc UNUSED_PARAM, char **argv)
*/
xread(STDIN_FILENO, flags, 7);
- if (strncmp(flags, BINARY_KEYMAP_MAGIC, 7))
+ if (!is_prefixed_with(flags, BINARY_KEYMAP_MAGIC))
bb_error_msg_and_die("not a valid binary keymap");
xread(STDIN_FILENO, flags, MAX_NR_KEYMAPS);
for (i = 0; i < MAX_NR_KEYMAPS; i++) {
- if (flags[i] == 1) {
- xread(STDIN_FILENO, ibuff, NR_KEYS * sizeof(uint16_t));
- for (j = 0; j < NR_KEYS; j++) {
- ke.kb_index = j;
- ke.kb_table = i;
- ke.kb_value = ibuff[j];
- ioctl(fd, KDSKBENT, &ke);
- }
+ if (flags[i] != 1)
+ continue;
+ xread(STDIN_FILENO, ibuff, NR_KEYS * sizeof(uint16_t));
+ for (j = 0; j < NR_KEYS; j++) {
+ ke.kb_index = j;
+ ke.kb_table = i;
+ ke.kb_value = ibuff[j];
+ /*
+ * Note: table[idx:0] can contain special value
+ * K_ALLOCATED (marks allocated tables in kernel).
+ * dumpkmap saves the value as-is; but attempts
+ * to load it here fail, since it isn't a valid
+ * key value: it is K(KT_SPEC,126) == 2<<8 + 126,
+ * whereas last valid KT_SPEC is
+ * K_BARENUMLOCK == K(KT_SPEC,19).
+ * So far we just ignore these errors:
+ */
+ ioctl(fd, KDSKBENT, &ke);
}
}
diff --git a/release/src/router/busybox/console-tools/resize.c b/release/src/router/busybox/console-tools/resize.c
index 4b0d63a03c..a3342a1956 100644
--- a/release/src/router/busybox/console-tools/resize.c
+++ b/release/src/router/busybox/console-tools/resize.c
@@ -14,10 +14,12 @@
//usage: "Resize the screen"
#include "libbb.h"
+#include "common_bufsiz.h"
#define ESC "\033"
-#define old_termios_p ((struct termios*)&bb_common_bufsiz1)
+#define old_termios_p ((struct termios*)bb_common_bufsiz1)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
static void
onintr(int sig UNUSED_PARAM)
@@ -33,6 +35,8 @@ int resize_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
struct winsize w = { 0, 0, 0, 0 };
int ret;
+ INIT_G();
+
/* We use _stderr_ in order to make resize usable
* in shell backticks (those redirect stdout away from tty).
* NB: other versions of resize open "/dev/tty"
diff --git a/release/src/router/busybox/console-tools/setlogcons.c b/release/src/router/busybox/console-tools/setlogcons.c
index 83a895407b..2a11da3296 100644
--- a/release/src/router/busybox/console-tools/setlogcons.c
+++ b/release/src/router/busybox/console-tools/setlogcons.c
@@ -10,9 +10,9 @@
*/
//usage:#define setlogcons_trivial_usage
-//usage: "N"
+//usage: "[N]"
//usage:#define setlogcons_full_usage "\n\n"
-//usage: "Redirect the kernel output to console N (0 for current)"
+//usage: "Redirect the kernel output to console N. Default:0 (current console)"
#include "libbb.h"
@@ -22,9 +22,10 @@ int setlogcons_main(int argc UNUSED_PARAM, char **argv)
struct {
char fn;
char subarg;
- } arg = { 11, /* redirect kernel messages */
- 0 /* to specified console (current as default) */
- };
+ } arg = {
+ 11, /* redirect kernel messages */
+ 0 /* to specified console (current as default) */
+ };
if (argv[1])
arg.subarg = xatou_range(argv[1], 0, 63);
diff --git a/release/src/router/busybox/console-tools/showkey.c b/release/src/router/busybox/console-tools/showkey.c
index 69b785ec62..b7b4c32a80 100644
--- a/release/src/router/busybox/console-tools/showkey.c
+++ b/release/src/router/busybox/console-tools/showkey.c
@@ -83,7 +83,6 @@ int showkey_main(int argc UNUSED_PARAM, char **argv)
if (04 /*CTRL-D*/ == c)
break;
}
-
} else {
// we assume a PC keyboard
xioctl(STDIN_FILENO, KDGKBMODE, &kbmode);
diff --git a/release/src/router/busybox/coreutils/Config.src b/release/src/router/busybox/coreutils/Config.src
index a28449b11d..619c2efe83 100644
--- a/release/src/router/busybox/coreutils/Config.src
+++ b/release/src/router/busybox/coreutils/Config.src
@@ -11,7 +11,7 @@ config CAL
bool "cal"
default y
help
- cal is used to display a monthly calender.
+ cal is used to display a monthly calendar.
config CATV
bool "catv"
@@ -87,44 +87,6 @@ config CUT
cut is used to print selected parts of lines from
each file to stdout.
-config DD
- bool "dd"
- default y
- help
- dd copies a file (from standard input to standard output,
- by default) using specific input and output blocksizes,
- while optionally performing conversions on it.
-
-config FEATURE_DD_SIGNAL_HANDLING
- bool "Enable DD signal handling for status reporting"
- default y
- depends on DD
- help
- Sending a SIGUSR1 signal to a running `dd' process makes it
- print to standard error the number of records read and written
- so far, then to resume copying.
-
- $ dd if=/dev/zero of=/dev/null&
- $ pid=$! kill -USR1 $pid; sleep 1; kill $pid
- 10899206+0 records in
- 10899206+0 records out
-
-config FEATURE_DD_THIRD_STATUS_LINE
- bool "Enable the third status line upon signal"
- default y
- depends on DD && FEATURE_DD_SIGNAL_HANDLING
- help
- Displays a coreutils-like third status line with transferred bytes,
- elapsed time and speed.
-
-config FEATURE_DD_IBS_OBS
- bool "Enable ibs, obs and conv options"
- default y
- depends on DD
- help
- Enables support for writing a certain number of bytes in and out,
- at a time, and performing conversions on the data stream.
-
config DF
bool "df"
default y
@@ -514,6 +476,12 @@ config SHA512SUM
help
Compute and check SHA512 message digest
+config SHA3SUM
+ bool "sha3sum"
+ default y
+ help
+ Compute and check SHA3 (512-bit) message digest
+
config SLEEP
bool "sleep"
default y
@@ -575,22 +543,6 @@ config FEATURE_SPLIT_FANCY
Supports additional suffixes 'b' for 512 bytes,
'g' for 1GiB for the -b option.
-config STAT
- bool "stat"
- default y
- select PLATFORM_LINUX # statfs()
- help
- display file or filesystem status.
-
-config FEATURE_STAT_FORMAT
- bool "Enable custom formats (-c)"
- default y
- depends on STAT
- help
- Without this, stat will not support the '-c format' option where
- users can pass a custom format string for output. This adds about
- 7k to a nonstatic build on amd64.
-
config STTY
bool "stty"
default y
@@ -603,12 +555,6 @@ config SUM
help
checksum and count the blocks in a file
-config SYNC
- bool "sync"
- default y
- help
- sync is used to flush filesystem buffers.
-
config TAC
bool "tac"
default y
@@ -627,12 +573,13 @@ config FEATURE_FANCY_TAIL
default y
depends on TAIL
help
- The options (-q, -s, and -v) are provided by GNU tail, but
+ The options (-q, -s, -v and -F) are provided by GNU tail, but
are not specific in the SUSv3 standard.
-q Never output headers giving file names
-s SEC Wait SEC seconds between reads with -f
-v Always output headers giving file names
+ -F Same as -f, but keep retrying
config TEE
bool "tee"
@@ -667,6 +614,14 @@ config UNAME
help
uname is used to print system information.
+config UNAME_OSNAME
+ string "Operating system name"
+ default "GNU/Linux"
+ depends on UNAME
+ help
+ Sets the operating system name reported by uname -o. The
+ default is "GNU/Linux".
+
config UNEXPAND
bool "unexpand"
default y
@@ -732,6 +687,16 @@ config YES
yes is used to repeatedly output a specific string, or
the default string `y'.
+comment "Common options"
+
+config FEATURE_VERBOSE
+ bool "Support verbose options (usually -v) for various applets"
+ default y
+ help
+ Enable cp -v, rm -v and similar messages.
+ Also enables long option (--verbose) if it exists.
+ Without this option, -v is accepted but ignored.
+
comment "Common options for cp and mv"
depends on CP || MV
@@ -766,13 +731,13 @@ config FEATURE_HUMAN_READABLE
help
Allow df, du, and ls to have human readable output.
-comment "Common options for md5sum, sha1sum, sha256sum, sha512sum"
- depends on MD5SUM || SHA1SUM || SHA256SUM || SHA512SUM
+comment "Common options for md5sum, sha1sum, sha256sum, sha512sum, sha3sum"
+ depends on MD5SUM || SHA1SUM || SHA256SUM || SHA512SUM || SHA3SUM
config FEATURE_MD5_SHA1_SUM_CHECK
bool "Enable -c, -s and -w options"
default y
- depends on MD5SUM || SHA1SUM || SHA256SUM || SHA512SUM
+ depends on MD5SUM || SHA1SUM || SHA256SUM || SHA512SUM || SHA3SUM
help
Enabling the -c options allows files to be checked
against pre-calculated hash values.
diff --git a/release/src/router/busybox/coreutils/Kbuild.src b/release/src/router/busybox/coreutils/Kbuild.src
index d6453f0145..4ec075ac67 100644
--- a/release/src/router/busybox/coreutils/Kbuild.src
+++ b/release/src/router/busybox/coreutils/Kbuild.src
@@ -35,7 +35,6 @@ lib-$(CONFIG_EXPAND) += expand.o
lib-$(CONFIG_FALSE) += false.o
lib-$(CONFIG_FOLD) += fold.o
lib-$(CONFIG_FSYNC) += fsync.o
-lib-$(CONFIG_HEAD) += head.o
lib-$(CONFIG_INSTALL) += install.o
#lib-$(CONFIG_LENGTH) += length.o
lib-$(CONFIG_LN) += ln.o
@@ -62,15 +61,14 @@ lib-$(CONFIG_SEQ) += seq.o
lib-$(CONFIG_SHA1SUM) += md5_sha1_sum.o
lib-$(CONFIG_SHA256SUM) += md5_sha1_sum.o
lib-$(CONFIG_SHA512SUM) += md5_sha1_sum.o
+lib-$(CONFIG_SHA3SUM) += md5_sha1_sum.o
lib-$(CONFIG_SLEEP) += sleep.o
lib-$(CONFIG_SPLIT) += split.o
lib-$(CONFIG_SORT) += sort.o
lib-$(CONFIG_STAT) += stat.o
lib-$(CONFIG_STTY) += stty.o
lib-$(CONFIG_SUM) += sum.o
-lib-$(CONFIG_SYNC) += sync.o
lib-$(CONFIG_TAC) += tac.o
-lib-$(CONFIG_TAIL) += tail.o
lib-$(CONFIG_TEE) += tee.o
lib-$(CONFIG_TRUE) += true.o
lib-$(CONFIG_TTY) += tty.o
diff --git a/release/src/router/busybox/coreutils/basename.c b/release/src/router/busybox/coreutils/basename.c
index 1f7a13713c..ab0c972edd 100644
--- a/release/src/router/busybox/coreutils/basename.c
+++ b/release/src/router/busybox/coreutils/basename.c
@@ -31,7 +31,7 @@
//usage:#define basename_trivial_usage
//usage: "FILE [SUFFIX]"
//usage:#define basename_full_usage "\n\n"
-//usage: "Strip directory path and .SUFFIX from FILE\n"
+//usage: "Strip directory path and .SUFFIX from FILE"
//usage:
//usage:#define basename_example_usage
//usage: "$ basename /usr/local/bin/foo\n"
diff --git a/release/src/router/busybox/coreutils/cal.c b/release/src/router/busybox/coreutils/cal.c
index b470ad968a..12c46b14ff 100644
--- a/release/src/router/busybox/coreutils/cal.c
+++ b/release/src/router/busybox/coreutils/cal.c
@@ -43,7 +43,7 @@ static const unsigned char days_in_month[] ALIGN1 = {
};
static const unsigned char sep1752[] ALIGN1 = {
- 1, 2, 14, 15, 16,
+ 1, 2, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30
};
@@ -165,10 +165,10 @@ int cal_main(int argc UNUSED_PARAM, char **argv)
char lineout[30];
day_array(month, year, dp);
- len = sprintf(lineout, "%s %d", month_names[month - 1], year);
+ len = sprintf(lineout, "%s %u", month_names[month - 1], year);
printf("%*s%s\n%s\n",
- ((7*julian + WEEK_LEN) - len) / 2, "",
- lineout, day_headings);
+ ((7*julian + WEEK_LEN) - len) / 2, "",
+ lineout, day_headings);
for (row = 0; row < 6; row++) {
build_row(lineout, dp)[0] = '\0';
dp += 7;
@@ -181,10 +181,11 @@ int cal_main(int argc UNUSED_PARAM, char **argv)
sprintf(lineout, "%u", year);
center(lineout,
- (WEEK_LEN * 3 + HEAD_SEP * 2)
- + julian * (J_WEEK_LEN * 2 + HEAD_SEP
- - (WEEK_LEN * 3 + HEAD_SEP * 2)),
- 0);
+ (WEEK_LEN * 3 + HEAD_SEP * 2)
+ + julian * (J_WEEK_LEN * 2 + HEAD_SEP
+ - (WEEK_LEN * 3 + HEAD_SEP * 2)),
+ 0
+ );
puts("\n"); /* two \n's */
for (i = 0; i < 12; i++) {
day_array(i + 1, year, days[i]);
diff --git a/release/src/router/busybox/coreutils/catv.c b/release/src/router/busybox/coreutils/catv.c
index 214b4311a6..0e71368a5f 100644
--- a/release/src/router/busybox/coreutils/catv.c
+++ b/release/src/router/busybox/coreutils/catv.c
@@ -19,24 +19,39 @@
//usage: "\n -v Don't use ^x or M-x escapes"
#include "libbb.h"
+#include "common_bufsiz.h"
+
+#define CATV_OPT_e (1<<0)
+#define CATV_OPT_t (1<<1)
+#define CATV_OPT_v (1<<2)
+struct BUG_const_mismatch {
+ char BUG_const_mismatch[
+ CATV_OPT_e == VISIBLE_ENDLINE && CATV_OPT_t == VISIBLE_SHOW_TABS
+ ? 1 : -1
+ ];
+};
int catv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int catv_main(int argc UNUSED_PARAM, char **argv)
{
int retval = EXIT_SUCCESS;
int fd;
- unsigned flags;
-
- flags = getopt32(argv, "etv");
-#define CATV_OPT_e (1<<0)
-#define CATV_OPT_t (1<<1)
-#define CATV_OPT_v (1<<2)
- flags ^= CATV_OPT_v;
+ unsigned opts;
+ opts = getopt32(argv, "etv");
argv += optind;
+#if 0 /* These consts match, we can just pass "opts" to visible() */
+ if (opts & CATV_OPT_e)
+ flags |= VISIBLE_ENDLINE;
+ if (opts & CATV_OPT_t)
+ flags |= VISIBLE_SHOW_TABS;
+#endif
/* Read from stdin if there's nothing else to do. */
if (!argv[0])
*--argv = (char*)"-";
+
+#define read_buf bb_common_bufsiz1
+ setup_common_bufsiz();
do {
fd = open_or_warn_stdin(*argv);
if (fd < 0) {
@@ -46,33 +61,20 @@ int catv_main(int argc UNUSED_PARAM, char **argv)
for (;;) {
int i, res;
-#define read_buf bb_common_bufsiz1
res = read(fd, read_buf, COMMON_BUFSIZE);
if (res < 0)
retval = EXIT_FAILURE;
- if (res < 1)
+ if (res <= 0)
break;
for (i = 0; i < res; i++) {
unsigned char c = read_buf[i];
-
- if (c > 126 && (flags & CATV_OPT_v)) {
- if (c == 127) {
- printf("^?");
- continue;
- }
- printf("M-");
- c -= 128;
- }
- if (c < 32) {
- if (c == 10) {
- if (flags & CATV_OPT_e)
- bb_putchar('$');
- } else if (flags & (c==9 ? CATV_OPT_t : CATV_OPT_v)) {
- printf("^%c", c+'@');
- continue;
- }
+ if (opts & CATV_OPT_v) {
+ putchar(c);
+ } else {
+ char buf[sizeof("M-^c")];
+ visible(c, buf, opts);
+ fputs(buf, stdout);
}
- bb_putchar(c);
}
}
if (ENABLE_FEATURE_CLEAN_UP && fd)
diff --git a/release/src/router/busybox/coreutils/chmod.c b/release/src/router/busybox/coreutils/chmod.c
index 5ee45b9420..a21c6d5018 100644
--- a/release/src/router/busybox/coreutils/chmod.c
+++ b/release/src/router/busybox/coreutils/chmod.c
@@ -69,9 +69,9 @@ static int FAST_FUNC fileAction(const char *fileName, struct stat *statbuf, void
if (S_ISLNK(statbuf->st_mode))
return TRUE;
}
- newmode = statbuf->st_mode;
- if (!bb_parse_mode((char *)param, &newmode))
+ newmode = bb_parse_mode((char *)param, statbuf->st_mode);
+ if (newmode == (mode_t)-1)
bb_error_msg_and_die("invalid mode '%s'", (char *)param);
if (chmod(fileName, newmode) == 0) {
diff --git a/release/src/router/busybox/coreutils/chown.c b/release/src/router/busybox/coreutils/chown.c
index bb166d8fe4..247aa3bf12 100644
--- a/release/src/router/busybox/coreutils/chown.c
+++ b/release/src/router/busybox/coreutils/chown.c
@@ -11,15 +11,15 @@
/* http://www.opengroup.org/onlinepubs/007904975/utilities/chown.html */
//usage:#define chown_trivial_usage
-//usage: "[-RhLHP"IF_DESKTOP("cvf")"]... OWNER[<.|:>[GROUP]] FILE..."
+//usage: "[-Rh"IF_DESKTOP("LHPcvf")"]... USER[:[GRP]] FILE..."
//usage:#define chown_full_usage "\n\n"
-//usage: "Change the owner and/or group of each FILE to OWNER and/or GROUP\n"
+//usage: "Change the owner and/or group of each FILE to USER and/or GRP\n"
//usage: "\n -R Recurse"
//usage: "\n -h Affect symlinks instead of symlink targets"
+//usage: IF_DESKTOP(
//usage: "\n -L Traverse all symlinks to directories"
//usage: "\n -H Traverse symlinks on command line only"
//usage: "\n -P Don't traverse symlinks (default)"
-//usage: IF_DESKTOP(
//usage: "\n -c List changed files"
//usage: "\n -v List all files"
//usage: "\n -f Hide errors"
@@ -112,10 +112,6 @@ int chown_main(int argc UNUSED_PARAM, char **argv)
int opt, flags;
struct param_t param;
- /* Just -1 might not work: uid_t may be unsigned long */
- param.ugid.uid = -1L;
- param.ugid.gid = -1L;
-
#if ENABLE_FEATURE_CHOWN_LONG_OPTIONS
applet_long_options = chown_longopts;
#endif
@@ -126,8 +122,8 @@ int chown_main(int argc UNUSED_PARAM, char **argv)
/* This matches coreutils behavior (almost - see below) */
param.chown_func = chown;
if (OPT_NODEREF
- /* || (OPT_RECURSE && !OPT_TRAVERSE_TOP): */
- IF_DESKTOP( || (opt & (BIT_RECURSE|BIT_TRAVERSE_TOP)) == BIT_RECURSE)
+ /* || (OPT_RECURSE && !OPT_TRAVERSE_TOP): */
+ IF_DESKTOP( || (opt & (BIT_RECURSE|BIT_TRAVERSE_TOP)) == BIT_RECURSE)
) {
param.chown_func = lchown;
}
diff --git a/release/src/router/busybox/coreutils/cksum.c b/release/src/router/busybox/coreutils/cksum.c
index ac0b0c319e..8a8a39f68a 100644
--- a/release/src/router/busybox/coreutils/cksum.c
+++ b/release/src/router/busybox/coreutils/cksum.c
@@ -13,6 +13,7 @@
//usage: "Calculate the CRC32 checksums of FILES"
#include "libbb.h"
+#include "common_bufsiz.h"
/* This is a NOEXEC applet. Be very careful! */
@@ -32,6 +33,7 @@ int cksum_main(int argc UNUSED_PARAM, char **argv)
argv++;
#endif
+ setup_common_bufsiz();
do {
int fd = open_or_warn_stdin(*argv ? *argv : bb_msg_standard_input);
@@ -43,7 +45,7 @@ int cksum_main(int argc UNUSED_PARAM, char **argv)
length = 0;
#define read_buf bb_common_bufsiz1
- while ((bytes_read = safe_read(fd, read_buf, sizeof(read_buf))) > 0) {
+ while ((bytes_read = safe_read(fd, read_buf, COMMON_BUFSIZE)) > 0) {
length += bytes_read;
crc = crc32_block_endian1(crc, read_buf, bytes_read, crc32_table);
}
diff --git a/release/src/router/busybox/coreutils/cp.c b/release/src/router/busybox/coreutils/cp.c
index de2e512be3..2630c0d596 100644
--- a/release/src/router/busybox/coreutils/cp.c
+++ b/release/src/router/busybox/coreutils/cp.c
@@ -31,6 +31,7 @@
//usage: "\n -f Overwrite"
//usage: "\n -i Prompt before overwrite"
//usage: "\n -l,-s Create (sym)links"
+//usage: "\n -u Copy only newer files"
#include "libbb.h"
#include "libcoreutils/coreutils.h"
@@ -49,12 +50,10 @@ int cp_main(int argc, char **argv)
int flags;
int status;
enum {
- OPT_a = 1 << (sizeof(FILEUTILS_CP_OPTSTR)-1),
- OPT_r = 1 << (sizeof(FILEUTILS_CP_OPTSTR)),
- OPT_P = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+1),
- OPT_v = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+2),
+ FILEUTILS_CP_OPTNUM = sizeof(FILEUTILS_CP_OPTSTR)-1,
#if ENABLE_FEATURE_CP_LONG_OPTIONS
- OPT_parents = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+3),
+ /*OPT_rmdest = FILEUTILS_RMDEST = 1 << FILEUTILS_CP_OPTNUM */
+ OPT_parents = 1 << (FILEUTILS_CP_OPTNUM+1),
#endif
};
@@ -76,11 +75,12 @@ int cp_main(int argc, char **argv)
"recursive\0" No_argument "R"
"symbolic-link\0" No_argument "s"
"verbose\0" No_argument "v"
- "parents\0" No_argument "\xff"
+ "update\0" No_argument "u"
+ "remove-destination\0" No_argument "\xff"
+ "parents\0" No_argument "\xfe"
;
#endif
- // -v (--verbose) is ignored
- flags = getopt32(argv, FILEUTILS_CP_OPTSTR "arPv");
+ flags = getopt32(argv, FILEUTILS_CP_OPTSTR);
/* Options of cp from GNU coreutils 6.10:
* -a, --archive
* -f, --force
@@ -95,6 +95,11 @@ int cp_main(int argc, char **argv)
* -d same as --no-dereference --preserve=links
* -p same as --preserve=mode,ownership,timestamps
* -c same as --preserve=context
+ * -u, --update
+ * copy only when the SOURCE file is newer than the destination
+ * file or when the destination file is missing
+ * --remove-destination
+ * remove each existing destination file before attempting to open
* --parents
* use full source file name under DIRECTORY
* NOT SUPPORTED IN BBOX:
@@ -107,8 +112,6 @@ int cp_main(int argc, char **argv)
* preserve attributes (default: mode,ownership,timestamps),
* if possible additional attributes: security context,links,all
* --no-preserve=ATTR_LIST
- * --remove-destination
- * remove each existing destination file before attempting to open
* --sparse=WHEN
* control creation of sparse files
* --strip-trailing-slashes
@@ -119,9 +122,6 @@ int cp_main(int argc, char **argv)
* copy all SOURCE arguments into DIRECTORY
* -T, --no-target-directory
* treat DEST as a normal file
- * -u, --update
- * copy only when the SOURCE file is newer than the destination
- * file or when the destination file is missing
* -x, --one-file-system
* stay on this file system
* -Z, --context=CONTEXT
@@ -157,11 +157,16 @@ int cp_main(int argc, char **argv)
return EXIT_FAILURE;
#if ENABLE_FEATURE_CP_LONG_OPTIONS
+ //bb_error_msg("flags:%x FILEUTILS_RMDEST:%x OPT_parents:%x",
+ // flags, FILEUTILS_RMDEST, OPT_parents);
if (flags & OPT_parents) {
if (!(d_flags & 2)) {
bb_error_msg_and_die("with --parents, the destination must be a directory");
}
}
+ if (flags & FILEUTILS_RMDEST) {
+ flags |= FILEUTILS_FORCE;
+ }
#endif
/* ...if neither is a directory... */
diff --git a/release/src/router/busybox/coreutils/cut.c b/release/src/router/busybox/coreutils/cut.c
index 2c27b704f5..84449c775c 100644
--- a/release/src/router/busybox/coreutils/cut.c
+++ b/release/src/router/busybox/coreutils/cut.c
@@ -212,7 +212,7 @@ int cut_main(int argc UNUSED_PARAM, char **argv)
if (opt & CUT_OPT_SUPPRESS_FLGS) {
bb_error_msg_and_die
("suppressing non-delimited lines makes sense%s",
- _op_on_field);
+ _op_on_field);
}
if (delim != '\t') {
bb_error_msg_and_die
diff --git a/release/src/router/busybox/coreutils/date.c b/release/src/router/busybox/coreutils/date.c
index 767e0d4a29..ff3214d851 100644
--- a/release/src/router/busybox/coreutils/date.c
+++ b/release/src/router/busybox/coreutils/date.c
@@ -138,6 +138,7 @@
//usage: "Wed Apr 12 18:52:41 MDT 2000\n"
#include "libbb.h"
+#include "common_bufsiz.h"
#if ENABLE_FEATURE_DATE_NANO
# include <sys/syscall.h>
#endif
@@ -368,16 +369,17 @@ int date_main(int argc UNUSED_PARAM, char **argv)
#endif
#define date_buf bb_common_bufsiz1
+ setup_common_bufsiz();
if (*fmt_dt2str == '\0') {
/* With no format string, just print a blank line */
date_buf[0] = '\0';
} else {
/* Handle special conversions */
- if (strncmp(fmt_dt2str, "%f", 2) == 0) {
+ if (is_prefixed_with(fmt_dt2str, "%f")) {
fmt_dt2str = (char*)"%Y.%m.%d-%H:%M:%S";
}
/* Generate output string */
- strftime(date_buf, sizeof(date_buf), fmt_dt2str, &tm_time);
+ strftime(date_buf, COMMON_BUFSIZE, fmt_dt2str, &tm_time);
}
puts(date_buf);
diff --git a/release/src/router/busybox/coreutils/dd.c b/release/src/router/busybox/coreutils/dd.c
index 96602ebdd5..4dc3029260 100644
--- a/release/src/router/busybox/coreutils/dd.c
+++ b/release/src/router/busybox/coreutils/dd.c
@@ -8,9 +8,54 @@
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//config:config DD
+//config: bool "dd"
+//config: default y
+//config: help
+//config: dd copies a file (from standard input to standard output,
+//config: by default) using specific input and output blocksizes,
+//config: while optionally performing conversions on it.
+//config:
+//config:config FEATURE_DD_SIGNAL_HANDLING
+//config: bool "Enable signal handling for status reporting"
+//config: default y
+//config: depends on DD
+//config: help
+//config: Sending a SIGUSR1 signal to a running `dd' process makes it
+//config: print to standard error the number of records read and written
+//config: so far, then to resume copying.
+//config:
+//config: $ dd if=/dev/zero of=/dev/null &
+//config: $ pid=$!; kill -USR1 $pid; sleep 1; kill $pid
+//config: 10899206+0 records in
+//config: 10899206+0 records out
+//config:
+//config:config FEATURE_DD_THIRD_STATUS_LINE
+//config: bool "Enable the third status line upon signal"
+//config: default y
+//config: depends on DD && FEATURE_DD_SIGNAL_HANDLING
+//config: help
+//config: Displays a coreutils-like third status line with transferred bytes,
+//config: elapsed time and speed.
+//config:
+//config:config FEATURE_DD_IBS_OBS
+//config: bool "Enable ibs, obs and conv options"
+//config: default y
+//config: depends on DD
+//config: help
+//config: Enables support for writing a certain number of bytes in and out,
+//config: at a time, and performing conversions on the data stream.
+//config:
+//config:config FEATURE_DD_STATUS
+//config: bool "Enable status display options"
+//config: default y
+//config: depends on DD
+//config: help
+//config: Enables support for status=noxfer/none option.
+
//usage:#define dd_trivial_usage
//usage: "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n"
-//usage: " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync]")
+//usage: " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync] [iflag=skip_bytes]")
//usage:#define dd_full_usage "\n\n"
//usage: "Copy a file with converting and formatting\n"
//usage: "\n if=FILE Read from FILE instead of stdin"
@@ -30,10 +75,15 @@
//usage: "\n conv=noerror Continue after read errors"
//usage: "\n conv=sync Pad blocks with zeros"
//usage: "\n conv=fsync Physically write data out before finishing"
+//usage: "\n conv=swab Swap every pair of bytes"
+//usage: "\n iflag=skip_bytes skip=N is in bytes"
+//usage: )
+//usage: IF_FEATURE_DD_STATUS(
+//usage: "\n status=noxfer Suppress rate output"
+//usage: "\n status=none Suppress all output"
//usage: )
//usage: "\n"
-//usage: "\nNumbers may be suffixed by c (x1), w (x2), b (x512), kD (x1000), k (x1024),"
-//usage: "\nMD (x1000000), M (x1048576), GD (x1000000000) or G (x1073741824)"
+//usage: "\nN may be suffixed by c (1), w (2), b (512), kB (1000), k (1024), MB, M, GB, G"
//usage:
//usage:#define dd_example_usage
//usage: "$ dd if=/dev/zero of=/dev/ram1 bs=1M count=4\n"
@@ -41,6 +91,7 @@
//usage: "4+0 records out\n"
#include "libbb.h"
+#include "common_bufsiz.h"
/* This is a NOEXEC applet. Be very careful! */
@@ -50,33 +101,40 @@ enum {
ofd = STDOUT_FILENO,
};
-static const struct suffix_mult dd_suffixes[] = {
- { "c", 1 },
- { "w", 2 },
- { "b", 512 },
- { "kD", 1000 },
- { "k", 1024 },
- { "K", 1024 }, /* compat with coreutils dd */
- { "MD", 1000000 },
- { "M", 1048576 },
- { "GD", 1000000000 },
- { "G", 1073741824 },
- { "", 0 }
-};
-
struct globals {
off_t out_full, out_part, in_full, in_part;
#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE
unsigned long long total_bytes;
unsigned long long begin_time_us;
#endif
+ int flags;
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define INIT_G() do { \
+ setup_common_bufsiz(); \
/* we have to zero it out because of NOEXEC */ \
memset(&G, 0, sizeof(G)); \
} while (0)
+enum {
+ /* Must be in the same order as OP_conv_XXX! */
+ /* (see "flags |= (1 << what)" below) */
+ FLAG_NOTRUNC = (1 << 0) * ENABLE_FEATURE_DD_IBS_OBS,
+ FLAG_SYNC = (1 << 1) * ENABLE_FEATURE_DD_IBS_OBS,
+ FLAG_NOERROR = (1 << 2) * ENABLE_FEATURE_DD_IBS_OBS,
+ FLAG_FSYNC = (1 << 3) * ENABLE_FEATURE_DD_IBS_OBS,
+ FLAG_SWAB = (1 << 4) * ENABLE_FEATURE_DD_IBS_OBS,
+ /* end of conv flags */
+ /* start of input flags */
+ FLAG_IFLAG_SHIFT = 5,
+ FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS,
+ /* end of input flags */
+ FLAG_TWOBUFS = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS,
+ FLAG_COUNT = 1 << 7,
+ FLAG_STATUS = 1 << 8,
+ FLAG_STATUS_NONE = 1 << 9,
+ FLAG_STATUS_NOXFER = 1 << 10,
+};
static void dd_output_status(int UNUSED_PARAM cur_signal)
{
@@ -93,6 +151,13 @@ static void dd_output_status(int UNUSED_PARAM cur_signal)
G.out_full, G.out_part);
#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE
+# if ENABLE_FEATURE_DD_STATUS
+ if (G.flags & FLAG_STATUS_NOXFER) /* status=noxfer active? */
+ return;
+ //TODO: should status=none make dd stop reacting to USR1 entirely?
+ //So far we react to it (we print the stats),
+ //status=none only suppresses final, non-USR1 generated status message.
+# endif
fprintf(stderr, "%llu bytes (%sB) copied, ",
G.total_bytes,
/* show fractional digit, use suffixes */
@@ -145,29 +210,51 @@ static bool write_and_stats(const void *buf, size_t len, size_t obs,
# define XATOU_SFX xatoul_sfx
#endif
+#if ENABLE_FEATURE_DD_IBS_OBS
+static int parse_comma_flags(char *val, const char *words, const char *error_in)
+{
+ int flags = 0;
+ while (1) {
+ int n;
+ char *arg;
+ /* find ',', replace them with NUL so we can use val for
+ * index_in_strings() without copying.
+ * We rely on val being non-null, else strchr would fault.
+ */
+ arg = strchr(val, ',');
+ if (arg)
+ *arg = '\0';
+ n = index_in_strings(words, val);
+ if (n < 0)
+ bb_error_msg_and_die(bb_msg_invalid_arg_to, val, error_in);
+ flags |= (1 << n);
+ if (!arg) /* no ',' left, so this was the last specifier */
+ break;
+ *arg = ','; /* to preserve ps listing */
+ val = arg + 1; /* skip this keyword and ',' */
+ }
+ return flags;
+}
+#endif
+
int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int dd_main(int argc UNUSED_PARAM, char **argv)
{
- enum {
- /* Must be in the same order as OP_conv_XXX! */
- /* (see "flags |= (1 << what)" below) */
- FLAG_NOTRUNC = 1 << 0,
- FLAG_SYNC = 1 << 1,
- FLAG_NOERROR = 1 << 2,
- FLAG_FSYNC = 1 << 3,
- /* end of conv flags */
- FLAG_TWOBUFS = 1 << 4,
- FLAG_COUNT = 1 << 5,
- };
static const char keywords[] ALIGN1 =
- "bs\0""count\0""seek\0""skip\0""if\0""of\0"
+ "bs\0""count\0""seek\0""skip\0""if\0""of\0"IF_FEATURE_DD_STATUS("status\0")
#if ENABLE_FEATURE_DD_IBS_OBS
- "ibs\0""obs\0""conv\0"
+ "ibs\0""obs\0""conv\0""iflag\0"
#endif
;
#if ENABLE_FEATURE_DD_IBS_OBS
static const char conv_words[] ALIGN1 =
- "notrunc\0""sync\0""noerror\0""fsync\0";
+ "notrunc\0""sync\0""noerror\0""fsync\0""swab\0";
+ static const char iflag_words[] ALIGN1 =
+ "skip_bytes\0";
+#endif
+#if ENABLE_FEATURE_DD_STATUS
+ static const char status_words[] ALIGN1 =
+ "none\0""noxfer\0";
#endif
enum {
OP_bs = 0,
@@ -176,20 +263,22 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
OP_skip,
OP_if,
OP_of,
+ IF_FEATURE_DD_STATUS(OP_status,)
#if ENABLE_FEATURE_DD_IBS_OBS
OP_ibs,
OP_obs,
OP_conv,
+ OP_iflag,
/* Must be in the same order as FLAG_XXX! */
OP_conv_notrunc = 0,
OP_conv_sync,
OP_conv_noerror,
OP_conv_fsync,
+ OP_conv_swab,
/* Unimplemented conv=XXX: */
//nocreat do not create the output file
//excl fail if the output file already exists
//fdatasync physically write output file data before finishing
- //swab swap every pair of input bytes
//lcase change upper case to lower case
//ucase change lower case to upper case
//block pad newline-terminated records with spaces to cbs-size
@@ -197,22 +286,32 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
//ascii from EBCDIC to ASCII
//ebcdic from ASCII to EBCDIC
//ibm from ASCII to alternate EBCDIC
+ /* Partially implemented: */
+ //swab swap every pair of input bytes: will abort on non-even reads
+ OP_iflag_skip_bytes,
#endif
};
- int exitcode = EXIT_FAILURE;
- size_t ibs = 512, obs = 512;
- ssize_t n, w;
- char *ibuf, *obuf;
- /* And these are all zeroed at once! */
+ smallint exitcode = EXIT_FAILURE;
+ int i;
+ size_t ibs = 512;
+ char *ibuf;
+#if ENABLE_FEATURE_DD_IBS_OBS
+ size_t obs = 512;
+ char *obuf;
+#else
+# define obs ibs
+# define obuf ibuf
+#endif
+ /* These are all zeroed at once! */
struct {
- int flags;
size_t oc;
+ ssize_t prev_read_size; /* for detecting swab failure */
off_t count;
off_t seek, skip;
const char *infile, *outfile;
} Z;
-#define flags (Z.flags )
#define oc (Z.oc )
+#define prev_read_size (Z.prev_read_size)
#define count (Z.count )
#define seek (Z.seek )
#define skip (Z.skip )
@@ -223,10 +322,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
INIT_G();
//fflush_all(); - is this needed because of NOEXEC?
- for (n = 1; argv[n]; n++) {
+ for (i = 1; argv[i]; i++) {
int what;
char *val;
- char *arg = argv[n];
+ char *arg = argv[i];
#if ENABLE_DESKTOP
/* "dd --". NB: coreutils 6.9 will complain if they see
@@ -246,50 +345,39 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
#if ENABLE_FEATURE_DD_IBS_OBS
if (what == OP_ibs) {
/* Must fit into positive ssize_t */
- ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes);
+ ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, cwbkMG_suffixes);
/*continue;*/
}
if (what == OP_obs) {
- obs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes);
+ obs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, cwbkMG_suffixes);
/*continue;*/
}
if (what == OP_conv) {
- while (1) {
- /* find ',', replace them with NUL so we can use val for
- * index_in_strings() without copying.
- * We rely on val being non-null, else strchr would fault.
- */
- arg = strchr(val, ',');
- if (arg)
- *arg = '\0';
- what = index_in_strings(conv_words, val);
- if (what < 0)
- bb_error_msg_and_die(bb_msg_invalid_arg, val, "conv");
- flags |= (1 << what);
- if (!arg) /* no ',' left, so this was the last specifier */
- break;
- /* *arg = ','; - to preserve ps listing? */
- val = arg + 1; /* skip this keyword and ',' */
- }
- continue; /* we trashed 'what', can't fall through */
+ G.flags |= parse_comma_flags(val, conv_words, "conv");
+ /*continue;*/
+ }
+ if (what == OP_iflag) {
+ G.flags |= parse_comma_flags(val, iflag_words, "iflag") << FLAG_IFLAG_SHIFT;
+ /*continue;*/
}
#endif
if (what == OP_bs) {
- ibs = obs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes);
+ ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, cwbkMG_suffixes);
+ obs = ibs;
/*continue;*/
}
/* These can be large: */
if (what == OP_count) {
- flags |= FLAG_COUNT;
- count = XATOU_SFX(val, dd_suffixes);
+ G.flags |= FLAG_COUNT;
+ count = XATOU_SFX(val, cwbkMG_suffixes);
/*continue;*/
}
if (what == OP_seek) {
- seek = XATOU_SFX(val, dd_suffixes);
+ seek = XATOU_SFX(val, cwbkMG_suffixes);
/*continue;*/
}
if (what == OP_skip) {
- skip = XATOU_SFX(val, dd_suffixes);
+ skip = XATOU_SFX(val, cwbkMG_suffixes);
/*continue;*/
}
if (what == OP_if) {
@@ -300,14 +388,27 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
outfile = val;
/*continue;*/
}
- } /* end of "for (argv[n])" */
+#if ENABLE_FEATURE_DD_STATUS
+ if (what == OP_status) {
+ int n;
+ n = index_in_strings(status_words, val);
+ if (n < 0)
+ bb_error_msg_and_die(bb_msg_invalid_arg_to, val, "status");
+ G.flags |= FLAG_STATUS << n;
+ /*continue;*/
+ }
+#endif
+ } /* end of "for (argv[i])" */
//XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever
- ibuf = obuf = xmalloc(ibs);
+ ibuf = xmalloc(ibs);
+ obuf = ibuf;
+#if ENABLE_FEATURE_DD_IBS_OBS
if (ibs != obs) {
- flags |= FLAG_TWOBUFS;
+ G.flags |= FLAG_TWOBUFS;
obuf = xmalloc(obs);
}
+#endif
#if ENABLE_FEATURE_DD_SIGNAL_HANDLING
signal_SA_RESTART_empty_mask(SIGUSR1, dd_output_status);
@@ -316,20 +417,20 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
G.begin_time_us = monotonic_us();
#endif
- if (infile != NULL)
+ if (infile) {
xmove_fd(xopen(infile, O_RDONLY), ifd);
- else {
+ } else {
infile = bb_msg_standard_input;
}
- if (outfile != NULL) {
+ if (outfile) {
int oflag = O_WRONLY | O_CREAT;
- if (!seek && !(flags & FLAG_NOTRUNC))
+ if (!seek && !(G.flags & FLAG_NOTRUNC))
oflag |= O_TRUNC;
xmove_fd(xopen(outfile, oflag), ofd);
- if (seek && !(flags & FLAG_NOTRUNC)) {
+ if (seek && !(G.flags & FLAG_NOTRUNC)) {
if (ftruncate(ofd, seek * obs) < 0) {
struct stat st;
@@ -345,14 +446,15 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
outfile = bb_msg_standard_output;
}
if (skip) {
- if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) {
- while (skip-- > 0) {
- n = safe_read(ifd, ibuf, ibs);
+ size_t blocksz = (G.flags & FLAG_SKIP_BYTES) ? 1 : ibs;
+ if (lseek(ifd, skip * blocksz, SEEK_CUR) < 0) {
+ do {
+ ssize_t n = safe_read(ifd, ibuf, blocksz);
if (n < 0)
goto die_infile;
if (n == 0)
break;
- }
+ } while (--skip != 0);
}
}
if (seek) {
@@ -360,13 +462,15 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
goto die_outfile;
}
- while (!(flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) {
+ while (!(G.flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) {
+ ssize_t n;
+
n = safe_read(ifd, ibuf, ibs);
if (n == 0)
break;
if (n < 0) {
/* "Bad block" */
- if (!(flags & FLAG_NOERROR))
+ if (!(G.flags & FLAG_NOERROR))
goto die_infile;
bb_simple_perror_msg(infile);
/* GNU dd with conv=noerror skips over bad blocks */
@@ -375,16 +479,37 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
* conv=noerror just ignores input bad blocks */
n = 0;
}
+ if (G.flags & FLAG_SWAB) {
+ uint16_t *p16;
+ ssize_t n2;
+
+ /* Our code allows only last read to be odd-sized */
+ if (prev_read_size & 1)
+ bb_error_msg_and_die("can't swab %lu byte buffer",
+ (unsigned long)prev_read_size);
+ prev_read_size = n;
+
+ /* If n is odd, last byte is not swapped:
+ * echo -n "qwe" | dd conv=swab
+ * prints "wqe".
+ */
+ p16 = (void*) ibuf;
+ n2 = (n >> 1);
+ while (--n2 >= 0) {
+ *p16 = bswap_16(*p16);
+ p16++;
+ }
+ }
if ((size_t)n == ibs)
G.in_full++;
else {
G.in_part++;
- if (flags & FLAG_SYNC) {
+ if (G.flags & FLAG_SYNC) {
memset(ibuf + n, 0, ibs - n);
n = ibs;
}
}
- if (flags & FLAG_TWOBUFS) {
+ if (G.flags & FLAG_TWOBUFS) {
char *tmp = ibuf;
while (n) {
size_t d = obs - oc;
@@ -401,19 +526,20 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
oc = 0;
}
}
- } else if (write_and_stats(ibuf, n, obs, outfile))
- goto out_status;
+ } else {
+ if (write_and_stats(ibuf, n, obs, outfile))
+ goto out_status;
+ }
- if (flags & FLAG_FSYNC) {
+ if (G.flags & FLAG_FSYNC) {
if (fsync(ofd) < 0)
goto die_outfile;
}
}
if (ENABLE_FEATURE_DD_IBS_OBS && oc) {
- w = full_write_or_warn(obuf, oc, outfile);
- if (w < 0) goto out_status;
- if (w > 0) G.out_part++;
+ if (write_and_stats(obuf, oc, obs, outfile))
+ goto out_status;
}
if (close(ifd) < 0) {
die_infile:
@@ -427,11 +553,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
exitcode = EXIT_SUCCESS;
out_status:
- dd_output_status(0);
+ if (!ENABLE_FEATURE_DD_STATUS || !(G.flags & FLAG_STATUS_NONE))
+ dd_output_status(0);
if (ENABLE_FEATURE_CLEAN_UP) {
free(obuf);
- if (flags & FLAG_TWOBUFS)
+ if (G.flags & FLAG_TWOBUFS)
free(ibuf);
}
diff --git a/release/src/router/busybox/coreutils/df.c b/release/src/router/busybox/coreutils/df.c
index 25dbd3eec1..d79c11a6c0 100644
--- a/release/src/router/busybox/coreutils/df.c
+++ b/release/src/router/busybox/coreutils/df.c
@@ -25,6 +25,7 @@
//usage:#define df_trivial_usage
//usage: "[-Pk"
//usage: IF_FEATURE_HUMAN_READABLE("mh")
+//usage: "T"
//usage: IF_FEATURE_DF_FANCY("ai] [-B SIZE")
//usage: "] [FILESYSTEM]..."
//usage:#define df_full_usage "\n\n"
@@ -35,6 +36,7 @@
//usage: "\n -m 1M-byte blocks"
//usage: "\n -h Human readable (e.g. 1K 243M 2G)"
//usage: )
+//usage: "\n -T Print filesystem type"
//usage: IF_FEATURE_DF_FANCY(
//usage: "\n -a Show all filesystems"
//usage: "\n -i Inodes"
@@ -83,11 +85,12 @@ int df_main(int argc UNUSED_PARAM, char **argv)
enum {
OPT_KILO = (1 << 0),
OPT_POSIX = (1 << 1),
- OPT_ALL = (1 << 2) * ENABLE_FEATURE_DF_FANCY,
- OPT_INODE = (1 << 3) * ENABLE_FEATURE_DF_FANCY,
- OPT_BSIZE = (1 << 4) * ENABLE_FEATURE_DF_FANCY,
- OPT_HUMAN = (1 << (2 + 3*ENABLE_FEATURE_DF_FANCY)) * ENABLE_FEATURE_HUMAN_READABLE,
- OPT_MEGA = (1 << (3 + 3*ENABLE_FEATURE_DF_FANCY)) * ENABLE_FEATURE_HUMAN_READABLE,
+ OPT_FSTYPE = (1 << 2),
+ OPT_ALL = (1 << 3) * ENABLE_FEATURE_DF_FANCY,
+ OPT_INODE = (1 << 4) * ENABLE_FEATURE_DF_FANCY,
+ OPT_BSIZE = (1 << 5) * ENABLE_FEATURE_DF_FANCY,
+ OPT_HUMAN = (1 << (3 + 3*ENABLE_FEATURE_DF_FANCY)) * ENABLE_FEATURE_HUMAN_READABLE,
+ OPT_MEGA = (1 << (4 + 3*ENABLE_FEATURE_DF_FANCY)) * ENABLE_FEATURE_HUMAN_READABLE,
};
const char *disp_units_hdr = NULL;
char *chp;
@@ -99,7 +102,7 @@ int df_main(int argc UNUSED_PARAM, char **argv)
#elif ENABLE_FEATURE_HUMAN_READABLE
opt_complementary = "k-m:m-k";
#endif
- opt = getopt32(argv, "kP"
+ opt = getopt32(argv, "kPT"
IF_FEATURE_DF_FANCY("aiB:")
IF_FEATURE_HUMAN_READABLE("hm")
IF_FEATURE_DF_FANCY(, &chp));
@@ -110,9 +113,9 @@ int df_main(int argc UNUSED_PARAM, char **argv)
df_disp_hr = xatoul_range(chp, 1, ULONG_MAX); /* disallow 0 */
/* From the manpage of df from coreutils-6.10:
- Disk space is shown in 1K blocks by default, unless the environment
- variable POSIXLY_CORRECT is set, in which case 512-byte blocks are used.
- */
+ * Disk space is shown in 1K blocks by default, unless the environment
+ * variable POSIXLY_CORRECT is set, in which case 512-byte blocks are used.
+ */
if (getenv("POSIXLY_CORRECT")) /* TODO - a new libbb function? */
df_disp_hr = 512;
@@ -134,8 +137,11 @@ int df_main(int argc UNUSED_PARAM, char **argv)
disp_units_hdr = xasprintf("%lu-blocks", df_disp_hr);
#endif
}
- printf("Filesystem %-15sUsed Available %s Mounted on\n",
- disp_units_hdr, (opt & OPT_POSIX) ? "Capacity" : "Use%");
+
+ printf("Filesystem %s%-15sUsed Available %s Mounted on\n",
+ (opt & OPT_FSTYPE) ? "Type " : "",
+ disp_units_hdr,
+ (opt & OPT_POSIX) ? "Capacity" : "Use%");
mount_table = NULL;
argv += optind;
@@ -148,6 +154,7 @@ int df_main(int argc UNUSED_PARAM, char **argv)
while (1) {
const char *device;
const char *mount_point;
+ const char *fs_type;
if (mount_table) {
mount_entry = getmntent(mount_table);
@@ -170,8 +177,7 @@ int df_main(int argc UNUSED_PARAM, char **argv)
device = mount_entry->mnt_fsname;
mount_point = mount_entry->mnt_dir;
- if (strcmp(mount_point, "proc") == 0 || strcmp(mount_point, "ramfs") == 0)
- continue;
+ fs_type = mount_entry->mnt_type;
if (statfs(mount_point, &s) != 0) {
bb_simple_perror_msg(mount_point);
@@ -220,10 +226,22 @@ int df_main(int argc UNUSED_PARAM, char **argv)
printf("%s%*s", uni_dev, 20 - (int)uni_stat.unicode_width, "");
}
free(uni_dev);
+ if (opt & OPT_FSTYPE) {
+ char *uni_type = unicode_conv_to_printable(&uni_stat, fs_type);
+ if (uni_stat.unicode_width > 10 && !(opt & OPT_POSIX))
+ printf(" %s\n%31s", uni_type, "");
+ else
+ printf(" %s%*s", uni_type, 10 - (int)uni_stat.unicode_width, "");
+ free(uni_type);
+ }
}
#else
if (printf("\n%-20s" + 1, device) > 20 && !(opt & OPT_POSIX))
- printf("\n%-20s", "");
+ printf("\n%-20s", "");
+ if (opt & OPT_FSTYPE) {
+ if (printf(" %-10s", fs_type) > 11 && !(opt & OPT_POSIX))
+ printf("\n%-30s", "");
+ }
#endif
#if ENABLE_FEATURE_HUMAN_READABLE
diff --git a/release/src/router/busybox/coreutils/dos2unix.c b/release/src/router/busybox/coreutils/dos2unix.c
index 07398bdfa7..ccb74a1132 100644
--- a/release/src/router/busybox/coreutils/dos2unix.c
+++ b/release/src/router/busybox/coreutils/dos2unix.c
@@ -41,7 +41,7 @@ enum {
static void convert(char *fn, int conv_type)
{
FILE *in, *out;
- int i;
+ int ch;
char *temp_fn = temp_fn; /* for compiler */
char *resolved_fn = resolved_fn;
@@ -49,28 +49,30 @@ static void convert(char *fn, int conv_type)
out = stdout;
if (fn != NULL) {
struct stat st;
+ int fd;
resolved_fn = xmalloc_follow_symlinks(fn);
if (resolved_fn == NULL)
bb_simple_perror_msg_and_die(fn);
in = xfopen_for_read(resolved_fn);
- fstat(fileno(in), &st);
+ xfstat(fileno(in), &st, resolved_fn);
temp_fn = xasprintf("%sXXXXXX", resolved_fn);
- i = xmkstemp(temp_fn);
- if (fchmod(i, st.st_mode) == -1)
+ fd = xmkstemp(temp_fn);
+ if (fchmod(fd, st.st_mode) == -1)
bb_simple_perror_msg_and_die(temp_fn);
+ fchown(fd, st.st_uid, st.st_gid);
- out = xfdopen_for_write(i);
+ out = xfdopen_for_write(fd);
}
- while ((i = fgetc(in)) != EOF) {
- if (i == '\r')
+ while ((ch = fgetc(in)) != EOF) {
+ if (ch == '\r')
continue;
- if (i == '\n')
+ if (ch == '\n')
if (conv_type == CT_UNIX2DOS)
fputc('\r', out);
- fputc(i, out);
+ fputc(ch, out);
}
if (fn != NULL) {
diff --git a/release/src/router/busybox/coreutils/du.c b/release/src/router/busybox/coreutils/du.c
index 19a0319f13..1240bcbbc3 100644
--- a/release/src/router/busybox/coreutils/du.c
+++ b/release/src/router/busybox/coreutils/du.c
@@ -58,6 +58,7 @@
//usage: "2417 .\n"
#include "libbb.h"
+#include "common_bufsiz.h"
enum {
OPT_a_files_too = (1 << 0),
@@ -75,7 +76,7 @@ enum {
struct globals {
#if ENABLE_FEATURE_HUMAN_READABLE
- unsigned long disp_hr;
+ unsigned long disp_unit;
#else
unsigned disp_k;
#endif
@@ -85,18 +86,31 @@ struct globals {
int du_depth;
dev_t dir_dev;
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
-#define INIT_G() do { } while (0)
+#define G (*(struct globals*)bb_common_bufsiz1)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
static void print(unsigned long long size, const char *filename)
{
/* TODO - May not want to defer error checking here. */
#if ENABLE_FEATURE_HUMAN_READABLE
+# if ENABLE_DESKTOP
+ /* ~30 bytes of code for extra comtat:
+ * coreutils' du rounds sizes up:
+ * for example, 1025k file is shown as "2" by du -m.
+ * We round to nearest if human-readable [too hard to fix],
+ * else (fixed scale such as -m), we round up. To that end,
+ * add yet another half of the unit before displaying:
+ */
+ if (G.disp_unit)
+ size += (G.disp_unit-1) / (unsigned)(512 * 2);
+# endif
printf("%s\t%s\n",
- /* size x 512 / G.disp_hr, show one fractional,
- * use suffixes if G.disp_hr == 0 */
- make_human_readable_str(size, 512, G.disp_hr),
+ /* size x 512 / G.disp_unit.
+ * If G.disp_unit == 0, show one fractional
+ * and use suffixes
+ */
+ make_human_readable_str(size, 512, G.disp_unit),
filename);
#else
if (G.disp_k) {
@@ -195,10 +209,10 @@ int du_main(int argc UNUSED_PARAM, char **argv)
INIT_G();
#if ENABLE_FEATURE_HUMAN_READABLE
- IF_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_hr = 1024;)
- IF_NOT_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_hr = 512;)
+ IF_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_unit = 1024;)
+ IF_NOT_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_unit = 512;)
if (getenv("POSIXLY_CORRECT")) /* TODO - a new libbb function? */
- G.disp_hr = 512;
+ G.disp_unit = 512;
#else
IF_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_k = 1;)
/* IF_NOT_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_k = 0;) - G is pre-zeroed */
@@ -216,13 +230,13 @@ int du_main(int argc UNUSED_PARAM, char **argv)
opt = getopt32(argv, "aHkLsx" "d:" "lc" "hm", &G.max_print_depth);
argv += optind;
if (opt & OPT_h_for_humans) {
- G.disp_hr = 0;
+ G.disp_unit = 0;
}
if (opt & OPT_m_mbytes) {
- G.disp_hr = 1024*1024;
+ G.disp_unit = 1024*1024;
}
if (opt & OPT_k_kbytes) {
- G.disp_hr = 1024;
+ G.disp_unit = 1024;
}
#else
opt_complementary = "H-L:L-H:s-d:d-s:d+";
diff --git a/release/src/router/busybox/coreutils/echo.c b/release/src/router/busybox/coreutils/echo.c
index 9663894ec8..1c41745598 100644
--- a/release/src/router/busybox/coreutils/echo.c
+++ b/release/src/router/busybox/coreutils/echo.c
@@ -72,7 +72,7 @@ int echo_main(int argc UNUSED_PARAM, char **argv)
unsigned buflen;
#if !ENABLE_FEATURE_FANCY_ECHO
enum {
- eflag = '\\',
+ eflag = 0, /* 0 -- disable escape sequences */
nflag = 1, /* 1 -- print '\n' */
};
diff --git a/release/src/router/busybox/coreutils/expand.c b/release/src/router/busybox/coreutils/expand.c
index 25bbffc66f..8d376ff4e5 100644
--- a/release/src/router/busybox/coreutils/expand.c
+++ b/release/src/router/busybox/coreutils/expand.c
@@ -78,11 +78,7 @@ static void expand(FILE *file, unsigned tab_size, unsigned opt)
unsigned len;
*ptr = '\0';
# if ENABLE_UNICODE_SUPPORT
- {
- uni_stat_t uni_stat;
- printable_string(&uni_stat, ptr_strbeg);
- len = uni_stat.unicode_width;
- }
+ len = unicode_strwidth(ptr_strbeg);
# else
len = ptr - ptr_strbeg;
# endif
@@ -138,12 +134,9 @@ static void unexpand(FILE *file, unsigned tab_size, unsigned opt)
printf("%*s%.*s", len, "", n, ptr);
# if ENABLE_UNICODE_SUPPORT
{
- char c;
- uni_stat_t uni_stat;
- c = ptr[n];
+ char c = ptr[n];
ptr[n] = '\0';
- printable_string(&uni_stat, ptr);
- len = uni_stat.unicode_width;
+ len = unicode_strwidth(ptr);
ptr[n] = c;
}
# else
diff --git a/release/src/router/busybox/coreutils/expr.c b/release/src/router/busybox/coreutils/expr.c
index c986f93274..ce6b2d1891 100644
--- a/release/src/router/busybox/coreutils/expr.c
+++ b/release/src/router/busybox/coreutils/expr.c
@@ -61,6 +61,7 @@
//usage: "of characters matched or 0."
#include "libbb.h"
+#include "common_bufsiz.h"
#include "xregex.h"
#if ENABLE_EXPR_MATH_SUPPORT_64
@@ -99,8 +100,8 @@ typedef struct valinfo VALUE;
struct globals {
char **args;
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
-#define INIT_G() do { } while (0)
+#define G (*(struct globals*)bb_common_bufsiz1)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
/* forward declarations */
static VALUE *eval(void);
diff --git a/release/src/router/busybox/coreutils/false.c b/release/src/router/busybox/coreutils/false.c
index 59c2f321ae..0591a6cdcd 100644
--- a/release/src/router/busybox/coreutils/false.c
+++ b/release/src/router/busybox/coreutils/false.c
@@ -10,11 +10,9 @@
/* BB_AUDIT SUSv3 compliant */
/* http://www.opengroup.org/onlinepubs/000095399/utilities/false.html */
-//usage:#define false_trivial_usage
-//usage: ""
-//usage:#define false_full_usage "\n\n"
-//usage: "Return an exit code of FALSE (1)"
-//usage:
+/* "false --help" is special-cased to ignore --help */
+//usage:#define false_trivial_usage NOUSAGE_STR
+//usage:#define false_full_usage ""
//usage:#define false_example_usage
//usage: "$ false\n"
//usage: "$ echo $?\n"
diff --git a/release/src/router/busybox/coreutils/head.c b/release/src/router/busybox/coreutils/head.c
index ec4512765a..9388b026af 100644
--- a/release/src/router/busybox/coreutils/head.c
+++ b/release/src/router/busybox/coreutils/head.c
@@ -11,6 +11,8 @@
/* BB_AUDIT GNU compatible -c, -q, and -v options in 'fancy' configuration. */
/* http://www.opengroup.org/onlinepubs/007904975/utilities/head.html */
+//kbuild:lib-$(CONFIG_HEAD) += head.o
+
//usage:#define head_trivial_usage
//usage: "[OPTIONS] [FILE]..."
//usage:#define head_full_usage "\n\n"
@@ -18,7 +20,8 @@
//usage: "With more than one FILE, precede each with a filename header.\n"
//usage: "\n -n N[kbm] Print first N lines"
//usage: IF_FEATURE_FANCY_HEAD(
-//usage: "\n -c N[kbm] Print first N bytes"
+//usage: "\n -n -N[kbm] Print all except N last lines"
+//usage: "\n -c [-]N[kbm] Print first N bytes"
//usage: "\n -q Never print headers"
//usage: "\n -v Always print headers"
//usage: )
@@ -34,6 +37,110 @@
/* This is a NOEXEC applet. Be very careful! */
+#if !ENABLE_FEATURE_FANCY_HEAD
+# define print_first_N(fp,count,bytes) print_first_N(fp,count)
+#endif
+static void
+print_first_N(FILE *fp, unsigned long count, bool count_bytes)
+{
+#if !ENABLE_FEATURE_FANCY_HEAD
+ const int count_bytes = 0;
+#endif
+ while (count) {
+ int c = getc(fp);
+ if (c == EOF)
+ break;
+ if (count_bytes || (c == '\n'))
+ --count;
+ putchar(c);
+ }
+}
+
+#if ENABLE_FEATURE_FANCY_HEAD
+static void
+print_except_N_last_bytes(FILE *fp, unsigned count)
+{
+ unsigned char *circle = xmalloc(++count);
+ unsigned head = 0;
+ for(;;) {
+ int c;
+ c = getc(fp);
+ if (c == EOF)
+ goto ret;
+ circle[head++] = c;
+ if (head == count)
+ break;
+ }
+ for (;;) {
+ int c;
+ if (head == count)
+ head = 0;
+ putchar(circle[head]);
+ c = getc(fp);
+ if (c == EOF)
+ goto ret;
+ circle[head] = c;
+ head++;
+ }
+ ret:
+ free(circle);
+}
+
+static void
+print_except_N_last_lines(FILE *fp, unsigned count)
+{
+ char **circle = xzalloc((++count) * sizeof(circle[0]));
+ unsigned head = 0;
+ for(;;) {
+ char *c;
+ c = xmalloc_fgets(fp);
+ if (!c)
+ goto ret;
+ circle[head++] = c;
+ if (head == count)
+ break;
+ }
+ for (;;) {
+ char *c;
+ if (head == count)
+ head = 0;
+ fputs(circle[head], stdout);
+ c = xmalloc_fgets(fp);
+ if (!c)
+ goto ret;
+ free(circle[head]);
+ circle[head++] = c;
+ }
+ ret:
+ head = 0;
+ for(;;) {
+ free(circle[head++]);
+ if (head == count)
+ break;
+ }
+ free(circle);
+}
+#else
+/* Must never be called */
+void print_except_N_last_bytes(FILE *fp, unsigned count);
+void print_except_N_last_lines(FILE *fp, unsigned count);
+#endif
+
+#if !ENABLE_FEATURE_FANCY_HEAD
+# define eat_num(negative_N,p) eat_num(p)
+#endif
+static unsigned long
+eat_num(bool *negative_N, const char *p)
+{
+#if ENABLE_FEATURE_FANCY_HEAD
+ if (*p == '-') {
+ *negative_N = 1;
+ p++;
+ }
+#endif
+ return xatoul_sfx(p, bkm_suffixes);
+}
+
static const char head_opts[] ALIGN1 =
"n:"
#if ENABLE_FEATURE_FANCY_HEAD
@@ -41,29 +148,25 @@ static const char head_opts[] ALIGN1 =
#endif
;
-static const struct suffix_mult head_suffixes[] = {
- { "b", 512 },
- { "k", 1024 },
- { "m", 1024*1024 },
- { "", 0 }
-};
-
#define header_fmt_str "\n==> %s <==\n"
int head_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int head_main(int argc, char **argv)
{
unsigned long count = 10;
- unsigned long i;
#if ENABLE_FEATURE_FANCY_HEAD
- int count_bytes = 0;
int header_threshhold = 1;
+ bool count_bytes = 0;
+ bool negative_N = 0;
+#else
+# define header_threshhold 1
+# define count_bytes 0
+# define negative_N 0
#endif
FILE *fp;
const char *fmt;
char *p;
int opt;
- int c;
int retval = EXIT_SUCCESS;
#if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_HEAD
@@ -73,7 +176,7 @@ int head_main(int argc, char **argv)
) {
--argc;
++argv;
- p = (*argv) + 1;
+ p = argv[0] + 1;
goto GET_COUNT;
}
#endif
@@ -97,7 +200,7 @@ int head_main(int argc, char **argv)
#if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_HEAD
GET_COUNT:
#endif
- count = xatoul_sfx(p, head_suffixes);
+ count = eat_num(&negative_N, p);
break;
default:
bb_show_usage();
@@ -110,19 +213,17 @@ int head_main(int argc, char **argv)
*--argv = (char*)"-";
fmt = header_fmt_str + 1;
-#if ENABLE_FEATURE_FANCY_HEAD
if (argc <= header_threshhold) {
+#if ENABLE_FEATURE_FANCY_HEAD
header_threshhold = 0;
- }
#else
- if (argc <= 1) {
fmt += 11; /* "" */
- }
- /* Now define some things here to avoid #ifdefs in the code below.
- * These should optimize out of the if conditions below. */
-#define header_threshhold 1
-#define count_bytes 0
#endif
+ }
+ if (negative_N) {
+ if (count >= INT_MAX / sizeof(char*))
+ bb_error_msg("count is too big: %lu", count);
+ }
do {
fp = fopen_or_warn_stdin(*argv);
@@ -133,18 +234,20 @@ int head_main(int argc, char **argv)
if (header_threshhold) {
printf(fmt, *argv);
}
- i = count;
- while (i && ((c = getc(fp)) != EOF)) {
- if (count_bytes || (c == '\n')) {
- --i;
+ if (negative_N) {
+ if (count_bytes) {
+ print_except_N_last_bytes(fp, count);
+ } else {
+ print_except_N_last_lines(fp, count);
}
- putchar(c);
+ } else {
+ print_first_N(fp, count, count_bytes);
}
+ die_if_ferror_stdout();
if (fclose_if_not_stdin(fp)) {
bb_simple_perror_msg(*argv);
retval = EXIT_FAILURE;
}
- die_if_ferror_stdout();
} else {
retval = EXIT_FAILURE;
}
diff --git a/release/src/router/busybox/coreutils/hostid.c b/release/src/router/busybox/coreutils/hostid.c
index 5c1a4e0861..e5b1f51883 100644
--- a/release/src/router/busybox/coreutils/hostid.c
+++ b/release/src/router/busybox/coreutils/hostid.c
@@ -36,7 +36,8 @@ int hostid_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
bb_show_usage();
}
- printf("%08lx\n", gethostid());
+ /* POSIX says gethostid returns a "32-bit identifier" */
+ printf("%08x\n", (unsigned)(uint32_t)gethostid());
return fflush_all();
}
diff --git a/release/src/router/busybox/coreutils/id.c b/release/src/router/busybox/coreutils/id.c
index 399d25e342..1f3e1c4c2f 100644
--- a/release/src/router/busybox/coreutils/id.c
+++ b/release/src/router/busybox/coreutils/id.c
@@ -64,12 +64,10 @@
/* This is a NOEXEC applet. Be very careful! */
#if !ENABLE_USE_BB_PWD_GRP
-#if defined(__UCLIBC_MAJOR__) && (__UCLIBC_MAJOR__ == 0)
-#if (__UCLIBC_MINOR__ < 9) || (__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ < 30)
+#if defined(__UCLIBC__) && UCLIBC_VERSION < KERNEL_VERSION(0, 9, 30)
#error "Sorry, you need at least uClibc version 0.9.30 for id applet to build"
#endif
#endif
-#endif
enum {
PRINT_REAL = (1 << 0),
@@ -174,7 +172,7 @@ int id_main(int argc UNUSED_PARAM, char **argv)
/* Don't allow -n -r -nr -ug -rug -nug -rnug -uZ -gZ -GZ*/
/* Don't allow more than one username */
opt_complementary = "?1:u--g:g--u:G--u:u--G:g--G:G--g:r?ugG:n?ugG"
- IF_SELINUX(":u--Z:Z--u:g--Z:Z--g:G--Z:Z--G");
+ IF_SELINUX(":u--Z:Z--u:g--Z:Z--g:G--Z:Z--G");
opt = getopt32(argv, "rnugG" IF_SELINUX("Z"));
}
diff --git a/release/src/router/busybox/coreutils/install.c b/release/src/router/busybox/coreutils/install.c
index 445497f9a8..8aa51cc342 100644
--- a/release/src/router/busybox/coreutils/install.c
+++ b/release/src/router/busybox/coreutils/install.c
@@ -8,7 +8,7 @@
/* -v, -b, -c are ignored */
//usage:#define install_trivial_usage
-//usage: "[-cdDsp] [-o USER] [-g GRP] [-m MODE] [SOURCE]... DEST"
+//usage: "[-cdDsp] [-o USER] [-g GRP] [-m MODE] [-t DIR] [SOURCE]... DEST"
//usage:#define install_full_usage "\n\n"
//usage: "Copy files and set attributes\n"
//usage: "\n -c Just copy (default)"
@@ -19,6 +19,7 @@
//usage: "\n -o USER Set ownership"
//usage: "\n -g GRP Set group ownership"
//usage: "\n -m MODE Set permissions"
+//usage: "\n -t DIR Install to DIR"
//usage: IF_SELINUX(
//usage: "\n -Z Set security context"
//usage: )
@@ -28,12 +29,16 @@
#if ENABLE_FEATURE_INSTALL_LONG_OPTIONS
static const char install_longopts[] ALIGN1 =
+ IF_FEATURE_VERBOSE(
+ "verbose\0" No_argument "v"
+ )
"directory\0" No_argument "d"
"preserve-timestamps\0" No_argument "p"
"strip\0" No_argument "s"
"group\0" Required_argument "g"
"mode\0" Required_argument "m"
"owner\0" Required_argument "o"
+ "target-directory\0" Required_argument "t"
/* autofs build insists of using -b --suffix=.orig */
/* TODO? (short option for --suffix is -S) */
#if ENABLE_SELINUX
@@ -89,11 +94,11 @@ int install_main(int argc, char **argv)
const char *gid_str;
const char *uid_str;
const char *mode_str;
+ int mkdir_flags = FILEUTILS_RECUR;
int copy_flags = FILEUTILS_DEREFERENCE | FILEUTILS_FORCE;
int opts;
- int min_args = 1;
int ret = EXIT_SUCCESS;
- int isdir = 0;
+ int isdir;
#if ENABLE_SELINUX
security_context_t scontext;
bool use_default_selinux_context = 1;
@@ -109,21 +114,22 @@ int install_main(int argc, char **argv)
OPT_GROUP = 1 << 7,
OPT_MODE = 1 << 8,
OPT_OWNER = 1 << 9,
+ OPT_TARGET = 1 << 10,
#if ENABLE_SELINUX
- OPT_SET_SECURITY_CONTEXT = 1 << 10,
- OPT_PRESERVE_SECURITY_CONTEXT = 1 << 11,
+ OPT_SET_SECURITY_CONTEXT = 1 << 11,
+ OPT_PRESERVE_SECURITY_CONTEXT = 1 << 12,
#endif
};
#if ENABLE_FEATURE_INSTALL_LONG_OPTIONS
applet_long_options = install_longopts;
#endif
- opt_complementary = "s--d:d--s" IF_FEATURE_INSTALL_LONG_OPTIONS(IF_SELINUX(":Z--\xff:\xff--Z"));
+ opt_complementary = "t--d:d--t:s--d:d--s" IF_FEATURE_INSTALL_LONG_OPTIONS(IF_SELINUX(":Z--\xff:\xff--Z"));
/* -c exists for backwards compatibility, it's needed */
- /* -v is ignored ("print name of each created directory") */
/* -b is ignored ("make a backup of each existing destination file") */
- opts = getopt32(argv, "cvb" "Ddpsg:m:o:" IF_SELINUX("Z:"),
- &gid_str, &mode_str, &uid_str IF_SELINUX(, &scontext));
+ opts = getopt32(argv, "cvb" "Ddpsg:m:o:t:" IF_SELINUX("Z:"),
+ &gid_str, &mode_str, &uid_str, &last
+ IF_SELINUX(, &scontext));
argc -= optind;
argv += optind;
@@ -141,6 +147,11 @@ int install_main(int argc, char **argv)
}
#endif
+ if ((opts & OPT_v) && FILEUTILS_VERBOSE) {
+ mkdir_flags |= FILEUTILS_VERBOSE;
+ copy_flags |= FILEUTILS_VERBOSE;
+ }
+
/* preserve access and modification time, this is GNU behaviour,
* BSD only preserves modification time */
if (opts & OPT_PRESERVE_TIME) {
@@ -148,37 +159,41 @@ int install_main(int argc, char **argv)
}
mode = 0755; /* GNU coreutils 6.10 compat */
if (opts & OPT_MODE)
- bb_parse_mode(mode_str, &mode);
+ mode = bb_parse_mode(mode_str, mode);
uid = (opts & OPT_OWNER) ? get_ug_id(uid_str, xuname2uid) : getuid();
gid = (opts & OPT_GROUP) ? get_ug_id(gid_str, xgroup2gid) : getgid();
- last = argv[argc - 1];
- if (!(opts & OPT_DIRECTORY)) {
- argv[argc - 1] = NULL;
- min_args++;
-
+ /* If -t DIR is in use, then isdir=true, last="DIR" */
+ isdir = (opts & OPT_TARGET);
+ if (!(opts & (OPT_TARGET|OPT_DIRECTORY))) {
+ /* Neither -t DIR nor -d is in use */
+ argc--;
+ last = argv[argc];
+ argv[argc] = NULL;
/* coreutils install resolves link in this case, don't use lstat */
isdir = stat(last, &statbuf) < 0 ? 0 : S_ISDIR(statbuf.st_mode);
}
- if (argc < min_args)
+ if (argc < 1)
bb_show_usage();
while ((arg = *argv++) != NULL) {
- char *dest = last;
+ char *dest;
+
if (opts & OPT_DIRECTORY) {
dest = arg;
/* GNU coreutils 6.9 does not set uid:gid
* on intermediate created directories
* (only on last one) */
- if (bb_make_directory(dest, 0755, FILEUTILS_RECUR)) {
+ if (bb_make_directory(dest, 0755, mkdir_flags)) {
ret = EXIT_FAILURE;
goto next;
}
} else {
+ dest = last;
if (opts & OPT_MKDIR_LEADING) {
char *ddir = xstrdup(dest);
- bb_make_directory(dirname(ddir), 0755, FILEUTILS_RECUR);
+ bb_make_directory(dirname(ddir), 0755, mkdir_flags);
/* errors are not checked. copy_file
* will fail if dir is not created. */
free(ddir);
diff --git a/release/src/router/busybox/coreutils/libcoreutils/getopt_mk_fifo_nod.c b/release/src/router/busybox/coreutils/libcoreutils/getopt_mk_fifo_nod.c
index 2227171494..47375ff915 100644
--- a/release/src/router/busybox/coreutils/libcoreutils/getopt_mk_fifo_nod.c
+++ b/release/src/router/busybox/coreutils/libcoreutils/getopt_mk_fifo_nod.c
@@ -33,7 +33,9 @@ mode_t FAST_FUNC getopt_mk_fifo_nod(char **argv)
int opt;
opt = getopt32(argv, "m:" IF_SELINUX("Z:"), &smode IF_SELINUX(,&scontext));
if (opt & 1) {
- if (bb_parse_mode(smode, &mode))
+ mode = bb_parse_mode(smode, mode);
+ if (mode != (mode_t)-1) /* if mode is valid */
+ /* make future mknod/mkfifo set mode bits exactly */
umask(0);
}
diff --git a/release/src/router/busybox/coreutils/ln.c b/release/src/router/busybox/coreutils/ln.c
index 0eb3e6579e..1688148017 100644
--- a/release/src/router/busybox/coreutils/ln.c
+++ b/release/src/router/busybox/coreutils/ln.c
@@ -20,6 +20,8 @@
//usage: "\n -n Don't dereference symlinks - treat like normal file"
//usage: "\n -b Make a backup of the target (if exists) before link operation"
//usage: "\n -S suf Use suffix instead of ~ when making backup files"
+//usage: "\n -T 2nd arg must be a DIR"
+//usage: "\n -v Verbose"
//usage:
//usage:#define ln_example_usage
//usage: "$ ln -s BusyBox /tmp/ls\n"
@@ -31,11 +33,13 @@
/* This is a NOEXEC applet. Be very careful! */
-#define LN_SYMLINK 1
-#define LN_FORCE 2
-#define LN_NODEREFERENCE 4
-#define LN_BACKUP 8
-#define LN_SUFFIX 16
+#define LN_SYMLINK (1 << 0)
+#define LN_FORCE (1 << 1)
+#define LN_NODEREFERENCE (1 << 2)
+#define LN_BACKUP (1 << 3)
+#define LN_SUFFIX (1 << 4)
+#define LN_VERBOSE (1 << 5)
+#define LN_LINKFILE (1 << 6)
int ln_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int ln_main(int argc, char **argv)
@@ -50,10 +54,15 @@ int ln_main(int argc, char **argv)
int (*link_func)(const char *, const char *);
opt_complementary = "-1"; /* min one arg */
- opts = getopt32(argv, "sfnbS:", &suffix);
+ opts = getopt32(argv, "sfnbS:vT", &suffix);
last = argv[argc - 1];
argv += optind;
+ argc -= optind;
+
+ if ((opts & LN_LINKFILE) && argc > 2) {
+ bb_error_msg_and_die("-T accepts 2 args max");
+ }
if (!argv[1]) {
/* "ln PATH/TO/FILE" -> "ln PATH/TO/FILE FILE" */
@@ -72,6 +81,9 @@ int ln_main(int argc, char **argv)
(opts & LN_NODEREFERENCE) ^ LN_NODEREFERENCE
)
) {
+ if (opts & LN_LINKFILE) {
+ bb_error_msg_and_die("'%s' is a directory", src);
+ }
src_name = xstrdup(*argv);
src = concat_path_file(src, bb_get_last_path_component_strip(src_name));
free(src_name);
@@ -112,13 +124,16 @@ int ln_main(int argc, char **argv)
link_func = symlink;
}
+ if (opts & LN_VERBOSE) {
+ printf("'%s' -> '%s'\n", src, *argv);
+ }
+
if (link_func(*argv, src) != 0) {
bb_simple_perror_msg(src);
status = EXIT_FAILURE;
}
free(src_name);
-
} while ((++argv)[1]);
return status;
diff --git a/release/src/router/busybox/coreutils/ls.c b/release/src/router/busybox/coreutils/ls.c
index d5b25ee70b..344b4e61e5 100644
--- a/release/src/router/busybox/coreutils/ls.c
+++ b/release/src/router/busybox/coreutils/ls.c
@@ -93,6 +93,7 @@
//usage: )
#include "libbb.h"
+#include "common_bufsiz.h"
#include "unicode.h"
@@ -260,7 +261,7 @@ enum {
/* TODO: simple toggles may be stored as OPT_xxx bits instead */
static const uint32_t opt_flags[] = {
- STYLE_COLUMNAR, /* C */
+ STYLE_COLUMNAR, /* C */
DISP_HIDDEN | DISP_DOT, /* a */
DISP_NOLIST, /* d */
LIST_INO, /* i */
@@ -365,8 +366,9 @@ struct globals {
time_t current_time_t;
#endif
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define INIT_G() do { \
+ setup_common_bufsiz(); \
/* we have to zero it out because of NOEXEC */ \
memset(&G, 0, sizeof(G)); \
IF_FEATURE_AUTOWIDTH(G_terminal_width = TERMINAL_WIDTH;) \
@@ -566,12 +568,12 @@ static NOINLINE unsigned display_single(const struct dnode *dn)
#if ENABLE_FEATURE_LS_TIMESTAMPS
if (G.all_fmt & (LIST_FULLTIME|LIST_DATE_TIME)) {
char *filetime;
- time_t ttime = dn->dn_mtime;
+ const time_t *ttime = &dn->dn_mtime;
if (G.all_fmt & TIME_ACCESS)
- ttime = dn->dn_atime;
+ ttime = &dn->dn_atime;
if (G.all_fmt & TIME_CHANGE)
- ttime = dn->dn_ctime;
- filetime = ctime(&ttime);
+ ttime = &dn->dn_ctime;
+ filetime = ctime(ttime);
/* filetime's format: "Wed Jun 30 21:49:08 1993\n" */
if (G.all_fmt & LIST_FULLTIME) { /* -e */
/* Note: coreutils 8.4 ls --full-time prints:
@@ -580,13 +582,16 @@ static NOINLINE unsigned display_single(const struct dnode *dn)
column += printf("%.24s ", filetime);
} else { /* LIST_DATE_TIME */
/* G.current_time_t ~== time(NULL) */
- time_t age = G.current_time_t - ttime;
- printf("%.6s ", filetime + 4); /* "Jun 30" */
+ time_t age = G.current_time_t - *ttime;
if (age < 3600L * 24 * 365 / 2 && age > -15 * 60) {
- /* hh:mm if less than 6 months old */
- printf("%.5s ", filetime + 11);
- } else { /* year. buggy if year > 9999 ;) */
- printf(" %.4s ", filetime + 20);
+ /* less than 6 months old */
+ /* "mmm dd hh:mm " */
+ printf("%.12s ", filetime + 4);
+ } else {
+ /* "mmm dd yyyy " */
+ /* "mmm dd yyyyy " after year 9999 :) */
+ strchr(filetime + 20, '\n')[0] = ' ';
+ printf("%.7s%6s", filetime + 4, filetime + 20);
}
column += 13;
}
@@ -665,7 +670,7 @@ static void display_files(struct dnode **dn, unsigned nfiles)
if (column_width < len)
column_width = len;
}
- column_width += 1 +
+ column_width += 2 +
IF_SELINUX( ((G.all_fmt & LIST_CONTEXT) ? 33 : 0) + )
((G.all_fmt & LIST_INO) ? 8 : 0) +
((G.all_fmt & LIST_BLOCKS) ? 5 : 0);
@@ -693,8 +698,8 @@ static void display_files(struct dnode **dn, unsigned nfiles)
if (i < nfiles) {
if (column > 0) {
nexttab -= column;
- printf("%*s ", nexttab, "");
- column += nexttab + 1;
+ printf("%*s", nexttab, "");
+ column += nexttab;
}
nexttab = column + column_width;
column += display_single(dn[i]);
@@ -720,7 +725,7 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f
if ((option_mask32 & OPT_L) || force_follow) {
#if ENABLE_SELINUX
if (is_selinux_enabled()) {
- getfilecon(fullname, &cur->sid);
+ getfilecon(fullname, &cur->sid);
}
#endif
if (stat(fullname, &statbuf)) {
@@ -1032,7 +1037,7 @@ static void scan_and_display_dirs_recur(struct dnode **dn, int first)
}
subdnp = scan_one_dir((*dn)->fullname, &nfiles);
#if ENABLE_DESKTOP
- if ((G.all_fmt & STYLE_MASK) == STYLE_LONG)
+ if ((G.all_fmt & STYLE_MASK) == STYLE_LONG || (G.all_fmt & LIST_BLOCKS))
printf("total %"OFF_FMT"u\n", calculate_blocks(subdnp));
#endif
if (nfiles > 0) {
@@ -1102,7 +1107,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
#if ENABLE_FEATURE_AUTOWIDTH
/* obtain the terminal width */
- get_terminal_width_height(STDIN_FILENO, &G_terminal_width, NULL);
+ G_terminal_width = get_terminal_width(STDIN_FILENO);
/* go one less... */
G_terminal_width--;
#endif
diff --git a/release/src/router/busybox/coreutils/md5_sha1_sum.c b/release/src/router/busybox/coreutils/md5_sha1_sum.c
index 2cb6dd43c1..1a5342e879 100644
--- a/release/src/router/busybox/coreutils/md5_sha1_sum.c
+++ b/release/src/router/busybox/coreutils/md5_sha1_sum.c
@@ -55,6 +55,16 @@
//usage: "\n -s Don't output anything, status code shows success"
//usage: "\n -w Warn about improperly formatted checksum lines"
//usage: )
+//usage:
+//usage:#define sha3sum_trivial_usage
+//usage: IF_FEATURE_MD5_SHA1_SUM_CHECK("[-c[sw]] ")"[FILE]..."
+//usage:#define sha3sum_full_usage "\n\n"
+//usage: "Print" IF_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " SHA3-512 checksums"
+//usage: IF_FEATURE_MD5_SHA1_SUM_CHECK( "\n"
+//usage: "\n -c Check sums against list in FILEs"
+//usage: "\n -s Don't output anything, status code shows success"
+//usage: "\n -w Warn about improperly formatted checksum lines"
+//usage: )
#include "libbb.h"
@@ -65,6 +75,7 @@ enum {
HASH_MD5 = 's', /* "md5>s<um" */
HASH_SHA1 = '1',
HASH_SHA256 = '2',
+ HASH_SHA3 = '3',
HASH_SHA512 = '5',
};
@@ -86,6 +97,7 @@ static uint8_t *hash_file(const char *filename)
{
int src_fd, hash_len, count;
union _ctx_ {
+ sha3_ctx_t sha3;
sha512_ctx_t sha512;
sha256_ctx_t sha256;
sha1_ctx_t sha1;
@@ -124,6 +136,11 @@ static uint8_t *hash_file(const char *filename)
update = (void*)sha512_hash;
final = (void*)sha512_end;
hash_len = 64;
+ } else if (ENABLE_SHA3SUM && hash_algo == HASH_SHA3) {
+ sha3_begin(&context.sha3);
+ update = (void*)sha3_hash;
+ final = (void*)sha3_end;
+ hash_len = 64;
} else {
xfunc_die(); /* can't reach this */
}
@@ -134,7 +151,9 @@ static uint8_t *hash_file(const char *filename)
update(&context, in_buf, count);
}
hash_value = NULL;
- if (count == 0) {
+ if (count < 0)
+ bb_perror_msg("can't read '%s'", filename);
+ else /* count == 0 */ {
final(&context, in_buf);
hash_value = hash_bin_to_hex(in_buf, hash_len);
}
@@ -223,7 +242,7 @@ int md5_sha1_sum_main(int argc UNUSED_PARAM, char **argv)
}
if (count_failed && !(flags & FLAG_SILENT)) {
bb_error_msg("WARNING: %d of %d computed checksums did NOT match",
- count_failed, count_total);
+ count_failed, count_total);
}
fclose_if_not_stdin(pre_computed_stream);
} else {
diff --git a/release/src/router/busybox/coreutils/mkdir.c b/release/src/router/busybox/coreutils/mkdir.c
index b33b6bba3b..6f7b004dd3 100644
--- a/release/src/router/busybox/coreutils/mkdir.c
+++ b/release/src/router/busybox/coreutils/mkdir.c
@@ -48,6 +48,9 @@ static const char mkdir_longopts[] ALIGN1 =
#if ENABLE_SELINUX
"context\0" Required_argument "Z"
#endif
+#if ENABLE_FEATURE_VERBOSE
+ "verbose\0" No_argument "v"
+#endif
;
#endif
@@ -66,18 +69,20 @@ int mkdir_main(int argc UNUSED_PARAM, char **argv)
#if ENABLE_FEATURE_MKDIR_LONG_OPTIONS
applet_long_options = mkdir_longopts;
#endif
- opt = getopt32(argv, "m:p" IF_SELINUX("Z:"), &smode IF_SELINUX(,&scontext));
+ opt = getopt32(argv, "m:pv" IF_SELINUX("Z:"), &smode IF_SELINUX(,&scontext));
if (opt & 1) {
- mode_t mmode = 0777;
- if (!bb_parse_mode(smode, &mmode)) {
+ mode_t mmode = bb_parse_mode(smode, 0777);
+ if (mmode == (mode_t)-1) {
bb_error_msg_and_die("invalid mode '%s'", smode);
}
mode = mmode;
}
if (opt & 2)
flags |= FILEUTILS_RECUR;
+ if ((opt & 4) && FILEUTILS_VERBOSE)
+ flags |= FILEUTILS_VERBOSE;
#if ENABLE_SELINUX
- if (opt & 4) {
+ if (opt & 8) {
selinux_or_die();
setfscreatecon_or_die(scontext);
}
diff --git a/release/src/router/busybox/coreutils/mknod.c b/release/src/router/busybox/coreutils/mknod.c
index 32d3659acc..aa04504819 100644
--- a/release/src/router/busybox/coreutils/mknod.c
+++ b/release/src/router/busybox/coreutils/mknod.c
@@ -59,7 +59,7 @@ int mknod_main(int argc, char **argv)
/* Autodetect what the system supports; these macros should
* optimize out to two constants. */
dev = makedev(xatoul_range(argv[2], 0, major(UINT_MAX)),
- xatoul_range(argv[3], 0, minor(UINT_MAX)));
+ xatoul_range(argv[3], 0, minor(UINT_MAX)));
}
}
diff --git a/release/src/router/busybox/coreutils/mv.c b/release/src/router/busybox/coreutils/mv.c
index 87f4cd5a54..50571755b5 100644
--- a/release/src/router/busybox/coreutils/mv.c
+++ b/release/src/router/busybox/coreutils/mv.c
@@ -33,12 +33,17 @@ static const char mv_longopts[] ALIGN1 =
"interactive\0" No_argument "i"
"force\0" No_argument "f"
"no-clobber\0" No_argument "n"
+ IF_FEATURE_VERBOSE(
+ "verbose\0" No_argument "v"
+ )
;
#endif
-#define OPT_FILEUTILS_FORCE 1
-#define OPT_FILEUTILS_INTERACTIVE 2
-#define OPT_FILEUTILS_NOCLOBBER 4
+#define OPT_FORCE (1 << 0)
+#define OPT_INTERACTIVE (1 << 1)
+#define OPT_NOCLOBBER (1 << 2)
+#define OPT_VERBOSE ((1 << 3) * ENABLE_FEATURE_VERBOSE)
+
int mv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int mv_main(int argc, char **argv)
@@ -56,9 +61,10 @@ int mv_main(int argc, char **argv)
#endif
/* Need at least two arguments.
* If more than one of -f, -i, -n is specified , only the final one
- * takes effect (it unsets previous options). */
+ * takes effect (it unsets previous options).
+ */
opt_complementary = "-2:f-in:i-fn:n-fi";
- flags = getopt32(argv, "fin");
+ flags = getopt32(argv, "finv");
argc -= optind;
argv += optind;
last = argv[argc - 1];
@@ -84,11 +90,11 @@ int mv_main(int argc, char **argv)
DO_MOVE:
if (dest_exists) {
- if (flags & OPT_FILEUTILS_NOCLOBBER)
+ if (flags & OPT_NOCLOBBER)
goto RET_0;
- if (!(flags & OPT_FILEUTILS_FORCE)
+ if (!(flags & OPT_FORCE)
&& ((access(dest, W_OK) < 0 && isatty(0))
- || (flags & OPT_FILEUTILS_INTERACTIVE))
+ || (flags & OPT_INTERACTIVE))
) {
if (fprintf(stderr, "mv: overwrite '%s'? ", dest) < 0) {
goto RET_1; /* Ouch! fprintf failed! */
@@ -145,6 +151,9 @@ int mv_main(int argc, char **argv)
status = 1;
}
RET_0:
+ if (flags & OPT_VERBOSE) {
+ printf("'%s' -> '%s'\n", *argv, dest);
+ }
if (dest != last) {
free((void *) dest);
}
diff --git a/release/src/router/busybox/coreutils/od_bloaty.c b/release/src/router/busybox/coreutils/od_bloaty.c
index 347f879d70..c8a6541654 100644
--- a/release/src/router/busybox/coreutils/od_bloaty.c
+++ b/release/src/router/busybox/coreutils/od_bloaty.c
@@ -20,12 +20,13 @@
/* #include "libbb.h" - done in od.c */
+#include "common_bufsiz.h"
#define assert(a) ((void)0)
//usage:#if ENABLE_DESKTOP
//usage:#define od_trivial_usage
-//usage: "[-abcdfhilovxs] [-t TYPE] [-A RADIX] [-N SIZE] [-j SKIP] [-S MINSTR] [-w WIDTH] [FILE...]"
+//usage: "[-abcdfhilovxs] [-t TYPE] [-A RADIX] [-N SIZE] [-j SKIP] [-S MINSTR] [-w WIDTH] [FILE]..."
// We don't support:
// ... [FILE] [[+]OFFSET[.][b]]
// Support is buggy for:
@@ -66,7 +67,7 @@ enum {
/* -S was -s and also had optional parameter */ \
/* but in coreutils 6.3 it was renamed and now has */ \
/* _mandatory_ parameter */ \
- &str_A, &str_N, &str_j, &lst_t, &str_S, &bytes_per_block)
+ &str_A, &str_N, &str_j, &lst_t, &str_S, &G.bytes_per_block)
/* Check for 0x7f is a coreutils 6.3 addition */
@@ -174,38 +175,53 @@ struct ERR_width_bytes_has_bad_size {
char ERR_width_bytes_has_bad_size[ARRAY_SIZE(width_bytes) == N_SIZE_SPECS ? 1 : -1];
};
-static smallint exit_code;
+struct globals {
+ smallint exit_code;
-static unsigned string_min;
+ unsigned string_min;
-/* An array of specs describing how to format each input block. */
-static size_t n_specs;
-static struct tspec *spec;
+ /* An array of specs describing how to format each input block. */
+ unsigned n_specs;
+ struct tspec *spec;
-/* Function that accepts an address and an optional following char,
- and prints the address and char to stdout. */
-static void (*format_address)(off_t, char);
-/* The difference between the old-style pseudo starting address and
- the number of bytes to skip. */
+ /* Function that accepts an address and an optional following char,
+ and prints the address and char to stdout. */
+ void (*format_address)(off_t, char);
+
+ /* The difference between the old-style pseudo starting address and
+ the number of bytes to skip. */
#if ENABLE_LONG_OPTS
-static off_t pseudo_offset;
-#else
-enum { pseudo_offset = 0 };
+ off_t pseudo_offset;
+# define G_pseudo_offset G.pseudo_offset
#endif
-/* When zero, MAX_BYTES_TO_FORMAT and END_OFFSET are ignored, and all
- input is formatted. */
-
-/* The number of input bytes formatted per output line. It must be
- a multiple of the least common multiple of the sizes associated with
- the specified output types. It should be as large as possible, but
- no larger than 16 -- unless specified with the -w option. */
-static unsigned bytes_per_block = 32; /* have to use unsigned, not size_t */
-
-/* A NULL-terminated list of the file-arguments from the command line. */
-static const char *const *file_list;
+ /* When zero, MAX_BYTES_TO_FORMAT and END_OFFSET are ignored, and all
+ input is formatted. */
+
+ /* The number of input bytes formatted per output line. It must be
+ a multiple of the least common multiple of the sizes associated with
+ the specified output types. It should be as large as possible, but
+ no larger than 16 -- unless specified with the -w option. */
+ unsigned bytes_per_block; /* have to use unsigned, not size_t */
+
+ /* A NULL-terminated list of the file-arguments from the command line. */
+ const char *const *file_list;
+
+ /* The input stream associated with the current file. */
+ FILE *in_stream;
+
+ bool not_first;
+ bool prev_pair_equal;
+} FIX_ALIASING;
+#if !ENABLE_LONG_OPTS
+enum { G_pseudo_offset = 0 };
+#endif
+#define G (*(struct globals*)bb_common_bufsiz1)
+#define INIT_G() do { \
+ setup_common_bufsiz(); \
+ BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
+ G.bytes_per_block = 32; \
+} while (0)
-/* The input stream associated with the current file. */
-static FILE *in_stream;
#define MAX_INTEGRAL_TYPE_SIZE sizeof(ulonglong_t)
static const unsigned char integral_type_size[MAX_INTEGRAL_TYPE_SIZE + 1] ALIGN1 = {
@@ -387,11 +403,11 @@ print_named_ascii(size_t n_bytes, const char *block,
" sp"
};
// buf[N] pos: 01234 56789
- char buf[12] = " x\0 0xx\0";
- // actually " x\0 xxx\0", but want to share string with print_ascii.
+ char buf[12] = " x\0 xxx\0";
// [12] because we take three 32bit stack slots anyway, and
// gcc is too dumb to initialize with constant stores,
// it copies initializer from rodata. Oh well.
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65410
while (n_bytes--) {
unsigned masked_c = *(unsigned char *) block++;
@@ -419,7 +435,7 @@ print_ascii(size_t n_bytes, const char *block,
const char *unused_fmt_string UNUSED_PARAM)
{
// buf[N] pos: 01234 56789
- char buf[12] = " x\0 0xx\0";
+ char buf[12] = " x\0 xxx\0";
while (n_bytes--) {
const char *s;
@@ -455,11 +471,9 @@ print_ascii(size_t n_bytes, const char *block,
case '\v':
s = " \\v";
break;
- case '\x7f':
- s = " 177";
- break;
- default: /* c is never larger than 040 */
- buf[7] = (c >> 3) + '0';
+ default:
+ buf[6] = (c >> 6 & 3) + '0';
+ buf[7] = (c >> 3 & 7) + '0';
buf[8] = (c & 7) + '0';
s = buf + 5;
}
@@ -478,17 +492,17 @@ static void
open_next_file(void)
{
while (1) {
- if (!*file_list)
+ if (!*G.file_list)
return;
- in_stream = fopen_or_warn_stdin(*file_list++);
- if (in_stream) {
+ G.in_stream = fopen_or_warn_stdin(*G.file_list++);
+ if (G.in_stream) {
break;
}
- exit_code = 1;
+ G.exit_code = 1;
}
if ((option_mask32 & (OPT_N|OPT_S)) == OPT_N)
- setbuf(in_stream, NULL);
+ setbuf(G.in_stream, NULL);
}
/* Test whether there have been errors on in_stream, and close it if
@@ -501,16 +515,16 @@ open_next_file(void)
static void
check_and_close(void)
{
- if (in_stream) {
- if (ferror(in_stream)) {
- bb_error_msg("%s: read error", (in_stream == stdin)
+ if (G.in_stream) {
+ if (ferror(G.in_stream)) {
+ bb_error_msg("%s: read error", (G.in_stream == stdin)
? bb_msg_standard_input
- : file_list[-1]
+ : G.file_list[-1]
);
- exit_code = 1;
+ G.exit_code = 1;
}
- fclose_if_not_stdin(in_stream);
- in_stream = NULL;
+ fclose_if_not_stdin(G.in_stream);
+ G.in_stream = NULL;
}
if (ferror(stdout)) {
@@ -746,9 +760,9 @@ decode_format_string(const char *s)
assert(s != next);
s = next;
- spec = xrealloc_vector(spec, 4, n_specs);
- memcpy(&spec[n_specs], &tspec, sizeof(spec[0]));
- n_specs++;
+ G.spec = xrealloc_vector(G.spec, 4, G.n_specs);
+ memcpy(&G.spec[G.n_specs], &tspec, sizeof(G.spec[0]));
+ G.n_specs++;
}
}
@@ -765,7 +779,7 @@ skip(off_t n_skip)
if (n_skip == 0)
return;
- while (in_stream) { /* !EOF */
+ while (G.in_stream) { /* !EOF */
struct stat file_stats;
/* First try seeking. For large offsets, this extra work is
@@ -783,15 +797,15 @@ skip(off_t n_skip)
If the number of bytes left to skip is at least
as large as the size of the current file, we can
decrement n_skip and go on to the next file. */
- if (fstat(fileno(in_stream), &file_stats) == 0
+ if (fstat(fileno(G.in_stream), &file_stats) == 0
&& S_ISREG(file_stats.st_mode) && file_stats.st_size > 0
) {
if (file_stats.st_size < n_skip) {
n_skip -= file_stats.st_size;
/* take "check & close / open_next" route */
} else {
- if (fseeko(in_stream, n_skip, SEEK_CUR) != 0)
- exit_code = 1;
+ if (fseeko(G.in_stream, n_skip, SEEK_CUR) != 0)
+ G.exit_code = 1;
return;
}
} else {
@@ -804,7 +818,7 @@ skip(off_t n_skip)
while (n_skip > 0) {
if (n_skip < n_bytes_to_read)
n_bytes_to_read = n_skip;
- n_bytes_read = fread(buf, 1, n_bytes_to_read, in_stream);
+ n_bytes_read = fread(buf, 1, n_bytes_to_read, G.in_stream);
n_skip -= n_bytes_read;
if (n_bytes_read != n_bytes_to_read)
break; /* EOF on this file or error */
@@ -857,7 +871,7 @@ static void
format_address_label(off_t address, char c)
{
format_address_std(address, ' ');
- format_address_paren(address + pseudo_offset, c);
+ format_address_paren(address + G_pseudo_offset, c);
}
#endif
@@ -888,36 +902,34 @@ static void
write_block(off_t current_offset, size_t n_bytes,
const char *prev_block, const char *curr_block)
{
- static char first = 1;
- static char prev_pair_equal = 0;
- size_t i;
+ unsigned i;
if (!(option_mask32 & OPT_v)
- && !first
- && n_bytes == bytes_per_block
- && memcmp(prev_block, curr_block, bytes_per_block) == 0
+ && G.not_first
+ && n_bytes == G.bytes_per_block
+ && memcmp(prev_block, curr_block, G.bytes_per_block) == 0
) {
- if (prev_pair_equal) {
+ if (G.prev_pair_equal) {
/* The two preceding blocks were equal, and the current
block is the same as the last one, so print nothing. */
} else {
puts("*");
- prev_pair_equal = 1;
+ G.prev_pair_equal = 1;
}
} else {
- first = 0;
- prev_pair_equal = 0;
- for (i = 0; i < n_specs; i++) {
+ G.not_first = 1;
+ G.prev_pair_equal = 0;
+ for (i = 0; i < G.n_specs; i++) {
if (i == 0)
- format_address(current_offset, '\0');
+ G.format_address(current_offset, '\0');
else
printf("%*s", address_pad_len_char - '0', "");
- (*spec[i].print_function) (n_bytes, curr_block, spec[i].fmt_string);
- if (spec[i].hexl_mode_trailer) {
+ (*G.spec[i].print_function) (n_bytes, curr_block, G.spec[i].fmt_string);
+ if (G.spec[i].hexl_mode_trailer) {
/* space-pad out to full line width, then dump the trailer */
- unsigned datum_width = width_bytes[spec[i].size];
- unsigned blank_fields = (bytes_per_block - n_bytes) / datum_width;
- unsigned field_width = spec[i].field_width + 1;
+ unsigned datum_width = width_bytes[G.spec[i].size];
+ unsigned blank_fields = (G.bytes_per_block - n_bytes) / datum_width;
+ unsigned field_width = G.spec[i].field_width + 1;
printf("%*s", blank_fields * field_width, "");
dump_hexl_mode_trailer(n_bytes, curr_block);
}
@@ -929,19 +941,19 @@ write_block(off_t current_offset, size_t n_bytes,
static void
read_block(size_t n, char *block, size_t *n_bytes_in_buffer)
{
- assert(0 < n && n <= bytes_per_block);
+ assert(0 < n && n <= G.bytes_per_block);
*n_bytes_in_buffer = 0;
if (n == 0)
return;
- while (in_stream != NULL) { /* EOF. */
+ while (G.in_stream != NULL) { /* EOF. */
size_t n_needed;
size_t n_read;
n_needed = n - *n_bytes_in_buffer;
- n_read = fread(block + *n_bytes_in_buffer, 1, n_needed, in_stream);
+ n_read = fread(block + *n_bytes_in_buffer, 1, n_needed, G.in_stream);
*n_bytes_in_buffer += n_read;
if (n_read == n_needed)
break;
@@ -960,8 +972,8 @@ get_lcm(void)
size_t i;
int l_c_m = 1;
- for (i = 0; i < n_specs; i++)
- l_c_m = lcm(l_c_m, width_bytes[(int) spec[i].size]);
+ for (i = 0; i < G.n_specs; i++)
+ l_c_m = lcm(l_c_m, width_bytes[(int) G.spec[i].size]);
return l_c_m;
}
@@ -982,8 +994,8 @@ dump(off_t current_offset, off_t end_offset)
int idx;
size_t n_bytes_read;
- block[0] = xmalloc(2 * bytes_per_block);
- block[1] = block[0] + bytes_per_block;
+ block[0] = xmalloc(2 * G.bytes_per_block);
+ block[1] = block[0] + G.bytes_per_block;
idx = 0;
if (option_mask32 & OPT_N) {
@@ -993,21 +1005,21 @@ dump(off_t current_offset, off_t end_offset)
n_bytes_read = 0;
break;
}
- n_needed = MIN(end_offset - current_offset, (off_t) bytes_per_block);
+ n_needed = MIN(end_offset - current_offset, (off_t) G.bytes_per_block);
read_block(n_needed, block[idx], &n_bytes_read);
- if (n_bytes_read < bytes_per_block)
+ if (n_bytes_read < G.bytes_per_block)
break;
- assert(n_bytes_read == bytes_per_block);
+ assert(n_bytes_read == G.bytes_per_block);
write_block(current_offset, n_bytes_read, block[idx ^ 1], block[idx]);
current_offset += n_bytes_read;
idx ^= 1;
}
} else {
while (1) {
- read_block(bytes_per_block, block[idx], &n_bytes_read);
- if (n_bytes_read < bytes_per_block)
+ read_block(G.bytes_per_block, block[idx], &n_bytes_read);
+ if (n_bytes_read < G.bytes_per_block)
break;
- assert(n_bytes_read == bytes_per_block);
+ assert(n_bytes_read == G.bytes_per_block);
write_block(current_offset, n_bytes_read, block[idx ^ 1], block[idx]);
current_offset += n_bytes_read;
idx ^= 1;
@@ -1021,16 +1033,16 @@ dump(off_t current_offset, off_t end_offset)
l_c_m = get_lcm();
/* Make bytes_to_write the smallest multiple of l_c_m that
- is at least as large as n_bytes_read. */
+ is at least as large as n_bytes_read. */
bytes_to_write = l_c_m * ((n_bytes_read + l_c_m - 1) / l_c_m);
memset(block[idx] + n_bytes_read, 0, bytes_to_write - n_bytes_read);
write_block(current_offset, bytes_to_write,
- block[idx ^ 1], block[idx]);
+ block[idx ^ 1], block[idx]);
current_offset += n_bytes_read;
}
- format_address(current_offset, '\n');
+ G.format_address(current_offset, '\n');
if ((option_mask32 & OPT_N) && current_offset >= end_offset)
check_and_close();
@@ -1061,16 +1073,16 @@ dump(off_t current_offset, off_t end_offset)
static void
dump_strings(off_t address, off_t end_offset)
{
- unsigned bufsize = MAX(100, string_min);
+ unsigned bufsize = MAX(100, G.string_min);
unsigned char *buf = xmalloc(bufsize);
while (1) {
size_t i;
int c;
- /* See if the next 'string_min' chars are all printing chars. */
+ /* See if the next 'G.string_min' chars are all printing chars. */
tryline:
- if ((option_mask32 & OPT_N) && (end_offset - string_min <= address))
+ if ((option_mask32 & OPT_N) && (end_offset - G.string_min <= address))
break;
i = 0;
while (!(option_mask32 & OPT_N) || address < end_offset) {
@@ -1079,8 +1091,8 @@ dump_strings(off_t address, off_t end_offset)
buf = xrealloc(buf, bufsize);
}
- while (in_stream) { /* !EOF */
- c = fgetc(in_stream);
+ while (G.in_stream) { /* !EOF */
+ c = fgetc(G.in_stream);
if (c != EOF)
goto got_char;
check_and_close();
@@ -1097,12 +1109,12 @@ dump_strings(off_t address, off_t end_offset)
buf[i++] = c; /* String continues; store it all. */
}
- if (i < string_min) /* Too short! */
+ if (i < G.string_min) /* Too short! */
goto tryline;
/* If we get here, the string is all printable and NUL-terminated */
buf[i] = 0;
- format_address(address - i - 1, ' ');
+ G.format_address(address - i - 1, ' ');
for (i = 0; (c = buf[i]); i++) {
switch (c) {
@@ -1120,7 +1132,7 @@ dump_strings(off_t address, off_t end_offset)
}
/* We reach this point only if we search through
- (max_bytes_to_format - string_min) bytes before reaching EOF. */
+ (max_bytes_to_format - G.string_min) bytes before reaching EOF. */
check_and_close();
ret:
free(buf);
@@ -1166,12 +1178,6 @@ parse_old_offset(const char *s, off_t *offset)
int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int od_main(int argc UNUSED_PARAM, char **argv)
{
- static const struct suffix_mult bkm[] = {
- { "b", 512 },
- { "k", 1024 },
- { "m", 1024*1024 },
- { "", 0 }
- };
#if ENABLE_LONG_OPTS
static const char od_longopts[] ALIGN1 =
"skip-bytes\0" Required_argument "j"
@@ -1198,8 +1204,10 @@ int od_main(int argc UNUSED_PARAM, char **argv)
/* The maximum number of bytes that will be formatted. */
off_t max_bytes_to_format = 0;
- spec = NULL;
- format_address = format_address_std;
+ INIT_G();
+
+ /*G.spec = NULL; - already is */
+ G.format_address = format_address_std;
address_base_char = 'o';
address_pad_len_char = '7';
@@ -1225,12 +1233,12 @@ int od_main(int argc UNUSED_PARAM, char **argv)
bb_error_msg_and_die("bad output address radix "
"'%c' (must be [doxn])", str_A[0]);
pos = p - doxn;
- if (pos == 3) format_address = format_address_none;
+ if (pos == 3) G.format_address = format_address_none;
address_base_char = doxn_address_base_char[pos];
address_pad_len_char = doxn_address_pad_len_char[pos];
}
if (opt & OPT_N) {
- max_bytes_to_format = xstrtooff_sfx(str_N, 0, bkm);
+ max_bytes_to_format = xstrtooff_sfx(str_N, 0, bkm_suffixes);
}
if (opt & OPT_a) decode_format_string("a");
if (opt & OPT_b) decode_format_string("oC");
@@ -1239,7 +1247,7 @@ int od_main(int argc UNUSED_PARAM, char **argv)
if (opt & OPT_f) decode_format_string("fF");
if (opt & OPT_h) decode_format_string("x2");
if (opt & OPT_i) decode_format_string("d2");
- if (opt & OPT_j) n_bytes_to_skip = xstrtooff_sfx(str_j, 0, bkm);
+ if (opt & OPT_j) n_bytes_to_skip = xstrtooff_sfx(str_j, 0, bkm_suffixes);
if (opt & OPT_l) decode_format_string("d4");
if (opt & OPT_o) decode_format_string("o2");
while (lst_t) {
@@ -1248,11 +1256,11 @@ int od_main(int argc UNUSED_PARAM, char **argv)
if (opt & OPT_x) decode_format_string("x2");
if (opt & OPT_s) decode_format_string("d2");
if (opt & OPT_S) {
- string_min = xstrtou_sfx(str_S, 0, bkm);
+ G.string_min = xstrtou_sfx(str_S, 0, bkm_suffixes);
}
// Bloat:
- //if ((option_mask32 & OPT_S) && n_specs > 0)
+ //if ((option_mask32 & OPT_S) && G.n_specs > 0)
// bb_error_msg_and_die("no type may be specified when dumping strings");
/* If the --traditional option is used, there may be from
@@ -1308,14 +1316,14 @@ int od_main(int argc UNUSED_PARAM, char **argv)
}
if (pseudo_start >= 0) {
- if (format_address == format_address_none) {
+ if (G.format_address == format_address_none) {
address_base_char = 'o';
address_pad_len_char = '7';
- format_address = format_address_paren;
+ G.format_address = format_address_paren;
} else {
- format_address = format_address_label;
+ G.format_address = format_address_label;
}
- pseudo_offset = pseudo_start - n_bytes_to_skip;
+ G_pseudo_offset = pseudo_start - n_bytes_to_skip;
}
}
/* else: od --traditional (without args) */
@@ -1328,45 +1336,45 @@ int od_main(int argc UNUSED_PARAM, char **argv)
bb_error_msg_and_die("SKIP + SIZE is too large");
}
- if (n_specs == 0) {
+ if (G.n_specs == 0) {
decode_format_string("o2");
- /*n_specs = 1; - done by decode_format_string */
+ /*G.n_specs = 1; - done by decode_format_string */
}
/* If no files were listed on the command line,
set the global pointer FILE_LIST so that it
references the null-terminated list of one name: "-". */
- file_list = bb_argv_dash;
+ G.file_list = bb_argv_dash;
if (argv[0]) {
/* Set the global pointer FILE_LIST so that it
references the first file-argument on the command-line. */
- file_list = (char const *const *) argv;
+ G.file_list = (char const *const *) argv;
}
/* Open the first input file */
open_next_file();
/* Skip over any unwanted header bytes */
skip(n_bytes_to_skip);
- if (!in_stream)
+ if (!G.in_stream)
return EXIT_FAILURE;
/* Compute output block length */
l_c_m = get_lcm();
if (opt & OPT_w) { /* -w: width */
- if (!bytes_per_block || bytes_per_block % l_c_m != 0) {
+ if (!G.bytes_per_block || G.bytes_per_block % l_c_m != 0) {
bb_error_msg("warning: invalid width %u; using %d instead",
- (unsigned)bytes_per_block, l_c_m);
- bytes_per_block = l_c_m;
+ (unsigned)G.bytes_per_block, l_c_m);
+ G.bytes_per_block = l_c_m;
}
} else {
- bytes_per_block = l_c_m;
+ G.bytes_per_block = l_c_m;
if (l_c_m < DEFAULT_BYTES_PER_BLOCK)
- bytes_per_block *= DEFAULT_BYTES_PER_BLOCK / l_c_m;
+ G.bytes_per_block *= DEFAULT_BYTES_PER_BLOCK / l_c_m;
}
#ifdef DEBUG
- for (i = 0; i < n_specs; i++) {
+ for (i = 0; i < G.n_specs; i++) {
printf("%d: fmt=\"%s\" width=%d\n",
i, spec[i].fmt_string, width_bytes[spec[i].size]);
}
@@ -1380,5 +1388,5 @@ int od_main(int argc UNUSED_PARAM, char **argv)
if (fclose(stdin))
bb_perror_msg_and_die(bb_msg_standard_input);
- return exit_code;
+ return G.exit_code;
}
diff --git a/release/src/router/busybox/coreutils/printf.c b/release/src/router/busybox/coreutils/printf.c
index 3dd43a9782..9ee7350d01 100644
--- a/release/src/router/busybox/coreutils/printf.c
+++ b/release/src/router/busybox/coreutils/printf.c
@@ -131,8 +131,8 @@ static double my_xstrtod(const char *arg)
return result;
}
-/* Handles %b */
-static void print_esc_string(const char *str)
+/* Handles %b; return 1 if output is to be short-circuited by \c */
+static int print_esc_string(const char *str)
{
char c;
while ((c = *str) != '\0') {
@@ -145,6 +145,9 @@ static void print_esc_string(const char *str)
str++;
}
}
+ else if (*str == 'c') {
+ return 1;
+ }
{
/* optimization: don't force arg to be on-stack,
* use another variable for that. */
@@ -155,6 +158,8 @@ static void print_esc_string(const char *str)
}
putchar(c);
}
+
+ return 0;
}
static void print_direc(char *format, unsigned fmt_length,
@@ -280,7 +285,8 @@ static char **print_formatted(char *f, char **argv, int *conv_err)
}
if (*f == 'b') {
if (*argv) {
- print_esc_string(*argv);
+ if (print_esc_string(*argv))
+ return saved_argv; /* causes main() to exit */
++argv;
}
break;
diff --git a/release/src/router/busybox/coreutils/readlink.c b/release/src/router/busybox/coreutils/readlink.c
index f7ad791ec8..d73ef4ddb5 100644
--- a/release/src/router/busybox/coreutils/readlink.c
+++ b/release/src/router/busybox/coreutils/readlink.c
@@ -39,7 +39,10 @@
* -q, --quiet, -s, --silent suppress most error messages
* -v, --verbose report error messages
*
- * bbox supports: -f -n -v (fully), -q -s (accepts but ignores)
+ * bbox supports: -f (partially) -n -v (fully), -q -s (accepts but ignores)
+ * Note: we export the -f flag, but our -f behaves like coreutils' -e.
+ * Unfortunately, there isn't a C lib function we can leverage to get this
+ * behavior which means we'd have to implement the full stack ourselves :(.
*/
int readlink_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
diff --git a/release/src/router/busybox/coreutils/rm.c b/release/src/router/busybox/coreutils/rm.c
index 042fba1623..d0ad81dfc7 100644
--- a/release/src/router/busybox/coreutils/rm.c
+++ b/release/src/router/busybox/coreutils/rm.c
@@ -38,7 +38,6 @@ int rm_main(int argc UNUSED_PARAM, char **argv)
unsigned opt;
opt_complementary = "f-i:i-f";
- /* -v (verbose) is ignored */
opt = getopt32(argv, "fiRrv");
argv += optind;
if (opt & 1)
@@ -47,6 +46,8 @@ int rm_main(int argc UNUSED_PARAM, char **argv)
flags |= FILEUTILS_INTERACTIVE;
if (opt & (8|4))
flags |= FILEUTILS_RECUR;
+ if ((opt & 16) && FILEUTILS_VERBOSE)
+ flags |= FILEUTILS_VERBOSE;
if (*argv != NULL) {
do {
diff --git a/release/src/router/busybox/coreutils/rmdir.c b/release/src/router/busybox/coreutils/rmdir.c
index 2840d1cfaa..0792a1c8e2 100644
--- a/release/src/router/busybox/coreutils/rmdir.c
+++ b/release/src/router/busybox/coreutils/rmdir.c
@@ -30,8 +30,9 @@
/* This is a NOFORK applet. Be very careful! */
-#define PARENTS 0x01
-#define IGNORE_NON_EMPTY 0x02
+#define PARENTS (1 << 0)
+#define VERBOSE ((1 << 1) * ENABLE_FEATURE_VERBOSE)
+#define IGNORE_NON_EMPTY (1 << 2)
int rmdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int rmdir_main(int argc UNUSED_PARAM, char **argv)
@@ -46,10 +47,13 @@ int rmdir_main(int argc UNUSED_PARAM, char **argv)
/* Debian etch: many packages fail to be purged or installed
* because they desperately want this option: */
"ignore-fail-on-non-empty\0" No_argument "\xff"
+ IF_FEATURE_VERBOSE(
+ "verbose\0" No_argument "v"
+ )
;
applet_long_options = rmdir_longopts;
#endif
- flags = getopt32(argv, "p");
+ flags = getopt32(argv, "pv");
argv += optind;
if (!*argv) {
@@ -60,6 +64,10 @@ int rmdir_main(int argc UNUSED_PARAM, char **argv)
path = *argv;
while (1) {
+ if (flags & VERBOSE) {
+ printf("rmdir: removing directory, '%s'\n", path);
+ }
+
if (rmdir(path) < 0) {
#if ENABLE_FEATURE_RMDIR_LONG_OPTIONS
if ((flags & IGNORE_NON_EMPTY) && errno == ENOTEMPTY)
diff --git a/release/src/router/busybox/coreutils/shuf.c b/release/src/router/busybox/coreutils/shuf.c
new file mode 100644
index 0000000000..9f61f2f7de
--- /dev/null
+++ b/release/src/router/busybox/coreutils/shuf.c
@@ -0,0 +1,153 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * shuf: Write a random permutation of the input lines to standard output.
+ *
+ * Copyright (C) 2014 by Bartosz Golaszewski <bartekgola@gmail.com>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+//config:config SHUF
+//config: bool "shuf"
+//config: default y
+//config: help
+//config: Generate random permutations
+
+//kbuild:lib-$(CONFIG_SHUF) += shuf.o
+//applet:IF_SHUF(APPLET_NOEXEC(shuf, shuf, BB_DIR_USR_BIN, BB_SUID_DROP, shuf))
+
+//usage:#define shuf_trivial_usage
+//usage: "[-e|-i L-H] [-n NUM] [-o FILE] [-z] [FILE|ARG...]"
+//usage:#define shuf_full_usage "\n\n"
+//usage: "Randomly permute lines\n"
+//usage: "\n -e Treat ARGs as lines"
+//usage: "\n -i L-H Treat numbers L-H as lines"
+//usage: "\n -n NUM Output at most NUM lines"
+//usage: "\n -o FILE Write to FILE, not standard output"
+//usage: "\n -z End lines with zero byte, not newline"
+
+#include "libbb.h"
+
+/* This is a NOEXEC applet. Be very careful! */
+
+#define OPT_e (1 << 0)
+#define OPT_i (1 << 1)
+#define OPT_n (1 << 2)
+#define OPT_o (1 << 3)
+#define OPT_z (1 << 4)
+#define OPT_STR "ei:n:o:z"
+
+/*
+ * Use the Fisher-Yates shuffle algorithm on an array of lines.
+ */
+static void shuffle_lines(char **lines, unsigned numlines)
+{
+ unsigned i;
+ unsigned r;
+ char *tmp;
+
+ srand(monotonic_us());
+
+ for (i = numlines-1; i > 0; i--) {
+ r = rand();
+ /* RAND_MAX can be as small as 32767 */
+ if (i > RAND_MAX)
+ r ^= rand() << 15;
+ r %= i;
+ tmp = lines[i];
+ lines[i] = lines[r];
+ lines[r] = tmp;
+ }
+}
+
+int shuf_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int shuf_main(int argc, char **argv)
+{
+ unsigned opts;
+ char *opt_i_str, *opt_n_str, *opt_o_str;
+ unsigned i;
+ char **lines;
+ unsigned numlines;
+ char eol;
+
+ opt_complementary = "e--i:i--e"; /* mutually exclusive */
+ opts = getopt32(argv, OPT_STR, &opt_i_str, &opt_n_str, &opt_o_str);
+
+ argc -= optind;
+ argv += optind;
+
+ /* Prepare lines for shuffling - either: */
+ if (opts & OPT_e) {
+ /* make lines from command-line arguments */
+ numlines = argc;
+ lines = argv;
+ } else
+ if (opts & OPT_i) {
+ /* create a range of numbers */
+ char *dash;
+ unsigned lo, hi;
+
+ dash = strchr(opt_i_str, '-');
+ if (!dash) {
+ bb_error_msg_and_die("bad range '%s'", opt_i_str);
+ }
+ *dash = '\0';
+ lo = xatou(opt_i_str);
+ hi = xatou(dash + 1);
+ *dash = '-';
+ if (hi < lo) {
+ bb_error_msg_and_die("bad range '%s'", opt_i_str);
+ }
+
+ numlines = (hi+1) - lo;
+ lines = xmalloc(numlines * sizeof(lines[0]));
+ for (i = 0; i < numlines; i++) {
+ lines[i] = (char*)(uintptr_t)lo;
+ lo++;
+ }
+ } else {
+ /* default - read lines from stdin or the input file */
+ FILE *fp;
+
+ if (argc > 1)
+ bb_show_usage();
+
+ fp = xfopen_stdin(argv[0] ? argv[0] : "-");
+ lines = NULL;
+ numlines = 0;
+ for (;;) {
+ char *line = xmalloc_fgetline(fp);
+ if (!line)
+ break;
+ lines = xrealloc_vector(lines, 6, numlines);
+ lines[numlines++] = line;
+ }
+ fclose_if_not_stdin(fp);
+ }
+
+ if (numlines != 0)
+ shuffle_lines(lines, numlines);
+
+ if (opts & OPT_o)
+ xmove_fd(xopen(opt_o_str, O_WRONLY|O_CREAT|O_TRUNC), STDOUT_FILENO);
+
+ if (opts & OPT_n) {
+ unsigned maxlines;
+ maxlines = xatou(opt_n_str);
+ if (numlines > maxlines)
+ numlines = maxlines;
+ }
+
+ eol = '\n';
+ if (opts & OPT_z)
+ eol = '\0';
+
+ for (i = 0; i < numlines; i++) {
+ if (opts & OPT_i)
+ printf("%u%c", (unsigned)(uintptr_t)lines[i], eol);
+ else
+ printf("%s%c", lines[i], eol);
+ }
+
+ fflush_stdout_and_exit(EXIT_SUCCESS);
+}
diff --git a/release/src/router/busybox/coreutils/sort.c b/release/src/router/busybox/coreutils/sort.c
index 1df07285c7..9139d9f471 100644
--- a/release/src/router/busybox/coreutils/sort.c
+++ b/release/src/router/busybox/coreutils/sort.c
@@ -14,25 +14,25 @@
//usage:#define sort_trivial_usage
//usage: "[-nru"
-//usage: IF_FEATURE_SORT_BIG("gMcszbdfimSTokt] [-o FILE] [-k start[.offset][opts][,end[.offset][opts]] [-t CHAR")
+//usage: IF_FEATURE_SORT_BIG("gMcszbdfiokt] [-o FILE] [-k start[.offset][opts][,end[.offset][opts]] [-t CHAR")
//usage: "] [FILE]..."
//usage:#define sort_full_usage "\n\n"
//usage: "Sort lines of text\n"
//usage: IF_FEATURE_SORT_BIG(
-//usage: "\n -b Ignore leading blanks"
+//usage: "\n -o FILE Output to FILE"
//usage: "\n -c Check whether input is sorted"
-//usage: "\n -d Dictionary order (blank or alphanumeric only)"
+//usage: "\n -b Ignore leading blanks"
//usage: "\n -f Ignore case"
-//usage: "\n -g General numerical sort"
//usage: "\n -i Ignore unprintable characters"
-//usage: "\n -k Sort key"
+//usage: "\n -d Dictionary order (blank or alphanumeric only)"
+//usage: "\n -g General numerical sort"
//usage: "\n -M Sort month"
//usage: )
+//-h, --human-numeric-sort: compare human readable numbers (e.g., 2K 1G)
//usage: "\n -n Sort numbers"
//usage: IF_FEATURE_SORT_BIG(
-//usage: "\n -o Output to file"
-//usage: "\n -k Sort by key"
-//usage: "\n -t CHAR Key separator"
+//usage: "\n -t CHAR Field separator"
+//usage: "\n -k N[,M] Sort by Nth field"
//usage: )
//usage: "\n -r Reverse sort order"
//usage: IF_FEATURE_SORT_BIG(
@@ -41,7 +41,10 @@
//usage: "\n -u Suppress duplicate lines"
//usage: IF_FEATURE_SORT_BIG(
//usage: "\n -z Lines are terminated by NUL, not newline"
-//usage: "\n -mST Ignored for GNU compatibility")
+////usage: "\n -m Ignored for GNU compatibility"
+////usage: "\n -S BUFSZ Ignored for GNU compatibility"
+////usage: "\n -T TMPDIR Ignored for GNU compatibility"
+//usage: )
//usage:
//usage:#define sort_example_usage
//usage: "$ echo -e \"e\\nf\\nb\\nd\\nc\\na\" | sort\n"
@@ -106,7 +109,9 @@ static struct sort_key {
static char *get_key(char *str, struct sort_key *key, int flags)
{
- int start = 0, end = 0, len, j;
+ int start = start; /* for compiler */
+ int end;
+ int len, j;
unsigned i;
/* Special case whole string, so we don't have to make a copy */
@@ -123,12 +128,15 @@ static char *get_key(char *str, struct sort_key *key, int flags)
end = len;
/* Loop through fields */
else {
+ unsigned char ch = 0;
+
end = 0;
for (i = 1; i < key->range[2*j] + j; i++) {
if (key_separator) {
/* Skip body of key and separator */
- while (str[end]) {
- if (str[end++] == key_separator)
+ while ((ch = str[end]) != '\0') {
+ end++;
+ if (ch == key_separator)
break;
}
} else {
@@ -136,34 +144,44 @@ static char *get_key(char *str, struct sort_key *key, int flags)
while (isspace(str[end]))
end++;
/* Skip body of key */
- while (str[end]) {
+ while (str[end] != '\0') {
if (isspace(str[end]))
break;
end++;
}
}
}
+ /* Remove last delim: "abc:def:" => "abc:def" */
+ if (j && ch) {
+ //if (str[end-1] != key_separator)
+ // bb_error_msg(_and_die("BUG! "
+ // "str[start:%d,end:%d]:'%.*s'",
+ // start, end, (int)(end-start), &str[start]);
+ end--;
+ }
}
if (!j) start = end;
}
/* Strip leading whitespace if necessary */
-//XXX: skip_whitespace()
if (flags & FLAG_b)
+ /* not using skip_whitespace() for speed */
while (isspace(str[start])) start++;
/* Strip trailing whitespace if necessary */
if (flags & FLAG_bb)
while (end > start && isspace(str[end-1])) end--;
- /* Handle offsets on start and end */
+ /* -kSTART,N.ENDCHAR: honor ENDCHAR (1-based) */
if (key->range[3]) {
- end += key->range[3] - 1;
+ end = key->range[3];
if (end > len) end = len;
}
+ /* -kN.STARTCHAR[,...]: honor STARTCHAR (1-based) */
if (key->range[1]) {
start += key->range[1] - 1;
if (start > len) start = len;
}
/* Make the copy */
- if (end < start) end = start;
+ if (end < start)
+ end = start;
str = xstrndup(str+start, end-start);
/* Handle -d */
if (flags & FLAG_d) {
@@ -219,13 +237,13 @@ static int compare_keys(const void *xarg, const void *yarg)
y = get_key(*(char **)yarg, key, flags);
#else
/* This curly bracket serves no purpose but to match the nesting
- level of the for () loop we're not using */
+ * level of the for () loop we're not using */
{
x = *(char **)xarg;
y = *(char **)yarg;
#endif
/* Perform actual comparison */
- switch (flags & 7) {
+ switch (flags & (FLAG_n | FLAG_M | FLAG_g)) {
default:
bb_error_msg_and_die("unknown sort type");
break;
@@ -277,7 +295,7 @@ static int compare_keys(const void *xarg, const void *yarg)
else if (!yy)
retval = 1;
else
- retval = (dx == thyme.tm_mon) ? 0 : dx - thyme.tm_mon;
+ retval = dx - thyme.tm_mon;
break;
}
/* Full floating point version of -n */
@@ -302,10 +320,14 @@ static int compare_keys(const void *xarg, const void *yarg)
} /* for */
/* Perform fallback sort if necessary */
- if (!retval && !(option_mask32 & FLAG_s))
+ if (!retval && !(option_mask32 & FLAG_s)) {
+ flags = option_mask32;
retval = strcmp(*(char **)xarg, *(char **)yarg);
+ }
+
+ if (flags & FLAG_r)
+ return -retval;
- if (flags & FLAG_r) return -retval;
return retval;
}
@@ -328,7 +350,7 @@ int sort_main(int argc UNUSED_PARAM, char **argv)
char *line, **lines;
char *str_ignored, *str_o, *str_t;
llist_t *lst_k = NULL;
- int i, flag;
+ int i;
int linecount;
unsigned opts;
@@ -351,7 +373,7 @@ int sort_main(int argc UNUSED_PARAM, char **argv)
/* note: below this point we use option_mask32, not opts,
* since that reduces register pressure and makes code smaller */
- /* parse sort key */
+ /* Parse sort key */
while (lst_k) {
enum {
FLAG_allowed_for_k =
@@ -378,17 +400,18 @@ int sort_main(int argc UNUSED_PARAM, char **argv)
key->range[2*i+1] = str2u(&str_k);
}
while (*str_k) {
- const char *temp2;
+ int flag;
+ const char *idx;
if (*str_k == ',' && !i++) {
str_k++;
break;
} /* no else needed: fall through to syntax error
because comma isn't in OPT_STR */
- temp2 = strchr(OPT_STR, *str_k);
- if (!temp2)
+ idx = strchr(OPT_STR, *str_k);
+ if (!idx)
bb_error_msg_and_die("unknown key option");
- flag = 1 << (temp2 - OPT_STR);
+ flag = 1 << (idx - OPT_STR);
if (flag & ~FLAG_allowed_for_k)
bb_error_msg_and_die("unknown sort type");
/* b after ',' means strip _trailing_ space */
@@ -422,10 +445,10 @@ int sort_main(int argc UNUSED_PARAM, char **argv)
} while (*++argv);
#if ENABLE_FEATURE_SORT_BIG
- /* if no key, perform alphabetic sort */
+ /* If no key, perform alphabetic sort */
if (!key_list)
add_key()->range[0] = 1;
- /* handle -c */
+ /* Handle -c */
if (option_mask32 & FLAG_c) {
int j = (option_mask32 & FLAG_u) ? -1 : 0;
for (i = 1; i < linecount; i++) {
@@ -439,20 +462,21 @@ int sort_main(int argc UNUSED_PARAM, char **argv)
#endif
/* Perform the actual sort */
qsort(lines, linecount, sizeof(lines[0]), compare_keys);
- /* handle -u */
+
+ /* Handle -u */
if (option_mask32 & FLAG_u) {
- flag = 0;
+ int j = 0;
/* coreutils 6.3 drop lines for which only key is the same */
/* -- disabling last-resort compare... */
option_mask32 |= FLAG_s;
for (i = 1; i < linecount; i++) {
- if (compare_keys(&lines[flag], &lines[i]) == 0)
+ if (compare_keys(&lines[j], &lines[i]) == 0)
free(lines[i]);
else
- lines[++flag] = lines[i];
+ lines[++j] = lines[i];
}
if (linecount)
- linecount = flag+1;
+ linecount = j+1;
}
/* Print it */
@@ -461,9 +485,11 @@ int sort_main(int argc UNUSED_PARAM, char **argv)
if (option_mask32 & FLAG_o)
xmove_fd(xopen(str_o, O_WRONLY|O_CREAT|O_TRUNC), STDOUT_FILENO);
#endif
- flag = (option_mask32 & FLAG_z) ? '\0' : '\n';
- for (i = 0; i < linecount; i++)
- printf("%s%c", lines[i], flag);
+ {
+ int ch = (option_mask32 & FLAG_z) ? '\0' : '\n';
+ for (i = 0; i < linecount; i++)
+ printf("%s%c", lines[i], ch);
+ }
fflush_stdout_and_exit(EXIT_SUCCESS);
}
diff --git a/release/src/router/busybox/coreutils/split.c b/release/src/router/busybox/coreutils/split.c
index 11e6404425..e67c3de664 100644
--- a/release/src/router/busybox/coreutils/split.c
+++ b/release/src/router/busybox/coreutils/split.c
@@ -22,18 +22,17 @@
//usage: "$ cat TODO | split -a 2 -l 2 TODO_\n"
#include "libbb.h"
+#include "common_bufsiz.h"
-static const struct suffix_mult split_suffices[] = {
#if ENABLE_FEATURE_SPLIT_FANCY
+static const struct suffix_mult split_suffixes[] = {
{ "b", 512 },
-#endif
{ "k", 1024 },
{ "m", 1024*1024 },
-#if ENABLE_FEATURE_SPLIT_FANCY
{ "g", 1024*1024*1024 },
-#endif
{ "", 0 }
};
+#endif
/* Increment the suffix part of the filename.
* Returns NULL if we are out of filenames.
@@ -80,13 +79,18 @@ int split_main(int argc UNUSED_PARAM, char **argv)
ssize_t bytes_read, to_write;
char *src;
+ setup_common_bufsiz();
+
opt_complementary = "?2:a+"; /* max 2 args; -a N */
opt = getopt32(argv, "l:b:a:", &count_p, &count_p, &suffix_len);
if (opt & SPLIT_OPT_l)
cnt = XATOOFF(count_p);
if (opt & SPLIT_OPT_b) // FIXME: also needs XATOOFF
- cnt = xatoull_sfx(count_p, split_suffices);
+ cnt = xatoull_sfx(count_p,
+ IF_FEATURE_SPLIT_FANCY(split_suffixes)
+ IF_NOT_FEATURE_SPLIT_FANCY(km_suffixes)
+ );
sfx = "x";
argv += optind;
diff --git a/release/src/router/busybox/coreutils/stat.c b/release/src/router/busybox/coreutils/stat.c
index 2797719dd1..ddcfcf2d78 100644
--- a/release/src/router/busybox/coreutils/stat.c
+++ b/release/src/router/busybox/coreutils/stat.c
@@ -12,54 +12,83 @@
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//config:config STAT
+//config: bool "stat"
+//config: default y
+//config: help
+//config: display file or filesystem status.
+//config:
+//config:config FEATURE_STAT_FORMAT
+//config: bool "Enable custom formats (-c)"
+//config: default y
+//config: depends on STAT
+//config: help
+//config: Without this, stat will not support the '-c format' option where
+//config: users can pass a custom format string for output. This adds about
+//config: 7k to a nonstatic build on amd64.
+//config:
+//config:config FEATURE_STAT_FILESYSTEM
+//config: bool "Enable display of filesystem status (-f)"
+//config: default y
+//config: depends on STAT
+//config: select PLATFORM_LINUX # statfs()
+//config: help
+//config: Without this, stat will not support the '-f' option to display
+//config: information about filesystem status.
+
//usage:#define stat_trivial_usage
//usage: "[OPTIONS] FILE..."
//usage:#define stat_full_usage "\n\n"
-//usage: "Display file (default) or filesystem status\n"
+//usage: "Display file"
+//usage: IF_FEATURE_STAT_FILESYSTEM(" (default) or filesystem")
+//usage: " status\n"
//usage: IF_FEATURE_STAT_FORMAT(
-//usage: "\n -c fmt Use the specified format"
+//usage: "\n -c FMT Use the specified format"
//usage: )
+//usage: IF_FEATURE_STAT_FILESYSTEM(
//usage: "\n -f Display filesystem status"
+//usage: )
//usage: "\n -L Follow links"
-//usage: "\n -t Display info in terse form"
+//usage: "\n -t Terse display"
//usage: IF_SELINUX(
//usage: "\n -Z Print security context"
//usage: )
//usage: IF_FEATURE_STAT_FORMAT(
-//usage: "\n\nValid format sequences for files:\n"
+//usage: "\n\nFMT sequences"IF_FEATURE_STAT_FILESYSTEM(" for files")":\n"
//usage: " %a Access rights in octal\n"
//usage: " %A Access rights in human readable form\n"
//usage: " %b Number of blocks allocated (see %B)\n"
-//usage: " %B The size in bytes of each block reported by %b\n"
+//usage: " %B Size in bytes of each block reported by %b\n"
//usage: " %d Device number in decimal\n"
//usage: " %D Device number in hex\n"
//usage: " %f Raw mode in hex\n"
//usage: " %F File type\n"
-//usage: " %g Group ID of owner\n"
-//usage: " %G Group name of owner\n"
+//usage: " %g Group ID\n"
+//usage: " %G Group name\n"
//usage: " %h Number of hard links\n"
//usage: " %i Inode number\n"
//usage: " %n File name\n"
//usage: " %N File name, with -> TARGET if symlink\n"
//usage: " %o I/O block size\n"
-//usage: " %s Total size, in bytes\n"
+//usage: " %s Total size in bytes\n"
//usage: " %t Major device type in hex\n"
//usage: " %T Minor device type in hex\n"
-//usage: " %u User ID of owner\n"
-//usage: " %U User name of owner\n"
+//usage: " %u User ID\n"
+//usage: " %U User name\n"
//usage: " %x Time of last access\n"
//usage: " %X Time of last access as seconds since Epoch\n"
//usage: " %y Time of last modification\n"
//usage: " %Y Time of last modification as seconds since Epoch\n"
//usage: " %z Time of last change\n"
//usage: " %Z Time of last change as seconds since Epoch\n"
-//usage: "\nValid format sequences for file systems:\n"
+//usage: IF_FEATURE_STAT_FILESYSTEM(
+//usage: "\nFMT sequences for file systems:\n"
//usage: " %a Free blocks available to non-superuser\n"
-//usage: " %b Total data blocks in file system\n"
-//usage: " %c Total file nodes in file system\n"
-//usage: " %d Free file nodes in file system\n"
-//usage: " %f Free blocks in file system\n"
+//usage: " %b Total data blocks\n"
+//usage: " %c Total file nodes\n"
+//usage: " %d Free file nodes\n"
+//usage: " %f Free blocks\n"
//usage: IF_SELINUX(
//usage: " %C Security context in selinux\n"
//usage: )
@@ -71,13 +100,17 @@
//usage: " %t Type in hex\n"
//usage: " %T Type in human readable form"
//usage: )
+//usage: )
#include "libbb.h"
+#include "common_bufsiz.h"
-#define OPT_FILESYS (1 << 0)
-#define OPT_TERSE (1 << 1)
-#define OPT_DEREFERENCE (1 << 2)
-#define OPT_SELINUX (1 << 3)
+enum {
+ OPT_TERSE = (1 << 0),
+ OPT_DEREFERENCE = (1 << 1),
+ OPT_FILESYS = (1 << 2) * ENABLE_FEATURE_STAT_FILESYSTEM,
+ OPT_SELINUX = (1 << (2+ENABLE_FEATURE_STAT_FILESYSTEM)) * ENABLE_SELINUX,
+};
#if ENABLE_FEATURE_STAT_FORMAT
typedef bool (*statfunc_ptr)(const char *, const char *);
@@ -99,9 +132,15 @@ static const char *file_type(const struct stat *st)
if (S_ISFIFO(st->st_mode)) return "fifo";
if (S_ISLNK(st->st_mode)) return "symbolic link";
if (S_ISSOCK(st->st_mode)) return "socket";
+#ifdef S_TYPEISMQ
if (S_TYPEISMQ(st)) return "message queue";
+#endif
+#ifdef S_TYPEISSEM
if (S_TYPEISSEM(st)) return "semaphore";
+#endif
+#ifdef S_TYPEISSHM
if (S_TYPEISSHM(st)) return "shared memory object";
+#endif
#ifdef S_TYPEISTMO
if (S_TYPEISTMO(st)) return "typed memory object";
#endif
@@ -120,12 +159,13 @@ static const char *human_time(time_t t)
/*static char buf[sizeof("YYYY-MM-DD HH:MM:SS.000000000")] ALIGN1;*/
#define buf bb_common_bufsiz1
-
- strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S.000000000", localtime(&t));
+ setup_common_bufsiz();
+ strcpy(strftime_YYYYMMDDHHMMSS(buf, COMMON_BUFSIZE, &t), ".000000000");
return buf;
#undef buf
}
+#if ENABLE_FEATURE_STAT_FILESYSTEM
/* Return the type of the specified file system.
* Some systems have statfvs.f_basetype[FSTYPSZ]. (AIX, HP-UX, and Solaris)
* Others have statfs.f_fstypename[MFSNAMELEN]. (NetBSD 1.5.2)
@@ -196,6 +236,7 @@ static unsigned long long get_f_fsid(const struct statfs *statfsbuf)
while (--sz > 0);
return r;
}
+#endif /* FEATURE_STAT_FILESYSTEM */
#if ENABLE_FEATURE_STAT_FORMAT
static void strcatc(char *str, char c)
@@ -211,6 +252,7 @@ static void printfs(char *pformat, const char *msg)
printf(pformat, msg);
}
+#if ENABLE_FEATURE_STAT_FILESYSTEM
/* print statfs info */
static void FAST_FUNC print_statfs(char *pformat, const char m,
const char *const filename, const void *data
@@ -257,6 +299,7 @@ static void FAST_FUNC print_statfs(char *pformat, const char m,
printf(pformat, m);
}
}
+#endif
/* print stat info */
static void FAST_FUNC print_stat(char *pformat, const char m,
@@ -368,7 +411,7 @@ static void print_it(const char *masterformat,
{
/* Create a working copy of the format string */
char *format = xstrdup(masterformat);
- /* Add 2 to accomodate our conversion of the stat '%s' format string
+ /* Add 2 to accommodate our conversion of the stat '%s' format string
* to the printf '%llu' one. */
char *dest = xmalloc(strlen(format) + 2 + 1);
char *b;
@@ -417,6 +460,7 @@ static void print_it(const char *masterformat,
}
#endif /* FEATURE_STAT_FORMAT */
+#if ENABLE_FEATURE_STAT_FILESYSTEM
/* Stat the file system and print what we find. */
#if !ENABLE_FEATURE_STAT_FORMAT
#define do_statfs(filename, format) do_statfs(filename)
@@ -436,7 +480,7 @@ static bool do_statfs(const char *filename, const char *format)
: getfilecon(filename, &scontext)
) < 0
) {
- bb_perror_msg(filename);
+ bb_simple_perror_msg(filename);
return 0;
}
}
@@ -532,6 +576,7 @@ static bool do_statfs(const char *filename, const char *format)
#endif /* FEATURE_STAT_FORMAT */
return 1;
}
+#endif /* FEATURE_STAT_FILESYSTEM */
/* stat the file and print what we find */
#if !ENABLE_FEATURE_STAT_FORMAT
@@ -549,7 +594,7 @@ static bool do_stat(const char *filename, const char *format)
: getfilecon(filename, &scontext)
) < 0
) {
- bb_perror_msg(filename);
+ bb_simple_perror_msg(filename);
return 0;
}
}
@@ -585,37 +630,43 @@ static bool do_stat(const char *filename, const char *format)
# else
if (option_mask32 & OPT_TERSE) {
format = (option_mask32 & OPT_SELINUX ?
- "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o %C\n":
- "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o\n");
+ "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o %C\n"
+ :
+ "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o\n"
+ );
} else {
if (S_ISBLK(statbuf.st_mode) || S_ISCHR(statbuf.st_mode)) {
format = (option_mask32 & OPT_SELINUX ?
- " File: %N\n"
- " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
- "Device: %Dh/%dd\tInode: %-10i Links: %-5h"
- " Device type: %t,%T\n"
- "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
- " S_Context: %C\n"
- "Access: %x\n" "Modify: %y\n" "Change: %z\n":
- " File: %N\n"
- " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
- "Device: %Dh/%dd\tInode: %-10i Links: %-5h"
- " Device type: %t,%T\n"
- "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
- "Access: %x\n" "Modify: %y\n" "Change: %z\n");
+ " File: %N\n"
+ " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
+ "Device: %Dh/%dd\tInode: %-10i Links: %-5h"
+ " Device type: %t,%T\n"
+ "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
+ " S_Context: %C\n"
+ "Access: %x\n" "Modify: %y\n" "Change: %z\n"
+ :
+ " File: %N\n"
+ " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
+ "Device: %Dh/%dd\tInode: %-10i Links: %-5h"
+ " Device type: %t,%T\n"
+ "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
+ "Access: %x\n" "Modify: %y\n" "Change: %z\n"
+ );
} else {
format = (option_mask32 & OPT_SELINUX ?
- " File: %N\n"
- " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
- "Device: %Dh/%dd\tInode: %-10i Links: %h\n"
- "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
- "S_Context: %C\n"
- "Access: %x\n" "Modify: %y\n" "Change: %z\n":
- " File: %N\n"
- " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
- "Device: %Dh/%dd\tInode: %-10i Links: %h\n"
- "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
- "Access: %x\n" "Modify: %y\n" "Change: %z\n");
+ " File: %N\n"
+ " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
+ "Device: %Dh/%dd\tInode: %-10i Links: %h\n"
+ "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
+ "S_Context: %C\n"
+ "Access: %x\n" "Modify: %y\n" "Change: %z\n"
+ :
+ " File: %N\n"
+ " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
+ "Device: %Dh/%dd\tInode: %-10i Links: %h\n"
+ "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
+ "Access: %x\n" "Modify: %y\n" "Change: %z\n"
+ );
}
}
# endif
@@ -643,7 +694,7 @@ static bool do_stat(const char *filename, const char *format)
);
# if ENABLE_SELINUX
if (option_mask32 & OPT_SELINUX)
- printf(" %lc\n", *scontext);
+ printf(" %s\n", scontext);
else
bb_putchar('\n');
# endif
@@ -688,7 +739,8 @@ static bool do_stat(const char *filename, const char *format)
(unsigned long) statbuf.st_gid,
(gw_ent != NULL) ? gw_ent->gr_name : "UNKNOWN");
# if ENABLE_SELINUX
- printf(" S_Context: %lc\n", *scontext);
+ if (option_mask32 & OPT_SELINUX)
+ printf(" S_Context: %s\n", scontext);
# endif
printf("Access: %s\n", human_time(statbuf.st_atime));
printf("Modify: %s\n", human_time(statbuf.st_mtime));
@@ -708,12 +760,15 @@ int stat_main(int argc UNUSED_PARAM, char **argv)
statfunc_ptr statfunc = do_stat;
opt_complementary = "-1"; /* min one arg */
- opts = getopt32(argv, "ftL"
+ opts = getopt32(argv, "tL"
+ IF_FEATURE_STAT_FILESYSTEM("f")
IF_SELINUX("Z")
IF_FEATURE_STAT_FORMAT("c:", &format)
);
+#if ENABLE_FEATURE_STAT_FILESYSTEM
if (opts & OPT_FILESYS) /* -f */
statfunc = do_statfs;
+#endif
#if ENABLE_SELINUX
if (opts & OPT_SELINUX) {
selinux_or_die();
diff --git a/release/src/router/busybox/coreutils/stty.c b/release/src/router/busybox/coreutils/stty.c
index 0668cf7be5..52967ea8f3 100644
--- a/release/src/router/busybox/coreutils/stty.c
+++ b/release/src/router/busybox/coreutils/stty.c
@@ -32,6 +32,7 @@
//usage: "\n [SETTING] See manpage"
#include "libbb.h"
+#include "common_bufsiz.h"
#ifndef _POSIX_VDISABLE
# define _POSIX_VDISABLE ((unsigned char) 0)
@@ -246,10 +247,21 @@ enum speed_setting {
/* Which member(s) of 'struct termios' a mode uses */
enum {
- /* Do NOT change the order or values, as mode_type_flag()
- * depends on them */
control, input, output, local, combination
};
+static tcflag_t *get_ptr_to_tcflag(unsigned type, const struct termios *mode)
+{
+ static const uint8_t tcflag_offsets[] ALIGN1 = {
+ offsetof(struct termios, c_cflag), /* control */
+ offsetof(struct termios, c_iflag), /* input */
+ offsetof(struct termios, c_oflag), /* output */
+ offsetof(struct termios, c_lflag) /* local */
+ };
+ if (type <= local) {
+ return (tcflag_t*) (((char*)mode) + tcflag_offsets[type]);
+ }
+ return NULL;
+}
/* Flags for 'struct mode_info' */
#define SANE_SET 1 /* Set in 'sane' mode */
@@ -306,7 +318,7 @@ enum {
#define MI_ENTRY(N,T,F,B,M) N "\0"
/* Mode names given on command line */
-static const char mode_name[] =
+static const char mode_name[] ALIGN1 =
MI_ENTRY("evenp", combination, REV | OMIT, 0, 0 )
MI_ENTRY("parity", combination, REV | OMIT, 0, 0 )
MI_ENTRY("oddp", combination, REV | OMIT, 0, 0 )
@@ -669,7 +681,7 @@ enum {
#define CI_ENTRY(n,s,o) n "\0"
/* Name given on command line */
-static const char control_name[] =
+static const char control_name[] ALIGN1 =
CI_ENTRY("intr", CINTR, VINTR )
CI_ENTRY("quit", CQUIT, VQUIT )
CI_ENTRY("erase", CERASE, VERASE )
@@ -711,7 +723,7 @@ static const char control_name[] =
#undef CI_ENTRY
#define CI_ENTRY(n,s,o) { s, o },
-static const struct control_info control_info[] = {
+static const struct control_info control_info[] ALIGN2 = {
/* This should be verbatim cut-n-paste copy of the above CI_ENTRYs */
CI_ENTRY("intr", CINTR, VINTR )
CI_ENTRY("quit", CQUIT, VQUIT )
@@ -764,57 +776,12 @@ struct globals {
unsigned current_col;
char buf[10];
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define INIT_G() do { \
G.device_name = bb_msg_standard_input; \
G.max_col = 80; \
} while (0)
-
-/* Return a string that is the printable representation of character CH */
-/* Adapted from 'cat' by Torbjorn Granlund */
-static const char *visible(unsigned ch)
-{
- char *bpout = G.buf;
-
- if (ch == _POSIX_VDISABLE)
- return "<undef>";
-
- if (ch >= 128) {
- ch -= 128;
- *bpout++ = 'M';
- *bpout++ = '-';
- }
-
- if (ch < 32) {
- *bpout++ = '^';
- *bpout++ = ch + 64;
- } else if (ch < 127) {
- *bpout++ = ch;
- } else {
- *bpout++ = '^';
- *bpout++ = '?';
- }
-
- *bpout = '\0';
- return G.buf;
-}
-
-static tcflag_t *mode_type_flag(unsigned type, const struct termios *mode)
-{
- static const uint8_t tcflag_offsets[] ALIGN1 = {
- offsetof(struct termios, c_cflag), /* control */
- offsetof(struct termios, c_iflag), /* input */
- offsetof(struct termios, c_oflag), /* output */
- offsetof(struct termios, c_lflag) /* local */
- };
-
- if (type <= local) {
- return (tcflag_t*) (((char*)mode) + tcflag_offsets[type]);
- }
- return NULL;
-}
-
static void set_speed_or_die(enum speed_setting type, const char *arg,
struct termios *mode)
{
@@ -1042,6 +1009,7 @@ static void do_display(const struct termios *mode, int all)
#endif
for (i = 0; i != CIDX_min; ++i) {
+ char ch;
/* If swtch is the same as susp, don't print both */
#if VSWTCH == VSUSP
if (i == CIDX_swtch)
@@ -1055,8 +1023,12 @@ static void do_display(const struct termios *mode, int all)
continue;
}
#endif
- wrapf("%s = %s;", nth_string(control_name, i),
- visible(mode->c_cc[control_info[i].offset]));
+ ch = mode->c_cc[control_info[i].offset];
+ if (ch == _POSIX_VDISABLE)
+ strcpy(G.buf, "<undef>");
+ else
+ visible(ch, G.buf, 0);
+ wrapf("%s = %s;", nth_string(control_name, i), G.buf);
}
#if VEOF == VMIN
if ((mode->c_lflag & ICANON) == 0)
@@ -1072,7 +1044,7 @@ static void do_display(const struct termios *mode, int all)
prev_type = mode_info[i].type;
}
- bitsp = mode_type_flag(mode_info[i].type, mode);
+ bitsp = get_ptr_to_tcflag(mode_info[i].type, mode);
mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
if ((*bitsp & mask) == mode_info[i].bits) {
if (all || (mode_info[i].flags & SANE_UNSET))
@@ -1091,7 +1063,6 @@ static void do_display(const struct termios *mode, int all)
static void sane_mode(struct termios *mode)
{
int i;
- tcflag_t *bitsp;
for (i = 0; i < NUM_control_info; ++i) {
#if VMIN == VEOF
@@ -1102,14 +1073,17 @@ static void sane_mode(struct termios *mode)
}
for (i = 0; i < NUM_mode_info; ++i) {
+ tcflag_t val;
+ tcflag_t *bitsp = get_ptr_to_tcflag(mode_info[i].type, mode);
+
+ if (!bitsp)
+ continue;
+ val = *bitsp & ~((unsigned long)mode_info[i].mask);
if (mode_info[i].flags & SANE_SET) {
- bitsp = mode_type_flag(mode_info[i].type, mode);
- *bitsp = (*bitsp & ~((unsigned long)mode_info[i].mask))
- | mode_info[i].bits;
- } else if (mode_info[i].flags & SANE_UNSET) {
- bitsp = mode_type_flag(mode_info[i].type, mode);
- *bitsp = *bitsp & ~((unsigned long)mode_info[i].mask)
- & ~mode_info[i].bits;
+ *bitsp = val | mode_info[i].bits;
+ } else
+ if (mode_info[i].flags & SANE_UNSET) {
+ *bitsp = val & ~mode_info[i].bits;
}
}
}
@@ -1119,17 +1093,18 @@ static void set_mode(const struct mode_info *info, int reversed,
{
tcflag_t *bitsp;
- bitsp = mode_type_flag(info->type, mode);
+ bitsp = get_ptr_to_tcflag(info->type, mode);
if (bitsp) {
+ tcflag_t val = *bitsp & ~info->mask;
if (reversed)
- *bitsp = *bitsp & ~info->mask & ~info->bits;
+ *bitsp = val & ~info->bits;
else
- *bitsp = (*bitsp & ~info->mask) | info->bits;
+ *bitsp = val | info->bits;
return;
}
- /* Combination mode */
+ /* !bitsp - it's a "combination" mode */
if (info == &mode_info[IDX_evenp] || info == &mode_info[IDX_parity]) {
if (reversed)
mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
@@ -1429,7 +1404,7 @@ int stty_main(int argc UNUSED_PARAM, char **argv)
perror_on_device_and_die("%s");
if (stty_state & (STTY_verbose_output | STTY_recoverable_output | STTY_noargs)) {
- get_terminal_width_height(STDOUT_FILENO, &G.max_col, NULL);
+ G.max_col = get_terminal_width(STDOUT_FILENO);
output_func(&mode, display_all);
return EXIT_SUCCESS;
}
@@ -1534,7 +1509,12 @@ int stty_main(int argc UNUSED_PARAM, char **argv)
perror_on_device_and_die("%s");
if (memcmp(&mode, &new_mode, sizeof(mode)) != 0) {
-#if CIBAUD
+/*
+ * I think the below chunk is not necessary on Linux.
+ * If you are deleting it, also delete STTY_speed_was_set bit -
+ * it is only ever checked here.
+ */
+#if 0 /* was "if CIBAUD" */
/* SunOS 4.1.3 (at least) has the problem that after this sequence,
tcgetattr (&m1); tcsetattr (&m1); tcgetattr (&m2);
sometimes (m1 != m2). The only difference is in the four bits
diff --git a/release/src/router/busybox/coreutils/sum.c b/release/src/router/busybox/coreutils/sum.c
index 95110a6da6..ec9ed2a111 100644
--- a/release/src/router/busybox/coreutils/sum.c
+++ b/release/src/router/busybox/coreutils/sum.c
@@ -21,6 +21,7 @@
//usage: "\n -s Use System V sum algorithm (512byte blocks)"
#include "libbb.h"
+#include "common_bufsiz.h"
enum { SUM_BSD, PRINT_NAME, SUM_SYSV };
@@ -30,18 +31,20 @@ enum { SUM_BSD, PRINT_NAME, SUM_SYSV };
/* Return 1 if successful. */
static unsigned sum_file(const char *file, unsigned type)
{
-#define buf bb_common_bufsiz1
unsigned long long total_bytes = 0;
int fd, r;
/* The sum of all the input bytes, modulo (UINT_MAX + 1). */
unsigned s = 0;
+#define buf bb_common_bufsiz1
+ setup_common_bufsiz();
+
fd = open_or_warn_stdin(file);
if (fd == -1)
return 0;
while (1) {
- size_t bytes_read = safe_read(fd, buf, BUFSIZ);
+ size_t bytes_read = safe_read(fd, buf, COMMON_BUFSIZE);
if ((ssize_t)bytes_read <= 0) {
r = (fd && close(fd) != 0);
@@ -70,9 +73,9 @@ static unsigned sum_file(const char *file, unsigned type)
if (type >= SUM_SYSV) {
r = (s & 0xffff) + ((s & 0xffffffff) >> 16);
s = (r & 0xffff) + (r >> 16);
- printf("%d %llu %s\n", s, (total_bytes + 511) / 512, file);
+ printf("%u %llu %s\n", s, (total_bytes + 511) / 512, file);
} else
- printf("%05d %5llu %s\n", s, (total_bytes + 1023) / 1024, file);
+ printf("%05u %5llu %s\n", s, (total_bytes + 1023) / 1024, file);
return 1;
#undef buf
}
@@ -94,8 +97,8 @@ int sum_main(int argc UNUSED_PARAM, char **argv)
n = sum_file("-", type);
} else {
/* Need to print the name if either
- - more than one file given
- - doing sysv */
+ * - more than one file given
+ * - doing sysv */
type += (argv[1] || type == SUM_SYSV);
n = 1;
do {
diff --git a/release/src/router/busybox/coreutils/sync.c b/release/src/router/busybox/coreutils/sync.c
index 7d98a1e301..974e904520 100644
--- a/release/src/router/busybox/coreutils/sync.c
+++ b/release/src/router/busybox/coreutils/sync.c
@@ -3,16 +3,39 @@
* Mini sync implementation for busybox
*
* Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
+ * Copyright (C) 2015 by Ari Sundholm <ari@tuxera.com>
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
+//config:config SYNC
+//config: bool "sync"
+//config: default y
+//config: help
+//config: sync is used to flush filesystem buffers.
+//config:config FEATURE_SYNC_FANCY
+//config: bool "Enable -d and -f flags (requres syncfs(2) in libc)"
+//config: default y
+//config: depends on SYNC
+//config: help
+//config: sync -d FILE... executes fdatasync() on each FILE.
+//config: sync -f FILE... executes syncfs() on each FILE.
+
+//kbuild:lib-$(CONFIG_SYNC) += sync.o
+//applet:IF_SYNC(APPLET_NOFORK(sync, sync, BB_DIR_BIN, BB_SUID_DROP, sync))
//usage:#define sync_trivial_usage
-//usage: ""
+//usage: ""IF_FEATURE_SYNC_FANCY("[-df] [FILE]...")
//usage:#define sync_full_usage "\n\n"
+//usage: IF_NOT_FEATURE_SYNC_FANCY(
//usage: "Write all buffered blocks to disk"
+//usage: )
+//usage: IF_FEATURE_SYNC_FANCY(
+//usage: "Write all buffered blocks (in FILEs) to disk"
+//usage: "\n -d Avoid syncing metadata"
+//usage: "\n -f Sync filesystems underlying FILEs"
+//usage: )
#include "libbb.h"
@@ -21,10 +44,59 @@
int sync_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int sync_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM))
{
+#if !ENABLE_FEATURE_SYNC_FANCY
/* coreutils-6.9 compat */
bb_warn_ignoring_args(argv[1]);
-
sync();
-
return EXIT_SUCCESS;
+#else
+ unsigned opts;
+ int ret = EXIT_SUCCESS;
+
+ enum {
+ OPT_DATASYNC = (1 << 0),
+ OPT_SYNCFS = (1 << 1),
+ };
+
+ opt_complementary = "d--f:f--d";
+ opts = getopt32(argv, "df");
+ argv += optind;
+
+ /* Handle the no-argument case. */
+ if (!argv[0])
+ sync();
+
+ while (*argv) {
+ int fd = open_or_warn(*argv, O_RDONLY);
+
+ if (fd < 0) {
+ ret = EXIT_FAILURE;
+ goto next;
+ }
+ if (opts & OPT_DATASYNC) {
+ if (fdatasync(fd))
+ goto err;
+ goto do_close;
+ }
+ if (opts & OPT_SYNCFS) {
+ /*
+ * syncfs is documented to only fail with EBADF,
+ * which can't happen here. So, no error checks.
+ */
+ syncfs(fd);
+ goto do_close;
+ }
+ if (fsync(fd)) {
+ err:
+ bb_simple_perror_msg(*argv);
+ ret = EXIT_FAILURE;
+ }
+ do_close:
+ close(fd);
+ next:
+ ++argv;
+ }
+
+ return ret;
+#endif
}
diff --git a/release/src/router/busybox/coreutils/tail.c b/release/src/router/busybox/coreutils/tail.c
index b376ec863f..39f87679e9 100644
--- a/release/src/router/busybox/coreutils/tail.c
+++ b/release/src/router/busybox/coreutils/tail.c
@@ -24,24 +24,24 @@
* 7) lseek attempted when count==0 even if arg was +0 (from top)
*/
+//kbuild:lib-$(CONFIG_TAIL) += tail.o
+
//usage:#define tail_trivial_usage
//usage: "[OPTIONS] [FILE]..."
//usage:#define tail_full_usage "\n\n"
//usage: "Print last 10 lines of each FILE (or stdin) to stdout.\n"
//usage: "With more than one FILE, precede each with a filename header.\n"
//usage: "\n -f Print data as file grows"
-//usage: IF_FEATURE_FANCY_TAIL(
-//usage: "\n -s SECONDS Wait SECONDS between reads with -f"
-//usage: )
+//usage: "\n -c [+]N[kbm] Print last N bytes"
//usage: "\n -n N[kbm] Print last N lines"
+//usage: "\n -n +N[kbm] Start on Nth line and print the rest"
//usage: IF_FEATURE_FANCY_TAIL(
-//usage: "\n -c N[kbm] Print last N bytes"
//usage: "\n -q Never print headers"
+//usage: "\n -s SECONDS Wait SECONDS between reads with -f"
//usage: "\n -v Always print headers"
+//usage: "\n -F Same as -f, but keep retrying"
//usage: "\n"
//usage: "\nN may be suffixed by k (x1024), b (x512), or m (x1024^2)."
-//usage: "\nIf N starts with a '+', output begins with the Nth item from the start"
-//usage: "\nof each file, not from the end."
//usage: )
//usage:
//usage:#define tail_example_usage
@@ -49,20 +49,14 @@
//usage: "nameserver 10.0.0.1\n"
#include "libbb.h"
-
-static const struct suffix_mult tail_suffixes[] = {
- { "b", 512 },
- { "k", 1024 },
- { "m", 1024*1024 },
- { "", 0 }
-};
+#include "common_bufsiz.h"
struct globals {
bool from_top;
bool exitcode;
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
-#define INIT_G() do { } while (0)
+#define G (*(struct globals*)bb_common_bufsiz1)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
static void tail_xprint_header(const char *fmt, const char *filename)
{
@@ -73,15 +67,6 @@ static void tail_xprint_header(const char *fmt, const char *filename)
static ssize_t tail_read(int fd, char *buf, size_t count)
{
ssize_t r;
- off_t current;
- struct stat sbuf;
-
- /* /proc files report zero st_size, don't lseek them. */
- if (fstat(fd, &sbuf) == 0 && sbuf.st_size > 0) {
- current = lseek(fd, 0, SEEK_CUR);
- if (sbuf.st_size < current)
- xlseek(fd, 0, SEEK_SET);
- }
r = full_read(fd, buf, count);
if (r < 0) {
@@ -102,7 +87,7 @@ static unsigned eat_num(const char *p)
p++;
G.from_top = 1;
}
- return xatou_sfx(p, tail_suffixes);
+ return xatou_sfx(p, bkm_suffixes);
}
int tail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -120,6 +105,7 @@ int tail_main(int argc, char **argv)
int *fds;
const char *fmt;
+ int prev_fd;
INIT_G();
@@ -324,6 +310,7 @@ int tail_main(int argc, char **argv)
xwrite(STDOUT_FILENO, tailbuf, taillen);
}
} while (++i < nfiles);
+ prev_fd = fds[i-1];
tailbuf = xrealloc(tailbuf, BUFSIZ);
@@ -367,10 +354,23 @@ int tail_main(int argc, char **argv)
if (nfiles > header_threshhold) {
fmt = header_fmt_str;
}
- while ((nread = tail_read(fd, tailbuf, BUFSIZ)) > 0) {
- if (fmt) {
+ for (;;) {
+ /* tail -f keeps following files even if they are truncated */
+ struct stat sbuf;
+ /* /proc files report zero st_size, don't lseek them */
+ if (fstat(fd, &sbuf) == 0 && sbuf.st_size > 0) {
+ off_t current = lseek(fd, 0, SEEK_CUR);
+ if (sbuf.st_size < current)
+ xlseek(fd, 0, SEEK_SET);
+ }
+
+ nread = tail_read(fd, tailbuf, BUFSIZ);
+ if (nread <= 0)
+ break;
+ if (fmt && (fd != prev_fd)) {
tail_xprint_header(fmt, filename);
fmt = NULL;
+ prev_fd = fd;
}
xwrite(STDOUT_FILENO, tailbuf, nread);
}
diff --git a/release/src/router/busybox/coreutils/tee.c b/release/src/router/busybox/coreutils/tee.c
index 48cc0508fc..a68e9446ff 100644
--- a/release/src/router/busybox/coreutils/tee.c
+++ b/release/src/router/busybox/coreutils/tee.c
@@ -23,6 +23,7 @@
//usage: "Hello\n"
#include "libbb.h"
+#include "common_bufsiz.h"
int tee_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int tee_main(int argc, char **argv)
@@ -37,6 +38,7 @@ int tee_main(int argc, char **argv)
#if ENABLE_FEATURE_TEE_USE_BLOCK_IO
ssize_t c;
# define buf bb_common_bufsiz1
+ setup_common_bufsiz();
#else
int c;
#endif
@@ -79,7 +81,7 @@ int tee_main(int argc, char **argv)
/* names[0] will be filled later */
#if ENABLE_FEATURE_TEE_USE_BLOCK_IO
- while ((c = safe_read(STDIN_FILENO, buf, sizeof(buf))) > 0) {
+ while ((c = safe_read(STDIN_FILENO, buf, COMMON_BUFSIZE)) > 0) {
fp = files;
do
fwrite(buf, 1, c, *fp);
diff --git a/release/src/router/busybox/coreutils/test.c b/release/src/router/busybox/coreutils/test.c
index 0bc008e7c8..7b8b10cd97 100644
--- a/release/src/router/busybox/coreutils/test.c
+++ b/release/src/router/busybox/coreutils/test.c
@@ -39,14 +39,9 @@
//config: help
//config: Enable 64-bit support in test.
-/* "test --help" does not print help (POSIX compat), only "[ --help" does.
- * We display "<applet> EXPRESSION ]" here (not "<applet> EXPRESSION")
- * Unfortunately, it screws up generated BusyBox.html. TODO. */
-//usage:#define test_trivial_usage
-//usage: "EXPRESSION ]"
-//usage:#define test_full_usage "\n\n"
-//usage: "Check file types, compare values etc. Return a 0/1 exit code\n"
-//usage: "depending on logical value of EXPRESSION"
+/* "test --help" is special-cased to ignore --help */
+//usage:#define test_trivial_usage NOUSAGE_STR
+//usage:#define test_full_usage ""
//usage:
//usage:#define test_example_usage
//usage: "$ test 1 -eq 2\n"
@@ -610,7 +605,7 @@ static int test_eaccess(char *path, int mode)
return 0;
/* Root can execute any file that has any one of the execute
- bits set. */
+ * bits set. */
if (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
return 0;
}
@@ -826,7 +821,6 @@ int test_main(int argc, char **argv)
{
int res;
const char *arg0;
-// bool negate = 0;
arg0 = bb_basename(argv[0]);
if (arg0[0] == '[') {
@@ -844,6 +838,7 @@ int test_main(int argc, char **argv)
}
argv[argc] = NULL;
}
+ /* argc is unused after this point */
/* We must do DEINIT_S() prior to returning */
INIT_S();
@@ -862,43 +857,45 @@ int test_main(int argc, char **argv)
*/
/*ngroups = 0; - done by INIT_S() */
- //argc--;
argv++;
+ args = argv;
- /* Implement special cases from POSIX.2, section 4.62.4 */
- if (!argv[0]) { /* "test" */
- res = 1;
- goto ret;
- }
-#if 0
-// Now it's fixed in the parser and should not be needed
- if (LONE_CHAR(argv[0], '!') && argv[1]) {
- negate = 1;
- //argc--;
- argv++;
- }
- if (!argv[1]) { /* "test [!] arg" */
- res = (*argv[0] == '\0');
- goto ret;
- }
- if (argv[2] && !argv[3]) {
- check_operator(argv[1]);
- if (last_operator->op_type == BINOP) {
- /* "test [!] arg1 <binary_op> arg2" */
- args = argv;
- res = (binop() == 0);
- goto ret;
+ /* Implement special cases from POSIX.2, section 4.62.4.
+ * Testcase: "test '(' = '('"
+ * The general parser would misinterpret '(' as group start.
+ */
+ if (1) {
+ int negate = 0;
+ again:
+ if (!argv[0]) {
+ /* "test" */
+ res = 1;
+ goto ret_special;
+ }
+ if (!argv[1]) {
+ /* "test [!] arg" */
+ res = (argv[0][0] == '\0');
+ goto ret_special;
+ }
+ if (argv[2] && !argv[3]) {
+ check_operator(argv[1]);
+ if (last_operator->op_type == BINOP) {
+ /* "test [!] arg1 <binary_op> arg2" */
+ args = argv;
+ res = (binop() == 0);
+ ret_special:
+ /* If there was leading "!" op... */
+ res ^= negate;
+ goto ret;
+ }
+ }
+ if (LONE_CHAR(argv[0], '!')) {
+ argv++;
+ negate ^= 1;
+ goto again;
}
}
- /* Some complex expression. Undo '!' removal */
- if (negate) {
- negate = 0;
- //argc++;
- argv--;
- }
-#endif
- args = argv;
res = !oexpr(check_operator(*args));
if (*args != NULL && *++args != NULL) {
@@ -911,6 +908,5 @@ int test_main(int argc, char **argv)
}
ret:
DEINIT_S();
-// return negate ? !res : res;
return res;
}
diff --git a/release/src/router/busybox/coreutils/touch.c b/release/src/router/busybox/coreutils/touch.c
index 1216ca202b..293a968907 100644
--- a/release/src/router/busybox/coreutils/touch.c
+++ b/release/src/router/busybox/coreutils/touch.c
@@ -26,6 +26,14 @@
//config: touch is used to create or change the access and/or
//config: modification timestamp of specified files.
//config:
+//config:config FEATURE_TOUCH_NODEREF
+//config: bool "Add support for -h"
+//config: default y
+//config: depends on TOUCH
+//config: help
+//config: Enable touch to have the -h option.
+//config: This requires libc support for lutimes() function.
+//config:
//config:config FEATURE_TOUCH_SUSV3
//config: bool "Add support for SUSV3 features (-d -t -r)"
//config: default y
@@ -42,6 +50,9 @@
//usage:#define touch_full_usage "\n\n"
//usage: "Update the last-modified date on the given FILE[s]\n"
//usage: "\n -c Don't create files"
+//usage: IF_FEATURE_TOUCH_NODEREF(
+//usage: "\n -h Don't follow links"
+//usage: )
//usage: IF_FEATURE_TOUCH_SUSV3(
//usage: "\n -d DT Date/time to use"
//usage: "\n -t DT Date/time to use"
@@ -65,6 +76,7 @@
* parse STRING and use it instead of current time
* -f (ignored, BSD compat)
* -m change only the modification time
+ * -h, --no-dereference
* -r, --reference=FILE
* use this file's times instead of current time
* -t STAMP
@@ -79,6 +91,13 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
int fd;
int status = EXIT_SUCCESS;
int opts;
+ enum {
+ OPT_c = (1 << 0),
+ OPT_r = (1 << 1) * ENABLE_FEATURE_TOUCH_SUSV3,
+ OPT_d = (1 << 2) * ENABLE_FEATURE_TOUCH_SUSV3,
+ OPT_t = (1 << 3) * ENABLE_FEATURE_TOUCH_SUSV3,
+ OPT_h = (1 << 4) * ENABLE_FEATURE_TOUCH_NODEREF,
+ };
#if ENABLE_FEATURE_TOUCH_SUSV3
# if ENABLE_LONG_OPTS
static const char touch_longopts[] ALIGN1 =
@@ -86,6 +105,7 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
"no-create\0" No_argument "c"
"reference\0" Required_argument "r"
"date\0" Required_argument "d"
+ IF_FEATURE_TOUCH_NODEREF("no-dereference\0" No_argument "h")
;
# endif
char *reference_file = NULL;
@@ -105,13 +125,13 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
* accepted data format differs a bit between -d and -t.
* We accept the same formats for both */
opts = getopt32(argv, "c" IF_FEATURE_TOUCH_SUSV3("r:d:t:")
+ IF_FEATURE_TOUCH_NODEREF("h")
/*ignored:*/ "fma"
IF_FEATURE_TOUCH_SUSV3(, &reference_file)
IF_FEATURE_TOUCH_SUSV3(, &date_str)
IF_FEATURE_TOUCH_SUSV3(, &date_str)
);
- opts &= 1; /* only -c bit is left */
argv += optind;
if (!*argv) {
bb_show_usage();
@@ -121,6 +141,10 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
struct stat stbuf;
xstat(reference_file, &stbuf);
timebuf[1].tv_sec = timebuf[0].tv_sec = stbuf.st_mtime;
+ /* Can use .st_mtim.tv_nsec
+ * (or is it .st_mtimensec?? see date.c)
+ * to set microseconds too.
+ */
}
if (date_str) {
@@ -141,9 +165,16 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
}
do {
- if (utimes(*argv, (reference_file || date_str) ? timebuf : NULL) != 0) {
- if (errno == ENOENT) { /* no such file */
- if (opts) { /* creation is disabled, so ignore */
+ int result;
+ result = (
+#if ENABLE_FEATURE_TOUCH_NODEREF
+ (opts & OPT_h) ? lutimes :
+#endif
+ utimes)(*argv, (reference_file || date_str) ? timebuf : NULL);
+ if (result != 0) {
+ if (errno == ENOENT) { /* no such file? */
+ if (opts & OPT_c) {
+ /* Creation is disabled, so ignore */
continue;
}
/* Try to create the file */
diff --git a/release/src/router/busybox/coreutils/tr.c b/release/src/router/busybox/coreutils/tr.c
index e67948a36c..2f49d5a86a 100644
--- a/release/src/router/busybox/coreutils/tr.c
+++ b/release/src/router/busybox/coreutils/tr.c
@@ -91,7 +91,6 @@ static void map(char *pvector,
* Character classes, e.g. [:upper:] ==> A...Z
* Equiv classess, e.g. [=A=] ==> A (hmmmmmmm?)
* not supported:
- * \ooo-\ooo - octal ranges
* [x*N] - repeat char x N times
* [x*] - repeat char x until it fills STRING2:
* # echo qwe123 | /usr/bin/tr 123456789 '[d]'
@@ -99,7 +98,7 @@ static void map(char *pvector,
* # echo qwe123 | /usr/bin/tr 123456789 '[d*]'
* qweddd
*/
-static unsigned expand(const char *arg, char **buffer_p)
+static unsigned expand(char *arg, char **buffer_p)
{
char *buffer = *buffer_p;
unsigned pos = 0;
@@ -113,9 +112,17 @@ static unsigned expand(const char *arg, char **buffer_p)
*buffer_p = buffer = xrealloc(buffer, size);
}
if (*arg == '\\') {
+ const char *z;
arg++;
- buffer[pos++] = bb_process_escape_sequence(&arg);
- continue;
+ z = arg;
+ ac = bb_process_escape_sequence(&z);
+ arg = (char *)z;
+ arg--;
+ *arg = ac;
+ /*
+ * fall through, there may be a range.
+ * If not, current char will be treated anyway.
+ */
}
if (arg[1] == '-') { /* "0-9..." */
ac = arg[2];
@@ -124,9 +131,15 @@ static unsigned expand(const char *arg, char **buffer_p)
continue; /* next iter will copy '-' and stop */
}
i = (unsigned char) *arg;
+ arg += 3; /* skip 0-9 or 0-\ */
+ if (ac == '\\') {
+ const char *z;
+ z = arg;
+ ac = bb_process_escape_sequence(&z);
+ arg = (char *)z;
+ }
while (i <= ac) /* ok: i is unsigned _int_ */
buffer[pos++] = i++;
- arg += 3; /* skip 0-9 */
continue;
}
if ((ENABLE_FEATURE_TR_CLASSES || ENABLE_FEATURE_TR_EQUIV)
diff --git a/release/src/router/busybox/coreutils/true.c b/release/src/router/busybox/coreutils/true.c
index 382e476a8f..89f892961f 100644
--- a/release/src/router/busybox/coreutils/true.c
+++ b/release/src/router/busybox/coreutils/true.c
@@ -10,11 +10,9 @@
/* BB_AUDIT SUSv3 compliant */
/* http://www.opengroup.org/onlinepubs/007904975/utilities/true.html */
-//usage:#define true_trivial_usage
-//usage: ""
-//usage:#define true_full_usage "\n\n"
-//usage: "Return an exit code of TRUE (0)"
-//usage:
+/* "true --help" is special-cased to ignore --help */
+//usage:#define true_trivial_usage NOUSAGE_STR
+//usage:#define true_full_usage ""
//usage:#define true_example_usage
//usage: "$ true\n"
//usage: "$ echo $?\n"
diff --git a/release/src/router/busybox/coreutils/truncate.c b/release/src/router/busybox/coreutils/truncate.c
new file mode 100644
index 0000000000..8d845f218b
--- /dev/null
+++ b/release/src/router/busybox/coreutils/truncate.c
@@ -0,0 +1,87 @@
+/*
+ * Mini truncate implementation for busybox
+ *
+ * Copyright (C) 2015 by Ari Sundholm <ari@tuxera.com>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+//config:config TRUNCATE
+//config: bool "truncate"
+//config: default y
+//config: help
+//config: truncate truncates files to a given size. If a file does
+//config: not exist, it is created unless told otherwise.
+
+//kbuild:lib-$(CONFIG_TRUNCATE) += truncate.o
+//applet:IF_TRUNCATE(APPLET_NOFORK(truncate, truncate, BB_DIR_USR_BIN, BB_SUID_DROP, truncate))
+
+//usage:#define truncate_trivial_usage
+//usage: "[-c] -s SIZE FILE..."
+//usage:#define truncate_full_usage "\n\n"
+//usage: "Truncate FILEs to the given size\n"
+//usage: "\n -c Do not create files"
+//usage: "\n -s SIZE Truncate to SIZE"
+//usage:
+//usage:#define truncate_example_usage
+//usage: "$ truncate -s 1G foo"
+
+#include "libbb.h"
+
+#if ENABLE_LFS
+# define XATOU_SFX xatoull_sfx
+#else
+# define XATOU_SFX xatoul_sfx
+#endif
+
+/* This is a NOFORK applet. Be very careful! */
+
+int truncate_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int truncate_main(int argc UNUSED_PARAM, char **argv)
+{
+ unsigned opts;
+ int flags = O_WRONLY | O_NONBLOCK;
+ int ret = EXIT_SUCCESS;
+ char *size_str;
+ off_t size;
+
+ enum {
+ OPT_NOCREATE = (1 << 0),
+ OPT_SIZE = (1 << 1),
+ };
+
+ opt_complementary = "s:-1";
+ opts = getopt32(argv, "cs:", &size_str);
+
+ if (!(opts & OPT_NOCREATE))
+ flags |= O_CREAT;
+
+ // TODO: coreutils 8.17 also support "m" (lowercase) suffix
+ // with truncate, but not with dd!
+ // We share kMG_suffixes[], so we can't make both tools
+ // compatible at once...
+ size = XATOU_SFX(size_str, kMG_suffixes);
+
+ argv += optind;
+ while (*argv) {
+ int fd = open(*argv, flags, 0666);
+ if (fd < 0) {
+ if (errno != ENOENT || !(opts & OPT_NOCREATE)) {
+ bb_perror_msg("%s: open", *argv);
+ ret = EXIT_FAILURE;
+ }
+ /* else: ENOENT && OPT_NOCREATE:
+ * do not report error, exitcode is also 0.
+ */
+ } else {
+ if (ftruncate(fd, size) == -1) {
+ bb_perror_msg("%s: truncate", *argv);
+ ret = EXIT_FAILURE;
+ }
+ xclose(fd);
+ }
+ ++argv;
+ }
+
+ return ret;
+}
diff --git a/release/src/router/busybox/coreutils/uname.c b/release/src/router/busybox/coreutils/uname.c
index b96d76b6c3..fd677d27ca 100644
--- a/release/src/router/busybox/coreutils/uname.c
+++ b/release/src/router/busybox/coreutils/uname.c
@@ -49,16 +49,18 @@
*/
//usage:#define uname_trivial_usage
-//usage: "[-amnrspv]"
+//usage: "[-amnrspvio]"
//usage:#define uname_full_usage "\n\n"
//usage: "Print system information\n"
//usage: "\n -a Print all"
//usage: "\n -m The machine (hardware) type"
//usage: "\n -n Hostname"
-//usage: "\n -r OS release"
-//usage: "\n -s OS name (default)"
+//usage: "\n -r Kernel release"
+//usage: "\n -s Kernel name (default)"
//usage: "\n -p Processor type"
-//usage: "\n -v OS version"
+//usage: "\n -v Kernel version"
+//usage: "\n -i The hardware platform"
+//usage: "\n -o OS name"
//usage:
//usage:#define uname_example_usage
//usage: "$ uname -a\n"
@@ -72,7 +74,7 @@ typedef struct {
struct utsname name;
char processor[sizeof(((struct utsname*)NULL)->machine)];
char platform[sizeof(((struct utsname*)NULL)->machine)];
- char os[sizeof("GNU/Linux")];
+ char os[sizeof(CONFIG_UNAME_OSNAME)];
} uname_info_t;
static const char options[] ALIGN1 = "snrvmpioa";
@@ -139,7 +141,7 @@ int uname_main(int argc UNUSED_PARAM, char **argv)
#endif
strcpy(uname_info.processor, unknown_str);
strcpy(uname_info.platform, unknown_str);
- strcpy(uname_info.os, "GNU/Linux");
+ strcpy(uname_info.os, CONFIG_UNAME_OSNAME);
#if 0
/* Fedora does something like this */
strcpy(uname_info.processor, uname_info.name.machine);
diff --git a/release/src/router/busybox/coreutils/uniq.c b/release/src/router/busybox/coreutils/uniq.c
index 9208d34ec4..e0133998a5 100644
--- a/release/src/router/busybox/coreutils/uniq.c
+++ b/release/src/router/busybox/coreutils/uniq.c
@@ -112,7 +112,7 @@ int uniq_main(int argc UNUSED_PARAM, char **argv)
/* %7lu matches GNU coreutils 6.9 */
printf("%7lu ", dups + 1);
}
- printf("%s\n", old_line);
+ puts(old_line);
}
free(old_line);
}
diff --git a/release/src/router/busybox/coreutils/unlink.c b/release/src/router/busybox/coreutils/unlink.c
new file mode 100644
index 0000000000..3b7d0fb2ba
--- /dev/null
+++ b/release/src/router/busybox/coreutils/unlink.c
@@ -0,0 +1,34 @@
+/* vi: set sw=4 ts=4: */
+/* unlink for busybox
+ *
+ * Copyright (C) 2014 Isaac Dunham <ibid.ag@gmail.com>
+ *
+ * Licensed under GPLv2, see LICENSE in this source tree
+ */
+
+//config:config UNLINK
+//config: bool "unlink"
+//config: default y
+//config: help
+//config: unlink deletes a file by calling unlink()
+
+//kbuild:lib-$(CONFIG_UNLINK) += unlink.o
+
+//applet:IF_UNLINK(APPLET(unlink, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//usage:#define unlink_trivial_usage
+//usage: "FILE"
+//usage:#define unlink_full_usage "\n\n"
+//usage: "Delete FILE by calling unlink()"
+
+#include "libbb.h"
+
+int unlink_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int unlink_main(int argc UNUSED_PARAM, char **argv)
+{
+ opt_complementary = "=1"; /* must have exactly 1 param */
+ getopt32(argv, "");
+ argv += optind;
+ xunlink(argv[0]);
+ return 0;
+}
diff --git a/release/src/router/busybox/coreutils/uudecode.c b/release/src/router/busybox/coreutils/uudecode.c
index b298fcb953..37b254d301 100644
--- a/release/src/router/busybox/coreutils/uudecode.c
+++ b/release/src/router/busybox/coreutils/uudecode.c
@@ -29,9 +29,19 @@ static void FAST_FUNC read_stduu(FILE *src_stream, FILE *dst_stream, int flags U
{
char *line;
- while ((line = xmalloc_fgetline(src_stream)) != NULL) {
+ for (;;) {
int encoded_len, str_len;
char *line_ptr, *dst;
+ size_t line_len;
+
+ line_len = 64 * 1024;
+ line = xmalloc_fgets_str_len(src_stream, "\n", &line_len);
+ if (!line)
+ break;
+ /* Handle both Unix and MSDOS text, and stray trailing spaces */
+ str_len = line_len;
+ while (--str_len >= 0 && isspace(line[str_len]))
+ line[str_len] = '\0';
if (strcmp(line, "end") == 0) {
return; /* the only non-error exit */
@@ -46,7 +56,7 @@ static void FAST_FUNC read_stduu(FILE *src_stream, FILE *dst_stream, int flags U
encoded_len = line[0] * 4 / 3;
/* Check that line is not too short. (we tolerate
- * overly _long_ line to accomodate possible extra '`').
+ * overly _long_ line to accommodate possible extra '`').
* Empty line case is also caught here. */
if (str_len <= encoded_len) {
break; /* go to bb_error_msg_and_die("short file"); */
@@ -110,10 +120,10 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv)
FILE *dst_stream;
int mode;
- if (strncmp(line, "begin-base64 ", 13) == 0) {
+ if (is_prefixed_with(line, "begin-base64 ")) {
line_ptr = line + 13;
decode_fn_ptr = read_base64;
- } else if (strncmp(line, "begin ", 6) == 0) {
+ } else if (is_prefixed_with(line, "begin ")) {
line_ptr = line + 6;
decode_fn_ptr = read_stduu;
} else {
@@ -128,6 +138,7 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv)
if (!outname)
break;
outname++;
+ trim(outname); /* remove trailing space (and '\r' for DOS text) */
if (!outname[0])
break;
}
diff --git a/release/src/router/busybox/coreutils/who.c b/release/src/router/busybox/coreutils/who.c
index f955ce6d35..f694d0c603 100644
--- a/release/src/router/busybox/coreutils/who.c
+++ b/release/src/router/busybox/coreutils/who.c
@@ -73,7 +73,7 @@ static void idle_string(char *str6, time_t t)
int who_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int who_main(int argc UNUSED_PARAM, char **argv)
{
- struct utmp *ut;
+ struct utmpx *ut;
unsigned opt;
int do_users = (ENABLE_USERS && (!ENABLE_WHO || applet_name[0] == 'u'));
const char *fmt = "%s";
@@ -81,10 +81,10 @@ int who_main(int argc UNUSED_PARAM, char **argv)
opt_complementary = "=0";
opt = getopt32(argv, do_users ? "" : "aH");
if (opt & 2) // -H
- printf("USER\t\tTTY\t\tIDLE\tTIME\t\t HOST\n");
+ puts("USER\t\tTTY\t\tIDLE\tTIME\t\t HOST");
- setutent();
- while ((ut = getutent()) != NULL) {
+ setutxent();
+ while ((ut = getutxent()) != NULL) {
if (ut->ut_user[0]
&& ((opt & 1) || ut->ut_type == USER_PROCESS)
) {
@@ -126,6 +126,6 @@ int who_main(int argc UNUSED_PARAM, char **argv)
if (do_users)
bb_putchar('\n');
if (ENABLE_FEATURE_CLEAN_UP)
- endutent();
+ endutxent();
return EXIT_SUCCESS;
}
diff --git a/release/src/router/busybox/debianutils/Config.src b/release/src/router/busybox/debianutils/Config.src
index cbc09b5ce4..61daeb0478 100644
--- a/release/src/router/busybox/debianutils/Config.src
+++ b/release/src/router/busybox/debianutils/Config.src
@@ -7,79 +7,4 @@ menu "Debian Utilities"
INSERT
-config MKTEMP
- bool "mktemp"
- default y
- help
- mktemp is used to create unique temporary files
-
-config PIPE_PROGRESS
- bool "pipe_progress"
- default y
- help
- Display a dot to indicate pipe activity.
-
-config RUN_PARTS
- bool "run-parts"
- default y
- help
- run-parts is a utility designed to run all the scripts in a directory.
-
- It is useful to set up a directory like cron.daily, where you need to
- execute all the scripts in that directory.
-
- In this implementation of run-parts some features (such as report
- mode) are not implemented.
-
- Unless you know that run-parts is used in some of your scripts
- you can safely say N here.
-
-config FEATURE_RUN_PARTS_LONG_OPTIONS
- bool "Enable long options"
- default y
- depends on RUN_PARTS && LONG_OPTS
- help
- Support long options for the run-parts applet.
-
-config FEATURE_RUN_PARTS_FANCY
- bool "Support additional arguments"
- default y
- depends on RUN_PARTS
- help
- Support additional options:
- -l --list print the names of the all matching files (not
- limited to executables), but don't actually run them.
-
-config START_STOP_DAEMON
- bool "start-stop-daemon"
- default y
- help
- start-stop-daemon is used to control the creation and
- termination of system-level processes, usually the ones
- started during the startup of the system.
-
-config FEATURE_START_STOP_DAEMON_FANCY
- bool "Support additional arguments"
- default y
- depends on START_STOP_DAEMON
- help
- Support additional arguments.
- -o|--oknodo ignored since we exit with 0 anyway
- -v|--verbose
- -N|--nicelevel N
-
-config FEATURE_START_STOP_DAEMON_LONG_OPTIONS
- bool "Enable long options"
- default y
- depends on START_STOP_DAEMON && LONG_OPTS
- help
- Support long options for the start-stop-daemon applet.
-
-config WHICH
- bool "which"
- default y
- help
- which is used to find programs in your PATH and
- print out their pathnames.
-
endmenu
diff --git a/release/src/router/busybox/debianutils/Kbuild.src b/release/src/router/busybox/debianutils/Kbuild.src
index d41b5c8e40..6b4fb74700 100644
--- a/release/src/router/busybox/debianutils/Kbuild.src
+++ b/release/src/router/busybox/debianutils/Kbuild.src
@@ -7,8 +7,3 @@
lib-y:=
INSERT
-lib-$(CONFIG_MKTEMP) += mktemp.o
-lib-$(CONFIG_PIPE_PROGRESS) += pipe_progress.o
-lib-$(CONFIG_RUN_PARTS) += run_parts.o
-lib-$(CONFIG_START_STOP_DAEMON) += start_stop_daemon.o
-lib-$(CONFIG_WHICH) += which.o
diff --git a/release/src/router/busybox/debianutils/mktemp.c b/release/src/router/busybox/debianutils/mktemp.c
index dbe4309555..65353697a7 100644
--- a/release/src/router/busybox/debianutils/mktemp.c
+++ b/release/src/router/busybox/debianutils/mktemp.c
@@ -30,6 +30,15 @@
* a directory: $TMPDIR, if set; else the directory specified via
* -p; else /tmp [deprecated]
*/
+//config:config MKTEMP
+//config: bool "mktemp"
+//config: default y
+//config: help
+//config: mktemp is used to create unique temporary files
+
+//applet:IF_MKTEMP(APPLET(mktemp, BB_DIR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_MKTEMP) += mktemp.o
//usage:#define mktemp_trivial_usage
//usage: "[-dt] [-p DIR] [TEMPLATE]"
@@ -38,7 +47,7 @@
//usage: "TEMPLATE must end with XXXXXX (e.g. [/dir/]nameXXXXXX).\n"
//usage: "Without TEMPLATE, -t tmp.XXXXXX is assumed.\n"
//usage: "\n -d Make directory, not file"
-////usage: "\n -q Fail silently on errors" - we ignore this opt
+//usage: "\n -q Fail silently on errors"
//usage: "\n -t Prepend base directory name to TEMPLATE"
//usage: "\n -p DIR Use DIR as a base directory (implies -t)"
//usage: "\n -u Do not create anything; print a name"
@@ -71,7 +80,6 @@ int mktemp_main(int argc UNUSED_PARAM, char **argv)
if (!path || path[0] == '\0')
path = "/tmp";
- /* -q is ignored */
opt_complementary = "?1"; /* 1 argument max */
opts = getopt32(argv, "dqtp:u", &path);
@@ -83,33 +91,32 @@ int mktemp_main(int argc UNUSED_PARAM, char **argv)
chp = xstrdup("tmp.XXXXXX");
opts |= OPT_t;
}
-
- if (opts & OPT_u) {
- /* Remove (up to) 6 X's */
- unsigned len = strlen(chp);
- int cnt = len > 6 ? 6 : len;
- while (--cnt >= 0 && chp[--len] == 'X')
- chp[len] = '\0';
-
- chp = tempnam(opts & (OPT_t|OPT_p) ? path : "./", chp);
- if (!chp)
- return EXIT_FAILURE;
- if (!(opts & (OPT_t|OPT_p)))
- chp += 2;
- goto ret;
+#if 0
+ /* Don't allow directory separator in template */
+ if ((opts & OPT_t) && bb_basename(chp) != chp) {
+ errno = EINVAL;
+ goto error;
}
-
+#endif
if (opts & (OPT_t|OPT_p))
chp = concat_path_file(path, chp);
- if (opts & OPT_d) {
+ if (opts & OPT_u) {
+ chp = mktemp(chp);
+ if (chp[0] == '\0')
+ goto error;
+ } else if (opts & OPT_d) {
if (mkdtemp(chp) == NULL)
- return EXIT_FAILURE;
+ goto error;
} else {
if (mkstemp(chp) < 0)
- return EXIT_FAILURE;
+ goto error;
}
- ret:
puts(chp);
return EXIT_SUCCESS;
+ error:
+ if (opts & OPT_q)
+ return EXIT_FAILURE;
+ /* don't use chp as it gets mangled in case of error */
+ bb_perror_nomsg_and_die();
}
diff --git a/release/src/router/busybox/debianutils/pipe_progress.c b/release/src/router/busybox/debianutils/pipe_progress.c
index 2c7444f311..21d330b594 100644
--- a/release/src/router/busybox/debianutils/pipe_progress.c
+++ b/release/src/router/busybox/debianutils/pipe_progress.c
@@ -6,6 +6,15 @@
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//config:config PIPE_PROGRESS
+//config: bool "pipe_progress"
+//config: default y
+//config: help
+//config: Display a dot to indicate pipe activity.
+
+//applet:IF_PIPE_PROGRESS(APPLET(pipe_progress, BB_DIR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_PIPE_PROGRESS) += pipe_progress.o
//usage:#define pipe_progress_trivial_usage NOUSAGE_STR
//usage:#define pipe_progress_full_usage ""
diff --git a/release/src/router/busybox/debianutils/run_parts.c b/release/src/router/busybox/debianutils/run_parts.c
index 8f08f6dc66..c671b9252a 100644
--- a/release/src/router/busybox/debianutils/run_parts.c
+++ b/release/src/router/busybox/debianutils/run_parts.c
@@ -4,14 +4,13 @@
*
* Copyright (C) 2007 Bernhard Reutner-Fischer
*
- * Based on a older version that was in busybox which was 1k big..
+ * Based on a older version that was in busybox which was 1k big.
* Copyright (C) 2001 by Emanuele Aina <emanuele.aina@tiscali.it>
*
* Based on the Debian run-parts program, version 1.15
* Copyright (C) 1996 Jeff Noxon <jeff@router.patch.net>,
* Copyright (C) 1996-1999 Guy Maor <maor@debian.org>
*
- *
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
@@ -19,26 +18,60 @@
* attempt to write a program! :-) . */
/* This piece of code is heavily based on the original version of run-parts,
- * taken from debian-utils. I've only removed the long options and a the
+ * taken from debian-utils. I've only removed the long options and the
* report mode. As the original run-parts support only long options, I've
* broken compatibility because the BusyBox policy doesn't allow them.
- * The supported options are:
- * -t test. Print the name of the files to be executed, without
- * execute them.
- * -a ARG argument. Pass ARG as an argument the program executed. It can
- * be repeated to pass multiple arguments.
- * -u MASK umask. Set the umask of the program executed to MASK.
*/
+//config:config RUN_PARTS
+//config: bool "run-parts"
+//config: default y
+//config: help
+//config: run-parts is a utility designed to run all the scripts in a directory.
+//config:
+//config: It is useful to set up a directory like cron.daily, where you need to
+//config: execute all the scripts in that directory.
+//config:
+//config: In this implementation of run-parts some features (such as report
+//config: mode) are not implemented.
+//config:
+//config: Unless you know that run-parts is used in some of your scripts
+//config: you can safely say N here.
+//config:
+//config:config FEATURE_RUN_PARTS_LONG_OPTIONS
+//config: bool "Enable long options"
+//config: default y
+//config: depends on RUN_PARTS && LONG_OPTS
+//config: help
+//config: Support long options for the run-parts applet.
+//config:
+//config:config FEATURE_RUN_PARTS_FANCY
+//config: bool "Support additional arguments"
+//config: default y
+//config: depends on RUN_PARTS
+//config: help
+//config: Support additional options:
+//config: -l --list print the names of the all matching files (not
+//config: limited to executables), but don't actually run them.
+
+//applet:IF_RUN_PARTS(APPLET_ODDNAME(run-parts, run_parts, BB_DIR_BIN, BB_SUID_DROP, run_parts))
+
+//kbuild:lib-$(CONFIG_RUN_PARTS) += run_parts.o
//usage:#define run_parts_trivial_usage
-//usage: "[-t] "IF_FEATURE_RUN_PARTS_FANCY("[-l] ")"[-a ARG] [-u MASK] DIRECTORY"
+//usage: "[-a ARG]... [-u UMASK] "
+//usage: IF_FEATURE_RUN_PARTS_LONG_OPTIONS("[--reverse] [--test] [--exit-on-error] "IF_FEATURE_RUN_PARTS_FANCY("[--list] "))
+//usage: "DIRECTORY"
//usage:#define run_parts_full_usage "\n\n"
//usage: "Run a bunch of scripts in DIRECTORY\n"
-//usage: "\n -t Print what would be run, but don't actually run anything"
-//usage: "\n -a ARG Pass ARG as argument for every program"
-//usage: "\n -u MASK Set the umask to MASK before running every program"
+//usage: "\n -a ARG Pass ARG as argument to scripts"
+//usage: "\n -u UMASK Set UMASK before running scripts"
+//usage: IF_FEATURE_RUN_PARTS_LONG_OPTIONS(
+//usage: "\n --reverse Reverse execution order"
+//usage: "\n --test Dry run"
+//usage: "\n --exit-on-error Exit if a script exits with non-zero"
//usage: IF_FEATURE_RUN_PARTS_FANCY(
-//usage: "\n -l Print names of all matching files even if they are not executable"
+//usage: "\n --list Print names of matching files even if they are not executable"
+//usage: )
//usage: )
//usage:
//usage:#define run_parts_example_usage
@@ -56,34 +89,31 @@
//usage: "+ shutdown -h +4m"
#include "libbb.h"
+#include "common_bufsiz.h"
struct globals {
char **names;
int cur;
- char *cmd[1];
+ char *cmd[2 /* using 1 provokes compiler warning */];
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define names (G.names)
#define cur (G.cur )
#define cmd (G.cmd )
-#define INIT_G() do { } while (0)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
enum { NUM_CMD = (COMMON_BUFSIZE - sizeof(G)) / sizeof(cmd[0]) - 1 };
enum {
- OPT_r = (1 << 0),
- OPT_a = (1 << 1),
- OPT_u = (1 << 2),
- OPT_t = (1 << 3),
- OPT_l = (1 << 4) * ENABLE_FEATURE_RUN_PARTS_FANCY,
+ OPT_a = (1 << 0),
+ OPT_u = (1 << 1),
+ OPT_r = (1 << 2) * ENABLE_FEATURE_RUN_PARTS_LONG_OPTIONS,
+ OPT_t = (1 << 3) * ENABLE_FEATURE_RUN_PARTS_LONG_OPTIONS,
+ OPT_e = (1 << 4) * ENABLE_FEATURE_RUN_PARTS_LONG_OPTIONS,
+ OPT_l = (1 << 5) * ENABLE_FEATURE_RUN_PARTS_LONG_OPTIONS
+ * ENABLE_FEATURE_RUN_PARTS_FANCY,
};
-#if ENABLE_FEATURE_RUN_PARTS_FANCY
-#define list_mode (option_mask32 & OPT_l)
-#else
-#define list_mode 0
-#endif
-
/* Is this a valid filename (upper/lower alpha, digits,
* underscores, and hyphens only?)
*/
@@ -111,7 +141,7 @@ static int FAST_FUNC act(const char *file, struct stat *statbuf, void *args UNUS
if (depth == 2
&& ( !(statbuf->st_mode & (S_IFREG | S_IFLNK))
|| invalid_name(file)
- || (!list_mode && access(file, X_OK) != 0))
+ || (!(option_mask32 & OPT_l) && access(file, X_OK) != 0))
) {
return SKIP;
}
@@ -127,11 +157,12 @@ static int FAST_FUNC act(const char *file, struct stat *statbuf, void *args UNUS
static const char runparts_longopts[] ALIGN1 =
"arg\0" Required_argument "a"
"umask\0" Required_argument "u"
- "test\0" No_argument "t"
-#if ENABLE_FEATURE_RUN_PARTS_FANCY
- "list\0" No_argument "l"
- "reverse\0" No_argument "r"
//TODO: "verbose\0" No_argument "v"
+ "reverse\0" No_argument "\xf0"
+ "test\0" No_argument "\xf1"
+ "exit-on-error\0" No_argument "\xf2"
+#if ENABLE_FEATURE_RUN_PARTS_FANCY
+ "list\0" No_argument "\xf3"
#endif
;
#endif
@@ -151,7 +182,7 @@ int run_parts_main(int argc UNUSED_PARAM, char **argv)
#endif
/* We require exactly one argument: the directory name */
opt_complementary = "=1:a::";
- getopt32(argv, "ra:u:t"IF_FEATURE_RUN_PARTS_FANCY("l"), &arg_list, &umask_p);
+ getopt32(argv, "a:u:", &arg_list, &umask_p);
umask(xstrtou_range(umask_p, 8, 0, 07777));
@@ -193,7 +224,10 @@ int run_parts_main(int argc UNUSED_PARAM, char **argv)
if (ret < 0)
bb_perror_msg("can't execute '%s'", name);
else /* ret > 0 */
- bb_error_msg("%s exited with code %d", name, ret & 0xff);
+ bb_error_msg("%s: exit status %u", name, ret & 0xff);
+
+ if (option_mask32 & OPT_e)
+ xfunc_die();
}
return n;
diff --git a/release/src/router/busybox/debianutils/start_stop_daemon.c b/release/src/router/busybox/debianutils/start_stop_daemon.c
index 7dadc3c9ee..3625ffee88 100644
--- a/release/src/router/busybox/debianutils/start_stop_daemon.c
+++ b/release/src/router/busybox/debianutils/start_stop_daemon.c
@@ -56,6 +56,34 @@ Misc options:
-q,--quiet Quiet
-v,--verbose Verbose
*/
+//config:config START_STOP_DAEMON
+//config: bool "start-stop-daemon"
+//config: default y
+//config: help
+//config: start-stop-daemon is used to control the creation and
+//config: termination of system-level processes, usually the ones
+//config: started during the startup of the system.
+//config:
+//config:config FEATURE_START_STOP_DAEMON_FANCY
+//config: bool "Support additional arguments"
+//config: default y
+//config: depends on START_STOP_DAEMON
+//config: help
+//config: Support additional arguments.
+//config: -o|--oknodo ignored since we exit with 0 anyway
+//config: -v|--verbose
+//config: -N|--nicelevel N
+//config:
+//config:config FEATURE_START_STOP_DAEMON_LONG_OPTIONS
+//config: bool "Enable long options"
+//config: default y
+//config: depends on START_STOP_DAEMON && LONG_OPTS
+//config: help
+//config: Support long options for the start-stop-daemon applet.
+
+//applet:IF_START_STOP_DAEMON(APPLET_ODDNAME(start-stop-daemon, start_stop_daemon, BB_DIR_SBIN, BB_SUID_DROP, start_stop_daemon))
+
+//kbuild:lib-$(CONFIG_START_STOP_DAEMON) += start_stop_daemon.o
//usage:#define start_stop_daemon_trivial_usage
//usage: "[OPTIONS] [-S|-K] ... [-- ARGS...]"
@@ -125,6 +153,7 @@ Misc options:
/* Override ENABLE_FEATURE_PIDFILE */
#define WANT_PIDFILE 1
#include "libbb.h"
+#include "common_bufsiz.h"
struct pid_list {
struct pid_list *next;
@@ -163,7 +192,7 @@ struct globals {
int user_id;
smallint signal_nr;
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define userspec (G.userspec )
#define cmdname (G.cmdname )
#define execname (G.execname )
@@ -171,6 +200,7 @@ struct globals {
#define user_id (G.user_id )
#define signal_nr (G.signal_nr )
#define INIT_G() do { \
+ setup_common_bufsiz(); \
user_id = -1; \
signal_nr = 15; \
} while (0)
@@ -511,15 +541,15 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
write_pidfile(pidfile);
}
if (opt & OPT_c) {
- struct bb_uidgid_t ugid = { -1, -1 };
+ struct bb_uidgid_t ugid;
parse_chown_usergroup_or_die(&ugid, chuid);
- if (ugid.uid != (uid_t) -1) {
+ if (ugid.uid != (uid_t) -1L) {
struct passwd *pw = xgetpwuid(ugid.uid);
- if (ugid.gid != (gid_t) -1)
+ if (ugid.gid != (gid_t) -1L)
pw->pw_gid = ugid.gid;
/* initgroups, setgid, setuid: */
change_identity(pw);
- } else if (ugid.gid != (gid_t) -1) {
+ } else if (ugid.gid != (gid_t) -1L) {
xsetgid(ugid.gid);
setgroups(1, &ugid.gid);
}
diff --git a/release/src/router/busybox/debianutils/which.c b/release/src/router/busybox/debianutils/which.c
index 15fd598b78..c0f8978098 100644
--- a/release/src/router/busybox/debianutils/which.c
+++ b/release/src/router/busybox/debianutils/which.c
@@ -1,14 +1,20 @@
/* vi: set sw=4 ts=4: */
/*
- * Which implementation for busybox
- *
* Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
* Copyright (C) 2006 Gabriel Somlo <somlo at cmu.edu>
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
- *
- * Based on which from debianutils
*/
+//config:config WHICH
+//config: bool "which"
+//config: default y
+//config: help
+//config: which is used to find programs in your PATH and
+//config: print out their pathnames.
+
+//applet:IF_WHICH(APPLET(which, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_WHICH) += which.o
//usage:#define which_trivial_usage
//usage: "[COMMAND]..."
@@ -24,76 +30,43 @@
int which_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int which_main(int argc UNUSED_PARAM, char **argv)
{
- IF_DESKTOP(int opt;)
- int status = EXIT_SUCCESS;
- char *path;
- char *p;
+ const char *env_path;
+ int status = 0;
+
+ env_path = getenv("PATH");
+ if (!env_path)
+ env_path = bb_default_root_path;
opt_complementary = "-1"; /* at least one argument */
- IF_DESKTOP(opt =) getopt32(argv, "a");
+ getopt32(argv, "a");
argv += optind;
- /* This matches what is seen on e.g. ubuntu.
- * "which" there is a shell script. */
- path = getenv("PATH");
- if (!path) {
- path = (char*)bb_PATH_root_path;
- putenv(path);
- path += 5; /* skip "PATH=" */
- }
-
do {
-#if ENABLE_DESKTOP
-/* Much bloat just to support -a */
- if (strchr(*argv, '/')) {
- if (execable_file(*argv)) {
- puts(*argv);
- continue;
- }
- status = EXIT_FAILURE;
- } else {
- char *path2 = xstrdup(path);
- char *tmp = path2;
+ int missing = 1;
- p = find_execable(*argv, &tmp);
- if (!p)
- status = EXIT_FAILURE;
- else {
- print:
- puts(p);
- free(p);
- if (opt) {
- /* -a: show matches in all PATH components */
- if (tmp) {
- p = find_execable(*argv, &tmp);
- if (p)
- goto print;
- }
- }
- }
- free(path2);
- }
-#else
-/* Just ignoring -a */
+ /* If file contains a slash don't use PATH */
if (strchr(*argv, '/')) {
- if (execable_file(*argv)) {
+ if (file_is_executable(*argv)) {
+ missing = 0;
puts(*argv);
- continue;
}
} else {
- char *path2 = xstrdup(path);
- char *tmp = path2;
- p = find_execable(*argv, &tmp);
- free(path2);
- if (p) {
+ char *path;
+ char *tmp;
+ char *p;
+
+ path = tmp = xstrdup(env_path);
+ while ((p = find_executable(*argv, &tmp)) != NULL) {
+ missing = 0;
puts(p);
free(p);
- continue;
+ if (!option_mask32) /* -a not set */
+ break;
}
+ free(path);
}
- status = EXIT_FAILURE;
-#endif
- } while (*(++argv) != NULL);
+ status |= missing;
+ } while (*++argv);
- fflush_stdout_and_exit(status);
+ return status;
}
diff --git a/release/src/router/busybox/docs/.gitignore b/release/src/router/busybox/docs/.gitignore
index 3881e011dd..3d1c5bd8ad 100644
--- a/release/src/router/busybox/docs/.gitignore
+++ b/release/src/router/busybox/docs/.gitignore
@@ -1,5 +1,4 @@
/busybox.1
-/BusyBox.1
/BusyBox.html
/busybox.net
/BusyBox.txt
diff --git a/release/src/router/busybox/docs/cgi/env.html b/release/src/router/busybox/docs/cgi/env.html
index b83c750bf1..66a548b465 100644
--- a/release/src/router/busybox/docs/cgi/env.html
+++ b/release/src/router/busybox/docs/cgi/env.html
@@ -38,7 +38,7 @@ fulfilled by the gateway program: <p>
</p><ul>
<li> <a name="protocol"><code>SERVER_PROTOCOL</code></a> <p>
- The name and revision of the information protcol this request came
+ The name and revision of the information protocol this request came
in with. Format: protocol/revision </p><p>
</p></li><li> <code>SERVER_PORT</code> <p>
diff --git a/release/src/router/busybox/docs/ifupdown_design.txt b/release/src/router/busybox/docs/ifupdown_design.txt
index 8ab4e51adc..39e28a9f45 100644
--- a/release/src/router/busybox/docs/ifupdown_design.txt
+++ b/release/src/router/busybox/docs/ifupdown_design.txt
@@ -21,7 +21,7 @@ static int dhcp_down(struct interface_defn_t *ifd, execfn *exec)
#if ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCP
int i ;
for (i = 0; i < ARRAY_SIZE(ext_dhcp_clients); i++) {
- if (exists_execable(ext_dhcp_clients[i].name))
+ if (executable_exists(ext_dhcp_clients[i].name))
return execute(ext_dhcp_clients[i].stopcmd, ifd, exec);
}
bb_error_msg("no dhcp clients found, using static interface shutdown");
diff --git a/release/src/router/busybox/docs/keep_data_small.txt b/release/src/router/busybox/docs/keep_data_small.txt
index 21d732674c..3ced1a61da 100644
--- a/release/src/router/busybox/docs/keep_data_small.txt
+++ b/release/src/router/busybox/docs/keep_data_small.txt
@@ -103,7 +103,15 @@ smaller code. In order to assign it, use SET_PTR_TO_GLOBALS macro:
SET_PTR_TO_GLOBALS(xzalloc(sizeof(G)));
-Typically it is done in <applet>_main().
+Typically it is done in <applet>_main(). Another variation is
+to use stack:
+
+int <applet>_main(...)
+{
+#undef G
+ struct globals G;
+ memset(&G, 0, sizeof(G));
+ SET_PTR_TO_GLOBALS(&G);
Now you can reference "globals" by G.a, G.buf and so on, in any function.
@@ -138,13 +146,6 @@ less readable, use #defines:
#define sector (G.sector)
- Word of caution
-
-If applet doesn't use much of global data, converting it to use
-one of above methods is not worth the resulting code obfuscation.
-If you have less than ~300 bytes of global data - don't bother.
-
-
Finding non-shared duplicated strings
strings busybox | sort | uniq -c | sort -nr
@@ -224,6 +225,14 @@ Result (non-static busybox built against glibc):
Keeping code small
+Use scripts/bloat-o-meter to check whether introduced changes
+didn't generate unnecessary bloat. This script needs unstripped binaries
+to generate a detailed report. To automate this, just use
+"make bloatcheck". It requires busybox_old binary to be present,
+use "make baseline" to generate it from unmodified source, or
+copy busybox_unstripped to busybox_old before modifying sources
+and rebuilding.
+
Set CONFIG_EXTRA_CFLAGS="-fno-inline-functions-called-once",
produce "make bloatcheck", see the biggest auto-inlined functions.
Now, set CONFIG_EXTRA_CFLAGS back to "", but add NOINLINE
diff --git a/release/src/router/busybox/docs/logging_and_backgrounding.txt b/release/src/router/busybox/docs/logging_and_backgrounding.txt
index 7e68855608..c76cd36532 100644
--- a/release/src/router/busybox/docs/logging_and_backgrounding.txt
+++ b/release/src/router/busybox/docs/logging_and_backgrounding.txt
@@ -45,6 +45,8 @@ udhcpc - auto-backgrounds unless -f after lease is obtained,
udhcpd - auto-backgrounds and do not log to stderr unless -f,
otherwise logs to stderr, but option -S makes it log *also* to syslog
zcip - auto-backgrounds and logs *also* to syslog unless -f
+ behaviour can be overridden with experimental LOGGING env.var
+ (can be set to either "none" or "syslog")
Total: 13 applets (+1 obsolete),
4 log to syslog by default (crond fakeidentd inetd zcip),
diff --git a/release/src/router/busybox/docs/mdev.txt b/release/src/router/busybox/docs/mdev.txt
index 61f93c9df1..b24025f7b7 100644
--- a/release/src/router/busybox/docs/mdev.txt
+++ b/release/src/router/busybox/docs/mdev.txt
@@ -51,9 +51,9 @@ device nodes if your system needs something more than the default root/root
660 permissions.
The file has the format:
- [-]<device regex> <uid>:<gid> <permissions>
+ [-][envmatch]<device regex> <uid>:<gid> <permissions>
or
- @<maj[,min1[-min2]]> <uid>:<gid> <permissions>
+ [envmatch]@<maj[,min1[-min2]]> <uid>:<gid> <permissions>
or
$envvar=<regex> <uid>:<gid> <permissions>
diff --git a/release/src/router/busybox/docs/new-applet-HOWTO.txt b/release/src/router/busybox/docs/new-applet-HOWTO.txt
index 6a8054d0e8..078e77bce2 100644
--- a/release/src/router/busybox/docs/new-applet-HOWTO.txt
+++ b/release/src/router/busybox/docs/new-applet-HOWTO.txt
@@ -6,7 +6,7 @@ This document details the steps you must take to add a new applet to BusyBox.
Credits:
Matt Kraai - initial writeup
Mark Whitley - the remix
-Thomas Lundquist - Trying to keep it updated.
+Thomas Lundquist - trying to keep it updated
When doing this you should consider using the latest git HEAD.
This is a good thing if you plan to getting it committed into mainline.
@@ -16,14 +16,14 @@ Initial Write
First, write your applet. Be sure to include copyright information at the top,
such as who you stole the code from and so forth. Also include the mini-GPL
-boilerplate. Be sure to name the main function <applet>_main instead of main.
-And be sure to put it in <applet>.c. Usage does not have to be taken care of by
-your applet.
-Make sure to #include "libbb.h" as the first include file in your applet.
+boilerplate and Config.in/Kbuild/usage/applet.h snippets (more on that below
+in this document). Be sure to name the main function <applet>_main instead
+of main. And be sure to put it in <applet>.c. Make sure to #include "libbb.h"
+as the first include file in your applet.
For a new applet mu, here is the code that would go in mu.c:
-(busybox.h already includes most usual header files. You do not need
+(libbb.h already includes most usual header files. You do not need
#include <stdio.h> etc...)
@@ -41,6 +41,22 @@ For a new applet mu, here is the code that would go in mu.c:
#include "libbb.h"
#include "other.h"
+//config:config MU
+//config: bool "MU"
+//config: default y
+//config: help
+//config: Returns an indeterminate value.
+
+//kbuild:lib-$(CONFIG_MU) += mu.o
+//applet:IF_MU(APPLET(mu, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//usage:#define mu_trivial_usage
+//usage: "[-abcde] FILE..."
+//usage:#define mu_full_usage
+//usage: "Returns an indeterminate value\n"
+//usage: "\n -a First function"
+//usage: "\n -b Second function"
+
int mu_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int mu_main(int argc, char **argv)
{
@@ -90,6 +106,8 @@ Make a new file named <function_name>.c
#include "libbb.h"
#include "other.h"
+//kbuild:lib-y += function.o
+
int function(char *a)
{
return *a;
@@ -97,9 +115,7 @@ int function(char *a)
----end example code------
-Add <function_name>.o in the right alphabetically sorted place
-in libbb/Kbuild.src. You should look at the conditional part of
-libbb/Kbuild.src as well.
+Remember about the kbuild snippet.
You should also try to find a suitable place in include/libbb.h for
the function declaration. If not, add it somewhere anyway, with or without
@@ -109,60 +125,68 @@ You can look at libbb/Config.src and try to find out if the function is
tunable and add it there if it is.
+Kbuild/Config.in/usage/applets.h snippets in .c files
+-----------------------------------------------------
+
+The old way of adding new applets was to put all the information needed by the
+configuration and build system into appropriate files (namely: Kbuild.src and
+Config.src in new applet's directory) and to add the applet declaration and
+usage info text to include/applets.src.h and include/usage.src.h respectively.
+
+Since the scripts/gen_build_files.sh script had been introduced, the preferred
+way is to have all these declarations contained within the applet .c files.
+
+Every line intended to be processed by gen_build_files.sh should start as a
+comment without any preceding whitespaces and be followed by an appropriate
+keyword - kbuild, config, usage or applet - and a colon, just like shown in the
+first example above.
+
+
Placement / Directory
---------------------
Find the appropriate directory for your new applet.
-Make sure you find the appropriate places in the files, the applets are
-sorted alphabetically.
+Add the kbuild snippet to the .c file:
-Add the applet to Kbuild.src in the chosen directory:
+//kbuild:lib-$(CONFIG_MU) += mu.o
-lib-$(CONFIG_MU) += mu.o
+Add the config snippet to the .c file:
-Add the applet to Config.src in the chosen directory:
-
-config MU
- bool "MU"
- default n
- help
- Returns an indeterminate value.
+//config:config MU
+//config: bool "MU"
+//config: default y
+//config: help
+//config: Returns an indeterminate value.
Usage String(s)
---------------
-Next, add usage information for you applet to include/usage.src.h.
+Next, add usage information for your applet to the .c file.
This should look like the following:
- #define mu_trivial_usage \
- "-[abcde] FILES"
- #define mu_full_usage \
- "Returns an indeterminate value.\n\n" \
- "Options:\n" \
- "\t-a\t\tfirst function\n" \
- "\t-b\t\tsecond function\n" \
- ...
+//usage:#define mu_trivial_usage
+//usage: "[-abcde] FILE..."
+//usage:#define mu_full_usage
+//usage: "Returns an indeterminate value\n"
+//usage: "\n -a First function"
+//usage: "\n -b Second function"
+//usage: ...
If your program supports flags, the flags should be mentioned on the first
-line (-[abcde]) and a detailed description of each flag should go in the
-mu_full_usage section, one flag per line. (Numerous examples of this
-currently exist in usage.src.h.)
+line ([-abcde]) and a detailed description of each flag should go in the
+mu_full_usage section, one flag per line.
Header Files
------------
-Next, add an entry to include/applets.src.h. Be *sure* to keep the list
-in alphabetical order, or else it will break the binary-search lookup
-algorithm in busybox.c and the Gods of BusyBox smite you. Yea, verily:
-
-Be sure to read the top of applets.src.h before adding your applet.
+Finally add the applet declaration snippet. Be sure to read the top of
+applets.src.h before adding your applet - it contains important info
+on applet macros and conventions.
- /* all programs above here are alphabetically "less than" 'mu' */
- IF_MU(APPLET(mu, BB_DIR_USR_BIN, BB_SUID_DROP))
- /* all programs below here are alphabetically "greater than" 'mu' */
+//applet:IF_MU(APPLET(mu, BB_DIR_USR_BIN, BB_SUID_DROP))
The Grand Announcement
diff --git a/release/src/router/busybox/docs/posix_conformance.txt b/release/src/router/busybox/docs/posix_conformance.txt
index 5b616d7012..c0582dc231 100644
--- a/release/src/router/busybox/docs/posix_conformance.txt
+++ b/release/src/router/busybox/docs/posix_conformance.txt
@@ -178,6 +178,7 @@ dd POSIX options:
conv=noerror | yes | |
conv=notrunc | yes | |
conv=sync | yes | |
+ iflag=skip_bytes| yes | |
dd Busybox specific options:
conv=fsync
diff --git a/release/src/router/busybox/docs/tcp.txt b/release/src/router/busybox/docs/tcp.txt
new file mode 100644
index 0000000000..2000f31100
--- /dev/null
+++ b/release/src/router/busybox/docs/tcp.txt
@@ -0,0 +1,93 @@
+ Some less-widely known details of TCP connections.
+
+ Properly closing the connection.
+
+After this code sequence:
+
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ connect(sock, &remote, sizeof(remote));
+ write(sock, buffer, 1000000);
+
+a large block of data is only buffered by kernel, it can't be sent all at once.
+What will happen if we close the socket?
+
+"A host MAY implement a 'half-duplex' TCP close sequence, so that
+ an application that has called close() cannot continue to read
+ data from the connection. If such a host issues a close() call
+ while received data is still pending in TCP, or if new data is
+ received after close() is called, its TCP SHOULD send a RST
+ to show that data was lost."
+
+IOW: if we just close(sock) now, kernel can reset the TCP connection
+(send RST packet).
+
+This is problematic for two reasons: it discards some not-yet sent
+data, and it may be reported as error, not EOF, on peer's side.
+
+What can be done about it?
+
+Solution #1: block until sending is done:
+
+ /* When enabled, a close(2) or shutdown(2) will not return until
+ * all queued messages for the socket have been successfully sent
+ * or the linger timeout has been reached.
+ */
+ struct linger {
+ int l_onoff; /* linger active */
+ int l_linger; /* how many seconds to linger for */
+ } linger;
+ linger.l_onoff = 1;
+ linger.l_linger = SOME_NUM;
+ setsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger));
+ close(sock);
+
+Solution #2: tell kernel that you are done sending.
+This makes kernel send FIN after all data is written:
+
+ shutdown(sock, SHUT_WR);
+ close(sock);
+
+However, experiments on Linux 3.9.4 show that kernel can return from
+shutdown() and from close() before all data is sent,
+and if peer sends any data to us after this, kernel still responds with
+RST before all our data is sent.
+
+In practice the protocol in use often does not allow peer to send
+such data to us, in which case this solution is acceptable.
+
+Solution #3: if you know that peer is going to close its end after it sees
+our FIN (as EOF), it might be a good idea to perform a read after shutdown().
+When read finishes with 0-sized result, we conclude that peer received all
+the data, saw EOF, and closed its end.
+
+However, this incurs small performance penalty (we run for a longer time)
+and requires safeguards (nonblocking reads, timeouts etc) against
+malicious peers which don't close the connection.
+
+Solutions #1 and #2 can be combined:
+
+ /* ...set up struct linger... then: */
+ setsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger));
+ shutdown(sock, SHUT_WR);
+ /* At this point, kernel sent FIN packet, not RST, to the peer, */
+ /* even if there is buffered read data from the peer. */
+ close(sock);
+
+ Defeating Nagle.
+
+Method #1: manually control whether partial sends are allowed:
+
+This prevents partially filled packets being sent:
+
+ int state = 1;
+ setsockopt(fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
+
+and this forces last, partially filled packet (if any) to be sent:
+
+ int state = 0;
+ setsockopt(fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
+
+Method #2: make any write to immediately send data, even if it's partial:
+
+ int state = 1;
+ setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &state, sizeof(state));
diff --git a/release/src/router/busybox/docs/unit-tests.txt b/release/src/router/busybox/docs/unit-tests.txt
new file mode 100644
index 0000000000..0fb5220869
--- /dev/null
+++ b/release/src/router/busybox/docs/unit-tests.txt
@@ -0,0 +1,50 @@
+Busybox unit test framework
+===========================
+
+This document describes what you need to do to write test cases using the
+Busybox unit test framework.
+
+
+Building unit tests
+-------------------
+
+The framework and all tests are built as a regular Busybox applet if option
+CONFIG_UNIT_TEST (found in General Configuration -> Debugging Options) is set.
+
+
+Writing test cases
+------------------
+
+Unit testing interface can be found in include/bbunit.h.
+
+Tests can be placed in any .c file in Busybox tree - preferably right next to
+the functions they test. Test cases should be enclosed within an #if, and
+should start with BBUNIT_DEFINE_TEST macro and end with BBUNIT_ENDTEST within
+the test curly brackets. If an assertion fails the test ends immediately, ie.
+the following assertions will not be reached. Any code placed after
+BBUNIT_ENDTEST is executed regardless of the test result. Here's an example:
+
+#if ENABLE_UNIT_TEST
+
+BBUNIT_DEFINE_TEST(test_name)
+{
+ int *i;
+
+ i = malloc(sizeof(int));
+ BBUNIT_ASSERT_NOTNULL(i);
+ *i = 2;
+ BBUNIT_ASSERT_EQ((*i)*(*i), 4);
+
+ BBUNIT_ENDTEST;
+
+ free(i);
+}
+
+#endif /* ENABLE_UNIT_TEST */
+
+
+Running the unit test suite
+---------------------------
+
+To run the tests you can either directly run 'busybox unit' or use 'make test'
+to run both the unit tests (if compiled) and regular test suite.
diff --git a/release/src/router/busybox/e2fsprogs/Config.src b/release/src/router/busybox/e2fsprogs/Config.src
index a113378fb4..a20d849e6f 100644
--- a/release/src/router/busybox/e2fsprogs/Config.src
+++ b/release/src/router/busybox/e2fsprogs/Config.src
@@ -7,58 +7,37 @@ menu "Linux Ext2 FS Progs"
INSERT
-config CHATTR
- bool "chattr"
- default n
- help
- chattr changes the file attributes on a second extended file system.
-
-config E2FSCK
- bool "e2fsck"
- default n
- select VOLUMEID
- help
- e2fsck is used to check Linux second extended file systems (ext2fs).
- e2fsck also supports ext2 filesystems countaining a journal (ext3).
- The normal compat symlinks 'fsck.ext2' and 'fsck.ext3' are also
- provided.
-
-config FSCK
- bool "fsck"
- default n
- help
- fsck is used to check and optionally repair one or more filesystems.
- In actuality, fsck is simply a front-end for the various file system
- checkers (fsck.fstype) available under Linux.
-
-config LSATTR
- bool "lsattr"
- default n
- help
- lsattr lists the file attributes on a second extended file system.
-
-config MKE2FS
- bool "mke2fs"
- default n
- select VOLUMEID
- help
- mke2fs is used to create an ext2/ext3 filesystem. The normal compat
- symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided.
-
-config TUNE2FS
- bool "tune2fs"
- default n
- select VOLUMEID
- help
- tune2fs allows the system administrator to adjust various tunable
- filesystem parameters on Linux ext2/ext3 filesystems.
-
-config E2LABEL
- bool "e2label"
- default n
- depends on TUNE2FS
- help
- e2label will display or change the filesystem label on the ext2
- filesystem located on device.
+### config E2FSCK
+### bool "e2fsck"
+### default y
+### help
+### e2fsck is used to check Linux second extended file systems (ext2fs).
+### e2fsck also supports ext2 filesystems countaining a journal (ext3).
+### The normal compat symlinks 'fsck.ext2' and 'fsck.ext3' are also
+### provided.
+
+### config MKE2FS
+### bool "mke2fs"
+### default y
+### help
+### mke2fs is used to create an ext2/ext3 filesystem. The normal compat
+### symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided.
+
+### config E2LABEL
+### bool "e2label"
+### default y
+### depends on TUNE2FS
+### help
+### e2label will display or change the filesystem label on the ext2
+### filesystem located on device.
+
+### NB: this one is now provided by util-linux/volume_id/*
+### config FINDFS
+### bool "findfs"
+### default y
+### depends on TUNE2FS
+### help
+### findfs will search the disks in the system looking for a filesystem
+### which has a label matching label or a UUID equal to uuid.
endmenu
diff --git a/release/src/router/busybox/e2fsprogs/Kbuild.src b/release/src/router/busybox/e2fsprogs/Kbuild.src
index 8df2b17504..6b4fb74700 100644
--- a/release/src/router/busybox/e2fsprogs/Kbuild.src
+++ b/release/src/router/busybox/e2fsprogs/Kbuild.src
@@ -7,12 +7,3 @@
lib-y:=
INSERT
-
-lib-$(CONFIG_CHATTR) += chattr.o e2fs_lib.o
-lib-$(CONFIG_E2FSCK) += e2fsck.o util.o e2fs_lib.o
-lib-$(CONFIG_FSCK) += fsck.o
-lib-$(CONFIG_LSATTR) += lsattr.o e2fs_lib.o
-lib-$(CONFIG_MKE2FS) += mke2fs.o util.o e2fs_lib.o
-lib-$(CONFIG_TUNE2FS) += tune2fs.o util.o e2fs_lib.o
-
-CFLAGS += -include $(srctree)/e2fsprogs/e2fsbb.h
diff --git a/release/src/router/busybox/e2fsprogs/README b/release/src/router/busybox/e2fsprogs/README
index fac0901931..eb158e5881 100644
--- a/release/src/router/busybox/e2fsprogs/README
+++ b/release/src/router/busybox/e2fsprogs/README
@@ -1,3 +1,12 @@
-This is a pretty straight rip from the e2fsprogs pkg.
+Authors and contributors of original e2fsprogs:
-See README's in subdirs for specific info.
+Remy Card <card@masi.ibp.fr>
+Theodore Ts'o <tytso@mit.edu>
+Stephen C. Tweedie <sct@redhat.com>
+Andreas Gruenbacher, <a.gruenbacher@computer.org>
+Kaz Kylheku <kaz@ashi.footprints.net>
+F.W. ten Wolde <franky@duteca.et.tudelft.nl>
+Jeremy Fitzhardinge <jeremy@zip.com.au>
+M.J.E. Mol <marcel@duteca.et.tudelft.nl>
+Miquel van Smoorenburg <miquels@drinkel.ow.org>
+Uwe Ohse <uwe@tirka.gun.de>
diff --git a/release/src/router/busybox/e2fsprogs/blkid/Kbuild.src b/release/src/router/busybox/e2fsprogs/blkid/Kbuild.src
deleted file mode 100644
index 02b4d24961..0000000000
--- a/release/src/router/busybox/e2fsprogs/blkid/Kbuild.src
+++ /dev/null
@@ -1,26 +0,0 @@
-# Makefile for busybox
-#
-# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
-#
-# Licensed under GPLv2, see file LICENSE in this source tree.
-
-NEEDED-$(CONFIG_E2FSCK) = y
-NEEDED-$(CONFIG_FSCK) = y
-NEEDED-$(CONFIG_MKE2FS) = y
-NEEDED-$(CONFIG_TUNE2FS) = y
-
-lib-y:=
-
-INSERT
-
-lib-$(NEEDED-y) += cache.o dev.o devname.o devno.o blkid_getsize.o \
- probe.o read.o resolve.o save.o tag.o list.o
-
-CFLAGS_dev.o := -include $(srctree)/include/busybox.h
-CFLAGS_devname.o := -include $(srctree)/include/busybox.h
-CFLAGS_devno.o := -include $(srctree)/include/busybox.h
-CFLAGS_blkid_getsize.o := -include $(srctree)/include/busybox.h
-CFLAGS_probe.o := -include $(srctree)/include/busybox.h
-CFLAGS_save.o := -include $(srctree)/include/busybox.h
-CFLAGS_tag.o := -include $(srctree)/include/busybox.h
-CFLAGS_list.o := -include $(srctree)/include/busybox.h
diff --git a/release/src/router/busybox/e2fsprogs/blkid/blkid.h b/release/src/router/busybox/e2fsprogs/blkid/blkid.h
deleted file mode 100644
index 9a3c2afdbd..0000000000
--- a/release/src/router/busybox/e2fsprogs/blkid/blkid.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * blkid.h - Interface for libblkid, a library to identify block devices
- *
- * Copyright (C) 2001 Andreas Dilger
- * Copyright (C) 2003 Theodore Ts'o
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-#ifndef BLKID_BLKID_H
-#define BLKID_BLKID_H 1
-
-#include <sys/types.h>
-#include <linux/types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define BLKID_VERSION "1.0.0"
-#define BLKID_DATE "12-Feb-2003"
-
-typedef struct blkid_struct_dev *blkid_dev;
-typedef struct blkid_struct_cache *blkid_cache;
-typedef __s64 blkid_loff_t;
-
-typedef struct blkid_struct_tag_iterate *blkid_tag_iterate;
-typedef struct blkid_struct_dev_iterate *blkid_dev_iterate;
-
-/*
- * Flags for blkid_get_dev
- *
- * BLKID_DEV_CREATE Create an empty device structure if not found
- * in the cache.
- * BLKID_DEV_VERIFY Make sure the device structure corresponds
- * with reality.
- * BLKID_DEV_FIND Just look up a device entry, and return NULL
- * if it is not found.
- * BLKID_DEV_NORMAL Get a valid device structure, either from the
- * cache or by probing the device.
- */
-#define BLKID_DEV_FIND 0x0000
-#define BLKID_DEV_CREATE 0x0001
-#define BLKID_DEV_VERIFY 0x0002
-#define BLKID_DEV_NORMAL (BLKID_DEV_CREATE | BLKID_DEV_VERIFY)
-
-/* cache.c */
-extern void blkid_put_cache(blkid_cache cache);
-extern int blkid_get_cache(blkid_cache *cache, const char *filename);
-
-/* dev.c */
-extern const char *blkid_dev_devname(blkid_dev dev);
-
-extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache);
-extern int blkid_dev_set_search(blkid_dev_iterate iter,
- char *search_type, char *search_value);
-extern int blkid_dev_next(blkid_dev_iterate iterate, blkid_dev *dev);
-extern void blkid_dev_iterate_end(blkid_dev_iterate iterate);
-
-/* devno.c */
-extern char *blkid_devno_to_devname(dev_t devno);
-
-/* devname.c */
-extern int blkid_probe_all(blkid_cache cache);
-extern int blkid_probe_all_new(blkid_cache cache);
-extern blkid_dev blkid_get_dev(blkid_cache cache, const char *devname,
- int flags);
-
-/* getsize.c */
-extern blkid_loff_t blkid_get_dev_size(int fd);
-
-/* probe.c */
-int blkid_known_fstype(const char *fstype);
-extern blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev);
-
-/* read.c */
-
-/* resolve.c */
-extern char *blkid_get_tag_value(blkid_cache cache, const char *tagname,
- const char *devname);
-extern char *blkid_get_devname(blkid_cache cache, const char *token,
- const char *value);
-
-/* tag.c */
-extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev);
-extern int blkid_tag_next(blkid_tag_iterate iterate,
- const char **type, const char **value);
-extern void blkid_tag_iterate_end(blkid_tag_iterate iterate);
-extern int blkid_dev_has_tag(blkid_dev dev, const char *type,
- const char *value);
-extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
- const char *type,
- const char *value);
-extern int blkid_parse_tag_string(const char *token, char **ret_type,
- char **ret_val);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/blkid/blkidP.h b/release/src/router/busybox/e2fsprogs/blkid/blkidP.h
deleted file mode 100644
index d6b2b42cc5..0000000000
--- a/release/src/router/busybox/e2fsprogs/blkid/blkidP.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * blkidP.h - Internal interfaces for libblkid
- *
- * Copyright (C) 2001 Andreas Dilger
- * Copyright (C) 2003 Theodore Ts'o
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-#ifndef BLKID_BLKIDP_H
-#define BLKID_BLKIDP_H 1
-
-#include <sys/types.h>
-#include <stdio.h>
-
-#include "blkid.h"
-#include "list.h"
-
-#ifdef __GNUC__
-#define __BLKID_ATTR(x) __attribute__(x)
-#else
-#define __BLKID_ATTR(x)
-#endif
-
-
-/*
- * This describes the attributes of a specific device.
- * We can traverse all of the tags by bid_tags (linking to the tag bit_names).
- * The bid_label and bid_uuid fields are shortcuts to the LABEL and UUID tag
- * values, if they exist.
- */
-struct blkid_struct_dev
-{
- struct list_head bid_devs; /* All devices in the cache */
- struct list_head bid_tags; /* All tags for this device */
- blkid_cache bid_cache; /* Dev belongs to this cache */
- char *bid_name; /* Device inode pathname */
- char *bid_type; /* Preferred device TYPE */
- int bid_pri; /* Device priority */
- dev_t bid_devno; /* Device major/minor number */
- time_t bid_time; /* Last update time of device */
- unsigned int bid_flags; /* Device status bitflags */
- char *bid_label; /* Shortcut to device LABEL */
- char *bid_uuid; /* Shortcut to binary UUID */
-};
-
-#define BLKID_BID_FL_VERIFIED 0x0001 /* Device data validated from disk */
-#define BLKID_BID_FL_INVALID 0x0004 /* Device is invalid */
-
-/*
- * Each tag defines a NAME=value pair for a particular device. The tags
- * are linked via bit_names for a single device, so that traversing the
- * names list will get you a list of all tags associated with a device.
- * They are also linked via bit_values for all devices, so one can easily
- * search all tags with a given NAME for a specific value.
- */
-struct blkid_struct_tag
-{
- struct list_head bit_tags; /* All tags for this device */
- struct list_head bit_names; /* All tags with given NAME */
- char *bit_name; /* NAME of tag (shared) */
- char *bit_val; /* value of tag */
- blkid_dev bit_dev; /* pointer to device */
-};
-typedef struct blkid_struct_tag *blkid_tag;
-
-/*
- * Minimum number of seconds between device probes, even when reading
- * from the cache. This is to avoid re-probing all devices which were
- * just probed by another program that does not share the cache.
- */
-#define BLKID_PROBE_MIN 2
-
-/*
- * Time in seconds an entry remains verified in the in-memory cache
- * before being reverified (in case of long-running processes that
- * keep a cache in memory and continue to use it for a long time).
- */
-#define BLKID_PROBE_INTERVAL 200
-
-/* This describes an entire blkid cache file and probed devices.
- * We can traverse all of the found devices via bic_list.
- * We can traverse all of the tag types by bic_tags, which hold empty tags
- * for each tag type. Those tags can be used as list_heads for iterating
- * through all devices with a specific tag type (e.g. LABEL).
- */
-struct blkid_struct_cache
-{
- struct list_head bic_devs; /* List head of all devices */
- struct list_head bic_tags; /* List head of all tag types */
- time_t bic_time; /* Last probe time */
- time_t bic_ftime; /* Mod time of the cachefile */
- unsigned int bic_flags; /* Status flags of the cache */
- char *bic_filename; /* filename of cache */
-};
-
-#define BLKID_BIC_FL_PROBED 0x0002 /* We probed /proc/partition devices */
-#define BLKID_BIC_FL_CHANGED 0x0004 /* Cache has changed from disk */
-
-extern char *blkid_strdup(const char *s);
-extern char *blkid_strndup(const char *s, const int length);
-
-#define BLKID_CACHE_FILE "/etc/blkid.tab"
-extern const char *blkid_devdirs[];
-
-#define BLKID_ERR_IO 5
-#define BLKID_ERR_PROC 9
-#define BLKID_ERR_MEM 12
-#define BLKID_ERR_CACHE 14
-#define BLKID_ERR_DEV 19
-#define BLKID_ERR_PARAM 22
-#define BLKID_ERR_BIG 27
-
-/*
- * Priority settings for different types of devices
- */
-#define BLKID_PRI_EVMS 30
-#define BLKID_PRI_LVM 20
-#define BLKID_PRI_MD 10
-
-#if defined(TEST_PROGRAM) && !defined(CONFIG_BLKID_DEBUG)
-#define CONFIG_BLKID_DEBUG
-#endif
-
-#define DEBUG_CACHE 0x0001
-#define DEBUG_DUMP 0x0002
-#define DEBUG_DEV 0x0004
-#define DEBUG_DEVNAME 0x0008
-#define DEBUG_DEVNO 0x0010
-#define DEBUG_PROBE 0x0020
-#define DEBUG_READ 0x0040
-#define DEBUG_RESOLVE 0x0080
-#define DEBUG_SAVE 0x0100
-#define DEBUG_TAG 0x0200
-#define DEBUG_INIT 0x8000
-#define DEBUG_ALL 0xFFFF
-
-#ifdef CONFIG_BLKID_DEBUG
-#include <stdio.h>
-extern int blkid_debug_mask;
-#define DBG(m,x) if ((m) & blkid_debug_mask) x;
-#else
-#define DBG(m,x)
-#endif
-
-#ifdef CONFIG_BLKID_DEBUG
-extern void blkid_debug_dump_dev(blkid_dev dev);
-extern void blkid_debug_dump_tag(blkid_tag tag);
-#endif
-
-/* lseek.c */
-/* extern blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence); */
-#ifdef CONFIG_LFS
-# define blkid_llseek lseek64
-#else
-# define blkid_llseek lseek
-#endif
-
-/* read.c */
-extern void blkid_read_cache(blkid_cache cache);
-
-/* save.c */
-extern int blkid_flush_cache(blkid_cache cache);
-
-/*
- * Functions to create and find a specific tag type: tag.c
- */
-extern void blkid_free_tag(blkid_tag tag);
-extern blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type);
-extern int blkid_set_tag(blkid_dev dev, const char *name,
- const char *value, const int vlength);
-
-/*
- * Functions to create and find a specific tag type: dev.c
- */
-extern blkid_dev blkid_new_dev(void);
-extern void blkid_free_dev(blkid_dev dev);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/blkid/blkid_getsize.c b/release/src/router/busybox/e2fsprogs/blkid/blkid_getsize.c
deleted file mode 100644
index e1f6ba6d2a..0000000000
--- a/release/src/router/busybox/e2fsprogs/blkid/blkid_getsize.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * getsize.c --- get the size of a partition.
- *
- * Copyright (C) 1995, 1995 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-
-/* include this before sys/queues.h! */
-#include "blkidP.h"
-
-#include <stdio.h>
-#include <unistd.h>
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <fcntl.h>
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#ifdef HAVE_LINUX_FD_H
-#include <linux/fd.h>
-#endif
-#ifdef HAVE_SYS_DISKLABEL_H
-#include <sys/disklabel.h>
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_DISK_H
-#ifdef HAVE_SYS_QUEUE_H
-#include <sys/queue.h> /* for LIST_HEAD */
-#endif
-#include <sys/disk.h>
-#endif
-#ifdef __linux__
-#include <sys/utsname.h>
-#endif
-
-#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
-#define BLKGETSIZE _IO(0x12,96) /* return device size */
-#endif
-
-#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
-#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
-#endif
-
-#ifdef APPLE_DARWIN
-#define BLKGETSIZE DKIOCGETBLOCKCOUNT32
-#endif /* APPLE_DARWIN */
-
-static int valid_offset(int fd, blkid_loff_t offset)
-{
- char ch;
-
- if (blkid_llseek(fd, offset, 0) < 0)
- return 0;
- if (read(fd, &ch, 1) < 1)
- return 0;
- return 1;
-}
-
-/*
- * Returns the number of blocks in a partition
- */
-blkid_loff_t blkid_get_dev_size(int fd)
-{
- int valid_blkgetsize64 = 1;
-#ifdef __linux__
- struct utsname ut;
-#endif
- unsigned long long size64;
- unsigned long size;
- blkid_loff_t high, low;
-#ifdef FDGETPRM
- struct floppy_struct this_floppy;
-#endif
-#ifdef HAVE_SYS_DISKLABEL_H
- int part = -1;
- struct disklabel lab;
- struct partition *pp;
- char ch;
- struct stat st;
-#endif /* HAVE_SYS_DISKLABEL_H */
-
-#ifdef DKIOCGETBLOCKCOUNT /* For Apple Darwin */
- if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) {
- if ((sizeof(blkid_loff_t) < sizeof(unsigned long long))
- && (size64 << 9 > 0xFFFFFFFF))
- return 0; /* EFBIG */
- return (blkid_loff_t) size64 << 9;
- }
-#endif
-
-#ifdef BLKGETSIZE64
-#ifdef __linux__
- uname(&ut);
- if ((ut.release[0] == '2') && (ut.release[1] == '.') &&
- (ut.release[2] < '6') && (ut.release[3] == '.'))
- valid_blkgetsize64 = 0;
-#endif
- if (valid_blkgetsize64 &&
- ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
- if ((sizeof(blkid_loff_t) < sizeof(unsigned long long))
- && ((size64) > 0xFFFFFFFF))
- return 0; /* EFBIG */
- return size64;
- }
-#endif
-
-#ifdef BLKGETSIZE
- if (ioctl(fd, BLKGETSIZE, &size) >= 0)
- return (blkid_loff_t)size << 9;
-#endif
-
-#ifdef FDGETPRM
- if (ioctl(fd, FDGETPRM, &this_floppy) >= 0)
- return (blkid_loff_t)this_floppy.size << 9;
-#endif
-#ifdef HAVE_SYS_DISKLABEL_H
-#if 0
- /*
- * This should work in theory but I haven't tested it. Anyone
- * on a BSD system want to test this for me? In the meantime,
- * binary search mechanism should work just fine.
- */
- if ((fstat(fd, &st) >= 0) && S_ISBLK(st.st_mode))
- part = st.st_rdev & 7;
- if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
- pp = &lab.d_partitions[part];
- if (pp->p_size)
- return pp->p_size << 9;
- }
-#endif
-#endif /* HAVE_SYS_DISKLABEL_H */
-
- /*
- * OK, we couldn't figure it out by using a specialized ioctl,
- * which is generally the best way. So do binary search to
- * find the size of the partition.
- */
- low = 0;
- for (high = 1024; valid_offset(fd, high); high *= 2)
- low = high;
- while (low < high - 1)
- {
- const blkid_loff_t mid = (low + high) / 2;
-
- if (valid_offset(fd, mid))
- low = mid;
- else
- high = mid;
- }
- return low + 1;
-}
-
-#ifdef TEST_PROGRAM
-int main(int argc, char **argv)
-{
- blkid_loff_t bytes;
- int fd;
-
- if (argc < 2) {
- fprintf(stderr, "Usage: %s device\n"
- "Determine the size of a device\n", argv[0]);
- return 1;
- }
-
- if ((fd = open(argv[1], O_RDONLY)) < 0)
- perror(argv[0]);
-
- bytes = blkid_get_dev_size(fd);
- printf("Device %s has %lld 1k blocks.\n", argv[1], bytes >> 10);
-
- return 0;
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/blkid/cache.c b/release/src/router/busybox/e2fsprogs/blkid/cache.c
deleted file mode 100644
index d1d29146b3..0000000000
--- a/release/src/router/busybox/e2fsprogs/blkid/cache.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * cache.c - allocation/initialization/free routines for cache
- *
- * Copyright (C) 2001 Andreas Dilger
- * Copyright (C) 2003 Theodore Ts'o
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include "blkidP.h"
-
-int blkid_debug_mask = 0;
-
-int blkid_get_cache(blkid_cache *ret_cache, const char *filename)
-{
- blkid_cache cache;
-
-#ifdef CONFIG_BLKID_DEBUG
- if (!(blkid_debug_mask & DEBUG_INIT)) {
- char *dstr = getenv("BLKID_DEBUG");
-
- if (dstr)
- blkid_debug_mask = strtoul(dstr, 0, 0);
- blkid_debug_mask |= DEBUG_INIT;
- }
-#endif
-
- DBG(DEBUG_CACHE, printf("creating blkid cache (using %s)\n",
- filename ? filename : "default cache"));
-
- cache = xzalloc(sizeof(struct blkid_struct_cache));
-
- INIT_LIST_HEAD(&cache->bic_devs);
- INIT_LIST_HEAD(&cache->bic_tags);
-
- if (filename && !strlen(filename))
- filename = 0;
- if (!filename && (getuid() == geteuid()))
- filename = getenv("BLKID_FILE");
- if (!filename)
- filename = BLKID_CACHE_FILE;
- cache->bic_filename = blkid_strdup(filename);
-
- blkid_read_cache(cache);
-
- *ret_cache = cache;
- return 0;
-}
-
-void blkid_put_cache(blkid_cache cache)
-{
- if (!cache)
- return;
-
- (void) blkid_flush_cache(cache);
-
- DBG(DEBUG_CACHE, printf("freeing cache struct\n"));
-
- /* DBG(DEBUG_CACHE, blkid_debug_dump_cache(cache)); */
-
- while (!list_empty(&cache->bic_devs)) {
- blkid_dev dev = list_entry(cache->bic_devs.next,
- struct blkid_struct_dev,
- bid_devs);
- blkid_free_dev(dev);
- }
-
- while (!list_empty(&cache->bic_tags)) {
- blkid_tag tag = list_entry(cache->bic_tags.next,
- struct blkid_struct_tag,
- bit_tags);
-
- while (!list_empty(&tag->bit_names)) {
- blkid_tag bad = list_entry(tag->bit_names.next,
- struct blkid_struct_tag,
- bit_names);
-
- DBG(DEBUG_CACHE, printf("warning: unfreed tag %s=%s\n",
- bad->bit_name, bad->bit_val));
- blkid_free_tag(bad);
- }
- blkid_free_tag(tag);
- }
- free(cache->bic_filename);
-
- free(cache);
-}
-
-#ifdef TEST_PROGRAM
-int main(int argc, char** argv)
-{
- blkid_cache cache = NULL;
- int ret;
-
- blkid_debug_mask = DEBUG_ALL;
- if ((argc > 2)) {
- fprintf(stderr, "Usage: %s [filename]\n", argv[0]);
- exit(1);
- }
-
- if ((ret = blkid_get_cache(&cache, argv[1])) < 0) {
- fprintf(stderr, "error %d parsing cache file %s\n", ret,
- argv[1] ? argv[1] : BLKID_CACHE_FILE);
- exit(1);
- }
- if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
- fprintf(stderr, "%s: error creating cache (%d)\n",
- argv[0], ret);
- exit(1);
- }
- if ((ret = blkid_probe_all(cache) < 0))
- fprintf(stderr, "error probing devices\n");
-
- blkid_put_cache(cache);
-
- return ret;
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/blkid/dev.c b/release/src/router/busybox/e2fsprogs/blkid/dev.c
deleted file mode 100644
index bb0cc914a0..0000000000
--- a/release/src/router/busybox/e2fsprogs/blkid/dev.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * dev.c - allocation/initialization/free routines for dev
- *
- * Copyright (C) 2001 Andreas Dilger
- * Copyright (C) 2003 Theodore Ts'o
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "blkidP.h"
-
-blkid_dev blkid_new_dev(void)
-{
- blkid_dev dev;
-
- dev = xzalloc(sizeof(struct blkid_struct_dev));
-
- INIT_LIST_HEAD(&dev->bid_devs);
- INIT_LIST_HEAD(&dev->bid_tags);
-
- return dev;
-}
-
-void blkid_free_dev(blkid_dev dev)
-{
- if (!dev)
- return;
-
- DBG(DEBUG_DEV,
- printf(" freeing dev %s (%s)\n", dev->bid_name, dev->bid_type));
- DBG(DEBUG_DEV, blkid_debug_dump_dev(dev));
-
- list_del(&dev->bid_devs);
- while (!list_empty(&dev->bid_tags)) {
- blkid_tag tag = list_entry(dev->bid_tags.next,
- struct blkid_struct_tag,
- bit_tags);
- blkid_free_tag(tag);
- }
- if (dev->bid_name)
- free(dev->bid_name);
- free(dev);
-}
-
-/*
- * Given a blkid device, return its name
- */
-const char *blkid_dev_devname(blkid_dev dev)
-{
- return dev->bid_name;
-}
-
-#ifdef CONFIG_BLKID_DEBUG
-void blkid_debug_dump_dev(blkid_dev dev)
-{
- struct list_head *p;
-
- if (!dev) {
- printf(" dev: NULL\n");
- return;
- }
-
- printf(" dev: name = %s\n", dev->bid_name);
- printf(" dev: DEVNO=\"0x%0llx\"\n", dev->bid_devno);
- printf(" dev: TIME=\"%lu\"\n", dev->bid_time);
- printf(" dev: PRI=\"%d\"\n", dev->bid_pri);
- printf(" dev: flags = 0x%08X\n", dev->bid_flags);
-
- list_for_each(p, &dev->bid_tags) {
- blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
- if (tag)
- printf(" tag: %s=\"%s\"\n", tag->bit_name,
- tag->bit_val);
- else
- printf(" tag: NULL\n");
- }
- bb_putchar('\n');
-}
-#endif
-
-/*
- * dev iteration routines for the public libblkid interface.
- *
- * These routines do not expose the list.h implementation, which are a
- * contamination of the namespace, and which force us to reveal far, far
- * too much of our internal implemenation. I'm not convinced I want
- * to keep list.h in the long term, anyway. It's fine for kernel
- * programming, but performance is not the #1 priority for this
- * library, and I really don't like the tradeoff of type-safety for
- * performance for this application. [tytso:20030125.2007EST]
- */
-
-/*
- * This series of functions iterate over all devices in a blkid cache
- */
-#define DEV_ITERATE_MAGIC 0x01a5284c
-
-struct blkid_struct_dev_iterate {
- int magic;
- blkid_cache cache;
- struct list_head *p;
-};
-
-blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache)
-{
- blkid_dev_iterate iter;
-
- iter = xmalloc(sizeof(struct blkid_struct_dev_iterate));
- iter->magic = DEV_ITERATE_MAGIC;
- iter->cache = cache;
- iter->p = cache->bic_devs.next;
- return iter;
-}
-
-/*
- * Return 0 on success, -1 on error
- */
-extern int blkid_dev_next(blkid_dev_iterate iter,
- blkid_dev *dev)
-{
- *dev = 0;
- if (!iter || iter->magic != DEV_ITERATE_MAGIC ||
- iter->p == &iter->cache->bic_devs)
- return -1;
- *dev = list_entry(iter->p, struct blkid_struct_dev, bid_devs);
- iter->p = iter->p->next;
- return 0;
-}
-
-void blkid_dev_iterate_end(blkid_dev_iterate iter)
-{
- if (!iter || iter->magic != DEV_ITERATE_MAGIC)
- return;
- iter->magic = 0;
- free(iter);
-}
-
-#ifdef TEST_PROGRAM
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#else
-extern char *optarg;
-extern int optind;
-#endif
-
-void usage(char *prog)
-{
- fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask]\n", prog);
- fprintf(stderr, "\tList all devices and exit\n", prog);
- exit(1);
-}
-
-int main(int argc, char **argv)
-{
- blkid_dev_iterate iter;
- blkid_cache cache = NULL;
- blkid_dev dev;
- int c, ret;
- char *tmp;
- char *file = NULL;
- char *search_type = NULL;
- char *search_value = NULL;
-
- while ((c = getopt (argc, argv, "m:f:")) != EOF)
- switch (c) {
- case 'f':
- file = optarg;
- break;
- case 'm':
- blkid_debug_mask = strtoul (optarg, &tmp, 0);
- if (*tmp) {
- fprintf(stderr, "Invalid debug mask: %d\n",
- optarg);
- exit(1);
- }
- break;
- case '?':
- usage(argv[0]);
- }
- if (argc >= optind+2) {
- search_type = argv[optind];
- search_value = argv[optind+1];
- optind += 2;
- }
- if (argc != optind)
- usage(argv[0]);
-
- if ((ret = blkid_get_cache(&cache, file)) != 0) {
- fprintf(stderr, "%s: error creating cache (%d)\n",
- argv[0], ret);
- exit(1);
- }
-
- iter = blkid_dev_iterate_begin(cache);
- if (search_type)
- blkid_dev_set_search(iter, search_type, search_value);
- while (blkid_dev_next(iter, &dev) == 0) {
- printf("Device: %s\n", blkid_dev_devname(dev));
- }
- blkid_dev_iterate_end(iter);
-
-
- blkid_put_cache(cache);
- return 0;
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/blkid/devname.c b/release/src/router/busybox/e2fsprogs/blkid/devname.c
deleted file mode 100644
index fad92cb313..0000000000
--- a/release/src/router/busybox/e2fsprogs/blkid/devname.c
+++ /dev/null
@@ -1,367 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * devname.c - get a dev by its device inode name
- *
- * Copyright (C) Andries Brouwer
- * Copyright (C) 1999, 2000, 2001, 2002, 2003 Theodore Ts'o
- * Copyright (C) 2001 Andreas Dilger
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#include <sys/stat.h>
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_SYS_MKDEV_H
-#include <sys/mkdev.h>
-#endif
-#include <time.h>
-
-#include "blkidP.h"
-
-/*
- * Find a dev struct in the cache by device name, if available.
- *
- * If there is no entry with the specified device name, and the create
- * flag is set, then create an empty device entry.
- */
-blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags)
-{
- blkid_dev dev = NULL, tmp;
- struct list_head *p;
-
- if (!cache || !devname)
- return NULL;
-
- list_for_each(p, &cache->bic_devs) {
- tmp = list_entry(p, struct blkid_struct_dev, bid_devs);
- if (strcmp(tmp->bid_name, devname))
- continue;
-
- DBG(DEBUG_DEVNAME,
- printf("found devname %s in cache\n", tmp->bid_name));
- dev = tmp;
- break;
- }
-
- if (!dev && (flags & BLKID_DEV_CREATE)) {
- dev = blkid_new_dev();
- if (!dev)
- return NULL;
- dev->bid_name = blkid_strdup(devname);
- dev->bid_cache = cache;
- list_add_tail(&dev->bid_devs, &cache->bic_devs);
- cache->bic_flags |= BLKID_BIC_FL_CHANGED;
- }
-
- if (flags & BLKID_DEV_VERIFY)
- dev = blkid_verify(cache, dev);
- return dev;
-}
-
-/*
- * Probe a single block device to add to the device cache.
- */
-static void probe_one(blkid_cache cache, const char *ptname,
- dev_t devno, int pri)
-{
- blkid_dev dev = NULL;
- struct list_head *p;
- const char **dir;
- char *devname = NULL;
-
- /* See if we already have this device number in the cache. */
- list_for_each(p, &cache->bic_devs) {
- blkid_dev tmp = list_entry(p, struct blkid_struct_dev,
- bid_devs);
- if (tmp->bid_devno == devno) {
- dev = blkid_verify(cache, tmp);
- break;
- }
- }
- if (dev && dev->bid_devno == devno)
- goto set_pri;
-
- /*
- * Take a quick look at /dev/ptname for the device number. We check
- * all of the likely device directories. If we don't find it, or if
- * the stat information doesn't check out, use blkid_devno_to_devname()
- * to find it via an exhaustive search for the device major/minor.
- */
- for (dir = blkid_devdirs; *dir; dir++) {
- struct stat st;
- char device[256];
-
- sprintf(device, "%s/%s", *dir, ptname);
- if ((dev = blkid_get_dev(cache, device, BLKID_DEV_FIND)) &&
- dev->bid_devno == devno)
- goto set_pri;
-
- if (stat(device, &st) == 0 && S_ISBLK(st.st_mode) &&
- st.st_rdev == devno) {
- devname = blkid_strdup(device);
- break;
- }
- }
- if (!devname) {
- devname = blkid_devno_to_devname(devno);
- if (!devname)
- return;
- }
- dev = blkid_get_dev(cache, devname, BLKID_DEV_NORMAL);
- free(devname);
-
-set_pri:
- if (!pri && !strncmp(ptname, "md", 2))
- pri = BLKID_PRI_MD;
- if (dev)
- dev->bid_pri = pri;
-}
-
-#define PROC_PARTITIONS "/proc/partitions"
-#define VG_DIR "/proc/lvm/VGs"
-
-/*
- * This function initializes the UUID cache with devices from the LVM
- * proc hierarchy. We currently depend on the names of the LVM
- * hierarchy giving us the device structure in /dev. (XXX is this a
- * safe thing to do?)
- */
-#ifdef VG_DIR
-#include <dirent.h>
-static dev_t lvm_get_devno(const char *lvm_device)
-{
- FILE *lvf;
- char buf[1024];
- int ma, mi;
- dev_t ret = 0;
-
- DBG(DEBUG_DEVNAME, printf("opening %s\n", lvm_device));
- if ((lvf = fopen_for_read(lvm_device)) == NULL) {
- DBG(DEBUG_DEVNAME, printf("%s: (%d) %s\n", lvm_device, errno,
- strerror(errno)));
- return 0;
- }
-
- while (fgets(buf, sizeof(buf), lvf)) {
- if (sscanf(buf, "device: %d:%d", &ma, &mi) == 2) {
- ret = makedev(ma, mi);
- break;
- }
- }
- fclose(lvf);
-
- return ret;
-}
-
-static void lvm_probe_all(blkid_cache cache)
-{
- DIR *vg_list;
- struct dirent *vg_iter;
- int vg_len = strlen(VG_DIR);
- dev_t dev;
-
- if ((vg_list = opendir(VG_DIR)) == NULL)
- return;
-
- DBG(DEBUG_DEVNAME, printf("probing LVM devices under %s\n", VG_DIR));
-
- while ((vg_iter = readdir(vg_list)) != NULL) {
- DIR *lv_list;
- char *vdirname;
- char *vg_name;
- struct dirent *lv_iter;
-
- vg_name = vg_iter->d_name;
- if (LONE_CHAR(vg_name, '.') || !strcmp(vg_name, ".."))
- continue;
- vdirname = xmalloc(vg_len + strlen(vg_name) + 8);
- sprintf(vdirname, "%s/%s/LVs", VG_DIR, vg_name);
-
- lv_list = opendir(vdirname);
- free(vdirname);
- if (lv_list == NULL)
- continue;
-
- while ((lv_iter = readdir(lv_list)) != NULL) {
- char *lv_name, *lvm_device;
-
- lv_name = lv_iter->d_name;
- if (LONE_CHAR(lv_name, '.') || !strcmp(lv_name, ".."))
- continue;
-
- lvm_device = xmalloc(vg_len + strlen(vg_name) +
- strlen(lv_name) + 8);
- sprintf(lvm_device, "%s/%s/LVs/%s", VG_DIR, vg_name,
- lv_name);
- dev = lvm_get_devno(lvm_device);
- sprintf(lvm_device, "%s/%s", vg_name, lv_name);
- DBG(DEBUG_DEVNAME, printf("LVM dev %s: devno 0x%04X\n",
- lvm_device,
- (unsigned int) dev));
- probe_one(cache, lvm_device, dev, BLKID_PRI_LVM);
- free(lvm_device);
- }
- closedir(lv_list);
- }
- closedir(vg_list);
-}
-#endif
-
-#define PROC_EVMS_VOLUMES "/proc/evms/volumes"
-
-static int
-evms_probe_all(blkid_cache cache)
-{
- char line[100];
- int ma, mi, sz, num = 0;
- FILE *procpt;
- char device[110];
-
- procpt = fopen_for_read(PROC_EVMS_VOLUMES);
- if (!procpt)
- return 0;
- while (fgets(line, sizeof(line), procpt)) {
- if (sscanf(line, " %d %d %d %*s %*s %[^\n ]",
- &ma, &mi, &sz, device) != 4)
- continue;
-
- DBG(DEBUG_DEVNAME, printf("Checking partition %s (%d, %d)\n",
- device, ma, mi));
-
- probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS);
- num++;
- }
- fclose(procpt);
- return num;
-}
-
-/*
- * Read the device data for all available block devices in the system.
- */
-int blkid_probe_all(blkid_cache cache)
-{
- FILE *proc;
- char line[1024];
- char ptname0[128], ptname1[128], *ptname = NULL;
- char *ptnames[2];
- dev_t devs[2];
- int ma, mi;
- unsigned long long sz;
- int lens[2] = { 0, 0 };
- int which = 0, last = 0;
-
- ptnames[0] = ptname0;
- ptnames[1] = ptname1;
-
- if (!cache)
- return -BLKID_ERR_PARAM;
-
- if (cache->bic_flags & BLKID_BIC_FL_PROBED &&
- time(NULL) - cache->bic_time < BLKID_PROBE_INTERVAL)
- return 0;
-
- blkid_read_cache(cache);
- evms_probe_all(cache);
-#ifdef VG_DIR
- lvm_probe_all(cache);
-#endif
-
- proc = fopen_for_read(PROC_PARTITIONS);
- if (!proc)
- return -BLKID_ERR_PROC;
-
- while (fgets(line, sizeof(line), proc)) {
- last = which;
- which ^= 1;
- ptname = ptnames[which];
-
- if (sscanf(line, " %d %d %llu %128[^\n ]",
- &ma, &mi, &sz, ptname) != 4)
- continue;
- devs[which] = makedev(ma, mi);
-
- DBG(DEBUG_DEVNAME, printf("read partition name %s\n", ptname));
-
- /* Skip whole disk devs unless they have no partitions
- * If we don't have a partition on this dev, also
- * check previous dev to see if it didn't have a partn.
- * heuristic: partition name ends in a digit.
- *
- * Skip extended partitions.
- * heuristic: size is 1
- *
- * FIXME: skip /dev/{ida,cciss,rd} whole-disk devs
- */
-
- lens[which] = strlen(ptname);
- if (isdigit(ptname[lens[which] - 1])) {
- DBG(DEBUG_DEVNAME,
- printf("partition dev %s, devno 0x%04X\n",
- ptname, (unsigned int) devs[which]));
-
- if (sz > 1)
- probe_one(cache, ptname, devs[which], 0);
- lens[which] = 0;
- lens[last] = 0;
- } else if (lens[last] && strncmp(ptnames[last], ptname,
- lens[last])) {
- DBG(DEBUG_DEVNAME,
- printf("whole dev %s, devno 0x%04X\n",
- ptnames[last], (unsigned int) devs[last]));
- probe_one(cache, ptnames[last], devs[last], 0);
- lens[last] = 0;
- }
- }
-
- /* Handle the last device if it wasn't partitioned */
- if (lens[which])
- probe_one(cache, ptname, devs[which], 0);
-
- fclose(proc);
-
- cache->bic_time = time(NULL);
- cache->bic_flags |= BLKID_BIC_FL_PROBED;
- blkid_flush_cache(cache);
- return 0;
-}
-
-#ifdef TEST_PROGRAM
-int main(int argc, char **argv)
-{
- blkid_cache cache = NULL;
- int ret;
-
- blkid_debug_mask = DEBUG_ALL;
- if (argc != 1) {
- fprintf(stderr, "Usage: %s\n"
- "Probe all devices and exit\n", argv[0]);
- exit(1);
- }
- if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
- fprintf(stderr, "%s: error creating cache (%d)\n",
- argv[0], ret);
- exit(1);
- }
- if (blkid_probe_all(cache) < 0)
- printf("%s: error probing devices\n", argv[0]);
-
- blkid_put_cache(cache);
- return 0;
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/blkid/devno.c b/release/src/router/busybox/e2fsprogs/blkid/devno.c
deleted file mode 100644
index ae326f81a0..0000000000
--- a/release/src/router/busybox/e2fsprogs/blkid/devno.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * devno.c - find a particular device by its device number (major/minor)
- *
- * Copyright (C) 2000, 2001, 2003 Theodore Ts'o
- * Copyright (C) 2001 Andreas Dilger
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#include <sys/stat.h>
-#include <dirent.h>
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_SYS_MKDEV_H
-#include <sys/mkdev.h>
-#endif
-
-#include "blkidP.h"
-
-struct dir_list {
- char *name;
- struct dir_list *next;
-};
-
-char *blkid_strndup(const char *s, int length)
-{
- char *ret;
-
- if (!s)
- return NULL;
-
- if (!length)
- length = strlen(s);
-
- ret = xmalloc(length + 1);
- strncpy(ret, s, length);
- ret[length] = '\0';
- return ret;
-}
-
-char *blkid_strdup(const char *s)
-{
- return blkid_strndup(s, 0);
-}
-
-/*
- * This function adds an entry to the directory list
- */
-static void add_to_dirlist(const char *name, struct dir_list **list)
-{
- struct dir_list *dp;
-
- dp = xmalloc(sizeof(struct dir_list));
- dp->name = blkid_strdup(name);
- dp->next = *list;
- *list = dp;
-}
-
-/*
- * This function frees a directory list
- */
-static void free_dirlist(struct dir_list **list)
-{
- struct dir_list *dp, *next;
-
- for (dp = *list; dp; dp = next) {
- next = dp->next;
- free(dp->name);
- free(dp);
- }
- *list = NULL;
-}
-
-static void scan_dir(char *dir_name, dev_t devno, struct dir_list **list,
- char **devname)
-{
- DIR *dir;
- struct dirent *dp;
- char path[1024];
- int dirlen;
- struct stat st;
-
- if ((dir = opendir(dir_name)) == NULL)
- return;
- dirlen = strlen(dir_name) + 2;
- while ((dp = readdir(dir)) != 0) {
- if (dirlen + strlen(dp->d_name) >= sizeof(path))
- continue;
-
- if (dp->d_name[0] == '.' &&
- ((dp->d_name[1] == 0) ||
- ((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
- continue;
-
- sprintf(path, "%s/%s", dir_name, dp->d_name);
- if (stat(path, &st) < 0)
- continue;
-
- if (S_ISDIR(st.st_mode))
- add_to_dirlist(path, list);
- else if (S_ISBLK(st.st_mode) && st.st_rdev == devno) {
- *devname = blkid_strdup(path);
- DBG(DEBUG_DEVNO,
- printf("found 0x%llx at %s (%p)\n", devno,
- path, *devname));
- break;
- }
- }
- closedir(dir);
-}
-
-/* Directories where we will try to search for device numbers */
-const char *blkid_devdirs[] = { "/devices", "/devfs", "/dev", NULL };
-
-/*
- * This function finds the pathname to a block device with a given
- * device number. It returns a pointer to allocated memory to the
- * pathname on success, and NULL on failure.
- */
-char *blkid_devno_to_devname(dev_t devno)
-{
- struct dir_list *list = NULL, *new_list = NULL;
- char *devname = NULL;
- const char **dir;
-
- /*
- * Add the starting directories to search in reverse order of
- * importance, since we are using a stack...
- */
- for (dir = blkid_devdirs; *dir; dir++)
- add_to_dirlist(*dir, &list);
-
- while (list) {
- struct dir_list *current = list;
-
- list = list->next;
- DBG(DEBUG_DEVNO, printf("directory %s\n", current->name));
- scan_dir(current->name, devno, &new_list, &devname);
- free(current->name);
- free(current);
- if (devname)
- break;
- /*
- * If we're done checking at this level, descend to
- * the next level of subdirectories. (breadth-first)
- */
- if (list == NULL) {
- list = new_list;
- new_list = NULL;
- }
- }
- free_dirlist(&list);
- free_dirlist(&new_list);
-
- if (!devname) {
- DBG(DEBUG_DEVNO,
- printf("blkid: cannot find devno 0x%04lx\n",
- (unsigned long) devno));
- } else {
- DBG(DEBUG_DEVNO,
- printf("found devno 0x%04llx as %s\n", devno, devname));
- }
-
-
- return devname;
-}
-
-#ifdef TEST_PROGRAM
-int main(int argc, char** argv)
-{
- char *devname, *tmp;
- int major, minor;
- dev_t devno;
- const char *errmsg = "Cannot parse %s: %s\n";
-
- blkid_debug_mask = DEBUG_ALL;
- if ((argc != 2) && (argc != 3)) {
- fprintf(stderr, "Usage:\t%s device_number\n\t%s major minor\n"
- "Resolve a device number to a device name\n",
- argv[0], argv[0]);
- exit(1);
- }
- if (argc == 2) {
- devno = strtoul(argv[1], &tmp, 0);
- if (*tmp) {
- fprintf(stderr, errmsg, "device number", argv[1]);
- exit(1);
- }
- } else {
- major = strtoul(argv[1], &tmp, 0);
- if (*tmp) {
- fprintf(stderr, errmsg, "major number", argv[1]);
- exit(1);
- }
- minor = strtoul(argv[2], &tmp, 0);
- if (*tmp) {
- fprintf(stderr, errmsg, "minor number", argv[2]);
- exit(1);
- }
- devno = makedev(major, minor);
- }
- printf("Looking for device 0x%04Lx\n", devno);
- devname = blkid_devno_to_devname(devno);
- free(devname);
- return 0;
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/blkid/list.c b/release/src/router/busybox/e2fsprogs/blkid/list.c
deleted file mode 100644
index 04d61a19ba..0000000000
--- a/release/src/router/busybox/e2fsprogs/blkid/list.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/* vi: set sw=4 ts=4: */
-
-#include "list.h"
-
-/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-void __list_add(struct list_head * add,
- struct list_head * prev,
- struct list_head * next)
-{
- next->prev = add;
- add->next = next;
- add->prev = prev;
- prev->next = add;
-}
-
-/*
- * list_add - add a new entry
- * @add: new entry to be added
- * @head: list head to add it after
- *
- * Insert a new entry after the specified head.
- * This is good for implementing stacks.
- */
-void list_add(struct list_head *add, struct list_head *head)
-{
- __list_add(add, head, head->next);
-}
-
-/*
- * list_add_tail - add a new entry
- * @add: new entry to be added
- * @head: list head to add it before
- *
- * Insert a new entry before the specified head.
- * This is useful for implementing queues.
- */
-void list_add_tail(struct list_head *add, struct list_head *head)
-{
- __list_add(add, head->prev, head);
-}
-
-/*
- * Delete a list entry by making the prev/next entries
- * point to each other.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-void __list_del(struct list_head * prev, struct list_head * next)
-{
- next->prev = prev;
- prev->next = next;
-}
-
-/*
- * list_del - deletes entry from list.
- * @entry: the element to delete from the list.
- *
- * list_empty() on @entry does not return true after this, @entry is
- * in an undefined state.
- */
-void list_del(struct list_head *entry)
-{
- __list_del(entry->prev, entry->next);
-}
-
-/*
- * list_del_init - deletes entry from list and reinitialize it.
- * @entry: the element to delete from the list.
- */
-void list_del_init(struct list_head *entry)
-{
- __list_del(entry->prev, entry->next);
- INIT_LIST_HEAD(entry);
-}
-
-/*
- * list_empty - tests whether a list is empty
- * @head: the list to test.
- */
-int list_empty(struct list_head *head)
-{
- return head->next == head;
-}
-
-/*
- * list_splice - join two lists
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- */
-void list_splice(struct list_head *list, struct list_head *head)
-{
- struct list_head *first = list->next;
-
- if (first != list) {
- struct list_head *last = list->prev;
- struct list_head *at = head->next;
-
- first->prev = head;
- head->next = first;
-
- last->next = at;
- at->prev = last;
- }
-}
diff --git a/release/src/router/busybox/e2fsprogs/blkid/list.h b/release/src/router/busybox/e2fsprogs/blkid/list.h
deleted file mode 100644
index a24baaa912..0000000000
--- a/release/src/router/busybox/e2fsprogs/blkid/list.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* vi: set sw=4 ts=4: */
-#if !defined(_BLKID_LIST_H) && !defined(LIST_HEAD)
-#define BLKID_LIST_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Simple doubly linked list implementation.
- *
- * Some of the internal functions ("__xxx") are useful when
- * manipulating whole lists rather than single entries, as
- * sometimes we already know the next/prev entries and we can
- * generate better code by using them directly rather than
- * using the generic single-entry routines.
- */
-
-struct list_head {
- struct list_head *next, *prev;
-};
-
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define LIST_HEAD(name) \
- struct list_head name = LIST_HEAD_INIT(name)
-
-#define INIT_LIST_HEAD(ptr) do { \
- (ptr)->next = (ptr); (ptr)->prev = (ptr); \
-} while (0)
-
-void __list_add(struct list_head * add, struct list_head * prev, struct list_head * next);
-void list_add(struct list_head *add, struct list_head *head);
-void list_add_tail(struct list_head *add, struct list_head *head);
-void __list_del(struct list_head * prev, struct list_head * next);
-void list_del(struct list_head *entry);
-void list_del_init(struct list_head *entry);
-int list_empty(struct list_head *head);
-void list_splice(struct list_head *list, struct list_head *head);
-
-/**
- * list_entry - get the struct for this entry
- * @ptr: the &struct list_head pointer.
- * @type: the type of the struct this is embedded in.
- * @member: the name of the list_struct within the struct.
- */
-#define list_entry(ptr, type, member) \
- ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
-
-/**
- * list_for_each - iterate over elements in a list
- * @pos: the &struct list_head to use as a loop counter.
- * @head: the head for your list.
- */
-#define list_for_each(pos, head) \
- for (pos = (head)->next; pos != (head); pos = pos->next)
-
-/**
- * list_for_each_safe - iterate over elements in a list, but don't dereference
- * pos after the body is done (in case it is freed)
- * @pos: the &struct list_head to use as a loop counter.
- * @pnext: the &struct list_head to use as a pointer to the next item.
- * @head: the head for your list (not included in iteration).
- */
-#define list_for_each_safe(pos, pnext, head) \
- for (pos = (head)->next, pnext = pos->next; pos != (head); \
- pos = pnext, pnext = pos->next)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/blkid/probe.c b/release/src/router/busybox/e2fsprogs/blkid/probe.c
deleted file mode 100644
index 651193b426..0000000000
--- a/release/src/router/busybox/e2fsprogs/blkid/probe.c
+++ /dev/null
@@ -1,726 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * probe.c - identify a block device by its contents, and return a dev
- * struct with the details
- *
- * Copyright (C) 1999 by Andries Brouwer
- * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
- * Copyright (C) 2001 by Andreas Dilger
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_MKDEV_H
-#include <sys/mkdev.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include "blkidP.h"
-#include "../uuid/uuid.h"
-#include "probe.h"
-
-/*
- * This is a special case code to check for an MDRAID device. We do
- * this special since it requires checking for a superblock at the end
- * of the device.
- */
-static int check_mdraid(int fd, unsigned char *ret_uuid)
-{
- struct mdp_superblock_s *md;
- blkid_loff_t offset;
- char buf[4096];
-
- if (fd < 0)
- return -BLKID_ERR_PARAM;
-
- offset = (blkid_get_dev_size(fd) & ~((blkid_loff_t)65535)) - 65536;
-
- if (blkid_llseek(fd, offset, 0) < 0 ||
- read(fd, buf, 4096) != 4096)
- return -BLKID_ERR_IO;
-
- /* Check for magic number */
- if (memcmp("\251+N\374", buf, 4))
- return -BLKID_ERR_PARAM;
-
- if (!ret_uuid)
- return 0;
- *ret_uuid = 0;
-
- /* The MD UUID is not contiguous in the superblock, make it so */
- md = (struct mdp_superblock_s *)buf;
- if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) {
- memcpy(ret_uuid, &md->set_uuid0, 4);
- memcpy(ret_uuid, &md->set_uuid1, 12);
- }
- return 0;
-}
-
-static void set_uuid(blkid_dev dev, uuid_t uuid)
-{
- char str[37];
-
- if (!uuid_is_null(uuid)) {
- uuid_unparse(uuid, str);
- blkid_set_tag(dev, "UUID", str, sizeof(str));
- }
-}
-
-static void get_ext2_info(blkid_dev dev, unsigned char *buf)
-{
- struct ext2_super_block *es = (struct ext2_super_block *) buf;
- const char *label = NULL;
-
- DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n",
- blkid_le32(es->s_feature_compat),
- blkid_le32(es->s_feature_incompat),
- blkid_le32(es->s_feature_ro_compat)));
-
- if (strlen(es->s_volume_name))
- label = es->s_volume_name;
- blkid_set_tag(dev, "LABEL", label, sizeof(es->s_volume_name));
-
- set_uuid(dev, es->s_uuid);
-}
-
-static int probe_ext3(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct ext2_super_block *es;
-
- es = (struct ext2_super_block *)buf;
-
- /* Distinguish between jbd and ext2/3 fs */
- if (blkid_le32(es->s_feature_incompat) &
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
- return -BLKID_ERR_PARAM;
-
- /* Distinguish between ext3 and ext2 */
- if (!(blkid_le32(es->s_feature_compat) &
- EXT3_FEATURE_COMPAT_HAS_JOURNAL))
- return -BLKID_ERR_PARAM;
-
- get_ext2_info(dev, buf);
-
- blkid_set_tag(dev, "SEC_TYPE", "ext2", sizeof("ext2"));
-
- return 0;
-}
-
-static int probe_ext2(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct ext2_super_block *es;
-
- es = (struct ext2_super_block *)buf;
-
- /* Distinguish between jbd and ext2/3 fs */
- if (blkid_le32(es->s_feature_incompat) &
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
- return -BLKID_ERR_PARAM;
-
- get_ext2_info(dev, buf);
-
- return 0;
-}
-
-static int probe_jbd(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct ext2_super_block *es = (struct ext2_super_block *) buf;
-
- if (!(blkid_le32(es->s_feature_incompat) &
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV))
- return -BLKID_ERR_PARAM;
-
- get_ext2_info(dev, buf);
-
- return 0;
-}
-
-static int probe_vfat(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct vfat_super_block *vs;
- char serno[10];
- const char *label = NULL;
- int label_len = 0;
-
- vs = (struct vfat_super_block *)buf;
-
- if (strncmp(vs->vs_label, "NO NAME", 7)) {
- char *end = vs->vs_label + sizeof(vs->vs_label) - 1;
-
- while (*end == ' ' && end >= vs->vs_label)
- --end;
- if (end >= vs->vs_label) {
- label = vs->vs_label;
- label_len = end - vs->vs_label + 1;
- }
- }
-
- /* We can't just print them as %04X, because they are unaligned */
- sprintf(serno, "%02X%02X-%02X%02X", vs->vs_serno[3], vs->vs_serno[2],
- vs->vs_serno[1], vs->vs_serno[0]);
- blkid_set_tag(dev, "LABEL", label, label_len);
- blkid_set_tag(dev, "UUID", serno, sizeof(serno));
-
- return 0;
-}
-
-static int probe_msdos(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct msdos_super_block *ms = (struct msdos_super_block *) buf;
- char serno[10];
- const char *label = NULL;
- int label_len = 0;
-
- if (strncmp(ms->ms_label, "NO NAME", 7)) {
- char *end = ms->ms_label + sizeof(ms->ms_label) - 1;
-
- while (*end == ' ' && end >= ms->ms_label)
- --end;
- if (end >= ms->ms_label) {
- label = ms->ms_label;
- label_len = end - ms->ms_label + 1;
- }
- }
-
- /* We can't just print them as %04X, because they are unaligned */
- sprintf(serno, "%02X%02X-%02X%02X", ms->ms_serno[3], ms->ms_serno[2],
- ms->ms_serno[1], ms->ms_serno[0]);
- blkid_set_tag(dev, "UUID", serno, 0);
- blkid_set_tag(dev, "LABEL", label, label_len);
- blkid_set_tag(dev, "SEC_TYPE", "msdos", sizeof("msdos"));
-
- return 0;
-}
-
-static int probe_xfs(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct xfs_super_block *xs;
- const char *label = NULL;
-
- xs = (struct xfs_super_block *)buf;
-
- if (strlen(xs->xs_fname))
- label = xs->xs_fname;
- blkid_set_tag(dev, "LABEL", label, sizeof(xs->xs_fname));
- set_uuid(dev, xs->xs_uuid);
- return 0;
-}
-
-static int probe_reiserfs(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id, unsigned char *buf)
-{
- struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf;
- unsigned int blocksize;
- const char *label = NULL;
-
- blocksize = blkid_le16(rs->rs_blocksize);
-
- /* If the superblock is inside the journal, we have the wrong one */
- if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block))
- return -BLKID_ERR_BIG;
-
- /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */
- if (!strcmp(id->bim_magic, "ReIsEr2Fs") ||
- !strcmp(id->bim_magic, "ReIsEr3Fs")) {
- if (strlen(rs->rs_label))
- label = rs->rs_label;
- set_uuid(dev, rs->rs_uuid);
- }
- blkid_set_tag(dev, "LABEL", label, sizeof(rs->rs_label));
-
- return 0;
-}
-
-static int probe_jfs(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct jfs_super_block *js;
- const char *label = NULL;
-
- js = (struct jfs_super_block *)buf;
-
- if (strlen((char *) js->js_label))
- label = (char *) js->js_label;
- blkid_set_tag(dev, "LABEL", label, sizeof(js->js_label));
- set_uuid(dev, js->js_uuid);
- return 0;
-}
-
-static int probe_romfs(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct romfs_super_block *ros;
- const char *label = NULL;
-
- ros = (struct romfs_super_block *)buf;
-
- if (strlen((char *) ros->ros_volume))
- label = (char *) ros->ros_volume;
- blkid_set_tag(dev, "LABEL", label, 0);
- return 0;
-}
-
-static int probe_cramfs(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct cramfs_super_block *csb;
- const char *label = NULL;
-
- csb = (struct cramfs_super_block *)buf;
-
- if (strlen((char *) csb->name))
- label = (char *) csb->name;
- blkid_set_tag(dev, "LABEL", label, 0);
- return 0;
-}
-
-static int probe_swap0(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf __BLKID_ATTR((unused)))
-{
- blkid_set_tag(dev, "UUID", 0, 0);
- blkid_set_tag(dev, "LABEL", 0, 0);
- return 0;
-}
-
-static int probe_swap1(int fd,
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf __BLKID_ATTR((unused)))
-{
- struct swap_id_block *sws;
-
- probe_swap0(fd, cache, dev, id, buf);
- /*
- * Version 1 swap headers are always located at offset of 1024
- * bytes, although the swap signature itself is located at the
- * end of the page (which may vary depending on hardware
- * pagesize).
- */
- if (lseek(fd, 1024, SEEK_SET) < 0) return 1;
- sws = xmalloc(1024);
- if (read(fd, sws, 1024) != 1024) {
- free(sws);
- return 1;
- }
-
- /* arbitrary sanity check.. is there any garbage down there? */
- if (sws->sws_pad[32] == 0 && sws->sws_pad[33] == 0) {
- if (sws->sws_volume[0])
- blkid_set_tag(dev, "LABEL", (const char*)sws->sws_volume,
- sizeof(sws->sws_volume));
- if (sws->sws_uuid[0])
- set_uuid(dev, sws->sws_uuid);
- }
- free(sws);
-
- return 0;
-}
-
-static const char
-* const udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
- "NSR03", "TEA01", 0 };
-
-static int probe_udf(int fd, blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev __BLKID_ATTR((unused)),
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf __BLKID_ATTR((unused)))
-{
- int j, bs;
- struct iso_volume_descriptor isosb;
- const char *const *m;
-
- /* determine the block size by scanning in 2K increments
- (block sizes larger than 2K will be null padded) */
- for (bs = 1; bs < 16; bs++) {
- lseek(fd, bs*2048+32768, SEEK_SET);
- if (read(fd, (char *)&isosb, sizeof(isosb)) != sizeof(isosb))
- return 1;
- if (isosb.id[0])
- break;
- }
-
- /* Scan up to another 64 blocks looking for additional VSD's */
- for (j = 1; j < 64; j++) {
- if (j > 1) {
- lseek(fd, j*bs*2048+32768, SEEK_SET);
- if (read(fd, (char *)&isosb, sizeof(isosb))
- != sizeof(isosb))
- return 1;
- }
- /* If we find NSR0x then call it udf:
- NSR01 for UDF 1.00
- NSR02 for UDF 1.50
- NSR03 for UDF 2.00 */
- if (!strncmp(isosb.id, "NSR0", 4))
- return 0;
- for (m = udf_magic; *m; m++)
- if (!strncmp(*m, isosb.id, 5))
- break;
- if (*m == 0)
- return 1;
- }
- return 1;
-}
-
-static int probe_ocfs(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct ocfs_volume_header ovh;
- struct ocfs_volume_label ovl;
- __u32 major;
-
- memcpy(&ovh, buf, sizeof(ovh));
- memcpy(&ovl, buf+512, sizeof(ovl));
-
- major = ocfsmajor(ovh);
- if (major == 1)
- blkid_set_tag(dev, "SEC_TYPE", "ocfs1", sizeof("ocfs1"));
- else if (major >= 9)
- blkid_set_tag(dev, "SEC_TYPE", "ntocfs", sizeof("ntocfs"));
-
- blkid_set_tag(dev, "LABEL", (const char*)ovl.label, ocfslabellen(ovl));
- blkid_set_tag(dev, "MOUNT", (const char*)ovh.mount, ocfsmountlen(ovh));
- set_uuid(dev, ovl.vol_id);
- return 0;
-}
-
-static int probe_ocfs2(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct ocfs2_super_block *osb;
-
- osb = (struct ocfs2_super_block *)buf;
-
- blkid_set_tag(dev, "LABEL", (const char*)osb->s_label, sizeof(osb->s_label));
- set_uuid(dev, osb->s_uuid);
- return 0;
-}
-
-static int probe_oracleasm(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct oracle_asm_disk_label *dl;
-
- dl = (struct oracle_asm_disk_label *)buf;
-
- blkid_set_tag(dev, "LABEL", dl->dl_id, sizeof(dl->dl_id));
- return 0;
-}
-
-/*
- * BLKID_BLK_OFFS is at least as large as the highest bim_kboff defined
- * in the type_array table below + bim_kbalign.
- *
- * When probing for a lot of magics, we handle everything in 1kB buffers so
- * that we don't have to worry about reading each combination of block sizes.
- */
-#define BLKID_BLK_OFFS 64 /* currently reiserfs */
-
-/*
- * Various filesystem magics that we can check for. Note that kboff and
- * sboff are in kilobytes and bytes respectively. All magics are in
- * byte strings so we don't worry about endian issues.
- */
-static const struct blkid_magic type_array[] = {
-/* type kboff sboff len magic probe */
- { "oracleasm", 0, 32, 8, "ORCLDISK", probe_oracleasm },
- { "ntfs", 0, 3, 8, "NTFS ", 0 },
- { "jbd", 1, 0x38, 2, "\123\357", probe_jbd },
- { "ext3", 1, 0x38, 2, "\123\357", probe_ext3 },
- { "ext2", 1, 0x38, 2, "\123\357", probe_ext2 },
- { "reiserfs", 8, 0x34, 8, "ReIsErFs", probe_reiserfs },
- { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", probe_reiserfs },
- { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", probe_reiserfs },
- { "reiserfs", 64, 0x34, 8, "ReIsErFs", probe_reiserfs },
- { "reiserfs", 8, 20, 8, "ReIsErFs", probe_reiserfs },
- { "vfat", 0, 0x52, 5, "MSWIN", probe_vfat },
- { "vfat", 0, 0x52, 8, "FAT32 ", probe_vfat },
- { "vfat", 0, 0x36, 5, "MSDOS", probe_msdos },
- { "vfat", 0, 0x36, 8, "FAT16 ", probe_msdos },
- { "vfat", 0, 0x36, 8, "FAT12 ", probe_msdos },
- { "minix", 1, 0x10, 2, "\177\023", 0 },
- { "minix", 1, 0x10, 2, "\217\023", 0 },
- { "minix", 1, 0x10, 2, "\150\044", 0 },
- { "minix", 1, 0x10, 2, "\170\044", 0 },
- { "vxfs", 1, 0, 4, "\365\374\001\245", 0 },
- { "xfs", 0, 0, 4, "XFSB", probe_xfs },
- { "romfs", 0, 0, 8, "-rom1fs-", probe_romfs },
- { "bfs", 0, 0, 4, "\316\372\173\033", 0 },
- { "cramfs", 0, 0, 4, "E=\315\050", probe_cramfs },
- { "qnx4", 0, 4, 6, "QNX4FS", 0 },
- { "udf", 32, 1, 5, "BEA01", probe_udf },
- { "udf", 32, 1, 5, "BOOT2", probe_udf },
- { "udf", 32, 1, 5, "CD001", probe_udf },
- { "udf", 32, 1, 5, "CDW02", probe_udf },
- { "udf", 32, 1, 5, "NSR02", probe_udf },
- { "udf", 32, 1, 5, "NSR03", probe_udf },
- { "udf", 32, 1, 5, "TEA01", probe_udf },
- { "iso9660", 32, 1, 5, "CD001", 0 },
- { "iso9660", 32, 9, 5, "CDROM", 0 },
- { "jfs", 32, 0, 4, "JFS1", probe_jfs },
- { "hfs", 1, 0, 2, "BD", 0 },
- { "ufs", 8, 0x55c, 4, "T\031\001\000", 0 },
- { "hpfs", 8, 0, 4, "I\350\225\371", 0 },
- { "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 },
- { "swap", 0, 0xff6, 10, "SWAP-SPACE", probe_swap0 },
- { "swap", 0, 0xff6, 10, "SWAPSPACE2", probe_swap1 },
- { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", probe_swap0 },
- { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", probe_swap1 },
- { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", probe_swap0 },
- { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", probe_swap1 },
- { "swap", 0, 0x7ff6, 10, "SWAP-SPACE", probe_swap0 },
- { "swap", 0, 0x7ff6, 10, "SWAPSPACE2", probe_swap1 },
- { "swap", 0, 0xfff6, 10, "SWAP-SPACE", probe_swap0 },
- { "swap", 0, 0xfff6, 10, "SWAPSPACE2", probe_swap1 },
- { "ocfs", 0, 8, 9, "OracleCFS", probe_ocfs },
- { "ocfs2", 1, 0, 6, "OCFSV2", probe_ocfs2 },
- { "ocfs2", 2, 0, 6, "OCFSV2", probe_ocfs2 },
- { "ocfs2", 4, 0, 6, "OCFSV2", probe_ocfs2 },
- { "ocfs2", 8, 0, 6, "OCFSV2", probe_ocfs2 },
- { NULL, 0, 0, 0, NULL, NULL }
-};
-
-/*
- * Verify that the data in dev is consistent with what is on the actual
- * block device (using the devname field only). Normally this will be
- * called when finding items in the cache, but for long running processes
- * is also desirable to revalidate an item before use.
- *
- * If we are unable to revalidate the data, we return the old data and
- * do not set the BLKID_BID_FL_VERIFIED flag on it.
- */
-blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
-{
- const struct blkid_magic *id;
- unsigned char *bufs[BLKID_BLK_OFFS + 1], *buf;
- const char *type;
- struct stat st;
- time_t diff, now;
- int fd, idx;
-
- if (!dev)
- return NULL;
-
- now = time(NULL);
- diff = now - dev->bid_time;
-
- if ((now < dev->bid_time) ||
- (diff < BLKID_PROBE_MIN) ||
- (dev->bid_flags & BLKID_BID_FL_VERIFIED &&
- diff < BLKID_PROBE_INTERVAL))
- return dev;
-
- DBG(DEBUG_PROBE,
- printf("need to revalidate %s (time since last check %lu)\n",
- dev->bid_name, diff));
-
- fd = open(dev->bid_name, O_RDONLY);
- if (fd < 0
- || fstat(fd, &st) < 0
- ) {
- if (fd >= 0)
- close(fd);
- if (errno == ENXIO || errno == ENODEV || errno == ENOENT) {
- blkid_free_dev(dev);
- return NULL;
- }
- /* We don't have read permission, just return cache data. */
- DBG(DEBUG_PROBE,
- printf("returning unverified data for %s\n",
- dev->bid_name));
- return dev;
- }
-
- memset(bufs, 0, sizeof(bufs));
-
- /*
- * Iterate over the type array. If we already know the type,
- * then try that first. If it doesn't work, then blow away
- * the type information, and try again.
- *
- */
-try_again:
- type = 0;
- if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) {
- uuid_t uuid;
-
- if (check_mdraid(fd, uuid) == 0) {
- set_uuid(dev, uuid);
- type = "mdraid";
- goto found_type;
- }
- }
- for (id = type_array; id->bim_type; id++) {
- if (dev->bid_type &&
- strcmp(id->bim_type, dev->bid_type))
- continue;
-
- idx = id->bim_kboff + (id->bim_sboff >> 10);
- if (idx > BLKID_BLK_OFFS || idx < 0)
- continue;
- buf = bufs[idx];
- if (!buf) {
- if (lseek(fd, idx << 10, SEEK_SET) < 0)
- continue;
-
- buf = xmalloc(1024);
-
- if (read(fd, buf, 1024) != 1024) {
- free(buf);
- continue;
- }
- bufs[idx] = buf;
- }
-
- if (memcmp(id->bim_magic, buf + (id->bim_sboff&0x3ff),
- id->bim_len))
- continue;
-
- if ((id->bim_probe == NULL) ||
- (id->bim_probe(fd, cache, dev, id, buf) == 0)) {
- type = id->bim_type;
- goto found_type;
- }
- }
-
- if (!id->bim_type && dev->bid_type) {
- /*
- * Zap the device filesystem type and try again
- */
- blkid_set_tag(dev, "TYPE", 0, 0);
- blkid_set_tag(dev, "SEC_TYPE", 0, 0);
- blkid_set_tag(dev, "LABEL", 0, 0);
- blkid_set_tag(dev, "UUID", 0, 0);
- goto try_again;
- }
-
- if (!dev->bid_type) {
- blkid_free_dev(dev);
- close(fd);
- return NULL;
- }
-
-found_type:
- if (dev && type) {
- dev->bid_devno = st.st_rdev;
- dev->bid_time = time(NULL);
- dev->bid_flags |= BLKID_BID_FL_VERIFIED;
- cache->bic_flags |= BLKID_BIC_FL_CHANGED;
-
- blkid_set_tag(dev, "TYPE", type, 0);
-
- DBG(DEBUG_PROBE, printf("%s: devno 0x%04llx, type %s\n",
- dev->bid_name, st.st_rdev, type));
- }
-
- close(fd);
-
- return dev;
-}
-
-int blkid_known_fstype(const char *fstype)
-{
- const struct blkid_magic *id;
-
- for (id = type_array; id->bim_type; id++) {
- if (strcmp(fstype, id->bim_type) == 0)
- return 1;
- }
- return 0;
-}
-
-#ifdef TEST_PROGRAM
-int main(int argc, char **argv)
-{
- blkid_dev dev;
- blkid_cache cache;
- int ret;
-
- blkid_debug_mask = DEBUG_ALL;
- if (argc != 2) {
- fprintf(stderr, "Usage: %s device\n"
- "Probe a single device to determine type\n", argv[0]);
- exit(1);
- }
- if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
- fprintf(stderr, "%s: error creating cache (%d)\n",
- argv[0], ret);
- exit(1);
- }
- dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL);
- if (!dev) {
- printf("%s: %s has an unsupported type\n", argv[0], argv[1]);
- return 1;
- }
- printf("%s is type %s\n", argv[1], dev->bid_type ?
- dev->bid_type : "(null)");
- if (dev->bid_label)
- printf("\tlabel is '%s'\n", dev->bid_label);
- if (dev->bid_uuid)
- printf("\tuuid is %s\n", dev->bid_uuid);
-
- blkid_free_dev(dev);
- return 0;
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/blkid/probe.h b/release/src/router/busybox/e2fsprogs/blkid/probe.h
deleted file mode 100644
index b6d8f8e7dd..0000000000
--- a/release/src/router/busybox/e2fsprogs/blkid/probe.h
+++ /dev/null
@@ -1,374 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * probe.h - constants and on-disk structures for extracting device data
- *
- * Copyright (C) 1999 by Andries Brouwer
- * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
- * Copyright (C) 2001 by Andreas Dilger
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-#ifndef BLKID_PROBE_H
-#define BLKID_PROBE_H 1
-
-#include <linux/types.h>
-
-struct blkid_magic;
-
-typedef int (*blkid_probe_t)(int fd, blkid_cache cache, blkid_dev dev,
- const struct blkid_magic *id, unsigned char *buf);
-
-struct blkid_magic {
- const char *bim_type; /* type name for this magic */
- long bim_kboff; /* kilobyte offset of superblock */
- unsigned bim_sboff; /* byte offset within superblock */
- unsigned bim_len; /* length of magic */
- const char *bim_magic; /* magic string */
- blkid_probe_t bim_probe; /* probe function */
-};
-
-/*
- * Structures for each of the content types we want to extract information
- * from. We do not necessarily need the magic field here, because we have
- * already identified the content type before we get this far. It may still
- * be useful if there are probe functions which handle multiple content types.
- */
-struct ext2_super_block {
- __u32 s_inodes_count;
- __u32 s_blocks_count;
- __u32 s_r_blocks_count;
- __u32 s_free_blocks_count;
- __u32 s_free_inodes_count;
- __u32 s_first_data_block;
- __u32 s_log_block_size;
- __u32 s_dummy3[7];
- unsigned char s_magic[2];
- __u16 s_state;
- __u32 s_dummy5[8];
- __u32 s_feature_compat;
- __u32 s_feature_incompat;
- __u32 s_feature_ro_compat;
- unsigned char s_uuid[16];
- char s_volume_name[16];
-};
-#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x00000004
-#define EXT3_FEATURE_INCOMPAT_RECOVER 0x00000004
-#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x00000008
-
-struct xfs_super_block {
- unsigned char xs_magic[4];
- __u32 xs_blocksize;
- __u64 xs_dblocks;
- __u64 xs_rblocks;
- __u32 xs_dummy1[2];
- unsigned char xs_uuid[16];
- __u32 xs_dummy2[15];
- char xs_fname[12];
- __u32 xs_dummy3[2];
- __u64 xs_icount;
- __u64 xs_ifree;
- __u64 xs_fdblocks;
-};
-
-struct reiserfs_super_block {
- __u32 rs_blocks_count;
- __u32 rs_free_blocks;
- __u32 rs_root_block;
- __u32 rs_journal_block;
- __u32 rs_journal_dev;
- __u32 rs_orig_journal_size;
- __u32 rs_dummy2[5];
- __u16 rs_blocksize;
- __u16 rs_dummy3[3];
- unsigned char rs_magic[12];
- __u32 rs_dummy4[5];
- unsigned char rs_uuid[16];
- char rs_label[16];
-};
-
-struct jfs_super_block {
- unsigned char js_magic[4];
- __u32 js_version;
- __u64 js_size;
- __u32 js_bsize;
- __u32 js_dummy1;
- __u32 js_pbsize;
- __u32 js_dummy2[27];
- unsigned char js_uuid[16];
- unsigned char js_label[16];
- unsigned char js_loguuid[16];
-};
-
-struct romfs_super_block {
- unsigned char ros_magic[8];
- __u32 ros_dummy1[2];
- unsigned char ros_volume[16];
-};
-
-struct cramfs_super_block {
- __u8 magic[4];
- __u32 size;
- __u32 flags;
- __u32 future;
- __u8 signature[16];
- struct cramfs_info {
- __u32 crc;
- __u32 edition;
- __u32 blocks;
- __u32 files;
- } info;
- __u8 name[16];
-};
-
-struct swap_id_block {
-/* unsigned char sws_boot[1024]; */
- __u32 sws_version;
- __u32 sws_lastpage;
- __u32 sws_nrbad;
- unsigned char sws_uuid[16];
- char sws_volume[16];
- unsigned char sws_pad[117];
- __u32 sws_badpg;
-};
-
-/* Yucky misaligned values */
-struct vfat_super_block {
-/* 00*/ unsigned char vs_ignored[3];
-/* 03*/ unsigned char vs_sysid[8];
-/* 0b*/ unsigned char vs_sector_size[2];
-/* 0d*/ __u8 vs_cluster_size;
-/* 0e*/ __u16 vs_reserved;
-/* 10*/ __u8 vs_fats;
-/* 11*/ unsigned char vs_dir_entries[2];
-/* 13*/ unsigned char vs_sectors[2];
-/* 15*/ unsigned char vs_media;
-/* 16*/ __u16 vs_fat_length;
-/* 18*/ __u16 vs_secs_track;
-/* 1a*/ __u16 vs_heads;
-/* 1c*/ __u32 vs_hidden;
-/* 20*/ __u32 vs_total_sect;
-/* 24*/ __u32 vs_fat32_length;
-/* 28*/ __u16 vs_flags;
-/* 2a*/ __u8 vs_version[2];
-/* 2c*/ __u32 vs_root_cluster;
-/* 30*/ __u16 vs_insfo_sector;
-/* 32*/ __u16 vs_backup_boot;
-/* 34*/ __u16 vs_reserved2[6];
-/* 40*/ unsigned char vs_unknown[3];
-/* 43*/ unsigned char vs_serno[4];
-/* 47*/ char vs_label[11];
-/* 52*/ unsigned char vs_magic[8];
-/* 5a*/ unsigned char vs_dummy2[164];
-/*1fe*/ unsigned char vs_pmagic[2];
-};
-
-/* Yucky misaligned values */
-struct msdos_super_block {
-/* 00*/ unsigned char ms_ignored[3];
-/* 03*/ unsigned char ms_sysid[8];
-/* 0b*/ unsigned char ms_sector_size[2];
-/* 0d*/ __u8 ms_cluster_size;
-/* 0e*/ __u16 ms_reserved;
-/* 10*/ __u8 ms_fats;
-/* 11*/ unsigned char ms_dir_entries[2];
-/* 13*/ unsigned char ms_sectors[2];
-/* 15*/ unsigned char ms_media;
-/* 16*/ __u16 ms_fat_length;
-/* 18*/ __u16 ms_secs_track;
-/* 1a*/ __u16 ms_heads;
-/* 1c*/ __u32 ms_hidden;
-/* 20*/ __u32 ms_total_sect;
-/* 24*/ unsigned char ms_unknown[3];
-/* 27*/ unsigned char ms_serno[4];
-/* 2b*/ char ms_label[11];
-/* 36*/ unsigned char ms_magic[8];
-/* 3d*/ unsigned char ms_dummy2[192];
-/*1fe*/ unsigned char ms_pmagic[2];
-};
-
-struct minix_super_block {
- __u16 ms_ninodes;
- __u16 ms_nzones;
- __u16 ms_imap_blocks;
- __u16 ms_zmap_blocks;
- __u16 ms_firstdatazone;
- __u16 ms_log_zone_size;
- __u32 ms_max_size;
- unsigned char ms_magic[2];
- __u16 ms_state;
- __u32 ms_zones;
-};
-
-struct mdp_superblock_s {
- __u32 md_magic;
- __u32 major_version;
- __u32 minor_version;
- __u32 patch_version;
- __u32 gvalid_words;
- __u32 set_uuid0;
- __u32 ctime;
- __u32 level;
- __u32 size;
- __u32 nr_disks;
- __u32 raid_disks;
- __u32 md_minor;
- __u32 not_persistent;
- __u32 set_uuid1;
- __u32 set_uuid2;
- __u32 set_uuid3;
-};
-
-struct hfs_super_block {
- char h_magic[2];
- char h_dummy[18];
- __u32 h_blksize;
-};
-
-struct ocfs_volume_header {
- unsigned char minor_version[4];
- unsigned char major_version[4];
- unsigned char signature[128];
- char mount[128];
- unsigned char mount_len[2];
-};
-
-struct ocfs_volume_label {
- unsigned char disk_lock[48];
- char label[64];
- unsigned char label_len[2];
- unsigned char vol_id[16];
- unsigned char vol_id_len[2];
-};
-
-#define ocfsmajor(o) ((__u32)o.major_version[0] \
- + (((__u32) o.major_version[1]) << 8) \
- + (((__u32) o.major_version[2]) << 16) \
- + (((__u32) o.major_version[3]) << 24))
-#define ocfslabellen(o) ((__u32)o.label_len[0] + (((__u32) o.label_len[1]) << 8))
-#define ocfsmountlen(o) ((__u32)o.mount_len[0] + (((__u32) o.mount_len[1])<<8))
-
-#define OCFS_MAGIC "OracleCFS"
-
-struct ocfs2_super_block {
- unsigned char signature[8];
- unsigned char s_dummy1[184];
- unsigned char s_dummy2[80];
- char s_label[64];
- unsigned char s_uuid[16];
-};
-
-#define OCFS2_MIN_BLOCKSIZE 512
-#define OCFS2_MAX_BLOCKSIZE 4096
-
-#define OCFS2_SUPER_BLOCK_BLKNO 2
-
-#define OCFS2_SUPER_BLOCK_SIGNATURE "OCFSV2"
-
-struct oracle_asm_disk_label {
- char dummy[32];
- char dl_tag[8];
- char dl_id[24];
-};
-
-#define ORACLE_ASM_DISK_LABEL_MARKED "ORCLDISK"
-#define ORACLE_ASM_DISK_LABEL_OFFSET 32
-
-#define ISODCL(from, to) (to - from + 1)
-struct iso_volume_descriptor {
- char type[ISODCL(1,1)]; /* 711 */
- char id[ISODCL(2,6)];
- char version[ISODCL(7,7)];
- char data[ISODCL(8,2048)];
-};
-
-/*
- * Byte swap functions
- */
-#ifdef __GNUC__
-#define _INLINE_ static __inline__
-#else /* For Watcom C */
-#define _INLINE_ static inline
-#endif
-
-static __u16 blkid_swab16(__u16 val);
-static __u32 blkid_swab32(__u32 val);
-static __u64 blkid_swab64(__u64 val);
-
-#if ((defined __GNUC__) && \
- (defined(__i386__) || defined(__i486__) || defined(__i586__)))
-
-#define _BLKID_HAVE_ASM_BITOPS_
-
-_INLINE_ __u32 blkid_swab32(__u32 val)
-{
-#ifdef EXT2FS_REQUIRE_486
- __asm__("bswap %0" : "=r" (val) : "0" (val));
-#else
- __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
- "rorl $16,%0\n\t" /* swap words */
- "xchgb %b0,%h0" /* swap higher bytes */
- :"=q" (val)
- : "0" (val));
-#endif
- return val;
-}
-
-_INLINE_ __u16 blkid_swab16(__u16 val)
-{
- __asm__("xchgb %b0,%h0" /* swap bytes */
- : "=q" (val)
- : "0" (val));
- return val;
-}
-
-_INLINE_ __u64 blkid_swab64(__u64 val)
-{
- return blkid_swab32(val >> 32) |
- ( ((__u64)blkid_swab32((__u32)val)) << 32 );
-}
-#endif
-
-#if !defined(_BLKID_HAVE_ASM_BITOPS_)
-
-_INLINE_ __u16 blkid_swab16(__u16 val)
-{
- return (val >> 8) | (val << 8);
-}
-
-_INLINE_ __u32 blkid_swab32(__u32 val)
-{
- return (val>>24) | ((val>>8) & 0xFF00) |
- ((val<<8) & 0xFF0000) | (val<<24);
-}
-
-_INLINE_ __u64 blkid_swab64(__u64 val)
-{
- return blkid_swab32(val >> 32) |
- ( ((__u64)blkid_swab32((__u32)val)) << 32 );
-}
-#endif
-
-
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-#define blkid_le16(x) blkid_swab16(x)
-#define blkid_le32(x) blkid_swab32(x)
-#define blkid_le64(x) blkid_swab64(x)
-#define blkid_be16(x) (x)
-#define blkid_be32(x) (x)
-#define blkid_be64(x) (x)
-#else
-#define blkid_le16(x) (x)
-#define blkid_le32(x) (x)
-#define blkid_le64(x) (x)
-#define blkid_be16(x) blkid_swab16(x)
-#define blkid_be32(x) blkid_swab32(x)
-#define blkid_be64(x) blkid_swab64(x)
-#endif
-
-#undef _INLINE_
-
-#endif /* _BLKID_PROBE_H */
diff --git a/release/src/router/busybox/e2fsprogs/blkid/read.c b/release/src/router/busybox/e2fsprogs/blkid/read.c
deleted file mode 100644
index f795a5d145..0000000000
--- a/release/src/router/busybox/e2fsprogs/blkid/read.c
+++ /dev/null
@@ -1,459 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * read.c - read the blkid cache from disk, to avoid scanning all devices
- *
- * Copyright (C) 2001, 2003 Theodore Y. Ts'o
- * Copyright (C) 2001 Andreas Dilger
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include "blkidP.h"
-#include "../uuid/uuid.h"
-
-#ifdef HAVE_STRTOULL
-#define __USE_ISOC9X
-#define STRTOULL strtoull /* defined in stdlib.h if you try hard enough */
-#else
-/* FIXME: need to support real strtoull here */
-#define STRTOULL strtoul
-#endif
-
-#include <stdlib.h>
-
-#ifdef TEST_PROGRAM
-#define blkid_debug_dump_dev(dev) (debug_dump_dev(dev))
-static void debug_dump_dev(blkid_dev dev);
-#endif
-
-/*
- * File format:
- *
- * <device [<NAME="value"> ...]>device_name</device>
- *
- * The following tags are required for each entry:
- * <ID="id"> unique (within this file) ID number of this device
- * <TIME="time"> (ascii time_t) time this entry was last read from disk
- * <TYPE="type"> (detected) type of filesystem/data for this partition
- *
- * The following tags may be present, depending on the device contents
- * <LABEL="label"> (user supplied) label (volume name, etc)
- * <UUID="uuid"> (generated) universally unique identifier (serial no)
- */
-
-static char *skip_over_blank(char *cp)
-{
- while (*cp && isspace(*cp))
- cp++;
- return cp;
-}
-
-static char *skip_over_word(char *cp)
-{
- char ch;
-
- while ((ch = *cp)) {
- /* If we see a backslash, skip the next character */
- if (ch == '\\') {
- cp++;
- if (*cp == '\0')
- break;
- cp++;
- continue;
- }
- if (isspace(ch) || ch == '<' || ch == '>')
- break;
- cp++;
- }
- return cp;
-}
-
-static char *strip_line(char *line)
-{
- char *p;
-
- line = skip_over_blank(line);
-
- p = line + strlen(line) - 1;
-
- while (*line) {
- if (isspace(*p))
- *p-- = '\0';
- else
- break;
- }
-
- return line;
-}
-
-/*
- * Start parsing a new line from the cache.
- *
- * line starts with "<device" return 1 -> continue parsing line
- * line starts with "<foo", empty, or # return 0 -> skip line
- * line starts with other, return -BLKID_ERR_CACHE -> error
- */
-static int parse_start(char **cp)
-{
- char *p;
-
- p = strip_line(*cp);
-
- /* Skip comment or blank lines. We can't just NUL the first '#' char,
- * in case it is inside quotes, or escaped.
- */
- if (*p == '\0' || *p == '#')
- return 0;
-
- if (!strncmp(p, "<device", 7)) {
- DBG(DEBUG_READ, printf("found device header: %8s\n", p));
- p += 7;
-
- *cp = p;
- return 1;
- }
-
- if (*p == '<')
- return 0;
-
- return -BLKID_ERR_CACHE;
-}
-
-/* Consume the remaining XML on the line (cosmetic only) */
-static int parse_end(char **cp)
-{
- *cp = skip_over_blank(*cp);
-
- if (!strncmp(*cp, "</device>", 9)) {
- DBG(DEBUG_READ, printf("found device trailer %9s\n", *cp));
- *cp += 9;
- return 0;
- }
-
- return -BLKID_ERR_CACHE;
-}
-
-/*
- * Allocate a new device struct with device name filled in. Will handle
- * finding the device on lines of the form:
- * <device foo=bar>devname</device>
- * <device>devname<foo>bar</foo></device>
- */
-static int parse_dev(blkid_cache cache, blkid_dev *dev, char **cp)
-{
- char *start, *tmp, *end, *name;
- int ret;
-
- if ((ret = parse_start(cp)) <= 0)
- return ret;
-
- start = tmp = strchr(*cp, '>');
- if (!start) {
- DBG(DEBUG_READ,
- printf("blkid: short line parsing dev: %s\n", *cp));
- return -BLKID_ERR_CACHE;
- }
- start = skip_over_blank(start + 1);
- end = skip_over_word(start);
-
- DBG(DEBUG_READ, printf("device should be %*s\n", end - start, start));
-
- if (**cp == '>')
- *cp = end;
- else
- (*cp)++;
-
- *tmp = '\0';
-
- if (!(tmp = strrchr(end, '<')) || parse_end(&tmp) < 0) {
- DBG(DEBUG_READ,
- printf("blkid: missing </device> ending: %s\n", end));
- } else if (tmp)
- *tmp = '\0';
-
- if (end - start <= 1) {
- DBG(DEBUG_READ, printf("blkid: empty device name: %s\n", *cp));
- return -BLKID_ERR_CACHE;
- }
-
- name = blkid_strndup(start, end-start);
- if (name == NULL)
- return -BLKID_ERR_MEM;
-
- DBG(DEBUG_READ, printf("found dev %s\n", name));
-
- if (!(*dev = blkid_get_dev(cache, name, BLKID_DEV_CREATE)))
- return -BLKID_ERR_MEM;
-
- free(name);
- return 1;
-}
-
-/*
- * Extract a tag of the form NAME="value" from the line.
- */
-static int parse_token(char **name, char **value, char **cp)
-{
- char *end;
-
- if (!name || !value || !cp)
- return -BLKID_ERR_PARAM;
-
- if (!(*value = strchr(*cp, '=')))
- return 0;
-
- **value = '\0';
- *name = strip_line(*cp);
- *value = skip_over_blank(*value + 1);
-
- if (**value == '"') {
- end = strchr(*value + 1, '"');
- if (!end) {
- DBG(DEBUG_READ,
- printf("unbalanced quotes at: %s\n", *value));
- *cp = *value;
- return -BLKID_ERR_CACHE;
- }
- (*value)++;
- *end = '\0';
- end++;
- } else {
- end = skip_over_word(*value);
- if (*end) {
- *end = '\0';
- end++;
- }
- }
- *cp = end;
-
- return 1;
-}
-
-/*
- * Extract a tag of the form <NAME>value</NAME> from the line.
- */
-/*
-static int parse_xml(char **name, char **value, char **cp)
-{
- char *end;
-
- if (!name || !value || !cp)
- return -BLKID_ERR_PARAM;
-
- *name = strip_line(*cp);
-
- if ((*name)[0] != '<' || (*name)[1] == '/')
- return 0;
-
- FIXME: finish this.
-}
-*/
-
-/*
- * Extract a tag from the line.
- *
- * Return 1 if a valid tag was found.
- * Return 0 if no tag found.
- * Return -ve error code.
- */
-static int parse_tag(blkid_cache cache, blkid_dev dev, char **cp)
-{
- char *name;
- char *value;
- int ret;
-
- if (!cache || !dev)
- return -BLKID_ERR_PARAM;
-
- if ((ret = parse_token(&name, &value, cp)) <= 0 /* &&
- (ret = parse_xml(&name, &value, cp)) <= 0 */)
- return ret;
-
- /* Some tags are stored directly in the device struct */
- if (!strcmp(name, "DEVNO"))
- dev->bid_devno = STRTOULL(value, 0, 0);
- else if (!strcmp(name, "PRI"))
- dev->bid_pri = strtol(value, 0, 0);
- else if (!strcmp(name, "TIME"))
- /* FIXME: need to parse a long long eventually */
- dev->bid_time = strtol(value, 0, 0);
- else
- ret = blkid_set_tag(dev, name, value, strlen(value));
-
- DBG(DEBUG_READ, printf(" tag: %s=\"%s\"\n", name, value));
-
- return ret < 0 ? ret : 1;
-}
-
-/*
- * Parse a single line of data, and return a newly allocated dev struct.
- * Add the new device to the cache struct, if one was read.
- *
- * Lines are of the form <device [TAG="value" ...]>/dev/foo</device>
- *
- * Returns -ve value on error.
- * Returns 0 otherwise.
- * If a valid device was read, *dev_p is non-NULL, otherwise it is NULL
- * (e.g. comment lines, unknown XML content, etc).
- */
-static int blkid_parse_line(blkid_cache cache, blkid_dev *dev_p, char *cp)
-{
- blkid_dev dev;
- int ret;
-
- if (!cache || !dev_p)
- return -BLKID_ERR_PARAM;
-
- *dev_p = NULL;
-
- DBG(DEBUG_READ, printf("line: %s\n", cp));
-
- if ((ret = parse_dev(cache, dev_p, &cp)) <= 0)
- return ret;
-
- dev = *dev_p;
-
- while ((ret = parse_tag(cache, dev, &cp)) > 0) {
- ;
- }
-
- if (dev->bid_type == NULL) {
- DBG(DEBUG_READ,
- printf("blkid: device %s has no TYPE\n",dev->bid_name));
- blkid_free_dev(dev);
- }
-
- DBG(DEBUG_READ, blkid_debug_dump_dev(dev));
-
- return ret;
-}
-
-/*
- * Parse the specified filename, and return the data in the supplied or
- * a newly allocated cache struct. If the file doesn't exist, return a
- * new empty cache struct.
- */
-void blkid_read_cache(blkid_cache cache)
-{
- FILE *file;
- char buf[4096];
- int fd, lineno = 0;
- struct stat st;
-
- if (!cache)
- return;
-
- /*
- * If the file doesn't exist, then we just return an empty
- * struct so that the cache can be populated.
- */
- if ((fd = open(cache->bic_filename, O_RDONLY)) < 0)
- return;
- if (fstat(fd, &st) < 0)
- goto errout;
- if ((st.st_mtime == cache->bic_ftime) ||
- (cache->bic_flags & BLKID_BIC_FL_CHANGED)) {
- DBG(DEBUG_CACHE, printf("skipping re-read of %s\n",
- cache->bic_filename));
- goto errout;
- }
-
- DBG(DEBUG_CACHE, printf("reading cache file %s\n",
- cache->bic_filename));
-
- file = xfdopen_for_read(fd);
-
- while (fgets(buf, sizeof(buf), file)) {
- blkid_dev dev;
- unsigned int end;
-
- lineno++;
- if (buf[0] == 0)
- continue;
- end = strlen(buf) - 1;
- /* Continue reading next line if it ends with a backslash */
- while (buf[end] == '\\' && end < sizeof(buf) - 2 &&
- fgets(buf + end, sizeof(buf) - end, file)) {
- end = strlen(buf) - 1;
- lineno++;
- }
-
- if (blkid_parse_line(cache, &dev, buf) < 0) {
- DBG(DEBUG_READ,
- printf("blkid: bad format on line %d\n", lineno));
- continue;
- }
- }
- fclose(file);
-
- /*
- * Initially we do not need to write out the cache file.
- */
- cache->bic_flags &= ~BLKID_BIC_FL_CHANGED;
- cache->bic_ftime = st.st_mtime;
-
- return;
-errout:
- close(fd);
-}
-
-#ifdef TEST_PROGRAM
-static void debug_dump_dev(blkid_dev dev)
-{
- struct list_head *p;
-
- if (!dev) {
- printf(" dev: NULL\n");
- return;
- }
-
- printf(" dev: name = %s\n", dev->bid_name);
- printf(" dev: DEVNO=\"0x%0llx\"\n", dev->bid_devno);
- printf(" dev: TIME=\"%lu\"\n", dev->bid_time);
- printf(" dev: PRI=\"%d\"\n", dev->bid_pri);
- printf(" dev: flags = 0x%08X\n", dev->bid_flags);
-
- list_for_each(p, &dev->bid_tags) {
- blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
- if (tag)
- printf(" tag: %s=\"%s\"\n", tag->bit_name,
- tag->bit_val);
- else
- printf(" tag: NULL\n");
- }
- bb_putchar('\n');
-}
-
-int main(int argc, char**argv)
-{
- blkid_cache cache = NULL;
- int ret;
-
- blkid_debug_mask = DEBUG_ALL;
- if (argc > 2) {
- fprintf(stderr, "Usage: %s [filename]\n"
- "Test parsing of the cache (filename)\n", argv[0]);
- exit(1);
- }
- if ((ret = blkid_get_cache(&cache, argv[1])) < 0)
- fprintf(stderr, "error %d reading cache file %s\n", ret,
- argv[1] ? argv[1] : BLKID_CACHE_FILE);
-
- blkid_put_cache(cache);
-
- return ret;
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/blkid/resolve.c b/release/src/router/busybox/e2fsprogs/blkid/resolve.c
deleted file mode 100644
index 295ca61bff..0000000000
--- a/release/src/router/busybox/e2fsprogs/blkid/resolve.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * resolve.c - resolve names and tags into specific devices
- *
- * Copyright (C) 2001, 2003 Theodore Ts'o.
- * Copyright (C) 2001 Andreas Dilger
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <stdlib.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "blkidP.h"
-#include "probe.h"
-
-/*
- * Find a tagname (e.g. LABEL or UUID) on a specific device.
- */
-char *blkid_get_tag_value(blkid_cache cache, const char *tagname,
- const char *devname)
-{
- blkid_tag found;
- blkid_dev dev;
- blkid_cache c = cache;
- char *ret = NULL;
-
- DBG(DEBUG_RESOLVE, printf("looking for %s on %s\n", tagname, devname));
-
- if (!devname)
- return NULL;
-
- if (!cache) {
- if (blkid_get_cache(&c, NULL) < 0)
- return NULL;
- }
-
- if ((dev = blkid_get_dev(c, devname, BLKID_DEV_NORMAL)) &&
- (found = blkid_find_tag_dev(dev, tagname)))
- ret = blkid_strdup(found->bit_val);
-
- if (!cache)
- blkid_put_cache(c);
-
- return ret;
-}
-
-/*
- * Locate a device name from a token (NAME=value string), or (name, value)
- * pair. In the case of a token, value is ignored. If the "token" is not
- * of the form "NAME=value" and there is no value given, then it is assumed
- * to be the actual devname and a copy is returned.
- */
-char *blkid_get_devname(blkid_cache cache, const char *token,
- const char *value)
-{
- blkid_dev dev;
- blkid_cache c = cache;
- char *t = NULL, *v = NULL;
- char *ret = NULL;
-
- if (!token)
- return NULL;
-
- if (!cache) {
- if (blkid_get_cache(&c, NULL) < 0)
- return NULL;
- }
-
- DBG(DEBUG_RESOLVE,
- printf("looking for %s%s%s %s\n", token, value ? "=" : "",
- value ? value : "", cache ? "in cache" : "from disk"));
-
- if (!value) {
- if (!strchr(token, '='))
- return blkid_strdup(token);
- blkid_parse_tag_string(token, &t, &v);
- if (!t || !v)
- goto errout;
- token = t;
- value = v;
- }
-
- dev = blkid_find_dev_with_tag(c, token, value);
- if (!dev)
- goto errout;
-
- ret = blkid_strdup(blkid_dev_devname(dev));
-
-errout:
- free(t);
- free(v);
- if (!cache) {
- blkid_put_cache(c);
- }
- return ret;
-}
-
-#ifdef TEST_PROGRAM
-int main(int argc, char **argv)
-{
- char *value;
- blkid_cache cache;
-
- blkid_debug_mask = DEBUG_ALL;
- if (argc != 2 && argc != 3) {
- fprintf(stderr, "Usage:\t%s tagname=value\n"
- "\t%s tagname devname\n"
- "Find which device holds a given token or\n"
- "Find what the value of a tag is in a device\n",
- argv[0], argv[0]);
- exit(1);
- }
- if (blkid_get_cache(&cache, bb_dev_null) < 0) {
- fprintf(stderr, "Can't get blkid cache\n");
- exit(1);
- }
-
- if (argv[2]) {
- value = blkid_get_tag_value(cache, argv[1], argv[2]);
- printf("%s has tag %s=%s\n", argv[2], argv[1],
- value ? value : "<missing>");
- } else {
- value = blkid_get_devname(cache, argv[1], NULL);
- printf("%s has tag %s\n", value ? value : "<none>", argv[1]);
- }
- blkid_put_cache(cache);
- return value ? 0 : 1;
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/blkid/save.c b/release/src/router/busybox/e2fsprogs/blkid/save.c
deleted file mode 100644
index e60cca445f..0000000000
--- a/release/src/router/busybox/e2fsprogs/blkid/save.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * save.c - write the cache struct to disk
- *
- * Copyright (C) 2001 by Andreas Dilger
- * Copyright (C) 2003 Theodore Ts'o
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_MKDEV_H
-#include <sys/mkdev.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include "blkidP.h"
-
-static int save_dev(blkid_dev dev, FILE *file)
-{
- struct list_head *p;
-
- if (!dev || dev->bid_name[0] != '/')
- return 0;
-
- DBG(DEBUG_SAVE,
- printf("device %s, type %s\n", dev->bid_name, dev->bid_type));
-
- fprintf(file,
- "<device DEVNO=\"0x%04lx\" TIME=\"%lu\"",
- (unsigned long) dev->bid_devno, dev->bid_time);
- if (dev->bid_pri)
- fprintf(file, " PRI=\"%d\"", dev->bid_pri);
- list_for_each(p, &dev->bid_tags) {
- blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
- fprintf(file, " %s=\"%s\"", tag->bit_name,tag->bit_val);
- }
- fprintf(file, ">%s</device>\n", dev->bid_name);
-
- return 0;
-}
-
-/*
- * Write out the cache struct to the cache file on disk.
- */
-int blkid_flush_cache(blkid_cache cache)
-{
- struct list_head *p;
- char *tmp = NULL;
- const char *opened = NULL;
- const char *filename;
- FILE *file = NULL;
- int fd, ret = 0;
- struct stat st;
-
- if (!cache)
- return -BLKID_ERR_PARAM;
-
- if (list_empty(&cache->bic_devs) ||
- !(cache->bic_flags & BLKID_BIC_FL_CHANGED)) {
- DBG(DEBUG_SAVE, printf("skipping cache file write\n"));
- return 0;
- }
-
- filename = cache->bic_filename ? cache->bic_filename: BLKID_CACHE_FILE;
-
- /* If we can't write to the cache file, then don't even try */
- if (((ret = stat(filename, &st)) < 0 && errno != ENOENT) ||
- (ret == 0 && access(filename, W_OK) < 0)) {
- DBG(DEBUG_SAVE,
- printf("can't write to cache file %s\n", filename));
- return 0;
- }
-
- /*
- * Try and create a temporary file in the same directory so
- * that in case of error we don't overwrite the cache file.
- * If the cache file doesn't yet exist, it isn't a regular
- * file (e.g. /dev/null or a socket), or we couldn't create
- * a temporary file then we open it directly.
- */
- if (ret == 0 && S_ISREG(st.st_mode)) {
- tmp = xmalloc(strlen(filename) + 8);
- sprintf(tmp, "%s-XXXXXX", filename);
- fd = mkstemp(tmp);
- if (fd >= 0) {
- file = xfdopen_for_write(fd);
- opened = tmp;
- }
- fchmod(fd, 0644);
- }
-
- if (!file) {
- file = fopen_for_write(filename);
- opened = filename;
- }
-
- DBG(DEBUG_SAVE,
- printf("writing cache file %s (really %s)\n",
- filename, opened));
-
- if (!file) {
- ret = errno;
- goto errout;
- }
-
- list_for_each(p, &cache->bic_devs) {
- blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs);
- if (!dev->bid_type)
- continue;
- if ((ret = save_dev(dev, file)) < 0)
- break;
- }
-
- if (ret >= 0) {
- cache->bic_flags &= ~BLKID_BIC_FL_CHANGED;
- ret = 1;
- }
-
- fclose(file);
- if (opened != filename) {
- if (ret < 0) {
- unlink(opened);
- DBG(DEBUG_SAVE,
- printf("unlinked temp cache %s\n", opened));
- } else {
- char *backup;
-
- backup = xmalloc(strlen(filename) + 5);
- sprintf(backup, "%s.old", filename);
- unlink(backup);
- link(filename, backup);
- free(backup);
- rename(opened, filename);
- DBG(DEBUG_SAVE,
- printf("moved temp cache %s\n", opened));
- }
- }
-
-errout:
- free(tmp);
- return ret;
-}
-
-#ifdef TEST_PROGRAM
-int main(int argc, char **argv)
-{
- blkid_cache cache = NULL;
- int ret;
-
- blkid_debug_mask = DEBUG_ALL;
- if (argc > 2) {
- fprintf(stderr, "Usage: %s [filename]\n"
- "Test loading/saving a cache (filename)\n", argv[0]);
- exit(1);
- }
-
- if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
- fprintf(stderr, "%s: error creating cache (%d)\n",
- argv[0], ret);
- exit(1);
- }
- if ((ret = blkid_probe_all(cache)) < 0) {
- fprintf(stderr, "error (%d) probing devices\n", ret);
- exit(1);
- }
- cache->bic_filename = blkid_strdup(argv[1]);
-
- if ((ret = blkid_flush_cache(cache)) < 0) {
- fprintf(stderr, "error (%d) saving cache\n", ret);
- exit(1);
- }
-
- blkid_put_cache(cache);
-
- return ret;
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/blkid/tag.c b/release/src/router/busybox/e2fsprogs/blkid/tag.c
deleted file mode 100644
index 8337b46b6b..0000000000
--- a/release/src/router/busybox/e2fsprogs/blkid/tag.c
+++ /dev/null
@@ -1,431 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * tag.c - allocation/initialization/free routines for tag structs
- *
- * Copyright (C) 2001 Andreas Dilger
- * Copyright (C) 2003 Theodore Ts'o
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "blkidP.h"
-
-static blkid_tag blkid_new_tag(void)
-{
- blkid_tag tag;
-
- tag = xzalloc(sizeof(struct blkid_struct_tag));
-
- INIT_LIST_HEAD(&tag->bit_tags);
- INIT_LIST_HEAD(&tag->bit_names);
-
- return tag;
-}
-
-#ifdef CONFIG_BLKID_DEBUG
-void blkid_debug_dump_tag(blkid_tag tag)
-{
- if (!tag) {
- printf(" tag: NULL\n");
- return;
- }
-
- printf(" tag: %s=\"%s\"\n", tag->bit_name, tag->bit_val);
-}
-#endif
-
-void blkid_free_tag(blkid_tag tag)
-{
- if (!tag)
- return;
-
- DBG(DEBUG_TAG, printf(" freeing tag %s=%s\n", tag->bit_name,
- tag->bit_val ? tag->bit_val : "(NULL)"));
- DBG(DEBUG_TAG, blkid_debug_dump_tag(tag));
-
- list_del(&tag->bit_tags); /* list of tags for this device */
- list_del(&tag->bit_names); /* list of tags with this type */
-
- free(tag->bit_name);
- free(tag->bit_val);
- free(tag);
-}
-
-/*
- * Find the desired tag on a device. If value is NULL, then the
- * first such tag is returned, otherwise return only exact tag if found.
- */
-blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type)
-{
- struct list_head *p;
-
- if (!dev || !type)
- return NULL;
-
- list_for_each(p, &dev->bid_tags) {
- blkid_tag tmp = list_entry(p, struct blkid_struct_tag,
- bit_tags);
-
- if (!strcmp(tmp->bit_name, type))
- return tmp;
- }
- return NULL;
-}
-
-/*
- * Find the desired tag type in the cache.
- * We return the head tag for this tag type.
- */
-static blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type)
-{
- blkid_tag head = NULL, tmp;
- struct list_head *p;
-
- if (!cache || !type)
- return NULL;
-
- list_for_each(p, &cache->bic_tags) {
- tmp = list_entry(p, struct blkid_struct_tag, bit_tags);
- if (!strcmp(tmp->bit_name, type)) {
- DBG(DEBUG_TAG,
- printf(" found cache tag head %s\n", type));
- head = tmp;
- break;
- }
- }
- return head;
-}
-
-/*
- * Set a tag on an existing device.
- *
- * If value is NULL, then delete the tagsfrom the device.
- */
-int blkid_set_tag(blkid_dev dev, const char *name,
- const char *value, const int vlength)
-{
- blkid_tag t = 0, head = 0;
- char *val = NULL;
-
- if (!dev || !name)
- return -BLKID_ERR_PARAM;
-
- if (!(val = blkid_strndup(value, vlength)) && value)
- return -BLKID_ERR_MEM;
- t = blkid_find_tag_dev(dev, name);
- if (!value) {
- blkid_free_tag(t);
- } else if (t) {
- if (!strcmp(t->bit_val, val)) {
- /* Same thing, exit */
- free(val);
- return 0;
- }
- free(t->bit_val);
- t->bit_val = val;
- } else {
- /* Existing tag not present, add to device */
- if (!(t = blkid_new_tag()))
- goto errout;
- t->bit_name = blkid_strdup(name);
- t->bit_val = val;
- t->bit_dev = dev;
-
- list_add_tail(&t->bit_tags, &dev->bid_tags);
-
- if (dev->bid_cache) {
- head = blkid_find_head_cache(dev->bid_cache,
- t->bit_name);
- if (!head) {
- head = blkid_new_tag();
- if (!head)
- goto errout;
-
- DBG(DEBUG_TAG,
- printf(" creating new cache tag head %s\n", name));
- head->bit_name = blkid_strdup(name);
- if (!head->bit_name)
- goto errout;
- list_add_tail(&head->bit_tags,
- &dev->bid_cache->bic_tags);
- }
- list_add_tail(&t->bit_names, &head->bit_names);
- }
- }
-
- /* Link common tags directly to the device struct */
- if (!strcmp(name, "TYPE"))
- dev->bid_type = val;
- else if (!strcmp(name, "LABEL"))
- dev->bid_label = val;
- else if (!strcmp(name, "UUID"))
- dev->bid_uuid = val;
-
- if (dev->bid_cache)
- dev->bid_cache->bic_flags |= BLKID_BIC_FL_CHANGED;
- return 0;
-
-errout:
- blkid_free_tag(t);
- if (!t)
- free(val);
- blkid_free_tag(head);
- return -BLKID_ERR_MEM;
-}
-
-
-/*
- * Parse a "NAME=value" string. This is slightly different than
- * parse_token, because that will end an unquoted value at a space, while
- * this will assume that an unquoted value is the rest of the token (e.g.
- * if we are passed an already quoted string from the command-line we don't
- * have to both quote and escape quote so that the quotes make it to
- * us).
- *
- * Returns 0 on success, and -1 on failure.
- */
-int blkid_parse_tag_string(const char *token, char **ret_type, char **ret_val)
-{
- char *name, *value, *cp;
-
- DBG(DEBUG_TAG, printf("trying to parse '%s' as a tag\n", token));
-
- if (!token || !(cp = strchr(token, '=')))
- return -1;
-
- name = blkid_strdup(token);
- if (!name)
- return -1;
- value = name + (cp - token);
- *value++ = '\0';
- if (*value == '"' || *value == '\'') {
- char c = *value++;
- if (!(cp = strrchr(value, c)))
- goto errout; /* missing closing quote */
- *cp = '\0';
- }
- value = blkid_strdup(value);
- if (!value)
- goto errout;
-
- *ret_type = name;
- *ret_val = value;
-
- return 0;
-
-errout:
- free(name);
- return -1;
-}
-
-/*
- * Tag iteration routines for the public libblkid interface.
- *
- * These routines do not expose the list.h implementation, which are a
- * contamination of the namespace, and which force us to reveal far, far
- * too much of our internal implemenation. I'm not convinced I want
- * to keep list.h in the long term, anyway. It's fine for kernel
- * programming, but performance is not the #1 priority for this
- * library, and I really don't like the tradeoff of type-safety for
- * performance for this application. [tytso:20030125.2007EST]
- */
-
-/*
- * This series of functions iterate over all tags in a device
- */
-#define TAG_ITERATE_MAGIC 0x01a5284c
-
-struct blkid_struct_tag_iterate {
- int magic;
- blkid_dev dev;
- struct list_head *p;
-};
-
-blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev)
-{
- blkid_tag_iterate iter;
-
- iter = xmalloc(sizeof(struct blkid_struct_tag_iterate));
- iter->magic = TAG_ITERATE_MAGIC;
- iter->dev = dev;
- iter->p = dev->bid_tags.next;
- return iter;
-}
-
-/*
- * Return 0 on success, -1 on error
- */
-extern int blkid_tag_next(blkid_tag_iterate iter,
- const char **type, const char **value)
-{
- blkid_tag tag;
-
- *type = 0;
- *value = 0;
- if (!iter || iter->magic != TAG_ITERATE_MAGIC ||
- iter->p == &iter->dev->bid_tags)
- return -1;
- tag = list_entry(iter->p, struct blkid_struct_tag, bit_tags);
- *type = tag->bit_name;
- *value = tag->bit_val;
- iter->p = iter->p->next;
- return 0;
-}
-
-void blkid_tag_iterate_end(blkid_tag_iterate iter)
-{
- if (!iter || iter->magic != TAG_ITERATE_MAGIC)
- return;
- iter->magic = 0;
- free(iter);
-}
-
-/*
- * This function returns a device which matches a particular
- * type/value pair. If there is more than one device that matches the
- * search specification, it returns the one with the highest priority
- * value. This allows us to give preference to EVMS or LVM devices.
- *
- * XXX there should also be an interface which uses an iterator so we
- * can get all of the devices which match a type/value search parameter.
- */
-extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
- const char *type,
- const char *value)
-{
- blkid_tag head;
- blkid_dev dev;
- int pri;
- struct list_head *p;
-
- if (!cache || !type || !value)
- return NULL;
-
- blkid_read_cache(cache);
-
- DBG(DEBUG_TAG, printf("looking for %s=%s in cache\n", type, value));
-
-try_again:
- pri = -1;
- dev = 0;
- head = blkid_find_head_cache(cache, type);
-
- if (head) {
- list_for_each(p, &head->bit_names) {
- blkid_tag tmp = list_entry(p, struct blkid_struct_tag,
- bit_names);
-
- if (!strcmp(tmp->bit_val, value) &&
- tmp->bit_dev->bid_pri > pri) {
- dev = tmp->bit_dev;
- pri = dev->bid_pri;
- }
- }
- }
- if (dev && !(dev->bid_flags & BLKID_BID_FL_VERIFIED)) {
- dev = blkid_verify(cache, dev);
- if (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED))
- goto try_again;
- }
-
- if (!dev && !(cache->bic_flags & BLKID_BIC_FL_PROBED)) {
- if (blkid_probe_all(cache) < 0)
- return NULL;
- goto try_again;
- }
- return dev;
-}
-
-#ifdef TEST_PROGRAM
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#else
-extern char *optarg;
-extern int optind;
-#endif
-
-void usage(char *prog)
-{
- fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask] device "
- "[type value]\n",
- prog);
- fprintf(stderr, "\tList all tags for a device and exit\n", prog);
- exit(1);
-}
-
-int main(int argc, char **argv)
-{
- blkid_tag_iterate iter;
- blkid_cache cache = NULL;
- blkid_dev dev;
- int c, ret, found;
- int flags = BLKID_DEV_FIND;
- char *tmp;
- char *file = NULL;
- char *devname = NULL;
- char *search_type = NULL;
- char *search_value = NULL;
- const char *type, *value;
-
- while ((c = getopt (argc, argv, "m:f:")) != EOF)
- switch (c) {
- case 'f':
- file = optarg;
- break;
- case 'm':
- blkid_debug_mask = strtoul (optarg, &tmp, 0);
- if (*tmp) {
- fprintf(stderr, "Invalid debug mask: %d\n",
- optarg);
- exit(1);
- }
- break;
- case '?':
- usage(argv[0]);
- }
- if (argc > optind)
- devname = argv[optind++];
- if (argc > optind)
- search_type = argv[optind++];
- if (argc > optind)
- search_value = argv[optind++];
- if (!devname || (argc != optind))
- usage(argv[0]);
-
- if ((ret = blkid_get_cache(&cache, file)) != 0) {
- fprintf(stderr, "%s: error creating cache (%d)\n",
- argv[0], ret);
- exit(1);
- }
-
- dev = blkid_get_dev(cache, devname, flags);
- if (!dev) {
- fprintf(stderr, "%s: cannot find device in blkid cache\n");
- exit(1);
- }
- if (search_type) {
- found = blkid_dev_has_tag(dev, search_type, search_value);
- printf("Device %s: (%s, %s) %s\n", blkid_dev_devname(dev),
- search_type, search_value ? search_value : "NULL",
- found ? "FOUND" : "NOT FOUND");
- return !found;
- }
- printf("Device %s...\n", blkid_dev_devname(dev));
-
- iter = blkid_tag_iterate_begin(dev);
- while (blkid_tag_next(iter, &type, &value) == 0) {
- printf("\tTag %s has value %s\n", type, value);
- }
- blkid_tag_iterate_end(iter);
-
- blkid_put_cache(cache);
- return 0;
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/chattr.c b/release/src/router/busybox/e2fsprogs/chattr.c
index ae39d92245..043f395914 100644
--- a/release/src/router/busybox/e2fsprogs/chattr.c
+++ b/release/src/router/busybox/e2fsprogs/chattr.c
@@ -9,116 +9,106 @@
* This file can be redistributed under the terms of the GNU General
* Public License
*/
-
-/*
- * History:
- * 93/10/30 - Creation
- * 93/11/13 - Replace stat() calls by lstat() to avoid loops
- * 94/02/27 - Integrated in Ted's distribution
- * 98/12/29 - Ignore symlinks when working recursively (G M Sipe)
- * 98/12/29 - Display version info only when -V specified (G M Sipe)
- */
-
-#include <sys/types.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include "ext2fs/ext2_fs.h"
-
-#ifdef __GNUC__
-# define EXT2FS_ATTR(x) __attribute__(x)
-#else
-# define EXT2FS_ATTR(x)
-#endif
-
-#include "e2fsbb.h"
-#include "e2p/e2p.h"
+//config:config CHATTR
+//config: bool "chattr"
+//config: default y
+//config: help
+//config: chattr changes the file attributes on a second extended file system.
+
+//applet:IF_CHATTR(APPLET(chattr, BB_DIR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_CHATTR) += chattr.o e2fs_lib.o
+
+//usage:#define chattr_trivial_usage
+//usage: "[-R] [-+=AacDdijsStTu] [-v VERSION] [FILE]..."
+//usage:#define chattr_full_usage "\n\n"
+//usage: "Change ext2 file attributes\n"
+//usage: "\nModifiers:"
+//usage: "\n -,+,= Remove/add/set attributes"
+//usage: "\nAttributes:"
+//usage: "\n A Don't track atime"
+//usage: "\n a Append mode only"
+//usage: "\n c Enable compress"
+//usage: "\n D Write dir contents synchronously"
+//usage: "\n d Don't backup with dump"
+//usage: "\n i Cannot be modified (immutable)"
+//usage: "\n j Write all data to journal first"
+//usage: "\n s Zero disk storage when deleted"
+//usage: "\n S Write synchronously"
+//usage: "\n t Disable tail-merging of partial blocks with other files"
+//usage: "\n u Allow file to be undeleted"
+//usage: "\n -R Recurse"
+//usage: "\n -v VER Set version/generation number"
+
+#include "libbb.h"
+#include "e2fs_lib.h"
#define OPT_ADD 1
#define OPT_REM 2
#define OPT_SET 4
#define OPT_SET_VER 8
-static int flags;
-static int recursive;
-
-static unsigned long version;
-
-static unsigned long af;
-static unsigned long rf;
-static unsigned long sf;
-struct flags_char {
- unsigned long flag;
- char optchar;
-};
-
-static const struct flags_char flags_array[] = {
- { EXT2_NOATIME_FL, 'A' },
- { EXT2_SYNC_FL, 'S' },
- { EXT2_DIRSYNC_FL, 'D' },
- { EXT2_APPEND_FL, 'a' },
- { EXT2_COMPR_FL, 'c' },
- { EXT2_NODUMP_FL, 'd' },
- { EXT2_IMMUTABLE_FL, 'i' },
- { EXT3_JOURNAL_DATA_FL, 'j' },
- { EXT2_SECRM_FL, 's' },
- { EXT2_UNRM_FL, 'u' },
- { EXT2_NOTAIL_FL, 't' },
- { EXT2_TOPDIR_FL, 'T' },
- { 0, 0 }
+struct globals {
+ unsigned long version;
+ unsigned long af;
+ unsigned long rf;
+ smallint flags;
+ smallint recursive;
};
static unsigned long get_flag(char c)
{
- const struct flags_char *fp;
- for (fp = flags_array; fp->flag; fp++)
- if (fp->optchar == c)
- return fp->flag;
+ const char *fp = strchr(e2attr_flags_sname_chattr, c);
+ if (fp)
+ return e2attr_flags_value_chattr[fp - e2attr_flags_sname_chattr];
bb_show_usage();
- return 0;
}
-static int decode_arg(char *arg)
+static int decode_arg(const char *arg, struct globals *gp)
{
unsigned long *fl;
char opt = *arg++;
+ fl = &gp->af;
if (opt == '-') {
- flags |= OPT_REM;
- fl = &rf;
+ gp->flags |= OPT_REM;
+ fl = &gp->rf;
} else if (opt == '+') {
- flags |= OPT_ADD;
- fl = &af;
+ gp->flags |= OPT_ADD;
} else if (opt == '=') {
- flags |= OPT_SET;
- fl = &sf;
+ gp->flags |= OPT_SET;
} else
- return EOF;
+ return 0;
- for (; *arg; ++arg)
- (*fl) |= get_flag(*arg);
+ while (*arg)
+ *fl |= get_flag(*arg++);
return 1;
}
-static int chattr_dir_proc(const char *, struct dirent *, void *);
+static void change_attributes(const char *name, struct globals *gp);
-static void change_attributes(const char * name)
+static int FAST_FUNC chattr_dir_proc(const char *dir_name, struct dirent *de, void *gp)
+{
+ char *path = concat_subpath_file(dir_name, de->d_name);
+ /* path is NULL if de->d_name is "." or "..", else... */
+ if (path) {
+ change_attributes(path, gp);
+ free(path);
+ }
+ return 0;
+}
+
+static void change_attributes(const char *name, struct globals *gp)
{
unsigned long fsflags;
struct stat st;
- if (lstat(name, &st) == -1) {
- bb_error_msg("stat %s failed", name);
+ if (lstat(name, &st) != 0) {
+ bb_perror_msg("stat %s", name);
return;
}
- if (S_ISLNK(st.st_mode) && recursive)
+ if (S_ISLNK(st.st_mode) && gp->recursive)
return;
/* Don't try to open device files, fifos etc. We probably
@@ -128,93 +118,76 @@ static void change_attributes(const char * name)
if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode))
return;
- if (flags & OPT_SET_VER)
- if (fsetversion(name, version) == -1)
- bb_error_msg("setting version on %s", name);
+ if (gp->flags & OPT_SET_VER)
+ if (fsetversion(name, gp->version) != 0)
+ bb_perror_msg("setting version on %s", name);
- if (flags & OPT_SET) {
- fsflags = sf;
+ if (gp->flags & OPT_SET) {
+ fsflags = gp->af;
} else {
- if (fgetflags(name, &fsflags) == -1) {
- bb_error_msg("reading flags on %s", name);
+ if (fgetflags(name, &fsflags) != 0) {
+ bb_perror_msg("reading flags on %s", name);
goto skip_setflags;
}
- if (flags & OPT_REM)
- fsflags &= ~rf;
- if (flags & OPT_ADD)
- fsflags |= af;
+ /*if (gp->flags & OPT_REM) - not needed, rf is zero otherwise */
+ fsflags &= ~gp->rf;
+ /*if (gp->flags & OPT_ADD) - not needed, af is zero otherwise */
+ fsflags |= gp->af;
+ /* What is this? And why it's not done for SET case? */
if (!S_ISDIR(st.st_mode))
fsflags &= ~EXT2_DIRSYNC_FL;
}
- if (fsetflags(name, fsflags) == -1)
- bb_error_msg("setting flags on %s", name);
+ if (fsetflags(name, fsflags) != 0)
+ bb_perror_msg("setting flags on %s", name);
-skip_setflags:
- if (S_ISDIR(st.st_mode) && recursive)
- iterate_on_dir(name, chattr_dir_proc, NULL);
-}
-
-static int chattr_dir_proc(const char *dir_name, struct dirent *de,
- void *private EXT2FS_ATTR((unused)))
-{
- /*if (strcmp(de->d_name, ".") || strcmp(de->d_name, "..")) {*/
- if (de->d_name[0] == '.'
- && (!de->d_name[1] || (de->d_name[1] == '.' && !de->d_name[2]))
- ) {
- char *path = concat_subpath_file(dir_name, de->d_name);
- if (path) {
- change_attributes(path);
- free(path);
- }
- }
- return 0;
+ skip_setflags:
+ if (gp->recursive && S_ISDIR(st.st_mode))
+ iterate_on_dir(name, chattr_dir_proc, gp);
}
int chattr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int chattr_main(int argc, char **argv)
+int chattr_main(int argc UNUSED_PARAM, char **argv)
{
- int i;
+ struct globals g;
char *arg;
- /* parse the args */
- for (i = 1; i < argc; ++i) {
- arg = argv[i];
+ memset(&g, 0, sizeof(g));
+ /* parse the args */
+ while ((arg = *++argv)) {
/* take care of -R and -v <version> */
- if (arg[0] == '-') {
- if (arg[1] == 'R' && arg[2] == '\0') {
- recursive = 1;
- continue;
- } else if (arg[1] == 'v' && arg[2] == '\0') {
- char *tmp;
- ++i;
- if (i >= argc)
- bb_show_usage();
- version = strtol(argv[i], &tmp, 0);
- if (*tmp)
- bb_error_msg_and_die("bad version '%s'", arg);
- flags |= OPT_SET_VER;
+ if (arg[0] == '-'
+ && (arg[1] == 'R' || arg[1] == 'v')
+ && !arg[2]
+ ) {
+ if (arg[1] == 'R') {
+ g.recursive = 1;
continue;
}
+ /* arg[1] == 'v' */
+ if (!*++argv)
+ bb_show_usage();
+ g.version = xatoul(*argv);
+ g.flags |= OPT_SET_VER;
+ continue;
}
- if (decode_arg(arg) == EOF)
+ if (!decode_arg(arg, &g))
break;
}
/* run sanity checks on all the arguments given us */
- if (i >= argc)
+ if (!*argv)
bb_show_usage();
- if ((flags & OPT_SET) && ((flags & OPT_ADD) || (flags & OPT_REM)))
+ if ((g.flags & OPT_SET) && (g.flags & (OPT_ADD|OPT_REM)))
bb_error_msg_and_die("= is incompatible with - and +");
- if ((rf & af) != 0)
- bb_error_msg_and_die("Can't set and unset a flag");
- if (!flags)
- bb_error_msg_and_die("Must use '-v', =, - or +");
+ if (g.rf & g.af)
+ bb_error_msg_and_die("can't set and unset a flag");
+ if (!g.flags)
+ bb_error_msg_and_die("must use '-v', =, - or +");
/* now run chattr on all the files passed to us */
- while (i < argc)
- change_attributes(argv[i++]);
+ do change_attributes(*argv, &g); while (*++argv);
return EXIT_SUCCESS;
}
diff --git a/release/src/router/busybox/e2fsprogs/e2fs_lib.c b/release/src/router/busybox/e2fsprogs/e2fs_lib.c
index a6aec9484f..6ce655be36 100644
--- a/release/src/router/busybox/e2fsprogs/e2fs_lib.c
+++ b/release/src/router/busybox/e2fsprogs/e2fs_lib.c
@@ -149,14 +149,14 @@ const uint32_t e2attr_flags_value[] = {
EXT2_TOPDIR_FL
};
-const char e2attr_flags_sname[] =
+const char e2attr_flags_sname[] ALIGN1 =
#ifdef ENABLE_COMPRESSION
"BZXE"
#endif
"I"
"suSDiadAcjtT";
-static const char e2attr_flags_lname[] =
+static const char e2attr_flags_lname[] ALIGN1 =
#ifdef ENABLE_COMPRESSION
"Compressed_File" "\0"
"Compressed_Dirty_File" "\0"
diff --git a/release/src/router/busybox/e2fsprogs/e2fs_lib.h b/release/src/router/busybox/e2fsprogs/e2fs_lib.h
index fbabe9f46b..f2ae56f433 100644
--- a/release/src/router/busybox/e2fsprogs/e2fs_lib.h
+++ b/release/src/router/busybox/e2fsprogs/e2fs_lib.h
@@ -44,9 +44,4 @@ extern const char e2attr_flags_sname[];
#define e2attr_flags_sname_chattr (&e2attr_flags_sname[1])
#endif
-/* uuid helpers */
-#define uuid_clear(uu) memset(uu, 0, sizeof(uu))
-#define uuid_copy(dst,src) memcpy(dst, src, sizeof(dst))
-#define uuid_is_null(uu) (!memcmp(uu, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", sizeof(uu)))
-
POP_SAVED_FUNCTION_VISIBILITY
diff --git a/release/src/router/busybox/e2fsprogs/e2fsbb.h b/release/src/router/busybox/e2fsprogs/e2fsbb.h
deleted file mode 100644
index d31c319556..0000000000
--- a/release/src/router/busybox/e2fsprogs/e2fsbb.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * File: e2fsbb.h
- *
- * Redefine a bunch of e2fsprogs stuff to use busybox routines
- * instead. This makes upgrade between e2fsprogs versions easy.
- */
-
-#ifndef E2FSBB_H
-#define E2FSBB_H 1
-
-#include "libbb.h"
-
-/* version we've last synced against */
-#define E2FSPROGS_VERSION "1.38"
-#define E2FSPROGS_DATE "30-Jun-2005"
-
-typedef long errcode_t;
-#define ERRCODE_RANGE 8
-#define error_message(code) strerror((int) (code & ((1<<ERRCODE_RANGE)-1)))
-
-/* header defines */
-#define ENABLE_HTREE 1
-#define HAVE_ERRNO_H 1
-#define HAVE_EXT2_IOCTLS 1
-#define HAVE_LINUX_FD_H 1
-#define HAVE_MNTENT_H 1
-#define HAVE_NETINET_IN_H 1
-#define HAVE_NET_IF_H 1
-#define HAVE_SYS_IOCTL_H 1
-#define HAVE_SYS_MOUNT_H 1
-#define HAVE_SYS_QUEUE_H 1
-#define HAVE_SYS_STAT_H 1
-#define HAVE_SYS_TYPES_H 1
-#define HAVE_UNISTD_H 1
-
-/* Endianness */
-#if BB_BIG_ENDIAN
-#define ENABLE_SWAPFS 1
-#define WORDS_BIGENDIAN 1
-#endif
-
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/e2fsck.c b/release/src/router/busybox/e2fsprogs/e2fsck.c
deleted file mode 100644
index db9f8ce965..0000000000
--- a/release/src/router/busybox/e2fsprogs/e2fsck.c
+++ /dev/null
@@ -1,13521 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * e2fsck
- *
- * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
- * Copyright (C) 2006 Garrett Kajmowicz
- *
- * Dictionary Abstract Data Type
- * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
- * Free Software License:
- * All rights are reserved by the author, with the following exceptions:
- * Permission is granted to freely reproduce and distribute this software,
- * possibly in exchange for a fee, provided that this copyright notice appears
- * intact. Permission is also granted to adapt this software to produce
- * derivative works, as long as the modified versions carry this copyright
- * notice and additional notices stating that the work has been modified.
- * This source code may be translated into executable form and incorporated
- * into proprietary software; there is no requirement for such software to
- * contain a copyright notice related to this source.
- *
- * linux/fs/recovery and linux/fs/revoke
- * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
- *
- * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
- *
- * Journal recovery routines for the generic filesystem journaling code;
- * part of the ext2fs journaling system.
- *
- * Licensed under GPLv2 or later, see file LICENSE in this source tree.
- */
-
-//usage:#define e2fsck_trivial_usage
-//usage: "[-panyrcdfvstDFSV] [-b superblock] [-B blocksize] "
-//usage: "[-I inode_buffer_blocks] [-P process_inode_size] "
-//usage: "[-l|-L bad_blocks_file] [-C fd] [-j external_journal] "
-//usage: "[-E extended-options] device"
-//usage:#define e2fsck_full_usage "\n\n"
-//usage: "Check ext2/ext3 file system\n"
-//usage: "\n -p Automatic repair (no questions)"
-//usage: "\n -n Make no changes to the filesystem"
-//usage: "\n -y Assume 'yes' to all questions"
-//usage: "\n -c Check for bad blocks and add them to the badblock list"
-//usage: "\n -f Force checking even if filesystem is marked clean"
-//usage: "\n -v Verbose"
-//usage: "\n -b superblock Use alternative superblock"
-//usage: "\n -B blocksize Force blocksize when looking for superblock"
-//usage: "\n -j journal Set location of the external journal"
-//usage: "\n -l file Add to badblocks list"
-//usage: "\n -L file Set badblocks list"
-
-//usage:#define fsck_ext2_trivial_usage NOUSAGE_STR
-//usage:#define fsck_ext2_full_usage ""
-
-//usage:#define fsck_ext3_trivial_usage NOUSAGE_STR
-//usage:#define fsck_ext3_full_usage ""
-
-#include "e2fsck.h" /*Put all of our defines here to clean things up*/
-
-#define _(x) x
-#define N_(x) x
-
-/*
- * Procedure declarations
- */
-
-static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
-
-/* pass1.c */
-static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int fl_bool);
-
-/* pass2.c */
-static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
- ext2_ino_t ino, char *buf);
-
-/* pass3.c */
-static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
-static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
- int num, int gauranteed_size);
-static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
-static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
- int adj);
-
-/* rehash.c */
-static void e2fsck_rehash_directories(e2fsck_t ctx);
-
-/* util.c */
-static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
- const char *description);
-static int ask(e2fsck_t ctx, const char * string, int def);
-static void e2fsck_read_bitmaps(e2fsck_t ctx);
-static void preenhalt(e2fsck_t ctx);
-static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
- struct ext2_inode * inode, const char * proc);
-static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
- struct ext2_inode * inode, const char * proc);
-static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
- const char *name, io_manager manager);
-
-/* unix.c */
-static void e2fsck_clear_progbar(e2fsck_t ctx);
-static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
- float percent, unsigned int dpynum);
-
-
-/*
- * problem.h --- e2fsck problem error codes
- */
-
-typedef __u32 problem_t;
-
-struct problem_context {
- errcode_t errcode;
- ext2_ino_t ino, ino2, dir;
- struct ext2_inode *inode;
- struct ext2_dir_entry *dirent;
- blk_t blk, blk2;
- e2_blkcnt_t blkcount;
- int group;
- __u64 num;
- const char *str;
-};
-
-
-/*
- * Function declarations
- */
-static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
-static int end_problem_latch(e2fsck_t ctx, int mask);
-static int set_latch_flags(int mask, int setflags, int clearflags);
-static void clear_problem_context(struct problem_context *ctx);
-
-/*
- * Dictionary Abstract Data Type
- * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
- *
- * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
- * kazlib_1_20
- */
-
-#ifndef DICT_H
-#define DICT_H
-
-/*
- * Blurb for inclusion into C++ translation units
- */
-
-typedef unsigned long dictcount_t;
-#define DICTCOUNT_T_MAX ULONG_MAX
-
-/*
- * The dictionary is implemented as a red-black tree
- */
-
-typedef enum { dnode_red, dnode_black } dnode_color_t;
-
-typedef struct dnode_t {
- struct dnode_t *dict_left;
- struct dnode_t *dict_right;
- struct dnode_t *dict_parent;
- dnode_color_t dict_color;
- const void *dict_key;
- void *dict_data;
-} dnode_t;
-
-typedef int (*dict_comp_t)(const void *, const void *);
-typedef void (*dnode_free_t)(dnode_t *);
-
-typedef struct dict_t {
- dnode_t dict_nilnode;
- dictcount_t dict_nodecount;
- dictcount_t dict_maxcount;
- dict_comp_t dict_compare;
- dnode_free_t dict_freenode;
- int dict_dupes;
-} dict_t;
-
-typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
-
-typedef struct dict_load_t {
- dict_t *dict_dictptr;
- dnode_t dict_nilnode;
-} dict_load_t;
-
-#define dict_count(D) ((D)->dict_nodecount)
-#define dnode_get(N) ((N)->dict_data)
-#define dnode_getkey(N) ((N)->dict_key)
-
-#endif
-
-/*
- * Compatibility header file for e2fsck which should be included
- * instead of linux/jfs.h
- *
- * Copyright (C) 2000 Stephen C. Tweedie
- */
-
-/*
- * Pull in the definition of the e2fsck context structure
- */
-
-struct buffer_head {
- char b_data[8192];
- e2fsck_t b_ctx;
- io_channel b_io;
- int b_size;
- blk_t b_blocknr;
- int b_dirty;
- int b_uptodate;
- int b_err;
-};
-
-
-#define K_DEV_FS 1
-#define K_DEV_JOURNAL 2
-
-#define lock_buffer(bh) do {} while (0)
-#define unlock_buffer(bh) do {} while (0)
-#define buffer_req(bh) 1
-#define do_readahead(journal, start) do {} while (0)
-
-static e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
-
-typedef struct {
- int object_length;
-} kmem_cache_t;
-
-#define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
-
-/*
- * We use the standard libext2fs portability tricks for inline
- * functions.
- */
-
-static kmem_cache_t * do_cache_create(int len)
-{
- kmem_cache_t *new_cache;
-
- new_cache = xmalloc(sizeof(*new_cache));
- new_cache->object_length = len;
- return new_cache;
-}
-
-static void do_cache_destroy(kmem_cache_t *cache)
-{
- free(cache);
-}
-
-
-/*
- * Dictionary Abstract Data Type
- */
-
-
-/*
- * These macros provide short convenient names for structure members,
- * which are embellished with dict_ prefixes so that they are
- * properly confined to the documented namespace. It's legal for a
- * program which uses dict to define, for instance, a macro called ``parent''.
- * Such a macro would interfere with the dnode_t struct definition.
- * In general, highly portable and reusable C modules which expose their
- * structures need to confine structure member names to well-defined spaces.
- * The resulting identifiers aren't necessarily convenient to use, nor
- * readable, in the implementation, however!
- */
-
-#define left dict_left
-#define right dict_right
-#define parent dict_parent
-#define color dict_color
-#define key dict_key
-#define data dict_data
-
-#define nilnode dict_nilnode
-#define maxcount dict_maxcount
-#define compare dict_compare
-#define dupes dict_dupes
-
-#define dict_root(D) ((D)->nilnode.left)
-#define dict_nil(D) (&(D)->nilnode)
-
-static void dnode_free(dnode_t *node);
-
-/*
- * Perform a ``left rotation'' adjustment on the tree. The given node P and
- * its right child C are rearranged so that the P instead becomes the left
- * child of C. The left subtree of C is inherited as the new right subtree
- * for P. The ordering of the keys within the tree is thus preserved.
- */
-
-static void rotate_left(dnode_t *upper)
-{
- dnode_t *lower, *lowleft, *upparent;
-
- lower = upper->right;
- upper->right = lowleft = lower->left;
- lowleft->parent = upper;
-
- lower->parent = upparent = upper->parent;
-
- /* don't need to check for root node here because root->parent is
- the sentinel nil node, and root->parent->left points back to root */
-
- if (upper == upparent->left) {
- upparent->left = lower;
- } else {
- assert (upper == upparent->right);
- upparent->right = lower;
- }
-
- lower->left = upper;
- upper->parent = lower;
-}
-
-/*
- * This operation is the ``mirror'' image of rotate_left. It is
- * the same procedure, but with left and right interchanged.
- */
-
-static void rotate_right(dnode_t *upper)
-{
- dnode_t *lower, *lowright, *upparent;
-
- lower = upper->left;
- upper->left = lowright = lower->right;
- lowright->parent = upper;
-
- lower->parent = upparent = upper->parent;
-
- if (upper == upparent->right) {
- upparent->right = lower;
- } else {
- assert (upper == upparent->left);
- upparent->left = lower;
- }
-
- lower->right = upper;
- upper->parent = lower;
-}
-
-/*
- * Do a postorder traversal of the tree rooted at the specified
- * node and free everything under it. Used by dict_free().
- */
-
-static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
-{
- if (node == nil)
- return;
- free_nodes(dict, node->left, nil);
- free_nodes(dict, node->right, nil);
- dict->dict_freenode(node);
-}
-
-/*
- * Verify that the tree contains the given node. This is done by
- * traversing all of the nodes and comparing their pointers to the
- * given pointer. Returns 1 if the node is found, otherwise
- * returns zero. It is intended for debugging purposes.
- */
-
-static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
-{
- if (root != nil) {
- return root == node
- || verify_dict_has_node(nil, root->left, node)
- || verify_dict_has_node(nil, root->right, node);
- }
- return 0;
-}
-
-
-/*
- * Select a different set of node allocator routines.
- */
-
-static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
-{
- assert(dict_count(dict) == 0);
- dict->dict_freenode = fr;
-}
-
-/*
- * Free all the nodes in the dictionary by using the dictionary's
- * installed free routine. The dictionary is emptied.
- */
-
-static void dict_free_nodes(dict_t *dict)
-{
- dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
- free_nodes(dict, root, nil);
- dict->dict_nodecount = 0;
- dict->nilnode.left = &dict->nilnode;
- dict->nilnode.right = &dict->nilnode;
-}
-
-/*
- * Initialize a user-supplied dictionary object.
- */
-
-static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
-{
- dict->compare = comp;
- dict->dict_freenode = dnode_free;
- dict->dict_nodecount = 0;
- dict->maxcount = maxcount;
- dict->nilnode.left = &dict->nilnode;
- dict->nilnode.right = &dict->nilnode;
- dict->nilnode.parent = &dict->nilnode;
- dict->nilnode.color = dnode_black;
- dict->dupes = 0;
- return dict;
-}
-
-/*
- * Locate a node in the dictionary having the given key.
- * If the node is not found, a null a pointer is returned (rather than
- * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
- * located node is returned.
- */
-
-static dnode_t *dict_lookup(dict_t *dict, const void *key)
-{
- dnode_t *root = dict_root(dict);
- dnode_t *nil = dict_nil(dict);
- dnode_t *saved;
- int result;
-
- /* simple binary search adapted for trees that contain duplicate keys */
-
- while (root != nil) {
- result = dict->compare(key, root->key);
- if (result < 0)
- root = root->left;
- else if (result > 0)
- root = root->right;
- else {
- if (!dict->dupes) { /* no duplicates, return match */
- return root;
- } else { /* could be dupes, find leftmost one */
- do {
- saved = root;
- root = root->left;
- while (root != nil && dict->compare(key, root->key))
- root = root->right;
- } while (root != nil);
- return saved;
- }
- }
- }
-
- return NULL;
-}
-
-/*
- * Insert a node into the dictionary. The node should have been
- * initialized with a data field. All other fields are ignored.
- * The behavior is undefined if the user attempts to insert into
- * a dictionary that is already full (for which the dict_isfull()
- * function returns true).
- */
-
-static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
-{
- dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
- dnode_t *parent = nil, *uncle, *grandpa;
- int result = -1;
-
- node->key = key;
-
- /* basic binary tree insert */
-
- while (where != nil) {
- parent = where;
- result = dict->compare(key, where->key);
- /* trap attempts at duplicate key insertion unless it's explicitly allowed */
- assert(dict->dupes || result != 0);
- if (result < 0)
- where = where->left;
- else
- where = where->right;
- }
-
- assert(where == nil);
-
- if (result < 0)
- parent->left = node;
- else
- parent->right = node;
-
- node->parent = parent;
- node->left = nil;
- node->right = nil;
-
- dict->dict_nodecount++;
-
- /* red black adjustments */
-
- node->color = dnode_red;
-
- while (parent->color == dnode_red) {
- grandpa = parent->parent;
- if (parent == grandpa->left) {
- uncle = grandpa->right;
- if (uncle->color == dnode_red) { /* red parent, red uncle */
- parent->color = dnode_black;
- uncle->color = dnode_black;
- grandpa->color = dnode_red;
- node = grandpa;
- parent = grandpa->parent;
- } else { /* red parent, black uncle */
- if (node == parent->right) {
- rotate_left(parent);
- parent = node;
- assert (grandpa == parent->parent);
- /* rotation between parent and child preserves grandpa */
- }
- parent->color = dnode_black;
- grandpa->color = dnode_red;
- rotate_right(grandpa);
- break;
- }
- } else { /* symmetric cases: parent == parent->parent->right */
- uncle = grandpa->left;
- if (uncle->color == dnode_red) {
- parent->color = dnode_black;
- uncle->color = dnode_black;
- grandpa->color = dnode_red;
- node = grandpa;
- parent = grandpa->parent;
- } else {
- if (node == parent->left) {
- rotate_right(parent);
- parent = node;
- assert (grandpa == parent->parent);
- }
- parent->color = dnode_black;
- grandpa->color = dnode_red;
- rotate_left(grandpa);
- break;
- }
- }
- }
-
- dict_root(dict)->color = dnode_black;
-}
-
-/*
- * Allocate a node using the dictionary's allocator routine, give it
- * the data item.
- */
-
-static dnode_t *dnode_init(dnode_t *dnode, void *data)
-{
- dnode->data = data;
- dnode->parent = NULL;
- dnode->left = NULL;
- dnode->right = NULL;
- return dnode;
-}
-
-static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
-{
- dnode_t *node = xmalloc(sizeof(dnode_t));
-
- dnode_init(node, data);
- dict_insert(dict, node, key);
- return 1;
-}
-
-/*
- * Return the node with the lowest (leftmost) key. If the dictionary is empty
- * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
- */
-
-static dnode_t *dict_first(dict_t *dict)
-{
- dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
-
- if (root != nil)
- while ((left = root->left) != nil)
- root = left;
-
- return (root == nil) ? NULL : root;
-}
-
-/*
- * Return the given node's successor node---the node which has the
- * next key in the left to right ordering. If the node has
- * no successor, a null pointer is returned rather than a pointer to
- * the nil node.
- */
-
-static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
-{
- dnode_t *nil = dict_nil(dict), *parent, *left;
-
- if (curr->right != nil) {
- curr = curr->right;
- while ((left = curr->left) != nil)
- curr = left;
- return curr;
- }
-
- parent = curr->parent;
-
- while (parent != nil && curr == parent->right) {
- curr = parent;
- parent = curr->parent;
- }
-
- return (parent == nil) ? NULL : parent;
-}
-
-
-static void dnode_free(dnode_t *node)
-{
- free(node);
-}
-
-
-#undef left
-#undef right
-#undef parent
-#undef color
-#undef key
-#undef data
-
-#undef nilnode
-#undef maxcount
-#undef compare
-#undef dupes
-
-
-/*
- * dirinfo.c --- maintains the directory information table for e2fsck.
- */
-
-/*
- * This subroutine is called during pass1 to create a directory info
- * entry. During pass1, the passed-in parent is 0; it will get filled
- * in during pass2.
- */
-static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
-{
- struct dir_info *dir;
- int i, j;
- ext2_ino_t num_dirs;
- errcode_t retval;
- unsigned long old_size;
-
- if (!ctx->dir_info) {
- ctx->dir_info_count = 0;
- retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
- if (retval)
- num_dirs = 1024; /* Guess */
- ctx->dir_info_size = num_dirs + 10;
- ctx->dir_info = (struct dir_info *)
- e2fsck_allocate_memory(ctx, ctx->dir_info_size
- * sizeof (struct dir_info),
- "directory map");
- }
-
- if (ctx->dir_info_count >= ctx->dir_info_size) {
- old_size = ctx->dir_info_size * sizeof(struct dir_info);
- ctx->dir_info_size += 10;
- retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
- sizeof(struct dir_info),
- &ctx->dir_info);
- if (retval) {
- ctx->dir_info_size -= 10;
- return;
- }
- }
-
- /*
- * Normally, add_dir_info is called with each inode in
- * sequential order; but once in a while (like when pass 3
- * needs to recreate the root directory or lost+found
- * directory) it is called out of order. In those cases, we
- * need to move the dir_info entries down to make room, since
- * the dir_info array needs to be sorted by inode number for
- * get_dir_info()'s sake.
- */
- if (ctx->dir_info_count &&
- ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
- for (i = ctx->dir_info_count-1; i > 0; i--)
- if (ctx->dir_info[i-1].ino < ino)
- break;
- dir = &ctx->dir_info[i];
- if (dir->ino != ino)
- for (j = ctx->dir_info_count++; j > i; j--)
- ctx->dir_info[j] = ctx->dir_info[j-1];
- } else
- dir = &ctx->dir_info[ctx->dir_info_count++];
-
- dir->ino = ino;
- dir->dotdot = parent;
- dir->parent = parent;
-}
-
-/*
- * get_dir_info() --- given an inode number, try to find the directory
- * information entry for it.
- */
-static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
-{
- int low, high, mid;
-
- low = 0;
- high = ctx->dir_info_count-1;
- if (!ctx->dir_info)
- return 0;
- if (ino == ctx->dir_info[low].ino)
- return &ctx->dir_info[low];
- if (ino == ctx->dir_info[high].ino)
- return &ctx->dir_info[high];
-
- while (low < high) {
- mid = (low+high)/2;
- if (mid == low || mid == high)
- break;
- if (ino == ctx->dir_info[mid].ino)
- return &ctx->dir_info[mid];
- if (ino < ctx->dir_info[mid].ino)
- high = mid;
- else
- low = mid;
- }
- return 0;
-}
-
-/*
- * Free the dir_info structure when it isn't needed any more.
- */
-static void e2fsck_free_dir_info(e2fsck_t ctx)
-{
- ext2fs_free_mem(&ctx->dir_info);
- ctx->dir_info_size = 0;
- ctx->dir_info_count = 0;
-}
-
-/*
- * Return the count of number of directories in the dir_info structure
- */
-static int e2fsck_get_num_dirinfo(e2fsck_t ctx)
-{
- return ctx->dir_info_count;
-}
-
-/*
- * A simple interator function
- */
-static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
-{
- if (*control >= ctx->dir_info_count)
- return 0;
-
- return ctx->dir_info + (*control)++;
-}
-
-/*
- * dirinfo.c --- maintains the directory information table for e2fsck.
- *
- */
-
-#ifdef ENABLE_HTREE
-
-/*
- * This subroutine is called during pass1 to create a directory info
- * entry. During pass1, the passed-in parent is 0; it will get filled
- * in during pass2.
- */
-static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
-{
- struct dx_dir_info *dir;
- int i, j;
- errcode_t retval;
- unsigned long old_size;
-
- if (!ctx->dx_dir_info) {
- ctx->dx_dir_info_count = 0;
- ctx->dx_dir_info_size = 100; /* Guess */
- ctx->dx_dir_info = (struct dx_dir_info *)
- e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
- * sizeof (struct dx_dir_info),
- "directory map");
- }
-
- if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
- old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
- ctx->dx_dir_info_size += 10;
- retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
- sizeof(struct dx_dir_info),
- &ctx->dx_dir_info);
- if (retval) {
- ctx->dx_dir_info_size -= 10;
- return;
- }
- }
-
- /*
- * Normally, add_dx_dir_info is called with each inode in
- * sequential order; but once in a while (like when pass 3
- * needs to recreate the root directory or lost+found
- * directory) it is called out of order. In those cases, we
- * need to move the dx_dir_info entries down to make room, since
- * the dx_dir_info array needs to be sorted by inode number for
- * get_dx_dir_info()'s sake.
- */
- if (ctx->dx_dir_info_count &&
- ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
- for (i = ctx->dx_dir_info_count-1; i > 0; i--)
- if (ctx->dx_dir_info[i-1].ino < ino)
- break;
- dir = &ctx->dx_dir_info[i];
- if (dir->ino != ino)
- for (j = ctx->dx_dir_info_count++; j > i; j--)
- ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
- } else
- dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
-
- dir->ino = ino;
- dir->numblocks = num_blocks;
- dir->hashversion = 0;
- dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
- * sizeof (struct dx_dirblock_info),
- "dx_block info array");
-}
-
-/*
- * get_dx_dir_info() --- given an inode number, try to find the directory
- * information entry for it.
- */
-static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
-{
- int low, high, mid;
-
- low = 0;
- high = ctx->dx_dir_info_count-1;
- if (!ctx->dx_dir_info)
- return 0;
- if (ino == ctx->dx_dir_info[low].ino)
- return &ctx->dx_dir_info[low];
- if (ino == ctx->dx_dir_info[high].ino)
- return &ctx->dx_dir_info[high];
-
- while (low < high) {
- mid = (low+high)/2;
- if (mid == low || mid == high)
- break;
- if (ino == ctx->dx_dir_info[mid].ino)
- return &ctx->dx_dir_info[mid];
- if (ino < ctx->dx_dir_info[mid].ino)
- high = mid;
- else
- low = mid;
- }
- return 0;
-}
-
-/*
- * Free the dx_dir_info structure when it isn't needed any more.
- */
-static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
-{
- int i;
- struct dx_dir_info *dir;
-
- if (ctx->dx_dir_info) {
- dir = ctx->dx_dir_info;
- for (i=0; i < ctx->dx_dir_info_count; i++) {
- ext2fs_free_mem(&dir->dx_block);
- }
- ext2fs_free_mem(&ctx->dx_dir_info);
- }
- ctx->dx_dir_info_size = 0;
- ctx->dx_dir_info_count = 0;
-}
-
-/*
- * A simple interator function
- */
-static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
-{
- if (*control >= ctx->dx_dir_info_count)
- return 0;
-
- return ctx->dx_dir_info + (*control)++;
-}
-
-#endif /* ENABLE_HTREE */
-/*
- * e2fsck.c - a consistency checker for the new extended file system.
- *
- */
-
-/*
- * This function allocates an e2fsck context
- */
-static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
-{
- e2fsck_t context;
- errcode_t retval;
-
- retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
- if (retval)
- return retval;
-
- memset(context, 0, sizeof(struct e2fsck_struct));
-
- context->process_inode_size = 256;
- context->ext_attr_ver = 2;
-
- *ret = context;
- return 0;
-}
-
-struct ea_refcount_el {
- blk_t ea_blk;
- int ea_count;
-};
-
-struct ea_refcount {
- blk_t count;
- blk_t size;
- blk_t cursor;
- struct ea_refcount_el *list;
-};
-
-static void ea_refcount_free(ext2_refcount_t refcount)
-{
- if (!refcount)
- return;
-
- ext2fs_free_mem(&refcount->list);
- ext2fs_free_mem(&refcount);
-}
-
-/*
- * This function resets an e2fsck context; it is called when e2fsck
- * needs to be restarted.
- */
-static errcode_t e2fsck_reset_context(e2fsck_t ctx)
-{
- ctx->flags = 0;
- ctx->lost_and_found = 0;
- ctx->bad_lost_and_found = 0;
- ext2fs_free_inode_bitmap(ctx->inode_used_map);
- ctx->inode_used_map = 0;
- ext2fs_free_inode_bitmap(ctx->inode_dir_map);
- ctx->inode_dir_map = 0;
- ext2fs_free_inode_bitmap(ctx->inode_reg_map);
- ctx->inode_reg_map = 0;
- ext2fs_free_block_bitmap(ctx->block_found_map);
- ctx->block_found_map = 0;
- ext2fs_free_icount(ctx->inode_link_info);
- ctx->inode_link_info = 0;
- if (ctx->journal_io) {
- if (ctx->fs && ctx->fs->io != ctx->journal_io)
- io_channel_close(ctx->journal_io);
- ctx->journal_io = 0;
- }
- if (ctx->fs) {
- ext2fs_free_dblist(ctx->fs->dblist);
- ctx->fs->dblist = 0;
- }
- e2fsck_free_dir_info(ctx);
-#ifdef ENABLE_HTREE
- e2fsck_free_dx_dir_info(ctx);
-#endif
- ea_refcount_free(ctx->refcount);
- ctx->refcount = 0;
- ea_refcount_free(ctx->refcount_extra);
- ctx->refcount_extra = 0;
- ext2fs_free_block_bitmap(ctx->block_dup_map);
- ctx->block_dup_map = 0;
- ext2fs_free_block_bitmap(ctx->block_ea_map);
- ctx->block_ea_map = 0;
- ext2fs_free_inode_bitmap(ctx->inode_bad_map);
- ctx->inode_bad_map = 0;
- ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
- ctx->inode_imagic_map = 0;
- ext2fs_u32_list_free(ctx->dirs_to_hash);
- ctx->dirs_to_hash = 0;
-
- /*
- * Clear the array of invalid meta-data flags
- */
- ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
- ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
- ext2fs_free_mem(&ctx->invalid_inode_table_flag);
-
- /* Clear statistic counters */
- ctx->fs_directory_count = 0;
- ctx->fs_regular_count = 0;
- ctx->fs_blockdev_count = 0;
- ctx->fs_chardev_count = 0;
- ctx->fs_links_count = 0;
- ctx->fs_symlinks_count = 0;
- ctx->fs_fast_symlinks_count = 0;
- ctx->fs_fifo_count = 0;
- ctx->fs_total_count = 0;
- ctx->fs_sockets_count = 0;
- ctx->fs_ind_count = 0;
- ctx->fs_dind_count = 0;
- ctx->fs_tind_count = 0;
- ctx->fs_fragmented = 0;
- ctx->large_files = 0;
-
- /* Reset the superblock to the user's requested value */
- ctx->superblock = ctx->use_superblock;
-
- return 0;
-}
-
-static void e2fsck_free_context(e2fsck_t ctx)
-{
- if (!ctx)
- return;
-
- e2fsck_reset_context(ctx);
-
- ext2fs_free_mem(&ctx);
-}
-
-/*
- * ea_refcount.c
- */
-
-/*
- * The strategy we use for keeping track of EA refcounts is as
- * follows. We keep a sorted array of first EA blocks and its
- * reference counts. Once the refcount has dropped to zero, it is
- * removed from the array to save memory space. Once the EA block is
- * checked, its bit is set in the block_ea_map bitmap.
- */
-
-
-static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
-{
- ext2_refcount_t refcount;
- errcode_t retval;
- size_t bytes;
-
- retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
- if (retval)
- return retval;
- memset(refcount, 0, sizeof(struct ea_refcount));
-
- if (!size)
- size = 500;
- refcount->size = size;
- bytes = (size_t) (size * sizeof(struct ea_refcount_el));
-#ifdef DEBUG
- printf("Refcount allocated %d entries, %d bytes.\n",
- refcount->size, bytes);
-#endif
- retval = ext2fs_get_mem(bytes, &refcount->list);
- if (retval)
- goto errout;
- memset(refcount->list, 0, bytes);
-
- refcount->count = 0;
- refcount->cursor = 0;
-
- *ret = refcount;
- return 0;
-
-errout:
- ea_refcount_free(refcount);
- return retval;
-}
-
-/*
- * collapse_refcount() --- go through the refcount array, and get rid
- * of any count == zero entries
- */
-static void refcount_collapse(ext2_refcount_t refcount)
-{
- unsigned int i, j;
- struct ea_refcount_el *list;
-
- list = refcount->list;
- for (i = 0, j = 0; i < refcount->count; i++) {
- if (list[i].ea_count) {
- if (i != j)
- list[j] = list[i];
- j++;
- }
- }
-#if defined(DEBUG) || defined(TEST_PROGRAM)
- printf("Refcount_collapse: size was %d, now %d\n",
- refcount->count, j);
-#endif
- refcount->count = j;
-}
-
-
-/*
- * insert_refcount_el() --- Insert a new entry into the sorted list at a
- * specified position.
- */
-static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
- blk_t blk, int pos)
-{
- struct ea_refcount_el *el;
- errcode_t retval;
- blk_t new_size = 0;
- int num;
-
- if (refcount->count >= refcount->size) {
- new_size = refcount->size + 100;
-#ifdef DEBUG
- printf("Reallocating refcount %d entries...\n", new_size);
-#endif
- retval = ext2fs_resize_mem((size_t) refcount->size *
- sizeof(struct ea_refcount_el),
- (size_t) new_size *
- sizeof(struct ea_refcount_el),
- &refcount->list);
- if (retval)
- return 0;
- refcount->size = new_size;
- }
- num = (int) refcount->count - pos;
- if (num < 0)
- return 0; /* should never happen */
- if (num) {
- memmove(&refcount->list[pos+1], &refcount->list[pos],
- sizeof(struct ea_refcount_el) * num);
- }
- refcount->count++;
- el = &refcount->list[pos];
- el->ea_count = 0;
- el->ea_blk = blk;
- return el;
-}
-
-
-/*
- * get_refcount_el() --- given an block number, try to find refcount
- * information in the sorted list. If the create flag is set,
- * and we can't find an entry, create one in the sorted list.
- */
-static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
- blk_t blk, int create)
-{
- float range;
- int low, high, mid;
- blk_t lowval, highval;
-
- if (!refcount || !refcount->list)
- return 0;
-retry:
- low = 0;
- high = (int) refcount->count-1;
- if (create && ((refcount->count == 0) ||
- (blk > refcount->list[high].ea_blk))) {
- if (refcount->count >= refcount->size)
- refcount_collapse(refcount);
-
- return insert_refcount_el(refcount, blk,
- (unsigned) refcount->count);
- }
- if (refcount->count == 0)
- return 0;
-
- if (refcount->cursor >= refcount->count)
- refcount->cursor = 0;
- if (blk == refcount->list[refcount->cursor].ea_blk)
- return &refcount->list[refcount->cursor++];
-#ifdef DEBUG
- printf("Non-cursor get_refcount_el: %u\n", blk);
-#endif
- while (low <= high) {
- if (low == high)
- mid = low;
- else {
- /* Interpolate for efficiency */
- lowval = refcount->list[low].ea_blk;
- highval = refcount->list[high].ea_blk;
-
- if (blk < lowval)
- range = 0;
- else if (blk > highval)
- range = 1;
- else
- range = ((float) (blk - lowval)) /
- (highval - lowval);
- mid = low + ((int) (range * (high-low)));
- }
-
- if (blk == refcount->list[mid].ea_blk) {
- refcount->cursor = mid+1;
- return &refcount->list[mid];
- }
- if (blk < refcount->list[mid].ea_blk)
- high = mid-1;
- else
- low = mid+1;
- }
- /*
- * If we need to create a new entry, it should be right at
- * low (where high will be left at low-1).
- */
- if (create) {
- if (refcount->count >= refcount->size) {
- refcount_collapse(refcount);
- if (refcount->count < refcount->size)
- goto retry;
- }
- return insert_refcount_el(refcount, blk, low);
- }
- return 0;
-}
-
-static errcode_t
-ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
-{
- struct ea_refcount_el *el;
-
- el = get_refcount_el(refcount, blk, 1);
- if (!el)
- return EXT2_ET_NO_MEMORY;
- el->ea_count++;
-
- if (ret)
- *ret = el->ea_count;
- return 0;
-}
-
-static errcode_t
-ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
-{
- struct ea_refcount_el *el;
-
- el = get_refcount_el(refcount, blk, 0);
- if (!el || el->ea_count == 0)
- return EXT2_ET_INVALID_ARGUMENT;
-
- el->ea_count--;
-
- if (ret)
- *ret = el->ea_count;
- return 0;
-}
-
-static errcode_t
-ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
-{
- struct ea_refcount_el *el;
-
- /*
- * Get the refcount element
- */
- el = get_refcount_el(refcount, blk, count ? 1 : 0);
- if (!el)
- return count ? EXT2_ET_NO_MEMORY : 0;
- el->ea_count = count;
- return 0;
-}
-
-static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
-{
- refcount->cursor = 0;
-}
-
-
-static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
-{
- struct ea_refcount_el *list;
-
- while (1) {
- if (refcount->cursor >= refcount->count)
- return 0;
- list = refcount->list;
- if (list[refcount->cursor].ea_count) {
- if (ret)
- *ret = list[refcount->cursor].ea_count;
- return list[refcount->cursor++].ea_blk;
- }
- refcount->cursor++;
- }
-}
-
-
-/*
- * ehandler.c --- handle bad block errors which come up during the
- * course of an e2fsck session.
- */
-
-
-static const char *operation;
-
-static errcode_t
-e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
- void *data, size_t size FSCK_ATTR((unused)),
- int actual FSCK_ATTR((unused)), errcode_t error)
-{
- int i;
- char *p;
- ext2_filsys fs = (ext2_filsys) channel->app_data;
- e2fsck_t ctx;
-
- ctx = (e2fsck_t) fs->priv_data;
-
- /*
- * If more than one block was read, try reading each block
- * separately. We could use the actual bytes read to figure
- * out where to start, but we don't bother.
- */
- if (count > 1) {
- p = (char *) data;
- for (i=0; i < count; i++, p += channel->block_size, block++) {
- error = io_channel_read_blk(channel, block,
- 1, p);
- if (error)
- return error;
- }
- return 0;
- }
- if (operation)
- printf(_("Error reading block %lu (%s) while %s. "), block,
- error_message(error), operation);
- else
- printf(_("Error reading block %lu (%s). "), block,
- error_message(error));
- preenhalt(ctx);
- if (ask(ctx, _("Ignore error"), 1)) {
- if (ask(ctx, _("Force rewrite"), 1))
- io_channel_write_blk(channel, block, 1, data);
- return 0;
- }
-
- return error;
-}
-
-static errcode_t
-e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
- const void *data, size_t size FSCK_ATTR((unused)),
- int actual FSCK_ATTR((unused)), errcode_t error)
-{
- int i;
- const char *p;
- ext2_filsys fs = (ext2_filsys) channel->app_data;
- e2fsck_t ctx;
-
- ctx = (e2fsck_t) fs->priv_data;
-
- /*
- * If more than one block was written, try writing each block
- * separately. We could use the actual bytes read to figure
- * out where to start, but we don't bother.
- */
- if (count > 1) {
- p = (const char *) data;
- for (i=0; i < count; i++, p += channel->block_size, block++) {
- error = io_channel_write_blk(channel, block,
- 1, p);
- if (error)
- return error;
- }
- return 0;
- }
-
- if (operation)
- printf(_("Error writing block %lu (%s) while %s. "), block,
- error_message(error), operation);
- else
- printf(_("Error writing block %lu (%s). "), block,
- error_message(error));
- preenhalt(ctx);
- if (ask(ctx, _("Ignore error"), 1))
- return 0;
-
- return error;
-}
-
-static const char *ehandler_operation(const char *op)
-{
- const char *ret = operation;
-
- operation = op;
- return ret;
-}
-
-static void ehandler_init(io_channel channel)
-{
- channel->read_error = e2fsck_handle_read_error;
- channel->write_error = e2fsck_handle_write_error;
-}
-
-/*
- * journal.c --- code for handling the "ext3" journal
- *
- * Copyright (C) 2000 Andreas Dilger
- * Copyright (C) 2000 Theodore Ts'o
- *
- * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
- * Copyright (C) 1999 Red Hat Software
- *
- * This file may be redistributed under the terms of the
- * GNU General Public License version 2 or at your discretion
- * any later version.
- */
-
-/*
- * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
- * This creates a larger static binary, and a smaller binary using
- * shared libraries. It's also probably slightly less CPU-efficient,
- * which is why it's not on by default. But, it's a good way of
- * testing the functions in inode_io.c and fileio.c.
- */
-#undef USE_INODE_IO
-
-/* Kernel compatibility functions for handling the journal. These allow us
- * to use the recovery.c file virtually unchanged from the kernel, so we
- * don't have to do much to keep kernel and user recovery in sync.
- */
-static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
-{
-#ifdef USE_INODE_IO
- *phys = block;
- return 0;
-#else
- struct inode *inode = journal->j_inode;
- errcode_t retval;
- blk_t pblk;
-
- if (!inode) {
- *phys = block;
- return 0;
- }
-
- retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
- &inode->i_ext2, NULL, 0, block, &pblk);
- *phys = pblk;
- return retval;
-#endif
-}
-
-static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
-{
- struct buffer_head *bh;
-
- bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
- if (!bh)
- return NULL;
-
- bh->b_ctx = kdev->k_ctx;
- if (kdev->k_dev == K_DEV_FS)
- bh->b_io = kdev->k_ctx->fs->io;
- else
- bh->b_io = kdev->k_ctx->journal_io;
- bh->b_size = blocksize;
- bh->b_blocknr = blocknr;
-
- return bh;
-}
-
-static void sync_blockdev(kdev_t kdev)
-{
- io_channel io;
-
- if (kdev->k_dev == K_DEV_FS)
- io = kdev->k_ctx->fs->io;
- else
- io = kdev->k_ctx->journal_io;
-
- io_channel_flush(io);
-}
-
-static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
-{
- int retval;
- struct buffer_head *bh;
-
- for (; nr > 0; --nr) {
- bh = *bhp++;
- if (rw == READ && !bh->b_uptodate) {
- retval = io_channel_read_blk(bh->b_io,
- bh->b_blocknr,
- 1, bh->b_data);
- if (retval) {
- bb_error_msg("while reading block %lu",
- (unsigned long) bh->b_blocknr);
- bh->b_err = retval;
- continue;
- }
- bh->b_uptodate = 1;
- } else if (rw == WRITE && bh->b_dirty) {
- retval = io_channel_write_blk(bh->b_io,
- bh->b_blocknr,
- 1, bh->b_data);
- if (retval) {
- bb_error_msg("while writing block %lu",
- (unsigned long) bh->b_blocknr);
- bh->b_err = retval;
- continue;
- }
- bh->b_dirty = 0;
- bh->b_uptodate = 1;
- }
- }
-}
-
-static void mark_buffer_dirty(struct buffer_head *bh)
-{
- bh->b_dirty = 1;
-}
-
-static inline void mark_buffer_clean(struct buffer_head * bh)
-{
- bh->b_dirty = 0;
-}
-
-static void brelse(struct buffer_head *bh)
-{
- if (bh->b_dirty)
- ll_rw_block(WRITE, 1, &bh);
- ext2fs_free_mem(&bh);
-}
-
-static int buffer_uptodate(struct buffer_head *bh)
-{
- return bh->b_uptodate;
-}
-
-static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
-{
- bh->b_uptodate = val;
-}
-
-static void wait_on_buffer(struct buffer_head *bh)
-{
- if (!bh->b_uptodate)
- ll_rw_block(READ, 1, &bh);
-}
-
-
-static void e2fsck_clear_recover(e2fsck_t ctx, int error)
-{
- ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
-
- /* if we had an error doing journal recovery, we need a full fsck */
- if (error)
- ctx->fs->super->s_state &= ~EXT2_VALID_FS;
- ext2fs_mark_super_dirty(ctx->fs);
-}
-
-static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
-{
- struct ext2_super_block *sb = ctx->fs->super;
- struct ext2_super_block jsuper;
- struct problem_context pctx;
- struct buffer_head *bh;
- struct inode *j_inode = NULL;
- struct kdev_s *dev_fs = NULL, *dev_journal;
- const char *journal_name = NULL;
- journal_t *journal = NULL;
- errcode_t retval = 0;
- io_manager io_ptr = 0;
- unsigned long start = 0;
- blk_t blk;
- int ext_journal = 0;
- int tried_backup_jnl = 0;
- int i;
-
- clear_problem_context(&pctx);
-
- journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
- if (!journal) {
- return EXT2_ET_NO_MEMORY;
- }
-
- dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
- if (!dev_fs) {
- retval = EXT2_ET_NO_MEMORY;
- goto errout;
- }
- dev_journal = dev_fs+1;
-
- dev_fs->k_ctx = dev_journal->k_ctx = ctx;
- dev_fs->k_dev = K_DEV_FS;
- dev_journal->k_dev = K_DEV_JOURNAL;
-
- journal->j_dev = dev_journal;
- journal->j_fs_dev = dev_fs;
- journal->j_inode = NULL;
- journal->j_blocksize = ctx->fs->blocksize;
-
- if (uuid_is_null(sb->s_journal_uuid)) {
- if (!sb->s_journal_inum)
- return EXT2_ET_BAD_INODE_NUM;
- j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
- "journal inode");
- if (!j_inode) {
- retval = EXT2_ET_NO_MEMORY;
- goto errout;
- }
-
- j_inode->i_ctx = ctx;
- j_inode->i_ino = sb->s_journal_inum;
-
- if ((retval = ext2fs_read_inode(ctx->fs,
- sb->s_journal_inum,
- &j_inode->i_ext2))) {
- try_backup_journal:
- if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
- tried_backup_jnl)
- goto errout;
- memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
- memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
- EXT2_N_BLOCKS*4);
- j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
- j_inode->i_ext2.i_links_count = 1;
- j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
- tried_backup_jnl++;
- }
- if (!j_inode->i_ext2.i_links_count ||
- !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
- retval = EXT2_ET_NO_JOURNAL;
- goto try_backup_journal;
- }
- if (j_inode->i_ext2.i_size / journal->j_blocksize <
- JFS_MIN_JOURNAL_BLOCKS) {
- retval = EXT2_ET_JOURNAL_TOO_SMALL;
- goto try_backup_journal;
- }
- for (i=0; i < EXT2_N_BLOCKS; i++) {
- blk = j_inode->i_ext2.i_block[i];
- if (!blk) {
- if (i < EXT2_NDIR_BLOCKS) {
- retval = EXT2_ET_JOURNAL_TOO_SMALL;
- goto try_backup_journal;
- }
- continue;
- }
- if (blk < sb->s_first_data_block ||
- blk >= sb->s_blocks_count) {
- retval = EXT2_ET_BAD_BLOCK_NUM;
- goto try_backup_journal;
- }
- }
- journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
-
-#ifdef USE_INODE_IO
- retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
- &j_inode->i_ext2,
- &journal_name);
- if (retval)
- goto errout;
-
- io_ptr = inode_io_manager;
-#else
- journal->j_inode = j_inode;
- ctx->journal_io = ctx->fs->io;
- if ((retval = journal_bmap(journal, 0, &start)) != 0)
- goto errout;
-#endif
- } else {
- ext_journal = 1;
- if (!ctx->journal_name) {
- char uuid[37];
-
- unparse_uuid(sb->s_journal_uuid, uuid);
- ctx->journal_name = get_devname_from_uuid(uuid);
- if (!ctx->journal_name)
- ctx->journal_name = get_devname_from_device(sb->s_journal_dev);
- }
- journal_name = ctx->journal_name;
-
- if (!journal_name) {
- fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
- return EXT2_ET_LOAD_EXT_JOURNAL;
- }
-
- io_ptr = unix_io_manager;
- }
-
-#ifndef USE_INODE_IO
- if (ext_journal)
-#endif
- retval = io_ptr->open(journal_name, IO_FLAG_RW,
- &ctx->journal_io);
- if (retval)
- goto errout;
-
- io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
-
- if (ext_journal) {
- if (ctx->fs->blocksize == 1024)
- start = 1;
- bh = getblk(dev_journal, start, ctx->fs->blocksize);
- if (!bh) {
- retval = EXT2_ET_NO_MEMORY;
- goto errout;
- }
- ll_rw_block(READ, 1, &bh);
- if ((retval = bh->b_err) != 0)
- goto errout;
- memcpy(&jsuper, start ? bh->b_data : bh->b_data + 1024,
- sizeof(jsuper));
- brelse(bh);
-#if BB_BIG_ENDIAN
- if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
- ext2fs_swap_super(&jsuper);
-#endif
- if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
- !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
- fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
- retval = EXT2_ET_LOAD_EXT_JOURNAL;
- goto errout;
- }
- /* Make sure the journal UUID is correct */
- if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
- sizeof(jsuper.s_uuid))) {
- fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
- retval = EXT2_ET_LOAD_EXT_JOURNAL;
- goto errout;
- }
-
- journal->j_maxlen = jsuper.s_blocks_count;
- start++;
- }
-
- if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
- retval = EXT2_ET_NO_MEMORY;
- goto errout;
- }
-
- journal->j_sb_buffer = bh;
- journal->j_superblock = (journal_superblock_t *)bh->b_data;
-
-#ifdef USE_INODE_IO
- ext2fs_free_mem(&j_inode);
-#endif
-
- *ret_journal = journal;
- return 0;
-
-errout:
- ext2fs_free_mem(&dev_fs);
- ext2fs_free_mem(&j_inode);
- ext2fs_free_mem(&journal);
- return retval;
-}
-
-static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
- struct problem_context *pctx)
-{
- struct ext2_super_block *sb = ctx->fs->super;
- int recover = ctx->fs->super->s_feature_incompat &
- EXT3_FEATURE_INCOMPAT_RECOVER;
- int has_journal = ctx->fs->super->s_feature_compat &
- EXT3_FEATURE_COMPAT_HAS_JOURNAL;
-
- if (has_journal || sb->s_journal_inum) {
- /* The journal inode is bogus, remove and force full fsck */
- pctx->ino = sb->s_journal_inum;
- if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
- if (has_journal && sb->s_journal_inum)
- printf("*** ext3 journal has been deleted - "
- "filesystem is now ext2 only ***\n\n");
- sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
- sb->s_journal_inum = 0;
- ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
- e2fsck_clear_recover(ctx, 1);
- return 0;
- }
- return EXT2_ET_BAD_INODE_NUM;
- } else if (recover) {
- if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
- e2fsck_clear_recover(ctx, 1);
- return 0;
- }
- return EXT2_ET_UNSUPP_FEATURE;
- }
- return 0;
-}
-
-#define V1_SB_SIZE 0x0024
-static void clear_v2_journal_fields(journal_t *journal)
-{
- e2fsck_t ctx = journal->j_dev->k_ctx;
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
-
- if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
- return;
-
- memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
- ctx->fs->blocksize-V1_SB_SIZE);
- mark_buffer_dirty(journal->j_sb_buffer);
-}
-
-
-static errcode_t e2fsck_journal_load(journal_t *journal)
-{
- e2fsck_t ctx = journal->j_dev->k_ctx;
- journal_superblock_t *jsb;
- struct buffer_head *jbh = journal->j_sb_buffer;
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
-
- ll_rw_block(READ, 1, &jbh);
- if (jbh->b_err) {
- bb_error_msg(_("reading journal superblock"));
- return jbh->b_err;
- }
-
- jsb = journal->j_superblock;
- /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
- if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
- return e2fsck_journal_fix_bad_inode(ctx, &pctx);
-
- switch (ntohl(jsb->s_header.h_blocktype)) {
- case JFS_SUPERBLOCK_V1:
- journal->j_format_version = 1;
- if (jsb->s_feature_compat ||
- jsb->s_feature_incompat ||
- jsb->s_feature_ro_compat ||
- jsb->s_nr_users)
- clear_v2_journal_fields(journal);
- break;
-
- case JFS_SUPERBLOCK_V2:
- journal->j_format_version = 2;
- if (ntohl(jsb->s_nr_users) > 1 &&
- uuid_is_null(ctx->fs->super->s_journal_uuid))
- clear_v2_journal_fields(journal);
- if (ntohl(jsb->s_nr_users) > 1) {
- fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
- return EXT2_ET_JOURNAL_UNSUPP_VERSION;
- }
- break;
-
- /*
- * These should never appear in a journal super block, so if
- * they do, the journal is badly corrupted.
- */
- case JFS_DESCRIPTOR_BLOCK:
- case JFS_COMMIT_BLOCK:
- case JFS_REVOKE_BLOCK:
- return EXT2_ET_CORRUPT_SUPERBLOCK;
-
- /* If we don't understand the superblock major type, but there
- * is a magic number, then it is likely to be a new format we
- * just don't understand, so leave it alone. */
- default:
- return EXT2_ET_JOURNAL_UNSUPP_VERSION;
- }
-
- if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
- return EXT2_ET_UNSUPP_FEATURE;
-
- if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
- return EXT2_ET_RO_UNSUPP_FEATURE;
-
- /* We have now checked whether we know enough about the journal
- * format to be able to proceed safely, so any other checks that
- * fail we should attempt to recover from. */
- if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
- bb_error_msg(_("%s: no valid journal superblock found"),
- ctx->device_name);
- return EXT2_ET_CORRUPT_SUPERBLOCK;
- }
-
- if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
- journal->j_maxlen = ntohl(jsb->s_maxlen);
- else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
- bb_error_msg(_("%s: journal too short"),
- ctx->device_name);
- return EXT2_ET_CORRUPT_SUPERBLOCK;
- }
-
- journal->j_tail_sequence = ntohl(jsb->s_sequence);
- journal->j_transaction_sequence = journal->j_tail_sequence;
- journal->j_tail = ntohl(jsb->s_start);
- journal->j_first = ntohl(jsb->s_first);
- journal->j_last = ntohl(jsb->s_maxlen);
-
- return 0;
-}
-
-static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
- journal_t *journal)
-{
- char *p;
- union {
- __u8 uuid[16];
- __u32 val[4];
- } u;
- __u32 new_seq = 0;
- int i;
-
- /* Leave a valid existing V1 superblock signature alone.
- * Anything unrecognizable we overwrite with a new V2
- * signature. */
-
- if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
- jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
- jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
- jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
- }
-
- /* Zero out everything else beyond the superblock header */
-
- p = ((char *) jsb) + sizeof(journal_header_t);
- memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
-
- jsb->s_blocksize = htonl(ctx->fs->blocksize);
- jsb->s_maxlen = htonl(journal->j_maxlen);
- jsb->s_first = htonl(1);
-
- /* Initialize the journal sequence number so that there is "no"
- * chance we will find old "valid" transactions in the journal.
- * This avoids the need to zero the whole journal (slow to do,
- * and risky when we are just recovering the filesystem).
- */
- generate_uuid(u.uuid);
- for (i = 0; i < 4; i ++)
- new_seq ^= u.val[i];
- jsb->s_sequence = htonl(new_seq);
-
- mark_buffer_dirty(journal->j_sb_buffer);
- ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
-}
-
-static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
- journal_t *journal,
- struct problem_context *pctx)
-{
- struct ext2_super_block *sb = ctx->fs->super;
- int recover = ctx->fs->super->s_feature_incompat &
- EXT3_FEATURE_INCOMPAT_RECOVER;
-
- if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
- if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
- e2fsck_journal_reset_super(ctx, journal->j_superblock,
- journal);
- journal->j_transaction_sequence = 1;
- e2fsck_clear_recover(ctx, recover);
- return 0;
- }
- return EXT2_ET_CORRUPT_SUPERBLOCK;
- } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
- return EXT2_ET_CORRUPT_SUPERBLOCK;
-
- return 0;
-}
-
-static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
- int reset, int drop)
-{
- journal_superblock_t *jsb;
-
- if (drop)
- mark_buffer_clean(journal->j_sb_buffer);
- else if (!(ctx->options & E2F_OPT_READONLY)) {
- jsb = journal->j_superblock;
- jsb->s_sequence = htonl(journal->j_transaction_sequence);
- if (reset)
- jsb->s_start = 0; /* this marks the journal as empty */
- mark_buffer_dirty(journal->j_sb_buffer);
- }
- brelse(journal->j_sb_buffer);
-
- if (ctx->journal_io) {
- if (ctx->fs && ctx->fs->io != ctx->journal_io)
- io_channel_close(ctx->journal_io);
- ctx->journal_io = 0;
- }
-
-#ifndef USE_INODE_IO
- ext2fs_free_mem(&journal->j_inode);
-#endif
- ext2fs_free_mem(&journal->j_fs_dev);
- ext2fs_free_mem(&journal);
-}
-
-/*
- * This function makes sure that the superblock fields regarding the
- * journal are consistent.
- */
-static int e2fsck_check_ext3_journal(e2fsck_t ctx)
-{
- struct ext2_super_block *sb = ctx->fs->super;
- journal_t *journal;
- int recover = ctx->fs->super->s_feature_incompat &
- EXT3_FEATURE_INCOMPAT_RECOVER;
- struct problem_context pctx;
- problem_t problem;
- int reset = 0, force_fsck = 0;
- int retval;
-
- /* If we don't have any journal features, don't do anything more */
- if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
- !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
- uuid_is_null(sb->s_journal_uuid))
- return 0;
-
- clear_problem_context(&pctx);
- pctx.num = sb->s_journal_inum;
-
- retval = e2fsck_get_journal(ctx, &journal);
- if (retval) {
- if ((retval == EXT2_ET_BAD_INODE_NUM) ||
- (retval == EXT2_ET_BAD_BLOCK_NUM) ||
- (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
- (retval == EXT2_ET_NO_JOURNAL))
- return e2fsck_journal_fix_bad_inode(ctx, &pctx);
- return retval;
- }
-
- retval = e2fsck_journal_load(journal);
- if (retval) {
- if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
- ((retval == EXT2_ET_UNSUPP_FEATURE) &&
- (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
- &pctx))) ||
- ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
- (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
- &pctx))) ||
- ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
- (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
- retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
- &pctx);
- e2fsck_journal_release(ctx, journal, 0, 1);
- return retval;
- }
-
- /*
- * We want to make the flags consistent here. We will not leave with
- * needs_recovery set but has_journal clear. We can't get in a loop
- * with -y, -n, or -p, only if a user isn't making up their mind.
- */
-no_has_journal:
- if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
- recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
- pctx.str = "inode";
- if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
- if (recover &&
- !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
- goto no_has_journal;
- /*
- * Need a full fsck if we are releasing a
- * journal stored on a reserved inode.
- */
- force_fsck = recover ||
- (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
- /* Clear all of the journal fields */
- sb->s_journal_inum = 0;
- sb->s_journal_dev = 0;
- memset(sb->s_journal_uuid, 0,
- sizeof(sb->s_journal_uuid));
- e2fsck_clear_recover(ctx, force_fsck);
- } else if (!(ctx->options & E2F_OPT_READONLY)) {
- sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
- ext2fs_mark_super_dirty(ctx->fs);
- }
- }
-
- if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
- !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
- journal->j_superblock->s_start != 0) {
- /* Print status information */
- fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
- if (ctx->superblock)
- problem = PR_0_JOURNAL_RUN_DEFAULT;
- else
- problem = PR_0_JOURNAL_RUN;
- if (fix_problem(ctx, problem, &pctx)) {
- ctx->options |= E2F_OPT_FORCE;
- sb->s_feature_incompat |=
- EXT3_FEATURE_INCOMPAT_RECOVER;
- ext2fs_mark_super_dirty(ctx->fs);
- } else if (fix_problem(ctx,
- PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
- reset = 1;
- sb->s_state &= ~EXT2_VALID_FS;
- ext2fs_mark_super_dirty(ctx->fs);
- }
- /*
- * If the user answers no to the above question, we
- * ignore the fact that journal apparently has data;
- * accidentally replaying over valid data would be far
- * worse than skipping a questionable recovery.
- *
- * XXX should we abort with a fatal error here? What
- * will the ext3 kernel code do if a filesystem with
- * !NEEDS_RECOVERY but with a non-zero
- * journal->j_superblock->s_start is mounted?
- */
- }
-
- e2fsck_journal_release(ctx, journal, reset, 0);
- return retval;
-}
-
-static errcode_t recover_ext3_journal(e2fsck_t ctx)
-{
- journal_t *journal;
- int retval;
-
- journal_init_revoke_caches();
- retval = e2fsck_get_journal(ctx, &journal);
- if (retval)
- return retval;
-
- retval = e2fsck_journal_load(journal);
- if (retval)
- goto errout;
-
- retval = journal_init_revoke(journal, 1024);
- if (retval)
- goto errout;
-
- retval = -journal_recover(journal);
- if (retval)
- goto errout;
-
- if (journal->j_superblock->s_errno) {
- ctx->fs->super->s_state |= EXT2_ERROR_FS;
- ext2fs_mark_super_dirty(ctx->fs);
- journal->j_superblock->s_errno = 0;
- mark_buffer_dirty(journal->j_sb_buffer);
- }
-
-errout:
- journal_destroy_revoke(journal);
- journal_destroy_revoke_caches();
- e2fsck_journal_release(ctx, journal, 1, 0);
- return retval;
-}
-
-static int e2fsck_run_ext3_journal(e2fsck_t ctx)
-{
- io_manager io_ptr = ctx->fs->io->manager;
- int blocksize = ctx->fs->blocksize;
- errcode_t retval, recover_retval;
-
- printf(_("%s: recovering journal\n"), ctx->device_name);
- if (ctx->options & E2F_OPT_READONLY) {
- printf(_("%s: won't do journal recovery while read-only\n"),
- ctx->device_name);
- return EXT2_ET_FILE_RO;
- }
-
- if (ctx->fs->flags & EXT2_FLAG_DIRTY)
- ext2fs_flush(ctx->fs); /* Force out any modifications */
-
- recover_retval = recover_ext3_journal(ctx);
-
- /*
- * Reload the filesystem context to get up-to-date data from disk
- * because journal recovery will change the filesystem under us.
- */
- ext2fs_close(ctx->fs);
- retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
- ctx->superblock, blocksize, io_ptr,
- &ctx->fs);
-
- if (retval) {
- bb_error_msg(_("while trying to re-open %s"),
- ctx->device_name);
- bb_error_msg_and_die(0);
- }
- ctx->fs->priv_data = ctx;
-
- /* Set the superblock flags */
- e2fsck_clear_recover(ctx, recover_retval);
- return recover_retval;
-}
-
-/*
- * This function will move the journal inode from a visible file in
- * the filesystem directory hierarchy to the reserved inode if necessary.
- */
-static const char *const journal_names[] = {
- ".journal", "journal", ".journal.dat", "journal.dat", 0 };
-
-static void e2fsck_move_ext3_journal(e2fsck_t ctx)
-{
- struct ext2_super_block *sb = ctx->fs->super;
- struct problem_context pctx;
- struct ext2_inode inode;
- ext2_filsys fs = ctx->fs;
- ext2_ino_t ino;
- errcode_t retval;
- const char *const * cpp;
- int group, mount_flags;
-
- clear_problem_context(&pctx);
-
- /*
- * If the filesystem is opened read-only, or there is no
- * journal, then do nothing.
- */
- if ((ctx->options & E2F_OPT_READONLY) ||
- (sb->s_journal_inum == 0) ||
- !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
- return;
-
- /*
- * Read in the journal inode
- */
- if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
- return;
-
- /*
- * If it's necessary to backup the journal inode, do so.
- */
- if ((sb->s_jnl_backup_type == 0) ||
- ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
- memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
- if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
- memcpy(sb->s_jnl_blocks, inode.i_block,
- EXT2_N_BLOCKS*4);
- sb->s_jnl_blocks[16] = inode.i_size;
- sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
- ext2fs_mark_super_dirty(fs);
- fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
- }
- }
-
- /*
- * If the journal is already the hidden inode, then do nothing
- */
- if (sb->s_journal_inum == EXT2_JOURNAL_INO)
- return;
-
- /*
- * The journal inode had better have only one link and not be readable.
- */
- if (inode.i_links_count != 1)
- return;
-
- /*
- * If the filesystem is mounted, or we can't tell whether
- * or not it's mounted, do nothing.
- */
- retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
- if (retval || (mount_flags & EXT2_MF_MOUNTED))
- return;
-
- /*
- * If we can't find the name of the journal inode, then do
- * nothing.
- */
- for (cpp = journal_names; *cpp; cpp++) {
- retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
- strlen(*cpp), 0, &ino);
- if ((retval == 0) && (ino == sb->s_journal_inum))
- break;
- }
- if (*cpp == 0)
- return;
-
- /* We need the inode bitmap to be loaded */
- retval = ext2fs_read_bitmaps(fs);
- if (retval)
- return;
-
- pctx.str = *cpp;
- if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
- return;
-
- /*
- * OK, we've done all the checks, let's actually move the
- * journal inode. Errors at this point mean we need to force
- * an ext2 filesystem check.
- */
- if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
- goto err_out;
- if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
- goto err_out;
- sb->s_journal_inum = EXT2_JOURNAL_INO;
- ext2fs_mark_super_dirty(fs);
- fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
- inode.i_links_count = 0;
- inode.i_dtime = time(NULL);
- if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
- goto err_out;
-
- group = ext2fs_group_of_ino(fs, ino);
- ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
- ext2fs_mark_ib_dirty(fs);
- fs->group_desc[group].bg_free_inodes_count++;
- fs->super->s_free_inodes_count++;
- return;
-
-err_out:
- pctx.errcode = retval;
- fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
- fs->super->s_state &= ~EXT2_VALID_FS;
- ext2fs_mark_super_dirty(fs);
-}
-
-/*
- * message.c --- print e2fsck messages (with compression)
- *
- * print_e2fsck_message() prints a message to the user, using
- * compression techniques and expansions of abbreviations.
- *
- * The following % expansions are supported:
- *
- * %b <blk> block number
- * %B <blkcount> integer
- * %c <blk2> block number
- * %Di <dirent>->ino inode number
- * %Dn <dirent>->name string
- * %Dr <dirent>->rec_len
- * %Dl <dirent>->name_len
- * %Dt <dirent>->filetype
- * %d <dir> inode number
- * %g <group> integer
- * %i <ino> inode number
- * %Is <inode> -> i_size
- * %IS <inode> -> i_extra_isize
- * %Ib <inode> -> i_blocks
- * %Il <inode> -> i_links_count
- * %Im <inode> -> i_mode
- * %IM <inode> -> i_mtime
- * %IF <inode> -> i_faddr
- * %If <inode> -> i_file_acl
- * %Id <inode> -> i_dir_acl
- * %Iu <inode> -> i_uid
- * %Ig <inode> -> i_gid
- * %j <ino2> inode number
- * %m <com_err error message>
- * %N <num>
- * %p ext2fs_get_pathname of directory <ino>
- * %P ext2fs_get_pathname of <dirent>->ino with <ino2> as
- * the containing directory. (If dirent is NULL
- * then return the pathname of directory <ino2>)
- * %q ext2fs_get_pathname of directory <dir>
- * %Q ext2fs_get_pathname of directory <ino> with <dir> as
- * the containing directory.
- * %s <str> miscellaneous string
- * %S backup superblock
- * %X <num> hexadecimal format
- *
- * The following '@' expansions are supported:
- *
- * @a extended attribute
- * @A error allocating
- * @b block
- * @B bitmap
- * @c compress
- * @C conflicts with some other fs block
- * @D deleted
- * @d directory
- * @e entry
- * @E Entry '%Dn' in %p (%i)
- * @f filesystem
- * @F for @i %i (%Q) is
- * @g group
- * @h HTREE directory inode
- * @i inode
- * @I illegal
- * @j journal
- * @l lost+found
- * @L is a link
- * @m multiply-claimed
- * @n invalid
- * @o orphaned
- * @p problem in
- * @r root inode
- * @s should be
- * @S superblock
- * @u unattached
- * @v device
- * @z zero-length
- */
-
-
-/*
- * This structure defines the abbreviations used by the text strings
- * below. The first character in the string is the index letter. An
- * abbreviation of the form '@<i>' is expanded by looking up the index
- * letter <i> in the table below.
- */
-static const char *const abbrevs[] = {
- N_("aextended attribute"),
- N_("Aerror allocating"),
- N_("bblock"),
- N_("Bbitmap"),
- N_("ccompress"),
- N_("Cconflicts with some other fs @b"),
- N_("iinode"),
- N_("Iillegal"),
- N_("jjournal"),
- N_("Ddeleted"),
- N_("ddirectory"),
- N_("eentry"),
- N_("E@e '%Dn' in %p (%i)"),
- N_("ffilesystem"),
- N_("Ffor @i %i (%Q) is"),
- N_("ggroup"),
- N_("hHTREE @d @i"),
- N_("llost+found"),
- N_("Lis a link"),
- N_("mmultiply-claimed"),
- N_("ninvalid"),
- N_("oorphaned"),
- N_("pproblem in"),
- N_("rroot @i"),
- N_("sshould be"),
- N_("Ssuper@b"),
- N_("uunattached"),
- N_("vdevice"),
- N_("zzero-length"),
- "@@",
- 0
- };
-
-/*
- * Give more user friendly names to the "special" inodes.
- */
-#define num_special_inodes 11
-static const char *const special_inode_name[] =
-{
- N_("<The NULL inode>"), /* 0 */
- N_("<The bad blocks inode>"), /* 1 */
- "/", /* 2 */
- N_("<The ACL index inode>"), /* 3 */
- N_("<The ACL data inode>"), /* 4 */
- N_("<The boot loader inode>"), /* 5 */
- N_("<The undelete directory inode>"), /* 6 */
- N_("<The group descriptor inode>"), /* 7 */
- N_("<The journal inode>"), /* 8 */
- N_("<Reserved inode 9>"), /* 9 */
- N_("<Reserved inode 10>"), /* 10 */
-};
-
-/*
- * This function does "safe" printing. It will convert non-printable
- * ASCII characters using '^' and M- notation.
- */
-static void safe_print(const char *cp, int len)
-{
- unsigned char ch;
-
- if (len < 0)
- len = strlen(cp);
-
- while (len--) {
- ch = *cp++;
- if (ch > 128) {
- fputs("M-", stdout);
- ch -= 128;
- }
- if ((ch < 32) || (ch == 0x7f)) {
- bb_putchar('^');
- ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
- }
- bb_putchar(ch);
- }
-}
-
-
-/*
- * This function prints a pathname, using the ext2fs_get_pathname
- * function
- */
-static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
-{
- errcode_t retval;
- char *path;
-
- if (!dir && (ino < num_special_inodes)) {
- fputs(_(special_inode_name[ino]), stdout);
- return;
- }
-
- retval = ext2fs_get_pathname(fs, dir, ino, &path);
- if (retval)
- fputs("???", stdout);
- else {
- safe_print(path, -1);
- ext2fs_free_mem(&path);
- }
-}
-
-static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
- struct problem_context *pctx, int first);
-/*
- * This function handles the '@' expansion. We allow recursive
- * expansion; an @ expression can contain further '@' and '%'
- * expressions.
- */
-static void expand_at_expression(e2fsck_t ctx, char ch,
- struct problem_context *pctx,
- int *first)
-{
- const char *const *cpp;
- const char *str;
-
- /* Search for the abbreviation */
- for (cpp = abbrevs; *cpp; cpp++) {
- if (ch == *cpp[0])
- break;
- }
- if (*cpp) {
- str = _(*cpp) + 1;
- if (*first && islower(*str)) {
- *first = 0;
- bb_putchar(toupper(*str++));
- }
- print_e2fsck_message(ctx, str, pctx, *first);
- } else
- printf("@%c", ch);
-}
-
-/*
- * This function expands '%IX' expressions
- */
-static void expand_inode_expression(char ch,
- struct problem_context *ctx)
-{
- struct ext2_inode *inode;
- struct ext2_inode_large *large_inode;
- char * time_str;
- time_t t;
- int do_gmt = -1;
-
- if (!ctx || !ctx->inode)
- goto no_inode;
-
- inode = ctx->inode;
- large_inode = (struct ext2_inode_large *) inode;
-
- switch (ch) {
- case 's':
- if (LINUX_S_ISDIR(inode->i_mode))
- printf("%u", inode->i_size);
- else {
- printf("%"PRIu64, (inode->i_size |
- ((uint64_t) inode->i_size_high << 32)));
- }
- break;
- case 'S':
- printf("%u", large_inode->i_extra_isize);
- break;
- case 'b':
- printf("%u", inode->i_blocks);
- break;
- case 'l':
- printf("%d", inode->i_links_count);
- break;
- case 'm':
- printf("0%o", inode->i_mode);
- break;
- case 'M':
- /* The diet libc doesn't respect the TZ environemnt variable */
- if (do_gmt == -1) {
- time_str = getenv("TZ");
- if (!time_str)
- time_str = (char *)"";
- do_gmt = !strcmp(time_str, "GMT");
- }
- t = inode->i_mtime;
- time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
- printf("%.24s", time_str);
- break;
- case 'F':
- printf("%u", inode->i_faddr);
- break;
- case 'f':
- printf("%u", inode->i_file_acl);
- break;
- case 'd':
- printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
- inode->i_dir_acl : 0));
- break;
- case 'u':
- printf("%d", (inode->i_uid |
- (inode->osd2.linux2.l_i_uid_high << 16)));
- break;
- case 'g':
- printf("%d", (inode->i_gid |
- (inode->osd2.linux2.l_i_gid_high << 16)));
- break;
- default:
- no_inode:
- printf("%%I%c", ch);
- break;
- }
-}
-
-/*
- * This function expands '%dX' expressions
- */
-static void expand_dirent_expression(char ch,
- struct problem_context *ctx)
-{
- struct ext2_dir_entry *dirent;
- int len;
-
- if (!ctx || !ctx->dirent)
- goto no_dirent;
-
- dirent = ctx->dirent;
-
- switch (ch) {
- case 'i':
- printf("%u", dirent->inode);
- break;
- case 'n':
- len = dirent->name_len & 0xFF;
- if (len > EXT2_NAME_LEN)
- len = EXT2_NAME_LEN;
- if (len > dirent->rec_len)
- len = dirent->rec_len;
- safe_print(dirent->name, len);
- break;
- case 'r':
- printf("%u", dirent->rec_len);
- break;
- case 'l':
- printf("%u", dirent->name_len & 0xFF);
- break;
- case 't':
- printf("%u", dirent->name_len >> 8);
- break;
- default:
- no_dirent:
- printf("%%D%c", ch);
- break;
- }
-}
-
-static void expand_percent_expression(ext2_filsys fs, char ch,
- struct problem_context *ctx)
-{
- if (!ctx)
- goto no_context;
-
- switch (ch) {
- case '%':
- bb_putchar('%');
- break;
- case 'b':
- printf("%u", ctx->blk);
- break;
- case 'B':
- printf("%"PRIi64, ctx->blkcount);
- break;
- case 'c':
- printf("%u", ctx->blk2);
- break;
- case 'd':
- printf("%u", ctx->dir);
- break;
- case 'g':
- printf("%d", ctx->group);
- break;
- case 'i':
- printf("%u", ctx->ino);
- break;
- case 'j':
- printf("%u", ctx->ino2);
- break;
- case 'm':
- fputs(error_message(ctx->errcode), stdout);
- break;
- case 'N':
- printf("%"PRIi64, ctx->num);
- break;
- case 'p':
- print_pathname(fs, ctx->ino, 0);
- break;
- case 'P':
- print_pathname(fs, ctx->ino2,
- ctx->dirent ? ctx->dirent->inode : 0);
- break;
- case 'q':
- print_pathname(fs, ctx->dir, 0);
- break;
- case 'Q':
- print_pathname(fs, ctx->dir, ctx->ino);
- break;
- case 'S':
- printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
- break;
- case 's':
- fputs((ctx->str ? ctx->str : "NULL"), stdout);
- break;
- case 'X':
- printf("0x%"PRIi64, ctx->num);
- break;
- default:
- no_context:
- printf("%%%c", ch);
- break;
- }
-}
-
-
-static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
- struct problem_context *pctx, int first)
-{
- ext2_filsys fs = ctx->fs;
- const char * cp;
- int i;
-
- e2fsck_clear_progbar(ctx);
- for (cp = msg; *cp; cp++) {
- if (cp[0] == '@') {
- cp++;
- expand_at_expression(ctx, *cp, pctx, &first);
- } else if (cp[0] == '%' && cp[1] == 'I') {
- cp += 2;
- expand_inode_expression(*cp, pctx);
- } else if (cp[0] == '%' && cp[1] == 'D') {
- cp += 2;
- expand_dirent_expression(*cp, pctx);
- } else if ((cp[0] == '%')) {
- cp++;
- expand_percent_expression(fs, *cp, pctx);
- } else {
- for (i=0; cp[i]; i++)
- if ((cp[i] == '@') || cp[i] == '%')
- break;
- printf("%.*s", i, cp);
- cp += i-1;
- }
- first = 0;
- }
-}
-
-
-/*
- * region.c --- code which manages allocations within a region.
- */
-
-struct region_el {
- region_addr_t start;
- region_addr_t end;
- struct region_el *next;
-};
-
-struct region_struct {
- region_addr_t min;
- region_addr_t max;
- struct region_el *allocated;
-};
-
-static region_t region_create(region_addr_t min, region_addr_t max)
-{
- region_t region;
-
- region = xzalloc(sizeof(struct region_struct));
- region->min = min;
- region->max = max;
- return region;
-}
-
-static void region_free(region_t region)
-{
- struct region_el *r, *next;
-
- for (r = region->allocated; r; r = next) {
- next = r->next;
- free(r);
- }
- memset(region, 0, sizeof(struct region_struct));
- free(region);
-}
-
-static int region_allocate(region_t region, region_addr_t start, int n)
-{
- struct region_el *r, *new_region, *prev, *next;
- region_addr_t end;
-
- end = start+n;
- if ((start < region->min) || (end > region->max))
- return -1;
- if (n == 0)
- return 1;
-
- /*
- * Search through the linked list. If we find that it
- * conflicts witih something that's already allocated, return
- * 1; if we can find an existing region which we can grow, do
- * so. Otherwise, stop when we find the appropriate place
- * insert a new region element into the linked list.
- */
- for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
- if (((start >= r->start) && (start < r->end)) ||
- ((end > r->start) && (end <= r->end)) ||
- ((start <= r->start) && (end >= r->end)))
- return 1;
- if (end == r->start) {
- r->start = start;
- return 0;
- }
- if (start == r->end) {
- if ((next = r->next)) {
- if (end > next->start)
- return 1;
- if (end == next->start) {
- r->end = next->end;
- r->next = next->next;
- free(next);
- return 0;
- }
- }
- r->end = end;
- return 0;
- }
- if (start < r->start)
- break;
- }
- /*
- * Insert a new region element structure into the linked list
- */
- new_region = xmalloc(sizeof(struct region_el));
- new_region->start = start;
- new_region->end = start + n;
- new_region->next = r;
- if (prev)
- prev->next = new_region;
- else
- region->allocated = new_region;
- return 0;
-}
-
-/*
- * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
- *
- * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
- * and applies the following tests to each inode:
- *
- * - The mode field of the inode must be legal.
- * - The size and block count fields of the inode are correct.
- * - A data block must not be used by another inode
- *
- * Pass 1 also gathers the collects the following information:
- *
- * - A bitmap of which inodes are in use. (inode_used_map)
- * - A bitmap of which inodes are directories. (inode_dir_map)
- * - A bitmap of which inodes are regular files. (inode_reg_map)
- * - A bitmap of which inodes have bad fields. (inode_bad_map)
- * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
- * - A bitmap of which blocks are in use. (block_found_map)
- * - A bitmap of which blocks are in use by two inodes (block_dup_map)
- * - The data blocks of the directory inodes. (dir_map)
- *
- * Pass 1 is designed to stash away enough information so that the
- * other passes should not need to read in the inode information
- * during the normal course of a filesystem check. (Althogh if an
- * inconsistency is detected, other passes may need to read in an
- * inode to fix it.)
- *
- * Note that pass 1B will be invoked if there are any duplicate blocks
- * found.
- */
-
-
-static int process_block(ext2_filsys fs, blk_t *blocknr,
- e2_blkcnt_t blockcnt, blk_t ref_blk,
- int ref_offset, void *priv_data);
-static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
- e2_blkcnt_t blockcnt, blk_t ref_blk,
- int ref_offset, void *priv_data);
-static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
- char *block_buf);
-static void mark_table_blocks(e2fsck_t ctx);
-static void alloc_imagic_map(e2fsck_t ctx);
-static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
-static void handle_fs_bad_blocks(e2fsck_t ctx);
-static void process_inodes(e2fsck_t ctx, char *block_buf);
-static int process_inode_cmp(const void *a, const void *b);
-static errcode_t scan_callback(ext2_filsys fs,
- dgrp_t group, void * priv_data);
-static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
- char *block_buf, int adjust_sign);
-/* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
-
-static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
- struct ext2_inode * inode, int bufsize,
- const char *proc);
-
-struct process_block_struct_1 {
- ext2_ino_t ino;
- unsigned is_dir:1, is_reg:1, clear:1, suppress:1,
- fragmented:1, compressed:1, bbcheck:1;
- blk_t num_blocks;
- blk_t max_blocks;
- e2_blkcnt_t last_block;
- int num_illegal_blocks;
- blk_t previous_block;
- struct ext2_inode *inode;
- struct problem_context *pctx;
- ext2fs_block_bitmap fs_meta_blocks;
- e2fsck_t ctx;
-};
-
-struct process_inode_block {
- ext2_ino_t ino;
- struct ext2_inode inode;
-};
-
-struct scan_callback_struct {
- e2fsck_t ctx;
- char *block_buf;
-};
-
-/*
- * For the inodes to process list.
- */
-static struct process_inode_block *inodes_to_process;
-static int process_inode_count;
-
-static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
- EXT2_MIN_BLOCK_LOG_SIZE + 1];
-
-/*
- * Free all memory allocated by pass1 in preparation for restarting
- * things.
- */
-static void unwind_pass1(void)
-{
- ext2fs_free_mem(&inodes_to_process);
-}
-
-/*
- * Check to make sure a device inode is real. Returns 1 if the device
- * checks out, 0 if not.
- *
- * Note: this routine is now also used to check FIFO's and Sockets,
- * since they have the same requirement; the i_block fields should be
- * zero.
- */
-static int
-e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
-{
- int i;
-
- /*
- * If i_blocks is non-zero, or the index flag is set, then
- * this is a bogus device/fifo/socket
- */
- if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
- (inode->i_flags & EXT2_INDEX_FL))
- return 0;
-
- /*
- * We should be able to do the test below all the time, but
- * because the kernel doesn't forcibly clear the device
- * inode's additional i_block fields, there are some rare
- * occasions when a legitimate device inode will have non-zero
- * additional i_block fields. So for now, we only complain
- * when the immutable flag is set, which should never happen
- * for devices. (And that's when the problem is caused, since
- * you can't set or clear immutable flags for devices.) Once
- * the kernel has been fixed we can change this...
- */
- if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
- for (i=4; i < EXT2_N_BLOCKS; i++)
- if (inode->i_block[i])
- return 0;
- }
- return 1;
-}
-
-/*
- * Check to make sure a symlink inode is real. Returns 1 if the symlink
- * checks out, 0 if not.
- */
-static int
-e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
-{
- unsigned int len;
- int i;
- blk_t blocks;
-
- if ((inode->i_size_high || inode->i_size == 0) ||
- (inode->i_flags & EXT2_INDEX_FL))
- return 0;
-
- blocks = ext2fs_inode_data_blocks(fs, inode);
- if (blocks) {
- if ((inode->i_size >= fs->blocksize) ||
- (blocks != fs->blocksize >> 9) ||
- (inode->i_block[0] < fs->super->s_first_data_block) ||
- (inode->i_block[0] >= fs->super->s_blocks_count))
- return 0;
-
- for (i = 1; i < EXT2_N_BLOCKS; i++)
- if (inode->i_block[i])
- return 0;
-
- if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
- return 0;
-
- len = strnlen(buf, fs->blocksize);
- if (len == fs->blocksize)
- return 0;
- } else {
- if (inode->i_size >= sizeof(inode->i_block))
- return 0;
-
- len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
- if (len == sizeof(inode->i_block))
- return 0;
- }
- if (len != inode->i_size)
- return 0;
- return 1;
-}
-
-/*
- * If the immutable (or append-only) flag is set on the inode, offer
- * to clear it.
- */
-#define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
-static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
-{
- if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
- return;
-
- if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
- return;
-
- pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
- e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
-}
-
-/*
- * If device, fifo or socket, check size is zero -- if not offer to
- * clear it
- */
-static void check_size(e2fsck_t ctx, struct problem_context *pctx)
-{
- struct ext2_inode *inode = pctx->inode;
-
- if ((inode->i_size == 0) && (inode->i_size_high == 0))
- return;
-
- if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
- return;
-
- inode->i_size = 0;
- inode->i_size_high = 0;
- e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
-}
-
-static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
-{
- struct ext2_super_block *sb = ctx->fs->super;
- struct ext2_inode_large *inode;
- struct ext2_ext_attr_entry *entry;
- char *start, *end;
- int storage_size, remain, offs;
- int problem = 0;
-
- inode = (struct ext2_inode_large *) pctx->inode;
- storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
- inode->i_extra_isize;
- start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
- inode->i_extra_isize + sizeof(__u32);
- end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
- entry = (struct ext2_ext_attr_entry *) start;
-
- /* scan all entry's headers first */
-
- /* take finish entry 0UL into account */
- remain = storage_size - sizeof(__u32);
- offs = end - start;
-
- while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
-
- /* header eats this space */
- remain -= sizeof(struct ext2_ext_attr_entry);
-
- /* is attribute name valid? */
- if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
- pctx->num = entry->e_name_len;
- problem = PR_1_ATTR_NAME_LEN;
- goto fix;
- }
-
- /* attribute len eats this space */
- remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
-
- /* check value size */
- if (entry->e_value_size == 0 || entry->e_value_size > remain) {
- pctx->num = entry->e_value_size;
- problem = PR_1_ATTR_VALUE_SIZE;
- goto fix;
- }
-
- /* check value placement */
- if (entry->e_value_offs +
- EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
- printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
- pctx->num = entry->e_value_offs;
- problem = PR_1_ATTR_VALUE_OFFSET;
- goto fix;
- }
-
- /* e_value_block must be 0 in inode's ea */
- if (entry->e_value_block != 0) {
- pctx->num = entry->e_value_block;
- problem = PR_1_ATTR_VALUE_BLOCK;
- goto fix;
- }
-
- /* e_hash must be 0 in inode's ea */
- if (entry->e_hash != 0) {
- pctx->num = entry->e_hash;
- problem = PR_1_ATTR_HASH;
- goto fix;
- }
-
- remain -= entry->e_value_size;
- offs -= EXT2_XATTR_SIZE(entry->e_value_size);
-
- entry = EXT2_EXT_ATTR_NEXT(entry);
- }
-fix:
- /*
- * it seems like a corruption. it's very unlikely we could repair
- * EA(s) in automatic fashion -bzzz
- */
- if (problem == 0 || !fix_problem(ctx, problem, pctx))
- return;
-
- /* simple remove all possible EA(s) */
- *((__u32 *)start) = 0UL;
- e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
- EXT2_INODE_SIZE(sb), "pass1");
-}
-
-static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
-{
- struct ext2_super_block *sb = ctx->fs->super;
- struct ext2_inode_large *inode;
- __u32 *eamagic;
- int min, max;
-
- inode = (struct ext2_inode_large *) pctx->inode;
- if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
- /* this isn't large inode. so, nothing to check */
- return;
- }
-
- /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
- min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
- max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
- /*
- * For now we will allow i_extra_isize to be 0, but really
- * implementations should never allow i_extra_isize to be 0
- */
- if (inode->i_extra_isize &&
- (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
- if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
- return;
- inode->i_extra_isize = min;
- e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
- EXT2_INODE_SIZE(sb), "pass1");
- return;
- }
-
- eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
- inode->i_extra_isize);
- if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
- /* it seems inode has an extended attribute(s) in body */
- check_ea_in_inode(ctx, pctx);
- }
-}
-
-static void e2fsck_pass1(e2fsck_t ctx)
-{
- int i;
- __u64 max_sizes;
- ext2_filsys fs = ctx->fs;
- ext2_ino_t ino;
- struct ext2_inode *inode;
- ext2_inode_scan scan;
- char *block_buf;
- unsigned char frag, fsize;
- struct problem_context pctx;
- struct scan_callback_struct scan_struct;
- struct ext2_super_block *sb = ctx->fs->super;
- int imagic_fs;
- int busted_fs_time = 0;
- int inode_size;
-
- clear_problem_context(&pctx);
-
- if (!(ctx->options & E2F_OPT_PREEN))
- fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
-
- if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
- !(ctx->options & E2F_OPT_NO)) {
- if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
- ctx->dirs_to_hash = 0;
- }
-
- /* Pass 1 */
-
-#define EXT2_BPP(bits) (1ULL << ((bits) - 2))
-
- for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
- max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
- max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
- max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
- max_sizes = (max_sizes * (1UL << i)) - 1;
- ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
- }
-#undef EXT2_BPP
-
- imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
-
- /*
- * Allocate bitmaps structures
- */
- pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
- &ctx->inode_used_map);
- if (pctx.errcode) {
- pctx.num = 1;
- fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
- _("directory inode map"), &ctx->inode_dir_map);
- if (pctx.errcode) {
- pctx.num = 2;
- fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
- _("regular file inode map"), &ctx->inode_reg_map);
- if (pctx.errcode) {
- pctx.num = 6;
- fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
- &ctx->block_found_map);
- if (pctx.errcode) {
- pctx.num = 1;
- fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
- &ctx->inode_link_info);
- if (pctx.errcode) {
- fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- inode_size = EXT2_INODE_SIZE(fs->super);
- inode = (struct ext2_inode *)
- e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
-
- inodes_to_process = (struct process_inode_block *)
- e2fsck_allocate_memory(ctx,
- (ctx->process_inode_size *
- sizeof(struct process_inode_block)),
- "array of inodes to process");
- process_inode_count = 0;
-
- pctx.errcode = ext2fs_init_dblist(fs, 0);
- if (pctx.errcode) {
- fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-
- /*
- * If the last orphan field is set, clear it, since the pass1
- * processing will automatically find and clear the orphans.
- * In the future, we may want to try using the last_orphan
- * linked list ourselves, but for now, we clear it so that the
- * ext3 mount code won't get confused.
- */
- if (!(ctx->options & E2F_OPT_READONLY)) {
- if (fs->super->s_last_orphan) {
- fs->super->s_last_orphan = 0;
- ext2fs_mark_super_dirty(fs);
- }
- }
-
- mark_table_blocks(ctx);
- block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
- "block interate buffer");
- e2fsck_use_inode_shortcuts(ctx, 1);
- ehandler_operation(_("doing inode scan"));
- pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
- &scan);
- if (pctx.errcode) {
- fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
- ctx->stashed_inode = inode;
- scan_struct.ctx = ctx;
- scan_struct.block_buf = block_buf;
- ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
- if (ctx->progress)
- if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
- return;
- if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
- (fs->super->s_mtime < fs->super->s_inodes_count))
- busted_fs_time = 1;
-
- while (1) {
- pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
- inode, inode_size);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
- if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
- continue;
- }
- if (pctx.errcode) {
- fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- if (!ino)
- break;
- pctx.ino = ino;
- pctx.inode = inode;
- ctx->stashed_ino = ino;
- if (inode->i_links_count) {
- pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
- ino, inode->i_links_count);
- if (pctx.errcode) {
- pctx.num = inode->i_links_count;
- fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- }
- if (ino == EXT2_BAD_INO) {
- struct process_block_struct_1 pb;
-
- pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
- &pb.fs_meta_blocks);
- if (pctx.errcode) {
- pctx.num = 4;
- fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- pb.ino = EXT2_BAD_INO;
- pb.num_blocks = pb.last_block = 0;
- pb.num_illegal_blocks = 0;
- pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
- pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
- pb.inode = inode;
- pb.pctx = &pctx;
- pb.ctx = ctx;
- pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
- block_buf, process_bad_block, &pb);
- ext2fs_free_block_bitmap(pb.fs_meta_blocks);
- if (pctx.errcode) {
- fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- if (pb.bbcheck)
- if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
- clear_problem_context(&pctx);
- continue;
- } else if (ino == EXT2_ROOT_INO) {
- /*
- * Make sure the root inode is a directory; if
- * not, offer to clear it. It will be
- * regnerated in pass #3.
- */
- if (!LINUX_S_ISDIR(inode->i_mode)) {
- if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
- inode->i_dtime = time(NULL);
- inode->i_links_count = 0;
- ext2fs_icount_store(ctx->inode_link_info,
- ino, 0);
- e2fsck_write_inode(ctx, ino, inode,
- "pass1");
- }
- }
- /*
- * If dtime is set, offer to clear it. mke2fs
- * version 0.2b created filesystems with the
- * dtime field set for the root and lost+found
- * directories. We won't worry about
- * /lost+found, since that can be regenerated
- * easily. But we will fix the root directory
- * as a special case.
- */
- if (inode->i_dtime && inode->i_links_count) {
- if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
- inode->i_dtime = 0;
- e2fsck_write_inode(ctx, ino, inode,
- "pass1");
- }
- }
- } else if (ino == EXT2_JOURNAL_INO) {
- ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
- if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
- if (!LINUX_S_ISREG(inode->i_mode) &&
- fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
- &pctx)) {
- inode->i_mode = LINUX_S_IFREG;
- e2fsck_write_inode(ctx, ino, inode,
- "pass1");
- }
- check_blocks(ctx, &pctx, block_buf);
- continue;
- }
- if ((inode->i_links_count || inode->i_blocks ||
- inode->i_blocks || inode->i_block[0]) &&
- fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
- &pctx)) {
- memset(inode, 0, inode_size);
- ext2fs_icount_store(ctx->inode_link_info,
- ino, 0);
- e2fsck_write_inode_full(ctx, ino, inode,
- inode_size, "pass1");
- }
- } else if (ino < EXT2_FIRST_INODE(fs->super)) {
- int problem = 0;
-
- ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
- if (ino == EXT2_BOOT_LOADER_INO) {
- if (LINUX_S_ISDIR(inode->i_mode))
- problem = PR_1_RESERVED_BAD_MODE;
- } else if (ino == EXT2_RESIZE_INO) {
- if (inode->i_mode &&
- !LINUX_S_ISREG(inode->i_mode))
- problem = PR_1_RESERVED_BAD_MODE;
- } else {
- if (inode->i_mode != 0)
- problem = PR_1_RESERVED_BAD_MODE;
- }
- if (problem) {
- if (fix_problem(ctx, problem, &pctx)) {
- inode->i_mode = 0;
- e2fsck_write_inode(ctx, ino, inode,
- "pass1");
- }
- }
- check_blocks(ctx, &pctx, block_buf);
- continue;
- }
- /*
- * Check for inodes who might have been part of the
- * orphaned list linked list. They should have gotten
- * dealt with by now, unless the list had somehow been
- * corrupted.
- *
- * FIXME: In the future, inodes which are still in use
- * (and which are therefore) pending truncation should
- * be handled specially. Right now we just clear the
- * dtime field, and the normal e2fsck handling of
- * inodes where i_size and the inode blocks are
- * inconsistent is to fix i_size, instead of releasing
- * the extra blocks. This won't catch the inodes that
- * was at the end of the orphan list, but it's better
- * than nothing. The right answer is that there
- * shouldn't be any bugs in the orphan list handling. :-)
- */
- if (inode->i_dtime && !busted_fs_time &&
- inode->i_dtime < ctx->fs->super->s_inodes_count) {
- if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
- inode->i_dtime = inode->i_links_count ?
- 0 : time(NULL);
- e2fsck_write_inode(ctx, ino, inode,
- "pass1");
- }
- }
-
- /*
- * This code assumes that deleted inodes have
- * i_links_count set to 0.
- */
- if (!inode->i_links_count) {
- if (!inode->i_dtime && inode->i_mode) {
- if (fix_problem(ctx,
- PR_1_ZERO_DTIME, &pctx)) {
- inode->i_dtime = time(NULL);
- e2fsck_write_inode(ctx, ino, inode,
- "pass1");
- }
- }
- continue;
- }
- /*
- * n.b. 0.3c ext2fs code didn't clear i_links_count for
- * deleted files. Oops.
- *
- * Since all new ext2 implementations get this right,
- * we now assume that the case of non-zero
- * i_links_count and non-zero dtime means that we
- * should keep the file, not delete it.
- *
- */
- if (inode->i_dtime) {
- if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
- inode->i_dtime = 0;
- e2fsck_write_inode(ctx, ino, inode, "pass1");
- }
- }
-
- ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
- switch (fs->super->s_creator_os) {
- case EXT2_OS_LINUX:
- frag = inode->osd2.linux2.l_i_frag;
- fsize = inode->osd2.linux2.l_i_fsize;
- break;
- case EXT2_OS_HURD:
- frag = inode->osd2.hurd2.h_i_frag;
- fsize = inode->osd2.hurd2.h_i_fsize;
- break;
- case EXT2_OS_MASIX:
- frag = inode->osd2.masix2.m_i_frag;
- fsize = inode->osd2.masix2.m_i_fsize;
- break;
- default:
- frag = fsize = 0;
- }
-
- if (inode->i_faddr || frag || fsize ||
- (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
- mark_inode_bad(ctx, ino);
- if (inode->i_flags & EXT2_IMAGIC_FL) {
- if (imagic_fs) {
- if (!ctx->inode_imagic_map)
- alloc_imagic_map(ctx);
- ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
- ino);
- } else {
- if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
- inode->i_flags &= ~EXT2_IMAGIC_FL;
- e2fsck_write_inode(ctx, ino,
- inode, "pass1");
- }
- }
- }
-
- check_inode_extra_space(ctx, &pctx);
-
- if (LINUX_S_ISDIR(inode->i_mode)) {
- ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
- e2fsck_add_dir_info(ctx, ino, 0);
- ctx->fs_directory_count++;
- } else if (LINUX_S_ISREG (inode->i_mode)) {
- ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
- ctx->fs_regular_count++;
- } else if (LINUX_S_ISCHR (inode->i_mode) &&
- e2fsck_pass1_check_device_inode(fs, inode)) {
- check_immutable(ctx, &pctx);
- check_size(ctx, &pctx);
- ctx->fs_chardev_count++;
- } else if (LINUX_S_ISBLK (inode->i_mode) &&
- e2fsck_pass1_check_device_inode(fs, inode)) {
- check_immutable(ctx, &pctx);
- check_size(ctx, &pctx);
- ctx->fs_blockdev_count++;
- } else if (LINUX_S_ISLNK (inode->i_mode) &&
- e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
- check_immutable(ctx, &pctx);
- ctx->fs_symlinks_count++;
- if (ext2fs_inode_data_blocks(fs, inode) == 0) {
- ctx->fs_fast_symlinks_count++;
- check_blocks(ctx, &pctx, block_buf);
- continue;
- }
- }
- else if (LINUX_S_ISFIFO (inode->i_mode) &&
- e2fsck_pass1_check_device_inode(fs, inode)) {
- check_immutable(ctx, &pctx);
- check_size(ctx, &pctx);
- ctx->fs_fifo_count++;
- } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
- e2fsck_pass1_check_device_inode(fs, inode)) {
- check_immutable(ctx, &pctx);
- check_size(ctx, &pctx);
- ctx->fs_sockets_count++;
- } else
- mark_inode_bad(ctx, ino);
- if (inode->i_block[EXT2_IND_BLOCK])
- ctx->fs_ind_count++;
- if (inode->i_block[EXT2_DIND_BLOCK])
- ctx->fs_dind_count++;
- if (inode->i_block[EXT2_TIND_BLOCK])
- ctx->fs_tind_count++;
- if (inode->i_block[EXT2_IND_BLOCK] ||
- inode->i_block[EXT2_DIND_BLOCK] ||
- inode->i_block[EXT2_TIND_BLOCK] ||
- inode->i_file_acl) {
- inodes_to_process[process_inode_count].ino = ino;
- inodes_to_process[process_inode_count].inode = *inode;
- process_inode_count++;
- } else
- check_blocks(ctx, &pctx, block_buf);
-
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
-
- if (process_inode_count >= ctx->process_inode_size) {
- process_inodes(ctx, block_buf);
-
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
- }
- }
- process_inodes(ctx, block_buf);
- ext2fs_close_inode_scan(scan);
- ehandler_operation(0);
-
- /*
- * If any extended attribute blocks' reference counts need to
- * be adjusted, either up (ctx->refcount_extra), or down
- * (ctx->refcount), then fix them.
- */
- if (ctx->refcount) {
- adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
- ea_refcount_free(ctx->refcount);
- ctx->refcount = 0;
- }
- if (ctx->refcount_extra) {
- adjust_extattr_refcount(ctx, ctx->refcount_extra,
- block_buf, +1);
- ea_refcount_free(ctx->refcount_extra);
- ctx->refcount_extra = 0;
- }
-
- if (ctx->invalid_bitmaps)
- handle_fs_bad_blocks(ctx);
-
- /* We don't need the block_ea_map any more */
- ext2fs_free_block_bitmap(ctx->block_ea_map);
- ctx->block_ea_map = 0;
-
- if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
- ext2fs_block_bitmap save_bmap;
-
- save_bmap = fs->block_map;
- fs->block_map = ctx->block_found_map;
- clear_problem_context(&pctx);
- pctx.errcode = ext2fs_create_resize_inode(fs);
- if (pctx.errcode) {
- fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
- /* Should never get here */
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
- "recreate inode");
- inode->i_mtime = time(NULL);
- e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
- "recreate inode");
- fs->block_map = save_bmap;
- ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
- }
-
- if (ctx->flags & E2F_FLAG_RESTART) {
- /*
- * Only the master copy of the superblock and block
- * group descriptors are going to be written during a
- * restart, so set the superblock to be used to be the
- * master superblock.
- */
- ctx->use_superblock = 0;
- unwind_pass1();
- goto endit;
- }
-
- if (ctx->block_dup_map) {
- if (ctx->options & E2F_OPT_PREEN) {
- clear_problem_context(&pctx);
- fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
- }
- e2fsck_pass1_dupblocks(ctx, block_buf);
- }
- ext2fs_free_mem(&inodes_to_process);
-endit:
- e2fsck_use_inode_shortcuts(ctx, 0);
-
- ext2fs_free_mem(&block_buf);
- ext2fs_free_mem(&inode);
-}
-
-/*
- * When the inode_scan routines call this callback at the end of the
- * glock group, call process_inodes.
- */
-static errcode_t scan_callback(ext2_filsys fs,
- dgrp_t group, void * priv_data)
-{
- struct scan_callback_struct *scan_struct;
- e2fsck_t ctx;
-
- scan_struct = (struct scan_callback_struct *) priv_data;
- ctx = scan_struct->ctx;
-
- process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
-
- if (ctx->progress)
- if ((ctx->progress)(ctx, 1, group+1,
- ctx->fs->group_desc_count))
- return EXT2_ET_CANCEL_REQUESTED;
-
- return 0;
-}
-
-/*
- * Process the inodes in the "inodes to process" list.
- */
-static void process_inodes(e2fsck_t ctx, char *block_buf)
-{
- int i;
- struct ext2_inode *old_stashed_inode;
- ext2_ino_t old_stashed_ino;
- const char *old_operation;
- char buf[80];
- struct problem_context pctx;
-
- /* begin process_inodes */
- if (process_inode_count == 0)
- return;
- old_operation = ehandler_operation(0);
- old_stashed_inode = ctx->stashed_inode;
- old_stashed_ino = ctx->stashed_ino;
- qsort(inodes_to_process, process_inode_count,
- sizeof(struct process_inode_block), process_inode_cmp);
- clear_problem_context(&pctx);
- for (i=0; i < process_inode_count; i++) {
- pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
- pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
- sprintf(buf, _("reading indirect blocks of inode %u"),
- pctx.ino);
- ehandler_operation(buf);
- check_blocks(ctx, &pctx, block_buf);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- break;
- }
- ctx->stashed_inode = old_stashed_inode;
- ctx->stashed_ino = old_stashed_ino;
- process_inode_count = 0;
- /* end process inodes */
-
- ehandler_operation(old_operation);
-}
-
-static int process_inode_cmp(const void *a, const void *b)
-{
- const struct process_inode_block *ib_a =
- (const struct process_inode_block *) a;
- const struct process_inode_block *ib_b =
- (const struct process_inode_block *) b;
- int ret;
-
- ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
- ib_b->inode.i_block[EXT2_IND_BLOCK]);
- if (ret == 0)
- ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
- return ret;
-}
-
-/*
- * Mark an inode as being bad in some what
- */
-static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
-{
- struct problem_context pctx;
-
- if (!ctx->inode_bad_map) {
- clear_problem_context(&pctx);
-
- pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
- _("bad inode map"), &ctx->inode_bad_map);
- if (pctx.errcode) {
- pctx.num = 3;
- fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
- /* Should never get here */
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- }
- ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
-}
-
-
-/*
- * This procedure will allocate the inode imagic table
- */
-static void alloc_imagic_map(e2fsck_t ctx)
-{
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
- pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
- _("imagic inode map"),
- &ctx->inode_imagic_map);
- if (pctx.errcode) {
- pctx.num = 5;
- fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
- /* Should never get here */
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-}
-
-/*
- * Marks a block as in use, setting the dup_map if it's been set
- * already. Called by process_block and process_bad_block.
- *
- * WARNING: Assumes checks have already been done to make sure block
- * is valid. This is true in both process_block and process_bad_block.
- */
-static void mark_block_used(e2fsck_t ctx, blk_t block)
-{
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
-
- if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
- if (!ctx->block_dup_map) {
- pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
- _("multiply claimed block map"),
- &ctx->block_dup_map);
- if (pctx.errcode) {
- pctx.num = 3;
- fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
- &pctx);
- /* Should never get here */
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- }
- ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
- } else {
- ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
- }
-}
-
-/*
- * Adjust the extended attribute block's reference counts at the end
- * of pass 1, either by subtracting out references for EA blocks that
- * are still referenced in ctx->refcount, or by adding references for
- * EA blocks that had extra references as accounted for in
- * ctx->refcount_extra.
- */
-static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
- char *block_buf, int adjust_sign)
-{
- struct ext2_ext_attr_header *header;
- struct problem_context pctx;
- ext2_filsys fs = ctx->fs;
- blk_t blk;
- __u32 should_be;
- int count;
-
- clear_problem_context(&pctx);
-
- ea_refcount_intr_begin(refcount);
- while (1) {
- if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
- break;
- pctx.blk = blk;
- pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
- if (pctx.errcode) {
- fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
- return;
- }
- header = (struct ext2_ext_attr_header *) block_buf;
- pctx.blkcount = header->h_refcount;
- should_be = header->h_refcount + adjust_sign * count;
- pctx.num = should_be;
- if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
- header->h_refcount = should_be;
- pctx.errcode = ext2fs_write_ext_attr(fs, blk,
- block_buf);
- if (pctx.errcode) {
- fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
- continue;
- }
- }
- }
-}
-
-/*
- * Handle processing the extended attribute blocks
- */
-static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
- char *block_buf)
-{
- ext2_filsys fs = ctx->fs;
- ext2_ino_t ino = pctx->ino;
- struct ext2_inode *inode = pctx->inode;
- blk_t blk;
- char * end;
- struct ext2_ext_attr_header *header;
- struct ext2_ext_attr_entry *entry;
- int count;
- region_t region;
-
- blk = inode->i_file_acl;
- if (blk == 0)
- return 0;
-
- /*
- * If the Extended attribute flag isn't set, then a non-zero
- * file acl means that the inode is corrupted.
- *
- * Or if the extended attribute block is an invalid block,
- * then the inode is also corrupted.
- */
- if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
- (blk < fs->super->s_first_data_block) ||
- (blk >= fs->super->s_blocks_count)) {
- mark_inode_bad(ctx, ino);
- return 0;
- }
-
- /* If ea bitmap hasn't been allocated, create it */
- if (!ctx->block_ea_map) {
- pctx->errcode = ext2fs_allocate_block_bitmap(fs,
- _("ext attr block map"),
- &ctx->block_ea_map);
- if (pctx->errcode) {
- pctx->num = 2;
- fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return 0;
- }
- }
-
- /* Create the EA refcount structure if necessary */
- if (!ctx->refcount) {
- pctx->errcode = ea_refcount_create(0, &ctx->refcount);
- if (pctx->errcode) {
- pctx->num = 1;
- fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return 0;
- }
- }
-
- /* Have we seen this EA block before? */
- if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
- if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
- return 1;
- /* Ooops, this EA was referenced more than it stated */
- if (!ctx->refcount_extra) {
- pctx->errcode = ea_refcount_create(0,
- &ctx->refcount_extra);
- if (pctx->errcode) {
- pctx->num = 2;
- fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return 0;
- }
- }
- ea_refcount_increment(ctx->refcount_extra, blk, 0);
- return 1;
- }
-
- /*
- * OK, we haven't seen this EA block yet. So we need to
- * validate it
- */
- pctx->blk = blk;
- pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
- if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
- goto clear_extattr;
- header = (struct ext2_ext_attr_header *) block_buf;
- pctx->blk = inode->i_file_acl;
- if (((ctx->ext_attr_ver == 1) &&
- (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
- ((ctx->ext_attr_ver == 2) &&
- (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
- if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
- goto clear_extattr;
- }
-
- if (header->h_blocks != 1) {
- if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
- goto clear_extattr;
- }
-
- region = region_create(0, fs->blocksize);
- if (!region) {
- fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return 0;
- }
- if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
- if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
- goto clear_extattr;
- }
-
- entry = (struct ext2_ext_attr_entry *)(header+1);
- end = block_buf + fs->blocksize;
- while ((char *)entry < end && *(__u32 *)entry) {
- if (region_allocate(region, (char *)entry - (char *)header,
- EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
- if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
- goto clear_extattr;
- }
- if ((ctx->ext_attr_ver == 1 &&
- (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
- (ctx->ext_attr_ver == 2 &&
- entry->e_name_index == 0)) {
- if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
- goto clear_extattr;
- }
- if (entry->e_value_block != 0) {
- if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
- goto clear_extattr;
- }
- if (entry->e_value_size &&
- region_allocate(region, entry->e_value_offs,
- EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
- if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
- goto clear_extattr;
- }
- entry = EXT2_EXT_ATTR_NEXT(entry);
- }
- if (region_allocate(region, (char *)entry - (char *)header, 4)) {
- if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
- goto clear_extattr;
- }
- region_free(region);
-
- count = header->h_refcount - 1;
- if (count)
- ea_refcount_store(ctx->refcount, blk, count);
- mark_block_used(ctx, blk);
- ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
-
- return 1;
-
-clear_extattr:
- inode->i_file_acl = 0;
- e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
- return 0;
-}
-
-/* Returns 1 if bad htree, 0 if OK */
-static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
- ext2_ino_t ino FSCK_ATTR((unused)),
- struct ext2_inode *inode,
- char *block_buf)
-{
- struct ext2_dx_root_info *root;
- ext2_filsys fs = ctx->fs;
- errcode_t retval;
- blk_t blk;
-
- if ((!LINUX_S_ISDIR(inode->i_mode) &&
- fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
- (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
- fix_problem(ctx, PR_1_HTREE_SET, pctx)))
- return 1;
-
- blk = inode->i_block[0];
- if (((blk == 0) ||
- (blk < fs->super->s_first_data_block) ||
- (blk >= fs->super->s_blocks_count)) &&
- fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
- return 1;
-
- retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
- if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
- return 1;
-
- /* XXX should check that beginning matches a directory */
- root = (struct ext2_dx_root_info *) (block_buf + 24);
-
- if ((root->reserved_zero || root->info_length < 8) &&
- fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
- return 1;
-
- pctx->num = root->hash_version;
- if ((root->hash_version != EXT2_HASH_LEGACY) &&
- (root->hash_version != EXT2_HASH_HALF_MD4) &&
- (root->hash_version != EXT2_HASH_TEA) &&
- fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
- return 1;
-
- if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
- fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
- return 1;
-
- pctx->num = root->indirect_levels;
- if ((root->indirect_levels > 1) &&
- fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
- return 1;
-
- return 0;
-}
-
-/*
- * This subroutine is called on each inode to account for all of the
- * blocks used by that inode.
- */
-static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
- char *block_buf)
-{
- ext2_filsys fs = ctx->fs;
- struct process_block_struct_1 pb;
- ext2_ino_t ino = pctx->ino;
- struct ext2_inode *inode = pctx->inode;
- int bad_size = 0;
- int dirty_inode = 0;
- __u64 size;
-
- pb.ino = ino;
- pb.num_blocks = 0;
- pb.last_block = -1;
- pb.num_illegal_blocks = 0;
- pb.suppress = 0; pb.clear = 0;
- pb.fragmented = 0;
- pb.compressed = 0;
- pb.previous_block = 0;
- pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
- pb.is_reg = LINUX_S_ISREG(inode->i_mode);
- pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
- pb.inode = inode;
- pb.pctx = pctx;
- pb.ctx = ctx;
- pctx->ino = ino;
- pctx->errcode = 0;
-
- if (inode->i_flags & EXT2_COMPRBLK_FL) {
- if (fs->super->s_feature_incompat &
- EXT2_FEATURE_INCOMPAT_COMPRESSION)
- pb.compressed = 1;
- else {
- if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
- inode->i_flags &= ~EXT2_COMPRBLK_FL;
- dirty_inode++;
- }
- }
- }
-
- if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
- pb.num_blocks++;
-
- if (ext2fs_inode_has_valid_blocks(inode))
- pctx->errcode = ext2fs_block_iterate2(fs, ino,
- pb.is_dir ? BLOCK_FLAG_HOLE : 0,
- block_buf, process_block, &pb);
- end_problem_latch(ctx, PR_LATCH_BLOCK);
- end_problem_latch(ctx, PR_LATCH_TOOBIG);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- goto out;
- if (pctx->errcode)
- fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
-
- if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
- ctx->fs_fragmented++;
-
- if (pb.clear) {
- inode->i_links_count = 0;
- ext2fs_icount_store(ctx->inode_link_info, ino, 0);
- inode->i_dtime = time(NULL);
- dirty_inode++;
- ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
- ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
- ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
- /*
- * The inode was probably partially accounted for
- * before processing was aborted, so we need to
- * restart the pass 1 scan.
- */
- ctx->flags |= E2F_FLAG_RESTART;
- goto out;
- }
-
- if (inode->i_flags & EXT2_INDEX_FL) {
- if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
- inode->i_flags &= ~EXT2_INDEX_FL;
- dirty_inode++;
- } else {
-#ifdef ENABLE_HTREE
- e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
-#endif
- }
- }
- if (ctx->dirs_to_hash && pb.is_dir &&
- !(inode->i_flags & EXT2_INDEX_FL) &&
- ((inode->i_size / fs->blocksize) >= 3))
- ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
-
- if (!pb.num_blocks && pb.is_dir) {
- if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
- inode->i_links_count = 0;
- ext2fs_icount_store(ctx->inode_link_info, ino, 0);
- inode->i_dtime = time(NULL);
- dirty_inode++;
- ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
- ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
- ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
- ctx->fs_directory_count--;
- goto out;
- }
- }
-
- pb.num_blocks *= (fs->blocksize / 512);
-
- if (pb.is_dir) {
- int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
- if (nblock > (pb.last_block + 1))
- bad_size = 1;
- else if (nblock < (pb.last_block + 1)) {
- if (((pb.last_block + 1) - nblock) >
- fs->super->s_prealloc_dir_blocks)
- bad_size = 2;
- }
- } else {
- size = EXT2_I_SIZE(inode);
- if ((pb.last_block >= 0) &&
- (size < (__u64) pb.last_block * fs->blocksize))
- bad_size = 3;
- else if (size > ext2_max_sizes[fs->super->s_log_block_size])
- bad_size = 4;
- }
- /* i_size for symlinks is checked elsewhere */
- if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
- pctx->num = (pb.last_block+1) * fs->blocksize;
- if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
- inode->i_size = pctx->num;
- if (!LINUX_S_ISDIR(inode->i_mode))
- inode->i_size_high = pctx->num >> 32;
- dirty_inode++;
- }
- pctx->num = 0;
- }
- if (LINUX_S_ISREG(inode->i_mode) &&
- (inode->i_size_high || inode->i_size & 0x80000000UL))
- ctx->large_files++;
- if (pb.num_blocks != inode->i_blocks) {
- pctx->num = pb.num_blocks;
- if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
- inode->i_blocks = pb.num_blocks;
- dirty_inode++;
- }
- pctx->num = 0;
- }
-out:
- if (dirty_inode)
- e2fsck_write_inode(ctx, ino, inode, "check_blocks");
-}
-
-
-/*
- * This is a helper function for check_blocks().
- */
-static int process_block(ext2_filsys fs,
- blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block FSCK_ATTR((unused)),
- int ref_offset FSCK_ATTR((unused)),
- void *priv_data)
-{
- struct process_block_struct_1 *p;
- struct problem_context *pctx;
- blk_t blk = *block_nr;
- int ret_code = 0;
- int problem = 0;
- e2fsck_t ctx;
-
- p = (struct process_block_struct_1 *) priv_data;
- pctx = p->pctx;
- ctx = p->ctx;
-
- if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
- /* todo: Check that the comprblk_fl is high, that the
- blkaddr pattern looks right (all non-holes up to
- first EXT2FS_COMPRESSED_BLKADDR, then all
- EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
- that the feature_incompat bit is high, and that the
- inode is a regular file. If we're doing a "full
- check" (a concept introduced to e2fsck by e2compr,
- meaning that we look at data blocks as well as
- metadata) then call some library routine that
- checks the compressed data. I'll have to think
- about this, because one particularly important
- problem to be able to fix is to recalculate the
- cluster size if necessary. I think that perhaps
- we'd better do most/all e2compr-specific checks
- separately, after the non-e2compr checks. If not
- doing a full check, it may be useful to test that
- the personality is linux; e.g. if it isn't then
- perhaps this really is just an illegal block. */
- return 0;
- }
-
- if (blk == 0) {
- if (p->is_dir == 0) {
- /*
- * Should never happen, since only directories
- * get called with BLOCK_FLAG_HOLE
- */
-#ifdef DEBUG_E2FSCK
- printf("process_block() called with blk == 0, "
- "blockcnt=%d, inode %lu???\n",
- blockcnt, p->ino);
-#endif
- return 0;
- }
- if (blockcnt < 0)
- return 0;
- if (blockcnt * fs->blocksize < p->inode->i_size) {
- goto mark_dir;
- }
- return 0;
- }
-
- /*
- * Simplistic fragmentation check. We merely require that the
- * file be contiguous. (Which can never be true for really
- * big files that are greater than a block group.)
- */
- if (!HOLE_BLKADDR(p->previous_block)) {
- if (p->previous_block+1 != blk)
- p->fragmented = 1;
- }
- p->previous_block = blk;
-
- if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
- problem = PR_1_TOOBIG_DIR;
- if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
- problem = PR_1_TOOBIG_REG;
- if (!p->is_dir && !p->is_reg && blockcnt > 0)
- problem = PR_1_TOOBIG_SYMLINK;
-
- if (blk < fs->super->s_first_data_block ||
- blk >= fs->super->s_blocks_count)
- problem = PR_1_ILLEGAL_BLOCK_NUM;
-
- if (problem) {
- p->num_illegal_blocks++;
- if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
- if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
- p->clear = 1;
- return BLOCK_ABORT;
- }
- if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
- p->suppress = 1;
- set_latch_flags(PR_LATCH_BLOCK,
- PRL_SUPPRESS, 0);
- }
- }
- pctx->blk = blk;
- pctx->blkcount = blockcnt;
- if (fix_problem(ctx, problem, pctx)) {
- blk = *block_nr = 0;
- ret_code = BLOCK_CHANGED;
- goto mark_dir;
- } else
- return 0;
- }
-
- if (p->ino == EXT2_RESIZE_INO) {
- /*
- * The resize inode has already be sanity checked
- * during pass #0 (the superblock checks). All we
- * have to do is mark the double indirect block as
- * being in use; all of the other blocks are handled
- * by mark_table_blocks()).
- */
- if (blockcnt == BLOCK_COUNT_DIND)
- mark_block_used(ctx, blk);
- } else
- mark_block_used(ctx, blk);
- p->num_blocks++;
- if (blockcnt >= 0)
- p->last_block = blockcnt;
-mark_dir:
- if (p->is_dir && (blockcnt >= 0)) {
- pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
- blk, blockcnt);
- if (pctx->errcode) {
- pctx->blk = blk;
- pctx->num = blockcnt;
- fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
- /* Should never get here */
- ctx->flags |= E2F_FLAG_ABORT;
- return BLOCK_ABORT;
- }
- }
- return ret_code;
-}
-
-static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)),
- blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block FSCK_ATTR((unused)),
- int ref_offset FSCK_ATTR((unused)),
- void *priv_data EXT2FS_ATTR((unused)))
-{
- /*
- * Note: This function processes blocks for the bad blocks
- * inode, which is never compressed. So we don't use HOLE_BLKADDR().
- */
-
- printf("Unrecoverable Error: Found %"PRIi64" bad blocks starting at block number: %u\n", blockcnt, *block_nr);
- return BLOCK_ERROR;
-}
-
-/*
- * This routine gets called at the end of pass 1 if bad blocks are
- * detected in the superblock, group descriptors, inode_bitmaps, or
- * block bitmaps. At this point, all of the blocks have been mapped
- * out, so we can try to allocate new block(s) to replace the bad
- * blocks.
- */
-static void handle_fs_bad_blocks(e2fsck_t ctx EXT2FS_ATTR((unused)))
-{
- printf("Bad blocks detected on your filesystem\n"
- "You should get your data off as the device will soon die\n");
-}
-
-/*
- * This routine marks all blocks which are used by the superblock,
- * group descriptors, inode bitmaps, and block bitmaps.
- */
-static void mark_table_blocks(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- blk_t block, b;
- dgrp_t i;
- int j;
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
-
- block = fs->super->s_first_data_block;
- for (i = 0; i < fs->group_desc_count; i++) {
- pctx.group = i;
-
- ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
-
- /*
- * Mark the blocks used for the inode table
- */
- if (fs->group_desc[i].bg_inode_table) {
- for (j = 0, b = fs->group_desc[i].bg_inode_table;
- j < fs->inode_blocks_per_group;
- j++, b++) {
- if (ext2fs_test_block_bitmap(ctx->block_found_map,
- b)) {
- pctx.blk = b;
- if (fix_problem(ctx,
- PR_1_ITABLE_CONFLICT, &pctx)) {
- ctx->invalid_inode_table_flag[i]++;
- ctx->invalid_bitmaps++;
- }
- } else {
- ext2fs_mark_block_bitmap(ctx->block_found_map, b);
- }
- }
- }
-
- /*
- * Mark block used for the block bitmap
- */
- if (fs->group_desc[i].bg_block_bitmap) {
- if (ext2fs_test_block_bitmap(ctx->block_found_map,
- fs->group_desc[i].bg_block_bitmap)) {
- pctx.blk = fs->group_desc[i].bg_block_bitmap;
- if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
- ctx->invalid_block_bitmap_flag[i]++;
- ctx->invalid_bitmaps++;
- }
- } else {
- ext2fs_mark_block_bitmap(ctx->block_found_map,
- fs->group_desc[i].bg_block_bitmap);
- }
- }
- /*
- * Mark block used for the inode bitmap
- */
- if (fs->group_desc[i].bg_inode_bitmap) {
- if (ext2fs_test_block_bitmap(ctx->block_found_map,
- fs->group_desc[i].bg_inode_bitmap)) {
- pctx.blk = fs->group_desc[i].bg_inode_bitmap;
- if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
- ctx->invalid_inode_bitmap_flag[i]++;
- ctx->invalid_bitmaps++;
- }
- } else {
- ext2fs_mark_block_bitmap(ctx->block_found_map,
- fs->group_desc[i].bg_inode_bitmap);
- }
- }
- block += fs->super->s_blocks_per_group;
- }
-}
-
-/*
- * Thes subroutines short circuits ext2fs_get_blocks and
- * ext2fs_check_directory; we use them since we already have the inode
- * structure, so there's no point in letting the ext2fs library read
- * the inode again.
- */
-static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
- blk_t *blocks)
-{
- e2fsck_t ctx = (e2fsck_t) fs->priv_data;
- int i;
-
- if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
- return EXT2_ET_CALLBACK_NOTHANDLED;
-
- for (i=0; i < EXT2_N_BLOCKS; i++)
- blocks[i] = ctx->stashed_inode->i_block[i];
- return 0;
-}
-
-static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode)
-{
- e2fsck_t ctx = (e2fsck_t) fs->priv_data;
-
- if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
- return EXT2_ET_CALLBACK_NOTHANDLED;
- *inode = *ctx->stashed_inode;
- return 0;
-}
-
-static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode)
-{
- e2fsck_t ctx = (e2fsck_t) fs->priv_data;
-
- if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
- *ctx->stashed_inode = *inode;
- return EXT2_ET_CALLBACK_NOTHANDLED;
-}
-
-static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
-{
- e2fsck_t ctx = (e2fsck_t) fs->priv_data;
-
- if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
- return EXT2_ET_CALLBACK_NOTHANDLED;
-
- if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
- return EXT2_ET_NO_DIRECTORY;
- return 0;
-}
-
-void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int fl_bool)
-{
- ext2_filsys fs = ctx->fs;
-
- if (fl_bool) {
- fs->get_blocks = pass1_get_blocks;
- fs->check_directory = pass1_check_directory;
- fs->read_inode = pass1_read_inode;
- fs->write_inode = pass1_write_inode;
- ctx->stashed_ino = 0;
- } else {
- fs->get_blocks = 0;
- fs->check_directory = 0;
- fs->read_inode = 0;
- fs->write_inode = 0;
- }
-}
-
-/*
- * pass1b.c --- Pass #1b of e2fsck
- *
- * This file contains pass1B, pass1C, and pass1D of e2fsck. They are
- * only invoked if pass 1 discovered blocks which are in use by more
- * than one inode.
- *
- * Pass1B scans the data blocks of all the inodes again, generating a
- * complete list of duplicate blocks and which inodes have claimed
- * them.
- *
- * Pass1C does a tree-traversal of the filesystem, to determine the
- * parent directories of these inodes. This step is necessary so that
- * e2fsck can print out the pathnames of affected inodes.
- *
- * Pass1D is a reconciliation pass. For each inode with duplicate
- * blocks, the user is prompted if s/he would like to clone the file
- * (so that the file gets a fresh copy of the duplicated blocks) or
- * simply to delete the file.
- *
- */
-
-
-/* Needed for architectures where sizeof(int) != sizeof(void *) */
-#define INT_TO_VOIDPTR(val) ((void *)(intptr_t)(val))
-#define VOIDPTR_TO_INT(ptr) ((int)(intptr_t)(ptr))
-
-/* Define an extension to the ext2 library's block count information */
-#define BLOCK_COUNT_EXTATTR (-5)
-
-struct block_el {
- blk_t block;
- struct block_el *next;
-};
-
-struct inode_el {
- ext2_ino_t inode;
- struct inode_el *next;
-};
-
-struct dup_block {
- int num_bad;
- struct inode_el *inode_list;
-};
-
-/*
- * This structure stores information about a particular inode which
- * is sharing blocks with other inodes. This information is collected
- * to display to the user, so that the user knows what files he or she
- * is dealing with, when trying to decide how to resolve the conflict
- * of multiply-claimed blocks.
- */
-struct dup_inode {
- ext2_ino_t dir;
- int num_dupblocks;
- struct ext2_inode inode;
- struct block_el *block_list;
-};
-
-static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
- e2_blkcnt_t blockcnt, blk_t ref_blk,
- int ref_offset, void *priv_data);
-static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
- struct dup_inode *dp, char *block_buf);
-static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
- struct dup_inode *dp, char* block_buf);
-static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
-
-static void pass1b(e2fsck_t ctx, char *block_buf);
-static void pass1c(e2fsck_t ctx, char *block_buf);
-static void pass1d(e2fsck_t ctx, char *block_buf);
-
-static int dup_inode_count = 0;
-
-static dict_t blk_dict, ino_dict;
-
-static ext2fs_inode_bitmap inode_dup_map;
-
-static int dict_int_cmp(const void *a, const void *b)
-{
- intptr_t ia, ib;
-
- ia = (intptr_t)a;
- ib = (intptr_t)b;
-
- return (ia-ib);
-}
-
-/*
- * Add a duplicate block record
- */
-static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
- struct ext2_inode *inode)
-{
- dnode_t *n;
- struct dup_block *db;
- struct dup_inode *di;
- struct block_el *blk_el;
- struct inode_el *ino_el;
-
- n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
- if (n)
- db = (struct dup_block *) dnode_get(n);
- else {
- db = (struct dup_block *) e2fsck_allocate_memory(ctx,
- sizeof(struct dup_block), "duplicate block header");
- db->num_bad = 0;
- db->inode_list = 0;
- dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
- }
- ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
- sizeof(struct inode_el), "inode element");
- ino_el->inode = ino;
- ino_el->next = db->inode_list;
- db->inode_list = ino_el;
- db->num_bad++;
-
- n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
- if (n)
- di = (struct dup_inode *) dnode_get(n);
- else {
- di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
- sizeof(struct dup_inode), "duplicate inode header");
- di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0;
- di->num_dupblocks = 0;
- di->block_list = 0;
- di->inode = *inode;
- dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
- }
- blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
- sizeof(struct block_el), "block element");
- blk_el->block = blk;
- blk_el->next = di->block_list;
- di->block_list = blk_el;
- di->num_dupblocks++;
-}
-
-/*
- * Free a duplicate inode record
- */
-static void inode_dnode_free(dnode_t *node)
-{
- struct dup_inode *di;
- struct block_el *p, *next;
-
- di = (struct dup_inode *) dnode_get(node);
- for (p = di->block_list; p; p = next) {
- next = p->next;
- free(p);
- }
- free(node);
-}
-
-/*
- * Free a duplicate block record
- */
-static void block_dnode_free(dnode_t *node)
-{
- struct dup_block *db;
- struct inode_el *p, *next;
-
- db = (struct dup_block *) dnode_get(node);
- for (p = db->inode_list; p; p = next) {
- next = p->next;
- free(p);
- }
- free(node);
-}
-
-
-/*
- * Main procedure for handling duplicate blocks
- */
-void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
-{
- ext2_filsys fs = ctx->fs;
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
-
- pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
- _("multiply claimed inode map"), &inode_dup_map);
- if (pctx.errcode) {
- fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-
- dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
- dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
- dict_set_allocator(&ino_dict, inode_dnode_free);
- dict_set_allocator(&blk_dict, block_dnode_free);
-
- pass1b(ctx, block_buf);
- pass1c(ctx, block_buf);
- pass1d(ctx, block_buf);
-
- /*
- * Time to free all of the accumulated data structures that we
- * don't need anymore.
- */
- dict_free_nodes(&ino_dict);
- dict_free_nodes(&blk_dict);
-}
-
-/*
- * Scan the inodes looking for inodes that contain duplicate blocks.
- */
-struct process_block_struct_1b {
- e2fsck_t ctx;
- ext2_ino_t ino;
- int dup_blocks;
- struct ext2_inode *inode;
- struct problem_context *pctx;
-};
-
-static void pass1b(e2fsck_t ctx, char *block_buf)
-{
- ext2_filsys fs = ctx->fs;
- ext2_ino_t ino;
- struct ext2_inode inode;
- ext2_inode_scan scan;
- struct process_block_struct_1b pb;
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
-
- if (!(ctx->options & E2F_OPT_PREEN))
- fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
- pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
- &scan);
- if (pctx.errcode) {
- fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- ctx->stashed_inode = &inode;
- pb.ctx = ctx;
- pb.pctx = &pctx;
- pctx.str = "pass1b";
- while (1) {
- pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
- if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
- continue;
- if (pctx.errcode) {
- fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- if (!ino)
- break;
- pctx.ino = ctx->stashed_ino = ino;
- if ((ino != EXT2_BAD_INO) &&
- !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
- continue;
-
- pb.ino = ino;
- pb.dup_blocks = 0;
- pb.inode = &inode;
-
- if (ext2fs_inode_has_valid_blocks(&inode) ||
- (ino == EXT2_BAD_INO))
- pctx.errcode = ext2fs_block_iterate2(fs, ino,
- 0, block_buf, process_pass1b_block, &pb);
- if (inode.i_file_acl)
- process_pass1b_block(fs, &inode.i_file_acl,
- BLOCK_COUNT_EXTATTR, 0, 0, &pb);
- if (pb.dup_blocks) {
- end_problem_latch(ctx, PR_LATCH_DBLOCK);
- if (ino >= EXT2_FIRST_INODE(fs->super) ||
- ino == EXT2_ROOT_INO)
- dup_inode_count++;
- }
- if (pctx.errcode)
- fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
- }
- ext2fs_close_inode_scan(scan);
- e2fsck_use_inode_shortcuts(ctx, 0);
-}
-
-static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
- blk_t *block_nr,
- e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
- blk_t ref_blk FSCK_ATTR((unused)),
- int ref_offset FSCK_ATTR((unused)),
- void *priv_data)
-{
- struct process_block_struct_1b *p;
- e2fsck_t ctx;
-
- if (HOLE_BLKADDR(*block_nr))
- return 0;
- p = (struct process_block_struct_1b *) priv_data;
- ctx = p->ctx;
-
- if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
- return 0;
-
- /* OK, this is a duplicate block */
- if (p->ino != EXT2_BAD_INO) {
- p->pctx->blk = *block_nr;
- fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
- }
- p->dup_blocks++;
- ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
-
- add_dupe(ctx, p->ino, *block_nr, p->inode);
-
- return 0;
-}
-
-/*
- * Pass 1c: Scan directories for inodes with duplicate blocks. This
- * is used so that we can print pathnames when prompting the user for
- * what to do.
- */
-struct search_dir_struct {
- int count;
- ext2_ino_t first_inode;
- ext2_ino_t max_inode;
-};
-
-static int search_dirent_proc(ext2_ino_t dir, int entry,
- struct ext2_dir_entry *dirent,
- int offset FSCK_ATTR((unused)),
- int blocksize FSCK_ATTR((unused)),
- char *buf FSCK_ATTR((unused)),
- void *priv_data)
-{
- struct search_dir_struct *sd;
- struct dup_inode *p;
- dnode_t *n;
-
- sd = (struct search_dir_struct *) priv_data;
-
- if (dirent->inode > sd->max_inode)
- /* Should abort this inode, but not everything */
- return 0;
-
- if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
- !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
- return 0;
-
- n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
- if (!n)
- return 0;
- p = (struct dup_inode *) dnode_get(n);
- p->dir = dir;
- sd->count--;
-
- return sd->count ? 0 : DIRENT_ABORT;
-}
-
-
-static void pass1c(e2fsck_t ctx, char *block_buf)
-{
- ext2_filsys fs = ctx->fs;
- struct search_dir_struct sd;
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
-
- if (!(ctx->options & E2F_OPT_PREEN))
- fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
-
- /*
- * Search through all directories to translate inodes to names
- * (by searching for the containing directory for that inode.)
- */
- sd.count = dup_inode_count;
- sd.first_inode = EXT2_FIRST_INODE(fs->super);
- sd.max_inode = fs->super->s_inodes_count;
- ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
- search_dirent_proc, &sd);
-}
-
-static void pass1d(e2fsck_t ctx, char *block_buf)
-{
- ext2_filsys fs = ctx->fs;
- struct dup_inode *p, *t;
- struct dup_block *q;
- ext2_ino_t *shared, ino;
- int shared_len;
- int i;
- int file_ok;
- int meta_data = 0;
- struct problem_context pctx;
- dnode_t *n, *m;
- struct block_el *s;
- struct inode_el *r;
-
- clear_problem_context(&pctx);
-
- if (!(ctx->options & E2F_OPT_PREEN))
- fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
- e2fsck_read_bitmaps(ctx);
-
- pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
- fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
- shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
- sizeof(ext2_ino_t) * dict_count(&ino_dict),
- "Shared inode list");
- for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
- p = (struct dup_inode *) dnode_get(n);
- shared_len = 0;
- file_ok = 1;
- ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
- if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
- continue;
-
- /*
- * Find all of the inodes which share blocks with this
- * one. First we find all of the duplicate blocks
- * belonging to this inode, and then search each block
- * get the list of inodes, and merge them together.
- */
- for (s = p->block_list; s; s = s->next) {
- m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
- if (!m)
- continue; /* Should never happen... */
- q = (struct dup_block *) dnode_get(m);
- if (q->num_bad > 1)
- file_ok = 0;
- if (check_if_fs_block(ctx, s->block)) {
- file_ok = 0;
- meta_data = 1;
- }
-
- /*
- * Add all inodes used by this block to the
- * shared[] --- which is a unique list, so
- * if an inode is already in shared[], don't
- * add it again.
- */
- for (r = q->inode_list; r; r = r->next) {
- if (r->inode == ino)
- continue;
- for (i = 0; i < shared_len; i++)
- if (shared[i] == r->inode)
- break;
- if (i == shared_len) {
- shared[shared_len++] = r->inode;
- }
- }
- }
-
- /*
- * Report the inode that we are working on
- */
- pctx.inode = &p->inode;
- pctx.ino = ino;
- pctx.dir = p->dir;
- pctx.blkcount = p->num_dupblocks;
- pctx.num = meta_data ? shared_len+1 : shared_len;
- fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
- pctx.blkcount = 0;
- pctx.num = 0;
-
- if (meta_data)
- fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
-
- for (i = 0; i < shared_len; i++) {
- m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
- if (!m)
- continue; /* should never happen */
- t = (struct dup_inode *) dnode_get(m);
- /*
- * Report the inode that we are sharing with
- */
- pctx.inode = &t->inode;
- pctx.ino = shared[i];
- pctx.dir = t->dir;
- fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
- }
- if (file_ok) {
- fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
- continue;
- }
- if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
- pctx.errcode = clone_file(ctx, ino, p, block_buf);
- if (pctx.errcode)
- fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
- else
- continue;
- }
- if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
- delete_file(ctx, ino, p, block_buf);
- else
- ext2fs_unmark_valid(fs);
- }
- ext2fs_free_mem(&shared);
-}
-
-/*
- * Drop the refcount on the dup_block structure, and clear the entry
- * in the block_dup_map if appropriate.
- */
-static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
-{
- p->num_bad--;
- if (p->num_bad <= 0 ||
- (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
- ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
-}
-
-static int delete_file_block(ext2_filsys fs,
- blk_t *block_nr,
- e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
- blk_t ref_block FSCK_ATTR((unused)),
- int ref_offset FSCK_ATTR((unused)),
- void *priv_data)
-{
- struct process_block_struct_1b *pb;
- struct dup_block *p;
- dnode_t *n;
- e2fsck_t ctx;
-
- pb = (struct process_block_struct_1b *) priv_data;
- ctx = pb->ctx;
-
- if (HOLE_BLKADDR(*block_nr))
- return 0;
-
- if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
- n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
- if (n) {
- p = (struct dup_block *) dnode_get(n);
- decrement_badcount(ctx, *block_nr, p);
- } else
- bb_error_msg(_("internal error; can't find dup_blk for %d"),
- *block_nr);
- } else {
- ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
- ext2fs_block_alloc_stats(fs, *block_nr, -1);
- }
-
- return 0;
-}
-
-static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
- struct dup_inode *dp, char* block_buf)
-{
- ext2_filsys fs = ctx->fs;
- struct process_block_struct_1b pb;
- struct ext2_inode inode;
- struct problem_context pctx;
- unsigned int count;
-
- clear_problem_context(&pctx);
- pctx.ino = pb.ino = ino;
- pb.dup_blocks = dp->num_dupblocks;
- pb.ctx = ctx;
- pctx.str = "delete_file";
-
- e2fsck_read_inode(ctx, ino, &inode, "delete_file");
- if (ext2fs_inode_has_valid_blocks(&inode))
- pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
- delete_file_block, &pb);
- if (pctx.errcode)
- fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
- ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
- ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
- if (ctx->inode_bad_map)
- ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
- ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
-
- /* Inode may have changed by block_iterate, so reread it */
- e2fsck_read_inode(ctx, ino, &inode, "delete_file");
- inode.i_links_count = 0;
- inode.i_dtime = time(NULL);
- if (inode.i_file_acl &&
- (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
- count = 1;
- pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
- block_buf, -1, &count);
- if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
- pctx.errcode = 0;
- count = 1;
- }
- if (pctx.errcode) {
- pctx.blk = inode.i_file_acl;
- fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
- }
- /*
- * If the count is zero, then arrange to have the
- * block deleted. If the block is in the block_dup_map,
- * also call delete_file_block since it will take care
- * of keeping the accounting straight.
- */
- if ((count == 0) ||
- ext2fs_test_block_bitmap(ctx->block_dup_map,
- inode.i_file_acl))
- delete_file_block(fs, &inode.i_file_acl,
- BLOCK_COUNT_EXTATTR, 0, 0, &pb);
- }
- e2fsck_write_inode(ctx, ino, &inode, "delete_file");
-}
-
-struct clone_struct {
- errcode_t errcode;
- ext2_ino_t dir;
- char *buf;
- e2fsck_t ctx;
-};
-
-static int clone_file_block(ext2_filsys fs,
- blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block FSCK_ATTR((unused)),
- int ref_offset FSCK_ATTR((unused)),
- void *priv_data)
-{
- struct dup_block *p;
- blk_t new_block;
- errcode_t retval;
- struct clone_struct *cs = (struct clone_struct *) priv_data;
- dnode_t *n;
- e2fsck_t ctx;
-
- ctx = cs->ctx;
-
- if (HOLE_BLKADDR(*block_nr))
- return 0;
-
- if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
- n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
- if (n) {
- p = (struct dup_block *) dnode_get(n);
- retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
- &new_block);
- if (retval) {
- cs->errcode = retval;
- return BLOCK_ABORT;
- }
- if (cs->dir && (blockcnt >= 0)) {
- retval = ext2fs_set_dir_block(fs->dblist,
- cs->dir, new_block, blockcnt);
- if (retval) {
- cs->errcode = retval;
- return BLOCK_ABORT;
- }
- }
-
- retval = io_channel_read_blk(fs->io, *block_nr, 1,
- cs->buf);
- if (retval) {
- cs->errcode = retval;
- return BLOCK_ABORT;
- }
- retval = io_channel_write_blk(fs->io, new_block, 1,
- cs->buf);
- if (retval) {
- cs->errcode = retval;
- return BLOCK_ABORT;
- }
- decrement_badcount(ctx, *block_nr, p);
- *block_nr = new_block;
- ext2fs_mark_block_bitmap(ctx->block_found_map,
- new_block);
- ext2fs_mark_block_bitmap(fs->block_map, new_block);
- return BLOCK_CHANGED;
- } else
- bb_error_msg(_("internal error; can't find dup_blk for %d"),
- *block_nr);
- }
- return 0;
-}
-
-static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
- struct dup_inode *dp, char* block_buf)
-{
- ext2_filsys fs = ctx->fs;
- errcode_t retval;
- struct clone_struct cs;
- struct problem_context pctx;
- blk_t blk;
- dnode_t *n;
- struct inode_el *ino_el;
- struct dup_block *db;
- struct dup_inode *di;
-
- clear_problem_context(&pctx);
- cs.errcode = 0;
- cs.dir = 0;
- cs.ctx = ctx;
- retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
- if (retval)
- return retval;
-
- if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
- cs.dir = ino;
-
- pctx.ino = ino;
- pctx.str = "clone_file";
- if (ext2fs_inode_has_valid_blocks(&dp->inode))
- pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
- clone_file_block, &cs);
- ext2fs_mark_bb_dirty(fs);
- if (pctx.errcode) {
- fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
- retval = pctx.errcode;
- goto errout;
- }
- if (cs.errcode) {
- bb_error_msg(_("returned from clone_file_block"));
- retval = cs.errcode;
- goto errout;
- }
- /* The inode may have changed on disk, so we have to re-read it */
- e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
- blk = dp->inode.i_file_acl;
- if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
- BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
- BLOCK_CHANGED)) {
- e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
- /*
- * If we cloned the EA block, find all other inodes
- * which refered to that EA block, and modify
- * them to point to the new EA block.
- */
- n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
- db = (struct dup_block *) dnode_get(n);
- for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
- if (ino_el->inode == ino)
- continue;
- n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
- di = (struct dup_inode *) dnode_get(n);
- if (di->inode.i_file_acl == blk) {
- di->inode.i_file_acl = dp->inode.i_file_acl;
- e2fsck_write_inode(ctx, ino_el->inode,
- &di->inode, "clone file EA");
- decrement_badcount(ctx, blk, db);
- }
- }
- }
- retval = 0;
-errout:
- ext2fs_free_mem(&cs.buf);
- return retval;
-}
-
-/*
- * This routine returns 1 if a block overlaps with one of the superblocks,
- * group descriptors, inode bitmaps, or block bitmaps.
- */
-static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
-{
- ext2_filsys fs = ctx->fs;
- blk_t block;
- dgrp_t i;
-
- block = fs->super->s_first_data_block;
- for (i = 0; i < fs->group_desc_count; i++) {
-
- /* Check superblocks/block group descriptros */
- if (ext2fs_bg_has_super(fs, i)) {
- if (test_block >= block &&
- (test_block <= block + fs->desc_blocks))
- return 1;
- }
-
- /* Check the inode table */
- if ((fs->group_desc[i].bg_inode_table) &&
- (test_block >= fs->group_desc[i].bg_inode_table) &&
- (test_block < (fs->group_desc[i].bg_inode_table +
- fs->inode_blocks_per_group)))
- return 1;
-
- /* Check the bitmap blocks */
- if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
- (test_block == fs->group_desc[i].bg_inode_bitmap))
- return 1;
-
- block += fs->super->s_blocks_per_group;
- }
- return 0;
-}
-/*
- * pass2.c --- check directory structure
- *
- * Pass 2 of e2fsck iterates through all active directory inodes, and
- * applies to following tests to each directory entry in the directory
- * blocks in the inodes:
- *
- * - The length of the directory entry (rec_len) should be at
- * least 8 bytes, and no more than the remaining space
- * left in the directory block.
- * - The length of the name in the directory entry (name_len)
- * should be less than (rec_len - 8).
- * - The inode number in the directory entry should be within
- * legal bounds.
- * - The inode number should refer to a in-use inode.
- * - The first entry should be '.', and its inode should be
- * the inode of the directory.
- * - The second entry should be '..'.
- *
- * To minimize disk seek time, the directory blocks are processed in
- * sorted order of block numbers.
- *
- * Pass 2 also collects the following information:
- * - The inode numbers of the subdirectories for each directory.
- *
- * Pass 2 relies on the following information from previous passes:
- * - The directory information collected in pass 1.
- * - The inode_used_map bitmap
- * - The inode_bad_map bitmap
- * - The inode_dir_map bitmap
- *
- * Pass 2 frees the following data structures
- * - The inode_bad_map bitmap
- * - The inode_reg_map bitmap
- */
-
-/*
- * Keeps track of how many times an inode is referenced.
- */
-static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
-static int check_dir_block(ext2_filsys fs,
- struct ext2_db_entry *dir_blocks_info,
- void *priv_data);
-static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
- struct problem_context *pctx);
-static int update_dir_block(ext2_filsys fs,
- blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block,
- int ref_offset,
- void *priv_data);
-static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
-static int htree_depth(struct dx_dir_info *dx_dir,
- struct dx_dirblock_info *dx_db);
-static int special_dir_block_cmp(const void *a, const void *b);
-
-struct check_dir_struct {
- char *buf;
- struct problem_context pctx;
- int count, max;
- e2fsck_t ctx;
-};
-
-static void e2fsck_pass2(e2fsck_t ctx)
-{
- struct ext2_super_block *sb = ctx->fs->super;
- struct problem_context pctx;
- ext2_filsys fs = ctx->fs;
- char *buf;
- struct dir_info *dir;
- struct check_dir_struct cd;
- struct dx_dir_info *dx_dir;
- struct dx_dirblock_info *dx_db, *dx_parent;
- int b;
- int i, depth;
- problem_t code;
- int bad_dir;
-
- clear_problem_context(&cd.pctx);
-
- /* Pass 2 */
-
- if (!(ctx->options & E2F_OPT_PREEN))
- fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
-
- cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
- 0, ctx->inode_link_info,
- &ctx->inode_count);
- if (cd.pctx.errcode) {
- fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
- "directory scan buffer");
-
- /*
- * Set up the parent pointer for the root directory, if
- * present. (If the root directory is not present, we will
- * create it in pass 3.)
- */
- dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
- if (dir)
- dir->parent = EXT2_ROOT_INO;
-
- cd.buf = buf;
- cd.ctx = ctx;
- cd.count = 1;
- cd.max = ext2fs_dblist_count(fs->dblist);
-
- if (ctx->progress)
- (void) (ctx->progress)(ctx, 2, 0, cd.max);
-
- if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
- ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
-
- cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
- &cd);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
- if (cd.pctx.errcode) {
- fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-
-#ifdef ENABLE_HTREE
- for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
- if (dx_dir->numblocks == 0)
- continue;
- clear_problem_context(&pctx);
- bad_dir = 0;
- pctx.dir = dx_dir->ino;
- dx_db = dx_dir->dx_block;
- if (dx_db->flags & DX_FLAG_REFERENCED)
- dx_db->flags |= DX_FLAG_DUP_REF;
- else
- dx_db->flags |= DX_FLAG_REFERENCED;
- /*
- * Find all of the first and last leaf blocks, and
- * update their parent's min and max hash values
- */
- for (b=0, dx_db = dx_dir->dx_block;
- b < dx_dir->numblocks;
- b++, dx_db++) {
- if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
- !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
- continue;
- dx_parent = &dx_dir->dx_block[dx_db->parent];
- /*
- * XXX Make sure dx_parent->min_hash > dx_db->min_hash
- */
- if (dx_db->flags & DX_FLAG_FIRST)
- dx_parent->min_hash = dx_db->min_hash;
- /*
- * XXX Make sure dx_parent->max_hash < dx_db->max_hash
- */
- if (dx_db->flags & DX_FLAG_LAST)
- dx_parent->max_hash = dx_db->max_hash;
- }
-
- for (b=0, dx_db = dx_dir->dx_block;
- b < dx_dir->numblocks;
- b++, dx_db++) {
- pctx.blkcount = b;
- pctx.group = dx_db->parent;
- code = 0;
- if (!(dx_db->flags & DX_FLAG_FIRST) &&
- (dx_db->min_hash < dx_db->node_min_hash)) {
- pctx.blk = dx_db->min_hash;
- pctx.blk2 = dx_db->node_min_hash;
- code = PR_2_HTREE_MIN_HASH;
- fix_problem(ctx, code, &pctx);
- bad_dir++;
- }
- if (dx_db->type == DX_DIRBLOCK_LEAF) {
- depth = htree_depth(dx_dir, dx_db);
- if (depth != dx_dir->depth) {
- code = PR_2_HTREE_BAD_DEPTH;
- fix_problem(ctx, code, &pctx);
- bad_dir++;
- }
- }
- /*
- * This test doesn't apply for the root block
- * at block #0
- */
- if (b &&
- (dx_db->max_hash > dx_db->node_max_hash)) {
- pctx.blk = dx_db->max_hash;
- pctx.blk2 = dx_db->node_max_hash;
- code = PR_2_HTREE_MAX_HASH;
- fix_problem(ctx, code, &pctx);
- bad_dir++;
- }
- if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
- code = PR_2_HTREE_NOTREF;
- fix_problem(ctx, code, &pctx);
- bad_dir++;
- } else if (dx_db->flags & DX_FLAG_DUP_REF) {
- code = PR_2_HTREE_DUPREF;
- fix_problem(ctx, code, &pctx);
- bad_dir++;
- }
- if (code == 0)
- continue;
- }
- if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
- clear_htree(ctx, dx_dir->ino);
- dx_dir->numblocks = 0;
- }
- }
-#endif
- ext2fs_free_mem(&buf);
- ext2fs_free_dblist(fs->dblist);
-
- ext2fs_free_inode_bitmap(ctx->inode_bad_map);
- ctx->inode_bad_map = 0;
- ext2fs_free_inode_bitmap(ctx->inode_reg_map);
- ctx->inode_reg_map = 0;
-
- clear_problem_context(&pctx);
- if (ctx->large_files) {
- if (!(sb->s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
- fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
- sb->s_feature_ro_compat |=
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
- ext2fs_mark_super_dirty(fs);
- }
- if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
- fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
- ext2fs_update_dynamic_rev(fs);
- ext2fs_mark_super_dirty(fs);
- }
- } else if (!ctx->large_files &&
- (sb->s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
- if (fs->flags & EXT2_FLAG_RW) {
- sb->s_feature_ro_compat &=
- ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
- ext2fs_mark_super_dirty(fs);
- }
- }
-}
-
-#define MAX_DEPTH 32000
-static int htree_depth(struct dx_dir_info *dx_dir,
- struct dx_dirblock_info *dx_db)
-{
- int depth = 0;
-
- while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
- dx_db = &dx_dir->dx_block[dx_db->parent];
- depth++;
- }
- return depth;
-}
-
-static int dict_de_cmp(const void *a, const void *b)
-{
- const struct ext2_dir_entry *de_a, *de_b;
- int a_len, b_len;
-
- de_a = (const struct ext2_dir_entry *) a;
- a_len = de_a->name_len & 0xFF;
- de_b = (const struct ext2_dir_entry *) b;
- b_len = de_b->name_len & 0xFF;
-
- if (a_len != b_len)
- return (a_len - b_len);
-
- return strncmp(de_a->name, de_b->name, a_len);
-}
-
-/*
- * This is special sort function that makes sure that directory blocks
- * with a dirblock of zero are sorted to the beginning of the list.
- * This guarantees that the root node of the htree directories are
- * processed first, so we know what hash version to use.
- */
-static int special_dir_block_cmp(const void *a, const void *b)
-{
- const struct ext2_db_entry *db_a =
- (const struct ext2_db_entry *) a;
- const struct ext2_db_entry *db_b =
- (const struct ext2_db_entry *) b;
-
- if (db_a->blockcnt && !db_b->blockcnt)
- return 1;
-
- if (!db_a->blockcnt && db_b->blockcnt)
- return -1;
-
- if (db_a->blk != db_b->blk)
- return (int) (db_a->blk - db_b->blk);
-
- if (db_a->ino != db_b->ino)
- return (int) (db_a->ino - db_b->ino);
-
- return (int) (db_a->blockcnt - db_b->blockcnt);
-}
-
-
-/*
- * Make sure the first entry in the directory is '.', and that the
- * directory entry is sane.
- */
-static int check_dot(e2fsck_t ctx,
- struct ext2_dir_entry *dirent,
- ext2_ino_t ino, struct problem_context *pctx)
-{
- struct ext2_dir_entry *nextdir;
- int status = 0;
- int created = 0;
- int new_len;
- int problem = 0;
-
- if (!dirent->inode)
- problem = PR_2_MISSING_DOT;
- else if (((dirent->name_len & 0xFF) != 1) ||
- (dirent->name[0] != '.'))
- problem = PR_2_1ST_NOT_DOT;
- else if (dirent->name[1] != '\0')
- problem = PR_2_DOT_NULL_TERM;
-
- if (problem) {
- if (fix_problem(ctx, problem, pctx)) {
- if (dirent->rec_len < 12)
- dirent->rec_len = 12;
- dirent->inode = ino;
- dirent->name_len = 1;
- dirent->name[0] = '.';
- dirent->name[1] = '\0';
- status = 1;
- created = 1;
- }
- }
- if (dirent->inode != ino) {
- if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
- dirent->inode = ino;
- status = 1;
- }
- }
- if (dirent->rec_len > 12) {
- new_len = dirent->rec_len - 12;
- if (new_len > 12) {
- if (created ||
- fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
- nextdir = (struct ext2_dir_entry *)
- ((char *) dirent + 12);
- dirent->rec_len = 12;
- nextdir->rec_len = new_len;
- nextdir->inode = 0;
- nextdir->name_len = 0;
- status = 1;
- }
- }
- }
- return status;
-}
-
-/*
- * Make sure the second entry in the directory is '..', and that the
- * directory entry is sane. We do not check the inode number of '..'
- * here; this gets done in pass 3.
- */
-static int check_dotdot(e2fsck_t ctx,
- struct ext2_dir_entry *dirent,
- struct dir_info *dir, struct problem_context *pctx)
-{
- int problem = 0;
-
- if (!dirent->inode)
- problem = PR_2_MISSING_DOT_DOT;
- else if (((dirent->name_len & 0xFF) != 2) ||
- (dirent->name[0] != '.') ||
- (dirent->name[1] != '.'))
- problem = PR_2_2ND_NOT_DOT_DOT;
- else if (dirent->name[2] != '\0')
- problem = PR_2_DOT_DOT_NULL_TERM;
-
- if (problem) {
- if (fix_problem(ctx, problem, pctx)) {
- if (dirent->rec_len < 12)
- dirent->rec_len = 12;
- /*
- * Note: we don't have the parent inode just
- * yet, so we will fill it in with the root
- * inode. This will get fixed in pass 3.
- */
- dirent->inode = EXT2_ROOT_INO;
- dirent->name_len = 2;
- dirent->name[0] = '.';
- dirent->name[1] = '.';
- dirent->name[2] = '\0';
- return 1;
- }
- return 0;
- }
- dir->dotdot = dirent->inode;
- return 0;
-}
-
-/*
- * Check to make sure a directory entry doesn't contain any illegal
- * characters.
- */
-static int check_name(e2fsck_t ctx,
- struct ext2_dir_entry *dirent,
- struct problem_context *pctx)
-{
- int i;
- int fixup = -1;
- int ret = 0;
-
- for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
- if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
- if (fixup < 0) {
- fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
- }
- if (fixup) {
- dirent->name[i] = '.';
- ret = 1;
- }
- }
- }
- return ret;
-}
-
-/*
- * Check the directory filetype (if present)
- */
-
-/*
- * Given a mode, return the ext2 file type
- */
-static int ext2_file_type(unsigned int mode)
-{
- if (LINUX_S_ISREG(mode))
- return EXT2_FT_REG_FILE;
-
- if (LINUX_S_ISDIR(mode))
- return EXT2_FT_DIR;
-
- if (LINUX_S_ISCHR(mode))
- return EXT2_FT_CHRDEV;
-
- if (LINUX_S_ISBLK(mode))
- return EXT2_FT_BLKDEV;
-
- if (LINUX_S_ISLNK(mode))
- return EXT2_FT_SYMLINK;
-
- if (LINUX_S_ISFIFO(mode))
- return EXT2_FT_FIFO;
-
- if (LINUX_S_ISSOCK(mode))
- return EXT2_FT_SOCK;
-
- return 0;
-}
-
-static int check_filetype(e2fsck_t ctx,
- struct ext2_dir_entry *dirent,
- struct problem_context *pctx)
-{
- int filetype = dirent->name_len >> 8;
- int should_be = EXT2_FT_UNKNOWN;
- struct ext2_inode inode;
-
- if (!(ctx->fs->super->s_feature_incompat &
- EXT2_FEATURE_INCOMPAT_FILETYPE)) {
- if (filetype == 0 ||
- !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
- return 0;
- dirent->name_len = dirent->name_len & 0xFF;
- return 1;
- }
-
- if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
- should_be = EXT2_FT_DIR;
- } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
- dirent->inode)) {
- should_be = EXT2_FT_REG_FILE;
- } else if (ctx->inode_bad_map &&
- ext2fs_test_inode_bitmap(ctx->inode_bad_map,
- dirent->inode))
- should_be = 0;
- else {
- e2fsck_read_inode(ctx, dirent->inode, &inode,
- "check_filetype");
- should_be = ext2_file_type(inode.i_mode);
- }
- if (filetype == should_be)
- return 0;
- pctx->num = should_be;
-
- if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
- pctx) == 0)
- return 0;
-
- dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
- return 1;
-}
-
-#ifdef ENABLE_HTREE
-static void parse_int_node(ext2_filsys fs,
- struct ext2_db_entry *db,
- struct check_dir_struct *cd,
- struct dx_dir_info *dx_dir,
- char *block_buf)
-{
- struct ext2_dx_root_info *root;
- struct ext2_dx_entry *ent;
- struct ext2_dx_countlimit *limit;
- struct dx_dirblock_info *dx_db;
- int i, expect_limit, count;
- blk_t blk;
- ext2_dirhash_t min_hash = 0xffffffff;
- ext2_dirhash_t max_hash = 0;
- ext2_dirhash_t hash = 0, prev_hash;
-
- if (db->blockcnt == 0) {
- root = (struct ext2_dx_root_info *) (block_buf + 24);
- ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
- } else {
- ent = (struct ext2_dx_entry *) (block_buf+8);
- }
- limit = (struct ext2_dx_countlimit *) ent;
-
- count = ext2fs_le16_to_cpu(limit->count);
- expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
- sizeof(struct ext2_dx_entry);
- if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
- cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
- if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
- goto clear_and_exit;
- }
- if (count > expect_limit) {
- cd->pctx.num = count;
- if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
- goto clear_and_exit;
- count = expect_limit;
- }
-
- for (i=0; i < count; i++) {
- prev_hash = hash;
- hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
- blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
- /* Check to make sure the block is valid */
- if (blk > (blk_t) dx_dir->numblocks) {
- cd->pctx.blk = blk;
- if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
- &cd->pctx))
- goto clear_and_exit;
- }
- if (hash < prev_hash &&
- fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
- goto clear_and_exit;
- dx_db = &dx_dir->dx_block[blk];
- if (dx_db->flags & DX_FLAG_REFERENCED) {
- dx_db->flags |= DX_FLAG_DUP_REF;
- } else {
- dx_db->flags |= DX_FLAG_REFERENCED;
- dx_db->parent = db->blockcnt;
- }
- if (hash < min_hash)
- min_hash = hash;
- if (hash > max_hash)
- max_hash = hash;
- dx_db->node_min_hash = hash;
- if ((i+1) < count)
- dx_db->node_max_hash =
- ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
- else {
- dx_db->node_max_hash = 0xfffffffe;
- dx_db->flags |= DX_FLAG_LAST;
- }
- if (i == 0)
- dx_db->flags |= DX_FLAG_FIRST;
- }
- dx_db = &dx_dir->dx_block[db->blockcnt];
- dx_db->min_hash = min_hash;
- dx_db->max_hash = max_hash;
- return;
-
-clear_and_exit:
- clear_htree(cd->ctx, cd->pctx.ino);
- dx_dir->numblocks = 0;
-}
-#endif /* ENABLE_HTREE */
-
-/*
- * Given a busted directory, try to salvage it somehow.
- *
- */
-static void salvage_directory(ext2_filsys fs,
- struct ext2_dir_entry *dirent,
- struct ext2_dir_entry *prev,
- unsigned int *offset)
-{
- char *cp = (char *) dirent;
- int left = fs->blocksize - *offset - dirent->rec_len;
- int name_len = dirent->name_len & 0xFF;
-
- /*
- * Special case of directory entry of size 8: copy what's left
- * of the directory block up to cover up the invalid hole.
- */
- if ((left >= 12) && (dirent->rec_len == 8)) {
- memmove(cp, cp+8, left);
- memset(cp + left, 0, 8);
- return;
- }
- /*
- * If the directory entry overruns the end of the directory
- * block, and the name is small enough to fit, then adjust the
- * record length.
- */
- if ((left < 0) &&
- (name_len + 8 <= dirent->rec_len + left) &&
- dirent->inode <= fs->super->s_inodes_count &&
- strnlen(dirent->name, name_len) == name_len) {
- dirent->rec_len += left;
- return;
- }
- /*
- * If the directory entry is a multiple of four, so it is
- * valid, let the previous directory entry absorb the invalid
- * one.
- */
- if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
- prev->rec_len += dirent->rec_len;
- *offset += dirent->rec_len;
- return;
- }
- /*
- * Default salvage method --- kill all of the directory
- * entries for the rest of the block. We will either try to
- * absorb it into the previous directory entry, or create a
- * new empty directory entry the rest of the directory block.
- */
- if (prev) {
- prev->rec_len += fs->blocksize - *offset;
- *offset = fs->blocksize;
- } else {
- dirent->rec_len = fs->blocksize - *offset;
- dirent->name_len = 0;
- dirent->inode = 0;
- }
-}
-
-static int check_dir_block(ext2_filsys fs,
- struct ext2_db_entry *db,
- void *priv_data)
-{
- struct dir_info *subdir, *dir;
- struct dx_dir_info *dx_dir;
-#ifdef ENABLE_HTREE
- struct dx_dirblock_info *dx_db = NULL;
-#endif /* ENABLE_HTREE */
- struct ext2_dir_entry *dirent, *prev;
- ext2_dirhash_t hash;
- unsigned int offset = 0;
- int dir_modified = 0;
- int dot_state;
- blk_t block_nr = db->blk;
- ext2_ino_t ino = db->ino;
- __u16 links;
- struct check_dir_struct *cd;
- char *buf;
- e2fsck_t ctx;
- int problem;
- struct ext2_dx_root_info *root;
- struct ext2_dx_countlimit *limit;
- static dict_t de_dict;
- struct problem_context pctx;
- int dups_found = 0;
-
- cd = (struct check_dir_struct *) priv_data;
- buf = cd->buf;
- ctx = cd->ctx;
-
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return DIRENT_ABORT;
-
- if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
- return DIRENT_ABORT;
-
- /*
- * Make sure the inode is still in use (could have been
- * deleted in the duplicate/bad blocks pass.
- */
- if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
- return 0;
-
- cd->pctx.ino = ino;
- cd->pctx.blk = block_nr;
- cd->pctx.blkcount = db->blockcnt;
- cd->pctx.ino2 = 0;
- cd->pctx.dirent = 0;
- cd->pctx.num = 0;
-
- if (db->blk == 0) {
- if (allocate_dir_block(ctx, db, &cd->pctx))
- return 0;
- block_nr = db->blk;
- }
-
- if (db->blockcnt)
- dot_state = 2;
- else
- dot_state = 0;
-
- if (ctx->dirs_to_hash &&
- ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
- dups_found++;
-
- cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
- if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
- cd->pctx.errcode = 0; /* We'll handle this ourselves */
- if (cd->pctx.errcode) {
- if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
- ctx->flags |= E2F_FLAG_ABORT;
- return DIRENT_ABORT;
- }
- memset(buf, 0, fs->blocksize);
- }
-#ifdef ENABLE_HTREE
- dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
- if (dx_dir && dx_dir->numblocks) {
- if (db->blockcnt >= dx_dir->numblocks) {
- printf("XXX should never happen!!!\n");
- abort();
- }
- dx_db = &dx_dir->dx_block[db->blockcnt];
- dx_db->type = DX_DIRBLOCK_LEAF;
- dx_db->phys = block_nr;
- dx_db->min_hash = ~0;
- dx_db->max_hash = 0;
-
- dirent = (struct ext2_dir_entry *) buf;
- limit = (struct ext2_dx_countlimit *) (buf+8);
- if (db->blockcnt == 0) {
- root = (struct ext2_dx_root_info *) (buf + 24);
- dx_db->type = DX_DIRBLOCK_ROOT;
- dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
- if ((root->reserved_zero ||
- root->info_length < 8 ||
- root->indirect_levels > 1) &&
- fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
- clear_htree(ctx, ino);
- dx_dir->numblocks = 0;
- dx_db = 0;
- }
- dx_dir->hashversion = root->hash_version;
- dx_dir->depth = root->indirect_levels + 1;
- } else if ((dirent->inode == 0) &&
- (dirent->rec_len == fs->blocksize) &&
- (dirent->name_len == 0) &&
- (ext2fs_le16_to_cpu(limit->limit) ==
- ((fs->blocksize-8) /
- sizeof(struct ext2_dx_entry))))
- dx_db->type = DX_DIRBLOCK_NODE;
- }
-#endif /* ENABLE_HTREE */
-
- dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
- prev = 0;
- do {
- problem = 0;
- dirent = (struct ext2_dir_entry *) (buf + offset);
- cd->pctx.dirent = dirent;
- cd->pctx.num = offset;
- if (((offset + dirent->rec_len) > fs->blocksize) ||
- (dirent->rec_len < 12) ||
- ((dirent->rec_len % 4) != 0) ||
- (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
- if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
- salvage_directory(fs, dirent, prev, &offset);
- dir_modified++;
- continue;
- } else
- goto abort_free_dict;
- }
- if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
- if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
- dirent->name_len = EXT2_NAME_LEN;
- dir_modified++;
- }
- }
-
- if (dot_state == 0) {
- if (check_dot(ctx, dirent, ino, &cd->pctx))
- dir_modified++;
- } else if (dot_state == 1) {
- dir = e2fsck_get_dir_info(ctx, ino);
- if (!dir) {
- fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
- goto abort_free_dict;
- }
- if (check_dotdot(ctx, dirent, dir, &cd->pctx))
- dir_modified++;
- } else if (dirent->inode == ino) {
- problem = PR_2_LINK_DOT;
- if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
- dirent->inode = 0;
- dir_modified++;
- goto next;
- }
- }
- if (!dirent->inode)
- goto next;
-
- /*
- * Make sure the inode listed is a legal one.
- */
- if (((dirent->inode != EXT2_ROOT_INO) &&
- (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
- (dirent->inode > fs->super->s_inodes_count)) {
- problem = PR_2_BAD_INO;
- } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
- dirent->inode))) {
- /*
- * If the inode is unused, offer to clear it.
- */
- problem = PR_2_UNUSED_INODE;
- } else if ((dot_state > 1) &&
- ((dirent->name_len & 0xFF) == 1) &&
- (dirent->name[0] == '.')) {
- /*
- * If there's a '.' entry in anything other
- * than the first directory entry, it's a
- * duplicate entry that should be removed.
- */
- problem = PR_2_DUP_DOT;
- } else if ((dot_state > 1) &&
- ((dirent->name_len & 0xFF) == 2) &&
- (dirent->name[0] == '.') &&
- (dirent->name[1] == '.')) {
- /*
- * If there's a '..' entry in anything other
- * than the second directory entry, it's a
- * duplicate entry that should be removed.
- */
- problem = PR_2_DUP_DOT_DOT;
- } else if ((dot_state > 1) &&
- (dirent->inode == EXT2_ROOT_INO)) {
- /*
- * Don't allow links to the root directory.
- * We check this specially to make sure we
- * catch this error case even if the root
- * directory hasn't been created yet.
- */
- problem = PR_2_LINK_ROOT;
- } else if ((dot_state > 1) &&
- (dirent->name_len & 0xFF) == 0) {
- /*
- * Don't allow zero-length directory names.
- */
- problem = PR_2_NULL_NAME;
- }
-
- if (problem) {
- if (fix_problem(ctx, problem, &cd->pctx)) {
- dirent->inode = 0;
- dir_modified++;
- goto next;
- } else {
- ext2fs_unmark_valid(fs);
- if (problem == PR_2_BAD_INO)
- goto next;
- }
- }
-
- /*
- * If the inode was marked as having bad fields in
- * pass1, process it and offer to fix/clear it.
- * (We wait until now so that we can display the
- * pathname to the user.)
- */
- if (ctx->inode_bad_map &&
- ext2fs_test_inode_bitmap(ctx->inode_bad_map,
- dirent->inode)) {
- if (e2fsck_process_bad_inode(ctx, ino,
- dirent->inode,
- buf + fs->blocksize)) {
- dirent->inode = 0;
- dir_modified++;
- goto next;
- }
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return DIRENT_ABORT;
- }
-
- if (check_name(ctx, dirent, &cd->pctx))
- dir_modified++;
-
- if (check_filetype(ctx, dirent, &cd->pctx))
- dir_modified++;
-
-#ifdef ENABLE_HTREE
- if (dx_db) {
- ext2fs_dirhash(dx_dir->hashversion, dirent->name,
- (dirent->name_len & 0xFF),
- fs->super->s_hash_seed, &hash, 0);
- if (hash < dx_db->min_hash)
- dx_db->min_hash = hash;
- if (hash > dx_db->max_hash)
- dx_db->max_hash = hash;
- }
-#endif
-
- /*
- * If this is a directory, then mark its parent in its
- * dir_info structure. If the parent field is already
- * filled in, then this directory has more than one
- * hard link. We assume the first link is correct,
- * and ask the user if he/she wants to clear this one.
- */
- if ((dot_state > 1) &&
- (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
- dirent->inode))) {
- subdir = e2fsck_get_dir_info(ctx, dirent->inode);
- if (!subdir) {
- cd->pctx.ino = dirent->inode;
- fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
- goto abort_free_dict;
- }
- if (subdir->parent) {
- cd->pctx.ino2 = subdir->parent;
- if (fix_problem(ctx, PR_2_LINK_DIR,
- &cd->pctx)) {
- dirent->inode = 0;
- dir_modified++;
- goto next;
- }
- cd->pctx.ino2 = 0;
- } else
- subdir->parent = ino;
- }
-
- if (dups_found) {
- ;
- } else if (dict_lookup(&de_dict, dirent)) {
- clear_problem_context(&pctx);
- pctx.ino = ino;
- pctx.dirent = dirent;
- fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
- if (!ctx->dirs_to_hash)
- ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
- if (ctx->dirs_to_hash)
- ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
- dups_found++;
- } else
- dict_alloc_insert(&de_dict, dirent, dirent);
-
- ext2fs_icount_increment(ctx->inode_count, dirent->inode,
- &links);
- if (links > 1)
- ctx->fs_links_count++;
- ctx->fs_total_count++;
- next:
- prev = dirent;
- offset += dirent->rec_len;
- dot_state++;
- } while (offset < fs->blocksize);
-#ifdef ENABLE_HTREE
- if (dx_db) {
- cd->pctx.dir = cd->pctx.ino;
- if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
- (dx_db->type == DX_DIRBLOCK_NODE))
- parse_int_node(fs, db, cd, dx_dir, buf);
- }
-#endif /* ENABLE_HTREE */
- if (offset != fs->blocksize) {
- cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
- if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
- dirent->rec_len = cd->pctx.num;
- dir_modified++;
- }
- }
- if (dir_modified) {
- cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
- if (cd->pctx.errcode) {
- if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
- &cd->pctx))
- goto abort_free_dict;
- }
- ext2fs_mark_changed(fs);
- }
- dict_free_nodes(&de_dict);
- return 0;
-abort_free_dict:
- dict_free_nodes(&de_dict);
- ctx->flags |= E2F_FLAG_ABORT;
- return DIRENT_ABORT;
-}
-
-/*
- * This function is called to deallocate a block, and is an interator
- * functioned called by deallocate inode via ext2fs_iterate_block().
- */
-static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
- e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
- blk_t ref_block FSCK_ATTR((unused)),
- int ref_offset FSCK_ATTR((unused)),
- void *priv_data)
-{
- e2fsck_t ctx = (e2fsck_t) priv_data;
-
- if (HOLE_BLKADDR(*block_nr))
- return 0;
- if ((*block_nr < fs->super->s_first_data_block) ||
- (*block_nr >= fs->super->s_blocks_count))
- return 0;
- ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
- ext2fs_block_alloc_stats(fs, *block_nr, -1);
- return 0;
-}
-
-/*
- * This fuction deallocates an inode
- */
-static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
-{
- ext2_filsys fs = ctx->fs;
- struct ext2_inode inode;
- struct problem_context pctx;
- __u32 count;
-
- ext2fs_icount_store(ctx->inode_link_info, ino, 0);
- e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
- inode.i_links_count = 0;
- inode.i_dtime = time(NULL);
- e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
- clear_problem_context(&pctx);
- pctx.ino = ino;
-
- /*
- * Fix up the bitmaps...
- */
- e2fsck_read_bitmaps(ctx);
- ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
- ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
- if (ctx->inode_bad_map)
- ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
- ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
-
- if (inode.i_file_acl &&
- (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
- pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
- block_buf, -1, &count);
- if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
- pctx.errcode = 0;
- count = 1;
- }
- if (pctx.errcode) {
- pctx.blk = inode.i_file_acl;
- fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- if (count == 0) {
- ext2fs_unmark_block_bitmap(ctx->block_found_map,
- inode.i_file_acl);
- ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
- }
- inode.i_file_acl = 0;
- }
-
- if (!ext2fs_inode_has_valid_blocks(&inode))
- return;
-
- if (LINUX_S_ISREG(inode.i_mode) &&
- (inode.i_size_high || inode.i_size & 0x80000000UL))
- ctx->large_files--;
-
- pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
- deallocate_inode_block, ctx);
- if (pctx.errcode) {
- fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-}
-
-/*
- * This fuction clears the htree flag on an inode
- */
-static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
-{
- struct ext2_inode inode;
-
- e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
- inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
- e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
- if (ctx->dirs_to_hash)
- ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
-}
-
-
-static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
- ext2_ino_t ino, char *buf)
-{
- ext2_filsys fs = ctx->fs;
- struct ext2_inode inode;
- int inode_modified = 0;
- int not_fixed = 0;
- unsigned char *frag, *fsize;
- struct problem_context pctx;
- int problem = 0;
-
- e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
-
- clear_problem_context(&pctx);
- pctx.ino = ino;
- pctx.dir = dir;
- pctx.inode = &inode;
-
- if (inode.i_file_acl &&
- !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
- fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
- inode.i_file_acl = 0;
-#if BB_BIG_ENDIAN
- /*
- * This is a special kludge to deal with long symlinks
- * on big endian systems. i_blocks had already been
- * decremented earlier in pass 1, but since i_file_acl
- * hadn't yet been cleared, ext2fs_read_inode()
- * assumed that the file was short symlink and would
- * not have byte swapped i_block[0]. Hence, we have
- * to byte-swap it here.
- */
- if (LINUX_S_ISLNK(inode.i_mode) &&
- (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
- (inode.i_blocks == fs->blocksize >> 9))
- inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
-#endif
- inode_modified++;
- } else
- not_fixed++;
-
- if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
- !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
- !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
- !(LINUX_S_ISSOCK(inode.i_mode)))
- problem = PR_2_BAD_MODE;
- else if (LINUX_S_ISCHR(inode.i_mode)
- && !e2fsck_pass1_check_device_inode(fs, &inode))
- problem = PR_2_BAD_CHAR_DEV;
- else if (LINUX_S_ISBLK(inode.i_mode)
- && !e2fsck_pass1_check_device_inode(fs, &inode))
- problem = PR_2_BAD_BLOCK_DEV;
- else if (LINUX_S_ISFIFO(inode.i_mode)
- && !e2fsck_pass1_check_device_inode(fs, &inode))
- problem = PR_2_BAD_FIFO;
- else if (LINUX_S_ISSOCK(inode.i_mode)
- && !e2fsck_pass1_check_device_inode(fs, &inode))
- problem = PR_2_BAD_SOCKET;
- else if (LINUX_S_ISLNK(inode.i_mode)
- && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
- problem = PR_2_INVALID_SYMLINK;
- }
-
- if (problem) {
- if (fix_problem(ctx, problem, &pctx)) {
- deallocate_inode(ctx, ino, 0);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return 0;
- return 1;
- } else
- not_fixed++;
- problem = 0;
- }
-
- if (inode.i_faddr) {
- if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
- inode.i_faddr = 0;
- inode_modified++;
- } else
- not_fixed++;
- }
-
- switch (fs->super->s_creator_os) {
- case EXT2_OS_LINUX:
- frag = &inode.osd2.linux2.l_i_frag;
- fsize = &inode.osd2.linux2.l_i_fsize;
- break;
- case EXT2_OS_HURD:
- frag = &inode.osd2.hurd2.h_i_frag;
- fsize = &inode.osd2.hurd2.h_i_fsize;
- break;
- case EXT2_OS_MASIX:
- frag = &inode.osd2.masix2.m_i_frag;
- fsize = &inode.osd2.masix2.m_i_fsize;
- break;
- default:
- frag = fsize = 0;
- }
- if (frag && *frag) {
- pctx.num = *frag;
- if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
- *frag = 0;
- inode_modified++;
- } else
- not_fixed++;
- pctx.num = 0;
- }
- if (fsize && *fsize) {
- pctx.num = *fsize;
- if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
- *fsize = 0;
- inode_modified++;
- } else
- not_fixed++;
- pctx.num = 0;
- }
-
- if (inode.i_file_acl &&
- ((inode.i_file_acl < fs->super->s_first_data_block) ||
- (inode.i_file_acl >= fs->super->s_blocks_count))) {
- if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
- inode.i_file_acl = 0;
- inode_modified++;
- } else
- not_fixed++;
- }
- if (inode.i_dir_acl &&
- LINUX_S_ISDIR(inode.i_mode)) {
- if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
- inode.i_dir_acl = 0;
- inode_modified++;
- } else
- not_fixed++;
- }
-
- if (inode_modified)
- e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
- if (!not_fixed)
- ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
- return 0;
-}
-
-
-/*
- * allocate_dir_block --- this function allocates a new directory
- * block for a particular inode; this is done if a directory has
- * a "hole" in it, or if a directory has a illegal block number
- * that was zeroed out and now needs to be replaced.
- */
-static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
- struct problem_context *pctx)
-{
- ext2_filsys fs = ctx->fs;
- blk_t blk;
- char *block;
- struct ext2_inode inode;
-
- if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
- return 1;
-
- /*
- * Read the inode and block bitmaps in; we'll be messing with
- * them.
- */
- e2fsck_read_bitmaps(ctx);
-
- /*
- * First, find a free block
- */
- pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
- if (pctx->errcode) {
- pctx->str = "ext2fs_new_block";
- fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
- return 1;
- }
- ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
- ext2fs_mark_block_bitmap(fs->block_map, blk);
- ext2fs_mark_bb_dirty(fs);
-
- /*
- * Now let's create the actual data block for the inode
- */
- if (db->blockcnt)
- pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
- else
- pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
- EXT2_ROOT_INO, &block);
-
- if (pctx->errcode) {
- pctx->str = "ext2fs_new_dir_block";
- fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
- return 1;
- }
-
- pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
- ext2fs_free_mem(&block);
- if (pctx->errcode) {
- pctx->str = "ext2fs_write_dir_block";
- fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
- return 1;
- }
-
- /*
- * Update the inode block count
- */
- e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
- inode.i_blocks += fs->blocksize / 512;
- if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
- inode.i_size = (db->blockcnt+1) * fs->blocksize;
- e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
-
- /*
- * Finally, update the block pointers for the inode
- */
- db->blk = blk;
- pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
- 0, update_dir_block, db);
- if (pctx->errcode) {
- pctx->str = "ext2fs_block_iterate";
- fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
- return 1;
- }
-
- return 0;
-}
-
-/*
- * This is a helper function for allocate_dir_block().
- */
-static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
- blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block FSCK_ATTR((unused)),
- int ref_offset FSCK_ATTR((unused)),
- void *priv_data)
-{
- struct ext2_db_entry *db;
-
- db = (struct ext2_db_entry *) priv_data;
- if (db->blockcnt == (int) blockcnt) {
- *block_nr = db->blk;
- return BLOCK_CHANGED;
- }
- return 0;
-}
-
-/*
- * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
- *
- * Pass #3 assures that all directories are connected to the
- * filesystem tree, using the following algorithm:
- *
- * First, the root directory is checked to make sure it exists; if
- * not, e2fsck will offer to create a new one. It is then marked as
- * "done".
- *
- * Then, pass3 interates over all directory inodes; for each directory
- * it attempts to trace up the filesystem tree, using dirinfo.parent
- * until it reaches a directory which has been marked "done". If it
- * cannot do so, then the directory must be disconnected, and e2fsck
- * will offer to reconnect it to /lost+found. While it is chasing
- * parent pointers up the filesystem tree, if pass3 sees a directory
- * twice, then it has detected a filesystem loop, and it will again
- * offer to reconnect the directory to /lost+found in to break the
- * filesystem loop.
- *
- * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
- * reconnect inodes to /lost+found; this subroutine is also used by
- * pass 4. e2fsck_reconnect_file() calls get_lost_and_found(), which
- * is responsible for creating /lost+found if it does not exist.
- *
- * Pass 3 frees the following data structures:
- * - The dirinfo directory information cache.
- */
-
-static void check_root(e2fsck_t ctx);
-static int check_directory(e2fsck_t ctx, struct dir_info *dir,
- struct problem_context *pctx);
-static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
-
-static ext2fs_inode_bitmap inode_loop_detect;
-static ext2fs_inode_bitmap inode_done_map;
-
-static void e2fsck_pass3(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- int i;
- struct problem_context pctx;
- struct dir_info *dir;
- unsigned long maxdirs, count;
-
- clear_problem_context(&pctx);
-
- /* Pass 3 */
-
- if (!(ctx->options & E2F_OPT_PREEN))
- fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
-
- /*
- * Allocate some bitmaps to do loop detection.
- */
- pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
- &inode_done_map);
- if (pctx.errcode) {
- pctx.num = 2;
- fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- goto abort_exit;
- }
- check_root(ctx);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- goto abort_exit;
-
- ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
-
- maxdirs = e2fsck_get_num_dirinfo(ctx);
- count = 1;
-
- if (ctx->progress)
- if ((ctx->progress)(ctx, 3, 0, maxdirs))
- goto abort_exit;
-
- for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- goto abort_exit;
- if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
- goto abort_exit;
- if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
- if (check_directory(ctx, dir, &pctx))
- goto abort_exit;
- }
-
- /*
- * Force the creation of /lost+found if not present
- */
- if ((ctx->flags & E2F_OPT_READONLY) == 0)
- e2fsck_get_lost_and_found(ctx, 1);
-
- /*
- * If there are any directories that need to be indexed or
- * optimized, do it here.
- */
- e2fsck_rehash_directories(ctx);
-
-abort_exit:
- e2fsck_free_dir_info(ctx);
- ext2fs_free_inode_bitmap(inode_loop_detect);
- inode_loop_detect = 0;
- ext2fs_free_inode_bitmap(inode_done_map);
- inode_done_map = 0;
-}
-
-/*
- * This makes sure the root inode is present; if not, we ask if the
- * user wants us to create it. Not creating it is a fatal error.
- */
-static void check_root(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- blk_t blk;
- struct ext2_inode inode;
- char * block;
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
-
- if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
- /*
- * If the root inode is not a directory, die here. The
- * user must have answered 'no' in pass1 when we
- * offered to clear it.
- */
- if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
- EXT2_ROOT_INO))) {
- fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- }
- return;
- }
-
- if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
- fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-
- e2fsck_read_bitmaps(ctx);
-
- /*
- * First, find a free block
- */
- pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
- if (pctx.errcode) {
- pctx.str = "ext2fs_new_block";
- fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
- ext2fs_mark_block_bitmap(fs->block_map, blk);
- ext2fs_mark_bb_dirty(fs);
-
- /*
- * Now let's create the actual data block for the inode
- */
- pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
- &block);
- if (pctx.errcode) {
- pctx.str = "ext2fs_new_dir_block";
- fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-
- pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
- if (pctx.errcode) {
- pctx.str = "ext2fs_write_dir_block";
- fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- ext2fs_free_mem(&block);
-
- /*
- * Set up the inode structure
- */
- memset(&inode, 0, sizeof(inode));
- inode.i_mode = 040755;
- inode.i_size = fs->blocksize;
- inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
- inode.i_links_count = 2;
- inode.i_blocks = fs->blocksize / 512;
- inode.i_block[0] = blk;
-
- /*
- * Write out the inode.
- */
- pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
- if (pctx.errcode) {
- pctx.str = "ext2fs_write_inode";
- fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-
- /*
- * Miscellaneous bookkeeping...
- */
- e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
- ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
- ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
-
- ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
- ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
- ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
- ext2fs_mark_ib_dirty(fs);
-}
-
-/*
- * This subroutine is responsible for making sure that a particular
- * directory is connected to the root; if it isn't we trace it up as
- * far as we can go, and then offer to connect the resulting parent to
- * the lost+found. We have to do loop detection; if we ever discover
- * a loop, we treat that as a disconnected directory and offer to
- * reparent it to lost+found.
- *
- * However, loop detection is expensive, because for very large
- * filesystems, the inode_loop_detect bitmap is huge, and clearing it
- * is non-trivial. Loops in filesystems are also a rare error case,
- * and we shouldn't optimize for error cases. So we try two passes of
- * the algorithm. The first time, we ignore loop detection and merely
- * increment a counter; if the counter exceeds some extreme threshold,
- * then we try again with the loop detection bitmap enabled.
- */
-static int check_directory(e2fsck_t ctx, struct dir_info *dir,
- struct problem_context *pctx)
-{
- ext2_filsys fs = ctx->fs;
- struct dir_info *p = dir;
- int loop_pass = 0, parent_count = 0;
-
- if (!p)
- return 0;
-
- while (1) {
- /*
- * Mark this inode as being "done"; by the time we
- * return from this function, the inode we either be
- * verified as being connected to the directory tree,
- * or we will have offered to reconnect this to
- * lost+found.
- *
- * If it was marked done already, then we've reached a
- * parent we've already checked.
- */
- if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
- break;
-
- /*
- * If this directory doesn't have a parent, or we've
- * seen the parent once already, then offer to
- * reparent it to lost+found
- */
- if (!p->parent ||
- (loop_pass &&
- (ext2fs_test_inode_bitmap(inode_loop_detect,
- p->parent)))) {
- pctx->ino = p->ino;
- if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
- if (e2fsck_reconnect_file(ctx, pctx->ino))
- ext2fs_unmark_valid(fs);
- else {
- p = e2fsck_get_dir_info(ctx, pctx->ino);
- p->parent = ctx->lost_and_found;
- fix_dotdot(ctx, p, ctx->lost_and_found);
- }
- }
- break;
- }
- p = e2fsck_get_dir_info(ctx, p->parent);
- if (!p) {
- fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
- return 0;
- }
- if (loop_pass) {
- ext2fs_mark_inode_bitmap(inode_loop_detect,
- p->ino);
- } else if (parent_count++ > 2048) {
- /*
- * If we've run into a path depth that's
- * greater than 2048, try again with the inode
- * loop bitmap turned on and start from the
- * top.
- */
- loop_pass = 1;
- if (inode_loop_detect)
- ext2fs_clear_inode_bitmap(inode_loop_detect);
- else {
- pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
- if (pctx->errcode) {
- pctx->num = 1;
- fix_problem(ctx,
- PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return -1;
- }
- }
- p = dir;
- }
- }
-
- /*
- * Make sure that .. and the parent directory are the same;
- * offer to fix it if not.
- */
- if (dir->parent != dir->dotdot) {
- pctx->ino = dir->ino;
- pctx->ino2 = dir->dotdot;
- pctx->dir = dir->parent;
- if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
- fix_dotdot(ctx, dir, dir->parent);
- }
- return 0;
-}
-
-/*
- * This routine gets the lost_and_found inode, making it a directory
- * if necessary
- */
-ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
-{
- ext2_filsys fs = ctx->fs;
- ext2_ino_t ino;
- blk_t blk;
- errcode_t retval;
- struct ext2_inode inode;
- char * block;
- static const char name[] = "lost+found";
- struct problem_context pctx;
- struct dir_info *dirinfo;
-
- if (ctx->lost_and_found)
- return ctx->lost_and_found;
-
- clear_problem_context(&pctx);
-
- retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
- sizeof(name)-1, 0, &ino);
- if (retval && !fix)
- return 0;
- if (!retval) {
- if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
- ctx->lost_and_found = ino;
- return ino;
- }
-
- /* Lost+found isn't a directory! */
- if (!fix)
- return 0;
- pctx.ino = ino;
- if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
- return 0;
-
- /* OK, unlink the old /lost+found file. */
- pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
- if (pctx.errcode) {
- pctx.str = "ext2fs_unlink";
- fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
- return 0;
- }
- dirinfo = e2fsck_get_dir_info(ctx, ino);
- if (dirinfo)
- dirinfo->parent = 0;
- e2fsck_adjust_inode_count(ctx, ino, -1);
- } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
- pctx.errcode = retval;
- fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
- }
- if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
- return 0;
-
- /*
- * Read the inode and block bitmaps in; we'll be messing with
- * them.
- */
- e2fsck_read_bitmaps(ctx);
-
- /*
- * First, find a free block
- */
- retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
- if (retval) {
- pctx.errcode = retval;
- fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
- return 0;
- }
- ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
- ext2fs_block_alloc_stats(fs, blk, +1);
-
- /*
- * Next find a free inode.
- */
- retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
- ctx->inode_used_map, &ino);
- if (retval) {
- pctx.errcode = retval;
- fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
- return 0;
- }
- ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
- ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
- ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
-
- /*
- * Now let's create the actual data block for the inode
- */
- retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
- if (retval) {
- pctx.errcode = retval;
- fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
- return 0;
- }
-
- retval = ext2fs_write_dir_block(fs, blk, block);
- ext2fs_free_mem(&block);
- if (retval) {
- pctx.errcode = retval;
- fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
- return 0;
- }
-
- /*
- * Set up the inode structure
- */
- memset(&inode, 0, sizeof(inode));
- inode.i_mode = 040700;
- inode.i_size = fs->blocksize;
- inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
- inode.i_links_count = 2;
- inode.i_blocks = fs->blocksize / 512;
- inode.i_block[0] = blk;
-
- /*
- * Next, write out the inode.
- */
- pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
- if (pctx.errcode) {
- pctx.str = "ext2fs_write_inode";
- fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
- return 0;
- }
- /*
- * Finally, create the directory link
- */
- pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
- if (pctx.errcode) {
- pctx.str = "ext2fs_link";
- fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
- return 0;
- }
-
- /*
- * Miscellaneous bookkeeping that needs to be kept straight.
- */
- e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
- e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
- ext2fs_icount_store(ctx->inode_count, ino, 2);
- ext2fs_icount_store(ctx->inode_link_info, ino, 2);
- ctx->lost_and_found = ino;
- return ino;
-}
-
-/*
- * This routine will connect a file to lost+found
- */
-int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
-{
- ext2_filsys fs = ctx->fs;
- errcode_t retval;
- char name[80];
- struct problem_context pctx;
- struct ext2_inode inode;
- int file_type = 0;
-
- clear_problem_context(&pctx);
- pctx.ino = ino;
-
- if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
- if (e2fsck_get_lost_and_found(ctx, 1) == 0)
- ctx->bad_lost_and_found++;
- }
- if (ctx->bad_lost_and_found) {
- fix_problem(ctx, PR_3_NO_LPF, &pctx);
- return 1;
- }
-
- sprintf(name, "#%u", ino);
- if (ext2fs_read_inode(fs, ino, &inode) == 0)
- file_type = ext2_file_type(inode.i_mode);
- retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
- if (retval == EXT2_ET_DIR_NO_SPACE) {
- if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
- return 1;
- retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
- 1, 0);
- if (retval) {
- pctx.errcode = retval;
- fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
- return 1;
- }
- retval = ext2fs_link(fs, ctx->lost_and_found, name,
- ino, file_type);
- }
- if (retval) {
- pctx.errcode = retval;
- fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
- return 1;
- }
- e2fsck_adjust_inode_count(ctx, ino, 1);
-
- return 0;
-}
-
-/*
- * Utility routine to adjust the inode counts on an inode.
- */
-errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
-{
- ext2_filsys fs = ctx->fs;
- errcode_t retval;
- struct ext2_inode inode;
-
- if (!ino)
- return 0;
-
- retval = ext2fs_read_inode(fs, ino, &inode);
- if (retval)
- return retval;
-
- if (adj == 1) {
- ext2fs_icount_increment(ctx->inode_count, ino, 0);
- if (inode.i_links_count == (__u16) ~0)
- return 0;
- ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
- inode.i_links_count++;
- } else if (adj == -1) {
- ext2fs_icount_decrement(ctx->inode_count, ino, 0);
- if (inode.i_links_count == 0)
- return 0;
- ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
- inode.i_links_count--;
- }
-
- retval = ext2fs_write_inode(fs, ino, &inode);
- if (retval)
- return retval;
-
- return 0;
-}
-
-/*
- * Fix parent --- this routine fixes up the parent of a directory.
- */
-struct fix_dotdot_struct {
- ext2_filsys fs;
- ext2_ino_t parent;
- int done;
- e2fsck_t ctx;
-};
-
-static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
- int offset FSCK_ATTR((unused)),
- int blocksize FSCK_ATTR((unused)),
- char *buf FSCK_ATTR((unused)),
- void *priv_data)
-{
- struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
- errcode_t retval;
- struct problem_context pctx;
-
- if ((dirent->name_len & 0xFF) != 2)
- return 0;
- if (strncmp(dirent->name, "..", 2))
- return 0;
-
- clear_problem_context(&pctx);
-
- retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
- if (retval) {
- pctx.errcode = retval;
- fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
- }
- retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
- if (retval) {
- pctx.errcode = retval;
- fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
- }
- dirent->inode = fp->parent;
-
- fp->done++;
- return DIRENT_ABORT | DIRENT_CHANGED;
-}
-
-static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
-{
- ext2_filsys fs = ctx->fs;
- errcode_t retval;
- struct fix_dotdot_struct fp;
- struct problem_context pctx;
-
- fp.fs = fs;
- fp.parent = parent;
- fp.done = 0;
- fp.ctx = ctx;
-
- retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
- 0, fix_dotdot_proc, &fp);
- if (retval || !fp.done) {
- clear_problem_context(&pctx);
- pctx.ino = dir->ino;
- pctx.errcode = retval;
- fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
- PR_3_FIX_PARENT_NOFIND, &pctx);
- ext2fs_unmark_valid(fs);
- }
- dir->dotdot = parent;
-}
-
-/*
- * These routines are responsible for expanding a /lost+found if it is
- * too small.
- */
-
-struct expand_dir_struct {
- int num;
- int guaranteed_size;
- int newblocks;
- int last_block;
- errcode_t err;
- e2fsck_t ctx;
-};
-
-static int expand_dir_proc(ext2_filsys fs,
- blk_t *blocknr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block FSCK_ATTR((unused)),
- int ref_offset FSCK_ATTR((unused)),
- void *priv_data)
-{
- struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
- blk_t new_blk;
- static blk_t last_blk = 0;
- char *block;
- errcode_t retval;
- e2fsck_t ctx;
-
- ctx = es->ctx;
-
- if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
- return BLOCK_ABORT;
-
- if (blockcnt > 0)
- es->last_block = blockcnt;
- if (*blocknr) {
- last_blk = *blocknr;
- return 0;
- }
- retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
- &new_blk);
- if (retval) {
- es->err = retval;
- return BLOCK_ABORT;
- }
- if (blockcnt > 0) {
- retval = ext2fs_new_dir_block(fs, 0, 0, &block);
- if (retval) {
- es->err = retval;
- return BLOCK_ABORT;
- }
- es->num--;
- retval = ext2fs_write_dir_block(fs, new_blk, block);
- } else {
- retval = ext2fs_get_mem(fs->blocksize, &block);
- if (retval) {
- es->err = retval;
- return BLOCK_ABORT;
- }
- memset(block, 0, fs->blocksize);
- retval = io_channel_write_blk(fs->io, new_blk, 1, block);
- }
- if (retval) {
- es->err = retval;
- return BLOCK_ABORT;
- }
- ext2fs_free_mem(&block);
- *blocknr = new_blk;
- ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
- ext2fs_block_alloc_stats(fs, new_blk, +1);
- es->newblocks++;
-
- if (es->num == 0)
- return (BLOCK_CHANGED | BLOCK_ABORT);
- else
- return BLOCK_CHANGED;
-}
-
-errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
- int num, int guaranteed_size)
-{
- ext2_filsys fs = ctx->fs;
- errcode_t retval;
- struct expand_dir_struct es;
- struct ext2_inode inode;
-
- if (!(fs->flags & EXT2_FLAG_RW))
- return EXT2_ET_RO_FILSYS;
-
- /*
- * Read the inode and block bitmaps in; we'll be messing with
- * them.
- */
- e2fsck_read_bitmaps(ctx);
-
- retval = ext2fs_check_directory(fs, dir);
- if (retval)
- return retval;
-
- es.num = num;
- es.guaranteed_size = guaranteed_size;
- es.last_block = 0;
- es.err = 0;
- es.newblocks = 0;
- es.ctx = ctx;
-
- retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
- 0, expand_dir_proc, &es);
-
- if (es.err)
- return es.err;
-
- /*
- * Update the size and block count fields in the inode.
- */
- retval = ext2fs_read_inode(fs, dir, &inode);
- if (retval)
- return retval;
-
- inode.i_size = (es.last_block + 1) * fs->blocksize;
- inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
-
- e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
-
- return 0;
-}
-
-/*
- * pass4.c -- pass #4 of e2fsck: Check reference counts
- *
- * Pass 4 frees the following data structures:
- * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
- */
-
-/*
- * This routine is called when an inode is not connected to the
- * directory tree.
- *
- * This subroutine returns 1 then the caller shouldn't bother with the
- * rest of the pass 4 tests.
- */
-static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
-{
- ext2_filsys fs = ctx->fs;
- struct ext2_inode inode;
- struct problem_context pctx;
-
- e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
- clear_problem_context(&pctx);
- pctx.ino = i;
- pctx.inode = &inode;
-
- /*
- * Offer to delete any zero-length files that does not have
- * blocks. If there is an EA block, it might have useful
- * information, so we won't prompt to delete it, but let it be
- * reconnected to lost+found.
- */
- if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
- LINUX_S_ISDIR(inode.i_mode))) {
- if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
- ext2fs_icount_store(ctx->inode_link_info, i, 0);
- inode.i_links_count = 0;
- inode.i_dtime = time(NULL);
- e2fsck_write_inode(ctx, i, &inode,
- "disconnect_inode");
- /*
- * Fix up the bitmaps...
- */
- e2fsck_read_bitmaps(ctx);
- ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
- ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
- ext2fs_inode_alloc_stats2(fs, i, -1,
- LINUX_S_ISDIR(inode.i_mode));
- return 0;
- }
- }
-
- /*
- * Prompt to reconnect.
- */
- if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
- if (e2fsck_reconnect_file(ctx, i))
- ext2fs_unmark_valid(fs);
- } else {
- /*
- * If we don't attach the inode, then skip the
- * i_links_test since there's no point in trying to
- * force i_links_count to zero.
- */
- ext2fs_unmark_valid(fs);
- return 1;
- }
- return 0;
-}
-
-
-static void e2fsck_pass4(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- ext2_ino_t i;
- struct ext2_inode inode;
- struct problem_context pctx;
- __u16 link_count, link_counted;
- char *buf = NULL;
- int group, maxgroup;
-
- /* Pass 4 */
-
- clear_problem_context(&pctx);
-
- if (!(ctx->options & E2F_OPT_PREEN))
- fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
-
- group = 0;
- maxgroup = fs->group_desc_count;
- if (ctx->progress)
- if ((ctx->progress)(ctx, 4, 0, maxgroup))
- return;
-
- for (i=1; i <= fs->super->s_inodes_count; i++) {
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
- if ((i % fs->super->s_inodes_per_group) == 0) {
- group++;
- if (ctx->progress)
- if ((ctx->progress)(ctx, 4, group, maxgroup))
- return;
- }
- if (i == EXT2_BAD_INO ||
- (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
- continue;
- if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
- (ctx->inode_imagic_map &&
- ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)))
- continue;
- ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
- ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
- if (link_counted == 0) {
- if (!buf)
- buf = e2fsck_allocate_memory(ctx,
- fs->blocksize, "bad_inode buffer");
- if (e2fsck_process_bad_inode(ctx, 0, i, buf))
- continue;
- if (disconnect_inode(ctx, i))
- continue;
- ext2fs_icount_fetch(ctx->inode_link_info, i,
- &link_count);
- ext2fs_icount_fetch(ctx->inode_count, i,
- &link_counted);
- }
- if (link_counted != link_count) {
- e2fsck_read_inode(ctx, i, &inode, "pass4");
- pctx.ino = i;
- pctx.inode = &inode;
- if (link_count != inode.i_links_count) {
- pctx.num = link_count;
- fix_problem(ctx,
- PR_4_INCONSISTENT_COUNT, &pctx);
- }
- pctx.num = link_counted;
- if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
- inode.i_links_count = link_counted;
- e2fsck_write_inode(ctx, i, &inode, "pass4");
- }
- }
- }
- ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
- ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
- ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
- ctx->inode_imagic_map = 0;
- ext2fs_free_mem(&buf);
-}
-
-/*
- * pass5.c --- check block and inode bitmaps against on-disk bitmaps
- */
-
-#define NO_BLK ((blk_t) -1)
-
-static void print_bitmap_problem(e2fsck_t ctx, int problem,
- struct problem_context *pctx)
-{
- switch (problem) {
- case PR_5_BLOCK_UNUSED:
- if (pctx->blk == pctx->blk2)
- pctx->blk2 = 0;
- else
- problem = PR_5_BLOCK_RANGE_UNUSED;
- break;
- case PR_5_BLOCK_USED:
- if (pctx->blk == pctx->blk2)
- pctx->blk2 = 0;
- else
- problem = PR_5_BLOCK_RANGE_USED;
- break;
- case PR_5_INODE_UNUSED:
- if (pctx->ino == pctx->ino2)
- pctx->ino2 = 0;
- else
- problem = PR_5_INODE_RANGE_UNUSED;
- break;
- case PR_5_INODE_USED:
- if (pctx->ino == pctx->ino2)
- pctx->ino2 = 0;
- else
- problem = PR_5_INODE_RANGE_USED;
- break;
- }
- fix_problem(ctx, problem, pctx);
- pctx->blk = pctx->blk2 = NO_BLK;
- pctx->ino = pctx->ino2 = 0;
-}
-
-static void check_block_bitmaps(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- blk_t i;
- int *free_array;
- int group = 0;
- unsigned int blocks = 0;
- unsigned int free_blocks = 0;
- int group_free = 0;
- int actual, bitmap;
- struct problem_context pctx;
- int problem, save_problem, fixit, had_problem;
- errcode_t retval;
-
- clear_problem_context(&pctx);
- free_array = (int *) e2fsck_allocate_memory(ctx,
- fs->group_desc_count * sizeof(int), "free block count array");
-
- if ((fs->super->s_first_data_block <
- ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
- (fs->super->s_blocks_count-1 >
- ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
- pctx.num = 1;
- pctx.blk = fs->super->s_first_data_block;
- pctx.blk2 = fs->super->s_blocks_count -1;
- pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
- pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
- fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
-
- ctx->flags |= E2F_FLAG_ABORT; /* fatal */
- return;
- }
-
- if ((fs->super->s_first_data_block <
- ext2fs_get_block_bitmap_start(fs->block_map)) ||
- (fs->super->s_blocks_count-1 >
- ext2fs_get_block_bitmap_end(fs->block_map))) {
- pctx.num = 2;
- pctx.blk = fs->super->s_first_data_block;
- pctx.blk2 = fs->super->s_blocks_count -1;
- pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
- pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
- fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
-
- ctx->flags |= E2F_FLAG_ABORT; /* fatal */
- return;
- }
-
-redo_counts:
- had_problem = 0;
- save_problem = 0;
- pctx.blk = pctx.blk2 = NO_BLK;
- for (i = fs->super->s_first_data_block;
- i < fs->super->s_blocks_count;
- i++) {
- actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
- bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
-
- if (actual == bitmap)
- goto do_counts;
-
- if (!actual && bitmap) {
- /*
- * Block not used, but marked in use in the bitmap.
- */
- problem = PR_5_BLOCK_UNUSED;
- } else {
- /*
- * Block used, but not marked in use in the bitmap.
- */
- problem = PR_5_BLOCK_USED;
- }
- if (pctx.blk == NO_BLK) {
- pctx.blk = pctx.blk2 = i;
- save_problem = problem;
- } else {
- if ((problem == save_problem) &&
- (pctx.blk2 == i-1))
- pctx.blk2++;
- else {
- print_bitmap_problem(ctx, save_problem, &pctx);
- pctx.blk = pctx.blk2 = i;
- save_problem = problem;
- }
- }
- ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
- had_problem++;
-
- do_counts:
- if (!bitmap) {
- group_free++;
- free_blocks++;
- }
- blocks ++;
- if ((blocks == fs->super->s_blocks_per_group) ||
- (i == fs->super->s_blocks_count-1)) {
- free_array[group] = group_free;
- group ++;
- blocks = 0;
- group_free = 0;
- if (ctx->progress)
- if ((ctx->progress)(ctx, 5, group,
- fs->group_desc_count*2))
- return;
- }
- }
- if (pctx.blk != NO_BLK)
- print_bitmap_problem(ctx, save_problem, &pctx);
- if (had_problem)
- fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
- else
- fixit = -1;
- ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
-
- if (fixit == 1) {
- ext2fs_free_block_bitmap(fs->block_map);
- retval = ext2fs_copy_bitmap(ctx->block_found_map,
- &fs->block_map);
- if (retval) {
- clear_problem_context(&pctx);
- fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- ext2fs_set_bitmap_padding(fs->block_map);
- ext2fs_mark_bb_dirty(fs);
-
- /* Redo the counts */
- blocks = 0; free_blocks = 0; group_free = 0; group = 0;
- memset(free_array, 0, fs->group_desc_count * sizeof(int));
- goto redo_counts;
- } else if (fixit == 0)
- ext2fs_unmark_valid(fs);
-
- for (i = 0; i < fs->group_desc_count; i++) {
- if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
- pctx.group = i;
- pctx.blk = fs->group_desc[i].bg_free_blocks_count;
- pctx.blk2 = free_array[i];
-
- if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
- &pctx)) {
- fs->group_desc[i].bg_free_blocks_count =
- free_array[i];
- ext2fs_mark_super_dirty(fs);
- } else
- ext2fs_unmark_valid(fs);
- }
- }
- if (free_blocks != fs->super->s_free_blocks_count) {
- pctx.group = 0;
- pctx.blk = fs->super->s_free_blocks_count;
- pctx.blk2 = free_blocks;
-
- if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
- fs->super->s_free_blocks_count = free_blocks;
- ext2fs_mark_super_dirty(fs);
- } else
- ext2fs_unmark_valid(fs);
- }
- ext2fs_free_mem(&free_array);
-}
-
-static void check_inode_bitmaps(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- ext2_ino_t i;
- unsigned int free_inodes = 0;
- int group_free = 0;
- int dirs_count = 0;
- int group = 0;
- unsigned int inodes = 0;
- int *free_array;
- int *dir_array;
- int actual, bitmap;
- errcode_t retval;
- struct problem_context pctx;
- int problem, save_problem, fixit, had_problem;
-
- clear_problem_context(&pctx);
- free_array = (int *) e2fsck_allocate_memory(ctx,
- fs->group_desc_count * sizeof(int), "free inode count array");
-
- dir_array = (int *) e2fsck_allocate_memory(ctx,
- fs->group_desc_count * sizeof(int), "directory count array");
-
- if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
- (fs->super->s_inodes_count >
- ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
- pctx.num = 3;
- pctx.blk = 1;
- pctx.blk2 = fs->super->s_inodes_count;
- pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
- pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
- fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
-
- ctx->flags |= E2F_FLAG_ABORT; /* fatal */
- return;
- }
- if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
- (fs->super->s_inodes_count >
- ext2fs_get_inode_bitmap_end(fs->inode_map))) {
- pctx.num = 4;
- pctx.blk = 1;
- pctx.blk2 = fs->super->s_inodes_count;
- pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
- pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
- fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
-
- ctx->flags |= E2F_FLAG_ABORT; /* fatal */
- return;
- }
-
-redo_counts:
- had_problem = 0;
- save_problem = 0;
- pctx.ino = pctx.ino2 = 0;
- for (i = 1; i <= fs->super->s_inodes_count; i++) {
- actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
- bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
-
- if (actual == bitmap)
- goto do_counts;
-
- if (!actual && bitmap) {
- /*
- * Inode wasn't used, but marked in bitmap
- */
- problem = PR_5_INODE_UNUSED;
- } else /* if (actual && !bitmap) */ {
- /*
- * Inode used, but not in bitmap
- */
- problem = PR_5_INODE_USED;
- }
- if (pctx.ino == 0) {
- pctx.ino = pctx.ino2 = i;
- save_problem = problem;
- } else {
- if ((problem == save_problem) &&
- (pctx.ino2 == i-1))
- pctx.ino2++;
- else {
- print_bitmap_problem(ctx, save_problem, &pctx);
- pctx.ino = pctx.ino2 = i;
- save_problem = problem;
- }
- }
- ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
- had_problem++;
-
-do_counts:
- if (!bitmap) {
- group_free++;
- free_inodes++;
- } else {
- if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
- dirs_count++;
- }
- inodes++;
- if ((inodes == fs->super->s_inodes_per_group) ||
- (i == fs->super->s_inodes_count)) {
- free_array[group] = group_free;
- dir_array[group] = dirs_count;
- group ++;
- inodes = 0;
- group_free = 0;
- dirs_count = 0;
- if (ctx->progress)
- if ((ctx->progress)(ctx, 5,
- group + fs->group_desc_count,
- fs->group_desc_count*2))
- return;
- }
- }
- if (pctx.ino)
- print_bitmap_problem(ctx, save_problem, &pctx);
-
- if (had_problem)
- fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
- else
- fixit = -1;
- ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
-
- if (fixit == 1) {
- ext2fs_free_inode_bitmap(fs->inode_map);
- retval = ext2fs_copy_bitmap(ctx->inode_used_map,
- &fs->inode_map);
- if (retval) {
- clear_problem_context(&pctx);
- fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- ext2fs_set_bitmap_padding(fs->inode_map);
- ext2fs_mark_ib_dirty(fs);
-
- /* redo counts */
- inodes = 0; free_inodes = 0; group_free = 0;
- dirs_count = 0; group = 0;
- memset(free_array, 0, fs->group_desc_count * sizeof(int));
- memset(dir_array, 0, fs->group_desc_count * sizeof(int));
- goto redo_counts;
- } else if (fixit == 0)
- ext2fs_unmark_valid(fs);
-
- for (i = 0; i < fs->group_desc_count; i++) {
- if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
- pctx.group = i;
- pctx.ino = fs->group_desc[i].bg_free_inodes_count;
- pctx.ino2 = free_array[i];
- if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
- &pctx)) {
- fs->group_desc[i].bg_free_inodes_count =
- free_array[i];
- ext2fs_mark_super_dirty(fs);
- } else
- ext2fs_unmark_valid(fs);
- }
- if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
- pctx.group = i;
- pctx.ino = fs->group_desc[i].bg_used_dirs_count;
- pctx.ino2 = dir_array[i];
-
- if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
- &pctx)) {
- fs->group_desc[i].bg_used_dirs_count =
- dir_array[i];
- ext2fs_mark_super_dirty(fs);
- } else
- ext2fs_unmark_valid(fs);
- }
- }
- if (free_inodes != fs->super->s_free_inodes_count) {
- pctx.group = -1;
- pctx.ino = fs->super->s_free_inodes_count;
- pctx.ino2 = free_inodes;
-
- if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
- fs->super->s_free_inodes_count = free_inodes;
- ext2fs_mark_super_dirty(fs);
- } else
- ext2fs_unmark_valid(fs);
- }
- ext2fs_free_mem(&free_array);
- ext2fs_free_mem(&dir_array);
-}
-
-static void check_inode_end(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- ext2_ino_t end, save_inodes_count, i;
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
-
- end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
- pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
- &save_inodes_count);
- if (pctx.errcode) {
- pctx.num = 1;
- fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT; /* fatal */
- return;
- }
- if (save_inodes_count == end)
- return;
-
- for (i = save_inodes_count + 1; i <= end; i++) {
- if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
- if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
- for (i = save_inodes_count + 1; i <= end; i++)
- ext2fs_mark_inode_bitmap(fs->inode_map,
- i);
- ext2fs_mark_ib_dirty(fs);
- } else
- ext2fs_unmark_valid(fs);
- break;
- }
- }
-
- pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
- save_inodes_count, 0);
- if (pctx.errcode) {
- pctx.num = 2;
- fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT; /* fatal */
- return;
- }
-}
-
-static void check_block_end(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- blk_t end, save_blocks_count, i;
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
-
- end = fs->block_map->start +
- (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
- pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
- &save_blocks_count);
- if (pctx.errcode) {
- pctx.num = 3;
- fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT; /* fatal */
- return;
- }
- if (save_blocks_count == end)
- return;
-
- for (i = save_blocks_count + 1; i <= end; i++) {
- if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
- if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
- for (i = save_blocks_count + 1; i <= end; i++)
- ext2fs_mark_block_bitmap(fs->block_map,
- i);
- ext2fs_mark_bb_dirty(fs);
- } else
- ext2fs_unmark_valid(fs);
- break;
- }
- }
-
- pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
- save_blocks_count, 0);
- if (pctx.errcode) {
- pctx.num = 4;
- fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT; /* fatal */
- return;
- }
-}
-
-static void e2fsck_pass5(e2fsck_t ctx)
-{
- struct problem_context pctx;
-
- /* Pass 5 */
-
- clear_problem_context(&pctx);
-
- if (!(ctx->options & E2F_OPT_PREEN))
- fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
-
- if (ctx->progress)
- if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
- return;
-
- e2fsck_read_bitmaps(ctx);
-
- check_block_bitmaps(ctx);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
- check_inode_bitmaps(ctx);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
- check_inode_end(ctx);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
- check_block_end(ctx);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
-
- ext2fs_free_inode_bitmap(ctx->inode_used_map);
- ctx->inode_used_map = 0;
- ext2fs_free_inode_bitmap(ctx->inode_dir_map);
- ctx->inode_dir_map = 0;
- ext2fs_free_block_bitmap(ctx->block_found_map);
- ctx->block_found_map = 0;
-}
-
-/*
- * problem.c --- report filesystem problems to the user
- */
-
-#define PR_PREEN_OK 0x000001 /* Don't need to do preenhalt */
-#define PR_NO_OK 0x000002 /* If user answers no, don't make fs invalid */
-#define PR_NO_DEFAULT 0x000004 /* Default to no */
-#define PR_MSG_ONLY 0x000008 /* Print message only */
-
-/* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
-
-#define PR_FATAL 0x001000 /* Fatal error */
-#define PR_AFTER_CODE 0x002000 /* After asking the first question, */
- /* ask another */
-#define PR_PREEN_NOMSG 0x004000 /* Don't print a message if we're preening */
-#define PR_NOCOLLATE 0x008000 /* Don't collate answers for this latch */
-#define PR_NO_NOMSG 0x010000 /* Don't print a message if e2fsck -n */
-#define PR_PREEN_NO 0x020000 /* Use No as an answer if preening */
-#define PR_PREEN_NOHDR 0x040000 /* Don't print the preen header */
-
-
-#define PROMPT_NONE 0
-#define PROMPT_FIX 1
-#define PROMPT_CLEAR 2
-#define PROMPT_RELOCATE 3
-#define PROMPT_ALLOCATE 4
-#define PROMPT_EXPAND 5
-#define PROMPT_CONNECT 6
-#define PROMPT_CREATE 7
-#define PROMPT_SALVAGE 8
-#define PROMPT_TRUNCATE 9
-#define PROMPT_CLEAR_INODE 10
-#define PROMPT_ABORT 11
-#define PROMPT_SPLIT 12
-#define PROMPT_CONTINUE 13
-#define PROMPT_CLONE 14
-#define PROMPT_DELETE 15
-#define PROMPT_SUPPRESS 16
-#define PROMPT_UNLINK 17
-#define PROMPT_CLEAR_HTREE 18
-#define PROMPT_RECREATE 19
-#define PROMPT_NULL 20
-
-struct e2fsck_problem {
- problem_t e2p_code;
- const char * e2p_description;
- char prompt;
- int flags;
- problem_t second_code;
-};
-
-struct latch_descr {
- int latch_code;
- problem_t question;
- problem_t end_message;
- int flags;
-};
-
-/*
- * These are the prompts which are used to ask the user if they want
- * to fix a problem.
- */
-static const char *const prompt[] = {
- N_("(no prompt)"), /* 0 */
- N_("Fix"), /* 1 */
- N_("Clear"), /* 2 */
- N_("Relocate"), /* 3 */
- N_("Allocate"), /* 4 */
- N_("Expand"), /* 5 */
- N_("Connect to /lost+found"), /* 6 */
- N_("Create"), /* 7 */
- N_("Salvage"), /* 8 */
- N_("Truncate"), /* 9 */
- N_("Clear inode"), /* 10 */
- N_("Abort"), /* 11 */
- N_("Split"), /* 12 */
- N_("Continue"), /* 13 */
- N_("Clone multiply-claimed blocks"), /* 14 */
- N_("Delete file"), /* 15 */
- N_("Suppress messages"),/* 16 */
- N_("Unlink"), /* 17 */
- N_("Clear HTree index"),/* 18 */
- N_("Recreate"), /* 19 */
- "", /* 20 */
-};
-
-/*
- * These messages are printed when we are preen mode and we will be
- * automatically fixing the problem.
- */
-static const char *const preen_msg[] = {
- N_("(NONE)"), /* 0 */
- N_("FIXED"), /* 1 */
- N_("CLEARED"), /* 2 */
- N_("RELOCATED"), /* 3 */
- N_("ALLOCATED"), /* 4 */
- N_("EXPANDED"), /* 5 */
- N_("RECONNECTED"), /* 6 */
- N_("CREATED"), /* 7 */
- N_("SALVAGED"), /* 8 */
- N_("TRUNCATED"), /* 9 */
- N_("INODE CLEARED"), /* 10 */
- N_("ABORTED"), /* 11 */
- N_("SPLIT"), /* 12 */
- N_("CONTINUING"), /* 13 */
- N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
- N_("FILE DELETED"), /* 15 */
- N_("SUPPRESSED"), /* 16 */
- N_("UNLINKED"), /* 17 */
- N_("HTREE INDEX CLEARED"),/* 18 */
- N_("WILL RECREATE"), /* 19 */
- "", /* 20 */
-};
-
-static const struct e2fsck_problem problem_table[] = {
-
- /* Pre-Pass 1 errors */
-
- /* Block bitmap not in group */
- { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g. (@b %b)\n"),
- PROMPT_RELOCATE, PR_LATCH_RELOC },
-
- /* Inode bitmap not in group */
- { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g. (@b %b)\n"),
- PROMPT_RELOCATE, PR_LATCH_RELOC },
-
- /* Inode table not in group */
- { PR_0_ITABLE_NOT_GROUP,
- N_("@i table for @g %g is not in @g. (@b %b)\n"
- "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
- PROMPT_RELOCATE, PR_LATCH_RELOC },
-
- /* Superblock corrupt */
- { PR_0_SB_CORRUPT,
- N_("\nThe @S could not be read or does not describe a correct ext2\n"
- "@f. If the @v is valid and it really contains an ext2\n"
- "@f (and not swap or ufs or something else), then the @S\n"
- "is corrupt, and you might try running e2fsck with an alternate @S:\n"
- " e2fsck -b %S <@v>\n\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Filesystem size is wrong */
- { PR_0_FS_SIZE_WRONG,
- N_("The @f size (according to the @S) is %b @bs\n"
- "The physical size of the @v is %c @bs\n"
- "Either the @S or the partition table is likely to be corrupt!\n"),
- PROMPT_ABORT, 0 },
-
- /* Fragments not supported */
- { PR_0_NO_FRAGMENTS,
- N_("@S @b_size = %b, fragsize = %c.\n"
- "This version of e2fsck does not support fragment sizes different\n"
- "from the @b size.\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Bad blocks_per_group */
- { PR_0_BLOCKS_PER_GROUP,
- N_("@S @bs_per_group = %b, should have been %c\n"),
- PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
-
- /* Bad first_data_block */
- { PR_0_FIRST_DATA_BLOCK,
- N_("@S first_data_@b = %b, should have been %c\n"),
- PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
-
- /* Adding UUID to filesystem */
- { PR_0_ADD_UUID,
- N_("@f did not have a UUID; generating one.\n\n"),
- PROMPT_NONE, 0 },
-
- /* Relocate hint */
- { PR_0_RELOCATE_HINT,
- N_("Note: if several inode or block bitmap blocks or part\n"
- "of the inode table require relocation, you may wish to try\n"
- "running e2fsck with the '-b %S' option first. The problem\n"
- "may lie only with the primary block group descriptors, and\n"
- "the backup block group descriptors may be OK.\n\n"),
- PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
-
- /* Miscellaneous superblock corruption */
- { PR_0_MISC_CORRUPT_SUPER,
- N_("Corruption found in @S. (%s = %N).\n"),
- PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
-
- /* Error determing physical device size of filesystem */
- { PR_0_GETSIZE_ERROR,
- N_("Error determining size of the physical @v: %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Inode count in superblock is incorrect */
- { PR_0_INODE_COUNT_WRONG,
- N_("@i count in @S is %i, @s %j.\n"),
- PROMPT_FIX, 0 },
-
- { PR_0_HURD_CLEAR_FILETYPE,
- N_("The Hurd does not support the filetype feature.\n"),
- PROMPT_CLEAR, 0 },
-
- /* Journal inode is invalid */
- { PR_0_JOURNAL_BAD_INODE,
- N_("@S has an @n ext3 @j (@i %i).\n"),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* The external journal has (unsupported) multiple filesystems */
- { PR_0_JOURNAL_UNSUPP_MULTIFS,
- N_("External @j has multiple @f users (unsupported).\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Can't find external journal */
- { PR_0_CANT_FIND_JOURNAL,
- N_("Can't find external @j\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* External journal has bad superblock */
- { PR_0_EXT_JOURNAL_BAD_SUPER,
- N_("External @j has bad @S\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Superblock has a bad journal UUID */
- { PR_0_JOURNAL_BAD_UUID,
- N_("External @j does not support this @f\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Journal has an unknown superblock type */
- { PR_0_JOURNAL_UNSUPP_SUPER,
- N_("Ext3 @j @S is unknown type %N (unsupported).\n"
- "It is likely that your copy of e2fsck is old and/or doesn't "
- "support this @j format.\n"
- "It is also possible the @j @S is corrupt.\n"),
- PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
-
- /* Journal superblock is corrupt */
- { PR_0_JOURNAL_BAD_SUPER,
- N_("Ext3 @j @S is corrupt.\n"),
- PROMPT_FIX, PR_PREEN_OK },
-
- /* Superblock flag should be cleared */
- { PR_0_JOURNAL_HAS_JOURNAL,
- N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* Superblock flag is incorrect */
- { PR_0_JOURNAL_RECOVER_SET,
- N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* Journal has data, but recovery flag is clear */
- { PR_0_JOURNAL_RECOVERY_CLEAR,
- N_("ext3 recovery flag is clear, but @j has data.\n"),
- PROMPT_NONE, 0 },
-
- /* Ask if we should clear the journal */
- { PR_0_JOURNAL_RESET_JOURNAL,
- N_("Clear @j"),
- PROMPT_NULL, PR_PREEN_NOMSG },
-
- /* Ask if we should run the journal anyway */
- { PR_0_JOURNAL_RUN,
- N_("Run @j anyway"),
- PROMPT_NULL, 0 },
-
- /* Run the journal by default */
- { PR_0_JOURNAL_RUN_DEFAULT,
- N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
- PROMPT_NONE, 0 },
-
- /* Clearing orphan inode */
- { PR_0_ORPHAN_CLEAR_INODE,
- N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
- PROMPT_NONE, 0 },
-
- /* Illegal block found in orphaned inode */
- { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
- N_("@I @b #%B (%b) found in @o @i %i.\n"),
- PROMPT_NONE, 0 },
-
- /* Already cleared block found in orphaned inode */
- { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
- N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
- PROMPT_NONE, 0 },
-
- /* Illegal orphan inode in superblock */
- { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
- N_("@I @o @i %i in @S.\n"),
- PROMPT_NONE, 0 },
-
- /* Illegal inode in orphaned inode list */
- { PR_0_ORPHAN_ILLEGAL_INODE,
- N_("@I @i %i in @o @i list.\n"),
- PROMPT_NONE, 0 },
-
- /* Filesystem revision is 0, but feature flags are set */
- { PR_0_FS_REV_LEVEL,
- N_("@f has feature flag(s) set, but is a revision 0 @f. "),
- PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
-
- /* Journal superblock has an unknown read-only feature flag set */
- { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
- N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
- PROMPT_ABORT, 0 },
-
- /* Journal superblock has an unknown incompatible feature flag set */
- { PR_0_JOURNAL_UNSUPP_INCOMPAT,
- N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
- PROMPT_ABORT, 0 },
-
- /* Journal has unsupported version number */
- { PR_0_JOURNAL_UNSUPP_VERSION,
- N_("@j version not supported by this e2fsck.\n"),
- PROMPT_ABORT, 0 },
-
- /* Moving journal to hidden file */
- { PR_0_MOVE_JOURNAL,
- N_("Moving @j from /%s to hidden @i.\n\n"),
- PROMPT_NONE, 0 },
-
- /* Error moving journal to hidden file */
- { PR_0_ERR_MOVE_JOURNAL,
- N_("Error moving @j: %m\n\n"),
- PROMPT_NONE, 0 },
-
- /* Clearing V2 journal superblock */
- { PR_0_CLEAR_V2_JOURNAL,
- N_("Found @n V2 @j @S fields (from V1 @j).\n"
- "Clearing fields beyond the V1 @j @S...\n\n"),
- PROMPT_NONE, 0 },
-
- /* Backup journal inode blocks */
- { PR_0_BACKUP_JNL,
- N_("Backing up @j @i @b information.\n\n"),
- PROMPT_NONE, 0 },
-
- /* Reserved blocks w/o resize_inode */
- { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
- N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
- "is %N; @s zero. "),
- PROMPT_FIX, 0 },
-
- /* Resize_inode not enabled, but resize inode is non-zero */
- { PR_0_CLEAR_RESIZE_INODE,
- N_("Resize_@i not enabled, but the resize @i is non-zero. "),
- PROMPT_CLEAR, 0 },
-
- /* Resize inode invalid */
- { PR_0_RESIZE_INODE_INVALID,
- N_("Resize @i not valid. "),
- PROMPT_RECREATE, 0 },
-
- /* Pass 1 errors */
-
- /* Pass 1: Checking inodes, blocks, and sizes */
- { PR_1_PASS_HEADER,
- N_("Pass 1: Checking @is, @bs, and sizes\n"),
- PROMPT_NONE, 0 },
-
- /* Root directory is not an inode */
- { PR_1_ROOT_NO_DIR, N_("@r is not a @d. "),
- PROMPT_CLEAR, 0 },
-
- /* Root directory has dtime set */
- { PR_1_ROOT_DTIME,
- N_("@r has dtime set (probably due to old mke2fs). "),
- PROMPT_FIX, PR_PREEN_OK },
-
- /* Reserved inode has bad mode */
- { PR_1_RESERVED_BAD_MODE,
- N_("Reserved @i %i (%Q) has @n mode. "),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* Deleted inode has zero dtime */
- { PR_1_ZERO_DTIME,
- N_("@D @i %i has zero dtime. "),
- PROMPT_FIX, PR_PREEN_OK },
-
- /* Inode in use, but dtime set */
- { PR_1_SET_DTIME,
- N_("@i %i is in use, but has dtime set. "),
- PROMPT_FIX, PR_PREEN_OK },
-
- /* Zero-length directory */
- { PR_1_ZERO_LENGTH_DIR,
- N_("@i %i is a @z @d. "),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* Block bitmap conflicts with some other fs block */
- { PR_1_BB_CONFLICT,
- N_("@g %g's @b @B at %b @C.\n"),
- PROMPT_RELOCATE, 0 },
-
- /* Inode bitmap conflicts with some other fs block */
- { PR_1_IB_CONFLICT,
- N_("@g %g's @i @B at %b @C.\n"),
- PROMPT_RELOCATE, 0 },
-
- /* Inode table conflicts with some other fs block */
- { PR_1_ITABLE_CONFLICT,
- N_("@g %g's @i table at %b @C.\n"),
- PROMPT_RELOCATE, 0 },
-
- /* Block bitmap is on a bad block */
- { PR_1_BB_BAD_BLOCK,
- N_("@g %g's @b @B (%b) is bad. "),
- PROMPT_RELOCATE, 0 },
-
- /* Inode bitmap is on a bad block */
- { PR_1_IB_BAD_BLOCK,
- N_("@g %g's @i @B (%b) is bad. "),
- PROMPT_RELOCATE, 0 },
-
- /* Inode has incorrect i_size */
- { PR_1_BAD_I_SIZE,
- N_("@i %i, i_size is %Is, @s %N. "),
- PROMPT_FIX, PR_PREEN_OK },
-
- /* Inode has incorrect i_blocks */
- { PR_1_BAD_I_BLOCKS,
- N_("@i %i, i_@bs is %Ib, @s %N. "),
- PROMPT_FIX, PR_PREEN_OK },
-
- /* Illegal blocknumber in inode */
- { PR_1_ILLEGAL_BLOCK_NUM,
- N_("@I @b #%B (%b) in @i %i. "),
- PROMPT_CLEAR, PR_LATCH_BLOCK },
-
- /* Block number overlaps fs metadata */
- { PR_1_BLOCK_OVERLAPS_METADATA,
- N_("@b #%B (%b) overlaps @f metadata in @i %i. "),
- PROMPT_CLEAR, PR_LATCH_BLOCK },
-
- /* Inode has illegal blocks (latch question) */
- { PR_1_INODE_BLOCK_LATCH,
- N_("@i %i has illegal @b(s). "),
- PROMPT_CLEAR, 0 },
-
- /* Too many bad blocks in inode */
- { PR_1_TOO_MANY_BAD_BLOCKS,
- N_("Too many illegal @bs in @i %i.\n"),
- PROMPT_CLEAR_INODE, PR_NO_OK },
-
- /* Illegal block number in bad block inode */
- { PR_1_BB_ILLEGAL_BLOCK_NUM,
- N_("@I @b #%B (%b) in bad @b @i. "),
- PROMPT_CLEAR, PR_LATCH_BBLOCK },
-
- /* Bad block inode has illegal blocks (latch question) */
- { PR_1_INODE_BBLOCK_LATCH,
- N_("Bad @b @i has illegal @b(s). "),
- PROMPT_CLEAR, 0 },
-
- /* Duplicate or bad blocks in use! */
- { PR_1_DUP_BLOCKS_PREENSTOP,
- N_("Duplicate or bad @b in use!\n"),
- PROMPT_NONE, 0 },
-
- /* Bad block used as bad block indirect block */
- { PR_1_BBINODE_BAD_METABLOCK,
- N_("Bad @b %b used as bad @b @i indirect @b. "),
- PROMPT_CLEAR, PR_LATCH_BBLOCK },
-
- /* Inconsistency can't be fixed prompt */
- { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
- N_("\nThe bad @b @i has probably been corrupted. You probably\n"
- "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
- "in the @f.\n"),
- PROMPT_CONTINUE, PR_PREEN_NOMSG },
-
- /* Bad primary block */
- { PR_1_BAD_PRIMARY_BLOCK,
- N_("\nIf the @b is really bad, the @f cannot be fixed.\n"),
- PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
-
- /* Bad primary block prompt */
- { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
- N_("You can remove this @b from the bad @b list and hope\n"
- "that the @b is really OK. But there are no guarantees.\n\n"),
- PROMPT_CLEAR, PR_PREEN_NOMSG },
-
- /* Bad primary superblock */
- { PR_1_BAD_PRIMARY_SUPERBLOCK,
- N_("The primary @S (%b) is on the bad @b list.\n"),
- PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
-
- /* Bad primary block group descriptors */
- { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
- N_("Block %b in the primary @g descriptors "
- "is on the bad @b list\n"),
- PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
-
- /* Bad superblock in group */
- { PR_1_BAD_SUPERBLOCK,
- N_("Warning: Group %g's @S (%b) is bad.\n"),
- PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Bad block group descriptors in group */
- { PR_1_BAD_GROUP_DESCRIPTORS,
- N_("Warning: Group %g's copy of the @g descriptors has a bad "
- "@b (%b).\n"),
- PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Block claimed for no reason */
- { PR_1_PROGERR_CLAIMED_BLOCK,
- N_("Programming error? @b #%b claimed for no reason in "
- "process_bad_@b.\n"),
- PROMPT_NONE, PR_PREEN_OK },
-
- /* Error allocating blocks for relocating metadata */
- { PR_1_RELOC_BLOCK_ALLOCATE,
- N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
- PROMPT_NONE, PR_PREEN_OK },
-
- /* Error allocating block buffer during relocation process */
- { PR_1_RELOC_MEMORY_ALLOCATE,
- N_("@A @b buffer for relocating %s\n"),
- PROMPT_NONE, PR_PREEN_OK },
-
- /* Relocating metadata group information from X to Y */
- { PR_1_RELOC_FROM_TO,
- N_("Relocating @g %g's %s from %b to %c...\n"),
- PROMPT_NONE, PR_PREEN_OK },
-
- /* Relocating metatdata group information to X */
- { PR_1_RELOC_TO,
- N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
- PROMPT_NONE, PR_PREEN_OK },
-
- /* Block read error during relocation process */
- { PR_1_RELOC_READ_ERR,
- N_("Warning: could not read @b %b of %s: %m\n"),
- PROMPT_NONE, PR_PREEN_OK },
-
- /* Block write error during relocation process */
- { PR_1_RELOC_WRITE_ERR,
- N_("Warning: could not write @b %b for %s: %m\n"),
- PROMPT_NONE, PR_PREEN_OK },
-
- /* Error allocating inode bitmap */
- { PR_1_ALLOCATE_IBITMAP_ERROR,
- N_("@A @i @B (%N): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error allocating block bitmap */
- { PR_1_ALLOCATE_BBITMAP_ERROR,
- N_("@A @b @B (%N): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error allocating icount structure */
- { PR_1_ALLOCATE_ICOUNT,
- N_("@A icount link information: %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error allocating dbcount */
- { PR_1_ALLOCATE_DBCOUNT,
- N_("@A @d @b array: %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error while scanning inodes */
- { PR_1_ISCAN_ERROR,
- N_("Error while scanning @is (%i): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error while iterating over blocks */
- { PR_1_BLOCK_ITERATE,
- N_("Error while iterating over @bs in @i %i: %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error while storing inode count information */
- { PR_1_ICOUNT_STORE,
- N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error while storing directory block information */
- { PR_1_ADD_DBLOCK,
- N_("Error storing @d @b information "
- "(@i=%i, @b=%b, num=%N): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error while reading inode (for clearing) */
- { PR_1_READ_INODE,
- N_("Error reading @i %i: %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Suppress messages prompt */
- { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
-
- /* Imagic flag set on an inode when filesystem doesn't support it */
- { PR_1_SET_IMAGIC,
- N_("@i %i has imagic flag set. "),
- PROMPT_CLEAR, 0 },
-
- /* Immutable flag set on a device or socket inode */
- { PR_1_SET_IMMUTABLE,
- N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
- "or append-only flag set. "),
- PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
-
- /* Compression flag set on an inode when filesystem doesn't support it */
- { PR_1_COMPR_SET,
- N_("@i %i has @cion flag set on @f without @cion support. "),
- PROMPT_CLEAR, 0 },
-
- /* Non-zero size for device, fifo or socket inode */
- { PR_1_SET_NONZSIZE,
- N_("Special (@v/socket/fifo) @i %i has non-zero size. "),
- PROMPT_FIX, PR_PREEN_OK },
-
- /* Filesystem revision is 0, but feature flags are set */
- { PR_1_FS_REV_LEVEL,
- N_("@f has feature flag(s) set, but is a revision 0 @f. "),
- PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
-
- /* Journal inode is not in use, but contains data */
- { PR_1_JOURNAL_INODE_NOT_CLEAR,
- N_("@j @i is not in use, but contains data. "),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* Journal has bad mode */
- { PR_1_JOURNAL_BAD_MODE,
- N_("@j is not regular file. "),
- PROMPT_FIX, PR_PREEN_OK },
-
- /* Deal with inodes that were part of orphan linked list */
- { PR_1_LOW_DTIME,
- N_("@i %i was part of the @o @i list. "),
- PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
-
- /* Deal with inodes that were part of corrupted orphan linked
- list (latch question) */
- { PR_1_ORPHAN_LIST_REFUGEES,
- N_("@is that were part of a corrupted orphan linked list found. "),
- PROMPT_FIX, 0 },
-
- /* Error allocating refcount structure */
- { PR_1_ALLOCATE_REFCOUNT,
- N_("@A refcount structure (%N): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error reading extended attribute block */
- { PR_1_READ_EA_BLOCK,
- N_("Error reading @a @b %b for @i %i. "),
- PROMPT_CLEAR, 0 },
-
- /* Invalid extended attribute block */
- { PR_1_BAD_EA_BLOCK,
- N_("@i %i has a bad @a @b %b. "),
- PROMPT_CLEAR, 0 },
-
- /* Error reading Extended Attribute block while fixing refcount */
- { PR_1_EXTATTR_READ_ABORT,
- N_("Error reading @a @b %b (%m). "),
- PROMPT_ABORT, 0 },
-
- /* Extended attribute reference count incorrect */
- { PR_1_EXTATTR_REFCOUNT,
- N_("@a @b %b has reference count %B, @s %N. "),
- PROMPT_FIX, 0 },
-
- /* Error writing Extended Attribute block while fixing refcount */
- { PR_1_EXTATTR_WRITE,
- N_("Error writing @a @b %b (%m). "),
- PROMPT_ABORT, 0 },
-
- /* Multiple EA blocks not supported */
- { PR_1_EA_MULTI_BLOCK,
- N_("@a @b %b has h_@bs > 1. "),
- PROMPT_CLEAR, 0},
-
- /* Error allocating EA region allocation structure */
- { PR_1_EA_ALLOC_REGION,
- N_("@A @a @b %b. "),
- PROMPT_ABORT, 0},
-
- /* Error EA allocation collision */
- { PR_1_EA_ALLOC_COLLISION,
- N_("@a @b %b is corrupt (allocation collision). "),
- PROMPT_CLEAR, 0},
-
- /* Bad extended attribute name */
- { PR_1_EA_BAD_NAME,
- N_("@a @b %b is corrupt (@n name). "),
- PROMPT_CLEAR, 0},
-
- /* Bad extended attribute value */
- { PR_1_EA_BAD_VALUE,
- N_("@a @b %b is corrupt (@n value). "),
- PROMPT_CLEAR, 0},
-
- /* Inode too big (latch question) */
- { PR_1_INODE_TOOBIG,
- N_("@i %i is too big. "), PROMPT_TRUNCATE, 0 },
-
- /* Directory too big */
- { PR_1_TOOBIG_DIR,
- N_("@b #%B (%b) causes @d to be too big. "),
- PROMPT_CLEAR, PR_LATCH_TOOBIG },
-
- /* Regular file too big */
- { PR_1_TOOBIG_REG,
- N_("@b #%B (%b) causes file to be too big. "),
- PROMPT_CLEAR, PR_LATCH_TOOBIG },
-
- /* Symlink too big */
- { PR_1_TOOBIG_SYMLINK,
- N_("@b #%B (%b) causes symlink to be too big. "),
- PROMPT_CLEAR, PR_LATCH_TOOBIG },
-
- /* INDEX_FL flag set on a non-HTREE filesystem */
- { PR_1_HTREE_SET,
- N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
- PROMPT_CLEAR_HTREE, PR_PREEN_OK },
-
- /* INDEX_FL flag set on a non-directory */
- { PR_1_HTREE_NODIR,
- N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
- PROMPT_CLEAR_HTREE, PR_PREEN_OK },
-
- /* Invalid root node in HTREE directory */
- { PR_1_HTREE_BADROOT,
- N_("@h %i has an @n root node.\n"),
- PROMPT_CLEAR_HTREE, PR_PREEN_OK },
-
- /* Unsupported hash version in HTREE directory */
- { PR_1_HTREE_HASHV,
- N_("@h %i has an unsupported hash version (%N)\n"),
- PROMPT_CLEAR_HTREE, PR_PREEN_OK },
-
- /* Incompatible flag in HTREE root node */
- { PR_1_HTREE_INCOMPAT,
- N_("@h %i uses an incompatible htree root node flag.\n"),
- PROMPT_CLEAR_HTREE, PR_PREEN_OK },
-
- /* HTREE too deep */
- { PR_1_HTREE_DEPTH,
- N_("@h %i has a tree depth (%N) which is too big\n"),
- PROMPT_CLEAR_HTREE, PR_PREEN_OK },
-
- /* Bad block has indirect block that conflicts with filesystem block */
- { PR_1_BB_FS_BLOCK,
- N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
- "@f metadata. "),
- PROMPT_CLEAR, PR_LATCH_BBLOCK },
-
- /* Resize inode failed */
- { PR_1_RESIZE_INODE_CREATE,
- N_("Resize @i (re)creation failed: %m."),
- PROMPT_ABORT, 0 },
-
- /* invalid inode->i_extra_isize */
- { PR_1_EXTRA_ISIZE,
- N_("@i %i has a extra size (%IS) which is @n\n"),
- PROMPT_FIX, PR_PREEN_OK },
-
- /* invalid ea entry->e_name_len */
- { PR_1_ATTR_NAME_LEN,
- N_("@a in @i %i has a namelen (%N) which is @n\n"),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* invalid ea entry->e_value_size */
- { PR_1_ATTR_VALUE_SIZE,
- N_("@a in @i %i has a value size (%N) which is @n\n"),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* invalid ea entry->e_value_offs */
- { PR_1_ATTR_VALUE_OFFSET,
- N_("@a in @i %i has a value offset (%N) which is @n\n"),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* invalid ea entry->e_value_block */
- { PR_1_ATTR_VALUE_BLOCK,
- N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* invalid ea entry->e_hash */
- { PR_1_ATTR_HASH,
- N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* Pass 1b errors */
-
- /* Pass 1B: Rescan for duplicate/bad blocks */
- { PR_1B_PASS_HEADER,
- N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
- "Pass 1B: Rescanning for @m @bs\n"),
- PROMPT_NONE, 0 },
-
- /* Duplicate/bad block(s) header */
- { PR_1B_DUP_BLOCK_HEADER,
- N_("@m @b(s) in @i %i:"),
- PROMPT_NONE, 0 },
-
- /* Duplicate/bad block(s) in inode */
- { PR_1B_DUP_BLOCK,
- " %b",
- PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
-
- /* Duplicate/bad block(s) end */
- { PR_1B_DUP_BLOCK_END,
- "\n",
- PROMPT_NONE, PR_PREEN_NOHDR },
-
- /* Error while scanning inodes */
- { PR_1B_ISCAN_ERROR,
- N_("Error while scanning inodes (%i): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error allocating inode bitmap */
- { PR_1B_ALLOCATE_IBITMAP_ERROR,
- N_("@A @i @B (@i_dup_map): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error while iterating over blocks */
- { PR_1B_BLOCK_ITERATE,
- N_("Error while iterating over @bs in @i %i (%s): %m\n"),
- PROMPT_NONE, 0 },
-
- /* Error adjusting EA refcount */
- { PR_1B_ADJ_EA_REFCOUNT,
- N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
- PROMPT_NONE, 0 },
-
-
- /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
- { PR_1C_PASS_HEADER,
- N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
- PROMPT_NONE, 0 },
-
-
- /* Pass 1D: Reconciling multiply-claimed blocks */
- { PR_1D_PASS_HEADER,
- N_("Pass 1D: Reconciling @m @bs\n"),
- PROMPT_NONE, 0 },
-
- /* File has duplicate blocks */
- { PR_1D_DUP_FILE,
- N_("File %Q (@i #%i, mod time %IM)\n"
- " has %B @m @b(s), shared with %N file(s):\n"),
- PROMPT_NONE, 0 },
-
- /* List of files sharing duplicate blocks */
- { PR_1D_DUP_FILE_LIST,
- N_("\t%Q (@i #%i, mod time %IM)\n"),
- PROMPT_NONE, 0 },
-
- /* File sharing blocks with filesystem metadata */
- { PR_1D_SHARE_METADATA,
- N_("\t<@f metadata>\n"),
- PROMPT_NONE, 0 },
-
- /* Report of how many duplicate/bad inodes */
- { PR_1D_NUM_DUP_INODES,
- N_("(There are %N @is containing @m @bs.)\n\n"),
- PROMPT_NONE, 0 },
-
- /* Duplicated blocks already reassigned or cloned. */
- { PR_1D_DUP_BLOCKS_DEALT,
- N_("@m @bs already reassigned or cloned.\n\n"),
- PROMPT_NONE, 0 },
-
- /* Clone duplicate/bad blocks? */
- { PR_1D_CLONE_QUESTION,
- "", PROMPT_CLONE, PR_NO_OK },
-
- /* Delete file? */
- { PR_1D_DELETE_QUESTION,
- "", PROMPT_DELETE, 0 },
-
- /* Couldn't clone file (error) */
- { PR_1D_CLONE_ERROR,
- N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
-
- /* Pass 2 errors */
-
- /* Pass 2: Checking directory structure */
- { PR_2_PASS_HEADER,
- N_("Pass 2: Checking @d structure\n"),
- PROMPT_NONE, 0 },
-
- /* Bad inode number for '.' */
- { PR_2_BAD_INODE_DOT,
- N_("@n @i number for '.' in @d @i %i.\n"),
- PROMPT_FIX, 0 },
-
- /* Directory entry has bad inode number */
- { PR_2_BAD_INO,
- N_("@E has @n @i #: %Di.\n"),
- PROMPT_CLEAR, 0 },
-
- /* Directory entry has deleted or unused inode */
- { PR_2_UNUSED_INODE,
- N_("@E has @D/unused @i %Di. "),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* Directry entry is link to '.' */
- { PR_2_LINK_DOT,
- N_("@E @L to '.' "),
- PROMPT_CLEAR, 0 },
-
- /* Directory entry points to inode now located in a bad block */
- { PR_2_BB_INODE,
- N_("@E points to @i (%Di) located in a bad @b.\n"),
- PROMPT_CLEAR, 0 },
-
- /* Directory entry contains a link to a directory */
- { PR_2_LINK_DIR,
- N_("@E @L to @d %P (%Di).\n"),
- PROMPT_CLEAR, 0 },
-
- /* Directory entry contains a link to the root directry */
- { PR_2_LINK_ROOT,
- N_("@E @L to the @r.\n"),
- PROMPT_CLEAR, 0 },
-
- /* Directory entry has illegal characters in its name */
- { PR_2_BAD_NAME,
- N_("@E has illegal characters in its name.\n"),
- PROMPT_FIX, 0 },
-
- /* Missing '.' in directory inode */
- { PR_2_MISSING_DOT,
- N_("Missing '.' in @d @i %i.\n"),
- PROMPT_FIX, 0 },
-
- /* Missing '..' in directory inode */
- { PR_2_MISSING_DOT_DOT,
- N_("Missing '..' in @d @i %i.\n"),
- PROMPT_FIX, 0 },
-
- /* First entry in directory inode doesn't contain '.' */
- { PR_2_1ST_NOT_DOT,
- N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
- PROMPT_FIX, 0 },
-
- /* Second entry in directory inode doesn't contain '..' */
- { PR_2_2ND_NOT_DOT_DOT,
- N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
- PROMPT_FIX, 0 },
-
- /* i_faddr should be zero */
- { PR_2_FADDR_ZERO,
- N_("i_faddr @F %IF, @s zero.\n"),
- PROMPT_CLEAR, 0 },
-
- /* i_file_acl should be zero */
- { PR_2_FILE_ACL_ZERO,
- N_("i_file_acl @F %If, @s zero.\n"),
- PROMPT_CLEAR, 0 },
-
- /* i_dir_acl should be zero */
- { PR_2_DIR_ACL_ZERO,
- N_("i_dir_acl @F %Id, @s zero.\n"),
- PROMPT_CLEAR, 0 },
-
- /* i_frag should be zero */
- { PR_2_FRAG_ZERO,
- N_("i_frag @F %N, @s zero.\n"),
- PROMPT_CLEAR, 0 },
-
- /* i_fsize should be zero */
- { PR_2_FSIZE_ZERO,
- N_("i_fsize @F %N, @s zero.\n"),
- PROMPT_CLEAR, 0 },
-
- /* inode has bad mode */
- { PR_2_BAD_MODE,
- N_("@i %i (%Q) has @n mode (%Im).\n"),
- PROMPT_CLEAR, 0 },
-
- /* directory corrupted */
- { PR_2_DIR_CORRUPTED,
- N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
- PROMPT_SALVAGE, 0 },
-
- /* filename too long */
- { PR_2_FILENAME_LONG,
- N_("@d @i %i, @b %B, offset %N: filename too long\n"),
- PROMPT_TRUNCATE, 0 },
-
- /* Directory inode has a missing block (hole) */
- { PR_2_DIRECTORY_HOLE,
- N_("@d @i %i has an unallocated @b #%B. "),
- PROMPT_ALLOCATE, 0 },
-
- /* '.' is not NULL terminated */
- { PR_2_DOT_NULL_TERM,
- N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
- PROMPT_FIX, 0 },
-
- /* '..' is not NULL terminated */
- { PR_2_DOT_DOT_NULL_TERM,
- N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
- PROMPT_FIX, 0 },
-
- /* Illegal character device inode */
- { PR_2_BAD_CHAR_DEV,
- N_("@i %i (%Q) is an @I character @v.\n"),
- PROMPT_CLEAR, 0 },
-
- /* Illegal block device inode */
- { PR_2_BAD_BLOCK_DEV,
- N_("@i %i (%Q) is an @I @b @v.\n"),
- PROMPT_CLEAR, 0 },
-
- /* Duplicate '.' entry */
- { PR_2_DUP_DOT,
- N_("@E is duplicate '.' @e.\n"),
- PROMPT_FIX, 0 },
-
- /* Duplicate '..' entry */
- { PR_2_DUP_DOT_DOT,
- N_("@E is duplicate '..' @e.\n"),
- PROMPT_FIX, 0 },
-
- /* Internal error: couldn't find dir_info */
- { PR_2_NO_DIRINFO,
- N_("Internal error: cannot find dir_info for %i.\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Final rec_len is wrong */
- { PR_2_FINAL_RECLEN,
- N_("@E has rec_len of %Dr, @s %N.\n"),
- PROMPT_FIX, 0 },
-
- /* Error allocating icount structure */
- { PR_2_ALLOCATE_ICOUNT,
- N_("@A icount structure: %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error iterating over directory blocks */
- { PR_2_DBLIST_ITERATE,
- N_("Error iterating over @d @bs: %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error reading directory block */
- { PR_2_READ_DIRBLOCK,
- N_("Error reading @d @b %b (@i %i): %m\n"),
- PROMPT_CONTINUE, 0 },
-
- /* Error writing directory block */
- { PR_2_WRITE_DIRBLOCK,
- N_("Error writing @d @b %b (@i %i): %m\n"),
- PROMPT_CONTINUE, 0 },
-
- /* Error allocating new directory block */
- { PR_2_ALLOC_DIRBOCK,
- N_("@A new @d @b for @i %i (%s): %m\n"),
- PROMPT_NONE, 0 },
-
- /* Error deallocating inode */
- { PR_2_DEALLOC_INODE,
- N_("Error deallocating @i %i: %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Directory entry for '.' is big. Split? */
- { PR_2_SPLIT_DOT,
- N_("@d @e for '.' is big. "),
- PROMPT_SPLIT, PR_NO_OK },
-
- /* Illegal FIFO inode */
- { PR_2_BAD_FIFO,
- N_("@i %i (%Q) is an @I FIFO.\n"),
- PROMPT_CLEAR, 0 },
-
- /* Illegal socket inode */
- { PR_2_BAD_SOCKET,
- N_("@i %i (%Q) is an @I socket.\n"),
- PROMPT_CLEAR, 0 },
-
- /* Directory filetype not set */
- { PR_2_SET_FILETYPE,
- N_("Setting filetype for @E to %N.\n"),
- PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
-
- /* Directory filetype incorrect */
- { PR_2_BAD_FILETYPE,
- N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
- PROMPT_FIX, 0 },
-
- /* Directory filetype set on filesystem */
- { PR_2_CLEAR_FILETYPE,
- N_("@E has filetype set.\n"),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* Directory filename is null */
- { PR_2_NULL_NAME,
- N_("@E has a @z name.\n"),
- PROMPT_CLEAR, 0 },
-
- /* Invalid symlink */
- { PR_2_INVALID_SYMLINK,
- N_("Symlink %Q (@i #%i) is @n.\n"),
- PROMPT_CLEAR, 0 },
-
- /* i_file_acl (extended attribute block) is bad */
- { PR_2_FILE_ACL_BAD,
- N_("@a @b @F @n (%If).\n"),
- PROMPT_CLEAR, 0 },
-
- /* Filesystem contains large files, but has no such flag in sb */
- { PR_2_FEATURE_LARGE_FILES,
- N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
- PROMPT_FIX, 0 },
-
- /* Node in HTREE directory not referenced */
- { PR_2_HTREE_NOTREF,
- N_("@p @h %d: node (%B) not referenced\n"),
- PROMPT_NONE, 0 },
-
- /* Node in HTREE directory referenced twice */
- { PR_2_HTREE_DUPREF,
- N_("@p @h %d: node (%B) referenced twice\n"),
- PROMPT_NONE, 0 },
-
- /* Node in HTREE directory has bad min hash */
- { PR_2_HTREE_MIN_HASH,
- N_("@p @h %d: node (%B) has bad min hash\n"),
- PROMPT_NONE, 0 },
-
- /* Node in HTREE directory has bad max hash */
- { PR_2_HTREE_MAX_HASH,
- N_("@p @h %d: node (%B) has bad max hash\n"),
- PROMPT_NONE, 0 },
-
- /* Clear invalid HTREE directory */
- { PR_2_HTREE_CLEAR,
- N_("@n @h %d (%q). "), PROMPT_CLEAR, 0 },
-
- /* Bad block in htree interior node */
- { PR_2_HTREE_BADBLK,
- N_("@p @h %d (%q): bad @b number %b.\n"),
- PROMPT_CLEAR_HTREE, 0 },
-
- /* Error adjusting EA refcount */
- { PR_2_ADJ_EA_REFCOUNT,
- N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Invalid HTREE root node */
- { PR_2_HTREE_BAD_ROOT,
- N_("@p @h %d: root node is @n\n"),
- PROMPT_CLEAR_HTREE, PR_PREEN_OK },
-
- /* Invalid HTREE limit */
- { PR_2_HTREE_BAD_LIMIT,
- N_("@p @h %d: node (%B) has @n limit (%N)\n"),
- PROMPT_CLEAR_HTREE, PR_PREEN_OK },
-
- /* Invalid HTREE count */
- { PR_2_HTREE_BAD_COUNT,
- N_("@p @h %d: node (%B) has @n count (%N)\n"),
- PROMPT_CLEAR_HTREE, PR_PREEN_OK },
-
- /* HTREE interior node has out-of-order hashes in table */
- { PR_2_HTREE_HASH_ORDER,
- N_("@p @h %d: node (%B) has an unordered hash table\n"),
- PROMPT_CLEAR_HTREE, PR_PREEN_OK },
-
- /* Node in HTREE directory has invalid depth */
- { PR_2_HTREE_BAD_DEPTH,
- N_("@p @h %d: node (%B) has @n depth\n"),
- PROMPT_NONE, 0 },
-
- /* Duplicate directory entry found */
- { PR_2_DUPLICATE_DIRENT,
- N_("Duplicate @E found. "),
- PROMPT_CLEAR, 0 },
-
- /* Non-unique filename found */
- { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
- N_("@E has a non-unique filename.\nRename to %s"),
- PROMPT_NULL, 0 },
-
- /* Duplicate directory entry found */
- { PR_2_REPORT_DUP_DIRENT,
- N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
- PROMPT_NONE, 0 },
-
- /* Pass 3 errors */
-
- /* Pass 3: Checking directory connectivity */
- { PR_3_PASS_HEADER,
- N_("Pass 3: Checking @d connectivity\n"),
- PROMPT_NONE, 0 },
-
- /* Root inode not allocated */
- { PR_3_NO_ROOT_INODE,
- N_("@r not allocated. "),
- PROMPT_ALLOCATE, 0 },
-
- /* No room in lost+found */
- { PR_3_EXPAND_LF_DIR,
- N_("No room in @l @d. "),
- PROMPT_EXPAND, 0 },
-
- /* Unconnected directory inode */
- { PR_3_UNCONNECTED_DIR,
- N_("Unconnected @d @i %i (%p)\n"),
- PROMPT_CONNECT, 0 },
-
- /* /lost+found not found */
- { PR_3_NO_LF_DIR,
- N_("/@l not found. "),
- PROMPT_CREATE, PR_PREEN_OK },
-
- /* .. entry is incorrect */
- { PR_3_BAD_DOT_DOT,
- N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
- PROMPT_FIX, 0 },
-
- /* Bad or non-existent /lost+found. Cannot reconnect */
- { PR_3_NO_LPF,
- N_("Bad or non-existent /@l. Cannot reconnect.\n"),
- PROMPT_NONE, 0 },
-
- /* Could not expand /lost+found */
- { PR_3_CANT_EXPAND_LPF,
- N_("Could not expand /@l: %m\n"),
- PROMPT_NONE, 0 },
-
- /* Could not reconnect inode */
- { PR_3_CANT_RECONNECT,
- N_("Could not reconnect %i: %m\n"),
- PROMPT_NONE, 0 },
-
- /* Error while trying to find /lost+found */
- { PR_3_ERR_FIND_LPF,
- N_("Error while trying to find /@l: %m\n"),
- PROMPT_NONE, 0 },
-
- /* Error in ext2fs_new_block while creating /lost+found */
- { PR_3_ERR_LPF_NEW_BLOCK,
- N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
- PROMPT_NONE, 0 },
-
- /* Error in ext2fs_new_inode while creating /lost+found */
- { PR_3_ERR_LPF_NEW_INODE,
- N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
- PROMPT_NONE, 0 },
-
- /* Error in ext2fs_new_dir_block while creating /lost+found */
- { PR_3_ERR_LPF_NEW_DIR_BLOCK,
- N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
- PROMPT_NONE, 0 },
-
- /* Error while writing directory block for /lost+found */
- { PR_3_ERR_LPF_WRITE_BLOCK,
- N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
- PROMPT_NONE, 0 },
-
- /* Error while adjusting inode count */
- { PR_3_ADJUST_INODE,
- N_("Error while adjusting @i count on @i %i\n"),
- PROMPT_NONE, 0 },
-
- /* Couldn't fix parent directory -- error */
- { PR_3_FIX_PARENT_ERR,
- N_("Couldn't fix parent of @i %i: %m\n\n"),
- PROMPT_NONE, 0 },
-
- /* Couldn't fix parent directory -- couldn't find it */
- { PR_3_FIX_PARENT_NOFIND,
- N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
- PROMPT_NONE, 0 },
-
- /* Error allocating inode bitmap */
- { PR_3_ALLOCATE_IBITMAP_ERROR,
- N_("@A @i @B (%N): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error creating root directory */
- { PR_3_CREATE_ROOT_ERROR,
- N_("Error creating root @d (%s): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error creating lost and found directory */
- { PR_3_CREATE_LPF_ERROR,
- N_("Error creating /@l @d (%s): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Root inode is not directory; aborting */
- { PR_3_ROOT_NOT_DIR_ABORT,
- N_("@r is not a @d; aborting.\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Cannot proceed without a root inode. */
- { PR_3_NO_ROOT_INODE_ABORT,
- N_("can't proceed without a @r.\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Internal error: couldn't find dir_info */
- { PR_3_NO_DIRINFO,
- N_("Internal error: cannot find dir_info for %i.\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Lost+found not a directory */
- { PR_3_LPF_NOTDIR,
- N_("/@l is not a @d (ino=%i)\n"),
- PROMPT_UNLINK, 0 },
-
- /* Pass 3A Directory Optimization */
-
- /* Pass 3A: Optimizing directories */
- { PR_3A_PASS_HEADER,
- N_("Pass 3A: Optimizing directories\n"),
- PROMPT_NONE, PR_PREEN_NOMSG },
-
- /* Error iterating over directories */
- { PR_3A_OPTIMIZE_ITER,
- N_("Failed to create dirs_to_hash iterator: %m"),
- PROMPT_NONE, 0 },
-
- /* Error rehash directory */
- { PR_3A_OPTIMIZE_DIR_ERR,
- N_("Failed to optimize directory %q (%d): %m"),
- PROMPT_NONE, 0 },
-
- /* Rehashing dir header */
- { PR_3A_OPTIMIZE_DIR_HEADER,
- N_("Optimizing directories: "),
- PROMPT_NONE, PR_MSG_ONLY },
-
- /* Rehashing directory %d */
- { PR_3A_OPTIMIZE_DIR,
- " %d",
- PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
-
- /* Rehashing dir end */
- { PR_3A_OPTIMIZE_DIR_END,
- "\n",
- PROMPT_NONE, PR_PREEN_NOHDR },
-
- /* Pass 4 errors */
-
- /* Pass 4: Checking reference counts */
- { PR_4_PASS_HEADER,
- N_("Pass 4: Checking reference counts\n"),
- PROMPT_NONE, 0 },
-
- /* Unattached zero-length inode */
- { PR_4_ZERO_LEN_INODE,
- N_("@u @z @i %i. "),
- PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
-
- /* Unattached inode */
- { PR_4_UNATTACHED_INODE,
- N_("@u @i %i\n"),
- PROMPT_CONNECT, 0 },
-
- /* Inode ref count wrong */
- { PR_4_BAD_REF_COUNT,
- N_("@i %i ref count is %Il, @s %N. "),
- PROMPT_FIX, PR_PREEN_OK },
-
- { PR_4_INCONSISTENT_COUNT,
- N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
- "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
- "@i_link_info[%i] is %N, @i.i_links_count is %Il. "
- "They @s the same!\n"),
- PROMPT_NONE, 0 },
-
- /* Pass 5 errors */
-
- /* Pass 5: Checking group summary information */
- { PR_5_PASS_HEADER,
- N_("Pass 5: Checking @g summary information\n"),
- PROMPT_NONE, 0 },
-
- /* Padding at end of inode bitmap is not set. */
- { PR_5_INODE_BMAP_PADDING,
- N_("Padding at end of @i @B is not set. "),
- PROMPT_FIX, PR_PREEN_OK },
-
- /* Padding at end of block bitmap is not set. */
- { PR_5_BLOCK_BMAP_PADDING,
- N_("Padding at end of @b @B is not set. "),
- PROMPT_FIX, PR_PREEN_OK },
-
- /* Block bitmap differences header */
- { PR_5_BLOCK_BITMAP_HEADER,
- N_("@b @B differences: "),
- PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
-
- /* Block not used, but marked in bitmap */
- { PR_5_BLOCK_UNUSED,
- " -%b",
- PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Block used, but not marked used in bitmap */
- { PR_5_BLOCK_USED,
- " +%b",
- PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Block bitmap differences end */
- { PR_5_BLOCK_BITMAP_END,
- "\n",
- PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Inode bitmap differences header */
- { PR_5_INODE_BITMAP_HEADER,
- N_("@i @B differences: "),
- PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Inode not used, but marked in bitmap */
- { PR_5_INODE_UNUSED,
- " -%i",
- PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Inode used, but not marked used in bitmap */
- { PR_5_INODE_USED,
- " +%i",
- PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Inode bitmap differences end */
- { PR_5_INODE_BITMAP_END,
- "\n",
- PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Free inodes count for group wrong */
- { PR_5_FREE_INODE_COUNT_GROUP,
- N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
- PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Directories count for group wrong */
- { PR_5_FREE_DIR_COUNT_GROUP,
- N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
- PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Free inodes count wrong */
- { PR_5_FREE_INODE_COUNT,
- N_("Free @is count wrong (%i, counted=%j).\n"),
- PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Free blocks count for group wrong */
- { PR_5_FREE_BLOCK_COUNT_GROUP,
- N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
- PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Free blocks count wrong */
- { PR_5_FREE_BLOCK_COUNT,
- N_("Free @bs count wrong (%b, counted=%c).\n"),
- PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Programming error: bitmap endpoints don't match */
- { PR_5_BMAP_ENDPOINTS,
- N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
- "match calculated @B endpoints (%i, %j)\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Internal error: fudging end of bitmap */
- { PR_5_FUDGE_BITMAP_ERROR,
- N_("Internal error: fudging end of bitmap (%N)\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error copying in replacement inode bitmap */
- { PR_5_COPY_IBITMAP_ERROR,
- N_("Error copying in replacement @i @B: %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error copying in replacement block bitmap */
- { PR_5_COPY_BBITMAP_ERROR,
- N_("Error copying in replacement @b @B: %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Block range not used, but marked in bitmap */
- { PR_5_BLOCK_RANGE_UNUSED,
- " -(%b--%c)",
- PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Block range used, but not marked used in bitmap */
- { PR_5_BLOCK_RANGE_USED,
- " +(%b--%c)",
- PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Inode range not used, but marked in bitmap */
- { PR_5_INODE_RANGE_UNUSED,
- " -(%i--%j)",
- PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Inode range used, but not marked used in bitmap */
- { PR_5_INODE_RANGE_USED,
- " +(%i--%j)",
- PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
-
- { 0 }
-};
-
-/*
- * This is the latch flags register. It allows several problems to be
- * "latched" together. This means that the user has to answer but one
- * question for the set of problems, and all of the associated
- * problems will be either fixed or not fixed.
- */
-static struct latch_descr pr_latch_info[] = {
- { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
- { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
- { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
- { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
- { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
- { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
- { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
- { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
- { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
- { -1, 0, 0 },
-};
-
-static const struct e2fsck_problem *find_problem(problem_t code)
-{
- int i;
-
- for (i=0; problem_table[i].e2p_code; i++) {
- if (problem_table[i].e2p_code == code)
- return &problem_table[i];
- }
- return 0;
-}
-
-static struct latch_descr *find_latch(int code)
-{
- int i;
-
- for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
- if (pr_latch_info[i].latch_code == code)
- return &pr_latch_info[i];
- }
- return 0;
-}
-
-int end_problem_latch(e2fsck_t ctx, int mask)
-{
- struct latch_descr *ldesc;
- struct problem_context pctx;
- int answer = -1;
-
- ldesc = find_latch(mask);
- if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
- clear_problem_context(&pctx);
- answer = fix_problem(ctx, ldesc->end_message, &pctx);
- }
- ldesc->flags &= ~(PRL_VARIABLE);
- return answer;
-}
-
-int set_latch_flags(int mask, int setflags, int clearflags)
-{
- struct latch_descr *ldesc;
-
- ldesc = find_latch(mask);
- if (!ldesc)
- return -1;
- ldesc->flags |= setflags;
- ldesc->flags &= ~clearflags;
- return 0;
-}
-
-void clear_problem_context(struct problem_context *ctx)
-{
- memset(ctx, 0, sizeof(struct problem_context));
- ctx->blkcount = -1;
- ctx->group = -1;
-}
-
-int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
-{
- ext2_filsys fs = ctx->fs;
- const struct e2fsck_problem *ptr;
- struct latch_descr *ldesc = NULL;
- const char *message;
- int def_yn, answer, ans;
- int print_answer = 0;
- int suppress = 0;
-
- ptr = find_problem(code);
- if (!ptr) {
- printf(_("Unhandled error code (0x%x)!\n"), code);
- return 0;
- }
- def_yn = 1;
- if ((ptr->flags & PR_NO_DEFAULT) ||
- ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
- (ctx->options & E2F_OPT_NO))
- def_yn= 0;
-
- /*
- * Do special latch processing. This is where we ask the
- * latch question, if it exists
- */
- if (ptr->flags & PR_LATCH_MASK) {
- ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
- if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
- ans = fix_problem(ctx, ldesc->question, pctx);
- if (ans == 1)
- ldesc->flags |= PRL_YES;
- if (ans == 0)
- ldesc->flags |= PRL_NO;
- ldesc->flags |= PRL_LATCHED;
- }
- if (ldesc->flags & PRL_SUPPRESS)
- suppress++;
- }
- if ((ptr->flags & PR_PREEN_NOMSG) &&
- (ctx->options & E2F_OPT_PREEN))
- suppress++;
- if ((ptr->flags & PR_NO_NOMSG) &&
- (ctx->options & E2F_OPT_NO))
- suppress++;
- if (!suppress) {
- message = ptr->e2p_description;
- if ((ctx->options & E2F_OPT_PREEN) &&
- !(ptr->flags & PR_PREEN_NOHDR)) {
- printf("%s: ", ctx->device_name ?
- ctx->device_name : ctx->filesystem_name);
- }
- if (*message)
- print_e2fsck_message(ctx, _(message), pctx, 1);
- }
- if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
- preenhalt(ctx);
-
- if (ptr->flags & PR_FATAL)
- bb_error_msg_and_die(0);
-
- if (ptr->prompt == PROMPT_NONE) {
- if (ptr->flags & PR_NOCOLLATE)
- answer = -1;
- else
- answer = def_yn;
- } else {
- if (ctx->options & E2F_OPT_PREEN) {
- answer = def_yn;
- if (!(ptr->flags & PR_PREEN_NOMSG))
- print_answer = 1;
- } else if ((ptr->flags & PR_LATCH_MASK) &&
- (ldesc->flags & (PRL_YES | PRL_NO))) {
- if (!suppress)
- print_answer = 1;
- if (ldesc->flags & PRL_YES)
- answer = 1;
- else
- answer = 0;
- } else
- answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
- if (!answer && !(ptr->flags & PR_NO_OK))
- ext2fs_unmark_valid(fs);
-
- if (print_answer)
- printf("%s.\n", answer ?
- _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
- }
-
- if ((ptr->prompt == PROMPT_ABORT) && answer)
- bb_error_msg_and_die(0);
-
- if (ptr->flags & PR_AFTER_CODE)
- answer = fix_problem(ctx, ptr->second_code, pctx);
-
- return answer;
-}
-
-/*
- * linux/fs/recovery.c
- *
- * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
- */
-
-/*
- * Maintain information about the progress of the recovery job, so that
- * the different passes can carry information between them.
- */
-struct recovery_info
-{
- tid_t start_transaction;
- tid_t end_transaction;
-
- int nr_replays;
- int nr_revokes;
- int nr_revoke_hits;
-};
-
-enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
-static int do_one_pass(journal_t *journal,
- struct recovery_info *info, enum passtype pass);
-static int scan_revoke_records(journal_t *, struct buffer_head *,
- tid_t, struct recovery_info *);
-
-/*
- * Read a block from the journal
- */
-
-static int jread(struct buffer_head **bhp, journal_t *journal,
- unsigned int offset)
-{
- int err;
- unsigned long blocknr;
- struct buffer_head *bh;
-
- *bhp = NULL;
-
- err = journal_bmap(journal, offset, &blocknr);
-
- if (err) {
- printf("JBD: bad block at offset %u\n", offset);
- return err;
- }
-
- bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
- if (!bh)
- return -ENOMEM;
-
- if (!buffer_uptodate(bh)) {
- /* If this is a brand new buffer, start readahead.
- Otherwise, we assume we are already reading it. */
- if (!buffer_req(bh))
- do_readahead(journal, offset);
- wait_on_buffer(bh);
- }
-
- if (!buffer_uptodate(bh)) {
- printf("JBD: Failed to read block at offset %u\n", offset);
- brelse(bh);
- return -EIO;
- }
-
- *bhp = bh;
- return 0;
-}
-
-
-/*
- * Count the number of in-use tags in a journal descriptor block.
- */
-
-static int count_tags(struct buffer_head *bh, int size)
-{
- char * tagp;
- journal_block_tag_t * tag;
- int nr = 0;
-
- tagp = &bh->b_data[sizeof(journal_header_t)];
-
- while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
- tag = (journal_block_tag_t *) tagp;
-
- nr++;
- tagp += sizeof(journal_block_tag_t);
- if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
- tagp += 16;
-
- if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
- break;
- }
-
- return nr;
-}
-
-
-/* Make sure we wrap around the log correctly! */
-#define wrap(journal, var) \
-do { \
- if (var >= (journal)->j_last) \
- var -= ((journal)->j_last - (journal)->j_first); \
-} while (0)
-
-/**
- * int journal_recover(journal_t *journal) - recovers a on-disk journal
- * @journal: the journal to recover
- *
- * The primary function for recovering the log contents when mounting a
- * journaled device.
- *
- * Recovery is done in three passes. In the first pass, we look for the
- * end of the log. In the second, we assemble the list of revoke
- * blocks. In the third and final pass, we replay any un-revoked blocks
- * in the log.
- */
-int journal_recover(journal_t *journal)
-{
- int err;
- journal_superblock_t * sb;
-
- struct recovery_info info;
-
- memset(&info, 0, sizeof(info));
- sb = journal->j_superblock;
-
- /*
- * The journal superblock's s_start field (the current log head)
- * is always zero if, and only if, the journal was cleanly
- * unmounted.
- */
-
- if (!sb->s_start) {
- journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
- return 0;
- }
-
- err = do_one_pass(journal, &info, PASS_SCAN);
- if (!err)
- err = do_one_pass(journal, &info, PASS_REVOKE);
- if (!err)
- err = do_one_pass(journal, &info, PASS_REPLAY);
-
- /* Restart the log at the next transaction ID, thus invalidating
- * any existing commit records in the log. */
- journal->j_transaction_sequence = ++info.end_transaction;
-
- journal_clear_revoke(journal);
- sync_blockdev(journal->j_fs_dev);
- return err;
-}
-
-static int do_one_pass(journal_t *journal,
- struct recovery_info *info, enum passtype pass)
-{
- unsigned int first_commit_ID, next_commit_ID;
- unsigned long next_log_block;
- int err, success = 0;
- journal_superblock_t * sb;
- journal_header_t * tmp;
- struct buffer_head * bh;
- unsigned int sequence;
- int blocktype;
-
- /* Precompute the maximum metadata descriptors in a descriptor block */
- int MAX_BLOCKS_PER_DESC;
- MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
- / sizeof(journal_block_tag_t));
-
- /*
- * First thing is to establish what we expect to find in the log
- * (in terms of transaction IDs), and where (in terms of log
- * block offsets): query the superblock.
- */
-
- sb = journal->j_superblock;
- next_commit_ID = ntohl(sb->s_sequence);
- next_log_block = ntohl(sb->s_start);
-
- first_commit_ID = next_commit_ID;
- if (pass == PASS_SCAN)
- info->start_transaction = first_commit_ID;
-
- /*
- * Now we walk through the log, transaction by transaction,
- * making sure that each transaction has a commit block in the
- * expected place. Each complete transaction gets replayed back
- * into the main filesystem.
- */
-
- while (1) {
- int flags;
- char * tagp;
- journal_block_tag_t * tag;
- struct buffer_head * obh;
- struct buffer_head * nbh;
-
- /* If we already know where to stop the log traversal,
- * check right now that we haven't gone past the end of
- * the log. */
-
- if (pass != PASS_SCAN)
- if (tid_geq(next_commit_ID, info->end_transaction))
- break;
-
- /* Skip over each chunk of the transaction looking
- * either the next descriptor block or the final commit
- * record. */
-
- err = jread(&bh, journal, next_log_block);
- if (err)
- goto failed;
-
- next_log_block++;
- wrap(journal, next_log_block);
-
- /* What kind of buffer is it?
- *
- * If it is a descriptor block, check that it has the
- * expected sequence number. Otherwise, we're all done
- * here. */
-
- tmp = (journal_header_t *)bh->b_data;
-
- if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
- brelse(bh);
- break;
- }
-
- blocktype = ntohl(tmp->h_blocktype);
- sequence = ntohl(tmp->h_sequence);
-
- if (sequence != next_commit_ID) {
- brelse(bh);
- break;
- }
-
- /* OK, we have a valid descriptor block which matches
- * all of the sequence number checks. What are we going
- * to do with it? That depends on the pass... */
-
- switch (blocktype) {
- case JFS_DESCRIPTOR_BLOCK:
- /* If it is a valid descriptor block, replay it
- * in pass REPLAY; otherwise, just skip over the
- * blocks it describes. */
- if (pass != PASS_REPLAY) {
- next_log_block +=
- count_tags(bh, journal->j_blocksize);
- wrap(journal, next_log_block);
- brelse(bh);
- continue;
- }
-
- /* A descriptor block: we can now write all of
- * the data blocks. Yay, useful work is finally
- * getting done here! */
-
- tagp = &bh->b_data[sizeof(journal_header_t)];
- while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
- <= journal->j_blocksize) {
- unsigned long io_block;
-
- tag = (journal_block_tag_t *) tagp;
- flags = ntohl(tag->t_flags);
-
- io_block = next_log_block++;
- wrap(journal, next_log_block);
- err = jread(&obh, journal, io_block);
- if (err) {
- /* Recover what we can, but
- * report failure at the end. */
- success = err;
- printf("JBD: IO error %d recovering "
- "block %ld in log\n",
- err, io_block);
- } else {
- unsigned long blocknr;
-
- blocknr = ntohl(tag->t_blocknr);
-
- /* If the block has been
- * revoked, then we're all done
- * here. */
- if (journal_test_revoke
- (journal, blocknr,
- next_commit_ID)) {
- brelse(obh);
- ++info->nr_revoke_hits;
- goto skip_write;
- }
-
- /* Find a buffer for the new
- * data being restored */
- nbh = getblk(journal->j_fs_dev,
- blocknr,
- journal->j_blocksize);
- if (nbh == NULL) {
- printf("JBD: Out of memory "
- "during recovery.\n");
- err = -ENOMEM;
- brelse(bh);
- brelse(obh);
- goto failed;
- }
-
- lock_buffer(nbh);
- memcpy(nbh->b_data, obh->b_data,
- journal->j_blocksize);
- if (flags & JFS_FLAG_ESCAPE) {
- *((unsigned int *)bh->b_data) =
- htonl(JFS_MAGIC_NUMBER);
- }
-
- mark_buffer_uptodate(nbh, 1);
- mark_buffer_dirty(nbh);
- ++info->nr_replays;
- /* ll_rw_block(WRITE, 1, &nbh); */
- unlock_buffer(nbh);
- brelse(obh);
- brelse(nbh);
- }
-
- skip_write:
- tagp += sizeof(journal_block_tag_t);
- if (!(flags & JFS_FLAG_SAME_UUID))
- tagp += 16;
-
- if (flags & JFS_FLAG_LAST_TAG)
- break;
- }
-
- brelse(bh);
- continue;
-
- case JFS_COMMIT_BLOCK:
- /* Found an expected commit block: not much to
- * do other than move on to the next sequence
- * number. */
- brelse(bh);
- next_commit_ID++;
- continue;
-
- case JFS_REVOKE_BLOCK:
- /* If we aren't in the REVOKE pass, then we can
- * just skip over this block. */
- if (pass != PASS_REVOKE) {
- brelse(bh);
- continue;
- }
-
- err = scan_revoke_records(journal, bh,
- next_commit_ID, info);
- brelse(bh);
- if (err)
- goto failed;
- continue;
-
- default:
- goto done;
- }
- }
-
- done:
- /*
- * We broke out of the log scan loop: either we came to the
- * known end of the log or we found an unexpected block in the
- * log. If the latter happened, then we know that the "current"
- * transaction marks the end of the valid log.
- */
-
- if (pass == PASS_SCAN)
- info->end_transaction = next_commit_ID;
- else {
- /* It's really bad news if different passes end up at
- * different places (but possible due to IO errors). */
- if (info->end_transaction != next_commit_ID) {
- printf("JBD: recovery pass %d ended at "
- "transaction %u, expected %u\n",
- pass, next_commit_ID, info->end_transaction);
- if (!success)
- success = -EIO;
- }
- }
-
- return success;
-
- failed:
- return err;
-}
-
-
-/* Scan a revoke record, marking all blocks mentioned as revoked. */
-
-static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
- tid_t sequence, struct recovery_info *info)
-{
- journal_revoke_header_t *header;
- int offset, max;
-
- header = (journal_revoke_header_t *) bh->b_data;
- offset = sizeof(journal_revoke_header_t);
- max = ntohl(header->r_count);
-
- while (offset < max) {
- unsigned long blocknr;
- int err;
-
- blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
- offset += 4;
- err = journal_set_revoke(journal, blocknr, sequence);
- if (err)
- return err;
- ++info->nr_revokes;
- }
- return 0;
-}
-
-
-/*
- * rehash.c --- rebuild hash tree directories
- *
- * This algorithm is designed for simplicity of implementation and to
- * pack the directory as much as possible. It however requires twice
- * as much memory as the size of the directory. The maximum size
- * directory supported using a 4k blocksize is roughly a gigabyte, and
- * so there may very well be problems with machines that don't have
- * virtual memory, and obscenely large directories.
- *
- * An alternate algorithm which is much more disk intensive could be
- * written, and probably will need to be written in the future. The
- * design goals of such an algorithm are: (a) use (roughly) constant
- * amounts of memory, no matter how large the directory, (b) the
- * directory must be safe at all times, even if e2fsck is interrupted
- * in the middle, (c) we must use minimal amounts of extra disk
- * blocks. This pretty much requires an incremental approach, where
- * we are reading from one part of the directory, and inserting into
- * the front half. So the algorithm will have to keep track of a
- * moving block boundary between the new tree and the old tree, and
- * files will need to be moved from the old directory and inserted
- * into the new tree. If the new directory requires space which isn't
- * yet available, blocks from the beginning part of the old directory
- * may need to be moved to the end of the directory to make room for
- * the new tree:
- *
- * --------------------------------------------------------
- * | new tree | | old tree |
- * --------------------------------------------------------
- * ^ ptr ^ptr
- * tail new head old
- *
- * This is going to be a pain in the tuckus to implement, and will
- * require a lot more disk accesses. So I'm going to skip it for now;
- * it's only really going to be an issue for really, really big
- * filesystems (when we reach the level of tens of millions of files
- * in a single directory). It will probably be easier to simply
- * require that e2fsck use VM first.
- */
-
-struct fill_dir_struct {
- char *buf;
- struct ext2_inode *inode;
- int err;
- e2fsck_t ctx;
- struct hash_entry *harray;
- int max_array, num_array;
- int dir_size;
- int compress;
- ino_t parent;
-};
-
-struct hash_entry {
- ext2_dirhash_t hash;
- ext2_dirhash_t minor_hash;
- struct ext2_dir_entry *dir;
-};
-
-struct out_dir {
- int num;
- int max;
- char *buf;
- ext2_dirhash_t *hashes;
-};
-
-static int fill_dir_block(ext2_filsys fs,
- blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block FSCK_ATTR((unused)),
- int ref_offset FSCK_ATTR((unused)),
- void *priv_data)
-{
- struct fill_dir_struct *fd = (struct fill_dir_struct *) priv_data;
- struct hash_entry *new_array, *ent;
- struct ext2_dir_entry *dirent;
- char *dir;
- unsigned int offset, dir_offset;
-
- if (blockcnt < 0)
- return 0;
-
- offset = blockcnt * fs->blocksize;
- if (offset + fs->blocksize > fd->inode->i_size) {
- fd->err = EXT2_ET_DIR_CORRUPTED;
- return BLOCK_ABORT;
- }
- dir = (fd->buf+offset);
- if (HOLE_BLKADDR(*block_nr)) {
- memset(dir, 0, fs->blocksize);
- dirent = (struct ext2_dir_entry *) dir;
- dirent->rec_len = fs->blocksize;
- } else {
- fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
- if (fd->err)
- return BLOCK_ABORT;
- }
- /* While the directory block is "hot", index it. */
- dir_offset = 0;
- while (dir_offset < fs->blocksize) {
- dirent = (struct ext2_dir_entry *) (dir + dir_offset);
- if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
- (dirent->rec_len < 8) ||
- ((dirent->rec_len % 4) != 0) ||
- (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
- fd->err = EXT2_ET_DIR_CORRUPTED;
- return BLOCK_ABORT;
- }
- dir_offset += dirent->rec_len;
- if (dirent->inode == 0)
- continue;
- if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
- (dirent->name[0] == '.'))
- continue;
- if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
- (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
- fd->parent = dirent->inode;
- continue;
- }
- if (fd->num_array >= fd->max_array) {
- new_array = xrealloc(fd->harray,
- sizeof(struct hash_entry) * (fd->max_array+500));
- fd->harray = new_array;
- fd->max_array += 500;
- }
- ent = fd->harray + fd->num_array++;
- ent->dir = dirent;
- fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
- if (fd->compress)
- ent->hash = ent->minor_hash = 0;
- else {
- fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
- dirent->name,
- dirent->name_len & 0xFF,
- fs->super->s_hash_seed,
- &ent->hash, &ent->minor_hash);
- if (fd->err)
- return BLOCK_ABORT;
- }
- }
-
- return 0;
-}
-
-/* Used for sorting the hash entry */
-static int name_cmp(const void *a, const void *b)
-{
- const struct hash_entry *he_a = (const struct hash_entry *) a;
- const struct hash_entry *he_b = (const struct hash_entry *) b;
- int ret;
- int min_len;
-
- min_len = he_a->dir->name_len;
- if (min_len > he_b->dir->name_len)
- min_len = he_b->dir->name_len;
-
- ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
- if (ret == 0) {
- if (he_a->dir->name_len > he_b->dir->name_len)
- ret = 1;
- else if (he_a->dir->name_len < he_b->dir->name_len)
- ret = -1;
- else
- ret = he_b->dir->inode - he_a->dir->inode;
- }
- return ret;
-}
-
-/* Used for sorting the hash entry */
-static int hash_cmp(const void *a, const void *b)
-{
- const struct hash_entry *he_a = (const struct hash_entry *) a;
- const struct hash_entry *he_b = (const struct hash_entry *) b;
- int ret;
-
- if (he_a->hash > he_b->hash)
- ret = 1;
- else if (he_a->hash < he_b->hash)
- ret = -1;
- else {
- if (he_a->minor_hash > he_b->minor_hash)
- ret = 1;
- else if (he_a->minor_hash < he_b->minor_hash)
- ret = -1;
- else
- ret = name_cmp(a, b);
- }
- return ret;
-}
-
-static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
- int blocks)
-{
- void *new_mem;
-
- if (outdir->max) {
- new_mem = xrealloc(outdir->buf, blocks * fs->blocksize);
- outdir->buf = new_mem;
- new_mem = xrealloc(outdir->hashes,
- blocks * sizeof(ext2_dirhash_t));
- outdir->hashes = new_mem;
- } else {
- outdir->buf = xmalloc(blocks * fs->blocksize);
- outdir->hashes = xmalloc(blocks * sizeof(ext2_dirhash_t));
- outdir->num = 0;
- }
- outdir->max = blocks;
- return 0;
-}
-
-static void free_out_dir(struct out_dir *outdir)
-{
- free(outdir->buf);
- free(outdir->hashes);
- outdir->max = 0;
- outdir->num =0;
-}
-
-static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
- char ** ret)
-{
- errcode_t retval;
-
- if (outdir->num >= outdir->max) {
- retval = alloc_size_dir(fs, outdir, outdir->max + 50);
- if (retval)
- return retval;
- }
- *ret = outdir->buf + (outdir->num++ * fs->blocksize);
- memset(*ret, 0, fs->blocksize);
- return 0;
-}
-
-/*
- * This function is used to make a unique filename. We do this by
- * appending ~0, and then incrementing the number. However, we cannot
- * expand the length of the filename beyond the padding available in
- * the directory entry.
- */
-static void mutate_name(char *str, __u16 *len)
-{
- int i;
- __u16 l = *len & 0xFF, h = *len & 0xff00;
-
- /*
- * First check to see if it looks the name has been mutated
- * already
- */
- for (i = l-1; i > 0; i--) {
- if (!isdigit(str[i]))
- break;
- }
- if ((i == l-1) || (str[i] != '~')) {
- if (((l-1) & 3) < 2)
- l += 2;
- else
- l = (l+3) & ~3;
- str[l-2] = '~';
- str[l-1] = '0';
- *len = l | h;
- return;
- }
- for (i = l-1; i >= 0; i--) {
- if (isdigit(str[i])) {
- if (str[i] == '9')
- str[i] = '0';
- else {
- str[i]++;
- return;
- }
- continue;
- }
- if (i == 1) {
- if (str[0] == 'z')
- str[0] = 'A';
- else if (str[0] == 'Z') {
- str[0] = '~';
- str[1] = '0';
- } else
- str[0]++;
- } else if (i > 0) {
- str[i] = '1';
- str[i-1] = '~';
- } else {
- if (str[0] == '~')
- str[0] = 'a';
- else
- str[0]++;
- }
- break;
- }
-}
-
-static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
- ext2_ino_t ino,
- struct fill_dir_struct *fd)
-{
- struct problem_context pctx;
- struct hash_entry *ent, *prev;
- int i, j;
- int fixed = 0;
- char new_name[256];
- __u16 new_len;
-
- clear_problem_context(&pctx);
- pctx.ino = ino;
-
- for (i=1; i < fd->num_array; i++) {
- ent = fd->harray + i;
- prev = ent - 1;
- if (!ent->dir->inode ||
- ((ent->dir->name_len & 0xFF) !=
- (prev->dir->name_len & 0xFF)) ||
- (strncmp(ent->dir->name, prev->dir->name,
- ent->dir->name_len & 0xFF)))
- continue;
- pctx.dirent = ent->dir;
- if ((ent->dir->inode == prev->dir->inode) &&
- fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
- e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
- ent->dir->inode = 0;
- fixed++;
- continue;
- }
- memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
- new_len = ent->dir->name_len;
- mutate_name(new_name, &new_len);
- for (j=0; j < fd->num_array; j++) {
- if ((i==j) ||
- ((ent->dir->name_len & 0xFF) !=
- (fd->harray[j].dir->name_len & 0xFF)) ||
- (strncmp(new_name, fd->harray[j].dir->name,
- new_len & 0xFF)))
- continue;
- mutate_name(new_name, &new_len);
-
- j = -1;
- }
- new_name[new_len & 0xFF] = 0;
- pctx.str = new_name;
- if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
- memcpy(ent->dir->name, new_name, new_len & 0xFF);
- ent->dir->name_len = new_len;
- ext2fs_dirhash(fs->super->s_def_hash_version,
- ent->dir->name,
- ent->dir->name_len & 0xFF,
- fs->super->s_hash_seed,
- &ent->hash, &ent->minor_hash);
- fixed++;
- }
- }
- return fixed;
-}
-
-
-static errcode_t copy_dir_entries(ext2_filsys fs,
- struct fill_dir_struct *fd,
- struct out_dir *outdir)
-{
- errcode_t retval;
- char *block_start;
- struct hash_entry *ent;
- struct ext2_dir_entry *dirent;
- int i, rec_len, left;
- ext2_dirhash_t prev_hash;
- int offset;
-
- outdir->max = 0;
- retval = alloc_size_dir(fs, outdir,
- (fd->dir_size / fs->blocksize) + 2);
- if (retval)
- return retval;
- outdir->num = fd->compress ? 0 : 1;
- offset = 0;
- outdir->hashes[0] = 0;
- prev_hash = 1;
- if ((retval = get_next_block(fs, outdir, &block_start)))
- return retval;
- dirent = (struct ext2_dir_entry *) block_start;
- left = fs->blocksize;
- for (i=0; i < fd->num_array; i++) {
- ent = fd->harray + i;
- if (ent->dir->inode == 0)
- continue;
- rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
- if (rec_len > left) {
- if (left)
- dirent->rec_len += left;
- if ((retval = get_next_block(fs, outdir,
- &block_start)))
- return retval;
- offset = 0;
- }
- left = fs->blocksize - offset;
- dirent = (struct ext2_dir_entry *) (block_start + offset);
- if (offset == 0) {
- if (ent->hash == prev_hash)
- outdir->hashes[outdir->num-1] = ent->hash | 1;
- else
- outdir->hashes[outdir->num-1] = ent->hash;
- }
- dirent->inode = ent->dir->inode;
- dirent->name_len = ent->dir->name_len;
- dirent->rec_len = rec_len;
- memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
- offset += rec_len;
- left -= rec_len;
- if (left < 12) {
- dirent->rec_len += left;
- offset += left;
- left = 0;
- }
- prev_hash = ent->hash;
- }
- if (left)
- dirent->rec_len += left;
-
- return 0;
-}
-
-
-static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
- ext2_ino_t ino, ext2_ino_t parent)
-{
- struct ext2_dir_entry *dir;
- struct ext2_dx_root_info *root;
- struct ext2_dx_countlimit *limits;
- int filetype = 0;
-
- if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
- filetype = EXT2_FT_DIR << 8;
-
- memset(buf, 0, fs->blocksize);
- dir = (struct ext2_dir_entry *) buf;
- dir->inode = ino;
- dir->name[0] = '.';
- dir->name_len = 1 | filetype;
- dir->rec_len = 12;
- dir = (struct ext2_dir_entry *) (buf + 12);
- dir->inode = parent;
- dir->name[0] = '.';
- dir->name[1] = '.';
- dir->name_len = 2 | filetype;
- dir->rec_len = fs->blocksize - 12;
-
- root = (struct ext2_dx_root_info *) (buf+24);
- root->reserved_zero = 0;
- root->hash_version = fs->super->s_def_hash_version;
- root->info_length = 8;
- root->indirect_levels = 0;
- root->unused_flags = 0;
-
- limits = (struct ext2_dx_countlimit *) (buf+32);
- limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
- limits->count = 0;
-
- return root;
-}
-
-
-static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
-{
- struct ext2_dir_entry *dir;
- struct ext2_dx_countlimit *limits;
-
- memset(buf, 0, fs->blocksize);
- dir = (struct ext2_dir_entry *) buf;
- dir->inode = 0;
- dir->rec_len = fs->blocksize;
-
- limits = (struct ext2_dx_countlimit *) (buf+8);
- limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
- limits->count = 0;
-
- return (struct ext2_dx_entry *) limits;
-}
-
-/*
- * This function takes the leaf nodes which have been written in
- * outdir, and populates the root node and any necessary interior nodes.
- */
-static errcode_t calculate_tree(ext2_filsys fs,
- struct out_dir *outdir,
- ext2_ino_t ino,
- ext2_ino_t parent)
-{
- struct ext2_dx_root_info *root_info;
- struct ext2_dx_entry *root, *dx_ent = NULL;
- struct ext2_dx_countlimit *root_limit, *limit;
- errcode_t retval;
- char * block_start;
- int i, c1, c2, nblks;
- int limit_offset, root_offset;
-
- root_info = set_root_node(fs, outdir->buf, ino, parent);
- root_offset = limit_offset = ((char *) root_info - outdir->buf) +
- root_info->info_length;
- root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
- c1 = root_limit->limit;
- nblks = outdir->num;
-
- /* Write out the pointer blocks */
- if (nblks-1 <= c1) {
- /* Just write out the root block, and we're done */
- root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
- for (i=1; i < nblks; i++) {
- root->block = ext2fs_cpu_to_le32(i);
- if (i != 1)
- root->hash =
- ext2fs_cpu_to_le32(outdir->hashes[i]);
- root++;
- c1--;
- }
- } else {
- c2 = 0;
- limit = 0;
- root_info->indirect_levels = 1;
- for (i=1; i < nblks; i++) {
- if (c1 == 0)
- return ENOSPC;
- if (c2 == 0) {
- if (limit)
- limit->limit = limit->count =
- ext2fs_cpu_to_le16(limit->limit);
- root = (struct ext2_dx_entry *)
- (outdir->buf + root_offset);
- root->block = ext2fs_cpu_to_le32(outdir->num);
- if (i != 1)
- root->hash =
- ext2fs_cpu_to_le32(outdir->hashes[i]);
- if ((retval = get_next_block(fs, outdir,
- &block_start)))
- return retval;
- dx_ent = set_int_node(fs, block_start);
- limit = (struct ext2_dx_countlimit *) dx_ent;
- c2 = limit->limit;
- root_offset += sizeof(struct ext2_dx_entry);
- c1--;
- }
- dx_ent->block = ext2fs_cpu_to_le32(i);
- if (c2 != limit->limit)
- dx_ent->hash =
- ext2fs_cpu_to_le32(outdir->hashes[i]);
- dx_ent++;
- c2--;
- }
- limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
- limit->limit = ext2fs_cpu_to_le16(limit->limit);
- }
- root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
- root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
- root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
-
- return 0;
-}
-
-struct write_dir_struct {
- struct out_dir *outdir;
- errcode_t err;
- e2fsck_t ctx;
- int cleared;
-};
-
-/*
- * Helper function which writes out a directory block.
- */
-static int write_dir_block(ext2_filsys fs,
- blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block FSCK_ATTR((unused)),
- int ref_offset FSCK_ATTR((unused)),
- void *priv_data)
-{
- struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
- blk_t blk;
- char *dir;
-
- if (*block_nr == 0)
- return 0;
- if (blockcnt >= wd->outdir->num) {
- e2fsck_read_bitmaps(wd->ctx);
- blk = *block_nr;
- ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
- ext2fs_block_alloc_stats(fs, blk, -1);
- *block_nr = 0;
- wd->cleared++;
- return BLOCK_CHANGED;
- }
- if (blockcnt < 0)
- return 0;
-
- dir = wd->outdir->buf + (blockcnt * fs->blocksize);
- wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
- if (wd->err)
- return BLOCK_ABORT;
- return 0;
-}
-
-static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
- struct out_dir *outdir,
- ext2_ino_t ino, int compress)
-{
- struct write_dir_struct wd;
- errcode_t retval;
- struct ext2_inode inode;
-
- retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
- if (retval)
- return retval;
-
- wd.outdir = outdir;
- wd.err = 0;
- wd.ctx = ctx;
- wd.cleared = 0;
-
- retval = ext2fs_block_iterate2(fs, ino, 0, 0,
- write_dir_block, &wd);
- if (retval)
- return retval;
- if (wd.err)
- return wd.err;
-
- e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
- if (compress)
- inode.i_flags &= ~EXT2_INDEX_FL;
- else
- inode.i_flags |= EXT2_INDEX_FL;
- inode.i_size = outdir->num * fs->blocksize;
- inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
- e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
-
- return 0;
-}
-
-static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
-{
- ext2_filsys fs = ctx->fs;
- errcode_t retval;
- struct ext2_inode inode;
- char *dir_buf = NULL;
- struct fill_dir_struct fd;
- struct out_dir outdir;
-
- outdir.max = outdir.num = 0;
- outdir.buf = 0;
- outdir.hashes = 0;
- e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
-
- retval = ENOMEM;
- fd.harray = 0;
- dir_buf = xmalloc(inode.i_size);
-
- fd.max_array = inode.i_size / 32;
- fd.num_array = 0;
- fd.harray = xmalloc(fd.max_array * sizeof(struct hash_entry));
-
- fd.ctx = ctx;
- fd.buf = dir_buf;
- fd.inode = &inode;
- fd.err = 0;
- fd.dir_size = 0;
- fd.compress = 0;
- if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
- (inode.i_size / fs->blocksize) < 2)
- fd.compress = 1;
- fd.parent = 0;
-
- /* Read in the entire directory into memory */
- retval = ext2fs_block_iterate2(fs, ino, 0, 0,
- fill_dir_block, &fd);
- if (fd.err) {
- retval = fd.err;
- goto errout;
- }
-
- /* Sort the list */
-resort:
- if (fd.compress)
- qsort(fd.harray+2, fd.num_array-2,
- sizeof(struct hash_entry), name_cmp);
- else
- qsort(fd.harray, fd.num_array,
- sizeof(struct hash_entry), hash_cmp);
-
- /*
- * Look for duplicates
- */
- if (duplicate_search_and_fix(ctx, fs, ino, &fd))
- goto resort;
-
- if (ctx->options & E2F_OPT_NO) {
- retval = 0;
- goto errout;
- }
-
- /*
- * Copy the directory entries. In a htree directory these
- * will become the leaf nodes.
- */
- retval = copy_dir_entries(fs, &fd, &outdir);
- if (retval)
- goto errout;
-
- free(dir_buf); dir_buf = 0;
-
- if (!fd.compress) {
- /* Calculate the interior nodes */
- retval = calculate_tree(fs, &outdir, ino, fd.parent);
- if (retval)
- goto errout;
- }
-
- retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
-
-errout:
- free(dir_buf);
- free(fd.harray);
-
- free_out_dir(&outdir);
- return retval;
-}
-
-void e2fsck_rehash_directories(e2fsck_t ctx)
-{
- struct problem_context pctx;
- struct dir_info *dir;
- ext2_u32_iterate iter;
- ext2_ino_t ino;
- errcode_t retval;
- int i, cur, max, all_dirs, dir_index, first = 1;
-
- all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
-
- if (!ctx->dirs_to_hash && !all_dirs)
- return;
-
- e2fsck_get_lost_and_found(ctx, 0);
-
- clear_problem_context(&pctx);
-
- dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
- cur = 0;
- if (all_dirs) {
- i = 0;
- max = e2fsck_get_num_dirinfo(ctx);
- } else {
- retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
- &iter);
- if (retval) {
- pctx.errcode = retval;
- fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
- return;
- }
- max = ext2fs_u32_list_count(ctx->dirs_to_hash);
- }
- while (1) {
- if (all_dirs) {
- if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
- break;
- ino = dir->ino;
- } else {
- if (!ext2fs_u32_list_iterate(iter, &ino))
- break;
- }
- if (ino == ctx->lost_and_found)
- continue;
- pctx.dir = ino;
- if (first) {
- fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
- first = 0;
- }
- pctx.errcode = e2fsck_rehash_dir(ctx, ino);
- if (pctx.errcode) {
- end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
- fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
- }
- if (ctx->progress && !ctx->progress_fd)
- e2fsck_simple_progress(ctx, "Rebuilding directory",
- 100.0 * (float) (++cur) / (float) max, ino);
- }
- end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
- if (!all_dirs)
- ext2fs_u32_list_iterate_end(iter);
-
- ext2fs_u32_list_free(ctx->dirs_to_hash);
- ctx->dirs_to_hash = 0;
-}
-
-/*
- * linux/fs/revoke.c
- *
- * Journal revoke routines for the generic filesystem journaling code;
- * part of the ext2fs journaling system.
- *
- * Revoke is the mechanism used to prevent old log records for deleted
- * metadata from being replayed on top of newer data using the same
- * blocks. The revoke mechanism is used in two separate places:
- *
- * + Commit: during commit we write the entire list of the current
- * transaction's revoked blocks to the journal
- *
- * + Recovery: during recovery we record the transaction ID of all
- * revoked blocks. If there are multiple revoke records in the log
- * for a single block, only the last one counts, and if there is a log
- * entry for a block beyond the last revoke, then that log entry still
- * gets replayed.
- *
- * We can get interactions between revokes and new log data within a
- * single transaction:
- *
- * Block is revoked and then journaled:
- * The desired end result is the journaling of the new block, so we
- * cancel the revoke before the transaction commits.
- *
- * Block is journaled and then revoked:
- * The revoke must take precedence over the write of the block, so we
- * need either to cancel the journal entry or to write the revoke
- * later in the log than the log block. In this case, we choose the
- * latter: journaling a block cancels any revoke record for that block
- * in the current transaction, so any revoke for that block in the
- * transaction must have happened after the block was journaled and so
- * the revoke must take precedence.
- *
- * Block is revoked and then written as data:
- * The data write is allowed to succeed, but the revoke is _not_
- * cancelled. We still need to prevent old log records from
- * overwriting the new data. We don't even need to clear the revoke
- * bit here.
- *
- * Revoke information on buffers is a tri-state value:
- *
- * RevokeValid clear: no cached revoke status, need to look it up
- * RevokeValid set, Revoked clear:
- * buffer has not been revoked, and cancel_revoke
- * need do nothing.
- * RevokeValid set, Revoked set:
- * buffer has been revoked.
- */
-
-static kmem_cache_t *revoke_record_cache;
-static kmem_cache_t *revoke_table_cache;
-
-/* Each revoke record represents one single revoked block. During
- journal replay, this involves recording the transaction ID of the
- last transaction to revoke this block. */
-
-struct jbd_revoke_record_s
-{
- struct list_head hash;
- tid_t sequence; /* Used for recovery only */
- unsigned long blocknr;
-};
-
-
-/* The revoke table is just a simple hash table of revoke records. */
-struct jbd_revoke_table_s
-{
- /* It is conceivable that we might want a larger hash table
- * for recovery. Must be a power of two. */
- int hash_size;
- int hash_shift;
- struct list_head *hash_table;
-};
-
-
-/* Utility functions to maintain the revoke table */
-
-/* Borrowed from buffer.c: this is a tried and tested block hash function */
-static int hash(journal_t *journal, unsigned long block)
-{
- struct jbd_revoke_table_s *table = journal->j_revoke;
- int hash_shift = table->hash_shift;
-
- return ((block << (hash_shift - 6)) ^
- (block >> 13) ^
- (block << (hash_shift - 12))) & (table->hash_size - 1);
-}
-
-static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
- tid_t seq)
-{
- struct list_head *hash_list;
- struct jbd_revoke_record_s *record;
-
- record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
- if (!record)
- goto oom;
-
- record->sequence = seq;
- record->blocknr = blocknr;
- hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
- list_add(&record->hash, hash_list);
- return 0;
-
-oom:
- return -ENOMEM;
-}
-
-/* Find a revoke record in the journal's hash table. */
-
-static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
- unsigned long blocknr)
-{
- struct list_head *hash_list;
- struct jbd_revoke_record_s *record;
-
- hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
-
- record = (struct jbd_revoke_record_s *) hash_list->next;
- while (&(record->hash) != hash_list) {
- if (record->blocknr == blocknr)
- return record;
- record = (struct jbd_revoke_record_s *) record->hash.next;
- }
- return NULL;
-}
-
-int journal_init_revoke_caches(void)
-{
- revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
- if (revoke_record_cache == 0)
- return -ENOMEM;
-
- revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
- if (revoke_table_cache == 0) {
- do_cache_destroy(revoke_record_cache);
- revoke_record_cache = NULL;
- return -ENOMEM;
- }
- return 0;
-}
-
-void journal_destroy_revoke_caches(void)
-{
- do_cache_destroy(revoke_record_cache);
- revoke_record_cache = 0;
- do_cache_destroy(revoke_table_cache);
- revoke_table_cache = 0;
-}
-
-/* Initialise the revoke table for a given journal to a given size. */
-
-int journal_init_revoke(journal_t *journal, int hash_size)
-{
- int shift, tmp;
-
- journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
- if (!journal->j_revoke)
- return -ENOMEM;
-
- /* Check that the hash_size is a power of two */
- journal->j_revoke->hash_size = hash_size;
-
- shift = 0;
- tmp = hash_size;
- while ((tmp >>= 1UL) != 0UL)
- shift++;
- journal->j_revoke->hash_shift = shift;
-
- journal->j_revoke->hash_table = xmalloc(hash_size * sizeof(struct list_head));
-
- for (tmp = 0; tmp < hash_size; tmp++)
- INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
-
- return 0;
-}
-
-/* Destoy a journal's revoke table. The table must already be empty! */
-
-void journal_destroy_revoke(journal_t *journal)
-{
- struct jbd_revoke_table_s *table;
- struct list_head *hash_list;
- int i;
-
- table = journal->j_revoke;
- if (!table)
- return;
-
- for (i=0; i<table->hash_size; i++) {
- hash_list = &table->hash_table[i];
- }
-
- free(table->hash_table);
- free(table);
- journal->j_revoke = NULL;
-}
-
-/*
- * Revoke support for recovery.
- *
- * Recovery needs to be able to:
- *
- * record all revoke records, including the tid of the latest instance
- * of each revoke in the journal
- *
- * check whether a given block in a given transaction should be replayed
- * (ie. has not been revoked by a revoke record in that or a subsequent
- * transaction)
- *
- * empty the revoke table after recovery.
- */
-
-/*
- * First, setting revoke records. We create a new revoke record for
- * every block ever revoked in the log as we scan it for recovery, and
- * we update the existing records if we find multiple revokes for a
- * single block.
- */
-
-int journal_set_revoke(journal_t *journal, unsigned long blocknr,
- tid_t sequence)
-{
- struct jbd_revoke_record_s *record;
-
- record = find_revoke_record(journal, blocknr);
- if (record) {
- /* If we have multiple occurences, only record the
- * latest sequence number in the hashed record */
- if (tid_gt(sequence, record->sequence))
- record->sequence = sequence;
- return 0;
- }
- return insert_revoke_hash(journal, blocknr, sequence);
-}
-
-/*
- * Test revoke records. For a given block referenced in the log, has
- * that block been revoked? A revoke record with a given transaction
- * sequence number revokes all blocks in that transaction and earlier
- * ones, but later transactions still need replayed.
- */
-
-int journal_test_revoke(journal_t *journal, unsigned long blocknr,
- tid_t sequence)
-{
- struct jbd_revoke_record_s *record;
-
- record = find_revoke_record(journal, blocknr);
- if (!record)
- return 0;
- if (tid_gt(sequence, record->sequence))
- return 0;
- return 1;
-}
-
-/*
- * Finally, once recovery is over, we need to clear the revoke table so
- * that it can be reused by the running filesystem.
- */
-
-void journal_clear_revoke(journal_t *journal)
-{
- int i;
- struct list_head *hash_list;
- struct jbd_revoke_record_s *record;
- struct jbd_revoke_table_s *revoke_var;
-
- revoke_var = journal->j_revoke;
-
- for (i = 0; i < revoke_var->hash_size; i++) {
- hash_list = &revoke_var->hash_table[i];
- while (!list_empty(hash_list)) {
- record = (struct jbd_revoke_record_s*) hash_list->next;
- list_del(&record->hash);
- free(record);
- }
- }
-}
-
-/*
- * e2fsck.c - superblock checks
- */
-
-#define MIN_CHECK 1
-#define MAX_CHECK 2
-
-static void check_super_value(e2fsck_t ctx, const char *descr,
- unsigned long value, int flags,
- unsigned long min_val, unsigned long max_val)
-{
- struct problem_context pctx;
-
- if (((flags & MIN_CHECK) && (value < min_val)) ||
- ((flags & MAX_CHECK) && (value > max_val))) {
- clear_problem_context(&pctx);
- pctx.num = value;
- pctx.str = descr;
- fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
- ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
- }
-}
-
-/*
- * This routine may get stubbed out in special compilations of the
- * e2fsck code..
- */
-#ifndef EXT2_SPECIAL_DEVICE_SIZE
-static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
-{
- return (ext2fs_get_device_size(ctx->filesystem_name,
- EXT2_BLOCK_SIZE(ctx->fs->super),
- &ctx->num_blocks));
-}
-#endif
-
-/*
- * helper function to release an inode
- */
-struct process_block_struct {
- e2fsck_t ctx;
- char *buf;
- struct problem_context *pctx;
- int truncating;
- int truncate_offset;
- e2_blkcnt_t truncate_block;
- int truncated_blocks;
- int abort;
- errcode_t errcode;
-};
-
-static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_blk FSCK_ATTR((unused)),
- int ref_offset FSCK_ATTR((unused)),
- void *priv_data)
-{
- struct process_block_struct *pb;
- e2fsck_t ctx;
- struct problem_context *pctx;
- blk_t blk = *block_nr;
- int retval = 0;
-
- pb = (struct process_block_struct *) priv_data;
- ctx = pb->ctx;
- pctx = pb->pctx;
-
- pctx->blk = blk;
- pctx->blkcount = blockcnt;
-
- if (HOLE_BLKADDR(blk))
- return 0;
-
- if ((blk < fs->super->s_first_data_block) ||
- (blk >= fs->super->s_blocks_count)) {
- fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
- return_abort:
- pb->abort = 1;
- return BLOCK_ABORT;
- }
-
- if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
- fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
- goto return_abort;
- }
-
- /*
- * If we are deleting an orphan, then we leave the fields alone.
- * If we are truncating an orphan, then update the inode fields
- * and clean up any partial block data.
- */
- if (pb->truncating) {
- /*
- * We only remove indirect blocks if they are
- * completely empty.
- */
- if (blockcnt < 0) {
- int i, limit;
- blk_t *bp;
-
- pb->errcode = io_channel_read_blk(fs->io, blk, 1,
- pb->buf);
- if (pb->errcode)
- goto return_abort;
-
- limit = fs->blocksize >> 2;
- for (i = 0, bp = (blk_t *) pb->buf;
- i < limit; i++, bp++)
- if (*bp)
- return 0;
- }
- /*
- * We don't remove direct blocks until we've reached
- * the truncation block.
- */
- if (blockcnt >= 0 && blockcnt < pb->truncate_block)
- return 0;
- /*
- * If part of the last block needs truncating, we do
- * it here.
- */
- if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
- pb->errcode = io_channel_read_blk(fs->io, blk, 1,
- pb->buf);
- if (pb->errcode)
- goto return_abort;
- memset(pb->buf + pb->truncate_offset, 0,
- fs->blocksize - pb->truncate_offset);
- pb->errcode = io_channel_write_blk(fs->io, blk, 1,
- pb->buf);
- if (pb->errcode)
- goto return_abort;
- }
- pb->truncated_blocks++;
- *block_nr = 0;
- retval |= BLOCK_CHANGED;
- }
-
- ext2fs_block_alloc_stats(fs, blk, -1);
- return retval;
-}
-
-/*
- * This function releases an inode. Returns 1 if an inconsistency was
- * found. If the inode has a link count, then it is being truncated and
- * not deleted.
- */
-static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
- struct ext2_inode *inode, char *block_buf,
- struct problem_context *pctx)
-{
- struct process_block_struct pb;
- ext2_filsys fs = ctx->fs;
- errcode_t retval;
- __u32 count;
-
- if (!ext2fs_inode_has_valid_blocks(inode))
- return 0;
-
- pb.buf = block_buf + 3 * ctx->fs->blocksize;
- pb.ctx = ctx;
- pb.abort = 0;
- pb.errcode = 0;
- pb.pctx = pctx;
- if (inode->i_links_count) {
- pb.truncating = 1;
- pb.truncate_block = (e2_blkcnt_t)
- ((((long long)inode->i_size_high << 32) +
- inode->i_size + fs->blocksize - 1) /
- fs->blocksize);
- pb.truncate_offset = inode->i_size % fs->blocksize;
- } else {
- pb.truncating = 0;
- pb.truncate_block = 0;
- pb.truncate_offset = 0;
- }
- pb.truncated_blocks = 0;
- retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
- block_buf, release_inode_block, &pb);
- if (retval) {
- bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"),
- ino);
- return 1;
- }
- if (pb.abort)
- return 1;
-
- /* Refresh the inode since ext2fs_block_iterate may have changed it */
- e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
-
- if (pb.truncated_blocks)
- inode->i_blocks -= pb.truncated_blocks *
- (fs->blocksize / 512);
-
- if (inode->i_file_acl) {
- retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
- block_buf, -1, &count);
- if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
- retval = 0;
- count = 1;
- }
- if (retval) {
- bb_error_msg(_("while calling ext2fs_adjust_ea_refocunt for inode %d"),
- ino);
- return 1;
- }
- if (count == 0)
- ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
- inode->i_file_acl = 0;
- }
- return 0;
-}
-
-/*
- * This function releases all of the orphan inodes. It returns 1 if
- * it hit some error, and 0 on success.
- */
-static int release_orphan_inodes(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- ext2_ino_t ino, next_ino;
- struct ext2_inode inode;
- struct problem_context pctx;
- char *block_buf;
-
- if ((ino = fs->super->s_last_orphan) == 0)
- return 0;
-
- /*
- * Win or lose, we won't be using the head of the orphan inode
- * list again.
- */
- fs->super->s_last_orphan = 0;
- ext2fs_mark_super_dirty(fs);
-
- /*
- * If the filesystem contains errors, don't run the orphan
- * list, since the orphan list can't be trusted; and we're
- * going to be running a full e2fsck run anyway...
- */
- if (fs->super->s_state & EXT2_ERROR_FS)
- return 0;
-
- if ((ino < EXT2_FIRST_INODE(fs->super)) ||
- (ino > fs->super->s_inodes_count)) {
- clear_problem_context(&pctx);
- pctx.ino = ino;
- fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
- return 1;
- }
-
- block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
- "block iterate buffer");
- e2fsck_read_bitmaps(ctx);
-
- while (ino) {
- e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
- clear_problem_context(&pctx);
- pctx.ino = ino;
- pctx.inode = &inode;
- pctx.str = inode.i_links_count ? _("Truncating") :
- _("Clearing");
-
- fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
-
- next_ino = inode.i_dtime;
- if (next_ino &&
- ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
- (next_ino > fs->super->s_inodes_count))) {
- pctx.ino = next_ino;
- fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
- goto return_abort;
- }
-
- if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
- goto return_abort;
-
- if (!inode.i_links_count) {
- ext2fs_inode_alloc_stats2(fs, ino, -1,
- LINUX_S_ISDIR(inode.i_mode));
- inode.i_dtime = time(NULL);
- } else {
- inode.i_dtime = 0;
- }
- e2fsck_write_inode(ctx, ino, &inode, "delete_file");
- ino = next_ino;
- }
- ext2fs_free_mem(&block_buf);
- return 0;
- return_abort:
- ext2fs_free_mem(&block_buf);
- return 1;
-}
-
-/*
- * Check the resize inode to make sure it is sane. We check both for
- * the case where on-line resizing is not enabled (in which case the
- * resize inode should be cleared) as well as the case where on-line
- * resizing is enabled.
- */
-static void check_resize_inode(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- struct ext2_inode inode;
- struct problem_context pctx;
- int i, j, gdt_off, ind_off;
- blk_t blk, pblk, expect;
- __u32 *dind_buf = NULL, *ind_buf;
- errcode_t retval;
-
- clear_problem_context(&pctx);
-
- /*
- * If the resize inode feature isn't set, then
- * s_reserved_gdt_blocks must be zero.
- */
- if (!(fs->super->s_feature_compat &
- EXT2_FEATURE_COMPAT_RESIZE_INO)) {
- if (fs->super->s_reserved_gdt_blocks) {
- pctx.num = fs->super->s_reserved_gdt_blocks;
- if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
- &pctx)) {
- fs->super->s_reserved_gdt_blocks = 0;
- ext2fs_mark_super_dirty(fs);
- }
- }
- }
-
- /* Read the resize inode */
- pctx.ino = EXT2_RESIZE_INO;
- retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
- if (retval) {
- if (fs->super->s_feature_compat &
- EXT2_FEATURE_COMPAT_RESIZE_INO)
- ctx->flags |= E2F_FLAG_RESIZE_INODE;
- return;
- }
-
- /*
- * If the resize inode feature isn't set, check to make sure
- * the resize inode is cleared; then we're done.
- */
- if (!(fs->super->s_feature_compat &
- EXT2_FEATURE_COMPAT_RESIZE_INO)) {
- for (i=0; i < EXT2_N_BLOCKS; i++) {
- if (inode.i_block[i])
- break;
- }
- if ((i < EXT2_N_BLOCKS) &&
- fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
- memset(&inode, 0, sizeof(inode));
- e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
- "clear_resize");
- }
- return;
- }
-
- /*
- * The resize inode feature is enabled; check to make sure the
- * only block in use is the double indirect block
- */
- blk = inode.i_block[EXT2_DIND_BLOCK];
- for (i=0; i < EXT2_N_BLOCKS; i++) {
- if (i != EXT2_DIND_BLOCK && inode.i_block[i])
- break;
- }
- if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
- !(inode.i_mode & LINUX_S_IFREG) ||
- (blk < fs->super->s_first_data_block ||
- blk >= fs->super->s_blocks_count)) {
- resize_inode_invalid:
- if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
- memset(&inode, 0, sizeof(inode));
- e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
- "clear_resize");
- ctx->flags |= E2F_FLAG_RESIZE_INODE;
- }
- if (!(ctx->options & E2F_OPT_READONLY)) {
- fs->super->s_state &= ~EXT2_VALID_FS;
- ext2fs_mark_super_dirty(fs);
- }
- goto cleanup;
- }
- dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
- "resize dind buffer");
- ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
-
- retval = ext2fs_read_ind_block(fs, blk, dind_buf);
- if (retval)
- goto resize_inode_invalid;
-
- gdt_off = fs->desc_blocks;
- pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
- for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
- i++, gdt_off++, pblk++) {
- gdt_off %= fs->blocksize/4;
- if (dind_buf[gdt_off] != pblk)
- goto resize_inode_invalid;
- retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
- if (retval)
- goto resize_inode_invalid;
- ind_off = 0;
- for (j = 1; j < fs->group_desc_count; j++) {
- if (!ext2fs_bg_has_super(fs, j))
- continue;
- expect = pblk + (j * fs->super->s_blocks_per_group);
- if (ind_buf[ind_off] != expect)
- goto resize_inode_invalid;
- ind_off++;
- }
- }
-
- cleanup:
- ext2fs_free_mem(&dind_buf);
-}
-
-static void check_super_block(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- blk_t first_block, last_block;
- struct ext2_super_block *sb = fs->super;
- struct ext2_group_desc *gd;
- blk_t blocks_per_group = fs->super->s_blocks_per_group;
- blk_t bpg_max;
- int inodes_per_block;
- int ipg_max;
- int inode_size;
- dgrp_t i;
- blk_t should_be;
- struct problem_context pctx;
- __u32 free_blocks = 0, free_inodes = 0;
-
- inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
- ipg_max = inodes_per_block * (blocks_per_group - 4);
- if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
- ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
- bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
- if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
- bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
-
- ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
- sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
- ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
- sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
- ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
- sizeof(int) * fs->group_desc_count, "invalid_inode_table");
-
- clear_problem_context(&pctx);
-
- /*
- * Verify the super block constants...
- */
- check_super_value(ctx, "inodes_count", sb->s_inodes_count,
- MIN_CHECK, 1, 0);
- check_super_value(ctx, "blocks_count", sb->s_blocks_count,
- MIN_CHECK, 1, 0);
- check_super_value(ctx, "first_data_block", sb->s_first_data_block,
- MAX_CHECK, 0, sb->s_blocks_count);
- check_super_value(ctx, "log_block_size", sb->s_log_block_size,
- MIN_CHECK | MAX_CHECK, 0,
- EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
- check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
- MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
- check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
- MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
- bpg_max);
- check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
- MIN_CHECK | MAX_CHECK, 8, bpg_max);
- check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
- MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
- check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
- MAX_CHECK, 0, sb->s_blocks_count / 2);
- check_super_value(ctx, "reserved_gdt_blocks",
- sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
- fs->blocksize/4);
- inode_size = EXT2_INODE_SIZE(sb);
- check_super_value(ctx, "inode_size",
- inode_size, MIN_CHECK | MAX_CHECK,
- EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
- if (inode_size & (inode_size - 1)) {
- pctx.num = inode_size;
- pctx.str = "inode_size";
- fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
- ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
- return;
- }
-
- if (!ctx->num_blocks) {
- pctx.errcode = e2fsck_get_device_size(ctx);
- if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
- fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
- (ctx->num_blocks < sb->s_blocks_count)) {
- pctx.blk = sb->s_blocks_count;
- pctx.blk2 = ctx->num_blocks;
- if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- }
- }
-
- if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
- pctx.blk = EXT2_BLOCK_SIZE(sb);
- pctx.blk2 = EXT2_FRAG_SIZE(sb);
- fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-
- should_be = sb->s_frags_per_group >>
- (sb->s_log_block_size - sb->s_log_frag_size);
- if (sb->s_blocks_per_group != should_be) {
- pctx.blk = sb->s_blocks_per_group;
- pctx.blk2 = should_be;
- fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-
- should_be = (sb->s_log_block_size == 0) ? 1 : 0;
- if (sb->s_first_data_block != should_be) {
- pctx.blk = sb->s_first_data_block;
- pctx.blk2 = should_be;
- fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-
- should_be = sb->s_inodes_per_group * fs->group_desc_count;
- if (sb->s_inodes_count != should_be) {
- pctx.ino = sb->s_inodes_count;
- pctx.ino2 = should_be;
- if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
- sb->s_inodes_count = should_be;
- ext2fs_mark_super_dirty(fs);
- }
- }
-
- /*
- * Verify the group descriptors....
- */
- first_block = sb->s_first_data_block;
- last_block = first_block + blocks_per_group;
-
- for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
- pctx.group = i;
-
- if (i == fs->group_desc_count - 1)
- last_block = sb->s_blocks_count;
- if ((gd->bg_block_bitmap < first_block) ||
- (gd->bg_block_bitmap >= last_block)) {
- pctx.blk = gd->bg_block_bitmap;
- if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
- gd->bg_block_bitmap = 0;
- }
- if (gd->bg_block_bitmap == 0) {
- ctx->invalid_block_bitmap_flag[i]++;
- ctx->invalid_bitmaps++;
- }
- if ((gd->bg_inode_bitmap < first_block) ||
- (gd->bg_inode_bitmap >= last_block)) {
- pctx.blk = gd->bg_inode_bitmap;
- if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
- gd->bg_inode_bitmap = 0;
- }
- if (gd->bg_inode_bitmap == 0) {
- ctx->invalid_inode_bitmap_flag[i]++;
- ctx->invalid_bitmaps++;
- }
- if ((gd->bg_inode_table < first_block) ||
- ((gd->bg_inode_table +
- fs->inode_blocks_per_group - 1) >= last_block)) {
- pctx.blk = gd->bg_inode_table;
- if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
- gd->bg_inode_table = 0;
- }
- if (gd->bg_inode_table == 0) {
- ctx->invalid_inode_table_flag[i]++;
- ctx->invalid_bitmaps++;
- }
- free_blocks += gd->bg_free_blocks_count;
- free_inodes += gd->bg_free_inodes_count;
- first_block += sb->s_blocks_per_group;
- last_block += sb->s_blocks_per_group;
-
- if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
- (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
- (gd->bg_used_dirs_count > sb->s_inodes_per_group))
- ext2fs_unmark_valid(fs);
- }
-
- /*
- * Update the global counts from the block group counts. This
- * is needed for an experimental patch which eliminates
- * locking the entire filesystem when allocating blocks or
- * inodes; if the filesystem is not unmounted cleanly, the
- * global counts may not be accurate.
- */
- if ((free_blocks != sb->s_free_blocks_count) ||
- (free_inodes != sb->s_free_inodes_count)) {
- if (ctx->options & E2F_OPT_READONLY)
- ext2fs_unmark_valid(fs);
- else {
- sb->s_free_blocks_count = free_blocks;
- sb->s_free_inodes_count = free_inodes;
- ext2fs_mark_super_dirty(fs);
- }
- }
-
- if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
- (sb->s_free_inodes_count > sb->s_inodes_count))
- ext2fs_unmark_valid(fs);
-
-
- /*
- * If we have invalid bitmaps, set the error state of the
- * filesystem.
- */
- if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
- sb->s_state &= ~EXT2_VALID_FS;
- ext2fs_mark_super_dirty(fs);
- }
-
- clear_problem_context(&pctx);
-
- /*
- * If the UUID field isn't assigned, assign it.
- */
- if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
- if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
- generate_uuid(sb->s_uuid);
- ext2fs_mark_super_dirty(fs);
- fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
- }
- }
-
- /* FIXME - HURD support?
- * For the Hurd, check to see if the filetype option is set,
- * since it doesn't support it.
- */
- if (!(ctx->options & E2F_OPT_READONLY) &&
- fs->super->s_creator_os == EXT2_OS_HURD &&
- (fs->super->s_feature_incompat &
- EXT2_FEATURE_INCOMPAT_FILETYPE)) {
- if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
- fs->super->s_feature_incompat &=
- ~EXT2_FEATURE_INCOMPAT_FILETYPE;
- ext2fs_mark_super_dirty(fs);
- }
- }
-
- /*
- * If we have any of the compatibility flags set, we need to have a
- * revision 1 filesystem. Most kernels will not check the flags on
- * a rev 0 filesystem and we may have corruption issues because of
- * the incompatible changes to the filesystem.
- */
- if (!(ctx->options & E2F_OPT_READONLY) &&
- fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
- (fs->super->s_feature_compat ||
- fs->super->s_feature_ro_compat ||
- fs->super->s_feature_incompat) &&
- fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
- ext2fs_update_dynamic_rev(fs);
- ext2fs_mark_super_dirty(fs);
- }
-
- check_resize_inode(ctx);
-
- /*
- * Clean up any orphan inodes, if present.
- */
- if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
- fs->super->s_state &= ~EXT2_VALID_FS;
- ext2fs_mark_super_dirty(fs);
- }
-
- /*
- * Move the ext3 journal file, if necessary.
- */
- e2fsck_move_ext3_journal(ctx);
-}
-
-/*
- * swapfs.c --- byte-swap an ext2 filesystem
- */
-
-#ifdef ENABLE_SWAPFS
-
-struct swap_block_struct {
- ext2_ino_t ino;
- int isdir;
- errcode_t errcode;
- char *dir_buf;
- struct ext2_inode *inode;
-};
-
-/*
- * This is a helper function for block_iterate. We mark all of the
- * indirect and direct blocks as changed, so that block_iterate will
- * write them out.
- */
-static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
- void *priv_data)
-{
- errcode_t retval;
-
- struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
-
- if (sb->isdir && (blockcnt >= 0) && *block_nr) {
- retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
- if (retval) {
- sb->errcode = retval;
- return BLOCK_ABORT;
- }
- retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
- if (retval) {
- sb->errcode = retval;
- return BLOCK_ABORT;
- }
- }
- if (blockcnt >= 0) {
- if (blockcnt < EXT2_NDIR_BLOCKS)
- return 0;
- return BLOCK_CHANGED;
- }
- if (blockcnt == BLOCK_COUNT_IND) {
- if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
- return 0;
- return BLOCK_CHANGED;
- }
- if (blockcnt == BLOCK_COUNT_DIND) {
- if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
- return 0;
- return BLOCK_CHANGED;
- }
- if (blockcnt == BLOCK_COUNT_TIND) {
- if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
- return 0;
- return BLOCK_CHANGED;
- }
- return BLOCK_CHANGED;
-}
-
-/*
- * This function is responsible for byte-swapping all of the indirect,
- * block pointers. It is also responsible for byte-swapping directories.
- */
-static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
- struct ext2_inode *inode)
-{
- errcode_t retval;
- struct swap_block_struct sb;
-
- sb.ino = ino;
- sb.inode = inode;
- sb.dir_buf = block_buf + ctx->fs->blocksize*3;
- sb.errcode = 0;
- sb.isdir = 0;
- if (LINUX_S_ISDIR(inode->i_mode))
- sb.isdir = 1;
-
- retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
- swap_block, &sb);
- if (retval) {
- bb_error_msg(_("while calling ext2fs_block_iterate"));
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- if (sb.errcode) {
- bb_error_msg(_("while calling iterator function"));
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-}
-
-static void swap_inodes(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- dgrp_t group;
- unsigned int i;
- ext2_ino_t ino = 1;
- char *buf, *block_buf;
- errcode_t retval;
- struct ext2_inode * inode;
-
- e2fsck_use_inode_shortcuts(ctx, 1);
-
- retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
- &buf);
- if (retval) {
- bb_error_msg(_("while allocating inode buffer"));
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
- "block interate buffer");
- for (group = 0; group < fs->group_desc_count; group++) {
- retval = io_channel_read_blk(fs->io,
- fs->group_desc[group].bg_inode_table,
- fs->inode_blocks_per_group, buf);
- if (retval) {
- bb_error_msg(_("while reading inode table (group %d)"),
- group);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- inode = (struct ext2_inode *) buf;
- for (i=0; i < fs->super->s_inodes_per_group;
- i++, ino++, inode++) {
- ctx->stashed_ino = ino;
- ctx->stashed_inode = inode;
-
- if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
- ext2fs_swap_inode(fs, inode, inode, 0);
-
- /*
- * Skip deleted files.
- */
- if (inode->i_links_count == 0)
- continue;
-
- if (LINUX_S_ISDIR(inode->i_mode) ||
- ((inode->i_block[EXT2_IND_BLOCK] ||
- inode->i_block[EXT2_DIND_BLOCK] ||
- inode->i_block[EXT2_TIND_BLOCK]) &&
- ext2fs_inode_has_valid_blocks(inode)))
- swap_inode_blocks(ctx, ino, block_buf, inode);
-
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
-
- if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
- ext2fs_swap_inode(fs, inode, inode, 1);
- }
- retval = io_channel_write_blk(fs->io,
- fs->group_desc[group].bg_inode_table,
- fs->inode_blocks_per_group, buf);
- if (retval) {
- bb_error_msg(_("while writing inode table (group %d)"),
- group);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- }
- ext2fs_free_mem(&buf);
- ext2fs_free_mem(&block_buf);
- e2fsck_use_inode_shortcuts(ctx, 0);
- ext2fs_flush_icache(fs);
-}
-
-#if defined(__powerpc__) && BB_BIG_ENDIAN
-/*
- * On the PowerPC, the big-endian variant of the ext2 filesystem
- * has its bitmaps stored as 32-bit words with bit 0 as the LSB
- * of each word. Thus a bitmap with only bit 0 set would be, as
- * a string of bytes, 00 00 00 01 00 ...
- * To cope with this, we byte-reverse each word of a bitmap if
- * we have a big-endian filesystem, that is, if we are *not*
- * byte-swapping other word-sized numbers.
- */
-#define EXT2_BIG_ENDIAN_BITMAPS
-#endif
-
-#ifdef EXT2_BIG_ENDIAN_BITMAPS
-static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
-{
- __u32 *p = (__u32 *) bmap->bitmap;
- int n, nbytes = (bmap->end - bmap->start + 7) / 8;
-
- for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
- *p = ext2fs_swab32(*p);
-}
-#endif
-
-
-#ifdef ENABLE_SWAPFS
-static void swap_filesys(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- if (!(ctx->options & E2F_OPT_PREEN))
- printf(_("Pass 0: Doing byte-swap of filesystem\n"));
-
- /* Byte swap */
-
- if (fs->super->s_mnt_count) {
- fprintf(stderr, _("%s: the filesystem must be freshly "
- "checked using fsck\n"
- "and not mounted before trying to "
- "byte-swap it.\n"), ctx->device_name);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
- fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
- EXT2_FLAG_SWAP_BYTES_WRITE);
- fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
- } else {
- fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
- fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
- }
- swap_inodes(ctx);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
- if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
- fs->flags |= EXT2_FLAG_SWAP_BYTES;
- fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
- EXT2_FLAG_SWAP_BYTES_WRITE);
-
-#ifdef EXT2_BIG_ENDIAN_BITMAPS
- e2fsck_read_bitmaps(ctx);
- ext2fs_swap_bitmap(fs->inode_map);
- ext2fs_swap_bitmap(fs->block_map);
- fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
-#endif
- fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
- ext2fs_flush(fs);
- fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
-}
-#endif /* ENABLE_SWAPFS */
-
-#endif
-
-/*
- * util.c --- miscellaneous utilities
- */
-
-
-void *e2fsck_allocate_memory(e2fsck_t ctx EXT2FS_ATTR((unused)), unsigned int size,
- const char *description EXT2FS_ATTR((unused)))
-{
- void *ret;
-
- ret = xzalloc(size);
- return ret;
-}
-
-static char *string_copy(const char *str, int len)
-{
- char *ret;
-
- if (!str)
- return NULL;
- if (!len)
- len = strlen(str);
- ret = xmalloc(len+1);
- strncpy(ret, str, len);
- ret[len] = 0;
- return ret;
-}
-
-#ifndef HAVE_CONIO_H
-static int read_a_char(void)
-{
- char c;
- int r;
- int fail = 0;
-
- while (1) {
- if (e2fsck_global_ctx &&
- (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
- return 3;
- }
- r = read(0, &c, 1);
- if (r == 1)
- return c;
- if (fail++ > 100)
- break;
- }
- return EOF;
-}
-#endif
-
-static int ask_yn(const char * string, int def)
-{
- int c;
- const char *defstr;
- static const char short_yes[] = "yY";
- static const char short_no[] = "nN";
-
-#ifdef HAVE_TERMIOS_H
- struct termios termios, tmp;
-
- tcgetattr (0, &termios);
- tmp = termios;
- tmp.c_lflag &= ~(ICANON | ECHO);
- tmp.c_cc[VMIN] = 1;
- tmp.c_cc[VTIME] = 0;
- tcsetattr_stdin_TCSANOW(&tmp);
-#endif
-
- if (def == 1)
- defstr = "<y>";
- else if (def == 0)
- defstr = "<n>";
- else
- defstr = " (y/n)";
- printf("%s%s? ", string, defstr);
- while (1) {
- fflush (stdout);
- if ((c = read_a_char()) == EOF)
- break;
- if (c == 3) {
-#ifdef HAVE_TERMIOS_H
- tcsetattr_stdin_TCSANOW(&termios);
-#endif
- if (e2fsck_global_ctx &&
- e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
- puts("\n");
- longjmp(e2fsck_global_ctx->abort_loc, 1);
- }
- puts(_("cancelled!\n"));
- return 0;
- }
- if (strchr(short_yes, (char) c)) {
- def = 1;
- break;
- }
- else if (strchr(short_no, (char) c)) {
- def = 0;
- break;
- }
- else if ((c == ' ' || c == '\n') && (def != -1))
- break;
- }
- if (def)
- puts("yes\n");
- else
- puts ("no\n");
-#ifdef HAVE_TERMIOS_H
- tcsetattr_stdin_TCSANOW(&termios);
-#endif
- return def;
-}
-
-int ask (e2fsck_t ctx, const char * string, int def)
-{
- if (ctx->options & E2F_OPT_NO) {
- printf(_("%s? no\n\n"), string);
- return 0;
- }
- if (ctx->options & E2F_OPT_YES) {
- printf(_("%s? yes\n\n"), string);
- return 1;
- }
- if (ctx->options & E2F_OPT_PREEN) {
- printf("%s? %s\n\n", string, def ? _("yes") : _("no"));
- return def;
- }
- return ask_yn(string, def);
-}
-
-void e2fsck_read_bitmaps(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- errcode_t retval;
-
- if (ctx->invalid_bitmaps) {
- bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
- ctx->device_name);
- bb_error_msg_and_die(0);
- }
-
- ehandler_operation(_("reading inode and block bitmaps"));
- retval = ext2fs_read_bitmaps(fs);
- ehandler_operation(0);
- if (retval) {
- bb_error_msg(_("while retrying to read bitmaps for %s"),
- ctx->device_name);
- bb_error_msg_and_die(0);
- }
-}
-
-static void e2fsck_write_bitmaps(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- errcode_t retval;
-
- if (ext2fs_test_bb_dirty(fs)) {
- ehandler_operation(_("writing block bitmaps"));
- retval = ext2fs_write_block_bitmap(fs);
- ehandler_operation(0);
- if (retval) {
- bb_error_msg(_("while retrying to write block bitmaps for %s"),
- ctx->device_name);
- bb_error_msg_and_die(0);
- }
- }
-
- if (ext2fs_test_ib_dirty(fs)) {
- ehandler_operation(_("writing inode bitmaps"));
- retval = ext2fs_write_inode_bitmap(fs);
- ehandler_operation(0);
- if (retval) {
- bb_error_msg(_("while retrying to write inode bitmaps for %s"),
- ctx->device_name);
- bb_error_msg_and_die(0);
- }
- }
-}
-
-void preenhalt(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
-
- if (!(ctx->options & E2F_OPT_PREEN))
- return;
- fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
- "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
- ctx->device_name);
- if (fs != NULL) {
- fs->super->s_state |= EXT2_ERROR_FS;
- ext2fs_mark_super_dirty(fs);
- ext2fs_close(fs);
- }
- exit(EXIT_UNCORRECTED);
-}
-
-void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
- struct ext2_inode * inode, const char *proc)
-{
- int retval;
-
- retval = ext2fs_read_inode(ctx->fs, ino, inode);
- if (retval) {
- bb_error_msg(_("while reading inode %ld in %s"), ino, proc);
- bb_error_msg_and_die(0);
- }
-}
-
-extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
- struct ext2_inode * inode, int bufsize,
- const char *proc)
-{
- int retval;
-
- retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
- if (retval) {
- bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
- bb_error_msg_and_die(0);
- }
-}
-
-extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
- struct ext2_inode * inode, const char *proc)
-{
- int retval;
-
- retval = ext2fs_write_inode(ctx->fs, ino, inode);
- if (retval) {
- bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
- bb_error_msg_and_die(0);
- }
-}
-
-blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
- io_manager manager)
-{
- struct ext2_super_block *sb;
- io_channel io = NULL;
- void *buf = NULL;
- int blocksize;
- blk_t superblock, ret_sb = 8193;
-
- if (fs && fs->super) {
- ret_sb = (fs->super->s_blocks_per_group +
- fs->super->s_first_data_block);
- if (ctx) {
- ctx->superblock = ret_sb;
- ctx->blocksize = fs->blocksize;
- }
- return ret_sb;
- }
-
- if (ctx) {
- if (ctx->blocksize) {
- ret_sb = ctx->blocksize * 8;
- if (ctx->blocksize == 1024)
- ret_sb++;
- ctx->superblock = ret_sb;
- return ret_sb;
- }
- ctx->superblock = ret_sb;
- ctx->blocksize = 1024;
- }
-
- if (!name || !manager)
- goto cleanup;
-
- if (manager->open(name, 0, &io) != 0)
- goto cleanup;
-
- if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
- goto cleanup;
- sb = (struct ext2_super_block *) buf;
-
- for (blocksize = EXT2_MIN_BLOCK_SIZE;
- blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
- superblock = blocksize*8;
- if (blocksize == 1024)
- superblock++;
- io_channel_set_blksize(io, blocksize);
- if (io_channel_read_blk(io, superblock,
- -SUPERBLOCK_SIZE, buf))
- continue;
-#if BB_BIG_ENDIAN
- if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
- ext2fs_swap_super(sb);
-#endif
- if (sb->s_magic == EXT2_SUPER_MAGIC) {
- ret_sb = superblock;
- if (ctx) {
- ctx->superblock = superblock;
- ctx->blocksize = blocksize;
- }
- break;
- }
- }
-
-cleanup:
- if (io)
- io_channel_close(io);
- ext2fs_free_mem(&buf);
- return ret_sb;
-}
-
-
-/*
- * This function runs through the e2fsck passes and calls them all,
- * returning restart, abort, or cancel as necessary...
- */
-typedef void (*pass_t)(e2fsck_t ctx);
-
-static const pass_t e2fsck_passes[] = {
- e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
- e2fsck_pass5, 0 };
-
-#define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
-
-static int e2fsck_run(e2fsck_t ctx)
-{
- int i;
- pass_t e2fsck_pass;
-
- if (setjmp(ctx->abort_loc)) {
- ctx->flags &= ~E2F_FLAG_SETJMP_OK;
- return (ctx->flags & E2F_FLAG_RUN_RETURN);
- }
- ctx->flags |= E2F_FLAG_SETJMP_OK;
-
- for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
- if (ctx->flags & E2F_FLAG_RUN_RETURN)
- break;
- e2fsck_pass(ctx);
- if (ctx->progress)
- (void) (ctx->progress)(ctx, 0, 0, 0);
- }
- ctx->flags &= ~E2F_FLAG_SETJMP_OK;
-
- if (ctx->flags & E2F_FLAG_RUN_RETURN)
- return (ctx->flags & E2F_FLAG_RUN_RETURN);
- return 0;
-}
-
-
-/*
- * unix.c - The unix-specific code for e2fsck
- */
-
-
-/* Command line options */
-static int swapfs;
-#ifdef ENABLE_SWAPFS
-static int normalize_swapfs;
-#endif
-static int cflag; /* check disk */
-static int show_version_only;
-static int verbose;
-
-#define P_E2(singular, plural, n) n, ((n) == 1 ? singular : plural)
-
-static void show_stats(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- int inodes, inodes_used, blocks, blocks_used;
- int dir_links;
- int num_files, num_links;
- int frag_percent;
-
- dir_links = 2 * ctx->fs_directory_count - 1;
- num_files = ctx->fs_total_count - dir_links;
- num_links = ctx->fs_links_count - dir_links;
- inodes = fs->super->s_inodes_count;
- inodes_used = (fs->super->s_inodes_count -
- fs->super->s_free_inodes_count);
- blocks = fs->super->s_blocks_count;
- blocks_used = (fs->super->s_blocks_count -
- fs->super->s_free_blocks_count);
-
- frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
- frag_percent = (frag_percent + 5) / 10;
-
- if (!verbose) {
- printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
- ctx->device_name, inodes_used, inodes,
- frag_percent / 10, frag_percent % 10,
- blocks_used, blocks);
- return;
- }
- printf("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
- 100 * inodes_used / inodes);
- printf("%8d non-contiguous inode%s (%0d.%d%%)\n",
- P_E2("", "s", ctx->fs_fragmented),
- frag_percent / 10, frag_percent % 10);
- printf(_(" # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
- ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
- printf("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
- (int) ((long long) 100 * blocks_used / blocks));
- printf("%8d large file%s\n", P_E2("", "s", ctx->large_files));
- printf("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
- printf("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
- printf("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
- printf("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
- printf("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
- printf("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
- printf("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
- printf(" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
- printf("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
- printf("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
-}
-
-static void check_mount(e2fsck_t ctx)
-{
- errcode_t retval;
- int cont;
-
- retval = ext2fs_check_if_mounted(ctx->filesystem_name,
- &ctx->mount_flags);
- if (retval) {
- bb_error_msg(_("while determining whether %s is mounted"),
- ctx->filesystem_name);
- return;
- }
-
- /*
- * If the filesystem isn't mounted, or it's the root filesystem
- * and it's mounted read-only, then everything's fine.
- */
- if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
- ((ctx->mount_flags & EXT2_MF_ISROOT) &&
- (ctx->mount_flags & EXT2_MF_READONLY)))
- return;
-
- if (ctx->options & E2F_OPT_READONLY) {
- printf(_("Warning! %s is mounted.\n"), ctx->filesystem_name);
- return;
- }
-
- printf(_("%s is mounted. "), ctx->filesystem_name);
- if (!ctx->interactive)
- bb_error_msg_and_die(_("can't continue, aborting"));
- printf(_("\n\n\007\007\007\007WARNING!!! "
- "Running e2fsck on a mounted filesystem may cause\n"
- "SEVERE filesystem damage.\007\007\007\n\n"));
- cont = ask_yn(_("Do you really want to continue"), -1);
- if (!cont) {
- printf(_("check aborted.\n"));
- exit(0);
- }
-}
-
-static int is_on_batt(void)
-{
- FILE *f;
- DIR *d;
- char tmp[80], tmp2[80], fname[80];
- unsigned int acflag;
- struct dirent* de;
-
- f = fopen_for_read("/proc/apm");
- if (f) {
- if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
- acflag = 1;
- fclose(f);
- return (acflag != 1);
- }
- d = opendir("/proc/acpi/ac_adapter");
- if (d) {
- while ((de=readdir(d)) != NULL) {
- if (!strncmp(".", de->d_name, 1))
- continue;
- snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
- de->d_name);
- f = fopen_for_read(fname);
- if (!f)
- continue;
- if (fscanf(f, "%s %s", tmp2, tmp) != 2)
- tmp[0] = 0;
- fclose(f);
- if (strncmp(tmp, "off-line", 8) == 0) {
- closedir(d);
- return 1;
- }
- }
- closedir(d);
- }
- return 0;
-}
-
-/*
- * This routine checks to see if a filesystem can be skipped; if so,
- * it will exit with EXIT_OK. Under some conditions it will print a
- * message explaining why a check is being forced.
- */
-static void check_if_skip(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- const char *reason = NULL;
- unsigned int reason_arg = 0;
- long next_check;
- int batt = is_on_batt();
- time_t now = time(NULL);
-
- if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
- return;
-
- if ((fs->super->s_state & EXT2_ERROR_FS) ||
- !ext2fs_test_valid(fs))
- reason = _(" contains a file system with errors");
- else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
- reason = _(" was not cleanly unmounted");
- else if ((fs->super->s_max_mnt_count > 0) &&
- (fs->super->s_mnt_count >=
- (unsigned) fs->super->s_max_mnt_count)) {
- reason = _(" has been mounted %u times without being checked");
- reason_arg = fs->super->s_mnt_count;
- if (batt && (fs->super->s_mnt_count <
- (unsigned) fs->super->s_max_mnt_count*2))
- reason = 0;
- } else if (!(ctx->options & E2F_OPT_PREEN) &&
- fs->super->s_checkinterval &&
- ((now - fs->super->s_lastcheck) >=
- fs->super->s_checkinterval)) {
- reason = _(" has gone %u days without being checked");
- reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
- if (batt && ((now - fs->super->s_lastcheck) <
- fs->super->s_checkinterval*2))
- reason = 0;
- }
- if (reason) {
- fputs(ctx->device_name, stdout);
- printf(reason, reason_arg);
- fputs(_(", check forced.\n"), stdout);
- return;
- }
- printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
- fs->super->s_inodes_count - fs->super->s_free_inodes_count,
- fs->super->s_inodes_count,
- fs->super->s_blocks_count - fs->super->s_free_blocks_count,
- fs->super->s_blocks_count);
- next_check = 100000;
- if (fs->super->s_max_mnt_count > 0) {
- next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
- if (next_check <= 0)
- next_check = 1;
- }
- if (fs->super->s_checkinterval &&
- ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
- next_check = 1;
- if (next_check <= 5) {
- if (next_check == 1)
- fputs(_(" (check after next mount)"), stdout);
- else
- printf(_(" (check in %ld mounts)"), next_check);
- }
- bb_putchar('\n');
- ext2fs_close(fs);
- ctx->fs = NULL;
- e2fsck_free_context(ctx);
- exit(EXIT_OK);
-}
-
-/*
- * For completion notice
- */
-struct percent_tbl {
- int max_pass;
- int table[32];
-};
-static const struct percent_tbl e2fsck_tbl = {
- 5, { 0, 70, 90, 92, 95, 100 }
-};
-
-static char bar[128], spaces[128];
-
-static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
- int max)
-{
- float percent;
-
- if (pass <= 0)
- return 0.0;
- if (pass > tbl->max_pass || max == 0)
- return 100.0;
- percent = ((float) curr) / ((float) max);
- return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
- + tbl->table[pass-1]);
-}
-
-void e2fsck_clear_progbar(e2fsck_t ctx)
-{
- if (!(ctx->flags & E2F_FLAG_PROG_BAR))
- return;
-
- printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
- ctx->stop_meta);
- fflush(stdout);
- ctx->flags &= ~E2F_FLAG_PROG_BAR;
-}
-
-int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
- unsigned int dpynum)
-{
- static const char spinner[] = "\\|/-";
- int i;
- unsigned int tick;
- struct timeval tv;
- int dpywidth;
- int fixed_percent;
-
- if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
- return 0;
-
- /*
- * Calculate the new progress position. If the
- * percentage hasn't changed, then we skip out right
- * away.
- */
- fixed_percent = (int) ((10 * percent) + 0.5);
- if (ctx->progress_last_percent == fixed_percent)
- return 0;
- ctx->progress_last_percent = fixed_percent;
-
- /*
- * If we've already updated the spinner once within
- * the last 1/8th of a second, no point doing it
- * again.
- */
- gettimeofday(&tv, NULL);
- tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
- if ((tick == ctx->progress_last_time) &&
- (fixed_percent != 0) && (fixed_percent != 1000))
- return 0;
- ctx->progress_last_time = tick;
-
- /*
- * Advance the spinner, and note that the progress bar
- * will be on the screen
- */
- ctx->progress_pos = (ctx->progress_pos+1) & 3;
- ctx->flags |= E2F_FLAG_PROG_BAR;
-
- dpywidth = 66 - strlen(label);
- dpywidth = 8 * (dpywidth / 8);
- if (dpynum)
- dpywidth -= 8;
-
- i = ((percent * dpywidth) + 50) / 100;
- printf("%s%s: |%s%s", ctx->start_meta, label,
- bar + (sizeof(bar) - (i+1)),
- spaces + (sizeof(spaces) - (dpywidth - i + 1)));
- if (fixed_percent == 1000)
- bb_putchar('|');
- else
- bb_putchar(spinner[ctx->progress_pos & 3]);
- printf(" %4.1f%% ", percent);
- if (dpynum)
- printf("%u\r", dpynum);
- else
- fputs(" \r", stdout);
- fputs(ctx->stop_meta, stdout);
-
- if (fixed_percent == 1000)
- e2fsck_clear_progbar(ctx);
- fflush(stdout);
-
- return 0;
-}
-
-static int e2fsck_update_progress(e2fsck_t ctx, int pass,
- unsigned long cur, unsigned long max)
-{
- char buf[80];
- float percent;
-
- if (pass == 0)
- return 0;
-
- if (ctx->progress_fd) {
- sprintf(buf, "%d %lu %lu\n", pass, cur, max);
- xwrite_str(ctx->progress_fd, buf);
- } else {
- percent = calc_percent(&e2fsck_tbl, pass, cur, max);
- e2fsck_simple_progress(ctx, ctx->device_name,
- percent, 0);
- }
- return 0;
-}
-
-static void reserve_stdio_fds(void)
-{
- int fd;
-
- while (1) {
- fd = open(bb_dev_null, O_RDWR);
- if (fd > 2)
- break;
- if (fd < 0) {
- fprintf(stderr, _("ERROR: Cannot open "
- "/dev/null (%s)\n"),
- strerror(errno));
- break;
- }
- }
- close(fd);
-}
-
-static void signal_progress_on(int sig FSCK_ATTR((unused)))
-{
- e2fsck_t ctx = e2fsck_global_ctx;
-
- if (!ctx)
- return;
-
- ctx->progress = e2fsck_update_progress;
- ctx->progress_fd = 0;
-}
-
-static void signal_progress_off(int sig FSCK_ATTR((unused)))
-{
- e2fsck_t ctx = e2fsck_global_ctx;
-
- if (!ctx)
- return;
-
- e2fsck_clear_progbar(ctx);
- ctx->progress = 0;
-}
-
-static void signal_cancel(int sig FSCK_ATTR((unused)))
-{
- e2fsck_t ctx = e2fsck_global_ctx;
-
- if (!ctx)
- exit(FSCK_CANCELED);
-
- ctx->flags |= E2F_FLAG_CANCEL;
-}
-
-static void parse_extended_opts(e2fsck_t ctx, const char *opts)
-{
- char *buf, *token, *next, *p, *arg;
- int ea_ver;
- int extended_usage = 0;
-
- buf = string_copy(opts, 0);
- for (token = buf; token && *token; token = next) {
- p = strchr(token, ',');
- next = 0;
- if (p) {
- *p = 0;
- next = p+1;
- }
- arg = strchr(token, '=');
- if (arg) {
- *arg = 0;
- arg++;
- }
- if (strcmp(token, "ea_ver") == 0) {
- if (!arg) {
- extended_usage++;
- continue;
- }
- ea_ver = strtoul(arg, &p, 0);
- if (*p ||
- ((ea_ver != 1) && (ea_ver != 2))) {
- fprintf(stderr,
- _("Invalid EA version.\n"));
- extended_usage++;
- continue;
- }
- ctx->ext_attr_ver = ea_ver;
- } else {
- fprintf(stderr, _("Unknown extended option: %s\n"),
- token);
- extended_usage++;
- }
- }
- if (extended_usage) {
- bb_error_msg_and_die(
- "Extended options are separated by commas, "
- "and may take an argument which\n"
- "is set off by an equals ('=') sign. "
- "Valid extended options are:\n"
- "\tea_ver=<ea_version (1 or 2)>\n\n");
- }
-}
-
-
-static errcode_t PRS(int argc, char **argv, e2fsck_t *ret_ctx)
-{
- int flush = 0;
- int c, fd;
- e2fsck_t ctx;
- errcode_t retval;
- struct sigaction sa;
- char *extended_opts = NULL;
-
- retval = e2fsck_allocate_context(&ctx);
- if (retval)
- return retval;
-
- *ret_ctx = ctx;
-
- setvbuf(stdout, NULL, _IONBF, BUFSIZ);
- setvbuf(stderr, NULL, _IONBF, BUFSIZ);
- if (isatty(0) && isatty(1)) {
- ctx->interactive = 1;
- } else {
- ctx->start_meta[0] = '\001';
- ctx->stop_meta[0] = '\002';
- }
- memset(bar, '=', sizeof(bar)-1);
- memset(spaces, ' ', sizeof(spaces)-1);
-
- if (argc && *argv)
- ctx->program_name = *argv;
- else
- ctx->program_name = "e2fsck";
- while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
- switch (c) {
- case 'C':
- ctx->progress = e2fsck_update_progress;
- ctx->progress_fd = atoi(optarg);
- if (!ctx->progress_fd)
- break;
- /* Validate the file descriptor to avoid disasters */
- fd = dup(ctx->progress_fd);
- if (fd < 0) {
- fprintf(stderr,
- _("Error validating file descriptor %d: %s\n"),
- ctx->progress_fd,
- error_message(errno));
- bb_error_msg_and_die(_("Invalid completion information file descriptor"));
- } else
- close(fd);
- break;
- case 'D':
- ctx->options |= E2F_OPT_COMPRESS_DIRS;
- break;
- case 'E':
- extended_opts = optarg;
- break;
- case 'p':
- case 'a':
- if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
- conflict_opt:
- bb_error_msg_and_die(_("only one the options -p/-a, -n or -y may be specified"));
- }
- ctx->options |= E2F_OPT_PREEN;
- break;
- case 'n':
- if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
- goto conflict_opt;
- ctx->options |= E2F_OPT_NO;
- break;
- case 'y':
- if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
- goto conflict_opt;
- ctx->options |= E2F_OPT_YES;
- break;
- case 't':
- /* FIXME - This needs to go away in a future path - will change binary */
- fprintf(stderr, _("The -t option is not "
- "supported on this version of e2fsck.\n"));
- break;
- case 'c':
- if (cflag++)
- ctx->options |= E2F_OPT_WRITECHECK;
- ctx->options |= E2F_OPT_CHECKBLOCKS;
- break;
- case 'r':
- /* What we do by default, anyway! */
- break;
- case 'b':
- ctx->use_superblock = atoi(optarg);
- ctx->flags |= E2F_FLAG_SB_SPECIFIED;
- break;
- case 'B':
- ctx->blocksize = atoi(optarg);
- break;
- case 'I':
- ctx->inode_buffer_blocks = atoi(optarg);
- break;
- case 'j':
- ctx->journal_name = string_copy(optarg, 0);
- break;
- case 'P':
- ctx->process_inode_size = atoi(optarg);
- break;
- case 'd':
- ctx->options |= E2F_OPT_DEBUG;
- break;
- case 'f':
- ctx->options |= E2F_OPT_FORCE;
- break;
- case 'F':
- flush = 1;
- break;
- case 'v':
- verbose = 1;
- break;
- case 'V':
- show_version_only = 1;
- break;
- case 'N':
- ctx->device_name = optarg;
- break;
-#ifdef ENABLE_SWAPFS
- case 's':
- normalize_swapfs = 1;
- case 'S':
- swapfs = 1;
- break;
-#else
- case 's':
- case 'S':
- fprintf(stderr, _("Byte-swapping filesystems "
- "not compiled in this version "
- "of e2fsck\n"));
- exit(1);
-#endif
- default:
- bb_show_usage();
- }
- if (show_version_only)
- return 0;
- if (optind != argc - 1)
- bb_show_usage();
- if ((ctx->options & E2F_OPT_NO) &&
- !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
- ctx->options |= E2F_OPT_READONLY;
- ctx->io_options = strchr(argv[optind], '?');
- if (ctx->io_options)
- *ctx->io_options++ = 0;
- ctx->filesystem_name = argv[optind];
- if (resolve_mount_spec(&ctx->filesystem_name) < 0 ||
- !ctx->filesystem_name) {
- bb_error_msg(_("Unable to resolve '%s'"), argv[optind]);
- bb_error_msg_and_die(0);
- }
- if (extended_opts)
- parse_extended_opts(ctx, extended_opts);
-
- if (flush) {
- fd = open(ctx->filesystem_name, O_RDONLY, 0);
- if (fd < 0) {
- bb_error_msg(_("while opening %s for flushing"),
- ctx->filesystem_name);
- bb_error_msg_and_die(0);
- }
- if ((retval = ext2fs_sync_device(fd, 1))) {
- bb_error_msg(_("while trying to flush %s"),
- ctx->filesystem_name);
- bb_error_msg_and_die(0);
- }
- close(fd);
- }
-#ifdef ENABLE_SWAPFS
- if (swapfs && cflag) {
- fprintf(stderr, _("Incompatible options not "
- "allowed when byte-swapping.\n"));
- exit(EXIT_USAGE);
- }
-#endif
- /*
- * Set up signal action
- */
- memset(&sa, 0, sizeof(struct sigaction));
- sa.sa_handler = signal_cancel;
- sigaction(SIGINT, &sa, 0);
- sigaction(SIGTERM, &sa, 0);
-#ifdef SA_RESTART
- sa.sa_flags = SA_RESTART;
-#endif
- e2fsck_global_ctx = ctx;
- sa.sa_handler = signal_progress_on;
- sigaction(SIGUSR1, &sa, 0);
- sa.sa_handler = signal_progress_off;
- sigaction(SIGUSR2, &sa, 0);
-
- /* Update our PATH to include /sbin if we need to run badblocks */
- if (cflag)
- e2fs_set_sbin_path();
- return 0;
-}
-
-static const char my_ver_string[] = E2FSPROGS_VERSION;
-static const char my_ver_date[] = E2FSPROGS_DATE;
-
-int e2fsck_main (int argc, char **argv);
-int e2fsck_main (int argc, char **argv)
-{
- errcode_t retval;
- int exit_value = EXIT_OK;
- ext2_filsys fs = 0;
- io_manager io_ptr;
- struct ext2_super_block *sb;
- const char *lib_ver_date;
- int my_ver, lib_ver;
- e2fsck_t ctx;
- struct problem_context pctx;
- int flags, run_result;
-
- clear_problem_context(&pctx);
-
- my_ver = ext2fs_parse_version_string(my_ver_string);
- lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
- if (my_ver > lib_ver) {
- fprintf( stderr, _("Error: ext2fs library version "
- "out of date!\n"));
- show_version_only++;
- }
-
- retval = PRS(argc, argv, &ctx);
- if (retval) {
- bb_error_msg(_("while trying to initialize program"));
- exit(EXIT_ERROR);
- }
- reserve_stdio_fds();
-
- if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
- fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
- my_ver_date);
-
- if (show_version_only) {
- fprintf(stderr, _("\tUsing %s, %s\n"),
- error_message(EXT2_ET_BASE), lib_ver_date);
- exit(EXIT_OK);
- }
-
- check_mount(ctx);
-
- if (!(ctx->options & E2F_OPT_PREEN) &&
- !(ctx->options & E2F_OPT_NO) &&
- !(ctx->options & E2F_OPT_YES)) {
- if (!ctx->interactive)
- bb_error_msg_and_die(_("need terminal for interactive repairs"));
- }
- ctx->superblock = ctx->use_superblock;
-restart:
-#ifdef CONFIG_TESTIO_DEBUG
- io_ptr = test_io_manager;
- test_io_backing_manager = unix_io_manager;
-#else
- io_ptr = unix_io_manager;
-#endif
- flags = 0;
- if ((ctx->options & E2F_OPT_READONLY) == 0)
- flags |= EXT2_FLAG_RW;
-
- if (ctx->superblock && ctx->blocksize) {
- retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
- flags, ctx->superblock, ctx->blocksize,
- io_ptr, &fs);
- } else if (ctx->superblock) {
- int blocksize;
- for (blocksize = EXT2_MIN_BLOCK_SIZE;
- blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
- retval = ext2fs_open2(ctx->filesystem_name,
- ctx->io_options, flags,
- ctx->superblock, blocksize,
- io_ptr, &fs);
- if (!retval)
- break;
- }
- } else
- retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
- flags, 0, 0, io_ptr, &fs);
- if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
- !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
- ((retval == EXT2_ET_BAD_MAGIC) ||
- ((retval == 0) && ext2fs_check_desc(fs)))) {
- if (!fs || (fs->group_desc_count > 1)) {
- printf(_("%s trying backup blocks...\n"),
- retval ? _("Couldn't find ext2 superblock,") :
- _("Group descriptors look bad..."));
- get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
- if (fs)
- ext2fs_close(fs);
- goto restart;
- }
- }
- if (retval) {
- bb_error_msg(_("while trying to open %s"),
- ctx->filesystem_name);
- if (retval == EXT2_ET_REV_TOO_HIGH) {
- printf(_("The filesystem revision is apparently "
- "too high for this version of e2fsck.\n"
- "(Or the filesystem superblock "
- "is corrupt)\n\n"));
- fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
- } else if (retval == EXT2_ET_SHORT_READ)
- printf(_("Could this be a zero-length partition?\n"));
- else if ((retval == EPERM) || (retval == EACCES))
- printf(_("You must have %s access to the "
- "filesystem or be root\n"),
- (ctx->options & E2F_OPT_READONLY) ?
- "r/o" : "r/w");
- else if (retval == ENXIO)
- printf(_("Possibly non-existent or swap device?\n"));
-#ifdef EROFS
- else if (retval == EROFS)
- printf(_("Disk write-protected; use the -n option "
- "to do a read-only\n"
- "check of the device.\n"));
-#endif
- else
- fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
- bb_error_msg_and_die(0);
- }
- ctx->fs = fs;
- fs->priv_data = ctx;
- sb = fs->super;
- if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
- bb_error_msg(_("while trying to open %s"),
- ctx->filesystem_name);
- get_newer:
- bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
- }
-
- /*
- * Set the device name, which is used whenever we print error
- * or informational messages to the user.
- */
- if (ctx->device_name == 0 &&
- (sb->s_volume_name[0] != 0)) {
- ctx->device_name = string_copy(sb->s_volume_name,
- sizeof(sb->s_volume_name));
- }
- if (ctx->device_name == 0)
- ctx->device_name = ctx->filesystem_name;
-
- /*
- * Make sure the ext3 superblock fields are consistent.
- */
- retval = e2fsck_check_ext3_journal(ctx);
- if (retval) {
- bb_error_msg(_("while checking ext3 journal for %s"),
- ctx->device_name);
- bb_error_msg_and_die(0);
- }
-
- /*
- * Check to see if we need to do ext3-style recovery. If so,
- * do it, and then restart the fsck.
- */
- if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
- if (ctx->options & E2F_OPT_READONLY) {
- printf(_("Warning: skipping journal recovery "
- "because doing a read-only filesystem "
- "check.\n"));
- io_channel_flush(ctx->fs->io);
- } else {
- if (ctx->flags & E2F_FLAG_RESTARTED) {
- /*
- * Whoops, we attempted to run the
- * journal twice. This should never
- * happen, unless the hardware or
- * device driver is being bogus.
- */
- bb_error_msg(_("can't set superblock flags on %s"), ctx->device_name);
- bb_error_msg_and_die(0);
- }
- retval = e2fsck_run_ext3_journal(ctx);
- if (retval) {
- bb_error_msg(_("while recovering ext3 journal of %s"),
- ctx->device_name);
- bb_error_msg_and_die(0);
- }
- ext2fs_close(ctx->fs);
- ctx->fs = 0;
- ctx->flags |= E2F_FLAG_RESTARTED;
- goto restart;
- }
- }
-
- /*
- * Check for compatibility with the feature sets. We need to
- * be more stringent than ext2fs_open().
- */
- if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
- (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
- bb_error_msg("(%s)", ctx->device_name);
- goto get_newer;
- }
- if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
- bb_error_msg("(%s)", ctx->device_name);
- goto get_newer;
- }
-#ifdef ENABLE_COMPRESSION
- /* FIXME - do we support this at all? */
- if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
- bb_error_msg(_("warning: compression support is experimental"));
-#endif
-#ifndef ENABLE_HTREE
- if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
- bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
- "but filesystem %s has HTREE directories."),
- ctx->device_name);
- goto get_newer;
- }
-#endif
-
- /*
- * If the user specified a specific superblock, presumably the
- * master superblock has been trashed. So we mark the
- * superblock as dirty, so it can be written out.
- */
- if (ctx->superblock &&
- !(ctx->options & E2F_OPT_READONLY))
- ext2fs_mark_super_dirty(fs);
-
- /*
- * We only update the master superblock because (a) paranoia;
- * we don't want to corrupt the backup superblocks, and (b) we
- * don't need to update the mount count and last checked
- * fields in the backup superblock (the kernel doesn't
- * update the backup superblocks anyway).
- */
- fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
-
- ehandler_init(fs->io);
-
- if (ctx->superblock)
- set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
- ext2fs_mark_valid(fs);
- check_super_block(ctx);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- bb_error_msg_and_die(0);
- check_if_skip(ctx);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- bb_error_msg_and_die(0);
-#ifdef ENABLE_SWAPFS
-
-#ifdef WORDS_BIGENDIAN
-#define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
-#else
-#define NATIVE_FLAG 0
-#endif
-
-
- if (normalize_swapfs) {
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
- fprintf(stderr, _("%s: Filesystem byte order "
- "already normalized.\n"), ctx->device_name);
- bb_error_msg_and_die(0);
- }
- }
- if (swapfs) {
- swap_filesys(ctx);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- bb_error_msg_and_die(0);
- }
-#endif
-
- /*
- * Mark the system as valid, 'til proven otherwise
- */
- ext2fs_mark_valid(fs);
-
- retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
- if (retval) {
- bb_error_msg(_("while reading bad blocks inode"));
- preenhalt(ctx);
- printf(_("This doesn't bode well,"
- " but we'll try to go on...\n"));
- }
-
- run_result = e2fsck_run(ctx);
- e2fsck_clear_progbar(ctx);
- if (run_result == E2F_FLAG_RESTART) {
- printf(_("Restarting e2fsck from the beginning...\n"));
- retval = e2fsck_reset_context(ctx);
- if (retval) {
- bb_error_msg(_("while resetting context"));
- bb_error_msg_and_die(0);
- }
- ext2fs_close(fs);
- goto restart;
- }
- if (run_result & E2F_FLAG_CANCEL) {
- printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
- ctx->device_name : ctx->filesystem_name);
- exit_value |= FSCK_CANCELED;
- }
- if (run_result & E2F_FLAG_ABORT)
- bb_error_msg_and_die(_("aborted"));
-
- /* Cleanup */
- if (ext2fs_test_changed(fs)) {
- exit_value |= EXIT_NONDESTRUCT;
- if (!(ctx->options & E2F_OPT_PREEN))
- printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
- ctx->device_name);
- if (ctx->mount_flags & EXT2_MF_ISROOT) {
- printf(_("%s: ***** REBOOT LINUX *****\n"),
- ctx->device_name);
- exit_value |= EXIT_DESTRUCT;
- }
- }
- if (!ext2fs_test_valid(fs)) {
- printf(_("\n%s: ********** WARNING: Filesystem still has "
- "errors **********\n\n"), ctx->device_name);
- exit_value |= EXIT_UNCORRECTED;
- exit_value &= ~EXIT_NONDESTRUCT;
- }
- if (exit_value & FSCK_CANCELED)
- exit_value &= ~EXIT_NONDESTRUCT;
- else {
- show_stats(ctx);
- if (!(ctx->options & E2F_OPT_READONLY)) {
- if (ext2fs_test_valid(fs)) {
- if (!(sb->s_state & EXT2_VALID_FS))
- exit_value |= EXIT_NONDESTRUCT;
- sb->s_state = EXT2_VALID_FS;
- } else
- sb->s_state &= ~EXT2_VALID_FS;
- sb->s_mnt_count = 0;
- sb->s_lastcheck = time(NULL);
- ext2fs_mark_super_dirty(fs);
- }
- }
-
- e2fsck_write_bitmaps(ctx);
-
- ext2fs_close(fs);
- ctx->fs = NULL;
- free(ctx->filesystem_name);
- free(ctx->journal_name);
- e2fsck_free_context(ctx);
-
- return exit_value;
-}
diff --git a/release/src/router/busybox/e2fsprogs/e2fsck.h b/release/src/router/busybox/e2fsprogs/e2fsck.h
deleted file mode 100644
index 754d6f1097..0000000000
--- a/release/src/router/busybox/e2fsprogs/e2fsck.h
+++ /dev/null
@@ -1,637 +0,0 @@
-/* vi: set sw=4 ts=4: */
-#include <sys/types.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <time.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <setjmp.h>
-#include <errno.h>
-#include <getopt.h>
-#include <limits.h>
-#include <stddef.h>
-#include <assert.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <sys/resource.h>
-#include <sys/param.h>
-#include <sys/mount.h>
-#include <sys/ioctl.h>
-#include <termios.h>
-#include <mntent.h>
-#include <dirent.h>
-#include "ext2fs/kernel-list.h"
-#include <sys/types.h>
-#include <linux/types.h>
-
-/*
- * Now pull in the real linux/jfs.h definitions.
- */
-#include "ext2fs/kernel-jbd.h"
-
-
-
-#include "fsck.h"
-
-#include "ext2fs/ext2_fs.h"
-#include "volume_id.h"
-#include "ext2fs/ext2_ext_attr.h"
-#include "e2fs_lib.h"
-#include "libbb.h"
-
-#ifdef HAVE_CONIO_H
-#undef HAVE_TERMIOS_H
-#include <conio.h>
-#define read_a_char() getch()
-#else
-#ifdef HAVE_TERMIOS_H
-#include <termios.h>
-#endif
-#endif
-
-
-/*
- * The last ext2fs revision level that this version of e2fsck is able to
- * support
- */
-#define E2FSCK_CURRENT_REV 1
-
-/* Used by the region allocation code */
-typedef __u32 region_addr_t;
-typedef struct region_struct *region_t;
-
-struct dx_dirblock_info {
- int type;
- blk_t phys;
- int flags;
- blk_t parent;
- ext2_dirhash_t min_hash;
- ext2_dirhash_t max_hash;
- ext2_dirhash_t node_min_hash;
- ext2_dirhash_t node_max_hash;
-};
-
-/*
-These defines are used in the type field of dx_dirblock_info
-*/
-
-#define DX_DIRBLOCK_ROOT 1
-#define DX_DIRBLOCK_LEAF 2
-#define DX_DIRBLOCK_NODE 3
-
-
-/*
-The following defines are used in the 'flags' field of a dx_dirblock_info
-*/
-#define DX_FLAG_REFERENCED 1
-#define DX_FLAG_DUP_REF 2
-#define DX_FLAG_FIRST 4
-#define DX_FLAG_LAST 8
-
-/*
- * E2fsck options
- */
-#define E2F_OPT_READONLY 0x0001
-#define E2F_OPT_PREEN 0x0002
-#define E2F_OPT_YES 0x0004
-#define E2F_OPT_NO 0x0008
-#define E2F_OPT_TIME 0x0010
-#define E2F_OPT_CHECKBLOCKS 0x0040
-#define E2F_OPT_DEBUG 0x0080
-#define E2F_OPT_FORCE 0x0100
-#define E2F_OPT_WRITECHECK 0x0200
-#define E2F_OPT_COMPRESS_DIRS 0x0400
-
-/*
- * E2fsck flags
- */
-#define E2F_FLAG_ABORT 0x0001 /* Abort signaled */
-#define E2F_FLAG_CANCEL 0x0002 /* Cancel signaled */
-#define E2F_FLAG_SIGNAL_MASK 0x0003
-#define E2F_FLAG_RESTART 0x0004 /* Restart signaled */
-
-#define E2F_FLAG_SETJMP_OK 0x0010 /* Setjmp valid for abort */
-
-#define E2F_FLAG_PROG_BAR 0x0020 /* Progress bar on screen */
-#define E2F_FLAG_PROG_SUPPRESS 0x0040 /* Progress suspended */
-#define E2F_FLAG_JOURNAL_INODE 0x0080 /* Create a new ext3 journal inode */
-#define E2F_FLAG_SB_SPECIFIED 0x0100 /* The superblock was explicitly
- * specified by the user */
-#define E2F_FLAG_RESTARTED 0x0200 /* E2fsck has been restarted */
-#define E2F_FLAG_RESIZE_INODE 0x0400 /* Request to recreate resize inode */
-
-
-/*Don't know where these come from*/
-#define READ 0
-#define WRITE 1
-#define cpu_to_be32(n) htonl(n)
-#define be32_to_cpu(n) ntohl(n)
-
-/*
- * We define a set of "latch groups"; these are problems which are
- * handled as a set. The user answers once for a particular latch
- * group.
- */
-#define PR_LATCH_MASK 0x0ff0 /* Latch mask */
-#define PR_LATCH_BLOCK 0x0010 /* Latch for illegal blocks (pass 1) */
-#define PR_LATCH_BBLOCK 0x0020 /* Latch for bad block inode blocks (pass 1) */
-#define PR_LATCH_IBITMAP 0x0030 /* Latch for pass 5 inode bitmap proc. */
-#define PR_LATCH_BBITMAP 0x0040 /* Latch for pass 5 inode bitmap proc. */
-#define PR_LATCH_RELOC 0x0050 /* Latch for superblock relocate hint */
-#define PR_LATCH_DBLOCK 0x0060 /* Latch for pass 1b dup block headers */
-#define PR_LATCH_LOW_DTIME 0x0070 /* Latch for pass1 orphaned list refugees */
-#define PR_LATCH_TOOBIG 0x0080 /* Latch for file to big errors */
-#define PR_LATCH_OPTIMIZE_DIR 0x0090 /* Latch for optimize directories */
-
-#define PR_LATCH(x) ((((x) & PR_LATCH_MASK) >> 4) - 1)
-
-/*
- * Latch group descriptor flags
- */
-#define PRL_YES 0x0001 /* Answer yes */
-#define PRL_NO 0x0002 /* Answer no */
-#define PRL_LATCHED 0x0004 /* The latch group is latched */
-#define PRL_SUPPRESS 0x0008 /* Suppress all latch group questions */
-
-#define PRL_VARIABLE 0x000f /* All the flags that need to be reset */
-
-/*
- * Pre-Pass 1 errors
- */
-
-#define PR_0_BB_NOT_GROUP 0x000001 /* Block bitmap not in group */
-#define PR_0_IB_NOT_GROUP 0x000002 /* Inode bitmap not in group */
-#define PR_0_ITABLE_NOT_GROUP 0x000003 /* Inode table not in group */
-#define PR_0_SB_CORRUPT 0x000004 /* Superblock corrupt */
-#define PR_0_FS_SIZE_WRONG 0x000005 /* Filesystem size is wrong */
-#define PR_0_NO_FRAGMENTS 0x000006 /* Fragments not supported */
-#define PR_0_BLOCKS_PER_GROUP 0x000007 /* Bad blocks_per_group */
-#define PR_0_FIRST_DATA_BLOCK 0x000008 /* Bad first_data_block */
-#define PR_0_ADD_UUID 0x000009 /* Adding UUID to filesystem */
-#define PR_0_RELOCATE_HINT 0x00000A /* Relocate hint */
-#define PR_0_MISC_CORRUPT_SUPER 0x00000B /* Miscellaneous superblock corruption */
-#define PR_0_GETSIZE_ERROR 0x00000C /* Error determing physical device size of filesystem */
-#define PR_0_INODE_COUNT_WRONG 0x00000D /* Inode count in the superblock incorrect */
-#define PR_0_HURD_CLEAR_FILETYPE 0x00000E /* The Hurd does not support the filetype feature */
-#define PR_0_JOURNAL_BAD_INODE 0x00000F /* The Hurd does not support the filetype feature */
-#define PR_0_JOURNAL_UNSUPP_MULTIFS 0x000010 /* The external journal has multiple filesystems (which we can't handle yet) */
-#define PR_0_CANT_FIND_JOURNAL 0x000011 /* Can't find external journal */
-#define PR_0_EXT_JOURNAL_BAD_SUPER 0x000012/* External journal has bad superblock */
-#define PR_0_JOURNAL_BAD_UUID 0x000013 /* Superblock has a bad journal UUID */
-#define PR_0_JOURNAL_UNSUPP_SUPER 0x000014 /* Journal has an unknown superblock type */
-#define PR_0_JOURNAL_BAD_SUPER 0x000015 /* Journal superblock is corrupt */
-#define PR_0_JOURNAL_HAS_JOURNAL 0x000016 /* Journal superblock is corrupt */
-#define PR_0_JOURNAL_RECOVER_SET 0x000017 /* Superblock has recovery flag set but no journal */
-#define PR_0_JOURNAL_RECOVERY_CLEAR 0x000018 /* Journal has data, but recovery flag is clear */
-#define PR_0_JOURNAL_RESET_JOURNAL 0x000019 /* Ask if we should clear the journal */
-#define PR_0_FS_REV_LEVEL 0x00001A /* Filesystem revision is 0, but feature flags are set */
-#define PR_0_ORPHAN_CLEAR_INODE 0x000020 /* Clearing orphan inode */
-#define PR_0_ORPHAN_ILLEGAL_BLOCK_NUM 0x000021 /* Illegal block found in orphaned inode */
-#define PR_0_ORPHAN_ALREADY_CLEARED_BLOCK 0x000022 /* Already cleared block found in orphaned inode */
-#define PR_0_ORPHAN_ILLEGAL_HEAD_INODE 0x000023 /* Illegal orphan inode in superblock */
-#define PR_0_ORPHAN_ILLEGAL_INODE 0x000024 /* Illegal inode in orphaned inode list */
-#define PR_0_JOURNAL_UNSUPP_ROCOMPAT 0x000025 /* Journal has unsupported read-only feature - abort */
-#define PR_0_JOURNAL_UNSUPP_INCOMPAT 0x000026 /* Journal has unsupported incompatible feature - abort */
-#define PR_0_JOURNAL_UNSUPP_VERSION 0x000027 /* Journal has unsupported version number */
-#define PR_0_MOVE_JOURNAL 0x000028 /* Moving journal to hidden file */
-#define PR_0_ERR_MOVE_JOURNAL 0x000029 /* Error moving journal */
-#define PR_0_CLEAR_V2_JOURNAL 0x00002A /* Clearing V2 journal superblock */
-#define PR_0_JOURNAL_RUN 0x00002B /* Run journal anyway */
-#define PR_0_JOURNAL_RUN_DEFAULT 0x00002C /* Run journal anyway by default */
-#define PR_0_BACKUP_JNL 0x00002D /* Backup journal inode blocks */
-#define PR_0_NONZERO_RESERVED_GDT_BLOCKS 0x00002E /* Reserved blocks w/o resize_inode */
-#define PR_0_CLEAR_RESIZE_INODE 0x00002F /* Resize_inode not enabled, but resize inode is non-zero */
-#define PR_0_RESIZE_INODE_INVALID 0x000030 /* Resize inode invalid */
-
-/*
- * Pass 1 errors
- */
-
-#define PR_1_PASS_HEADER 0x010000 /* Pass 1: Checking inodes, blocks, and sizes */
-#define PR_1_ROOT_NO_DIR 0x010001 /* Root directory is not an inode */
-#define PR_1_ROOT_DTIME 0x010002 /* Root directory has dtime set */
-#define PR_1_RESERVED_BAD_MODE 0x010003 /* Reserved inode has bad mode */
-#define PR_1_ZERO_DTIME 0x010004 /* Deleted inode has zero dtime */
-#define PR_1_SET_DTIME 0x010005 /* Inode in use, but dtime set */
-#define PR_1_ZERO_LENGTH_DIR 0x010006 /* Zero-length directory */
-#define PR_1_BB_CONFLICT 0x010007 /* Block bitmap conflicts with some other fs block */
-#define PR_1_IB_CONFLICT 0x010008 /* Inode bitmap conflicts with some other fs block */
-#define PR_1_ITABLE_CONFLICT 0x010009 /* Inode table conflicts with some other fs block */
-#define PR_1_BB_BAD_BLOCK 0x01000A /* Block bitmap is on a bad block */
-#define PR_1_IB_BAD_BLOCK 0x01000B /* Inode bitmap is on a bad block */
-#define PR_1_BAD_I_SIZE 0x01000C /* Inode has incorrect i_size */
-#define PR_1_BAD_I_BLOCKS 0x01000D /* Inode has incorrect i_blocks */
-#define PR_1_ILLEGAL_BLOCK_NUM 0x01000E /* Illegal block number in inode */
-#define PR_1_BLOCK_OVERLAPS_METADATA 0x01000F /* Block number overlaps fs metadata */
-#define PR_1_INODE_BLOCK_LATCH 0x010010 /* Inode has illegal blocks (latch question) */
-#define PR_1_TOO_MANY_BAD_BLOCKS 0x010011 /* Too many bad blocks in inode */
-#define PR_1_BB_ILLEGAL_BLOCK_NUM 0x010012 /* Illegal block number in bad block inode */
-#define PR_1_INODE_BBLOCK_LATCH 0x010013 /* Bad block inode has illegal blocks (latch question) */
-#define PR_1_DUP_BLOCKS_PREENSTOP 0x010014 /* Duplicate or bad blocks in use! */
-#define PR_1_BBINODE_BAD_METABLOCK 0x010015 /* Bad block used as bad block indirect block */
-#define PR_1_BBINODE_BAD_METABLOCK_PROMPT 0x010016 /* Inconsistency can't be fixed prompt */
-#define PR_1_BAD_PRIMARY_BLOCK 0x010017 /* Bad primary block */
-#define PR_1_BAD_PRIMARY_BLOCK_PROMPT 0x010018 /* Bad primary block prompt */
-#define PR_1_BAD_PRIMARY_SUPERBLOCK 0x010019 /* Bad primary superblock */
-#define PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR 0x01001A /* Bad primary block group descriptors */
-#define PR_1_BAD_SUPERBLOCK 0x01001B /* Bad superblock in group */
-#define PR_1_BAD_GROUP_DESCRIPTORS 0x01001C /* Bad block group descriptors in group */
-#define PR_1_PROGERR_CLAIMED_BLOCK 0x01001D /* Block claimed for no reason */
-#define PR_1_RELOC_BLOCK_ALLOCATE 0x01001E /* Error allocating blocks for relocating metadata */
-#define PR_1_RELOC_MEMORY_ALLOCATE 0x01001F /* Error allocating block buffer during relocation process */
-#define PR_1_RELOC_FROM_TO 0x010020 /* Relocating metadata group information from X to Y */
-#define PR_1_RELOC_TO 0x010021 /* Relocating metatdata group information to X */
-#define PR_1_RELOC_READ_ERR 0x010022 /* Block read error during relocation process */
-#define PR_1_RELOC_WRITE_ERR 0x010023 /* Block write error during relocation process */
-#define PR_1_ALLOCATE_IBITMAP_ERROR 0x010024 /* Error allocating inode bitmap */
-#define PR_1_ALLOCATE_BBITMAP_ERROR 0x010025 /* Error allocating block bitmap */
-#define PR_1_ALLOCATE_ICOUNT 0x010026 /* Error allocating icount structure */
-#define PR_1_ALLOCATE_DBCOUNT 0x010027 /* Error allocating dbcount */
-#define PR_1_ISCAN_ERROR 0x010028 /* Error while scanning inodes */
-#define PR_1_BLOCK_ITERATE 0x010029 /* Error while iterating over blocks */
-#define PR_1_ICOUNT_STORE 0x01002A /* Error while storing inode count information */
-#define PR_1_ADD_DBLOCK 0x01002B /* Error while storing directory block information */
-#define PR_1_READ_INODE 0x01002C /* Error while reading inode (for clearing) */
-#define PR_1_SUPPRESS_MESSAGES 0x01002D /* Suppress messages prompt */
-#define PR_1_SET_IMAGIC 0x01002F /* Imagic flag set on an inode when filesystem doesn't support it */
-#define PR_1_SET_IMMUTABLE 0x010030 /* Immutable flag set on a device or socket inode */
-#define PR_1_COMPR_SET 0x010031 /* Compression flag set on a non-compressed filesystem */
-#define PR_1_SET_NONZSIZE 0x010032 /* Non-zero size on device, fifo or socket inode */
-#define PR_1_FS_REV_LEVEL 0x010033 /* Filesystem revision is 0, but feature flags are set */
-#define PR_1_JOURNAL_INODE_NOT_CLEAR 0x010034 /* Journal inode not in use, needs clearing */
-#define PR_1_JOURNAL_BAD_MODE 0x010035 /* Journal inode has wrong mode */
-#define PR_1_LOW_DTIME 0x010036 /* Inode that was part of orphan linked list */
-#define PR_1_ORPHAN_LIST_REFUGEES 0x010037 /* Latch question which asks how to deal with low dtime inodes */
-#define PR_1_ALLOCATE_REFCOUNT 0x010038 /* Error allocating refcount structure */
-#define PR_1_READ_EA_BLOCK 0x010039 /* Error reading Extended Attribute block */
-#define PR_1_BAD_EA_BLOCK 0x01003A /* Invalid Extended Attribute block */
-#define PR_1_EXTATTR_READ_ABORT 0x01003B /* Error reading Extended Attribute block while fixing refcount -- abort */
-#define PR_1_EXTATTR_REFCOUNT 0x01003C /* Extended attribute reference count incorrect */
-#define PR_1_EXTATTR_WRITE 0x01003D /* Error writing Extended Attribute block while fixing refcount */
-#define PR_1_EA_MULTI_BLOCK 0x01003E /* Multiple EA blocks not supported */
-#define PR_1_EA_ALLOC_REGION 0x01003F /* Error allocating EA region allocation structure */
-#define PR_1_EA_ALLOC_COLLISION 0x010040 /* Error EA allocation collision */
-#define PR_1_EA_BAD_NAME 0x010041 /* Bad extended attribute name */
-#define PR_1_EA_BAD_VALUE 0x010042 /* Bad extended attribute value */
-#define PR_1_INODE_TOOBIG 0x010043 /* Inode too big (latch question) */
-#define PR_1_TOOBIG_DIR 0x010044 /* Directory too big */
-#define PR_1_TOOBIG_REG 0x010045 /* Regular file too big */
-#define PR_1_TOOBIG_SYMLINK 0x010046 /* Symlink too big */
-#define PR_1_HTREE_SET 0x010047 /* INDEX_FL flag set on a non-HTREE filesystem */
-#define PR_1_HTREE_NODIR 0x010048 /* INDEX_FL flag set on a non-directory */
-#define PR_1_HTREE_BADROOT 0x010049 /* Invalid root node in HTREE directory */
-#define PR_1_HTREE_HASHV 0x01004A /* Unsupported hash version in HTREE directory */
-#define PR_1_HTREE_INCOMPAT 0x01004B /* Incompatible flag in HTREE root node */
-#define PR_1_HTREE_DEPTH 0x01004C /* HTREE too deep */
-#define PR_1_BB_FS_BLOCK 0x01004D /* Bad block has indirect block that conflicts with filesystem block */
-#define PR_1_RESIZE_INODE_CREATE 0x01004E /* Resize inode failed */
-#define PR_1_EXTRA_ISIZE 0x01004F /* inode->i_size is too long */
-#define PR_1_ATTR_NAME_LEN 0x010050 /* attribute name is too long */
-#define PR_1_ATTR_VALUE_OFFSET 0x010051 /* wrong EA value offset */
-#define PR_1_ATTR_VALUE_BLOCK 0x010052 /* wrong EA blocknumber */
-#define PR_1_ATTR_VALUE_SIZE 0x010053 /* wrong EA value size */
-#define PR_1_ATTR_HASH 0x010054 /* wrong EA hash value */
-
-/*
- * Pass 1b errors
- */
-
-#define PR_1B_PASS_HEADER 0x011000 /* Pass 1B: Rescan for duplicate/bad blocks */
-#define PR_1B_DUP_BLOCK_HEADER 0x011001 /* Duplicate/bad block(s) header */
-#define PR_1B_DUP_BLOCK 0x011002 /* Duplicate/bad block(s) in inode */
-#define PR_1B_DUP_BLOCK_END 0x011003 /* Duplicate/bad block(s) end */
-#define PR_1B_ISCAN_ERROR 0x011004 /* Error while scanning inodes */
-#define PR_1B_ALLOCATE_IBITMAP_ERROR 0x011005 /* Error allocating inode bitmap */
-#define PR_1B_BLOCK_ITERATE 0x0110006 /* Error while iterating over blocks */
-#define PR_1B_ADJ_EA_REFCOUNT 0x0110007 /* Error adjusting EA refcount */
-#define PR_1C_PASS_HEADER 0x012000 /* Pass 1C: Scan directories for inodes with dup blocks. */
-#define PR_1D_PASS_HEADER 0x013000 /* Pass 1D: Reconciling duplicate blocks */
-#define PR_1D_DUP_FILE 0x013001 /* File has duplicate blocks */
-#define PR_1D_DUP_FILE_LIST 0x013002 /* List of files sharing duplicate blocks */
-#define PR_1D_SHARE_METADATA 0x013003 /* File sharing blocks with filesystem metadata */
-#define PR_1D_NUM_DUP_INODES 0x013004 /* Report of how many duplicate/bad inodes */
-#define PR_1D_DUP_BLOCKS_DEALT 0x013005 /* Duplicated blocks already reassigned or cloned. */
-#define PR_1D_CLONE_QUESTION 0x013006 /* Clone duplicate/bad blocks? */
-#define PR_1D_DELETE_QUESTION 0x013007 /* Delete file? */
-#define PR_1D_CLONE_ERROR 0x013008 /* Couldn't clone file (error) */
-
-/*
- * Pass 2 errors
- */
-
-#define PR_2_PASS_HEADER 0x020000 /* Pass 2: Checking directory structure */
-#define PR_2_BAD_INODE_DOT 0x020001 /* Bad inode number for '.' */
-#define PR_2_BAD_INO 0x020002 /* Directory entry has bad inode number */
-#define PR_2_UNUSED_INODE 0x020003 /* Directory entry has deleted or unused inode */
-#define PR_2_LINK_DOT 0x020004 /* Directry entry is link to '.' */
-#define PR_2_BB_INODE 0x020005 /* Directory entry points to inode now located in a bad block */
-#define PR_2_LINK_DIR 0x020006 /* Directory entry contains a link to a directory */
-#define PR_2_LINK_ROOT 0x020007 /* Directory entry contains a link to the root directry */
-#define PR_2_BAD_NAME 0x020008 /* Directory entry has illegal characters in its name */
-#define PR_2_MISSING_DOT 0x020009 /* Missing '.' in directory inode */
-#define PR_2_MISSING_DOT_DOT 0x02000A /* Missing '..' in directory inode */
-#define PR_2_1ST_NOT_DOT 0x02000B /* First entry in directory inode doesn't contain '.' */
-#define PR_2_2ND_NOT_DOT_DOT 0x02000C /* Second entry in directory inode doesn't contain '..' */
-#define PR_2_FADDR_ZERO 0x02000D /* i_faddr should be zero */
-#define PR_2_FILE_ACL_ZERO 0x02000E /* i_file_acl should be zero */
-#define PR_2_DIR_ACL_ZERO 0x02000F /* i_dir_acl should be zero */
-#define PR_2_FRAG_ZERO 0x020010 /* i_frag should be zero */
-#define PR_2_FSIZE_ZERO 0x020011 /* i_fsize should be zero */
-#define PR_2_BAD_MODE 0x020012 /* inode has bad mode */
-#define PR_2_DIR_CORRUPTED 0x020013 /* directory corrupted */
-#define PR_2_FILENAME_LONG 0x020014 /* filename too long */
-#define PR_2_DIRECTORY_HOLE 0x020015 /* Directory inode has a missing block (hole) */
-#define PR_2_DOT_NULL_TERM 0x020016 /* '.' is not NULL terminated */
-#define PR_2_DOT_DOT_NULL_TERM 0x020017 /* '..' is not NULL terminated */
-#define PR_2_BAD_CHAR_DEV 0x020018 /* Illegal character device in inode */
-#define PR_2_BAD_BLOCK_DEV 0x020019 /* Illegal block device in inode */
-#define PR_2_DUP_DOT 0x02001A /* Duplicate '.' entry */
-#define PR_2_DUP_DOT_DOT 0x02001B /* Duplicate '..' entry */
-#define PR_2_NO_DIRINFO 0x02001C /* Internal error: couldn't find dir_info */
-#define PR_2_FINAL_RECLEN 0x02001D /* Final rec_len is wrong */
-#define PR_2_ALLOCATE_ICOUNT 0x02001E /* Error allocating icount structure */
-#define PR_2_DBLIST_ITERATE 0x02001F /* Error iterating over directory blocks */
-#define PR_2_READ_DIRBLOCK 0x020020 /* Error reading directory block */
-#define PR_2_WRITE_DIRBLOCK 0x020021 /* Error writing directory block */
-#define PR_2_ALLOC_DIRBOCK 0x020022 /* Error allocating new directory block */
-#define PR_2_DEALLOC_INODE 0x020023 /* Error deallocating inode */
-#define PR_2_SPLIT_DOT 0x020024 /* Directory entry for '.' is big. Split? */
-#define PR_2_BAD_FIFO 0x020025 /* Illegal FIFO */
-#define PR_2_BAD_SOCKET 0x020026 /* Illegal socket */
-#define PR_2_SET_FILETYPE 0x020027 /* Directory filetype not set */
-#define PR_2_BAD_FILETYPE 0x020028 /* Directory filetype incorrect */
-#define PR_2_CLEAR_FILETYPE 0x020029 /* Directory filetype set when it shouldn't be */
-#define PR_2_NULL_NAME 0x020030 /* Directory filename can't be zero-length */
-#define PR_2_INVALID_SYMLINK 0x020031 /* Invalid symlink */
-#define PR_2_FILE_ACL_BAD 0x020032 /* i_file_acl (extended attribute) is bad */
-#define PR_2_FEATURE_LARGE_FILES 0x020033 /* Filesystem contains large files, but has no such flag in sb */
-#define PR_2_HTREE_NOTREF 0x020034 /* Node in HTREE directory not referenced */
-#define PR_2_HTREE_DUPREF 0x020035 /* Node in HTREE directory referenced twice */
-#define PR_2_HTREE_MIN_HASH 0x020036 /* Node in HTREE directory has bad min hash */
-#define PR_2_HTREE_MAX_HASH 0x020037 /* Node in HTREE directory has bad max hash */
-#define PR_2_HTREE_CLEAR 0x020038 /* Clear invalid HTREE directory */
-#define PR_2_HTREE_BADBLK 0x02003A /* Bad block in htree interior node */
-#define PR_2_ADJ_EA_REFCOUNT 0x02003B /* Error adjusting EA refcount */
-#define PR_2_HTREE_BAD_ROOT 0x02003C /* Invalid HTREE root node */
-#define PR_2_HTREE_BAD_LIMIT 0x02003D /* Invalid HTREE limit */
-#define PR_2_HTREE_BAD_COUNT 0x02003E /* Invalid HTREE count */
-#define PR_2_HTREE_HASH_ORDER 0x02003F /* HTREE interior node has out-of-order hashes in table */
-#define PR_2_HTREE_BAD_DEPTH 0x020040 /* Node in HTREE directory has bad depth */
-#define PR_2_DUPLICATE_DIRENT 0x020041 /* Duplicate directory entry found */
-#define PR_2_NON_UNIQUE_FILE 0x020042 /* Non-unique filename found */
-#define PR_2_REPORT_DUP_DIRENT 0x020043 /* Duplicate directory entry found */
-
-/*
- * Pass 3 errors
- */
-
-#define PR_3_PASS_HEADER 0x030000 /* Pass 3: Checking directory connectivity */
-#define PR_3_NO_ROOT_INODE 0x030001 /* Root inode not allocated */
-#define PR_3_EXPAND_LF_DIR 0x030002 /* No room in lost+found */
-#define PR_3_UNCONNECTED_DIR 0x030003 /* Unconnected directory inode */
-#define PR_3_NO_LF_DIR 0x030004 /* /lost+found not found */
-#define PR_3_BAD_DOT_DOT 0x030005 /* .. entry is incorrect */
-#define PR_3_NO_LPF 0x030006 /* Bad or non-existent /lost+found. Cannot reconnect */
-#define PR_3_CANT_EXPAND_LPF 0x030007 /* Could not expand /lost+found */
-#define PR_3_CANT_RECONNECT 0x030008 /* Could not reconnect inode */
-#define PR_3_ERR_FIND_LPF 0x030009 /* Error while trying to find /lost+found */
-#define PR_3_ERR_LPF_NEW_BLOCK 0x03000A /* Error in ext2fs_new_block while creating /lost+found */
-#define PR_3_ERR_LPF_NEW_INODE 0x03000B /* Error in ext2fs_new_inode while creating /lost+found */
-#define PR_3_ERR_LPF_NEW_DIR_BLOCK 0x03000C /* Error in ext2fs_new_dir_block while creating /lost+found */
-#define PR_3_ERR_LPF_WRITE_BLOCK 0x03000D /* Error while writing directory block for /lost+found */
-#define PR_3_ADJUST_INODE 0x03000E /* Error while adjusting inode count */
-#define PR_3_FIX_PARENT_ERR 0x03000F /* Couldn't fix parent directory -- error */
-#define PR_3_FIX_PARENT_NOFIND 0x030010 /* Couldn't fix parent directory -- couldn't find it */
-#define PR_3_ALLOCATE_IBITMAP_ERROR 0x030011 /* Error allocating inode bitmap */
-#define PR_3_CREATE_ROOT_ERROR 0x030012 /* Error creating root directory */
-#define PR_3_CREATE_LPF_ERROR 0x030013 /* Error creating lost and found directory */
-#define PR_3_ROOT_NOT_DIR_ABORT 0x030014 /* Root inode is not directory; aborting */
-#define PR_3_NO_ROOT_INODE_ABORT 0x030015 /* Cannot proceed without a root inode. */
-#define PR_3_NO_DIRINFO 0x030016 /* Internal error: couldn't find dir_info */
-#define PR_3_LPF_NOTDIR 0x030017 /* Lost+found is not a directory */
-
-/*
- * Pass 3a --- rehashing diretories
- */
-#define PR_3A_PASS_HEADER 0x031000 /* Pass 3a: Reindexing directories */
-#define PR_3A_OPTIMIZE_ITER 0x031001 /* Error iterating over directories */
-#define PR_3A_OPTIMIZE_DIR_ERR 0x031002 /* Error rehash directory */
-#define PR_3A_OPTIMIZE_DIR_HEADER 0x031003 /* Rehashing dir header */
-#define PR_3A_OPTIMIZE_DIR 0x031004 /* Rehashing directory %d */
-#define PR_3A_OPTIMIZE_DIR_END 0x031005 /* Rehashing dir end */
-
-/*
- * Pass 4 errors
- */
-
-#define PR_4_PASS_HEADER 0x040000 /* Pass 4: Checking reference counts */
-#define PR_4_ZERO_LEN_INODE 0x040001 /* Unattached zero-length inode */
-#define PR_4_UNATTACHED_INODE 0x040002 /* Unattached inode */
-#define PR_4_BAD_REF_COUNT 0x040003 /* Inode ref count wrong */
-#define PR_4_INCONSISTENT_COUNT 0x040004 /* Inconsistent inode count information cached */
-
-/*
- * Pass 5 errors
- */
-
-#define PR_5_PASS_HEADER 0x050000 /* Pass 5: Checking group summary information */
-#define PR_5_INODE_BMAP_PADDING 0x050001 /* Padding at end of inode bitmap is not set. */
-#define PR_5_BLOCK_BMAP_PADDING 0x050002 /* Padding at end of block bitmap is not set. */
-#define PR_5_BLOCK_BITMAP_HEADER 0x050003 /* Block bitmap differences header */
-#define PR_5_BLOCK_UNUSED 0x050004 /* Block not used, but marked in bitmap */
-#define PR_5_BLOCK_USED 0x050005 /* Block used, but not marked used in bitmap */
-#define PR_5_BLOCK_BITMAP_END 0x050006 /* Block bitmap differences end */
-#define PR_5_INODE_BITMAP_HEADER 0x050007 /* Inode bitmap differences header */
-#define PR_5_INODE_UNUSED 0x050008 /* Inode not used, but marked in bitmap */
-#define PR_5_INODE_USED 0x050009 /* Inode used, but not marked used in bitmap */
-#define PR_5_INODE_BITMAP_END 0x05000A /* Inode bitmap differences end */
-#define PR_5_FREE_INODE_COUNT_GROUP 0x05000B /* Free inodes count for group wrong */
-#define PR_5_FREE_DIR_COUNT_GROUP 0x05000C /* Directories count for group wrong */
-#define PR_5_FREE_INODE_COUNT 0x05000D /* Free inodes count wrong */
-#define PR_5_FREE_BLOCK_COUNT_GROUP 0x05000E /* Free blocks count for group wrong */
-#define PR_5_FREE_BLOCK_COUNT 0x05000F /* Free blocks count wrong */
-#define PR_5_BMAP_ENDPOINTS 0x050010 /* Programming error: bitmap endpoints don't match */
-#define PR_5_FUDGE_BITMAP_ERROR 0x050011 /* Internal error: fudging end of bitmap */
-#define PR_5_COPY_IBITMAP_ERROR 0x050012 /* Error copying in replacement inode bitmap */
-#define PR_5_COPY_BBITMAP_ERROR 0x050013 /* Error copying in replacement block bitmap */
-#define PR_5_BLOCK_RANGE_UNUSED 0x050014 /* Block range not used, but marked in bitmap */
-#define PR_5_BLOCK_RANGE_USED 0x050015 /* Block range used, but not marked used in bitmap */
-#define PR_5_INODE_RANGE_UNUSED 0x050016 /* Inode range not used, but marked in bitmap */
-#define PR_5_INODE_RANGE_USED 0x050017 /* Inode rangeused, but not marked used in bitmap */
-
-
-/*
- * The directory information structure; stores directory information
- * collected in earlier passes, to avoid disk i/o in fetching the
- * directory information.
- */
-struct dir_info {
- ext2_ino_t ino; /* Inode number */
- ext2_ino_t dotdot; /* Parent according to '..' */
- ext2_ino_t parent; /* Parent according to treewalk */
-};
-
-
-
-/*
- * The indexed directory information structure; stores information for
- * directories which contain a hash tree index.
- */
-struct dx_dir_info {
- ext2_ino_t ino; /* Inode number */
- int numblocks; /* number of blocks */
- int hashversion;
- short depth; /* depth of tree */
- struct dx_dirblock_info *dx_block; /* Array of size numblocks */
-};
-
-/*
- * Define the extended attribute refcount structure
- */
-typedef struct ea_refcount *ext2_refcount_t;
-
-struct e2fsck_struct {
- ext2_filsys fs;
- const char *program_name;
- char *filesystem_name;
- char *device_name;
- char *io_options;
- int flags; /* E2fsck internal flags */
- int options;
- blk_t use_superblock; /* sb requested by user */
- blk_t superblock; /* sb used to open fs */
- int blocksize; /* blocksize */
- blk_t num_blocks; /* Total number of blocks */
- int mount_flags;
-
- jmp_buf abort_loc;
-
- unsigned long abort_code;
-
- int (*progress)(e2fsck_t ctx, int pass, unsigned long cur,
- unsigned long max);
-
- ext2fs_inode_bitmap inode_used_map; /* Inodes which are in use */
- ext2fs_inode_bitmap inode_bad_map; /* Inodes which are bad somehow */
- ext2fs_inode_bitmap inode_dir_map; /* Inodes which are directories */
- ext2fs_inode_bitmap inode_imagic_map; /* AFS inodes */
- ext2fs_inode_bitmap inode_reg_map; /* Inodes which are regular files*/
-
- ext2fs_block_bitmap block_found_map; /* Blocks which are in use */
- ext2fs_block_bitmap block_dup_map; /* Blks referenced more than once */
- ext2fs_block_bitmap block_ea_map; /* Blocks which are used by EA's */
-
- /*
- * Inode count arrays
- */
- ext2_icount_t inode_count;
- ext2_icount_t inode_link_info;
-
- ext2_refcount_t refcount;
- ext2_refcount_t refcount_extra;
-
- /*
- * Array of flags indicating whether an inode bitmap, block
- * bitmap, or inode table is invalid
- */
- int *invalid_inode_bitmap_flag;
- int *invalid_block_bitmap_flag;
- int *invalid_inode_table_flag;
- int invalid_bitmaps; /* There are invalid bitmaps/itable */
-
- /*
- * Block buffer
- */
- char *block_buf;
-
- /*
- * For pass1_check_directory and pass1_get_blocks
- */
- ext2_ino_t stashed_ino;
- struct ext2_inode *stashed_inode;
-
- /*
- * Location of the lost and found directory
- */
- ext2_ino_t lost_and_found;
- int bad_lost_and_found;
-
- /*
- * Directory information
- */
- int dir_info_count;
- int dir_info_size;
- struct dir_info *dir_info;
-
- /*
- * Indexed directory information
- */
- int dx_dir_info_count;
- int dx_dir_info_size;
- struct dx_dir_info *dx_dir_info;
-
- /*
- * Directories to hash
- */
- ext2_u32_list dirs_to_hash;
-
- /*
- * Tuning parameters
- */
- int process_inode_size;
- int inode_buffer_blocks;
-
- /*
- * ext3 journal support
- */
- io_channel journal_io;
- char *journal_name;
-
- /*
- * How we display the progress update (for unix)
- */
- int progress_fd;
- int progress_pos;
- int progress_last_percent;
- unsigned int progress_last_time;
- int interactive; /* Are we connected directly to a tty? */
- char start_meta[2], stop_meta[2];
-
- /* File counts */
- int fs_directory_count;
- int fs_regular_count;
- int fs_blockdev_count;
- int fs_chardev_count;
- int fs_links_count;
- int fs_symlinks_count;
- int fs_fast_symlinks_count;
- int fs_fifo_count;
- int fs_total_count;
- int fs_sockets_count;
- int fs_ind_count;
- int fs_dind_count;
- int fs_tind_count;
- int fs_fragmented;
- int large_files;
- int fs_ext_attr_inodes;
- int fs_ext_attr_blocks;
-
- int ext_attr_ver;
-
- /*
- * For the use of callers of the e2fsck functions; not used by
- * e2fsck functions themselves.
- */
- void *priv_data;
-};
-
-
-#define tid_gt(x, y) ((x - y) > 0)
-
-static inline int tid_geq(tid_t x, tid_t y)
-{
- int difference = (x - y);
- return (difference >= 0);
-}
diff --git a/release/src/router/busybox/e2fsprogs/e2p/Kbuild.src b/release/src/router/busybox/e2fsprogs/e2p/Kbuild.src
deleted file mode 100644
index 01ac720b94..0000000000
--- a/release/src/router/busybox/e2fsprogs/e2p/Kbuild.src
+++ /dev/null
@@ -1,18 +0,0 @@
-# Makefile for busybox
-#
-# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
-#
-# Licensed under GPLv2, see file LICENSE in this source tree.
-
-NEEDED-$(CONFIG_CHATTR) = y
-NEEDED-$(CONFIG_LSATTR) = y
-NEEDED-$(CONFIG_MKE2FS) = y
-NEEDED-$(CONFIG_TUNE2FS) = y
-
-lib-y:=
-
-INSERT
-
-lib-$(NEEDED-y) += mntopts.o \
- feature.o ls.o pe.o ostype.o ps.o hashstr.o \
- parse_num.o
diff --git a/release/src/router/busybox/e2fsprogs/e2p/e2p.h b/release/src/router/busybox/e2fsprogs/e2p/e2p.h
deleted file mode 100644
index 2abb92c8f3..0000000000
--- a/release/src/router/busybox/e2fsprogs/e2p/e2p.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* vi: set sw=4 ts=4: */
-#include "libbb.h"
-#include <sys/types.h> /* Needed by dirent.h on netbsd */
-#include <stdio.h>
-#include <dirent.h>
-
-#include "../ext2fs/ext2_fs.h"
-
-#define E2P_FEATURE_COMPAT 0
-#define E2P_FEATURE_INCOMPAT 1
-#define E2P_FEATURE_RO_INCOMPAT 2
-#ifndef EXT3_FEATURE_INCOMPAT_EXTENTS
-#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040
-#endif
-
-/* `options' for print_e2flags() */
-
-#define PFOPT_LONG 1 /* Must be 1 for compatibility with `int long_format'. */
-
-
-/*void list_super(struct ext2_super_block * s);*/
-void list_super2(struct ext2_super_block * s, FILE *f);
-#define list_super(s) list_super2(s, stdout)
-void print_fs_errors (FILE *f, unsigned short errors);
-void print_fs_state (FILE *f, unsigned short state);
-
-const char *e2p_feature2string(int compat, unsigned int mask);
-int e2p_string2feature(char *string, int *compat, unsigned int *mask);
-int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array);
-
-const char *e2p_hash2string(int num);
-int e2p_string2hash(char *string);
-
-const char *e2p_mntopt2string(unsigned int mask);
-int e2p_string2mntopt(char *string, unsigned int *mask);
-int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok);
-
-unsigned long parse_num_blocks(const char *arg, int log_block_size);
-
-char *e2p_os2string(int os_type);
-int e2p_string2os(char *str);
diff --git a/release/src/router/busybox/e2fsprogs/e2p/feature.c b/release/src/router/busybox/e2fsprogs/e2p/feature.c
deleted file mode 100644
index 2102ed8e76..0000000000
--- a/release/src/router/busybox/e2fsprogs/e2p/feature.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * feature.c --- convert between features and strings
- *
- * Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu>
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-
-#include "e2p.h"
-
-struct feature {
- int compat;
- unsigned int mask;
- const char *string;
-};
-
-static const struct feature feature_list[] = {
- { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_PREALLOC,
- "dir_prealloc" },
- { E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL,
- "has_journal" },
- { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_IMAGIC_INODES,
- "imagic_inodes" },
- { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_EXT_ATTR,
- "ext_attr" },
- { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX,
- "dir_index" },
- { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_RESIZE_INO,
- "resize_inode" },
- { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER,
- "sparse_super" },
- { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_LARGE_FILE,
- "large_file" },
- { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_COMPRESSION,
- "compression" },
- { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_FILETYPE,
- "filetype" },
- { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_RECOVER,
- "needs_recovery" },
- { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV,
- "journal_dev" },
- { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS,
- "extents" },
- { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_META_BG,
- "meta_bg" },
- { 0, 0, 0 },
-};
-
-const char *e2p_feature2string(int compat, unsigned int mask)
-{
- const struct feature *f;
- static char buf[20];
- char fchar;
- int fnum;
-
- for (f = feature_list; f->string; f++) {
- if ((compat == f->compat) &&
- (mask == f->mask))
- return f->string;
- }
- switch (compat) {
- case E2P_FEATURE_COMPAT:
- fchar = 'C';
- break;
- case E2P_FEATURE_INCOMPAT:
- fchar = 'I';
- break;
- case E2P_FEATURE_RO_INCOMPAT:
- fchar = 'R';
- break;
- default:
- fchar = '?';
- break;
- }
- for (fnum = 0; mask >>= 1; fnum++);
- sprintf(buf, "FEATURE_%c%d", fchar, fnum);
- return buf;
-}
-
-int e2p_string2feature(char *string, int *compat_type, unsigned int *mask)
-{
- const struct feature *f;
- char *eptr;
- int num;
-
- for (f = feature_list; f->string; f++) {
- if (!strcasecmp(string, f->string)) {
- *compat_type = f->compat;
- *mask = f->mask;
- return 0;
- }
- }
- if (strncasecmp(string, "FEATURE_", 8))
- return 1;
-
- switch (string[8]) {
- case 'c':
- case 'C':
- *compat_type = E2P_FEATURE_COMPAT;
- break;
- case 'i':
- case 'I':
- *compat_type = E2P_FEATURE_INCOMPAT;
- break;
- case 'r':
- case 'R':
- *compat_type = E2P_FEATURE_RO_INCOMPAT;
- break;
- default:
- return 1;
- }
- if (string[9] == 0)
- return 1;
- num = strtol(string+9, &eptr, 10);
- if (num > 32 || num < 0)
- return 1;
- if (*eptr)
- return 1;
- *mask = 1 << num;
- return 0;
-}
-
-static inline char *skip_over_blanks(char *cp)
-{
- while (*cp && isspace(*cp))
- cp++;
- return cp;
-}
-
-static inline char *skip_over_word(char *cp)
-{
- while (*cp && !isspace(*cp) && *cp != ',')
- cp++;
- return cp;
-}
-
-/*
- * Edit a feature set array as requested by the user. The ok_array,
- * if set, allows the application to limit what features the user is
- * allowed to set or clear using this function.
- */
-int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array)
-{
- char *cp, *buf, *next;
- int neg;
- unsigned int mask;
- int compat_type;
-
- buf = xstrdup(str);
- cp = buf;
- while (cp && *cp) {
- neg = 0;
- cp = skip_over_blanks(cp);
- next = skip_over_word(cp);
- if (*next == 0)
- next = 0;
- else
- *next = 0;
- switch (*cp) {
- case '-':
- case '^':
- neg++;
- case '+':
- cp++;
- break;
- }
- if (e2p_string2feature(cp, &compat_type, &mask))
- return 1;
- if (ok_array && !(ok_array[compat_type] & mask))
- return 1;
- if (neg)
- compat_array[compat_type] &= ~mask;
- else
- compat_array[compat_type] |= mask;
- cp = next ? next+1 : 0;
- }
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/e2p/fgetsetflags.c b/release/src/router/busybox/e2fsprogs/e2p/fgetsetflags.c
deleted file mode 100644
index 008b798504..0000000000
--- a/release/src/router/busybox/e2fsprogs/e2p/fgetsetflags.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * fgetflags.c - Get a file flags on an ext2 file system
- * fsetflags.c - Set a file flags on an ext2 file system
- *
- * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
- * Laboratoire MASI, Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- */
-
-/*
- * History:
- * 93/10/30 - Creation
- */
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef HAVE_EXT2_IOCTLS
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#endif
-
-#include "e2p.h"
-
-#ifdef O_LARGEFILE
-#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
-#else
-#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
-#endif
-
-int fgetsetflags (const char * name, unsigned long * get_flags, unsigned long set_flags)
-{
-#ifdef HAVE_EXT2_IOCTLS
- struct stat buf;
- int fd, r, f, save_errno = 0;
-
- if (!stat(name, &buf) &&
- !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) {
- goto notsupp;
- }
- fd = open (name, OPEN_FLAGS);
- if (fd == -1)
- return -1;
- if (!get_flags) {
- f = (int) set_flags;
- r = ioctl (fd, EXT2_IOC_SETFLAGS, &f);
- } else {
- r = ioctl (fd, EXT2_IOC_GETFLAGS, &f);
- *get_flags = f;
- }
- if (r == -1)
- save_errno = errno;
- close (fd);
- if (save_errno)
- errno = save_errno;
- return r;
-notsupp:
-#endif /* HAVE_EXT2_IOCTLS */
- errno = EOPNOTSUPP;
- return -1;
-}
diff --git a/release/src/router/busybox/e2fsprogs/e2p/fgetsetversion.c b/release/src/router/busybox/e2fsprogs/e2p/fgetsetversion.c
deleted file mode 100644
index 8d79054d6a..0000000000
--- a/release/src/router/busybox/e2fsprogs/e2p/fgetsetversion.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * fgetversion.c - Get a file version on an ext2 file system
- * fsetversion.c - Set a file version on an ext2 file system
- *
- *
- * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
- * Laboratoire MASI, Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- */
-
-/*
- * History:
- * 93/10/30 - Creation
- */
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <sys/ioctl.h>
-
-#include "e2p.h"
-
-#ifdef O_LARGEFILE
-#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
-#else
-#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
-#endif
-
-/*
- To do fsetversion: unsigned long *ptr_version must be set to NULL.
- and unsigned long version must be set to a value
- To do fgetversion: unsigned long *ptr_version must NOT be set to NULL
- and unsigned long version is ignored.
- TITO.
-*/
-
-int fgetsetversion (const char * name, unsigned long * get_version, unsigned long set_version)
-{
-#ifdef HAVE_EXT2_IOCTLS
- int fd, r, ver, save_errno = 0;
-
- fd = open (name, OPEN_FLAGS);
- if (fd == -1)
- return -1;
- if (!get_version) {
- ver = (int) set_version;
- r = ioctl (fd, EXT2_IOC_SETVERSION, &ver);
- } else {
- r = ioctl (fd, EXT2_IOC_GETVERSION, &ver);
- *get_version = ver;
- }
- if (r == -1)
- save_errno = errno;
- close (fd);
- if (save_errno)
- errno = save_errno;
- return r;
-#else /* ! HAVE_EXT2_IOCTLS */
- errno = EOPNOTSUPP;
- return -1;
-#endif /* ! HAVE_EXT2_IOCTLS */
-}
diff --git a/release/src/router/busybox/e2fsprogs/e2p/hashstr.c b/release/src/router/busybox/e2fsprogs/e2p/hashstr.c
deleted file mode 100644
index 697ffadc37..0000000000
--- a/release/src/router/busybox/e2fsprogs/e2p/hashstr.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * feature.c --- convert between features and strings
- *
- * Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu>
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-
-#include "e2p.h"
-
-struct hash {
- int num;
- const char *string;
-};
-
-static const struct hash hash_list[] = {
- { EXT2_HASH_LEGACY, "legacy" },
- { EXT2_HASH_HALF_MD4, "half_md4" },
- { EXT2_HASH_TEA, "tea" },
- { 0, 0 },
-};
-
-const char *e2p_hash2string(int num)
-{
- const struct hash *p;
- static char buf[20];
-
- for (p = hash_list; p->string; p++) {
- if (num == p->num)
- return p->string;
- }
- sprintf(buf, "HASHALG_%d", num);
- return buf;
-}
-
-/*
- * Returns the hash algorithm, or -1 on error
- */
-int e2p_string2hash(char *string)
-{
- const struct hash *p;
- char *eptr;
- int num;
-
- for (p = hash_list; p->string; p++) {
- if (!strcasecmp(string, p->string)) {
- return p->num;
- }
- }
- if (strncasecmp(string, "HASHALG_", 8))
- return -1;
-
- if (string[8] == 0)
- return -1;
- num = strtol(string+8, &eptr, 10);
- if (num > 255 || num < 0)
- return -1;
- if (*eptr)
- return -1;
- return num;
-}
diff --git a/release/src/router/busybox/e2fsprogs/e2p/iod.c b/release/src/router/busybox/e2fsprogs/e2p/iod.c
deleted file mode 100644
index 23ab8d5b54..0000000000
--- a/release/src/router/busybox/e2fsprogs/e2p/iod.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * iod.c - Iterate a function on each entry of a directory
- *
- * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
- * Laboratoire MASI, Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- */
-
-/*
- * History:
- * 93/10/30 - Creation
- */
-
-#include "e2p.h"
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-
-int iterate_on_dir (const char * dir_name,
- int (*func) (const char *, struct dirent *, void *),
- void * private)
-{
- DIR * dir;
- struct dirent *de, *dep;
- int max_len, len;
-
- max_len = PATH_MAX + sizeof(struct dirent);
- de = xmalloc(max_len+1);
- memset(de, 0, max_len+1);
-
- dir = opendir (dir_name);
- if (dir == NULL) {
- free(de);
- return -1;
- }
- while ((dep = readdir (dir))) {
- len = sizeof(struct dirent);
- if (len < dep->d_reclen)
- len = dep->d_reclen;
- if (len > max_len)
- len = max_len;
- memcpy(de, dep, len);
- (*func) (dir_name, de, private);
- }
- free(de);
- closedir(dir);
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/e2p/ls.c b/release/src/router/busybox/e2fsprogs/e2p/ls.c
deleted file mode 100644
index 4a2ed5ff8d..0000000000
--- a/release/src/router/busybox/e2fsprogs/e2p/ls.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * ls.c - List the contents of an ext2fs superblock
- *
- * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr>
- * Laboratoire MASI, Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * Copyright (C) 1995, 1996, 1997 Theodore Ts'o <tytso@mit.edu>
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <string.h>
-#include <grp.h>
-#include <pwd.h>
-#include <time.h>
-
-#include "e2p.h"
-#include "../e2fs_lib.h"
-
-static void print_user(unsigned short uid, FILE *f)
-{
- struct passwd *pw = getpwuid(uid);
- fprintf(f, "%u (user %s)\n", uid,
- (pw == NULL ? "unknown" : pw->pw_name));
-}
-
-static void print_group(unsigned short gid, FILE *f)
-{
- struct group *gr = getgrgid(gid);
- fprintf(f, "%u (group %s)\n", gid,
- (gr == NULL ? "unknown" : gr->gr_name));
-}
-
-#define MONTH_INT (86400 * 30)
-#define WEEK_INT (86400 * 7)
-#define DAY_INT (86400)
-#define HOUR_INT (60 * 60)
-#define MINUTE_INT (60)
-
-static const char *interval_string(unsigned int secs)
-{
- static char buf[256], tmp[80];
- int hr, min, num;
-
- buf[0] = 0;
-
- if (secs == 0)
- return "<none>";
-
- if (secs >= MONTH_INT) {
- num = secs / MONTH_INT;
- secs -= num*MONTH_INT;
- sprintf(buf, "%d month%s", num, (num>1) ? "s" : "");
- }
- if (secs >= WEEK_INT) {
- num = secs / WEEK_INT;
- secs -= num*WEEK_INT;
- sprintf(tmp, "%s%d week%s", buf[0] ? ", " : "",
- num, (num>1) ? "s" : "");
- strcat(buf, tmp);
- }
- if (secs >= DAY_INT) {
- num = secs / DAY_INT;
- secs -= num*DAY_INT;
- sprintf(tmp, "%s%d day%s", buf[0] ? ", " : "",
- num, (num>1) ? "s" : "");
- strcat(buf, tmp);
- }
- if (secs > 0) {
- hr = secs / HOUR_INT;
- secs -= hr*HOUR_INT;
- min = secs / MINUTE_INT;
- secs -= min*MINUTE_INT;
- sprintf(tmp, "%s%d:%02d:%02d", buf[0] ? ", " : "",
- hr, min, secs);
- strcat(buf, tmp);
- }
- return buf;
-}
-
-static void print_features(struct ext2_super_block * s, FILE *f)
-{
-#ifdef EXT2_DYNAMIC_REV
- int i, j, printed=0;
- __u32 *mask = &s->s_feature_compat, m;
-
- fprintf(f, "Filesystem features: ");
- for (i=0; i <3; i++,mask++) {
- for (j=0,m=1; j < 32; j++, m<<=1) {
- if (*mask & m) {
- fprintf(f, " %s", e2p_feature2string(i, m));
- printed++;
- }
- }
- }
- if (printed == 0)
- fprintf(f, " (none)");
- fprintf(f, "\n");
-#endif
-}
-
-static void print_mntopts(struct ext2_super_block * s, FILE *f)
-{
-#ifdef EXT2_DYNAMIC_REV
- int i, printed=0;
- __u32 mask = s->s_default_mount_opts, m;
-
- fprintf(f, "Default mount options: ");
- if (mask & EXT3_DEFM_JMODE) {
- fprintf(f, " %s", e2p_mntopt2string(mask & EXT3_DEFM_JMODE));
- printed++;
- }
- for (i=0,m=1; i < 32; i++, m<<=1) {
- if (m & EXT3_DEFM_JMODE)
- continue;
- if (mask & m) {
- fprintf(f, " %s", e2p_mntopt2string(m));
- printed++;
- }
- }
- if (printed == 0)
- fprintf(f, " (none)");
- fprintf(f, "\n");
-#endif
-}
-
-
-#ifndef EXT2_INODE_SIZE
-#define EXT2_INODE_SIZE(s) sizeof(struct ext2_inode)
-#endif
-
-#ifndef EXT2_GOOD_OLD_REV
-#define EXT2_GOOD_OLD_REV 0
-#endif
-
-void list_super2(struct ext2_super_block * sb, FILE *f)
-{
- int inode_blocks_per_group;
- char buf[80], uuid_buf[37], *str;
- time_t tm;
-
- inode_blocks_per_group = (((sb->s_inodes_per_group *
- EXT2_INODE_SIZE(sb)) +
- EXT2_BLOCK_SIZE(sb) - 1) /
- EXT2_BLOCK_SIZE(sb));
- if (sb->s_volume_name[0]) {
- memset(buf, 0, sizeof(buf));
- strncpy(buf, sb->s_volume_name, sizeof(sb->s_volume_name));
- } else
- strcpy(buf, "<none>");
- fprintf(f, "Filesystem volume name: %s\n", buf);
- if (sb->s_last_mounted[0]) {
- memset(buf, 0, sizeof(buf));
- strncpy(buf, sb->s_last_mounted, sizeof(sb->s_last_mounted));
- } else
- strcpy(buf, "<not available>");
- fprintf(f,
- "Last mounted on: %s\n"
- "Filesystem UUID: %s\n"
- "Filesystem magic number: 0x%04X\n"
- "Filesystem revision #: %d",
- buf, unparse_uuid(sb->s_uuid, uuid_buf), sb->s_magic, sb->s_rev_level);
- if (sb->s_rev_level == EXT2_GOOD_OLD_REV) {
- fprintf(f, " (original)\n");
-#ifdef EXT2_DYNAMIC_REV
- } else if (sb->s_rev_level == EXT2_DYNAMIC_REV) {
- fprintf(f, " (dynamic)\n");
-#endif
- } else
- fprintf(f, " (unknown)\n");
- print_features(sb, f);
- print_mntopts(sb, f);
- fprintf(f, "Filesystem state: ");
- print_fs_state (f, sb->s_state);
- fprintf(f, "\nErrors behavior: ");
- print_fs_errors(f, sb->s_errors);
- str = e2p_os2string(sb->s_creator_os);
- fprintf(f,
- "\n"
- "Filesystem OS type: %s\n"
- "Inode count: %u\n"
- "Block count: %u\n"
- "Reserved block count: %u\n"
- "Free blocks: %u\n"
- "Free inodes: %u\n"
- "First block: %u\n"
- "Block size: %u\n"
- "Fragment size: %u\n",
- str, sb->s_inodes_count, sb->s_blocks_count, sb->s_r_blocks_count,
- sb->s_free_blocks_count, sb->s_free_inodes_count,
- sb->s_first_data_block, EXT2_BLOCK_SIZE(sb), EXT2_FRAG_SIZE(sb));
- free(str);
- if (sb->s_reserved_gdt_blocks)
- fprintf(f, "Reserved GDT blocks: %u\n",
- sb->s_reserved_gdt_blocks);
- fprintf(f,
- "Blocks per group: %u\n"
- "Fragments per group: %u\n"
- "Inodes per group: %u\n"
- "Inode blocks per group: %u\n",
- sb->s_blocks_per_group, sb->s_frags_per_group,
- sb->s_inodes_per_group, inode_blocks_per_group);
- if (sb->s_first_meta_bg)
- fprintf(f, "First meta block group: %u\n",
- sb->s_first_meta_bg);
- if (sb->s_mkfs_time) {
- tm = sb->s_mkfs_time;
- fprintf(f, "Filesystem created: %s", ctime(&tm));
- }
- tm = sb->s_mtime;
- fprintf(f, "Last mount time: %s",
- sb->s_mtime ? ctime(&tm) : "n/a\n");
- tm = sb->s_wtime;
- fprintf(f,
- "Last write time: %s"
- "Mount count: %u\n"
- "Maximum mount count: %d\n",
- ctime(&tm), sb->s_mnt_count, sb->s_max_mnt_count);
- tm = sb->s_lastcheck;
- fprintf(f,
- "Last checked: %s"
- "Check interval: %u (%s)\n",
- ctime(&tm),
- sb->s_checkinterval, interval_string(sb->s_checkinterval));
- if (sb->s_checkinterval)
- {
- time_t next;
-
- next = sb->s_lastcheck + sb->s_checkinterval;
- fprintf(f, "Next check after: %s", ctime(&next));
- }
- fprintf(f, "Reserved blocks uid: ");
- print_user(sb->s_def_resuid, f);
- fprintf(f, "Reserved blocks gid: ");
- print_group(sb->s_def_resgid, f);
- if (sb->s_rev_level >= EXT2_DYNAMIC_REV) {
- fprintf(f,
- "First inode: %d\n"
- "Inode size: %d\n",
- sb->s_first_ino, sb->s_inode_size);
- }
- if (!uuid_is_null(sb->s_journal_uuid))
- fprintf(f, "Journal UUID: %s\n",
- unparse_uuid(sb->s_journal_uuid, uuid_buf));
- if (sb->s_journal_inum)
- fprintf(f, "Journal inode: %u\n",
- sb->s_journal_inum);
- if (sb->s_journal_dev)
- fprintf(f, "Journal device: 0x%04x\n",
- sb->s_journal_dev);
- if (sb->s_last_orphan)
- fprintf(f, "First orphan inode: %u\n",
- sb->s_last_orphan);
- if ((sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
- sb->s_def_hash_version)
- fprintf(f, "Default directory hash: %s\n",
- e2p_hash2string(sb->s_def_hash_version));
- if (!uuid_is_null(sb->s_hash_seed))
- fprintf(f, "Directory Hash Seed: %s\n",
- unparse_uuid((unsigned char *)sb->s_hash_seed, uuid_buf));
- if (sb->s_jnl_backup_type) {
- fprintf(f, "Journal backup: ");
- if (sb->s_jnl_backup_type == 1)
- fprintf(f, "inode blocks\n");
- else
- fprintf(f, "type %u\n", sb->s_jnl_backup_type);
- }
-}
diff --git a/release/src/router/busybox/e2fsprogs/e2p/mntopts.c b/release/src/router/busybox/e2fsprogs/e2p/mntopts.c
deleted file mode 100644
index 17c26c480b..0000000000
--- a/release/src/router/busybox/e2fsprogs/e2p/mntopts.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * mountopts.c --- convert between default mount options and strings
- *
- * Copyright (C) 2002 Theodore Ts'o <tytso@mit.edu>
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-
-#include "e2p.h"
-
-struct mntopt {
- unsigned int mask;
- const char *string;
-};
-
-static const struct mntopt mntopt_list[] = {
- { EXT2_DEFM_DEBUG, "debug" },
- { EXT2_DEFM_BSDGROUPS, "bsdgroups" },
- { EXT2_DEFM_XATTR_USER, "user_xattr" },
- { EXT2_DEFM_ACL, "acl" },
- { EXT2_DEFM_UID16, "uid16" },
- { EXT3_DEFM_JMODE_DATA, "journal_data" },
- { EXT3_DEFM_JMODE_ORDERED, "journal_data_ordered" },
- { EXT3_DEFM_JMODE_WBACK, "journal_data_writeback" },
- { 0, 0 },
-};
-
-const char *e2p_mntopt2string(unsigned int mask)
-{
- const struct mntopt *f;
- static char buf[20];
- int fnum;
-
- for (f = mntopt_list; f->string; f++) {
- if (mask == f->mask)
- return f->string;
- }
- for (fnum = 0; mask >>= 1; fnum++);
- sprintf(buf, "MNTOPT_%d", fnum);
- return buf;
-}
-
-int e2p_string2mntopt(char *string, unsigned int *mask)
-{
- const struct mntopt *f;
- char *eptr;
- int num;
-
- for (f = mntopt_list; f->string; f++) {
- if (!strcasecmp(string, f->string)) {
- *mask = f->mask;
- return 0;
- }
- }
- if (strncasecmp(string, "MNTOPT_", 8))
- return 1;
-
- if (string[8] == 0)
- return 1;
- num = strtol(string+8, &eptr, 10);
- if (num > 32 || num < 0)
- return 1;
- if (*eptr)
- return 1;
- *mask = 1 << num;
- return 0;
-}
-
-static char *skip_over_blanks(char *cp)
-{
- while (*cp && isspace(*cp))
- cp++;
- return cp;
-}
-
-static char *skip_over_word(char *cp)
-{
- while (*cp && !isspace(*cp) && *cp != ',')
- cp++;
- return cp;
-}
-
-/*
- * Edit a mntopt set array as requested by the user. The ok
- * parameter, if non-zero, allows the application to limit what
- * mntopts the user is allowed to set or clear using this function.
- */
-int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok)
-{
- char *cp, *buf, *next;
- int neg;
- unsigned int mask;
-
- buf = xstrdup(str);
- cp = buf;
- while (cp && *cp) {
- neg = 0;
- cp = skip_over_blanks(cp);
- next = skip_over_word(cp);
- if (*next == 0)
- next = 0;
- else
- *next = 0;
- switch (*cp) {
- case '-':
- case '^':
- neg++;
- case '+':
- cp++;
- break;
- }
- if (e2p_string2mntopt(cp, &mask))
- return 1;
- if (ok && !(ok & mask))
- return 1;
- if (mask & EXT3_DEFM_JMODE)
- *mntopts &= ~EXT3_DEFM_JMODE;
- if (neg)
- *mntopts &= ~mask;
- else
- *mntopts |= mask;
- cp = next ? next+1 : 0;
- }
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/e2p/ostype.c b/release/src/router/busybox/e2fsprogs/e2p/ostype.c
deleted file mode 100644
index 6a2f178f33..0000000000
--- a/release/src/router/busybox/e2fsprogs/e2p/ostype.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * getostype.c - Get the Filesystem OS type
- *
- * Copyright (C) 2004,2005 Theodore Ts'o <tytso@mit.edu>
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- */
-
-#include "e2p.h"
-#include <string.h>
-#include <stdlib.h>
-
-static const char *const os_tab[] =
- { "Linux",
- "Hurd",
- "Masix",
- "FreeBSD",
- "Lites",
- 0 };
-
-/*
- * Convert an os_type to a string
- */
-char *e2p_os2string(int os_type)
-{
- const char *os;
- char *ret;
-
- if (os_type <= EXT2_OS_LITES)
- os = os_tab[os_type];
- else
- os = "(unknown os)";
-
- ret = xstrdup(os);
- return ret;
-}
-
-/*
- * Convert an os_type to a string
- */
-int e2p_string2os(char *str)
-{
- const char *const *cpp;
- int i = 0;
-
- for (cpp = os_tab; *cpp; cpp++, i++) {
- if (!strcasecmp(str, *cpp))
- return i;
- }
- return -1;
-}
-
-#ifdef TEST_PROGRAM
-int main(int argc, char **argv)
-{
- char *s;
- int i, os;
-
- for (i=0; i <= EXT2_OS_LITES; i++) {
- s = e2p_os2string(i);
- os = e2p_string2os(s);
- printf("%d: %s (%d)\n", i, s, os);
- if (i != os) {
- fprintf(stderr, "Failure!\n");
- exit(1);
- }
- }
- exit(0);
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/e2p/parse_num.c b/release/src/router/busybox/e2fsprogs/e2p/parse_num.c
deleted file mode 100644
index 6db076f9cd..0000000000
--- a/release/src/router/busybox/e2fsprogs/e2p/parse_num.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * parse_num.c - Parse the number of blocks
- *
- * Copyright (C) 2004,2005 Theodore Ts'o <tytso@mit.edu>
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- */
-
-#include "e2p.h"
-
-#include <stdlib.h>
-
-unsigned long parse_num_blocks(const char *arg, int log_block_size)
-{
- char *p;
- unsigned long long num;
-
- num = strtoull(arg, &p, 0);
-
- if (p[0] && p[1])
- return 0;
-
- switch (*p) { /* Using fall-through logic */
- case 'T': case 't':
- num <<= 10;
- case 'G': case 'g':
- num <<= 10;
- case 'M': case 'm':
- num <<= 10;
- case 'K': case 'k':
- num >>= log_block_size;
- break;
- case 's':
- num >>= 1;
- break;
- case '\0':
- break;
- default:
- return 0;
- }
- return num;
-}
-
-#ifdef DEBUG
-#include <unistd.h>
-#include <stdio.h>
-
-main(int argc, char **argv)
-{
- unsigned long num;
- int log_block_size = 0;
-
- if (argc != 2) {
- fprintf(stderr, "Usage: %s arg\n", argv[0]);
- exit(1);
- }
-
- num = parse_num_blocks(argv[1], log_block_size);
-
- printf("Parsed number: %lu\n", num);
- exit(0);
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/e2p/pe.c b/release/src/router/busybox/e2fsprogs/e2p/pe.c
deleted file mode 100644
index fd96dbeea4..0000000000
--- a/release/src/router/busybox/e2fsprogs/e2p/pe.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * pe.c - Print a second extended filesystem errors behavior
- *
- * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr>
- * Laboratoire MASI, Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- */
-
-/*
- * History:
- * 94/01/09 - Creation
- */
-
-#include <stdio.h>
-
-#include "e2p.h"
-
-void print_fs_errors(FILE *f, unsigned short errors)
-{
- const char *disp = NULL;
- switch (errors) {
- case EXT2_ERRORS_CONTINUE: disp = "Continue"; break;
- case EXT2_ERRORS_RO: disp = "Remount read-only"; break;
- case EXT2_ERRORS_PANIC: disp = "Panic"; break;
- default: disp = "Unknown (continue)";
- }
- fprintf(f, disp);
-}
diff --git a/release/src/router/busybox/e2fsprogs/e2p/pf.c b/release/src/router/busybox/e2fsprogs/e2p/pf.c
deleted file mode 100644
index 02cbec7e0f..0000000000
--- a/release/src/router/busybox/e2fsprogs/e2p/pf.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * pf.c - Print file attributes on an ext2 file system
- *
- * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
- * Laboratoire MASI, Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- */
-
-/*
- * History:
- * 93/10/30 - Creation
- */
-
-#include <stdio.h>
-
-#include "e2p.h"
-
-struct flags_name {
- unsigned long flag;
- const char *short_name;
- const char *long_name;
-};
-
-static const struct flags_name flags_array[] = {
- { EXT2_SECRM_FL, "s", "Secure_Deletion" },
- { EXT2_UNRM_FL, "u" , "Undelete" },
- { EXT2_SYNC_FL, "S", "Synchronous_Updates" },
- { EXT2_DIRSYNC_FL, "D", "Synchronous_Directory_Updates" },
- { EXT2_IMMUTABLE_FL, "i", "Immutable" },
- { EXT2_APPEND_FL, "a", "Append_Only" },
- { EXT2_NODUMP_FL, "d", "No_Dump" },
- { EXT2_NOATIME_FL, "A", "No_Atime" },
- { EXT2_COMPR_FL, "c", "Compression_Requested" },
-#ifdef ENABLE_COMPRESSION
- { EXT2_COMPRBLK_FL, "B", "Compressed_File" },
- { EXT2_DIRTY_FL, "Z", "Compressed_Dirty_File" },
- { EXT2_NOCOMPR_FL, "X", "Compression_Raw_Access" },
- { EXT2_ECOMPR_FL, "E", "Compression_Error" },
-#endif
- { EXT3_JOURNAL_DATA_FL, "j", "Journaled_Data" },
- { EXT2_INDEX_FL, "I", "Indexed_direcctory" },
- { EXT2_NOTAIL_FL, "t", "No_Tailmerging" },
- { EXT2_TOPDIR_FL, "T", "Top_of_Directory_Hierarchies" },
- { 0, NULL, NULL }
-};
-
-void print_flags (FILE *f, unsigned long flags, unsigned options)
-{
- int long_opt = (options & PFOPT_LONG);
- const struct flags_name *fp;
- int first = 1;
-
- for (fp = flags_array; fp->flag != 0; fp++) {
- if (flags & fp->flag) {
- if (long_opt) {
- if (first)
- first = 0;
- else
- fputs(", ", f);
- fputs(fp->long_name, f);
- } else
- fputs(fp->short_name, f);
- } else {
- if (!long_opt)
- fputs("-", f);
- }
- }
- if (long_opt && first)
- fputs("---", f);
-}
diff --git a/release/src/router/busybox/e2fsprogs/e2p/ps.c b/release/src/router/busybox/e2fsprogs/e2p/ps.c
deleted file mode 100644
index a6b4099db5..0000000000
--- a/release/src/router/busybox/e2fsprogs/e2p/ps.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * ps.c - Print filesystem state
- *
- * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
- * Laboratoire MASI, Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- */
-
-/*
- * History:
- * 93/12/22 - Creation
- */
-
-#include <stdio.h>
-
-#include "e2p.h"
-
-void print_fs_state(FILE *f, unsigned short state)
-{
- fprintf(f, (state & EXT2_VALID_FS ? " clean" : " not clean"));
- if (state & EXT2_ERROR_FS)
- fprintf(f, " with errors");
-}
diff --git a/release/src/router/busybox/e2fsprogs/e2p/uuid.c b/release/src/router/busybox/e2fsprogs/e2p/uuid.c
deleted file mode 100644
index 474d64a5a4..0000000000
--- a/release/src/router/busybox/e2fsprogs/e2p/uuid.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * uuid.c -- utility routines for manipulating UUID's.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include "../ext2fs/ext2_types.h"
-
-#include "e2p.h"
-
-struct uuid {
- __u32 time_low;
- __u16 time_mid;
- __u16 time_hi_and_version;
- __u16 clock_seq;
- __u8 node[6];
-};
-
-/* Returns 1 if the uuid is the NULL uuid */
-int e2p_is_null_uuid(void *uu)
-{
- __u8 *cp;
- int i;
-
- for (i=0, cp = uu; i < 16; i++)
- if (*cp)
- return 0;
- return 1;
-}
-
-static void e2p_unpack_uuid(void *in, struct uuid *uu)
-{
- __u8 *ptr = in;
- __u32 tmp;
-
- tmp = *ptr++;
- tmp = (tmp << 8) | *ptr++;
- tmp = (tmp << 8) | *ptr++;
- tmp = (tmp << 8) | *ptr++;
- uu->time_low = tmp;
-
- tmp = *ptr++;
- tmp = (tmp << 8) | *ptr++;
- uu->time_mid = tmp;
-
- tmp = *ptr++;
- tmp = (tmp << 8) | *ptr++;
- uu->time_hi_and_version = tmp;
-
- tmp = *ptr++;
- tmp = (tmp << 8) | *ptr++;
- uu->clock_seq = tmp;
-
- memcpy(uu->node, ptr, 6);
-}
-
-void e2p_uuid_to_str(void *uu, char *out)
-{
- struct uuid uuid;
-
- e2p_unpack_uuid(uu, &uuid);
- sprintf(out,
- "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
- uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
- uuid.node[0], uuid.node[1], uuid.node[2],
- uuid.node[3], uuid.node[4], uuid.node[5]);
-}
-
-const char *e2p_uuid2str(void *uu)
-{
- static char buf[80];
- if (e2p_is_null_uuid(uu))
- return "<none>";
- e2p_uuid_to_str(uu, buf);
- return buf;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/Kbuild.src b/release/src/router/busybox/e2fsprogs/ext2fs/Kbuild.src
deleted file mode 100644
index 12adc6e469..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/Kbuild.src
+++ /dev/null
@@ -1,26 +0,0 @@
-# Makefile for busybox
-#
-# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
-#
-# Licensed under GPLv2, see file LICENSE in this source tree.
-
-NEEDED-$(CONFIG_E2FSCK) = y
-NEEDED-$(CONFIG_FSCK) = y
-NEEDED-$(CONFIG_MKE2FS) = y
-NEEDED-$(CONFIG_TUNE2FS) = y
-
-lib-y:=
-
-INSERT
-
-lib-$(NEEDED-y) += gen_bitmap.o bitops.o ismounted.o mkjournal.o unix_io.o \
- rw_bitmaps.o initialize.o bitmaps.o block.o \
- ind_block.o inode.o freefs.o alloc_stats.o closefs.o \
- openfs.o io_manager.o finddev.o read_bb.o alloc.o badblocks.o \
- getsize.o getsectsize.o alloc_tables.o read_bb_file.o mkdir.o \
- bb_inode.o newdir.o alloc_sb.o lookup.o dirblock.o expanddir.o \
- dir_iterate.o link.o res_gdt.o icount.o get_pathname.o dblist.o \
- dirhash.o version.o flushb.o unlink.o check_desc.o valid_blk.o \
- ext_attr.o bmap.o dblist_dir.o ext2fs_inline.o swapfs.o
-
-CFLAGS += -include $(srctree)/e2fsprogs/e2fsbb.h
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/alloc.c b/release/src/router/busybox/e2fsprogs/ext2fs/alloc.c
deleted file mode 100644
index cbb63e15a5..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/alloc.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * alloc.c --- allocate new inodes, blocks for ext2fs
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- *
- */
-
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <time.h>
-#include <string.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * Right now, just search forward from the parent directory's block
- * group to find the next free inode.
- *
- * Should have a special policy for directories.
- */
-errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir,
- int mode EXT2FS_ATTR((unused)),
- ext2fs_inode_bitmap map, ext2_ino_t *ret)
-{
- ext2_ino_t dir_group = 0;
- ext2_ino_t i;
- ext2_ino_t start_inode;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!map)
- map = fs->inode_map;
- if (!map)
- return EXT2_ET_NO_INODE_BITMAP;
-
- if (dir > 0)
- dir_group = (dir - 1) / EXT2_INODES_PER_GROUP(fs->super);
-
- start_inode = (dir_group * EXT2_INODES_PER_GROUP(fs->super)) + 1;
- if (start_inode < EXT2_FIRST_INODE(fs->super))
- start_inode = EXT2_FIRST_INODE(fs->super);
- i = start_inode;
-
- do {
- if (!ext2fs_fast_test_inode_bitmap(map, i))
- break;
- i++;
- if (i > fs->super->s_inodes_count)
- i = EXT2_FIRST_INODE(fs->super);
- } while (i != start_inode);
-
- if (ext2fs_test_inode_bitmap(map, i))
- return EXT2_ET_INODE_ALLOC_FAIL;
- *ret = i;
- return 0;
-}
-
-/*
- * Stupid algorithm --- we now just search forward starting from the
- * goal. Should put in a smarter one someday....
- */
-errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
- ext2fs_block_bitmap map, blk_t *ret)
-{
- blk_t i;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!map)
- map = fs->block_map;
- if (!map)
- return EXT2_ET_NO_BLOCK_BITMAP;
- if (!goal || (goal >= fs->super->s_blocks_count))
- goal = fs->super->s_first_data_block;
- i = goal;
- do {
- if (!ext2fs_fast_test_block_bitmap(map, i)) {
- *ret = i;
- return 0;
- }
- i++;
- if (i >= fs->super->s_blocks_count)
- i = fs->super->s_first_data_block;
- } while (i != goal);
- return EXT2_ET_BLOCK_ALLOC_FAIL;
-}
-
-/*
- * This function zeros out the allocated block, and updates all of the
- * appropriate filesystem records.
- */
-errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
- char *block_buf, blk_t *ret)
-{
- errcode_t retval;
- blk_t block;
- char *buf = NULL;
-
- if (!block_buf) {
- retval = ext2fs_get_mem(fs->blocksize, &buf);
- if (retval)
- return retval;
- block_buf = buf;
- }
- memset(block_buf, 0, fs->blocksize);
-
- if (!fs->block_map) {
- retval = ext2fs_read_block_bitmap(fs);
- if (retval)
- goto fail;
- }
-
- retval = ext2fs_new_block(fs, goal, 0, &block);
- if (retval)
- goto fail;
-
- retval = io_channel_write_blk(fs->io, block, 1, block_buf);
- if (retval)
- goto fail;
-
- ext2fs_block_alloc_stats(fs, block, +1);
- *ret = block;
- return 0;
-
-fail:
- if (buf)
- ext2fs_free_mem(&buf);
- return retval;
-}
-
-errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish,
- int num, ext2fs_block_bitmap map, blk_t *ret)
-{
- blk_t b = start;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!map)
- map = fs->block_map;
- if (!map)
- return EXT2_ET_NO_BLOCK_BITMAP;
- if (!b)
- b = fs->super->s_first_data_block;
- if (!finish)
- finish = start;
- if (!num)
- num = 1;
- do {
- if (b+num-1 > fs->super->s_blocks_count)
- b = fs->super->s_first_data_block;
- if (ext2fs_fast_test_block_bitmap_range(map, b, num)) {
- *ret = b;
- return 0;
- }
- b++;
- } while (b != finish);
- return EXT2_ET_BLOCK_ALLOC_FAIL;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/alloc_sb.c b/release/src/router/busybox/e2fsprogs/ext2fs/alloc_sb.c
deleted file mode 100644
index a7437c96f5..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/alloc_sb.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * alloc_sb.c --- Allocate the superblock and block group descriptors for a
- * newly initialized filesystem. Used by mke2fs when initializing a filesystem
- *
- * Copyright (C) 1994, 1995, 1996, 2003 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-int ext2fs_reserve_super_and_bgd(ext2_filsys fs,
- dgrp_t group,
- ext2fs_block_bitmap bmap)
-{
- blk_t super_blk, old_desc_blk, new_desc_blk;
- int j, old_desc_blocks, num_blocks;
-
- num_blocks = ext2fs_super_and_bgd_loc(fs, group, &super_blk,
- &old_desc_blk, &new_desc_blk, 0);
-
- if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
- old_desc_blocks = fs->super->s_first_meta_bg;
- else
- old_desc_blocks =
- fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
-
- if (super_blk || (group == 0))
- ext2fs_mark_block_bitmap(bmap, super_blk);
-
- if (old_desc_blk) {
- for (j=0; j < old_desc_blocks; j++)
- ext2fs_mark_block_bitmap(bmap, old_desc_blk + j);
- }
- if (new_desc_blk)
- ext2fs_mark_block_bitmap(bmap, new_desc_blk);
-
- return num_blocks;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/alloc_stats.c b/release/src/router/busybox/e2fsprogs/ext2fs/alloc_stats.c
deleted file mode 100644
index f3ab06a237..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/alloc_stats.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * alloc_stats.c --- Update allocation statistics for ext2fs
- *
- * Copyright (C) 2001 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- *
- */
-
-#include <stdio.h>
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino,
- int inuse, int isdir)
-{
- int group = ext2fs_group_of_ino(fs, ino);
-
- if (inuse > 0)
- ext2fs_mark_inode_bitmap(fs->inode_map, ino);
- else
- ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
- fs->group_desc[group].bg_free_inodes_count -= inuse;
- if (isdir)
- fs->group_desc[group].bg_used_dirs_count += inuse;
- fs->super->s_free_inodes_count -= inuse;
- ext2fs_mark_super_dirty(fs);
- ext2fs_mark_ib_dirty(fs);
-}
-
-void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse)
-{
- ext2fs_inode_alloc_stats2(fs, ino, inuse, 0);
-}
-
-void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse)
-{
- int group = ext2fs_group_of_blk(fs, blk);
-
- if (inuse > 0)
- ext2fs_mark_block_bitmap(fs->block_map, blk);
- else
- ext2fs_unmark_block_bitmap(fs->block_map, blk);
- fs->group_desc[group].bg_free_blocks_count -= inuse;
- fs->super->s_free_blocks_count -= inuse;
- ext2fs_mark_super_dirty(fs);
- ext2fs_mark_bb_dirty(fs);
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/alloc_tables.c b/release/src/router/busybox/e2fsprogs/ext2fs/alloc_tables.c
deleted file mode 100644
index 7c60e2bf5f..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/alloc_tables.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * alloc_tables.c --- Allocate tables for a newly initialized
- * filesystem. Used by mke2fs when initializing a filesystem
- *
- * Copyright (C) 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
- ext2fs_block_bitmap bmap)
-{
- errcode_t retval;
- blk_t group_blk, start_blk, last_blk, new_blk, blk;
- int j;
-
- group_blk = fs->super->s_first_data_block +
- (group * fs->super->s_blocks_per_group);
-
- last_blk = group_blk + fs->super->s_blocks_per_group;
- if (last_blk >= fs->super->s_blocks_count)
- last_blk = fs->super->s_blocks_count - 1;
-
- if (!bmap)
- bmap = fs->block_map;
-
- /*
- * Allocate the block and inode bitmaps, if necessary
- */
- if (fs->stride) {
- start_blk = group_blk + fs->inode_blocks_per_group;
- start_blk += ((fs->stride * group) %
- (last_blk - start_blk));
- if (start_blk > last_blk)
- start_blk = group_blk;
- } else
- start_blk = group_blk;
-
- if (!fs->group_desc[group].bg_block_bitmap) {
- retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
- 1, bmap, &new_blk);
- if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
- retval = ext2fs_get_free_blocks(fs, group_blk,
- last_blk, 1, bmap, &new_blk);
- if (retval)
- return retval;
- ext2fs_mark_block_bitmap(bmap, new_blk);
- fs->group_desc[group].bg_block_bitmap = new_blk;
- }
-
- if (!fs->group_desc[group].bg_inode_bitmap) {
- retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
- 1, bmap, &new_blk);
- if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
- retval = ext2fs_get_free_blocks(fs, group_blk,
- last_blk, 1, bmap, &new_blk);
- if (retval)
- return retval;
- ext2fs_mark_block_bitmap(bmap, new_blk);
- fs->group_desc[group].bg_inode_bitmap = new_blk;
- }
-
- /*
- * Allocate the inode table
- */
- if (!fs->group_desc[group].bg_inode_table) {
- retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
- fs->inode_blocks_per_group,
- bmap, &new_blk);
- if (retval)
- return retval;
- for (j=0, blk = new_blk;
- j < fs->inode_blocks_per_group;
- j++, blk++)
- ext2fs_mark_block_bitmap(bmap, blk);
- fs->group_desc[group].bg_inode_table = new_blk;
- }
-
- return 0;
-}
-
-errcode_t ext2fs_allocate_tables(ext2_filsys fs)
-{
- errcode_t retval;
- dgrp_t i;
-
- for (i = 0; i < fs->group_desc_count; i++) {
- retval = ext2fs_allocate_group_table(fs, i, fs->block_map);
- if (retval)
- return retval;
- }
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/badblocks.c b/release/src/router/busybox/e2fsprogs/ext2fs/badblocks.c
deleted file mode 100644
index 6e5cc10b82..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/badblocks.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * badblocks.c --- routines to manipulate the bad block structure
- *
- * Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fsP.h"
-
-/*
- * Helper function for making a badblocks list
- */
-static errcode_t make_u32_list(int size, int num, __u32 *list,
- ext2_u32_list *ret)
-{
- ext2_u32_list bb;
- errcode_t retval;
-
- retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_list), &bb);
- if (retval)
- return retval;
- memset(bb, 0, sizeof(struct ext2_struct_u32_list));
- bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST;
- bb->size = size ? size : 10;
- bb->num = num;
- retval = ext2fs_get_mem(bb->size * sizeof(blk_t), &bb->list);
- if (!bb->list) {
- ext2fs_free_mem(&bb);
- return retval;
- }
- if (list)
- memcpy(bb->list, list, bb->size * sizeof(blk_t));
- else
- memset(bb->list, 0, bb->size * sizeof(blk_t));
- *ret = bb;
- return 0;
-}
-
-
-/*
- * This procedure creates an empty u32 list.
- */
-errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size)
-{
- return make_u32_list(size, 0, 0, ret);
-}
-
-/*
- * This procedure creates an empty badblocks list.
- */
-errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size)
-{
- return make_u32_list(size, 0, 0, (ext2_badblocks_list *) ret);
-}
-
-
-/*
- * This procedure copies a badblocks list
- */
-errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest)
-{
- errcode_t retval;
-
- retval = make_u32_list(src->size, src->num, src->list, dest);
- if (retval)
- return retval;
- (*dest)->badblocks_flags = src->badblocks_flags;
- return 0;
-}
-
-errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
- ext2_badblocks_list *dest)
-{
- return ext2fs_u32_copy((ext2_u32_list) src,
- (ext2_u32_list *) dest);
-}
-
-/*
- * This procedure frees a badblocks list.
- *
- * (note: moved to closefs.c)
- */
-
-
-/*
- * This procedure adds a block to a badblocks list.
- */
-errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk)
-{
- errcode_t retval;
- int i, j;
- unsigned long old_size;
-
- EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
-
- if (bb->num >= bb->size) {
- old_size = bb->size * sizeof(__u32);
- bb->size += 100;
- retval = ext2fs_resize_mem(old_size, bb->size * sizeof(__u32),
- &bb->list);
- if (retval) {
- bb->size -= 100;
- return retval;
- }
- }
-
- /*
- * Add special case code for appending to the end of the list
- */
- i = bb->num-1;
- if ((bb->num != 0) && (bb->list[i] == blk))
- return 0;
- if ((bb->num == 0) || (bb->list[i] < blk)) {
- bb->list[bb->num++] = blk;
- return 0;
- }
-
- j = bb->num;
- for (i=0; i < bb->num; i++) {
- if (bb->list[i] == blk)
- return 0;
- if (bb->list[i] > blk) {
- j = i;
- break;
- }
- }
- for (i=bb->num; i > j; i--)
- bb->list[i] = bb->list[i-1];
- bb->list[j] = blk;
- bb->num++;
- return 0;
-}
-
-errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk)
-{
- return ext2fs_u32_list_add((ext2_u32_list) bb, (__u32) blk);
-}
-
-/*
- * This procedure finds a particular block is on a badblocks
- * list.
- */
-int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk)
-{
- int low, high, mid;
-
- if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
- return -1;
-
- if (bb->num == 0)
- return -1;
-
- low = 0;
- high = bb->num-1;
- if (blk == bb->list[low])
- return low;
- if (blk == bb->list[high])
- return high;
-
- while (low < high) {
- mid = (low+high)/2;
- if (mid == low || mid == high)
- break;
- if (blk == bb->list[mid])
- return mid;
- if (blk < bb->list[mid])
- high = mid;
- else
- low = mid;
- }
- return -1;
-}
-
-/*
- * This procedure tests to see if a particular block is on a badblocks
- * list.
- */
-int ext2fs_u32_list_test(ext2_u32_list bb, __u32 blk)
-{
- if (ext2fs_u32_list_find(bb, blk) < 0)
- return 0;
- else
- return 1;
-}
-
-int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk)
-{
- return ext2fs_u32_list_test((ext2_u32_list) bb, (__u32) blk);
-}
-
-
-/*
- * Remove a block from the badblock list
- */
-int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk)
-{
- int remloc, i;
-
- if (bb->num == 0)
- return -1;
-
- remloc = ext2fs_u32_list_find(bb, blk);
- if (remloc < 0)
- return -1;
-
- for (i = remloc; i < bb->num - 1; i++)
- bb->list[i] = bb->list[i+1];
- bb->num--;
- return 0;
-}
-
-void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk)
-{
- ext2fs_u32_list_del(bb, blk);
-}
-
-errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb,
- ext2_u32_iterate *ret)
-{
- ext2_u32_iterate iter;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
-
- retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_iterate), &iter);
- if (retval)
- return retval;
-
- iter->magic = EXT2_ET_MAGIC_BADBLOCKS_ITERATE;
- iter->bb = bb;
- iter->ptr = 0;
- *ret = iter;
- return 0;
-}
-
-errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
- ext2_badblocks_iterate *ret)
-{
- return ext2fs_u32_list_iterate_begin((ext2_u32_list) bb,
- (ext2_u32_iterate *) ret);
-}
-
-
-int ext2fs_u32_list_iterate(ext2_u32_iterate iter, __u32 *blk)
-{
- ext2_u32_list bb;
-
- if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)
- return 0;
-
- bb = iter->bb;
-
- if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
- return 0;
-
- if (iter->ptr < bb->num) {
- *blk = bb->list[iter->ptr++];
- return 1;
- }
- *blk = 0;
- return 0;
-}
-
-int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk)
-{
- return ext2fs_u32_list_iterate((ext2_u32_iterate) iter,
- (__u32 *) blk);
-}
-
-
-void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter)
-{
- if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE))
- return;
-
- iter->bb = 0;
- ext2fs_free_mem(&iter);
-}
-
-void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter)
-{
- ext2fs_u32_list_iterate_end((ext2_u32_iterate) iter);
-}
-
-
-int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2)
-{
- EXT2_CHECK_MAGIC(bb1, EXT2_ET_MAGIC_BADBLOCKS_LIST);
- EXT2_CHECK_MAGIC(bb2, EXT2_ET_MAGIC_BADBLOCKS_LIST);
-
- if (bb1->num != bb2->num)
- return 0;
-
- if (memcmp(bb1->list, bb2->list, bb1->num * sizeof(blk_t)) != 0)
- return 0;
- return 1;
-}
-
-int ext2fs_badblocks_equal(ext2_badblocks_list bb1, ext2_badblocks_list bb2)
-{
- return ext2fs_u32_list_equal((ext2_u32_list) bb1,
- (ext2_u32_list) bb2);
-}
-
-int ext2fs_u32_list_count(ext2_u32_list bb)
-{
- return bb->num;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/bb_compat.c b/release/src/router/busybox/e2fsprogs/ext2fs/bb_compat.c
deleted file mode 100644
index 419ac77859..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/bb_compat.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * bb_compat.c --- compatibility badblocks routines
- *
- * Copyright (C) 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fsP.h"
-
-errcode_t badblocks_list_create(badblocks_list *ret, int size)
-{
- return ext2fs_badblocks_list_create(ret, size);
-}
-
-void badblocks_list_free(badblocks_list bb)
-{
- ext2fs_badblocks_list_free(bb);
-}
-
-errcode_t badblocks_list_add(badblocks_list bb, blk_t blk)
-{
- return ext2fs_badblocks_list_add(bb, blk);
-}
-
-int badblocks_list_test(badblocks_list bb, blk_t blk)
-{
- return ext2fs_badblocks_list_test(bb, blk);
-}
-
-errcode_t badblocks_list_iterate_begin(badblocks_list bb,
- badblocks_iterate *ret)
-{
- return ext2fs_badblocks_list_iterate_begin(bb, ret);
-}
-
-int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk)
-{
- return ext2fs_badblocks_list_iterate(iter, blk);
-}
-
-void badblocks_list_iterate_end(badblocks_iterate iter)
-{
- ext2fs_badblocks_list_iterate_end(iter);
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/bb_inode.c b/release/src/router/busybox/e2fsprogs/ext2fs/bb_inode.c
deleted file mode 100644
index a967896181..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/bb_inode.c
+++ /dev/null
@@ -1,262 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * bb_inode.c --- routines to update the bad block inode.
- *
- * WARNING: This routine modifies a lot of state in the filesystem; if
- * this routine returns an error, the bad block inode may be in an
- * inconsistent state.
- *
- * Copyright (C) 1994, 1995 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-struct set_badblock_record {
- ext2_badblocks_iterate bb_iter;
- int bad_block_count;
- blk_t *ind_blocks;
- int max_ind_blocks;
- int ind_blocks_size;
- int ind_blocks_ptr;
- char *block_buf;
- errcode_t err;
-};
-
-static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block, int ref_offset,
- void *priv_data);
-static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block, int ref_offset,
- void *priv_data);
-
-/*
- * Given a bad blocks bitmap, update the bad blocks inode to reflect
- * the map.
- */
-errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list)
-{
- errcode_t retval;
- struct set_badblock_record rec;
- struct ext2_inode inode;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!fs->block_map)
- return EXT2_ET_NO_BLOCK_BITMAP;
-
- rec.bad_block_count = 0;
- rec.ind_blocks_size = rec.ind_blocks_ptr = 0;
- rec.max_ind_blocks = 10;
- retval = ext2fs_get_mem(rec.max_ind_blocks * sizeof(blk_t),
- &rec.ind_blocks);
- if (retval)
- return retval;
- memset(rec.ind_blocks, 0, rec.max_ind_blocks * sizeof(blk_t));
- retval = ext2fs_get_mem(fs->blocksize, &rec.block_buf);
- if (retval)
- goto cleanup;
- memset(rec.block_buf, 0, fs->blocksize);
- rec.err = 0;
-
- /*
- * First clear the old bad blocks (while saving the indirect blocks)
- */
- retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
- BLOCK_FLAG_DEPTH_TRAVERSE, 0,
- clear_bad_block_proc, &rec);
- if (retval)
- goto cleanup;
- if (rec.err) {
- retval = rec.err;
- goto cleanup;
- }
-
- /*
- * Now set the bad blocks!
- *
- * First, mark the bad blocks as used. This prevents a bad
- * block from being used as an indirecto block for the bad
- * block inode (!).
- */
- if (bb_list) {
- retval = ext2fs_badblocks_list_iterate_begin(bb_list,
- &rec.bb_iter);
- if (retval)
- goto cleanup;
- retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
- BLOCK_FLAG_APPEND, 0,
- set_bad_block_proc, &rec);
- ext2fs_badblocks_list_iterate_end(rec.bb_iter);
- if (retval)
- goto cleanup;
- if (rec.err) {
- retval = rec.err;
- goto cleanup;
- }
- }
-
- /*
- * Update the bad block inode's mod time and block count
- * field.
- */
- retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode);
- if (retval)
- goto cleanup;
-
- inode.i_atime = inode.i_mtime = time(NULL);
- if (!inode.i_ctime)
- inode.i_ctime = time(NULL);
- inode.i_blocks = rec.bad_block_count * (fs->blocksize / 512);
- inode.i_size = rec.bad_block_count * fs->blocksize;
-
- retval = ext2fs_write_inode(fs, EXT2_BAD_INO, &inode);
- if (retval)
- goto cleanup;
-
-cleanup:
- ext2fs_free_mem(&rec.ind_blocks);
- ext2fs_free_mem(&rec.block_buf);
- return retval;
-}
-
-/*
- * Helper function for update_bb_inode()
- *
- * Clear the bad blocks in the bad block inode, while saving the
- * indirect blocks.
- */
-#ifdef __TURBOC__
-# pragma argsused
-#endif
-static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block EXT2FS_ATTR((unused)),
- int ref_offset EXT2FS_ATTR((unused)),
- void *priv_data)
-{
- struct set_badblock_record *rec = (struct set_badblock_record *)
- priv_data;
- errcode_t retval;
- unsigned long old_size;
-
- if (!*block_nr)
- return 0;
-
- /*
- * If the block number is outrageous, clear it and ignore it.
- */
- if (*block_nr >= fs->super->s_blocks_count ||
- *block_nr < fs->super->s_first_data_block) {
- *block_nr = 0;
- return BLOCK_CHANGED;
- }
-
- if (blockcnt < 0) {
- if (rec->ind_blocks_size >= rec->max_ind_blocks) {
- old_size = rec->max_ind_blocks * sizeof(blk_t);
- rec->max_ind_blocks += 10;
- retval = ext2fs_resize_mem(old_size,
- rec->max_ind_blocks * sizeof(blk_t),
- &rec->ind_blocks);
- if (retval) {
- rec->max_ind_blocks -= 10;
- rec->err = retval;
- return BLOCK_ABORT;
- }
- }
- rec->ind_blocks[rec->ind_blocks_size++] = *block_nr;
- }
-
- /*
- * Mark the block as unused, and update accounting information
- */
- ext2fs_block_alloc_stats(fs, *block_nr, -1);
-
- *block_nr = 0;
- return BLOCK_CHANGED;
-}
-
-
-/*
- * Helper function for update_bb_inode()
- *
- * Set the block list in the bad block inode, using the supplied bitmap.
- */
-#ifdef __TURBOC__
- #pragma argsused
-#endif
-static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block EXT2FS_ATTR((unused)),
- int ref_offset EXT2FS_ATTR((unused)),
- void *priv_data)
-{
- struct set_badblock_record *rec = (struct set_badblock_record *)
- priv_data;
- errcode_t retval;
- blk_t blk;
-
- if (blockcnt >= 0) {
- /*
- * Get the next bad block.
- */
- if (!ext2fs_badblocks_list_iterate(rec->bb_iter, &blk))
- return BLOCK_ABORT;
- rec->bad_block_count++;
- } else {
- /*
- * An indirect block; fetch a block from the
- * previously used indirect block list. The block
- * most be not marked as used; if so, get another one.
- * If we run out of reserved indirect blocks, allocate
- * a new one.
- */
- retry:
- if (rec->ind_blocks_ptr < rec->ind_blocks_size) {
- blk = rec->ind_blocks[rec->ind_blocks_ptr++];
- if (ext2fs_test_block_bitmap(fs->block_map, blk))
- goto retry;
- } else {
- retval = ext2fs_new_block(fs, 0, 0, &blk);
- if (retval) {
- rec->err = retval;
- return BLOCK_ABORT;
- }
- }
- retval = io_channel_write_blk(fs->io, blk, 1, rec->block_buf);
- if (retval) {
- rec->err = retval;
- return BLOCK_ABORT;
- }
- }
-
- /*
- * Update block counts
- */
- ext2fs_block_alloc_stats(fs, blk, +1);
-
- *block_nr = blk;
- return BLOCK_CHANGED;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/bitmaps.c b/release/src/router/busybox/e2fsprogs/ext2fs/bitmaps.c
deleted file mode 100644
index 637ed27af9..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/bitmaps.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * bitmaps.c --- routines to read, write, and manipulate the inode and
- * block bitmaps.
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-static errcode_t make_bitmap(__u32 start, __u32 end, __u32 real_end,
- const char *descr, char *init_map,
- ext2fs_generic_bitmap *ret)
-{
- ext2fs_generic_bitmap bitmap;
- errcode_t retval;
- size_t size;
-
- retval = ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap),
- &bitmap);
- if (retval)
- return retval;
-
- bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
- bitmap->fs = NULL;
- bitmap->start = start;
- bitmap->end = end;
- bitmap->real_end = real_end;
- bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK;
- if (descr) {
- retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description);
- if (retval) {
- ext2fs_free_mem(&bitmap);
- return retval;
- }
- strcpy(bitmap->description, descr);
- } else
- bitmap->description = 0;
-
- size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1);
- retval = ext2fs_get_mem(size, &bitmap->bitmap);
- if (retval) {
- ext2fs_free_mem(&bitmap->description);
- ext2fs_free_mem(&bitmap);
- return retval;
- }
-
- if (init_map)
- memcpy(bitmap->bitmap, init_map, size);
- else
- memset(bitmap->bitmap, 0, size);
- *ret = bitmap;
- return 0;
-}
-
-errcode_t ext2fs_allocate_generic_bitmap(__u32 start,
- __u32 end,
- __u32 real_end,
- const char *descr,
- ext2fs_generic_bitmap *ret)
-{
- return make_bitmap(start, end, real_end, descr, 0, ret);
-}
-
-errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
- ext2fs_generic_bitmap *dest)
-{
- errcode_t retval;
- ext2fs_generic_bitmap new_map;
-
- retval = make_bitmap(src->start, src->end, src->real_end,
- src->description, src->bitmap, &new_map);
- if (retval)
- return retval;
- new_map->magic = src->magic;
- new_map->fs = src->fs;
- new_map->base_error_code = src->base_error_code;
- *dest = new_map;
- return 0;
-}
-
-void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map)
-{
- __u32 i, j;
-
- for (i=map->end+1, j = i - map->start; i <= map->real_end; i++, j++)
- ext2fs_set_bit(j, map->bitmap);
-}
-
-errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs,
- const char *descr,
- ext2fs_inode_bitmap *ret)
-{
- ext2fs_inode_bitmap bitmap;
- errcode_t retval;
- __u32 start, end, real_end;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- fs->write_bitmaps = ext2fs_write_bitmaps;
-
- start = 1;
- end = fs->super->s_inodes_count;
- real_end = (EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count);
-
- retval = ext2fs_allocate_generic_bitmap(start, end, real_end,
- descr, &bitmap);
- if (retval)
- return retval;
-
- bitmap->magic = EXT2_ET_MAGIC_INODE_BITMAP;
- bitmap->fs = fs;
- bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK;
-
- *ret = bitmap;
- return 0;
-}
-
-errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
- const char *descr,
- ext2fs_block_bitmap *ret)
-{
- ext2fs_block_bitmap bitmap;
- errcode_t retval;
- __u32 start, end, real_end;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- fs->write_bitmaps = ext2fs_write_bitmaps;
-
- start = fs->super->s_first_data_block;
- end = fs->super->s_blocks_count-1;
- real_end = (EXT2_BLOCKS_PER_GROUP(fs->super)
- * fs->group_desc_count)-1 + start;
-
- retval = ext2fs_allocate_generic_bitmap(start, end, real_end,
- descr, &bitmap);
- if (retval)
- return retval;
-
- bitmap->magic = EXT2_ET_MAGIC_BLOCK_BITMAP;
- bitmap->fs = fs;
- bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK;
-
- *ret = bitmap;
- return 0;
-}
-
-errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap,
- ext2_ino_t end, ext2_ino_t *oend)
-{
- EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_INODE_BITMAP);
-
- if (end > bitmap->real_end)
- return EXT2_ET_FUDGE_INODE_BITMAP_END;
- if (oend)
- *oend = bitmap->end;
- bitmap->end = end;
- return 0;
-}
-
-errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap,
- blk_t end, blk_t *oend)
-{
- EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_BLOCK_BITMAP);
-
- if (end > bitmap->real_end)
- return EXT2_ET_FUDGE_BLOCK_BITMAP_END;
- if (oend)
- *oend = bitmap->end;
- bitmap->end = end;
- return 0;
-}
-
-void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap)
-{
- if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_INODE_BITMAP))
- return;
-
- memset(bitmap->bitmap, 0,
- (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
-}
-
-void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap)
-{
- if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_BLOCK_BITMAP))
- return;
-
- memset(bitmap->bitmap, 0,
- (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/bitops.c b/release/src/router/busybox/e2fsprogs/ext2fs/bitops.c
deleted file mode 100644
index b4ec51ed7c..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/bitops.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * bitops.c --- Bitmap frobbing code. See bitops.h for the inlined
- * routines.
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-#ifndef _EXT2_HAVE_ASM_BITOPS_
-
-/*
- * For the benefit of those who are trying to port Linux to another
- * architecture, here are some C-language equivalents. You should
- * recode these in the native assmebly language, if at all possible.
- *
- * C language equivalents written by Theodore Ts'o, 9/26/92.
- * Modified by Pete A. Zaitcev 7/14/95 to be portable to big endian
- * systems, as well as non-32 bit systems.
- */
-
-int ext2fs_set_bit(unsigned int nr,void * addr)
-{
- int mask, retval;
- unsigned char *ADDR = (unsigned char *) addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- retval = mask & *ADDR;
- *ADDR |= mask;
- return retval;
-}
-
-int ext2fs_clear_bit(unsigned int nr, void * addr)
-{
- int mask, retval;
- unsigned char *ADDR = (unsigned char *) addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- retval = mask & *ADDR;
- *ADDR &= ~mask;
- return retval;
-}
-
-int ext2fs_test_bit(unsigned int nr, const void * addr)
-{
- int mask;
- const unsigned char *ADDR = (const unsigned char *) addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- return (mask & *ADDR);
-}
-
-#endif /* !_EXT2_HAVE_ASM_BITOPS_ */
-
-void ext2fs_warn_bitmap(errcode_t errcode EXT2FS_ATTR((unused)),
- unsigned long arg,
- const char *description)
-{
-#ifndef OMIT_COM_ERR
- if (description)
- bb_error_msg("#%lu for %s", arg, description);
- else
- bb_error_msg("#%lu", arg);
-#endif
-}
-
-void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
- int code EXT2FS_ATTR((unused)), unsigned long arg)
-{
-#ifndef OMIT_COM_ERR
- if (bitmap->description)
- bb_error_msg("#%lu for %s", arg, bitmap->description);
- else
- bb_error_msg("#%lu", arg);
-#endif
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/bitops.h b/release/src/router/busybox/e2fsprogs/ext2fs/bitops.h
deleted file mode 100644
index 7271a497bf..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/bitops.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * bitops.h --- Bitmap frobbing code. The byte swapping routines are
- * also included here.
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- *
- * i386 bitops operations taken from <asm/bitops.h>, Copyright 1992,
- * Linus Torvalds.
- */
-#include <string.h>
-
-extern int ext2fs_set_bit(unsigned int nr,void * addr);
-extern int ext2fs_clear_bit(unsigned int nr, void * addr);
-extern int ext2fs_test_bit(unsigned int nr, const void * addr);
-extern __u16 ext2fs_swab16(__u16 val);
-extern __u32 ext2fs_swab32(__u32 val);
-
-#ifdef WORDS_BIGENDIAN
-#define ext2fs_cpu_to_le32(x) ext2fs_swab32((x))
-#define ext2fs_le32_to_cpu(x) ext2fs_swab32((x))
-#define ext2fs_cpu_to_le16(x) ext2fs_swab16((x))
-#define ext2fs_le16_to_cpu(x) ext2fs_swab16((x))
-#define ext2fs_cpu_to_be32(x) ((__u32)(x))
-#define ext2fs_be32_to_cpu(x) ((__u32)(x))
-#define ext2fs_cpu_to_be16(x) ((__u16)(x))
-#define ext2fs_be16_to_cpu(x) ((__u16)(x))
-#else
-#define ext2fs_cpu_to_le32(x) ((__u32)(x))
-#define ext2fs_le32_to_cpu(x) ((__u32)(x))
-#define ext2fs_cpu_to_le16(x) ((__u16)(x))
-#define ext2fs_le16_to_cpu(x) ((__u16)(x))
-#define ext2fs_cpu_to_be32(x) ext2fs_swab32((x))
-#define ext2fs_be32_to_cpu(x) ext2fs_swab32((x))
-#define ext2fs_cpu_to_be16(x) ext2fs_swab16((x))
-#define ext2fs_be16_to_cpu(x) ext2fs_swab16((x))
-#endif
-
-/*
- * EXT2FS bitmap manipulation routines.
- */
-
-/* Support for sending warning messages from the inline subroutines */
-extern const char *ext2fs_block_string;
-extern const char *ext2fs_inode_string;
-extern const char *ext2fs_mark_string;
-extern const char *ext2fs_unmark_string;
-extern const char *ext2fs_test_string;
-extern void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
- const char *description);
-extern void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
- int code, unsigned long arg);
-
-extern int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
-extern int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
- blk_t block);
-extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
-
-extern int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
-extern int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
- ext2_ino_t inode);
-extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
-
-extern void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
- blk_t block);
-extern void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
- blk_t block);
-extern int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
- blk_t block);
-
-extern void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
- ext2_ino_t inode);
-extern void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
- ext2_ino_t inode);
-extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
- ext2_ino_t inode);
-extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap);
-extern ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap);
-extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap);
-extern ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap);
-
-extern void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num);
-extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num);
-extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num);
-extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num);
-extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num);
-extern int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num);
-extern void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map);
-
-/* These two routines moved to gen_bitmap.c */
-extern int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
- __u32 bitno);
-extern int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
- blk_t bitno);
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/block.c b/release/src/router/busybox/e2fsprogs/ext2fs/block.c
deleted file mode 100644
index dbd04f8469..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/block.c
+++ /dev/null
@@ -1,437 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * block.c --- iterate over all blocks in an inode
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-struct block_context {
- ext2_filsys fs;
- int (*func)(ext2_filsys fs,
- blk_t *blocknr,
- e2_blkcnt_t bcount,
- blk_t ref_blk,
- int ref_offset,
- void *priv_data);
- e2_blkcnt_t bcount;
- int bsize;
- int flags;
- errcode_t errcode;
- char *ind_buf;
- char *dind_buf;
- char *tind_buf;
- void *priv_data;
-};
-
-static int block_iterate_ind(blk_t *ind_block, blk_t ref_block,
- int ref_offset, struct block_context *ctx)
-{
- int ret = 0, changed = 0;
- int i, flags, limit, offset;
- blk_t *block_nr;
-
- limit = ctx->fs->blocksize >> 2;
- if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
- !(ctx->flags & BLOCK_FLAG_DATA_ONLY))
- ret = (*ctx->func)(ctx->fs, ind_block,
- BLOCK_COUNT_IND, ref_block,
- ref_offset, ctx->priv_data);
- if (!*ind_block || (ret & BLOCK_ABORT)) {
- ctx->bcount += limit;
- return ret;
- }
- if (*ind_block >= ctx->fs->super->s_blocks_count ||
- *ind_block < ctx->fs->super->s_first_data_block) {
- ctx->errcode = EXT2_ET_BAD_IND_BLOCK;
- ret |= BLOCK_ERROR;
- return ret;
- }
- ctx->errcode = ext2fs_read_ind_block(ctx->fs, *ind_block,
- ctx->ind_buf);
- if (ctx->errcode) {
- ret |= BLOCK_ERROR;
- return ret;
- }
-
- block_nr = (blk_t *) ctx->ind_buf;
- offset = 0;
- if (ctx->flags & BLOCK_FLAG_APPEND) {
- for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
- flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
- *ind_block, offset,
- ctx->priv_data);
- changed |= flags;
- if (flags & BLOCK_ABORT) {
- ret |= BLOCK_ABORT;
- break;
- }
- offset += sizeof(blk_t);
- }
- } else {
- for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
- if (*block_nr == 0)
- continue;
- flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
- *ind_block, offset,
- ctx->priv_data);
- changed |= flags;
- if (flags & BLOCK_ABORT) {
- ret |= BLOCK_ABORT;
- break;
- }
- offset += sizeof(blk_t);
- }
- }
- if (changed & BLOCK_CHANGED) {
- ctx->errcode = ext2fs_write_ind_block(ctx->fs, *ind_block,
- ctx->ind_buf);
- if (ctx->errcode)
- ret |= BLOCK_ERROR | BLOCK_ABORT;
- }
- if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
- !(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
- !(ret & BLOCK_ABORT))
- ret |= (*ctx->func)(ctx->fs, ind_block,
- BLOCK_COUNT_IND, ref_block,
- ref_offset, ctx->priv_data);
- return ret;
-}
-
-static int block_iterate_dind(blk_t *dind_block, blk_t ref_block,
- int ref_offset, struct block_context *ctx)
-{
- int ret = 0, changed = 0;
- int i, flags, limit, offset;
- blk_t *block_nr;
-
- limit = ctx->fs->blocksize >> 2;
- if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE |
- BLOCK_FLAG_DATA_ONLY)))
- ret = (*ctx->func)(ctx->fs, dind_block,
- BLOCK_COUNT_DIND, ref_block,
- ref_offset, ctx->priv_data);
- if (!*dind_block || (ret & BLOCK_ABORT)) {
- ctx->bcount += limit*limit;
- return ret;
- }
- if (*dind_block >= ctx->fs->super->s_blocks_count ||
- *dind_block < ctx->fs->super->s_first_data_block) {
- ctx->errcode = EXT2_ET_BAD_DIND_BLOCK;
- ret |= BLOCK_ERROR;
- return ret;
- }
- ctx->errcode = ext2fs_read_ind_block(ctx->fs, *dind_block,
- ctx->dind_buf);
- if (ctx->errcode) {
- ret |= BLOCK_ERROR;
- return ret;
- }
-
- block_nr = (blk_t *) ctx->dind_buf;
- offset = 0;
- if (ctx->flags & BLOCK_FLAG_APPEND) {
- for (i = 0; i < limit; i++, block_nr++) {
- flags = block_iterate_ind(block_nr,
- *dind_block, offset,
- ctx);
- changed |= flags;
- if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
- ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
- break;
- }
- offset += sizeof(blk_t);
- }
- } else {
- for (i = 0; i < limit; i++, block_nr++) {
- if (*block_nr == 0) {
- ctx->bcount += limit;
- continue;
- }
- flags = block_iterate_ind(block_nr,
- *dind_block, offset,
- ctx);
- changed |= flags;
- if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
- ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
- break;
- }
- offset += sizeof(blk_t);
- }
- }
- if (changed & BLOCK_CHANGED) {
- ctx->errcode = ext2fs_write_ind_block(ctx->fs, *dind_block,
- ctx->dind_buf);
- if (ctx->errcode)
- ret |= BLOCK_ERROR | BLOCK_ABORT;
- }
- if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
- !(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
- !(ret & BLOCK_ABORT))
- ret |= (*ctx->func)(ctx->fs, dind_block,
- BLOCK_COUNT_DIND, ref_block,
- ref_offset, ctx->priv_data);
- return ret;
-}
-
-static int block_iterate_tind(blk_t *tind_block, blk_t ref_block,
- int ref_offset, struct block_context *ctx)
-{
- int ret = 0, changed = 0;
- int i, flags, limit, offset;
- blk_t *block_nr;
-
- limit = ctx->fs->blocksize >> 2;
- if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE |
- BLOCK_FLAG_DATA_ONLY)))
- ret = (*ctx->func)(ctx->fs, tind_block,
- BLOCK_COUNT_TIND, ref_block,
- ref_offset, ctx->priv_data);
- if (!*tind_block || (ret & BLOCK_ABORT)) {
- ctx->bcount += limit*limit*limit;
- return ret;
- }
- if (*tind_block >= ctx->fs->super->s_blocks_count ||
- *tind_block < ctx->fs->super->s_first_data_block) {
- ctx->errcode = EXT2_ET_BAD_TIND_BLOCK;
- ret |= BLOCK_ERROR;
- return ret;
- }
- ctx->errcode = ext2fs_read_ind_block(ctx->fs, *tind_block,
- ctx->tind_buf);
- if (ctx->errcode) {
- ret |= BLOCK_ERROR;
- return ret;
- }
-
- block_nr = (blk_t *) ctx->tind_buf;
- offset = 0;
- if (ctx->flags & BLOCK_FLAG_APPEND) {
- for (i = 0; i < limit; i++, block_nr++) {
- flags = block_iterate_dind(block_nr,
- *tind_block,
- offset, ctx);
- changed |= flags;
- if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
- ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
- break;
- }
- offset += sizeof(blk_t);
- }
- } else {
- for (i = 0; i < limit; i++, block_nr++) {
- if (*block_nr == 0) {
- ctx->bcount += limit*limit;
- continue;
- }
- flags = block_iterate_dind(block_nr,
- *tind_block,
- offset, ctx);
- changed |= flags;
- if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
- ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
- break;
- }
- offset += sizeof(blk_t);
- }
- }
- if (changed & BLOCK_CHANGED) {
- ctx->errcode = ext2fs_write_ind_block(ctx->fs, *tind_block,
- ctx->tind_buf);
- if (ctx->errcode)
- ret |= BLOCK_ERROR | BLOCK_ABORT;
- }
- if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
- !(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
- !(ret & BLOCK_ABORT))
- ret |= (*ctx->func)(ctx->fs, tind_block,
- BLOCK_COUNT_TIND, ref_block,
- ref_offset, ctx->priv_data);
-
- return ret;
-}
-
-errcode_t ext2fs_block_iterate2(ext2_filsys fs,
- ext2_ino_t ino,
- int flags,
- char *block_buf,
- int (*func)(ext2_filsys fs,
- blk_t *blocknr,
- e2_blkcnt_t blockcnt,
- blk_t ref_blk,
- int ref_offset,
- void *priv_data),
- void *priv_data)
-{
- int i;
- int got_inode = 0;
- int ret = 0;
- blk_t blocks[EXT2_N_BLOCKS]; /* directory data blocks */
- struct ext2_inode inode;
- errcode_t retval;
- struct block_context ctx;
- int limit;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- /*
- * Check to see if we need to limit large files
- */
- if (flags & BLOCK_FLAG_NO_LARGE) {
- ctx.errcode = ext2fs_read_inode(fs, ino, &inode);
- if (ctx.errcode)
- return ctx.errcode;
- got_inode = 1;
- if (!LINUX_S_ISDIR(inode.i_mode) &&
- (inode.i_size_high != 0))
- return EXT2_ET_FILE_TOO_BIG;
- }
-
- retval = ext2fs_get_blocks(fs, ino, blocks);
- if (retval)
- return retval;
-
- limit = fs->blocksize >> 2;
-
- ctx.fs = fs;
- ctx.func = func;
- ctx.priv_data = priv_data;
- ctx.flags = flags;
- ctx.bcount = 0;
- if (block_buf) {
- ctx.ind_buf = block_buf;
- } else {
- retval = ext2fs_get_mem(fs->blocksize * 3, &ctx.ind_buf);
- if (retval)
- return retval;
- }
- ctx.dind_buf = ctx.ind_buf + fs->blocksize;
- ctx.tind_buf = ctx.dind_buf + fs->blocksize;
-
- /*
- * Iterate over the HURD translator block (if present)
- */
- if ((fs->super->s_creator_os == EXT2_OS_HURD) &&
- !(flags & BLOCK_FLAG_DATA_ONLY)) {
- ctx.errcode = ext2fs_read_inode(fs, ino, &inode);
- if (ctx.errcode)
- goto abort_exit;
- got_inode = 1;
- if (inode.osd1.hurd1.h_i_translator) {
- ret |= (*ctx.func)(fs,
- &inode.osd1.hurd1.h_i_translator,
- BLOCK_COUNT_TRANSLATOR,
- 0, 0, priv_data);
- if (ret & BLOCK_ABORT)
- goto abort_exit;
- }
- }
-
- /*
- * Iterate over normal data blocks
- */
- for (i = 0; i < EXT2_NDIR_BLOCKS; i++, ctx.bcount++) {
- if (blocks[i] || (flags & BLOCK_FLAG_APPEND)) {
- ret |= (*ctx.func)(fs, &blocks[i],
- ctx.bcount, 0, i, priv_data);
- if (ret & BLOCK_ABORT)
- goto abort_exit;
- }
- }
- if (*(blocks + EXT2_IND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
- ret |= block_iterate_ind(blocks + EXT2_IND_BLOCK,
- 0, EXT2_IND_BLOCK, &ctx);
- if (ret & BLOCK_ABORT)
- goto abort_exit;
- } else
- ctx.bcount += limit;
- if (*(blocks + EXT2_DIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
- ret |= block_iterate_dind(blocks + EXT2_DIND_BLOCK,
- 0, EXT2_DIND_BLOCK, &ctx);
- if (ret & BLOCK_ABORT)
- goto abort_exit;
- } else
- ctx.bcount += limit * limit;
- if (*(blocks + EXT2_TIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
- ret |= block_iterate_tind(blocks + EXT2_TIND_BLOCK,
- 0, EXT2_TIND_BLOCK, &ctx);
- if (ret & BLOCK_ABORT)
- goto abort_exit;
- }
-
-abort_exit:
- if (ret & BLOCK_CHANGED) {
- if (!got_inode) {
- retval = ext2fs_read_inode(fs, ino, &inode);
- if (retval)
- return retval;
- }
- for (i=0; i < EXT2_N_BLOCKS; i++)
- inode.i_block[i] = blocks[i];
- retval = ext2fs_write_inode(fs, ino, &inode);
- if (retval)
- return retval;
- }
-
- if (!block_buf)
- ext2fs_free_mem(&ctx.ind_buf);
-
- return (ret & BLOCK_ERROR) ? ctx.errcode : 0;
-}
-
-/*
- * Emulate the old ext2fs_block_iterate function!
- */
-
-struct xlate {
- int (*func)(ext2_filsys fs,
- blk_t *blocknr,
- int bcount,
- void *priv_data);
- void *real_private;
-};
-
-#ifdef __TURBOC__
-# pragma argsused
-#endif
-static int xlate_func(ext2_filsys fs, blk_t *blocknr, e2_blkcnt_t blockcnt,
- blk_t ref_block EXT2FS_ATTR((unused)),
- int ref_offset EXT2FS_ATTR((unused)),
- void *priv_data)
-{
- struct xlate *xl = (struct xlate *) priv_data;
-
- return (*xl->func)(fs, blocknr, (int) blockcnt, xl->real_private);
-}
-
-errcode_t ext2fs_block_iterate(ext2_filsys fs,
- ext2_ino_t ino,
- int flags,
- char *block_buf,
- int (*func)(ext2_filsys fs,
- blk_t *blocknr,
- int blockcnt,
- void *priv_data),
- void *priv_data)
-{
- struct xlate xl;
-
- xl.real_private = priv_data;
- xl.func = func;
-
- return ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_NO_LARGE | flags,
- block_buf, xlate_func, &xl);
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/bmap.c b/release/src/router/busybox/e2fsprogs/ext2fs/bmap.c
deleted file mode 100644
index 796b0e4f51..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/bmap.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * bmap.c --- logical to physical block mapping
- *
- * Copyright (C) 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode,
- char *block_buf, int bmap_flags,
- blk_t block, blk_t *phys_blk);
-
-#define inode_bmap(inode, nr) ((inode)->i_block[(nr)])
-
-static errcode_t block_ind_bmap(ext2_filsys fs, int flags,
- blk_t ind, char *block_buf,
- int *blocks_alloc,
- blk_t nr, blk_t *ret_blk)
-{
- errcode_t retval;
- blk_t b;
-
- if (!ind) {
- if (flags & BMAP_SET)
- return EXT2_ET_SET_BMAP_NO_IND;
- *ret_blk = 0;
- return 0;
- }
- retval = io_channel_read_blk(fs->io, ind, 1, block_buf);
- if (retval)
- return retval;
-
- if (flags & BMAP_SET) {
- b = *ret_blk;
-#if BB_BIG_ENDIAN
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
- b = ext2fs_swab32(b);
-#endif
- ((blk_t *) block_buf)[nr] = b;
- return io_channel_write_blk(fs->io, ind, 1, block_buf);
- }
-
- b = ((blk_t *) block_buf)[nr];
-
-#if BB_BIG_ENDIAN
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
- b = ext2fs_swab32(b);
-#endif
-
- if (!b && (flags & BMAP_ALLOC)) {
- b = nr ? ((blk_t *) block_buf)[nr-1] : 0;
- retval = ext2fs_alloc_block(fs, b,
- block_buf + fs->blocksize, &b);
- if (retval)
- return retval;
-
-#if BB_BIG_ENDIAN
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
- ((blk_t *) block_buf)[nr] = ext2fs_swab32(b);
- else
-#endif
- ((blk_t *) block_buf)[nr] = b;
-
- retval = io_channel_write_blk(fs->io, ind, 1, block_buf);
- if (retval)
- return retval;
-
- (*blocks_alloc)++;
- }
-
- *ret_blk = b;
- return 0;
-}
-
-static errcode_t block_dind_bmap(ext2_filsys fs, int flags,
- blk_t dind, char *block_buf,
- int *blocks_alloc,
- blk_t nr, blk_t *ret_blk)
-{
- blk_t b;
- errcode_t retval;
- blk_t addr_per_block;
-
- addr_per_block = (blk_t) fs->blocksize >> 2;
-
- retval = block_ind_bmap(fs, flags & ~BMAP_SET, dind, block_buf,
- blocks_alloc, nr / addr_per_block, &b);
- if (retval)
- return retval;
- retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc,
- nr % addr_per_block, ret_blk);
- return retval;
-}
-
-static errcode_t block_tind_bmap(ext2_filsys fs, int flags,
- blk_t tind, char *block_buf,
- int *blocks_alloc,
- blk_t nr, blk_t *ret_blk)
-{
- blk_t b;
- errcode_t retval;
- blk_t addr_per_block;
-
- addr_per_block = (blk_t) fs->blocksize >> 2;
-
- retval = block_dind_bmap(fs, flags & ~BMAP_SET, tind, block_buf,
- blocks_alloc, nr / addr_per_block, &b);
- if (retval)
- return retval;
- retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc,
- nr % addr_per_block, ret_blk);
- return retval;
-}
-
-errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode,
- char *block_buf, int bmap_flags, blk_t block,
- blk_t *phys_blk)
-{
- struct ext2_inode inode_buf;
- blk_t addr_per_block;
- blk_t b;
- char *buf = NULL;
- errcode_t retval = 0;
- int blocks_alloc = 0, inode_dirty = 0;
-
- if (!(bmap_flags & BMAP_SET))
- *phys_blk = 0;
-
- /* Read inode structure if necessary */
- if (!inode) {
- retval = ext2fs_read_inode(fs, ino, &inode_buf);
- if (retval)
- return retval;
- inode = &inode_buf;
- }
- addr_per_block = (blk_t) fs->blocksize >> 2;
-
- if (!block_buf) {
- retval = ext2fs_get_mem(fs->blocksize * 2, &buf);
- if (retval)
- return retval;
- block_buf = buf;
- }
-
- if (block < EXT2_NDIR_BLOCKS) {
- if (bmap_flags & BMAP_SET) {
- b = *phys_blk;
-#if BB_BIG_ENDIAN
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
- b = ext2fs_swab32(b);
-#endif
- inode_bmap(inode, block) = b;
- inode_dirty++;
- goto done;
- }
-
- *phys_blk = inode_bmap(inode, block);
- b = block ? inode_bmap(inode, block-1) : 0;
-
- if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) {
- retval = ext2fs_alloc_block(fs, b, block_buf, &b);
- if (retval)
- goto done;
- inode_bmap(inode, block) = b;
- blocks_alloc++;
- *phys_blk = b;
- }
- goto done;
- }
-
- /* Indirect block */
- block -= EXT2_NDIR_BLOCKS;
- if (block < addr_per_block) {
- b = inode_bmap(inode, EXT2_IND_BLOCK);
- if (!b) {
- if (!(bmap_flags & BMAP_ALLOC)) {
- if (bmap_flags & BMAP_SET)
- retval = EXT2_ET_SET_BMAP_NO_IND;
- goto done;
- }
-
- b = inode_bmap(inode, EXT2_IND_BLOCK-1);
- retval = ext2fs_alloc_block(fs, b, block_buf, &b);
- if (retval)
- goto done;
- inode_bmap(inode, EXT2_IND_BLOCK) = b;
- blocks_alloc++;
- }
- retval = block_ind_bmap(fs, bmap_flags, b, block_buf,
- &blocks_alloc, block, phys_blk);
- goto done;
- }
-
- /* Doubly indirect block */
- block -= addr_per_block;
- if (block < addr_per_block * addr_per_block) {
- b = inode_bmap(inode, EXT2_DIND_BLOCK);
- if (!b) {
- if (!(bmap_flags & BMAP_ALLOC)) {
- if (bmap_flags & BMAP_SET)
- retval = EXT2_ET_SET_BMAP_NO_IND;
- goto done;
- }
-
- b = inode_bmap(inode, EXT2_IND_BLOCK);
- retval = ext2fs_alloc_block(fs, b, block_buf, &b);
- if (retval)
- goto done;
- inode_bmap(inode, EXT2_DIND_BLOCK) = b;
- blocks_alloc++;
- }
- retval = block_dind_bmap(fs, bmap_flags, b, block_buf,
- &blocks_alloc, block, phys_blk);
- goto done;
- }
-
- /* Triply indirect block */
- block -= addr_per_block * addr_per_block;
- b = inode_bmap(inode, EXT2_TIND_BLOCK);
- if (!b) {
- if (!(bmap_flags & BMAP_ALLOC)) {
- if (bmap_flags & BMAP_SET)
- retval = EXT2_ET_SET_BMAP_NO_IND;
- goto done;
- }
-
- b = inode_bmap(inode, EXT2_DIND_BLOCK);
- retval = ext2fs_alloc_block(fs, b, block_buf, &b);
- if (retval)
- goto done;
- inode_bmap(inode, EXT2_TIND_BLOCK) = b;
- blocks_alloc++;
- }
- retval = block_tind_bmap(fs, bmap_flags, b, block_buf,
- &blocks_alloc, block, phys_blk);
-done:
- ext2fs_free_mem(&buf);
- if ((retval == 0) && (blocks_alloc || inode_dirty)) {
- inode->i_blocks += (blocks_alloc * fs->blocksize) / 512;
- retval = ext2fs_write_inode(fs, ino, inode);
- }
- return retval;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/bmove.c b/release/src/router/busybox/e2fsprogs/ext2fs/bmove.c
deleted file mode 100644
index ec9244d0bc..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/bmove.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * bmove.c --- Move blocks around to make way for a particular
- * filesystem structure.
- *
- * Copyright (C) 1997 Theodore Ts'o. This file may be redistributed
- * under the terms of the GNU Public License.
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fsP.h"
-
-struct process_block_struct {
- ext2_ino_t ino;
- struct ext2_inode * inode;
- ext2fs_block_bitmap reserve;
- ext2fs_block_bitmap alloc_map;
- errcode_t error;
- char *buf;
- int add_dir;
- int flags;
-};
-
-static int process_block(ext2_filsys fs, blk_t *block_nr,
- e2_blkcnt_t blockcnt, blk_t ref_block,
- int ref_offset, void *priv_data)
-{
- struct process_block_struct *pb;
- errcode_t retval;
- int ret;
- blk_t block, orig;
-
- pb = (struct process_block_struct *) priv_data;
- block = orig = *block_nr;
- ret = 0;
-
- /*
- * Let's see if this is one which we need to relocate
- */
- if (ext2fs_test_block_bitmap(pb->reserve, block)) {
- do {
- if (++block >= fs->super->s_blocks_count)
- block = fs->super->s_first_data_block;
- if (block == orig) {
- pb->error = EXT2_ET_BLOCK_ALLOC_FAIL;
- return BLOCK_ABORT;
- }
- } while (ext2fs_test_block_bitmap(pb->reserve, block) ||
- ext2fs_test_block_bitmap(pb->alloc_map, block));
-
- retval = io_channel_read_blk(fs->io, orig, 1, pb->buf);
- if (retval) {
- pb->error = retval;
- return BLOCK_ABORT;
- }
- retval = io_channel_write_blk(fs->io, block, 1, pb->buf);
- if (retval) {
- pb->error = retval;
- return BLOCK_ABORT;
- }
- *block_nr = block;
- ext2fs_mark_block_bitmap(pb->alloc_map, block);
- ret = BLOCK_CHANGED;
- if (pb->flags & EXT2_BMOVE_DEBUG)
- printf("ino=%ld, blockcnt=%lld, %d->%d\n", pb->ino,
- blockcnt, orig, block);
- }
- if (pb->add_dir) {
- retval = ext2fs_add_dir_block(fs->dblist, pb->ino,
- block, (int) blockcnt);
- if (retval) {
- pb->error = retval;
- ret |= BLOCK_ABORT;
- }
- }
- return ret;
-}
-
-errcode_t ext2fs_move_blocks(ext2_filsys fs,
- ext2fs_block_bitmap reserve,
- ext2fs_block_bitmap alloc_map,
- int flags)
-{
- ext2_ino_t ino;
- struct ext2_inode inode;
- errcode_t retval;
- struct process_block_struct pb;
- ext2_inode_scan scan;
- char *block_buf;
-
- retval = ext2fs_open_inode_scan(fs, 0, &scan);
- if (retval)
- return retval;
-
- pb.reserve = reserve;
- pb.error = 0;
- pb.alloc_map = alloc_map ? alloc_map : fs->block_map;
- pb.flags = flags;
-
- retval = ext2fs_get_mem(fs->blocksize * 4, &block_buf);
- if (retval)
- return retval;
- pb.buf = block_buf + fs->blocksize * 3;
-
- /*
- * If GET_DBLIST is set in the flags field, then we should
- * gather directory block information while we're doing the
- * block move.
- */
- if (flags & EXT2_BMOVE_GET_DBLIST) {
- ext2fs_free_dblist(fs->dblist);
- fs->dblist = NULL;
- retval = ext2fs_init_dblist(fs, 0);
- if (retval)
- return retval;
- }
-
- retval = ext2fs_get_next_inode(scan, &ino, &inode);
- if (retval)
- return retval;
-
- while (ino) {
- if ((inode.i_links_count == 0) ||
- !ext2fs_inode_has_valid_blocks(&inode))
- goto next;
-
- pb.ino = ino;
- pb.inode = &inode;
-
- pb.add_dir = (LINUX_S_ISDIR(inode.i_mode) &&
- flags & EXT2_BMOVE_GET_DBLIST);
-
- retval = ext2fs_block_iterate2(fs, ino, 0, block_buf,
- process_block, &pb);
- if (retval)
- return retval;
- if (pb.error)
- return pb.error;
-
- next:
- retval = ext2fs_get_next_inode(scan, &ino, &inode);
- if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
- goto next;
- }
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/brel.h b/release/src/router/busybox/e2fsprogs/ext2fs/brel.h
deleted file mode 100644
index 87bf72be45..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/brel.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * brel.h
- *
- * Copyright (C) 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-struct ext2_block_relocate_entry {
- blk_t new;
- __s16 offset;
- __u16 flags;
- union {
- blk_t block_ref;
- ext2_ino_t inode_ref;
- } owner;
-};
-
-#define RELOCATE_TYPE_REF 0x0007
-#define RELOCATE_BLOCK_REF 0x0001
-#define RELOCATE_INODE_REF 0x0002
-
-typedef struct ext2_block_relocation_table *ext2_brel;
-
-struct ext2_block_relocation_table {
- __u32 magic;
- char *name;
- blk_t current;
- void *priv_data;
-
- /*
- * Add a block relocation entry.
- */
- errcode_t (*put)(ext2_brel brel, blk_t old,
- struct ext2_block_relocate_entry *ent);
-
- /*
- * Get a block relocation entry.
- */
- errcode_t (*get)(ext2_brel brel, blk_t old,
- struct ext2_block_relocate_entry *ent);
-
- /*
- * Initialize for iterating over the block relocation entries.
- */
- errcode_t (*start_iter)(ext2_brel brel);
-
- /*
- * The iterator function for the inode relocation entries.
- * Returns an inode number of 0 when out of entries.
- */
- errcode_t (*next)(ext2_brel brel, blk_t *old,
- struct ext2_block_relocate_entry *ent);
-
- /*
- * Move the inode relocation table from one block number to
- * another.
- */
- errcode_t (*move)(ext2_brel brel, blk_t old, blk_t new);
-
- /*
- * Remove a block relocation entry.
- */
- errcode_t (*delete)(ext2_brel brel, blk_t old);
-
-
- /*
- * Free the block relocation table.
- */
- errcode_t (*free)(ext2_brel brel);
-};
-
-errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block,
- ext2_brel *brel);
-
-#define ext2fs_brel_put(brel, old, ent) ((brel)->put((brel), old, ent))
-#define ext2fs_brel_get(brel, old, ent) ((brel)->get((brel), old, ent))
-#define ext2fs_brel_start_iter(brel) ((brel)->start_iter((brel)))
-#define ext2fs_brel_next(brel, old, ent) ((brel)->next((brel), old, ent))
-#define ext2fs_brel_move(brel, old, new) ((brel)->move((brel), old, new))
-#define ext2fs_brel_delete(brel, old) ((brel)->delete((brel), old))
-#define ext2fs_brel_free(brel) ((brel)->free((brel)))
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/brel_ma.c b/release/src/router/busybox/e2fsprogs/ext2fs/brel_ma.c
deleted file mode 100644
index 652a3509cb..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/brel_ma.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * brel_ma.c
- *
- * Copyright (C) 1996, 1997 Theodore Ts'o.
- *
- * TODO: rewrite to not use a direct array!!! (Fortunately this
- * module isn't really used yet.)
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-#include "brel.h"
-
-static errcode_t bma_put(ext2_brel brel, blk_t old,
- struct ext2_block_relocate_entry *ent);
-static errcode_t bma_get(ext2_brel brel, blk_t old,
- struct ext2_block_relocate_entry *ent);
-static errcode_t bma_start_iter(ext2_brel brel);
-static errcode_t bma_next(ext2_brel brel, blk_t *old,
- struct ext2_block_relocate_entry *ent);
-static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new);
-static errcode_t bma_delete(ext2_brel brel, blk_t old);
-static errcode_t bma_free(ext2_brel brel);
-
-struct brel_ma {
- __u32 magic;
- blk_t max_block;
- struct ext2_block_relocate_entry *entries;
-};
-
-errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block,
- ext2_brel *new_brel)
-{
- ext2_brel brel = 0;
- errcode_t retval;
- struct brel_ma *ma = 0;
- size_t size;
-
- *new_brel = 0;
-
- /*
- * Allocate memory structures
- */
- retval = ext2fs_get_mem(sizeof(struct ext2_block_relocation_table),
- &brel);
- if (retval)
- goto errout;
- memset(brel, 0, sizeof(struct ext2_block_relocation_table));
-
- retval = ext2fs_get_mem(strlen(name)+1, &brel->name);
- if (retval)
- goto errout;
- strcpy(brel->name, name);
-
- retval = ext2fs_get_mem(sizeof(struct brel_ma), &ma);
- if (retval)
- goto errout;
- memset(ma, 0, sizeof(struct brel_ma));
- brel->priv_data = ma;
-
- size = (size_t) (sizeof(struct ext2_block_relocate_entry) *
- (max_block+1));
- retval = ext2fs_get_mem(size, &ma->entries);
- if (retval)
- goto errout;
- memset(ma->entries, 0, size);
- ma->max_block = max_block;
-
- /*
- * Fill in the brel data structure
- */
- brel->put = bma_put;
- brel->get = bma_get;
- brel->start_iter = bma_start_iter;
- brel->next = bma_next;
- brel->move = bma_move;
- brel->delete = bma_delete;
- brel->free = bma_free;
-
- *new_brel = brel;
- return 0;
-
-errout:
- bma_free(brel);
- return retval;
-}
-
-static errcode_t bma_put(ext2_brel brel, blk_t old,
- struct ext2_block_relocate_entry *ent)
-{
- struct brel_ma *ma;
-
- ma = brel->priv_data;
- if (old > ma->max_block)
- return EXT2_ET_INVALID_ARGUMENT;
- ma->entries[(unsigned)old] = *ent;
- return 0;
-}
-
-static errcode_t bma_get(ext2_brel brel, blk_t old,
- struct ext2_block_relocate_entry *ent)
-{
- struct brel_ma *ma;
-
- ma = brel->priv_data;
- if (old > ma->max_block)
- return EXT2_ET_INVALID_ARGUMENT;
- if (ma->entries[(unsigned)old].new == 0)
- return ENOENT;
- *ent = ma->entries[old];
- return 0;
-}
-
-static errcode_t bma_start_iter(ext2_brel brel)
-{
- brel->current = 0;
- return 0;
-}
-
-static errcode_t bma_next(ext2_brel brel, blk_t *old,
- struct ext2_block_relocate_entry *ent)
-{
- struct brel_ma *ma;
-
- ma = brel->priv_data;
- while (++brel->current < ma->max_block) {
- if (ma->entries[(unsigned)brel->current].new == 0)
- continue;
- *old = brel->current;
- *ent = ma->entries[(unsigned)brel->current];
- return 0;
- }
- *old = 0;
- return 0;
-}
-
-static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new)
-{
- struct brel_ma *ma;
-
- ma = brel->priv_data;
- if ((old > ma->max_block) || (new > ma->max_block))
- return EXT2_ET_INVALID_ARGUMENT;
- if (ma->entries[(unsigned)old].new == 0)
- return ENOENT;
- ma->entries[(unsigned)new] = ma->entries[old];
- ma->entries[(unsigned)old].new = 0;
- return 0;
-}
-
-static errcode_t bma_delete(ext2_brel brel, blk_t old)
-{
- struct brel_ma *ma;
-
- ma = brel->priv_data;
- if (old > ma->max_block)
- return EXT2_ET_INVALID_ARGUMENT;
- if (ma->entries[(unsigned)old].new == 0)
- return ENOENT;
- ma->entries[(unsigned)old].new = 0;
- return 0;
-}
-
-static errcode_t bma_free(ext2_brel brel)
-{
- struct brel_ma *ma;
-
- if (!brel)
- return 0;
-
- ma = brel->priv_data;
-
- if (ma) {
- ext2fs_free_mem(&ma->entries);
- ext2fs_free_mem(&ma);
- }
- ext2fs_free_mem(&brel->name);
- ext2fs_free_mem(&brel);
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/check_desc.c b/release/src/router/busybox/e2fsprogs/ext2fs/check_desc.c
deleted file mode 100644
index dd4b0e9cf5..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/check_desc.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * check_desc.c --- Check the group descriptors of an ext2 filesystem
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * This routine sanity checks the group descriptors
- */
-errcode_t ext2fs_check_desc(ext2_filsys fs)
-{
- dgrp_t i;
- blk_t block = fs->super->s_first_data_block;
- blk_t next;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- for (i = 0; i < fs->group_desc_count; i++) {
- next = block + fs->super->s_blocks_per_group;
- /*
- * Check to make sure block bitmap for group is
- * located within the group.
- */
- if (fs->group_desc[i].bg_block_bitmap < block ||
- fs->group_desc[i].bg_block_bitmap >= next)
- return EXT2_ET_GDESC_BAD_BLOCK_MAP;
- /*
- * Check to make sure inode bitmap for group is
- * located within the group
- */
- if (fs->group_desc[i].bg_inode_bitmap < block ||
- fs->group_desc[i].bg_inode_bitmap >= next)
- return EXT2_ET_GDESC_BAD_INODE_MAP;
- /*
- * Check to make sure inode table for group is located
- * within the group
- */
- if (fs->group_desc[i].bg_inode_table < block ||
- ((fs->group_desc[i].bg_inode_table +
- fs->inode_blocks_per_group) >= next))
- return EXT2_ET_GDESC_BAD_INODE_TABLE;
-
- block = next;
- }
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/closefs.c b/release/src/router/busybox/e2fsprogs/ext2fs/closefs.c
deleted file mode 100644
index bfa15e22a8..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/closefs.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * closefs.c --- close an ext2 filesystem
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <time.h>
-#include <string.h>
-
-#include "ext2_fs.h"
-#include "ext2fsP.h"
-
-static int test_root(int a, int b)
-{
- if (a == 0)
- return 1;
- while (1) {
- if (a == 1)
- return 1;
- if (a % b)
- return 0;
- a = a / b;
- }
-}
-
-int ext2fs_bg_has_super(ext2_filsys fs, int group_block)
-{
- if (!(fs->super->s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
- return 1;
-
- if (test_root(group_block, 3) || (test_root(group_block, 5)) ||
- test_root(group_block, 7))
- return 1;
-
- return 0;
-}
-
-int ext2fs_super_and_bgd_loc(ext2_filsys fs,
- dgrp_t group,
- blk_t *ret_super_blk,
- blk_t *ret_old_desc_blk,
- blk_t *ret_new_desc_blk,
- int *ret_meta_bg)
-{
- blk_t group_block, super_blk = 0, old_desc_blk = 0, new_desc_blk = 0;
- unsigned int meta_bg, meta_bg_size;
- int numblocks, has_super;
- int old_desc_blocks;
-
- group_block = fs->super->s_first_data_block +
- (group * fs->super->s_blocks_per_group);
-
- if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
- old_desc_blocks = fs->super->s_first_meta_bg;
- else
- old_desc_blocks =
- fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
-
- if (group == fs->group_desc_count-1) {
- numblocks = (fs->super->s_blocks_count -
- fs->super->s_first_data_block) %
- fs->super->s_blocks_per_group;
- if (!numblocks)
- numblocks = fs->super->s_blocks_per_group;
- } else
- numblocks = fs->super->s_blocks_per_group;
-
- has_super = ext2fs_bg_has_super(fs, group);
-
- if (has_super) {
- super_blk = group_block;
- numblocks--;
- }
- meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc));
- meta_bg = group / meta_bg_size;
-
- if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
- (meta_bg < fs->super->s_first_meta_bg)) {
- if (has_super) {
- old_desc_blk = group_block + 1;
- numblocks -= old_desc_blocks;
- }
- } else {
- if (((group % meta_bg_size) == 0) ||
- ((group % meta_bg_size) == 1) ||
- ((group % meta_bg_size) == (meta_bg_size-1))) {
- if (has_super)
- has_super = 1;
- new_desc_blk = group_block + has_super;
- numblocks--;
- }
- }
-
- numblocks -= 2 + fs->inode_blocks_per_group;
-
- if (ret_super_blk)
- *ret_super_blk = super_blk;
- if (ret_old_desc_blk)
- *ret_old_desc_blk = old_desc_blk;
- if (ret_new_desc_blk)
- *ret_new_desc_blk = new_desc_blk;
- if (ret_meta_bg)
- *ret_meta_bg = meta_bg;
- return numblocks;
-}
-
-
-/*
- * This function forces out the primary superblock. We need to only
- * write out those fields which we have changed, since if the
- * filesystem is mounted, it may have changed some of the other
- * fields.
- *
- * It takes as input a superblock which has already been byte swapped
- * (if necessary).
- *
- */
-static errcode_t write_primary_superblock(ext2_filsys fs,
- struct ext2_super_block *super)
-{
- __u16 *old_super, *new_super;
- int check_idx, write_idx, size;
- errcode_t retval;
-
- if (!fs->io->manager->write_byte || !fs->orig_super) {
- io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET);
- retval = io_channel_write_blk(fs->io, 1, -SUPERBLOCK_SIZE,
- super);
- io_channel_set_blksize(fs->io, fs->blocksize);
- return retval;
- }
-
- old_super = (__u16 *) fs->orig_super;
- new_super = (__u16 *) super;
-
- for (check_idx = 0; check_idx < SUPERBLOCK_SIZE/2; check_idx++) {
- if (old_super[check_idx] == new_super[check_idx])
- continue;
- write_idx = check_idx;
- for (check_idx++; check_idx < SUPERBLOCK_SIZE/2; check_idx++)
- if (old_super[check_idx] == new_super[check_idx])
- break;
- size = 2 * (check_idx - write_idx);
- retval = io_channel_write_byte(fs->io,
- SUPERBLOCK_OFFSET + (2 * write_idx), size,
- new_super + write_idx);
- if (retval)
- return retval;
- }
- memcpy(fs->orig_super, super, SUPERBLOCK_SIZE);
- return 0;
-}
-
-
-/*
- * Updates the revision to EXT2_DYNAMIC_REV
- */
-void ext2fs_update_dynamic_rev(ext2_filsys fs)
-{
- struct ext2_super_block *sb = fs->super;
-
- if (sb->s_rev_level > EXT2_GOOD_OLD_REV)
- return;
-
- sb->s_rev_level = EXT2_DYNAMIC_REV;
- sb->s_first_ino = EXT2_GOOD_OLD_FIRST_INO;
- sb->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
- /* s_uuid is handled by e2fsck already */
- /* other fields should be left alone */
-}
-
-static errcode_t write_backup_super(ext2_filsys fs, dgrp_t group,
- blk_t group_block,
- struct ext2_super_block *super_shadow)
-{
- dgrp_t sgrp = group;
-
- if (sgrp > ((1 << 16) - 1))
- sgrp = (1 << 16) - 1;
-#if BB_BIG_ENDIAN
- if (fs->flags & EXT2_FLAG_SWAP_BYTES)
- super_shadow->s_block_group_nr = ext2fs_swab16(sgrp);
- else
-#endif
- fs->super->s_block_group_nr = sgrp;
-
- return io_channel_write_blk(fs->io, group_block, -SUPERBLOCK_SIZE,
- super_shadow);
-}
-
-
-errcode_t ext2fs_flush(ext2_filsys fs)
-{
- dgrp_t i;
- blk_t group_block;
- errcode_t retval;
- unsigned long fs_state;
- struct ext2_super_block *super_shadow = NULL;
- struct ext2_group_desc *group_shadow = NULL;
- char *group_ptr;
- int old_desc_blocks;
-#if BB_BIG_ENDIAN
- dgrp_t j;
- struct ext2_group_desc *s, *t;
-#endif
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- fs_state = fs->super->s_state;
-
- fs->super->s_wtime = time(NULL);
- fs->super->s_block_group_nr = 0;
-#if BB_BIG_ENDIAN
- if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
- retval = EXT2_ET_NO_MEMORY;
- retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow);
- if (retval)
- goto errout;
- retval = ext2fs_get_mem((size_t)(fs->blocksize *
- fs->desc_blocks),
- &group_shadow);
- if (retval)
- goto errout;
- memset(group_shadow, 0, (size_t) fs->blocksize *
- fs->desc_blocks);
-
- /* swap the group descriptors */
- for (j=0, s=fs->group_desc, t=group_shadow;
- j < fs->group_desc_count; j++, t++, s++) {
- *t = *s;
- ext2fs_swap_group_desc(t);
- }
- } else {
- super_shadow = fs->super;
- group_shadow = fs->group_desc;
- }
-#else
- super_shadow = fs->super;
- group_shadow = fs->group_desc;
-#endif
-
- /*
- * If this is an external journal device, don't write out the
- * block group descriptors or any of the backup superblocks
- */
- if (fs->super->s_feature_incompat &
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
- goto write_primary_superblock_only;
-
- /*
- * Set the state of the FS to be non-valid. (The state has
- * already been backed up earlier, and will be restored after
- * we write out the backup superblocks.)
- */
- fs->super->s_state &= ~EXT2_VALID_FS;
-#if BB_BIG_ENDIAN
- if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
- *super_shadow = *fs->super;
- ext2fs_swap_super(super_shadow);
- }
-#endif
-
- /*
- * Write out the master group descriptors, and the backup
- * superblocks and group descriptors.
- */
- group_block = fs->super->s_first_data_block;
- group_ptr = (char *) group_shadow;
- if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
- old_desc_blocks = fs->super->s_first_meta_bg;
- else
- old_desc_blocks = fs->desc_blocks;
-
- for (i = 0; i < fs->group_desc_count; i++) {
- blk_t super_blk, old_desc_blk, new_desc_blk;
- int meta_bg;
-
- ext2fs_super_and_bgd_loc(fs, i, &super_blk, &old_desc_blk,
- &new_desc_blk, &meta_bg);
-
- if (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) &&i && super_blk) {
- retval = write_backup_super(fs, i, super_blk,
- super_shadow);
- if (retval)
- goto errout;
- }
- if (fs->flags & EXT2_FLAG_SUPER_ONLY)
- continue;
- if ((old_desc_blk) &&
- (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) || (i == 0))) {
- retval = io_channel_write_blk(fs->io,
- old_desc_blk, old_desc_blocks, group_ptr);
- if (retval)
- goto errout;
- }
- if (new_desc_blk) {
- retval = io_channel_write_blk(fs->io, new_desc_blk,
- 1, group_ptr + (meta_bg*fs->blocksize));
- if (retval)
- goto errout;
- }
- }
- fs->super->s_block_group_nr = 0;
- fs->super->s_state = fs_state;
-#if BB_BIG_ENDIAN
- if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
- *super_shadow = *fs->super;
- ext2fs_swap_super(super_shadow);
- }
-#endif
-
- /*
- * If the write_bitmaps() function is present, call it to
- * flush the bitmaps. This is done this way so that a simple
- * program that doesn't mess with the bitmaps doesn't need to
- * drag in the bitmaps.c code.
- */
- if (fs->write_bitmaps) {
- retval = fs->write_bitmaps(fs);
- if (retval)
- goto errout;
- }
-
-write_primary_superblock_only:
- /*
- * Write out master superblock. This has to be done
- * separately, since it is located at a fixed location
- * (SUPERBLOCK_OFFSET). We flush all other pending changes
- * out to disk first, just to avoid a race condition with an
- * insy-tinsy window....
- */
- retval = io_channel_flush(fs->io);
- retval = write_primary_superblock(fs, super_shadow);
- if (retval)
- goto errout;
-
- fs->flags &= ~EXT2_FLAG_DIRTY;
-
- retval = io_channel_flush(fs->io);
-errout:
- fs->super->s_state = fs_state;
- if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
- if (super_shadow)
- ext2fs_free_mem(&super_shadow);
- if (group_shadow)
- ext2fs_free_mem(&group_shadow);
- }
- return retval;
-}
-
-errcode_t ext2fs_close(ext2_filsys fs)
-{
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (fs->flags & EXT2_FLAG_DIRTY) {
- retval = ext2fs_flush(fs);
- if (retval)
- return retval;
- }
- if (fs->write_bitmaps) {
- retval = fs->write_bitmaps(fs);
- if (retval)
- return retval;
- }
- ext2fs_free(fs);
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/cmp_bitmaps.c b/release/src/router/busybox/e2fsprogs/ext2fs/cmp_bitmaps.c
deleted file mode 100644
index 7f78ff8042..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/cmp_bitmaps.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * cmp_bitmaps.c --- routines to compare inode and block bitmaps.
- *
- * Copyright (C) 1995 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
- ext2fs_block_bitmap bm2)
-{
- blk_t i;
-
- EXT2_CHECK_MAGIC(bm1, EXT2_ET_MAGIC_BLOCK_BITMAP);
- EXT2_CHECK_MAGIC(bm2, EXT2_ET_MAGIC_BLOCK_BITMAP);
-
- if ((bm1->start != bm2->start) ||
- (bm1->end != bm2->end) ||
- (memcmp(bm1->bitmap, bm2->bitmap,
- (size_t) (bm1->end - bm1->start)/8)))
- return EXT2_ET_NEQ_BLOCK_BITMAP;
-
- for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
- if (ext2fs_fast_test_block_bitmap(bm1, i) !=
- ext2fs_fast_test_block_bitmap(bm2, i))
- return EXT2_ET_NEQ_BLOCK_BITMAP;
-
- return 0;
-}
-
-errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
- ext2fs_inode_bitmap bm2)
-{
- ext2_ino_t i;
-
- EXT2_CHECK_MAGIC(bm1, EXT2_ET_MAGIC_INODE_BITMAP);
- EXT2_CHECK_MAGIC(bm2, EXT2_ET_MAGIC_INODE_BITMAP);
-
- if ((bm1->start != bm2->start) ||
- (bm1->end != bm2->end) ||
- (memcmp(bm1->bitmap, bm2->bitmap,
- (size_t) (bm1->end - bm1->start)/8)))
- return EXT2_ET_NEQ_INODE_BITMAP;
-
- for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
- if (ext2fs_fast_test_inode_bitmap(bm1, i) !=
- ext2fs_fast_test_inode_bitmap(bm2, i))
- return EXT2_ET_NEQ_INODE_BITMAP;
-
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/dblist.c b/release/src/router/busybox/e2fsprogs/ext2fs/dblist.c
deleted file mode 100644
index 06ff6d8079..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/dblist.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * dblist.c -- directory block list functions
- *
- * Copyright 1997 by Theodore Ts'o
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- *
- */
-
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <string.h>
-#include <time.h>
-
-#include "ext2_fs.h"
-#include "ext2fsP.h"
-
-static int dir_block_cmp(const void *a, const void *b);
-
-/*
- * Returns the number of directories in the filesystem as reported by
- * the group descriptors. Of course, the group descriptors could be
- * wrong!
- */
-errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs)
-{
- dgrp_t i;
- ext2_ino_t num_dirs, max_dirs;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- num_dirs = 0;
- max_dirs = fs->super->s_inodes_per_group;
- for (i = 0; i < fs->group_desc_count; i++) {
- if (fs->group_desc[i].bg_used_dirs_count > max_dirs)
- num_dirs += max_dirs / 8;
- else
- num_dirs += fs->group_desc[i].bg_used_dirs_count;
- }
- if (num_dirs > fs->super->s_inodes_count)
- num_dirs = fs->super->s_inodes_count;
-
- *ret_num_dirs = num_dirs;
-
- return 0;
-}
-
-/*
- * helper function for making a new directory block list (for
- * initialize and copy).
- */
-static errcode_t make_dblist(ext2_filsys fs, ext2_ino_t size, ext2_ino_t count,
- struct ext2_db_entry *list,
- ext2_dblist *ret_dblist)
-{
- ext2_dblist dblist;
- errcode_t retval;
- size_t len;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if ((ret_dblist == 0) && fs->dblist &&
- (fs->dblist->magic == EXT2_ET_MAGIC_DBLIST))
- return 0;
-
- retval = ext2fs_get_mem(sizeof(struct ext2_struct_dblist), &dblist);
- if (retval)
- return retval;
- memset(dblist, 0, sizeof(struct ext2_struct_dblist));
-
- dblist->magic = EXT2_ET_MAGIC_DBLIST;
- dblist->fs = fs;
- if (size)
- dblist->size = size;
- else {
- retval = ext2fs_get_num_dirs(fs, &dblist->size);
- if (retval)
- goto cleanup;
- dblist->size = (dblist->size * 2) + 12;
- }
- len = (size_t) sizeof(struct ext2_db_entry) * dblist->size;
- dblist->count = count;
- retval = ext2fs_get_mem(len, &dblist->list);
- if (retval)
- goto cleanup;
-
- if (list)
- memcpy(dblist->list, list, len);
- else
- memset(dblist->list, 0, len);
- if (ret_dblist)
- *ret_dblist = dblist;
- else
- fs->dblist = dblist;
- return 0;
-cleanup:
- ext2fs_free_mem(&dblist);
- return retval;
-}
-
-/*
- * Initialize a directory block list
- */
-errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist)
-{
- ext2_dblist dblist;
- errcode_t retval;
-
- retval = make_dblist(fs, 0, 0, 0, &dblist);
- if (retval)
- return retval;
-
- dblist->sorted = 1;
- if (ret_dblist)
- *ret_dblist = dblist;
- else
- fs->dblist = dblist;
-
- return 0;
-}
-
-/*
- * Copy a directory block list
- */
-errcode_t ext2fs_copy_dblist(ext2_dblist src, ext2_dblist *dest)
-{
- ext2_dblist dblist;
- errcode_t retval;
-
- retval = make_dblist(src->fs, src->size, src->count, src->list,
- &dblist);
- if (retval)
- return retval;
- dblist->sorted = src->sorted;
- *dest = dblist;
- return 0;
-}
-
-/*
- * Close a directory block list
- *
- * (moved to closefs.c)
- */
-
-
-/*
- * Add a directory block to the directory block list
- */
-errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk,
- int blockcnt)
-{
- struct ext2_db_entry *new_entry;
- errcode_t retval;
- unsigned long old_size;
-
- EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
-
- if (dblist->count >= dblist->size) {
- old_size = dblist->size * sizeof(struct ext2_db_entry);
- dblist->size += 100;
- retval = ext2fs_resize_mem(old_size, (size_t) dblist->size *
- sizeof(struct ext2_db_entry),
- &dblist->list);
- if (retval) {
- dblist->size -= 100;
- return retval;
- }
- }
- new_entry = dblist->list + ( (int) dblist->count++);
- new_entry->blk = blk;
- new_entry->ino = ino;
- new_entry->blockcnt = blockcnt;
-
- dblist->sorted = 0;
-
- return 0;
-}
-
-/*
- * Change the directory block to the directory block list
- */
-errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk,
- int blockcnt)
-{
- dgrp_t i;
-
- EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
-
- for (i=0; i < dblist->count; i++) {
- if ((dblist->list[i].ino != ino) ||
- (dblist->list[i].blockcnt != blockcnt))
- continue;
- dblist->list[i].blk = blk;
- dblist->sorted = 0;
- return 0;
- }
- return EXT2_ET_DB_NOT_FOUND;
-}
-
-void ext2fs_dblist_sort(ext2_dblist dblist,
- int (*sortfunc)(const void *,
- const void *))
-{
- if (!sortfunc)
- sortfunc = dir_block_cmp;
- qsort(dblist->list, (size_t) dblist->count,
- sizeof(struct ext2_db_entry), sortfunc);
- dblist->sorted = 1;
-}
-
-/*
- * This function iterates over the directory block list
- */
-errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
- int (*func)(ext2_filsys fs,
- struct ext2_db_entry *db_info,
- void *priv_data),
- void *priv_data)
-{
- ext2_ino_t i;
- int ret;
-
- EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
-
- if (!dblist->sorted)
- ext2fs_dblist_sort(dblist, 0);
- for (i=0; i < dblist->count; i++) {
- ret = (*func)(dblist->fs, &dblist->list[(int)i], priv_data);
- if (ret & DBLIST_ABORT)
- return 0;
- }
- return 0;
-}
-
-static int dir_block_cmp(const void *a, const void *b)
-{
- const struct ext2_db_entry *db_a =
- (const struct ext2_db_entry *) a;
- const struct ext2_db_entry *db_b =
- (const struct ext2_db_entry *) b;
-
- if (db_a->blk != db_b->blk)
- return (int) (db_a->blk - db_b->blk);
-
- if (db_a->ino != db_b->ino)
- return (int) (db_a->ino - db_b->ino);
-
- return (int) (db_a->blockcnt - db_b->blockcnt);
-}
-
-int ext2fs_dblist_count(ext2_dblist dblist)
-{
- return (int) dblist->count;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/dblist_dir.c b/release/src/router/busybox/e2fsprogs/ext2fs/dblist_dir.c
deleted file mode 100644
index b239204664..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/dblist_dir.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * dblist_dir.c --- iterate by directory entry
- *
- * Copyright 1997 by Theodore Ts'o
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- *
- */
-
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <string.h>
-#include <time.h>
-
-#include "ext2_fs.h"
-#include "ext2fsP.h"
-
-static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info,
- void *priv_data);
-
-errcode_t ext2fs_dblist_dir_iterate(ext2_dblist dblist,
- int flags,
- char *block_buf,
- int (*func)(ext2_ino_t dir,
- int entry,
- struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *priv_data),
- void *priv_data)
-{
- errcode_t retval;
- struct dir_context ctx;
-
- EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
-
- ctx.dir = 0;
- ctx.flags = flags;
- if (block_buf)
- ctx.buf = block_buf;
- else {
- retval = ext2fs_get_mem(dblist->fs->blocksize, &ctx.buf);
- if (retval)
- return retval;
- }
- ctx.func = func;
- ctx.priv_data = priv_data;
- ctx.errcode = 0;
-
- retval = ext2fs_dblist_iterate(dblist, db_dir_proc, &ctx);
-
- if (!block_buf)
- ext2fs_free_mem(&ctx.buf);
- if (retval)
- return retval;
- return ctx.errcode;
-}
-
-static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info,
- void *priv_data)
-{
- struct dir_context *ctx;
-
- ctx = (struct dir_context *) priv_data;
- ctx->dir = db_info->ino;
-
- return ext2fs_process_dir_block(fs, &db_info->blk,
- db_info->blockcnt, 0, 0, priv_data);
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/dir_iterate.c b/release/src/router/busybox/e2fsprogs/ext2fs/dir_iterate.c
deleted file mode 100644
index eb5dae0a64..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/dir_iterate.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * dir_iterate.c --- ext2fs directory iteration operations
- *
- * Copyright (C) 1993, 1994, 1994, 1995, 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fsP.h"
-
-/*
- * This function checks to see whether or not a potential deleted
- * directory entry looks valid. What we do is check the deleted entry
- * and each successive entry to make sure that they all look valid and
- * that the last deleted entry ends at the beginning of the next
- * undeleted entry. Returns 1 if the deleted entry looks valid, zero
- * if not valid.
- */
-static int ext2fs_validate_entry(char *buf, int offset, int final_offset)
-{
- struct ext2_dir_entry *dirent;
-
- while (offset < final_offset) {
- dirent = (struct ext2_dir_entry *)(buf + offset);
- offset += dirent->rec_len;
- if ((dirent->rec_len < 8) ||
- ((dirent->rec_len % 4) != 0) ||
- (((dirent->name_len & 0xFF)+8) > dirent->rec_len))
- return 0;
- }
- return (offset == final_offset);
-}
-
-errcode_t ext2fs_dir_iterate2(ext2_filsys fs,
- ext2_ino_t dir,
- int flags,
- char *block_buf,
- int (*func)(ext2_ino_t dir,
- int entry,
- struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *priv_data),
- void *priv_data)
-{
- struct dir_context ctx;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- retval = ext2fs_check_directory(fs, dir);
- if (retval)
- return retval;
-
- ctx.dir = dir;
- ctx.flags = flags;
- if (block_buf)
- ctx.buf = block_buf;
- else {
- retval = ext2fs_get_mem(fs->blocksize, &ctx.buf);
- if (retval)
- return retval;
- }
- ctx.func = func;
- ctx.priv_data = priv_data;
- ctx.errcode = 0;
- retval = ext2fs_block_iterate2(fs, dir, 0, 0,
- ext2fs_process_dir_block, &ctx);
- if (!block_buf)
- ext2fs_free_mem(&ctx.buf);
- if (retval)
- return retval;
- return ctx.errcode;
-}
-
-struct xlate {
- int (*func)(struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *priv_data);
- void *real_private;
-};
-
-static int xlate_func(ext2_ino_t dir EXT2FS_ATTR((unused)),
- int entry EXT2FS_ATTR((unused)),
- struct ext2_dir_entry *dirent, int offset,
- int blocksize, char *buf, void *priv_data)
-{
- struct xlate *xl = (struct xlate *) priv_data;
-
- return (*xl->func)(dirent, offset, blocksize, buf, xl->real_private);
-}
-
-extern errcode_t ext2fs_dir_iterate(ext2_filsys fs,
- ext2_ino_t dir,
- int flags,
- char *block_buf,
- int (*func)(struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *priv_data),
- void *priv_data)
-{
- struct xlate xl;
-
- xl.real_private = priv_data;
- xl.func = func;
-
- return ext2fs_dir_iterate2(fs, dir, flags, block_buf,
- xlate_func, &xl);
-}
-
-
-/*
- * Helper function which is private to this module. Used by
- * ext2fs_dir_iterate() and ext2fs_dblist_dir_iterate()
- */
-int ext2fs_process_dir_block(ext2_filsys fs,
- blk_t *blocknr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block EXT2FS_ATTR((unused)),
- int ref_offset EXT2FS_ATTR((unused)),
- void *priv_data)
-{
- struct dir_context *ctx = (struct dir_context *) priv_data;
- unsigned int offset = 0;
- unsigned int next_real_entry = 0;
- int ret = 0;
- int changed = 0;
- int do_abort = 0;
- int entry, size;
- struct ext2_dir_entry *dirent;
-
- if (blockcnt < 0)
- return 0;
-
- entry = blockcnt ? DIRENT_OTHER_FILE : DIRENT_DOT_FILE;
-
- ctx->errcode = ext2fs_read_dir_block(fs, *blocknr, ctx->buf);
- if (ctx->errcode)
- return BLOCK_ABORT;
-
- while (offset < fs->blocksize) {
- dirent = (struct ext2_dir_entry *) (ctx->buf + offset);
- if (((offset + dirent->rec_len) > fs->blocksize) ||
- (dirent->rec_len < 8) ||
- ((dirent->rec_len % 4) != 0) ||
- (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
- ctx->errcode = EXT2_ET_DIR_CORRUPTED;
- return BLOCK_ABORT;
- }
- if (!dirent->inode &&
- !(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY))
- goto next;
-
- ret = (ctx->func)(ctx->dir,
- (next_real_entry > offset) ?
- DIRENT_DELETED_FILE : entry,
- dirent, offset,
- fs->blocksize, ctx->buf,
- ctx->priv_data);
- if (entry < DIRENT_OTHER_FILE)
- entry++;
-
- if (ret & DIRENT_CHANGED)
- changed++;
- if (ret & DIRENT_ABORT) {
- do_abort++;
- break;
- }
-next:
- if (next_real_entry == offset)
- next_real_entry += dirent->rec_len;
-
- if (ctx->flags & DIRENT_FLAG_INCLUDE_REMOVED) {
- size = ((dirent->name_len & 0xFF) + 11) & ~3;
-
- if (dirent->rec_len != size) {
- unsigned int final_offset;
-
- final_offset = offset + dirent->rec_len;
- offset += size;
- while (offset < final_offset &&
- !ext2fs_validate_entry(ctx->buf,
- offset,
- final_offset))
- offset += 4;
- continue;
- }
- }
- offset += dirent->rec_len;
- }
-
- if (changed) {
- ctx->errcode = ext2fs_write_dir_block(fs, *blocknr, ctx->buf);
- if (ctx->errcode)
- return BLOCK_ABORT;
- }
- if (do_abort)
- return BLOCK_ABORT;
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/dirblock.c b/release/src/router/busybox/e2fsprogs/ext2fs/dirblock.c
deleted file mode 100644
index f9c5a104b0..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/dirblock.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * dirblock.c --- directory block routines.
- *
- * Copyright (C) 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <string.h>
-#include <time.h>
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
- void *buf, int flags EXT2FS_ATTR((unused)))
-{
- errcode_t retval;
- char *p, *end;
- struct ext2_dir_entry *dirent;
- unsigned int name_len, rec_len;
-#if BB_BIG_ENDIAN
- unsigned int do_swap;
-#endif
-
- retval = io_channel_read_blk(fs->io, block, 1, buf);
- if (retval)
- return retval;
-#if BB_BIG_ENDIAN
- do_swap = (fs->flags & (EXT2_FLAG_SWAP_BYTES|
- EXT2_FLAG_SWAP_BYTES_READ)) != 0;
-#endif
- p = (char *) buf;
- end = (char *) buf + fs->blocksize;
- while (p < end-8) {
- dirent = (struct ext2_dir_entry *) p;
-#if BB_BIG_ENDIAN
- if (do_swap) {
- dirent->inode = ext2fs_swab32(dirent->inode);
- dirent->rec_len = ext2fs_swab16(dirent->rec_len);
- dirent->name_len = ext2fs_swab16(dirent->name_len);
- }
-#endif
- name_len = dirent->name_len;
-#ifdef WORDS_BIGENDIAN
- if (flags & EXT2_DIRBLOCK_V2_STRUCT)
- dirent->name_len = ext2fs_swab16(dirent->name_len);
-#endif
- rec_len = dirent->rec_len;
- if ((rec_len < 8) || (rec_len % 4)) {
- rec_len = 8;
- retval = EXT2_ET_DIR_CORRUPTED;
- }
- if (((name_len & 0xFF) + 8) > dirent->rec_len)
- retval = EXT2_ET_DIR_CORRUPTED;
- p += rec_len;
- }
- return retval;
-}
-
-errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
- void *buf)
-{
- return ext2fs_read_dir_block2(fs, block, buf, 0);
-}
-
-
-errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
- void *inbuf, int flags EXT2FS_ATTR((unused)))
-{
-#if BB_BIG_ENDIAN
- int do_swap = 0;
- errcode_t retval;
- char *p, *end;
- char *buf = NULL;
- struct ext2_dir_entry *dirent;
-
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
- do_swap = 1;
-
-#ifndef WORDS_BIGENDIAN
- if (!do_swap)
- return io_channel_write_blk(fs->io, block, 1, (char *) inbuf);
-#endif
-
- retval = ext2fs_get_mem(fs->blocksize, &buf);
- if (retval)
- return retval;
- memcpy(buf, inbuf, fs->blocksize);
- p = buf;
- end = buf + fs->blocksize;
- while (p < end) {
- dirent = (struct ext2_dir_entry *) p;
- if ((dirent->rec_len < 8) ||
- (dirent->rec_len % 4)) {
- ext2fs_free_mem(&buf);
- return EXT2_ET_DIR_CORRUPTED;
- }
- p += dirent->rec_len;
- if (do_swap) {
- dirent->inode = ext2fs_swab32(dirent->inode);
- dirent->rec_len = ext2fs_swab16(dirent->rec_len);
- dirent->name_len = ext2fs_swab16(dirent->name_len);
- }
-#ifdef WORDS_BIGENDIAN
- if (flags & EXT2_DIRBLOCK_V2_STRUCT)
- dirent->name_len = ext2fs_swab16(dirent->name_len);
-#endif
- }
- retval = io_channel_write_blk(fs->io, block, 1, buf);
- ext2fs_free_mem(&buf);
- return retval;
-#else
- return io_channel_write_blk(fs->io, block, 1, (char *) inbuf);
-#endif
-}
-
-
-errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
- void *inbuf)
-{
- return ext2fs_write_dir_block2(fs, block, inbuf, 0);
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/dirhash.c b/release/src/router/busybox/e2fsprogs/ext2fs/dirhash.c
deleted file mode 100644
index 09e34be3b6..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/dirhash.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * dirhash.c -- Calculate the hash of a directory entry
- *
- * Copyright (c) 2001 Daniel Phillips
- *
- * Copyright (c) 2002 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * Keyed 32-bit hash function using TEA in a Davis-Meyer function
- * H0 = Key
- * Hi = E Mi(Hi-1) + Hi-1
- *
- * (see Applied Cryptography, 2nd edition, p448).
- *
- * Jeremy Fitzhardinge <jeremy@zip.com.au> 1998
- *
- * This code is made available under the terms of the GPL
- */
-#define DELTA 0x9E3779B9
-
-static void TEA_transform(__u32 buf[4], __u32 const in[])
-{
- __u32 sum = 0;
- __u32 b0 = buf[0], b1 = buf[1];
- __u32 a = in[0], b = in[1], c = in[2], d = in[3];
- int n = 16;
-
- do {
- sum += DELTA;
- b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
- b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
- } while (--n);
-
- buf[0] += b0;
- buf[1] += b1;
-}
-
-/* F, G and H are basic MD4 functions: selection, majority, parity */
-#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
-#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-
-/*
- * The generic round function. The application is so specific that
- * we don't bother protecting all the arguments with parens, as is generally
- * good macro practice, in favor of extra legibility.
- * Rotation is separate from addition to prevent recomputation
- */
-#define ROUND(f, a, b, c, d, x, s) \
- (a += f(b, c, d) + x, a = (a << s) | (a >> (32-s)))
-#define K1 0
-#define K2 013240474631UL
-#define K3 015666365641UL
-
-/*
- * Basic cut-down MD4 transform. Returns only 32 bits of result.
- */
-static void halfMD4Transform (__u32 buf[4], __u32 const in[])
-{
- __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
-
- /* Round 1 */
- ROUND(F, a, b, c, d, in[0] + K1, 3);
- ROUND(F, d, a, b, c, in[1] + K1, 7);
- ROUND(F, c, d, a, b, in[2] + K1, 11);
- ROUND(F, b, c, d, a, in[3] + K1, 19);
- ROUND(F, a, b, c, d, in[4] + K1, 3);
- ROUND(F, d, a, b, c, in[5] + K1, 7);
- ROUND(F, c, d, a, b, in[6] + K1, 11);
- ROUND(F, b, c, d, a, in[7] + K1, 19);
-
- /* Round 2 */
- ROUND(G, a, b, c, d, in[1] + K2, 3);
- ROUND(G, d, a, b, c, in[3] + K2, 5);
- ROUND(G, c, d, a, b, in[5] + K2, 9);
- ROUND(G, b, c, d, a, in[7] + K2, 13);
- ROUND(G, a, b, c, d, in[0] + K2, 3);
- ROUND(G, d, a, b, c, in[2] + K2, 5);
- ROUND(G, c, d, a, b, in[4] + K2, 9);
- ROUND(G, b, c, d, a, in[6] + K2, 13);
-
- /* Round 3 */
- ROUND(H, a, b, c, d, in[3] + K3, 3);
- ROUND(H, d, a, b, c, in[7] + K3, 9);
- ROUND(H, c, d, a, b, in[2] + K3, 11);
- ROUND(H, b, c, d, a, in[6] + K3, 15);
- ROUND(H, a, b, c, d, in[1] + K3, 3);
- ROUND(H, d, a, b, c, in[5] + K3, 9);
- ROUND(H, c, d, a, b, in[0] + K3, 11);
- ROUND(H, b, c, d, a, in[4] + K3, 15);
-
- buf[0] += a;
- buf[1] += b;
- buf[2] += c;
- buf[3] += d;
-}
-
-#undef ROUND
-#undef F
-#undef G
-#undef H
-#undef K1
-#undef K2
-#undef K3
-
-/* The old legacy hash */
-static ext2_dirhash_t dx_hack_hash (const char *name, int len)
-{
- __u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
- while (len--) {
- __u32 hash = hash1 + (hash0 ^ (*name++ * 7152373));
-
- if (hash & 0x80000000) hash -= 0x7fffffff;
- hash1 = hash0;
- hash0 = hash;
- }
- return (hash0 << 1);
-}
-
-static void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
-{
- __u32 pad, val;
- int i;
-
- pad = (__u32)len | ((__u32)len << 8);
- pad |= pad << 16;
-
- val = pad;
- if (len > num*4)
- len = num * 4;
- for (i=0; i < len; i++) {
- if ((i % 4) == 0)
- val = pad;
- val = msg[i] + (val << 8);
- if ((i % 4) == 3) {
- *buf++ = val;
- val = pad;
- num--;
- }
- }
- if (--num >= 0)
- *buf++ = val;
- while (--num >= 0)
- *buf++ = pad;
-}
-
-/*
- * Returns the hash of a filename. If len is 0 and name is NULL, then
- * this function can be used to test whether or not a hash version is
- * supported.
- *
- * The seed is an 4 longword (32 bits) "secret" which can be used to
- * uniquify a hash. If the seed is all zero's, then some default seed
- * may be used.
- *
- * A particular hash version specifies whether or not the seed is
- * represented, and whether or not the returned hash is 32 bits or 64
- * bits. 32 bit hashes will return 0 for the minor hash.
- */
-errcode_t ext2fs_dirhash(int version, const char *name, int len,
- const __u32 *seed,
- ext2_dirhash_t *ret_hash,
- ext2_dirhash_t *ret_minor_hash)
-{
- __u32 hash;
- __u32 minor_hash = 0;
- const char *p;
- int i;
- __u32 in[8], buf[4];
-
- /* Initialize the default seed for the hash checksum functions */
- buf[0] = 0x67452301;
- buf[1] = 0xefcdab89;
- buf[2] = 0x98badcfe;
- buf[3] = 0x10325476;
-
- /* Check to see if the seed is all zero's */
- if (seed) {
- for (i=0; i < 4; i++) {
- if (seed[i])
- break;
- }
- if (i < 4)
- memcpy(buf, seed, sizeof(buf));
- }
-
- switch (version) {
- case EXT2_HASH_LEGACY:
- hash = dx_hack_hash(name, len);
- break;
- case EXT2_HASH_HALF_MD4:
- p = name;
- while (len > 0) {
- str2hashbuf(p, len, in, 8);
- halfMD4Transform(buf, in);
- len -= 32;
- p += 32;
- }
- minor_hash = buf[2];
- hash = buf[1];
- break;
- case EXT2_HASH_TEA:
- p = name;
- while (len > 0) {
- str2hashbuf(p, len, in, 4);
- TEA_transform(buf, in);
- len -= 16;
- p += 16;
- }
- hash = buf[0];
- minor_hash = buf[1];
- break;
- default:
- *ret_hash = 0;
- return EXT2_ET_DIRHASH_UNSUPP;
- }
- *ret_hash = hash & ~1;
- if (ret_minor_hash)
- *ret_minor_hash = minor_hash;
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/dupfs.c b/release/src/router/busybox/e2fsprogs/ext2fs/dupfs.c
deleted file mode 100644
index d1879377a0..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/dupfs.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * dupfs.c --- duplicate a ext2 filesystem handle
- *
- * Copyright (C) 1997, 1998, 2001, 2003, 2005 by Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <time.h>
-#include <string.h>
-
-#include "ext2_fs.h"
-#include "ext2fsP.h"
-
-errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest)
-{
- ext2_filsys fs;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(src, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
- if (retval)
- return retval;
-
- *fs = *src;
- fs->device_name = 0;
- fs->super = 0;
- fs->orig_super = 0;
- fs->group_desc = 0;
- fs->inode_map = 0;
- fs->block_map = 0;
- fs->badblocks = 0;
- fs->dblist = 0;
-
- io_channel_bumpcount(fs->io);
- if (fs->icache)
- fs->icache->refcount++;
-
- retval = ext2fs_get_mem(strlen(src->device_name)+1, &fs->device_name);
- if (retval)
- goto errout;
- strcpy(fs->device_name, src->device_name);
-
- retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->super);
- if (retval)
- goto errout;
- memcpy(fs->super, src->super, SUPERBLOCK_SIZE);
-
- retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super);
- if (retval)
- goto errout;
- memcpy(fs->orig_super, src->orig_super, SUPERBLOCK_SIZE);
-
- retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize,
- &fs->group_desc);
- if (retval)
- goto errout;
- memcpy(fs->group_desc, src->group_desc,
- (size_t) fs->desc_blocks * fs->blocksize);
-
- if (src->inode_map) {
- retval = ext2fs_copy_bitmap(src->inode_map, &fs->inode_map);
- if (retval)
- goto errout;
- }
- if (src->block_map) {
- retval = ext2fs_copy_bitmap(src->block_map, &fs->block_map);
- if (retval)
- goto errout;
- }
- if (src->badblocks) {
- retval = ext2fs_badblocks_copy(src->badblocks, &fs->badblocks);
- if (retval)
- goto errout;
- }
- if (src->dblist) {
- retval = ext2fs_copy_dblist(src->dblist, &fs->dblist);
- if (retval)
- goto errout;
- }
- *dest = fs;
- return 0;
-errout:
- ext2fs_free(fs);
- return retval;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/e2image.h b/release/src/router/busybox/e2fsprogs/ext2fs/e2image.h
deleted file mode 100644
index a598d01117..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/e2image.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * e2image.h --- header file describing the ext2 image format
- *
- * Copyright (C) 2000 Theodore Ts'o.
- *
- * Note: this uses the POSIX IO interfaces, unlike most of the other
- * functions in this library. So sue me.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-
-struct ext2_image_hdr {
- __u32 magic_number; /* This must be EXT2_ET_MAGIC_E2IMAGE */
- char magic_descriptor[16]; /* "Ext2 Image 1.0", w/ null padding */
- char fs_hostname[64];/* Hostname of machine of image */
- char fs_netaddr[32]; /* Network address */
- __u32 fs_netaddr_type;/* 0 = IPV4, 1 = IPV6, etc. */
- __u32 fs_device; /* Device number of image */
- char fs_device_name[64]; /* Device name */
- char fs_uuid[16]; /* UUID of filesystem */
- __u32 fs_blocksize; /* Block size of the filesystem */
- __u32 fs_reserved[8];
-
- __u32 image_device; /* Device number of image file */
- __u32 image_inode; /* Inode number of image file */
- __u32 image_time; /* Time of image creation */
- __u32 image_reserved[8];
-
- __u32 offset_super; /* Byte offset of the sb and descriptors */
- __u32 offset_inode; /* Byte offset of the inode table */
- __u32 offset_inodemap; /* Byte offset of the inode bitmaps */
- __u32 offset_blockmap; /* Byte offset of the inode bitmaps */
- __u32 offset_reserved[8];
-};
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/expanddir.c b/release/src/router/busybox/e2fsprogs/ext2fs/expanddir.c
deleted file mode 100644
index 8a29ae5849..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/expanddir.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * expand.c --- expand an ext2fs directory
- *
- * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-struct expand_dir_struct {
- int done;
- int newblocks;
- errcode_t err;
-};
-
-static int expand_dir_proc(ext2_filsys fs,
- blk_t *blocknr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block EXT2FS_ATTR((unused)),
- int ref_offset EXT2FS_ATTR((unused)),
- void *priv_data)
-{
- struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
- blk_t new_blk;
- static blk_t last_blk = 0;
- char *block;
- errcode_t retval;
-
- if (*blocknr) {
- last_blk = *blocknr;
- return 0;
- }
- retval = ext2fs_new_block(fs, last_blk, 0, &new_blk);
- if (retval) {
- es->err = retval;
- return BLOCK_ABORT;
- }
- if (blockcnt > 0) {
- retval = ext2fs_new_dir_block(fs, 0, 0, &block);
- if (retval) {
- es->err = retval;
- return BLOCK_ABORT;
- }
- es->done = 1;
- retval = ext2fs_write_dir_block(fs, new_blk, block);
- } else {
- retval = ext2fs_get_mem(fs->blocksize, &block);
- if (retval) {
- es->err = retval;
- return BLOCK_ABORT;
- }
- memset(block, 0, fs->blocksize);
- retval = io_channel_write_blk(fs->io, new_blk, 1, block);
- }
- if (retval) {
- es->err = retval;
- return BLOCK_ABORT;
- }
- ext2fs_free_mem(&block);
- *blocknr = new_blk;
- ext2fs_block_alloc_stats(fs, new_blk, +1);
- es->newblocks++;
-
- if (es->done)
- return (BLOCK_CHANGED | BLOCK_ABORT);
- else
- return BLOCK_CHANGED;
-}
-
-errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir)
-{
- errcode_t retval;
- struct expand_dir_struct es;
- struct ext2_inode inode;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!(fs->flags & EXT2_FLAG_RW))
- return EXT2_ET_RO_FILSYS;
-
- if (!fs->block_map)
- return EXT2_ET_NO_BLOCK_BITMAP;
-
- retval = ext2fs_check_directory(fs, dir);
- if (retval)
- return retval;
-
- es.done = 0;
- es.err = 0;
- es.newblocks = 0;
-
- retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
- 0, expand_dir_proc, &es);
-
- if (es.err)
- return es.err;
- if (!es.done)
- return EXT2_ET_EXPAND_DIR_ERR;
-
- /*
- * Update the size and block count fields in the inode.
- */
- retval = ext2fs_read_inode(fs, dir, &inode);
- if (retval)
- return retval;
-
- inode.i_size += fs->blocksize;
- inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
-
- retval = ext2fs_write_inode(fs, dir, &inode);
- if (retval)
- return retval;
-
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/ext2_err.h b/release/src/router/busybox/e2fsprogs/ext2fs/ext2_err.h
deleted file mode 100644
index ead352810a..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/ext2_err.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * ext2_err.h:
- * This file is automatically generated; please do not edit it.
- */
-
-#define EXT2_ET_BASE (2133571328L)
-#define EXT2_ET_MAGIC_EXT2FS_FILSYS (2133571329L)
-#define EXT2_ET_MAGIC_BADBLOCKS_LIST (2133571330L)
-#define EXT2_ET_MAGIC_BADBLOCKS_ITERATE (2133571331L)
-#define EXT2_ET_MAGIC_INODE_SCAN (2133571332L)
-#define EXT2_ET_MAGIC_IO_CHANNEL (2133571333L)
-#define EXT2_ET_MAGIC_UNIX_IO_CHANNEL (2133571334L)
-#define EXT2_ET_MAGIC_IO_MANAGER (2133571335L)
-#define EXT2_ET_MAGIC_BLOCK_BITMAP (2133571336L)
-#define EXT2_ET_MAGIC_INODE_BITMAP (2133571337L)
-#define EXT2_ET_MAGIC_GENERIC_BITMAP (2133571338L)
-#define EXT2_ET_MAGIC_TEST_IO_CHANNEL (2133571339L)
-#define EXT2_ET_MAGIC_DBLIST (2133571340L)
-#define EXT2_ET_MAGIC_ICOUNT (2133571341L)
-#define EXT2_ET_MAGIC_PQ_IO_CHANNEL (2133571342L)
-#define EXT2_ET_MAGIC_EXT2_FILE (2133571343L)
-#define EXT2_ET_MAGIC_E2IMAGE (2133571344L)
-#define EXT2_ET_MAGIC_INODE_IO_CHANNEL (2133571345L)
-#define EXT2_ET_MAGIC_RESERVED_9 (2133571346L)
-#define EXT2_ET_BAD_MAGIC (2133571347L)
-#define EXT2_ET_REV_TOO_HIGH (2133571348L)
-#define EXT2_ET_RO_FILSYS (2133571349L)
-#define EXT2_ET_GDESC_READ (2133571350L)
-#define EXT2_ET_GDESC_WRITE (2133571351L)
-#define EXT2_ET_GDESC_BAD_BLOCK_MAP (2133571352L)
-#define EXT2_ET_GDESC_BAD_INODE_MAP (2133571353L)
-#define EXT2_ET_GDESC_BAD_INODE_TABLE (2133571354L)
-#define EXT2_ET_INODE_BITMAP_WRITE (2133571355L)
-#define EXT2_ET_INODE_BITMAP_READ (2133571356L)
-#define EXT2_ET_BLOCK_BITMAP_WRITE (2133571357L)
-#define EXT2_ET_BLOCK_BITMAP_READ (2133571358L)
-#define EXT2_ET_INODE_TABLE_WRITE (2133571359L)
-#define EXT2_ET_INODE_TABLE_READ (2133571360L)
-#define EXT2_ET_NEXT_INODE_READ (2133571361L)
-#define EXT2_ET_UNEXPECTED_BLOCK_SIZE (2133571362L)
-#define EXT2_ET_DIR_CORRUPTED (2133571363L)
-#define EXT2_ET_SHORT_READ (2133571364L)
-#define EXT2_ET_SHORT_WRITE (2133571365L)
-#define EXT2_ET_DIR_NO_SPACE (2133571366L)
-#define EXT2_ET_NO_INODE_BITMAP (2133571367L)
-#define EXT2_ET_NO_BLOCK_BITMAP (2133571368L)
-#define EXT2_ET_BAD_INODE_NUM (2133571369L)
-#define EXT2_ET_BAD_BLOCK_NUM (2133571370L)
-#define EXT2_ET_EXPAND_DIR_ERR (2133571371L)
-#define EXT2_ET_TOOSMALL (2133571372L)
-#define EXT2_ET_BAD_BLOCK_MARK (2133571373L)
-#define EXT2_ET_BAD_BLOCK_UNMARK (2133571374L)
-#define EXT2_ET_BAD_BLOCK_TEST (2133571375L)
-#define EXT2_ET_BAD_INODE_MARK (2133571376L)
-#define EXT2_ET_BAD_INODE_UNMARK (2133571377L)
-#define EXT2_ET_BAD_INODE_TEST (2133571378L)
-#define EXT2_ET_FUDGE_BLOCK_BITMAP_END (2133571379L)
-#define EXT2_ET_FUDGE_INODE_BITMAP_END (2133571380L)
-#define EXT2_ET_BAD_IND_BLOCK (2133571381L)
-#define EXT2_ET_BAD_DIND_BLOCK (2133571382L)
-#define EXT2_ET_BAD_TIND_BLOCK (2133571383L)
-#define EXT2_ET_NEQ_BLOCK_BITMAP (2133571384L)
-#define EXT2_ET_NEQ_INODE_BITMAP (2133571385L)
-#define EXT2_ET_BAD_DEVICE_NAME (2133571386L)
-#define EXT2_ET_MISSING_INODE_TABLE (2133571387L)
-#define EXT2_ET_CORRUPT_SUPERBLOCK (2133571388L)
-#define EXT2_ET_BAD_GENERIC_MARK (2133571389L)
-#define EXT2_ET_BAD_GENERIC_UNMARK (2133571390L)
-#define EXT2_ET_BAD_GENERIC_TEST (2133571391L)
-#define EXT2_ET_SYMLINK_LOOP (2133571392L)
-#define EXT2_ET_CALLBACK_NOTHANDLED (2133571393L)
-#define EXT2_ET_BAD_BLOCK_IN_INODE_TABLE (2133571394L)
-#define EXT2_ET_UNSUPP_FEATURE (2133571395L)
-#define EXT2_ET_RO_UNSUPP_FEATURE (2133571396L)
-#define EXT2_ET_LLSEEK_FAILED (2133571397L)
-#define EXT2_ET_NO_MEMORY (2133571398L)
-#define EXT2_ET_INVALID_ARGUMENT (2133571399L)
-#define EXT2_ET_BLOCK_ALLOC_FAIL (2133571400L)
-#define EXT2_ET_INODE_ALLOC_FAIL (2133571401L)
-#define EXT2_ET_NO_DIRECTORY (2133571402L)
-#define EXT2_ET_TOO_MANY_REFS (2133571403L)
-#define EXT2_ET_FILE_NOT_FOUND (2133571404L)
-#define EXT2_ET_FILE_RO (2133571405L)
-#define EXT2_ET_DB_NOT_FOUND (2133571406L)
-#define EXT2_ET_DIR_EXISTS (2133571407L)
-#define EXT2_ET_UNIMPLEMENTED (2133571408L)
-#define EXT2_ET_CANCEL_REQUESTED (2133571409L)
-#define EXT2_ET_FILE_TOO_BIG (2133571410L)
-#define EXT2_ET_JOURNAL_NOT_BLOCK (2133571411L)
-#define EXT2_ET_NO_JOURNAL_SB (2133571412L)
-#define EXT2_ET_JOURNAL_TOO_SMALL (2133571413L)
-#define EXT2_ET_JOURNAL_UNSUPP_VERSION (2133571414L)
-#define EXT2_ET_LOAD_EXT_JOURNAL (2133571415L)
-#define EXT2_ET_NO_JOURNAL (2133571416L)
-#define EXT2_ET_DIRHASH_UNSUPP (2133571417L)
-#define EXT2_ET_BAD_EA_BLOCK_NUM (2133571418L)
-#define EXT2_ET_TOO_MANY_INODES (2133571419L)
-#define EXT2_ET_NOT_IMAGE_FILE (2133571420L)
-#define EXT2_ET_RES_GDT_BLOCKS (2133571421L)
-#define EXT2_ET_RESIZE_INODE_CORRUPT (2133571422L)
-#define EXT2_ET_SET_BMAP_NO_IND (2133571423L)
-
-#if 0
-extern const struct error_table et_ext2_error_table;
-extern void initialize_ext2_error_table(void);
-
-/* For compatibility with Heimdal */
-extern void initialize_ext2_error_table_r(struct et_list **list);
-
-#define ERROR_TABLE_BASE_ext2 (2133571328L)
-
-/* for compatibility with older versions... */
-#define init_ext2_err_tbl initialize_ext2_error_table
-#define ext2_err_base ERROR_TABLE_BASE_ext2
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/ext2_ext_attr.h b/release/src/router/busybox/e2fsprogs/ext2fs/ext2_ext_attr.h
deleted file mode 100644
index ca309c0d03..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/ext2_ext_attr.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- File: linux/ext2_ext_attr.h
-
- On-disk format of extended attributes for the ext2 filesystem.
-
- (C) 2000 Andreas Gruenbacher, <a.gruenbacher@computer.org>
-*/
-
-/* Magic value in attribute blocks */
-#define EXT2_EXT_ATTR_MAGIC_v1 0xEA010000
-#define EXT2_EXT_ATTR_MAGIC 0xEA020000
-
-/* Maximum number of references to one attribute block */
-#define EXT2_EXT_ATTR_REFCOUNT_MAX 1024
-
-struct ext2_ext_attr_header {
- __u32 h_magic; /* magic number for identification */
- __u32 h_refcount; /* reference count */
- __u32 h_blocks; /* number of disk blocks used */
- __u32 h_hash; /* hash value of all attributes */
- __u32 h_reserved[4]; /* zero right now */
-};
-
-struct ext2_ext_attr_entry {
- __u8 e_name_len; /* length of name */
- __u8 e_name_index; /* attribute name index */
- __u16 e_value_offs; /* offset in disk block of value */
- __u32 e_value_block; /* disk block attribute is stored on (n/i) */
- __u32 e_value_size; /* size of attribute value */
- __u32 e_hash; /* hash value of name and value */
-};
-
-#define EXT2_EXT_ATTR_PAD_BITS 2
-#define EXT2_EXT_ATTR_PAD (1<<EXT2_EXT_ATTR_PAD_BITS)
-#define EXT2_EXT_ATTR_ROUND (EXT2_EXT_ATTR_PAD-1)
-#define EXT2_EXT_ATTR_LEN(name_len) \
- (((name_len) + EXT2_EXT_ATTR_ROUND + \
- sizeof(struct ext2_ext_attr_entry)) & ~EXT2_EXT_ATTR_ROUND)
-#define EXT2_EXT_ATTR_NEXT(entry) \
- ( (struct ext2_ext_attr_entry *)( \
- (char *)(entry) + EXT2_EXT_ATTR_LEN((entry)->e_name_len)) )
-#define EXT2_EXT_ATTR_SIZE(size) \
- (((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND)
-#define EXT2_EXT_IS_LAST_ENTRY(entry) (*((__u32 *)(entry)) == 0UL)
-#define EXT2_EXT_ATTR_NAME(entry) \
- (((char *) (entry)) + sizeof(struct ext2_ext_attr_entry))
-#define EXT2_XATTR_LEN(name_len) \
- (((name_len) + EXT2_EXT_ATTR_ROUND + \
- sizeof(struct ext2_xattr_entry)) & ~EXT2_EXT_ATTR_ROUND)
-#define EXT2_XATTR_SIZE(size) \
- (((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND)
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/ext2_fs.h b/release/src/router/busybox/e2fsprogs/ext2fs/ext2_fs.h
deleted file mode 100644
index 80ea2cbddd..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/ext2_fs.h
+++ /dev/null
@@ -1,569 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * linux/include/linux/ext2_fs.h
- *
- * Copyright (C) 1992, 1993, 1994, 1995
- * Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * from
- *
- * linux/include/linux/minix_fs.h
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- */
-#ifndef LINUX_EXT2_FS_H
-#define LINUX_EXT2_FS_H 1
-
-#include "ext2_types.h" /* Changed from linux/types.h */
-
-/*
- * Special inode numbers
- */
-#define EXT2_BAD_INO 1 /* Bad blocks inode */
-#define EXT2_ROOT_INO 2 /* Root inode */
-#define EXT2_ACL_IDX_INO 3 /* ACL inode */
-#define EXT2_ACL_DATA_INO 4 /* ACL inode */
-#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
-#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
-#define EXT2_RESIZE_INO 7 /* Reserved group descriptors inode */
-#define EXT2_JOURNAL_INO 8 /* Journal inode */
-
-/* First non-reserved inode for old ext2 filesystems */
-#define EXT2_GOOD_OLD_FIRST_INO 11
-
-/*
- * The second extended file system magic number
- */
-#define EXT2_SUPER_MAGIC 0xEF53
-
-/* Assume that user mode programs are passing in an ext2fs superblock, not
- * a kernel struct super_block. This will allow us to call the feature-test
- * macros from user land. */
-#define EXT2_SB(sb) (sb)
-
-/*
- * Maximal count of links to a file
- */
-#define EXT2_LINK_MAX 32000
-
-/*
- * Macro-instructions used to manage several block sizes
- */
-#define EXT2_MIN_BLOCK_LOG_SIZE 10 /* 1024 */
-#define EXT2_MAX_BLOCK_LOG_SIZE 16 /* 65536 */
-#define EXT2_MIN_BLOCK_SIZE (1 << EXT2_MIN_BLOCK_LOG_SIZE)
-#define EXT2_MAX_BLOCK_SIZE (1 << EXT2_MAX_BLOCK_LOG_SIZE)
-#define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
-#define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
-#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
- EXT2_GOOD_OLD_INODE_SIZE : (s)->s_inode_size)
-#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
- EXT2_GOOD_OLD_FIRST_INO : (s)->s_first_ino)
-#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof(__u32))
-
-/*
- * Macro-instructions used to manage fragments
- */
-#define EXT2_MIN_FRAG_SIZE EXT2_MIN_BLOCK_SIZE
-#define EXT2_MAX_FRAG_SIZE EXT2_MAX_BLOCK_SIZE
-#define EXT2_MIN_FRAG_LOG_SIZE EXT2_MIN_BLOCK_LOG_SIZE
-# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size)
-# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
-
-/*
- * ACL structures
- */
-struct ext2_acl_header /* Header of Access Control Lists */
-{
- __u32 aclh_size;
- __u32 aclh_file_count;
- __u32 aclh_acle_count;
- __u32 aclh_first_acle;
-};
-
-struct ext2_acl_entry /* Access Control List Entry */
-{
- __u32 acle_size;
- __u16 acle_perms; /* Access permissions */
- __u16 acle_type; /* Type of entry */
- __u16 acle_tag; /* User or group identity */
- __u16 acle_pad1;
- __u32 acle_next; /* Pointer on next entry for the */
- /* same inode or on next free entry */
-};
-
-/*
- * Structure of a blocks group descriptor
- */
-struct ext2_group_desc
-{
- __u32 bg_block_bitmap; /* Blocks bitmap block */
- __u32 bg_inode_bitmap; /* Inodes bitmap block */
- __u32 bg_inode_table; /* Inodes table block */
- __u16 bg_free_blocks_count; /* Free blocks count */
- __u16 bg_free_inodes_count; /* Free inodes count */
- __u16 bg_used_dirs_count; /* Directories count */
- __u16 bg_pad;
- __u32 bg_reserved[3];
-};
-
-/*
- * Data structures used by the directory indexing feature
- *
- * Note: all of the multibyte integer fields are little endian.
- */
-
-/*
- * Note: dx_root_info is laid out so that if it should somehow get
- * overlaid by a dirent the two low bits of the hash version will be
- * zero. Therefore, the hash version mod 4 should never be 0.
- * Sincerely, the paranoia department.
- */
-struct ext2_dx_root_info {
- __u32 reserved_zero;
- __u8 hash_version; /* 0 now, 1 at release */
- __u8 info_length; /* 8 */
- __u8 indirect_levels;
- __u8 unused_flags;
-};
-
-#define EXT2_HASH_LEGACY 0
-#define EXT2_HASH_HALF_MD4 1
-#define EXT2_HASH_TEA 2
-
-#define EXT2_HASH_FLAG_INCOMPAT 0x1
-
-struct ext2_dx_entry {
- __u32 hash;
- __u32 block;
-};
-
-struct ext2_dx_countlimit {
- __u16 limit;
- __u16 count;
-};
-
-
-/*
- * Macro-instructions used to manage group descriptors
- */
-#define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->s_blocks_per_group)
-#define EXT2_INODES_PER_GROUP(s) (EXT2_SB(s)->s_inodes_per_group)
-#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s))
-/* limits imposed by 16-bit value gd_free_{blocks,inode}_count */
-#define EXT2_MAX_BLOCKS_PER_GROUP(s) ((1 << 16) - 8)
-#define EXT2_MAX_INODES_PER_GROUP(s) ((1 << 16) - EXT2_INODES_PER_BLOCK(s))
-#define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
-
-/*
- * Constants relative to the data blocks
- */
-#define EXT2_NDIR_BLOCKS 12
-#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
-#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
-#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
-#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
-
-/*
- * Inode flags
- */
-#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */
-#define EXT2_UNRM_FL 0x00000002 /* Undelete */
-#define EXT2_COMPR_FL 0x00000004 /* Compress file */
-#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */
-#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */
-#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */
-#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */
-#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */
-/* Reserved for compression usage... */
-#define EXT2_DIRTY_FL 0x00000100
-#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
-#define EXT2_NOCOMPR_FL 0x00000400 /* Access raw compressed data */
-#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */
-/* End compression flags --- maybe not all used */
-#define EXT2_BTREE_FL 0x00001000 /* btree format dir */
-#define EXT2_INDEX_FL 0x00001000 /* hash-indexed directory */
-#define EXT2_IMAGIC_FL 0x00002000
-#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */
-#define EXT2_NOTAIL_FL 0x00008000 /* file tail should not be merged */
-#define EXT2_DIRSYNC_FL 0x00010000 /* Synchronous directory modifications */
-#define EXT2_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
-#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */
-#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
-
-#define EXT2_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */
-#define EXT2_FL_USER_MODIFIABLE 0x000080FF /* User modifiable flags */
-
-/*
- * ioctl commands
- */
-#define EXT2_IOC_GETFLAGS _IOR('f', 1, long)
-#define EXT2_IOC_SETFLAGS _IOW('f', 2, long)
-#define EXT2_IOC_GETVERSION _IOR('v', 1, long)
-#define EXT2_IOC_SETVERSION _IOW('v', 2, long)
-
-/*
- * Structure of an inode on the disk
- */
-struct ext2_inode {
- __u16 i_mode; /* File mode */
- __u16 i_uid; /* Low 16 bits of Owner Uid */
- __u32 i_size; /* Size in bytes */
- __u32 i_atime; /* Access time */
- __u32 i_ctime; /* Creation time */
- __u32 i_mtime; /* Modification time */
- __u32 i_dtime; /* Deletion Time */
- __u16 i_gid; /* Low 16 bits of Group Id */
- __u16 i_links_count; /* Links count */
- __u32 i_blocks; /* Blocks count */
- __u32 i_flags; /* File flags */
- union {
- struct {
- __u32 l_i_reserved1;
- } linux1;
- struct {
- __u32 h_i_translator;
- } hurd1;
- struct {
- __u32 m_i_reserved1;
- } masix1;
- } osd1; /* OS dependent 1 */
- __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
- __u32 i_generation; /* File version (for NFS) */
- __u32 i_file_acl; /* File ACL */
- __u32 i_dir_acl; /* Directory ACL */
- __u32 i_faddr; /* Fragment address */
- union {
- struct {
- __u8 l_i_frag; /* Fragment number */
- __u8 l_i_fsize; /* Fragment size */
- __u16 i_pad1;
- __u16 l_i_uid_high; /* these 2 fields */
- __u16 l_i_gid_high; /* were reserved2[0] */
- __u32 l_i_reserved2;
- } linux2;
- struct {
- __u8 h_i_frag; /* Fragment number */
- __u8 h_i_fsize; /* Fragment size */
- __u16 h_i_mode_high;
- __u16 h_i_uid_high;
- __u16 h_i_gid_high;
- __u32 h_i_author;
- } hurd2;
- struct {
- __u8 m_i_frag; /* Fragment number */
- __u8 m_i_fsize; /* Fragment size */
- __u16 m_pad1;
- __u32 m_i_reserved2[2];
- } masix2;
- } osd2; /* OS dependent 2 */
-};
-
-/*
- * Permanent part of an large inode on the disk
- */
-struct ext2_inode_large {
- __u16 i_mode; /* File mode */
- __u16 i_uid; /* Low 16 bits of Owner Uid */
- __u32 i_size; /* Size in bytes */
- __u32 i_atime; /* Access time */
- __u32 i_ctime; /* Creation time */
- __u32 i_mtime; /* Modification time */
- __u32 i_dtime; /* Deletion Time */
- __u16 i_gid; /* Low 16 bits of Group Id */
- __u16 i_links_count; /* Links count */
- __u32 i_blocks; /* Blocks count */
- __u32 i_flags; /* File flags */
- union {
- struct {
- __u32 l_i_reserved1;
- } linux1;
- struct {
- __u32 h_i_translator;
- } hurd1;
- struct {
- __u32 m_i_reserved1;
- } masix1;
- } osd1; /* OS dependent 1 */
- __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
- __u32 i_generation; /* File version (for NFS) */
- __u32 i_file_acl; /* File ACL */
- __u32 i_dir_acl; /* Directory ACL */
- __u32 i_faddr; /* Fragment address */
- union {
- struct {
- __u8 l_i_frag; /* Fragment number */
- __u8 l_i_fsize; /* Fragment size */
- __u16 i_pad1;
- __u16 l_i_uid_high; /* these 2 fields */
- __u16 l_i_gid_high; /* were reserved2[0] */
- __u32 l_i_reserved2;
- } linux2;
- struct {
- __u8 h_i_frag; /* Fragment number */
- __u8 h_i_fsize; /* Fragment size */
- __u16 h_i_mode_high;
- __u16 h_i_uid_high;
- __u16 h_i_gid_high;
- __u32 h_i_author;
- } hurd2;
- struct {
- __u8 m_i_frag; /* Fragment number */
- __u8 m_i_fsize; /* Fragment size */
- __u16 m_pad1;
- __u32 m_i_reserved2[2];
- } masix2;
- } osd2; /* OS dependent 2 */
- __u16 i_extra_isize;
- __u16 i_pad1;
-};
-
-#define i_size_high i_dir_acl
-
-/*
- * File system states
- */
-#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */
-#define EXT2_ERROR_FS 0x0002 /* Errors detected */
-
-/*
- * Mount flags
- */
-#define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */
-#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */
-#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */
-#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */
-#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */
-#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
-#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
-#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
-
-#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
-#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
-#define test_opt(sb, opt) (EXT2_SB(sb)->s_mount_opt & \
- EXT2_MOUNT_##opt)
-/*
- * Maximal mount counts between two filesystem checks
- */
-#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */
-#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */
-
-/*
- * Behaviour when detecting errors
- */
-#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */
-#define EXT2_ERRORS_RO 2 /* Remount fs read-only */
-#define EXT2_ERRORS_PANIC 3 /* Panic */
-#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE
-
-/*
- * Structure of the super block
- */
-struct ext2_super_block {
- __u32 s_inodes_count; /* Inodes count */
- __u32 s_blocks_count; /* Blocks count */
- __u32 s_r_blocks_count; /* Reserved blocks count */
- __u32 s_free_blocks_count; /* Free blocks count */
- __u32 s_free_inodes_count; /* Free inodes count */
- __u32 s_first_data_block; /* First Data Block */
- __u32 s_log_block_size; /* Block size */
- __s32 s_log_frag_size; /* Fragment size */
- __u32 s_blocks_per_group; /* # Blocks per group */
- __u32 s_frags_per_group; /* # Fragments per group */
- __u32 s_inodes_per_group; /* # Inodes per group */
- __u32 s_mtime; /* Mount time */
- __u32 s_wtime; /* Write time */
- __u16 s_mnt_count; /* Mount count */
- __s16 s_max_mnt_count; /* Maximal mount count */
- __u16 s_magic; /* Magic signature */
- __u16 s_state; /* File system state */
- __u16 s_errors; /* Behaviour when detecting errors */
- __u16 s_minor_rev_level; /* minor revision level */
- __u32 s_lastcheck; /* time of last check */
- __u32 s_checkinterval; /* max. time between checks */
- __u32 s_creator_os; /* OS */
- __u32 s_rev_level; /* Revision level */
- __u16 s_def_resuid; /* Default uid for reserved blocks */
- __u16 s_def_resgid; /* Default gid for reserved blocks */
- /*
- * These fields are for EXT2_DYNAMIC_REV superblocks only.
- *
- * Note: the difference between the compatible feature set and
- * the incompatible feature set is that if there is a bit set
- * in the incompatible feature set that the kernel doesn't
- * know about, it should refuse to mount the filesystem.
- *
- * e2fsck's requirements are more strict; if it doesn't know
- * about a feature in either the compatible or incompatible
- * feature set, it must abort and not try to meddle with
- * things it doesn't understand...
- */
- __u32 s_first_ino; /* First non-reserved inode */
- __u16 s_inode_size; /* size of inode structure */
- __u16 s_block_group_nr; /* block group # of this superblock */
- __u32 s_feature_compat; /* compatible feature set */
- __u32 s_feature_incompat; /* incompatible feature set */
- __u32 s_feature_ro_compat; /* readonly-compatible feature set */
- __u8 s_uuid[16]; /* 128-bit uuid for volume */
- char s_volume_name[16]; /* volume name */
- char s_last_mounted[64]; /* directory where last mounted */
- __u32 s_algorithm_usage_bitmap; /* For compression */
- /*
- * Performance hints. Directory preallocation should only
- * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
- */
- __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
- __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
- __u16 s_reserved_gdt_blocks; /* Per group table for online growth */
- /*
- * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
- */
- __u8 s_journal_uuid[16]; /* uuid of journal superblock */
- __u32 s_journal_inum; /* inode number of journal file */
- __u32 s_journal_dev; /* device number of journal file */
- __u32 s_last_orphan; /* start of list of inodes to delete */
- __u32 s_hash_seed[4]; /* HTREE hash seed */
- __u8 s_def_hash_version; /* Default hash version to use */
- __u8 s_jnl_backup_type; /* Default type of journal backup */
- __u16 s_reserved_word_pad;
- __u32 s_default_mount_opts;
- __u32 s_first_meta_bg; /* First metablock group */
- __u32 s_mkfs_time; /* When the filesystem was created */
- __u32 s_jnl_blocks[17]; /* Backup of the journal inode */
- __u32 s_reserved[172]; /* Padding to the end of the block */
-};
-
-/*
- * Codes for operating systems
- */
-#define EXT2_OS_LINUX 0
-#define EXT2_OS_HURD 1
-#define EXT2_OS_MASIX 2
-#define EXT2_OS_FREEBSD 3
-#define EXT2_OS_LITES 4
-
-/*
- * Revision levels
- */
-#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
-#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
-
-#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV
-#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV
-
-#define EXT2_GOOD_OLD_INODE_SIZE 128
-
-/*
- * Journal inode backup types
- */
-#define EXT3_JNL_BACKUP_BLOCKS 1
-
-/*
- * Feature set definitions
- */
-
-#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \
- ( EXT2_SB(sb)->s_feature_compat & (mask) )
-#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \
- ( EXT2_SB(sb)->s_feature_ro_compat & (mask) )
-#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \
- ( EXT2_SB(sb)->s_feature_incompat & (mask) )
-
-#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001
-#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002
-#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
-#define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008
-#define EXT2_FEATURE_COMPAT_RESIZE_INO 0x0010
-#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020
-
-#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
-#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
-/* #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 not used */
-
-#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
-#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
-#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
-#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
-#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010
-#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040
-
-
-#define EXT2_FEATURE_COMPAT_SUPP 0
-#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE)
-#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
- EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
-
-/*
- * Default values for user and/or group using reserved blocks
- */
-#define EXT2_DEF_RESUID 0
-#define EXT2_DEF_RESGID 0
-
-/*
- * Default mount options
- */
-#define EXT2_DEFM_DEBUG 0x0001
-#define EXT2_DEFM_BSDGROUPS 0x0002
-#define EXT2_DEFM_XATTR_USER 0x0004
-#define EXT2_DEFM_ACL 0x0008
-#define EXT2_DEFM_UID16 0x0010
-#define EXT3_DEFM_JMODE 0x0060
-#define EXT3_DEFM_JMODE_DATA 0x0020
-#define EXT3_DEFM_JMODE_ORDERED 0x0040
-#define EXT3_DEFM_JMODE_WBACK 0x0060
-
-/*
- * Structure of a directory entry
- */
-#define EXT2_NAME_LEN 255
-
-struct ext2_dir_entry {
- __u32 inode; /* Inode number */
- __u16 rec_len; /* Directory entry length */
- __u16 name_len; /* Name length */
- char name[EXT2_NAME_LEN]; /* File name */
-};
-
-/*
- * The new version of the directory entry. Since EXT2 structures are
- * stored in intel byte order, and the name_len field could never be
- * bigger than 255 chars, it's safe to reclaim the extra byte for the
- * file_type field.
- */
-struct ext2_dir_entry_2 {
- __u32 inode; /* Inode number */
- __u16 rec_len; /* Directory entry length */
- __u8 name_len; /* Name length */
- __u8 file_type;
- char name[EXT2_NAME_LEN]; /* File name */
-};
-
-/*
- * Ext2 directory file types. Only the low 3 bits are used. The
- * other bits are reserved for now.
- */
-#define EXT2_FT_UNKNOWN 0
-#define EXT2_FT_REG_FILE 1
-#define EXT2_FT_DIR 2
-#define EXT2_FT_CHRDEV 3
-#define EXT2_FT_BLKDEV 4
-#define EXT2_FT_FIFO 5
-#define EXT2_FT_SOCK 6
-#define EXT2_FT_SYMLINK 7
-
-#define EXT2_FT_MAX 8
-
-/*
- * EXT2_DIR_PAD defines the directory entries boundaries
- *
- * NOTE: It must be a multiple of 4
- */
-#define EXT2_DIR_PAD 4
-#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
-#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
- ~EXT2_DIR_ROUND)
-
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/ext2_io.h b/release/src/router/busybox/e2fsprogs/ext2fs/ext2_io.h
deleted file mode 100644
index 1900a76392..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/ext2_io.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * io.h --- the I/O manager abstraction
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-#ifndef EXT2FS_EXT2_IO_H
-#define EXT2FS_EXT2_IO_H 1
-
-/*
- * ext2_loff_t is defined here since unix_io.c needs it.
- */
-#if defined(__GNUC__) || defined(HAS_LONG_LONG)
-typedef long long ext2_loff_t;
-#else
-typedef long ext2_loff_t;
-#endif
-
-/* llseek.c */
-/* ext2_loff_t ext2fs_llseek (int, ext2_loff_t, int); */
-#ifdef CONFIG_LFS
-# define ext2fs_llseek lseek64
-#else
-# define ext2fs_llseek lseek
-#endif
-
-typedef struct struct_io_manager *io_manager;
-typedef struct struct_io_channel *io_channel;
-
-#define CHANNEL_FLAGS_WRITETHROUGH 0x01
-
-struct struct_io_channel {
- errcode_t magic;
- io_manager manager;
- char *name;
- int block_size;
- errcode_t (*read_error)(io_channel channel,
- unsigned long block,
- int count,
- void *data,
- size_t size,
- int actual_bytes_read,
- errcode_t error);
- errcode_t (*write_error)(io_channel channel,
- unsigned long block,
- int count,
- const void *data,
- size_t size,
- int actual_bytes_written,
- errcode_t error);
- int refcount;
- int flags;
- int reserved[14];
- void *private_data;
- void *app_data;
-};
-
-struct struct_io_manager {
- errcode_t magic;
- const char *name;
- errcode_t (*open)(const char *name, int flags, io_channel *channel);
- errcode_t (*close)(io_channel channel);
- errcode_t (*set_blksize)(io_channel channel, int blksize);
- errcode_t (*read_blk)(io_channel channel, unsigned long block,
- int count, void *data);
- errcode_t (*write_blk)(io_channel channel, unsigned long block,
- int count, const void *data);
- errcode_t (*flush)(io_channel channel);
- errcode_t (*write_byte)(io_channel channel, unsigned long offset,
- int count, const void *data);
- errcode_t (*set_option)(io_channel channel, const char *option,
- const char *arg);
- int reserved[14];
-};
-
-#define IO_FLAG_RW 1
-
-/*
- * Convenience functions....
- */
-#define io_channel_close(c) ((c)->manager->close((c)))
-#define io_channel_set_blksize(c,s) ((c)->manager->set_blksize((c),s))
-#define io_channel_read_blk(c,b,n,d) ((c)->manager->read_blk((c),b,n,d))
-#define io_channel_write_blk(c,b,n,d) ((c)->manager->write_blk((c),b,n,d))
-#define io_channel_flush(c) ((c)->manager->flush((c)))
-#define io_channel_bumpcount(c) ((c)->refcount++)
-
-/* io_manager.c */
-extern errcode_t io_channel_set_options(io_channel channel,
- const char *options);
-extern errcode_t io_channel_write_byte(io_channel channel,
- unsigned long offset,
- int count, const void *data);
-
-/* unix_io.c */
-extern io_manager unix_io_manager;
-
-/* test_io.c */
-extern io_manager test_io_manager, test_io_backing_manager;
-extern void (*test_io_cb_read_blk)
- (unsigned long block, int count, errcode_t err);
-extern void (*test_io_cb_write_blk)
- (unsigned long block, int count, errcode_t err);
-extern void (*test_io_cb_set_blksize)
- (int blksize, errcode_t err);
-
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/ext2_types.h b/release/src/router/busybox/e2fsprogs/ext2fs/ext2_types.h
deleted file mode 100644
index 2c1196b8b7..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/ext2_types.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* vi: set sw=4 ts=4: */
-#include <linux/types.h>
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/ext2fs.h b/release/src/router/busybox/e2fsprogs/ext2fs/ext2fs.h
deleted file mode 100644
index ffd096f416..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/ext2fs.h
+++ /dev/null
@@ -1,926 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * ext2fs.h --- ext2fs
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-#ifndef EXT2FS_EXT2FS_H
-#define EXT2FS_EXT2FS_H 1
-
-
-#ifdef __GNUC__
-# define EXT2FS_ATTR(x) __attribute__(x)
-#else
-# define EXT2FS_ATTR(x)
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Where the master copy of the superblock is located, and how big
- * superblocks are supposed to be. We define SUPERBLOCK_SIZE because
- * the size of the superblock structure is not necessarily trustworthy
- * (some versions have the padding set up so that the superblock is
- * 1032 bytes long).
- */
-#define SUPERBLOCK_OFFSET 1024
-#define SUPERBLOCK_SIZE 1024
-
-/*
- * The last ext2fs revision level that this version of the library is
- * able to support.
- */
-#define EXT2_LIB_CURRENT_REV EXT2_DYNAMIC_REV
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "ext2_types.h"
-#include "ext2_fs.h"
-
-typedef __u32 ext2_ino_t;
-typedef __u32 blk_t;
-typedef __u32 dgrp_t;
-typedef __u32 ext2_off_t;
-typedef __s64 e2_blkcnt_t;
-typedef __u32 ext2_dirhash_t;
-
-#include "ext2_io.h"
-#include "ext2_err.h"
-
-typedef struct struct_ext2_filsys *ext2_filsys;
-
-struct ext2fs_struct_generic_bitmap {
- errcode_t magic;
- ext2_filsys fs;
- __u32 start, end;
- __u32 real_end;
- char * description;
- char * bitmap;
- errcode_t base_error_code;
- __u32 reserved[7];
-};
-
-#define EXT2FS_MARK_ERROR 0
-#define EXT2FS_UNMARK_ERROR 1
-#define EXT2FS_TEST_ERROR 2
-
-typedef struct ext2fs_struct_generic_bitmap *ext2fs_generic_bitmap;
-typedef struct ext2fs_struct_generic_bitmap *ext2fs_inode_bitmap;
-typedef struct ext2fs_struct_generic_bitmap *ext2fs_block_bitmap;
-
-#define EXT2_FIRST_INODE(s) EXT2_FIRST_INO(s)
-
-/*
- * badblocks list definitions
- */
-
-typedef struct ext2_struct_u32_list *ext2_badblocks_list;
-typedef struct ext2_struct_u32_iterate *ext2_badblocks_iterate;
-
-typedef struct ext2_struct_u32_list *ext2_u32_list;
-typedef struct ext2_struct_u32_iterate *ext2_u32_iterate;
-
-/* old */
-typedef struct ext2_struct_u32_list *badblocks_list;
-typedef struct ext2_struct_u32_iterate *badblocks_iterate;
-
-#define BADBLOCKS_FLAG_DIRTY 1
-
-/*
- * ext2_dblist structure and abstractions (see dblist.c)
- */
-struct ext2_db_entry {
- ext2_ino_t ino;
- blk_t blk;
- int blockcnt;
-};
-
-typedef struct ext2_struct_dblist *ext2_dblist;
-
-#define DBLIST_ABORT 1
-
-/*
- * ext2_fileio definitions
- */
-
-#define EXT2_FILE_WRITE 0x0001
-#define EXT2_FILE_CREATE 0x0002
-
-#define EXT2_FILE_MASK 0x00FF
-
-#define EXT2_FILE_BUF_DIRTY 0x4000
-#define EXT2_FILE_BUF_VALID 0x2000
-
-typedef struct ext2_file *ext2_file_t;
-
-#define EXT2_SEEK_SET 0
-#define EXT2_SEEK_CUR 1
-#define EXT2_SEEK_END 2
-
-/*
- * Flags for the ext2_filsys structure and for ext2fs_open()
- */
-#define EXT2_FLAG_RW 0x01
-#define EXT2_FLAG_CHANGED 0x02
-#define EXT2_FLAG_DIRTY 0x04
-#define EXT2_FLAG_VALID 0x08
-#define EXT2_FLAG_IB_DIRTY 0x10
-#define EXT2_FLAG_BB_DIRTY 0x20
-#define EXT2_FLAG_SWAP_BYTES 0x40
-#define EXT2_FLAG_SWAP_BYTES_READ 0x80
-#define EXT2_FLAG_SWAP_BYTES_WRITE 0x100
-#define EXT2_FLAG_MASTER_SB_ONLY 0x200
-#define EXT2_FLAG_FORCE 0x400
-#define EXT2_FLAG_SUPER_ONLY 0x800
-#define EXT2_FLAG_JOURNAL_DEV_OK 0x1000
-#define EXT2_FLAG_IMAGE_FILE 0x2000
-
-/*
- * Special flag in the ext2 inode i_flag field that means that this is
- * a new inode. (So that ext2_write_inode() can clear extra fields.)
- */
-#define EXT2_NEW_INODE_FL 0x80000000
-
-/*
- * Flags for mkjournal
- *
- * EXT2_MKJOURNAL_V1_SUPER Make a (deprecated) V1 journal superblock
- */
-#define EXT2_MKJOURNAL_V1_SUPER 0x0000001
-
-struct struct_ext2_filsys {
- errcode_t magic;
- io_channel io;
- int flags;
- char * device_name;
- struct ext2_super_block * super;
- unsigned int blocksize;
- int fragsize;
- dgrp_t group_desc_count;
- unsigned long desc_blocks;
- struct ext2_group_desc * group_desc;
- int inode_blocks_per_group;
- ext2fs_inode_bitmap inode_map;
- ext2fs_block_bitmap block_map;
- errcode_t (*get_blocks)(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks);
- errcode_t (*check_directory)(ext2_filsys fs, ext2_ino_t ino);
- errcode_t (*write_bitmaps)(ext2_filsys fs);
- errcode_t (*read_inode)(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode);
- errcode_t (*write_inode)(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode);
- ext2_badblocks_list badblocks;
- ext2_dblist dblist;
- __u32 stride; /* for mke2fs */
- struct ext2_super_block * orig_super;
- struct ext2_image_hdr * image_header;
- __u32 umask;
- /*
- * Reserved for future expansion
- */
- __u32 reserved[8];
-
- /*
- * Reserved for the use of the calling application.
- */
- void * priv_data;
-
- /*
- * Inode cache
- */
- struct ext2_inode_cache *icache;
- io_channel image_io;
-};
-
-#include "bitops.h"
-
-/*
- * Return flags for the block iterator functions
- */
-#define BLOCK_CHANGED 1
-#define BLOCK_ABORT 2
-#define BLOCK_ERROR 4
-
-/*
- * Block interate flags
- *
- * BLOCK_FLAG_APPEND, or BLOCK_FLAG_HOLE, indicates that the interator
- * function should be called on blocks where the block number is zero.
- * This is used by ext2fs_expand_dir() to be able to add a new block
- * to an inode. It can also be used for programs that want to be able
- * to deal with files that contain "holes".
- *
- * BLOCK_FLAG_TRAVERSE indicates that the iterator function for the
- * indirect, doubly indirect, etc. blocks should be called after all
- * of the blocks containined in the indirect blocks are processed.
- * This is useful if you are going to be deallocating blocks from an
- * inode.
- *
- * BLOCK_FLAG_DATA_ONLY indicates that the iterator function should be
- * called for data blocks only.
- *
- * BLOCK_FLAG_NO_LARGE is for internal use only. It informs
- * ext2fs_block_iterate2 that large files won't be accepted.
- */
-#define BLOCK_FLAG_APPEND 1
-#define BLOCK_FLAG_HOLE 1
-#define BLOCK_FLAG_DEPTH_TRAVERSE 2
-#define BLOCK_FLAG_DATA_ONLY 4
-
-#define BLOCK_FLAG_NO_LARGE 0x1000
-
-/*
- * Magic "block count" return values for the block iterator function.
- */
-#define BLOCK_COUNT_IND (-1)
-#define BLOCK_COUNT_DIND (-2)
-#define BLOCK_COUNT_TIND (-3)
-#define BLOCK_COUNT_TRANSLATOR (-4)
-
-#if 0
-/*
- * Flags for ext2fs_move_blocks
- */
-#define EXT2_BMOVE_GET_DBLIST 0x0001
-#define EXT2_BMOVE_DEBUG 0x0002
-#endif
-
-/*
- * Flags for directory block reading and writing functions
- */
-#define EXT2_DIRBLOCK_V2_STRUCT 0x0001
-
-/*
- * Return flags for the directory iterator functions
- */
-#define DIRENT_CHANGED 1
-#define DIRENT_ABORT 2
-#define DIRENT_ERROR 3
-
-/*
- * Directory iterator flags
- */
-
-#define DIRENT_FLAG_INCLUDE_EMPTY 1
-#define DIRENT_FLAG_INCLUDE_REMOVED 2
-
-#define DIRENT_DOT_FILE 1
-#define DIRENT_DOT_DOT_FILE 2
-#define DIRENT_OTHER_FILE 3
-#define DIRENT_DELETED_FILE 4
-
-/*
- * Inode scan definitions
- */
-typedef struct ext2_struct_inode_scan *ext2_inode_scan;
-
-/*
- * ext2fs_scan flags
- */
-#define EXT2_SF_CHK_BADBLOCKS 0x0001
-#define EXT2_SF_BAD_INODE_BLK 0x0002
-#define EXT2_SF_BAD_EXTRA_BYTES 0x0004
-#define EXT2_SF_SKIP_MISSING_ITABLE 0x0008
-
-/*
- * ext2fs_check_if_mounted flags
- */
-#define EXT2_MF_MOUNTED 1
-#define EXT2_MF_ISROOT 2
-#define EXT2_MF_READONLY 4
-#define EXT2_MF_SWAP 8
-#define EXT2_MF_BUSY 16
-
-/*
- * Ext2/linux mode flags. We define them here so that we don't need
- * to depend on the OS's sys/stat.h, since we may be compiling on a
- * non-Linux system.
- */
-#define LINUX_S_IFMT 00170000
-#define LINUX_S_IFSOCK 0140000
-#define LINUX_S_IFLNK 0120000
-#define LINUX_S_IFREG 0100000
-#define LINUX_S_IFBLK 0060000
-#define LINUX_S_IFDIR 0040000
-#define LINUX_S_IFCHR 0020000
-#define LINUX_S_IFIFO 0010000
-#define LINUX_S_ISUID 0004000
-#define LINUX_S_ISGID 0002000
-#define LINUX_S_ISVTX 0001000
-
-#define LINUX_S_IRWXU 00700
-#define LINUX_S_IRUSR 00400
-#define LINUX_S_IWUSR 00200
-#define LINUX_S_IXUSR 00100
-
-#define LINUX_S_IRWXG 00070
-#define LINUX_S_IRGRP 00040
-#define LINUX_S_IWGRP 00020
-#define LINUX_S_IXGRP 00010
-
-#define LINUX_S_IRWXO 00007
-#define LINUX_S_IROTH 00004
-#define LINUX_S_IWOTH 00002
-#define LINUX_S_IXOTH 00001
-
-#define LINUX_S_ISLNK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFLNK)
-#define LINUX_S_ISREG(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFREG)
-#define LINUX_S_ISDIR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFDIR)
-#define LINUX_S_ISCHR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFCHR)
-#define LINUX_S_ISBLK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFBLK)
-#define LINUX_S_ISFIFO(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFIFO)
-#define LINUX_S_ISSOCK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFSOCK)
-
-/*
- * ext2 size of an inode
- */
-#define EXT2_I_SIZE(i) ((i)->i_size | ((__u64) (i)->i_size_high << 32))
-
-/*
- * ext2_icount_t abstraction
- */
-#define EXT2_ICOUNT_OPT_INCREMENT 0x01
-
-typedef struct ext2_icount *ext2_icount_t;
-
-/*
- * Flags for ext2fs_bmap
- */
-#define BMAP_ALLOC 0x0001
-#define BMAP_SET 0x0002
-
-/*
- * Flags for imager.c functions
- */
-#define IMAGER_FLAG_INODEMAP 1
-#define IMAGER_FLAG_SPARSEWRITE 2
-
-/*
- * For checking structure magic numbers...
- */
-
-#define EXT2_CHECK_MAGIC(struct, code) \
- if ((struct)->magic != (code)) return (code)
-
-
-/*
- * For ext2 compression support
- */
-#define EXT2FS_COMPRESSED_BLKADDR ((blk_t) 0xffffffff)
-#define HOLE_BLKADDR(_b) ((_b) == 0 || (_b) == EXT2FS_COMPRESSED_BLKADDR)
-
-/*
- * Features supported by this version of the library
- */
-#define EXT2_LIB_FEATURE_COMPAT_SUPP (EXT2_FEATURE_COMPAT_DIR_PREALLOC|\
- EXT2_FEATURE_COMPAT_IMAGIC_INODES|\
- EXT3_FEATURE_COMPAT_HAS_JOURNAL|\
- EXT2_FEATURE_COMPAT_RESIZE_INO|\
- EXT2_FEATURE_COMPAT_DIR_INDEX|\
- EXT2_FEATURE_COMPAT_EXT_ATTR)
-
-/* This #ifdef is temporary until compression is fully supported */
-#ifdef ENABLE_COMPRESSION
-#ifndef I_KNOW_THAT_COMPRESSION_IS_EXPERIMENTAL
-/* If the below warning bugs you, then have
- `CPPFLAGS=-DI_KNOW_THAT_COMPRESSION_IS_EXPERIMENTAL' in your
- environment at configure time. */
- #warning "Compression support is experimental"
-#endif
-#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\
- EXT2_FEATURE_INCOMPAT_COMPRESSION|\
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
- EXT2_FEATURE_INCOMPAT_META_BG|\
- EXT3_FEATURE_INCOMPAT_RECOVER)
-#else
-#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
- EXT2_FEATURE_INCOMPAT_META_BG|\
- EXT3_FEATURE_INCOMPAT_RECOVER)
-#endif
-#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE)
-/*
- * function prototypes
- */
-
-/* alloc.c */
-extern errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir, int mode,
- ext2fs_inode_bitmap map, ext2_ino_t *ret);
-extern errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
- ext2fs_block_bitmap map, blk_t *ret);
-extern errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start,
- blk_t finish, int num,
- ext2fs_block_bitmap map,
- blk_t *ret);
-extern errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
- char *block_buf, blk_t *ret);
-
-/* alloc_sb.c */
-extern int ext2fs_reserve_super_and_bgd(ext2_filsys fs,
- dgrp_t group,
- ext2fs_block_bitmap bmap);
-
-/* alloc_stats.c */
-void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse);
-void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino,
- int inuse, int isdir);
-void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse);
-
-/* alloc_tables.c */
-extern errcode_t ext2fs_allocate_tables(ext2_filsys fs);
-extern errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
- ext2fs_block_bitmap bmap);
-
-/* badblocks.c */
-extern errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size);
-extern errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk);
-extern int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk);
-extern int ext2fs_u32_list_test(ext2_u32_list bb, blk_t blk);
-extern errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb,
- ext2_u32_iterate *ret);
-extern int ext2fs_u32_list_iterate(ext2_u32_iterate iter, blk_t *blk);
-extern void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter);
-extern errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest);
-extern int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2);
-
-extern errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret,
- int size);
-extern errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb,
- blk_t blk);
-extern int ext2fs_badblocks_list_test(ext2_badblocks_list bb,
- blk_t blk);
-extern int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk);
-extern void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk);
-extern errcode_t
- ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
- ext2_badblocks_iterate *ret);
-extern int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter,
- blk_t *blk);
-extern void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter);
-extern errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
- ext2_badblocks_list *dest);
-extern int ext2fs_badblocks_equal(ext2_badblocks_list bb1,
- ext2_badblocks_list bb2);
-extern int ext2fs_u32_list_count(ext2_u32_list bb);
-
-/* bb_compat */
-extern errcode_t badblocks_list_create(badblocks_list *ret, int size);
-extern errcode_t badblocks_list_add(badblocks_list bb, blk_t blk);
-extern int badblocks_list_test(badblocks_list bb, blk_t blk);
-extern errcode_t badblocks_list_iterate_begin(badblocks_list bb,
- badblocks_iterate *ret);
-extern int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk);
-extern void badblocks_list_iterate_end(badblocks_iterate iter);
-extern void badblocks_list_free(badblocks_list bb);
-
-/* bb_inode.c */
-extern errcode_t ext2fs_update_bb_inode(ext2_filsys fs,
- ext2_badblocks_list bb_list);
-
-/* bitmaps.c */
-extern errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs);
-extern errcode_t ext2fs_write_block_bitmap (ext2_filsys fs);
-extern errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs);
-extern errcode_t ext2fs_read_block_bitmap(ext2_filsys fs);
-extern errcode_t ext2fs_allocate_generic_bitmap(__u32 start,
- __u32 end,
- __u32 real_end,
- const char *descr,
- ext2fs_generic_bitmap *ret);
-extern errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
- const char *descr,
- ext2fs_block_bitmap *ret);
-extern errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs,
- const char *descr,
- ext2fs_inode_bitmap *ret);
-extern errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap,
- ext2_ino_t end, ext2_ino_t *oend);
-extern errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap,
- blk_t end, blk_t *oend);
-extern void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap);
-extern void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap);
-extern errcode_t ext2fs_read_bitmaps(ext2_filsys fs);
-extern errcode_t ext2fs_write_bitmaps(ext2_filsys fs);
-
-/* block.c */
-extern errcode_t ext2fs_block_iterate(ext2_filsys fs,
- ext2_ino_t ino,
- int flags,
- char *block_buf,
- int (*func)(ext2_filsys fs,
- blk_t *blocknr,
- int blockcnt,
- void *priv_data),
- void *priv_data);
-errcode_t ext2fs_block_iterate2(ext2_filsys fs,
- ext2_ino_t ino,
- int flags,
- char *block_buf,
- int (*func)(ext2_filsys fs,
- blk_t *blocknr,
- e2_blkcnt_t blockcnt,
- blk_t ref_blk,
- int ref_offset,
- void *priv_data),
- void *priv_data);
-
-/* bmap.c */
-extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode,
- char *block_buf, int bmap_flags,
- blk_t block, blk_t *phys_blk);
-
-
-#if 0
-/* bmove.c */
-extern errcode_t ext2fs_move_blocks(ext2_filsys fs,
- ext2fs_block_bitmap reserve,
- ext2fs_block_bitmap alloc_map,
- int flags);
-#endif
-
-/* check_desc.c */
-extern errcode_t ext2fs_check_desc(ext2_filsys fs);
-
-/* closefs.c */
-extern errcode_t ext2fs_close(ext2_filsys fs);
-extern errcode_t ext2fs_flush(ext2_filsys fs);
-extern int ext2fs_bg_has_super(ext2_filsys fs, int group_block);
-extern int ext2fs_super_and_bgd_loc(ext2_filsys fs,
- dgrp_t group,
- blk_t *ret_super_blk,
- blk_t *ret_old_desc_blk,
- blk_t *ret_new_desc_blk,
- int *ret_meta_bg);
-extern void ext2fs_update_dynamic_rev(ext2_filsys fs);
-
-/* cmp_bitmaps.c */
-extern errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
- ext2fs_block_bitmap bm2);
-extern errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
- ext2fs_inode_bitmap bm2);
-
-/* dblist.c */
-
-extern errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs);
-extern errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist);
-extern errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino,
- blk_t blk, int blockcnt);
-extern void ext2fs_dblist_sort(ext2_dblist dblist,
- int (*sortfunc)(const void *,
- const void *));
-extern errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
- int (*func)(ext2_filsys fs, struct ext2_db_entry *db_info,
- void *priv_data),
- void *priv_data);
-extern errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino,
- blk_t blk, int blockcnt);
-extern errcode_t ext2fs_copy_dblist(ext2_dblist src,
- ext2_dblist *dest);
-extern int ext2fs_dblist_count(ext2_dblist dblist);
-
-/* dblist_dir.c */
-extern errcode_t
- ext2fs_dblist_dir_iterate(ext2_dblist dblist,
- int flags,
- char *block_buf,
- int (*func)(ext2_ino_t dir,
- int entry,
- struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *priv_data),
- void *priv_data);
-
-/* dirblock.c */
-extern errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
- void *buf);
-extern errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
- void *buf, int flags);
-extern errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
- void *buf);
-extern errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
- void *buf, int flags);
-
-/* dirhash.c */
-extern errcode_t ext2fs_dirhash(int version, const char *name, int len,
- const __u32 *seed,
- ext2_dirhash_t *ret_hash,
- ext2_dirhash_t *ret_minor_hash);
-
-
-/* dir_iterate.c */
-extern errcode_t ext2fs_dir_iterate(ext2_filsys fs,
- ext2_ino_t dir,
- int flags,
- char *block_buf,
- int (*func)(struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *priv_data),
- void *priv_data);
-extern errcode_t ext2fs_dir_iterate2(ext2_filsys fs,
- ext2_ino_t dir,
- int flags,
- char *block_buf,
- int (*func)(ext2_ino_t dir,
- int entry,
- struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *priv_data),
- void *priv_data);
-
-/* dupfs.c */
-extern errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest);
-
-/* expanddir.c */
-extern errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir);
-
-/* ext_attr.c */
-extern errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf);
-extern errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block,
- void *buf);
-extern errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk,
- char *block_buf,
- int adjust, __u32 *newcount);
-
-/* fileio.c */
-extern errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode,
- int flags, ext2_file_t *ret);
-extern errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino,
- int flags, ext2_file_t *ret);
-extern ext2_filsys ext2fs_file_get_fs(ext2_file_t file);
-extern errcode_t ext2fs_file_close(ext2_file_t file);
-extern errcode_t ext2fs_file_flush(ext2_file_t file);
-extern errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
- unsigned int wanted, unsigned int *got);
-extern errcode_t ext2fs_file_write(ext2_file_t file, const void *buf,
- unsigned int nbytes, unsigned int *written);
-extern errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset,
- int whence, __u64 *ret_pos);
-extern errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
- int whence, ext2_off_t *ret_pos);
-errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size);
-extern ext2_off_t ext2fs_file_get_size(ext2_file_t file);
-extern errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size);
-
-/* finddev.c */
-extern char *ext2fs_find_block_device(dev_t device);
-
-/* flushb.c */
-extern errcode_t ext2fs_sync_device(int fd, int flushb);
-
-/* freefs.c */
-extern void ext2fs_free(ext2_filsys fs);
-extern void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap);
-extern void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap);
-extern void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap);
-extern void ext2fs_free_dblist(ext2_dblist dblist);
-extern void ext2fs_badblocks_list_free(ext2_badblocks_list bb);
-extern void ext2fs_u32_list_free(ext2_u32_list bb);
-
-/* getsize.c */
-extern errcode_t ext2fs_get_device_size(const char *file, int blocksize,
- blk_t *retblocks);
-
-/* getsectsize.c */
-errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize);
-
-/* imager.c */
-extern errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags);
-extern errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd, int flags);
-extern errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, int flags);
-extern errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd, int flags);
-extern errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags);
-extern errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags);
-
-/* ind_block.c */
-errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf);
-errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf);
-
-/* initialize.c */
-extern errcode_t ext2fs_initialize(const char *name, int flags,
- struct ext2_super_block *param,
- io_manager manager, ext2_filsys *ret_fs);
-
-/* icount.c */
-extern void ext2fs_free_icount(ext2_icount_t icount);
-extern errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags,
- unsigned int size,
- ext2_icount_t hint, ext2_icount_t *ret);
-extern errcode_t ext2fs_create_icount(ext2_filsys fs, int flags,
- unsigned int size,
- ext2_icount_t *ret);
-extern errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino,
- __u16 *ret);
-extern errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino,
- __u16 *ret);
-extern errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
- __u16 *ret);
-extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
- __u16 count);
-extern ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount);
-errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *);
-
-/* inode.c */
-extern errcode_t ext2fs_flush_icache(ext2_filsys fs);
-extern errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan,
- ext2_ino_t *ino,
- struct ext2_inode *inode,
- int bufsize);
-extern errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
- ext2_inode_scan *ret_scan);
-extern void ext2fs_close_inode_scan(ext2_inode_scan scan);
-extern errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino,
- struct ext2_inode *inode);
-extern errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,
- int group);
-extern void ext2fs_set_inode_callback
- (ext2_inode_scan scan,
- errcode_t (*done_group)(ext2_filsys fs,
- dgrp_t group,
- void * priv_data),
- void *done_group_data);
-extern int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags,
- int clear_flags);
-extern errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode * inode,
- int bufsize);
-extern errcode_t ext2fs_read_inode (ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode * inode);
-extern errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode * inode,
- int bufsize);
-extern errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode * inode);
-extern errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode * inode);
-extern errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks);
-extern errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino);
-
-/* inode_io.c */
-extern io_manager inode_io_manager;
-extern errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino,
- char **name);
-extern errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode,
- char **name);
-
-/* ismounted.c */
-extern errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags);
-extern errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags,
- char *mtpt, int mtlen);
-
-/* namei.c */
-extern errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name,
- int namelen, char *buf, ext2_ino_t *inode);
-extern errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
- const char *name, ext2_ino_t *inode);
-errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
- const char *name, ext2_ino_t *inode);
-extern errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
- ext2_ino_t inode, ext2_ino_t *res_inode);
-
-/* native.c */
-int ext2fs_native_flag(void);
-
-/* newdir.c */
-extern errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino,
- ext2_ino_t parent_ino, char **block);
-
-/* mkdir.c */
-extern errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
- const char *name);
-
-/* mkjournal.c */
-extern errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
- __u32 size, int flags,
- char **ret_jsb);
-extern errcode_t ext2fs_add_journal_device(ext2_filsys fs,
- ext2_filsys journal_dev);
-extern errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size,
- int flags);
-
-/* openfs.c */
-extern errcode_t ext2fs_open(const char *name, int flags, int superblock,
- unsigned int block_size, io_manager manager,
- ext2_filsys *ret_fs);
-extern errcode_t ext2fs_open2(const char *name, const char *io_options,
- int flags, int superblock,
- unsigned int block_size, io_manager manager,
- ext2_filsys *ret_fs);
-extern blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block,
- dgrp_t i);
-errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io);
-errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io);
-errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io);
-
-/* get_pathname.c */
-extern errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino,
- char **name);
-
-/* link.c */
-errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name,
- ext2_ino_t ino, int flags);
-errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir, const char *name,
- ext2_ino_t ino, int flags);
-
-/* read_bb.c */
-extern errcode_t ext2fs_read_bb_inode(ext2_filsys fs,
- ext2_badblocks_list *bb_list);
-
-/* read_bb_file.c */
-extern errcode_t ext2fs_read_bb_FILE2(ext2_filsys fs, FILE *f,
- ext2_badblocks_list *bb_list,
- void *priv_data,
- void (*invalid)(ext2_filsys fs,
- blk_t blk,
- char *badstr,
- void *priv_data));
-extern errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f,
- ext2_badblocks_list *bb_list,
- void (*invalid)(ext2_filsys fs,
- blk_t blk));
-
-/* res_gdt.c */
-extern errcode_t ext2fs_create_resize_inode(ext2_filsys fs);
-
-/* rs_bitmap.c */
-extern errcode_t ext2fs_resize_generic_bitmap(__u32 new_end,
- __u32 new_real_end,
- ext2fs_generic_bitmap bmap);
-extern errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
- ext2fs_inode_bitmap bmap);
-extern errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
- ext2fs_block_bitmap bmap);
-extern errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
- ext2fs_generic_bitmap *dest);
-
-/* swapfs.c */
-extern void ext2fs_swap_ext_attr(char *to, char *from, int bufsize,
- int has_header);
-extern void ext2fs_swap_super(struct ext2_super_block * super);
-extern void ext2fs_swap_group_desc(struct ext2_group_desc *gdp);
-extern void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t,
- struct ext2_inode_large *f, int hostorder,
- int bufsize);
-extern void ext2fs_swap_inode(ext2_filsys fs,struct ext2_inode *t,
- struct ext2_inode *f, int hostorder);
-
-/* valid_blk.c */
-extern int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode);
-
-/* version.c */
-extern int ext2fs_parse_version_string(const char *ver_string);
-extern int ext2fs_get_library_version(const char **ver_string,
- const char **date_string);
-
-/* write_bb_file.c */
-extern errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list,
- unsigned int flags,
- FILE *f);
-
-
-/* inline functions */
-extern errcode_t ext2fs_get_mem(unsigned long size, void *ptr);
-extern errcode_t ext2fs_free_mem(void *ptr);
-extern errcode_t ext2fs_resize_mem(unsigned long old_size,
- unsigned long size, void *ptr);
-extern void ext2fs_mark_super_dirty(ext2_filsys fs);
-extern void ext2fs_mark_changed(ext2_filsys fs);
-extern int ext2fs_test_changed(ext2_filsys fs);
-extern void ext2fs_mark_valid(ext2_filsys fs);
-extern void ext2fs_unmark_valid(ext2_filsys fs);
-extern int ext2fs_test_valid(ext2_filsys fs);
-extern void ext2fs_mark_ib_dirty(ext2_filsys fs);
-extern void ext2fs_mark_bb_dirty(ext2_filsys fs);
-extern int ext2fs_test_ib_dirty(ext2_filsys fs);
-extern int ext2fs_test_bb_dirty(ext2_filsys fs);
-extern int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk);
-extern int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino);
-extern blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
- struct ext2_inode *inode);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/ext2fsP.h b/release/src/router/busybox/e2fsprogs/ext2fs/ext2fsP.h
deleted file mode 100644
index 7a02e9a8e3..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/ext2fsP.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * ext2fsP.h --- private header file for ext2 library
- *
- * Copyright (C) 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include "ext2fs.h"
-
-/*
- * Badblocks list
- */
-struct ext2_struct_u32_list {
- int magic;
- int num;
- int size;
- __u32 *list;
- int badblocks_flags;
-};
-
-struct ext2_struct_u32_iterate {
- int magic;
- ext2_u32_list bb;
- int ptr;
-};
-
-
-/*
- * Directory block iterator definition
- */
-struct ext2_struct_dblist {
- int magic;
- ext2_filsys fs;
- ext2_ino_t size;
- ext2_ino_t count;
- int sorted;
- struct ext2_db_entry * list;
-};
-
-/*
- * For directory iterators
- */
-struct dir_context {
- ext2_ino_t dir;
- int flags;
- char *buf;
- int (*func)(ext2_ino_t dir,
- int entry,
- struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *priv_data);
- void *priv_data;
- errcode_t errcode;
-};
-
-/*
- * Inode cache structure
- */
-struct ext2_inode_cache {
- void * buffer;
- blk_t buffer_blk;
- int cache_last;
- int cache_size;
- int refcount;
- struct ext2_inode_cache_ent *cache;
-};
-
-struct ext2_inode_cache_ent {
- ext2_ino_t ino;
- struct ext2_inode inode;
-};
-
-/* Function prototypes */
-
-extern int ext2fs_process_dir_block(ext2_filsys fs,
- blk_t *blocknr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block,
- int ref_offset,
- void *priv_data);
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/ext2fs_inline.c b/release/src/router/busybox/e2fsprogs/ext2fs/ext2fs_inline.c
deleted file mode 100644
index 7d37d232d8..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/ext2fs_inline.c
+++ /dev/null
@@ -1,365 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * ext2fs.h --- ext2fs
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include "ext2fs.h"
-#include "bitops.h"
-#include <string.h>
-
-/*
- * Allocate memory
- */
-errcode_t ext2fs_get_mem(unsigned long size, void *ptr)
-{
- void **pp = (void **)ptr;
-
- *pp = malloc(size);
- if (!*pp)
- return EXT2_ET_NO_MEMORY;
- return 0;
-}
-
-/*
- * Free memory
- */
-errcode_t ext2fs_free_mem(void *ptr)
-{
- void **pp = (void **)ptr;
-
- free(*pp);
- *pp = 0;
- return 0;
-}
-
-/*
- * Resize memory
- */
-errcode_t ext2fs_resize_mem(unsigned long EXT2FS_ATTR((unused)) old_size,
- unsigned long size, void *ptr)
-{
- void *p;
-
- /* Use "memcpy" for pointer assignments here to avoid problems
- * with C99 strict type aliasing rules. */
- memcpy(&p, ptr, sizeof (p));
- p = xrealloc(p, size);
- memcpy(ptr, &p, sizeof (p));
- return 0;
-}
-
-/*
- * Mark a filesystem superblock as dirty
- */
-void ext2fs_mark_super_dirty(ext2_filsys fs)
-{
- fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_CHANGED;
-}
-
-/*
- * Mark a filesystem as changed
- */
-void ext2fs_mark_changed(ext2_filsys fs)
-{
- fs->flags |= EXT2_FLAG_CHANGED;
-}
-
-/*
- * Check to see if a filesystem has changed
- */
-int ext2fs_test_changed(ext2_filsys fs)
-{
- return (fs->flags & EXT2_FLAG_CHANGED);
-}
-
-/*
- * Mark a filesystem as valid
- */
-void ext2fs_mark_valid(ext2_filsys fs)
-{
- fs->flags |= EXT2_FLAG_VALID;
-}
-
-/*
- * Mark a filesystem as NOT valid
- */
-void ext2fs_unmark_valid(ext2_filsys fs)
-{
- fs->flags &= ~EXT2_FLAG_VALID;
-}
-
-/*
- * Check to see if a filesystem is valid
- */
-int ext2fs_test_valid(ext2_filsys fs)
-{
- return (fs->flags & EXT2_FLAG_VALID);
-}
-
-/*
- * Mark the inode bitmap as dirty
- */
-void ext2fs_mark_ib_dirty(ext2_filsys fs)
-{
- fs->flags |= EXT2_FLAG_IB_DIRTY | EXT2_FLAG_CHANGED;
-}
-
-/*
- * Mark the block bitmap as dirty
- */
-void ext2fs_mark_bb_dirty(ext2_filsys fs)
-{
- fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_CHANGED;
-}
-
-/*
- * Check to see if a filesystem's inode bitmap is dirty
- */
-int ext2fs_test_ib_dirty(ext2_filsys fs)
-{
- return (fs->flags & EXT2_FLAG_IB_DIRTY);
-}
-
-/*
- * Check to see if a filesystem's block bitmap is dirty
- */
-int ext2fs_test_bb_dirty(ext2_filsys fs)
-{
- return (fs->flags & EXT2_FLAG_BB_DIRTY);
-}
-
-/*
- * Return the group # of a block
- */
-int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk)
-{
- return (blk - fs->super->s_first_data_block) /
- fs->super->s_blocks_per_group;
-}
-
-/*
- * Return the group # of an inode number
- */
-int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino)
-{
- return (ino - 1) / fs->super->s_inodes_per_group;
-}
-
-blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
- struct ext2_inode *inode)
-{
- return inode->i_blocks -
- (inode->i_file_acl ? fs->blocksize >> 9 : 0);
-}
-
-
-
-
-
-
-
-
-
-__u16 ext2fs_swab16(__u16 val)
-{
- return (val >> 8) | (val << 8);
-}
-
-__u32 ext2fs_swab32(__u32 val)
-{
- return ((val>>24) | ((val>>8)&0xFF00) |
- ((val<<8)&0xFF0000) | (val<<24));
-}
-
-int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
- blk_t bitno);
-
-int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
- blk_t bitno)
-{
- if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
- ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, bitno);
- return 0;
- }
- return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap);
-}
-
-int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap,
- blk_t block)
-{
- return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap)
- bitmap,
- block);
-}
-
-int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
- blk_t block)
-{
- return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
- block);
-}
-
-int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap,
- blk_t block)
-{
- return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
- block);
-}
-
-int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
- ext2_ino_t inode)
-{
- return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
- inode);
-}
-
-int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
- ext2_ino_t inode)
-{
- return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
- inode);
-}
-
-int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
- ext2_ino_t inode)
-{
- return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
- inode);
-}
-
-void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
- blk_t block)
-{
- ext2fs_set_bit(block - bitmap->start, bitmap->bitmap);
-}
-
-void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
- blk_t block)
-{
- ext2fs_clear_bit(block - bitmap->start, bitmap->bitmap);
-}
-
-int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
- blk_t block)
-{
- return ext2fs_test_bit(block - bitmap->start, bitmap->bitmap);
-}
-
-void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
- ext2_ino_t inode)
-{
- ext2fs_set_bit(inode - bitmap->start, bitmap->bitmap);
-}
-
-void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
- ext2_ino_t inode)
-{
- ext2fs_clear_bit(inode - bitmap->start, bitmap->bitmap);
-}
-
-int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
- ext2_ino_t inode)
-{
- return ext2fs_test_bit(inode - bitmap->start, bitmap->bitmap);
-}
-
-blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap)
-{
- return bitmap->start;
-}
-
-ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
-{
- return bitmap->start;
-}
-
-blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap)
-{
- return bitmap->end;
-}
-
-ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
-{
- return bitmap->end;
-}
-
-int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num)
-{
- int i;
-
- if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
- ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
- block, bitmap->description);
- return 0;
- }
- for (i=0; i < num; i++) {
- if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
- return 0;
- }
- return 1;
-}
-
-int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num)
-{
- int i;
-
- for (i=0; i < num; i++) {
- if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
- return 0;
- }
- return 1;
-}
-
-void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num)
-{
- int i;
-
- if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
- ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
- bitmap->description);
- return;
- }
- for (i=0; i < num; i++)
- ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
-}
-
-void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num)
-{
- int i;
-
- for (i=0; i < num; i++)
- ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
-}
-
-void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num)
-{
- int i;
-
- if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
- ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
- bitmap->description);
- return;
- }
- for (i=0; i < num; i++)
- ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);
-}
-
-void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num)
-{
- int i;
- for (i=0; i < num; i++)
- ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/ext_attr.c b/release/src/router/busybox/e2fsprogs/ext2fs/ext_attr.c
deleted file mode 100644
index a2ba12d45c..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/ext_attr.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * ext_attr.c --- extended attribute blocks
- *
- * Copyright (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
- *
- * Copyright (C) 2002 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <time.h>
-
-#include "ext2_fs.h"
-#include "ext2_ext_attr.h"
-#include "ext2fs.h"
-
-errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf)
-{
- errcode_t retval;
-
- retval = io_channel_read_blk(fs->io, block, 1, buf);
- if (retval)
- return retval;
-#if BB_BIG_ENDIAN
- if ((fs->flags & (EXT2_FLAG_SWAP_BYTES|
- EXT2_FLAG_SWAP_BYTES_READ)) != 0)
- ext2fs_swap_ext_attr(buf, buf, fs->blocksize, 1);
-#endif
- return 0;
-}
-
-errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *inbuf)
-{
- errcode_t retval;
- char *write_buf;
- char *buf = NULL;
-
- if (BB_BIG_ENDIAN && ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))) {
- retval = ext2fs_get_mem(fs->blocksize, &buf);
- if (retval)
- return retval;
- write_buf = buf;
- ext2fs_swap_ext_attr(buf, inbuf, fs->blocksize, 1);
- } else
- write_buf = (char *) inbuf;
- retval = io_channel_write_blk(fs->io, block, 1, write_buf);
- if (buf)
- ext2fs_free_mem(&buf);
- if (!retval)
- ext2fs_mark_changed(fs);
- return retval;
-}
-
-/*
- * This function adjusts the reference count of the EA block.
- */
-errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk,
- char *block_buf, int adjust,
- __u32 *newcount)
-{
- errcode_t retval;
- struct ext2_ext_attr_header *header;
- char *buf = NULL;
-
- if ((blk >= fs->super->s_blocks_count) ||
- (blk < fs->super->s_first_data_block))
- return EXT2_ET_BAD_EA_BLOCK_NUM;
-
- if (!block_buf) {
- retval = ext2fs_get_mem(fs->blocksize, &buf);
- if (retval)
- return retval;
- block_buf = buf;
- }
-
- retval = ext2fs_read_ext_attr(fs, blk, block_buf);
- if (retval)
- goto errout;
-
- header = (struct ext2_ext_attr_header *) block_buf;
- header->h_refcount += adjust;
- if (newcount)
- *newcount = header->h_refcount;
-
- retval = ext2fs_write_ext_attr(fs, blk, block_buf);
- if (retval)
- goto errout;
-
-errout:
- if (buf)
- ext2fs_free_mem(&buf);
- return retval;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/fileio.c b/release/src/router/busybox/e2fsprogs/ext2fs/fileio.c
deleted file mode 100644
index 5a5ad3ef89..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/fileio.c
+++ /dev/null
@@ -1,377 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * fileio.c --- Simple file I/O routines
- *
- * Copyright (C) 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-struct ext2_file {
- errcode_t magic;
- ext2_filsys fs;
- ext2_ino_t ino;
- struct ext2_inode inode;
- int flags;
- __u64 pos;
- blk_t blockno;
- blk_t physblock;
- char *buf;
-};
-
-#define BMAP_BUFFER (file->buf + fs->blocksize)
-
-errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode,
- int flags, ext2_file_t *ret)
-{
- ext2_file_t file;
- errcode_t retval;
-
- /*
- * Don't let caller create or open a file for writing if the
- * filesystem is read-only.
- */
- if ((flags & (EXT2_FILE_WRITE | EXT2_FILE_CREATE)) &&
- !(fs->flags & EXT2_FLAG_RW))
- return EXT2_ET_RO_FILSYS;
-
- retval = ext2fs_get_mem(sizeof(struct ext2_file), &file);
- if (retval)
- return retval;
-
- memset(file, 0, sizeof(struct ext2_file));
- file->magic = EXT2_ET_MAGIC_EXT2_FILE;
- file->fs = fs;
- file->ino = ino;
- file->flags = flags & EXT2_FILE_MASK;
-
- if (inode) {
- memcpy(&file->inode, inode, sizeof(struct ext2_inode));
- } else {
- retval = ext2fs_read_inode(fs, ino, &file->inode);
- if (retval)
- goto fail;
- }
-
- retval = ext2fs_get_mem(fs->blocksize * 3, &file->buf);
- if (retval)
- goto fail;
-
- *ret = file;
- return 0;
-
-fail:
- ext2fs_free_mem(&file->buf);
- ext2fs_free_mem(&file);
- return retval;
-}
-
-errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino,
- int flags, ext2_file_t *ret)
-{
- return ext2fs_file_open2(fs, ino, NULL, flags, ret);
-}
-
-/*
- * This function returns the filesystem handle of a file from the structure
- */
-ext2_filsys ext2fs_file_get_fs(ext2_file_t file)
-{
- if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
- return 0;
- return file->fs;
-}
-
-/*
- * This function flushes the dirty block buffer out to disk if
- * necessary.
- */
-errcode_t ext2fs_file_flush(ext2_file_t file)
-{
- errcode_t retval;
- ext2_filsys fs;
-
- EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
- fs = file->fs;
-
- if (!(file->flags & EXT2_FILE_BUF_VALID) ||
- !(file->flags & EXT2_FILE_BUF_DIRTY))
- return 0;
-
- /*
- * OK, the physical block hasn't been allocated yet.
- * Allocate it.
- */
- if (!file->physblock) {
- retval = ext2fs_bmap(fs, file->ino, &file->inode,
- BMAP_BUFFER, file->ino ? BMAP_ALLOC : 0,
- file->blockno, &file->physblock);
- if (retval)
- return retval;
- }
-
- retval = io_channel_write_blk(fs->io, file->physblock,
- 1, file->buf);
- if (retval)
- return retval;
-
- file->flags &= ~EXT2_FILE_BUF_DIRTY;
-
- return retval;
-}
-
-/*
- * This function synchronizes the file's block buffer and the current
- * file position, possibly invalidating block buffer if necessary
- */
-static errcode_t sync_buffer_position(ext2_file_t file)
-{
- blk_t b;
- errcode_t retval;
-
- b = file->pos / file->fs->blocksize;
- if (b != file->blockno) {
- retval = ext2fs_file_flush(file);
- if (retval)
- return retval;
- file->flags &= ~EXT2_FILE_BUF_VALID;
- }
- file->blockno = b;
- return 0;
-}
-
-/*
- * This function loads the file's block buffer with valid data from
- * the disk as necessary.
- *
- * If dontfill is true, then skip initializing the buffer since we're
- * going to be replacing its entire contents anyway. If set, then the
- * function basically only sets file->physblock and EXT2_FILE_BUF_VALID
- */
-#define DONTFILL 1
-static errcode_t load_buffer(ext2_file_t file, int dontfill)
-{
- ext2_filsys fs = file->fs;
- errcode_t retval;
-
- if (!(file->flags & EXT2_FILE_BUF_VALID)) {
- retval = ext2fs_bmap(fs, file->ino, &file->inode,
- BMAP_BUFFER, 0, file->blockno,
- &file->physblock);
- if (retval)
- return retval;
- if (!dontfill) {
- if (file->physblock) {
- retval = io_channel_read_blk(fs->io,
- file->physblock,
- 1, file->buf);
- if (retval)
- return retval;
- } else
- memset(file->buf, 0, fs->blocksize);
- }
- file->flags |= EXT2_FILE_BUF_VALID;
- }
- return 0;
-}
-
-
-errcode_t ext2fs_file_close(ext2_file_t file)
-{
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
-
- retval = ext2fs_file_flush(file);
-
- ext2fs_free_mem(&file->buf);
- ext2fs_free_mem(&file);
-
- return retval;
-}
-
-
-errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
- unsigned int wanted, unsigned int *got)
-{
- ext2_filsys fs;
- errcode_t retval = 0;
- unsigned int start, c, count = 0;
- __u64 left;
- char *ptr = (char *) buf;
-
- EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
- fs = file->fs;
-
- while ((file->pos < EXT2_I_SIZE(&file->inode)) && (wanted > 0)) {
- retval = sync_buffer_position(file);
- if (retval)
- goto fail;
- retval = load_buffer(file, 0);
- if (retval)
- goto fail;
-
- start = file->pos % fs->blocksize;
- c = fs->blocksize - start;
- if (c > wanted)
- c = wanted;
- left = EXT2_I_SIZE(&file->inode) - file->pos;
- if (c > left)
- c = left;
-
- memcpy(ptr, file->buf+start, c);
- file->pos += c;
- ptr += c;
- count += c;
- wanted -= c;
- }
-
-fail:
- if (got)
- *got = count;
- return retval;
-}
-
-
-errcode_t ext2fs_file_write(ext2_file_t file, const void *buf,
- unsigned int nbytes, unsigned int *written)
-{
- ext2_filsys fs;
- errcode_t retval = 0;
- unsigned int start, c, count = 0;
- const char *ptr = (const char *) buf;
-
- EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
- fs = file->fs;
-
- if (!(file->flags & EXT2_FILE_WRITE))
- return EXT2_ET_FILE_RO;
-
- while (nbytes > 0) {
- retval = sync_buffer_position(file);
- if (retval)
- goto fail;
-
- start = file->pos % fs->blocksize;
- c = fs->blocksize - start;
- if (c > nbytes)
- c = nbytes;
-
- /*
- * We only need to do a read-modify-update cycle if
- * we're doing a partial write.
- */
- retval = load_buffer(file, (c == fs->blocksize));
- if (retval)
- goto fail;
-
- file->flags |= EXT2_FILE_BUF_DIRTY;
- memcpy(file->buf+start, ptr, c);
- file->pos += c;
- ptr += c;
- count += c;
- nbytes -= c;
- }
-
-fail:
- if (written)
- *written = count;
- return retval;
-}
-
-errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset,
- int whence, __u64 *ret_pos)
-{
- EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
-
- if (whence == EXT2_SEEK_SET)
- file->pos = offset;
- else if (whence == EXT2_SEEK_CUR)
- file->pos += offset;
- else if (whence == EXT2_SEEK_END)
- file->pos = EXT2_I_SIZE(&file->inode) + offset;
- else
- return EXT2_ET_INVALID_ARGUMENT;
-
- if (ret_pos)
- *ret_pos = file->pos;
-
- return 0;
-}
-
-errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
- int whence, ext2_off_t *ret_pos)
-{
- __u64 loffset, ret_loffset;
- errcode_t retval;
-
- loffset = offset;
- retval = ext2fs_file_llseek(file, loffset, whence, &ret_loffset);
- if (ret_pos)
- *ret_pos = (ext2_off_t) ret_loffset;
- return retval;
-}
-
-
-/*
- * This function returns the size of the file, according to the inode
- */
-errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size)
-{
- if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
- return EXT2_ET_MAGIC_EXT2_FILE;
- *ret_size = EXT2_I_SIZE(&file->inode);
- return 0;
-}
-
-/*
- * This function returns the size of the file, according to the inode
- */
-ext2_off_t ext2fs_file_get_size(ext2_file_t file)
-{
- __u64 size;
-
- if (ext2fs_file_get_lsize(file, &size))
- return 0;
- if ((size >> 32) != 0)
- return 0;
- return size;
-}
-
-/*
- * This function sets the size of the file, truncating it if necessary
- *
- * XXX still need to call truncate
- */
-errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size)
-{
- errcode_t retval;
- EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
-
- file->inode.i_size = size;
- file->inode.i_size_high = 0;
- if (file->ino) {
- retval = ext2fs_write_inode(file->fs, file->ino, &file->inode);
- if (retval)
- return retval;
- }
-
- /*
- * XXX truncate inode if necessary
- */
-
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/finddev.c b/release/src/router/busybox/e2fsprogs/ext2fs/finddev.c
deleted file mode 100644
index e9e83fd7ad..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/finddev.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * finddev.c -- this routine attempts to find a particular device in
- * /dev
- *
- * Copyright (C) 2000 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#include <dirent.h>
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_SYS_MKDEV_H
-#include <sys/mkdev.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-struct dir_list {
- char *name;
- struct dir_list *next;
-};
-
-/*
- * This function adds an entry to the directory list
- */
-static void add_to_dirlist(const char *name, struct dir_list **list)
-{
- struct dir_list *dp;
-
- dp = xmalloc(sizeof(struct dir_list));
- dp->name = xmalloc(strlen(name)+1);
- strcpy(dp->name, name);
- dp->next = *list;
- *list = dp;
-}
-
-/*
- * This function frees a directory list
- */
-static void free_dirlist(struct dir_list **list)
-{
- struct dir_list *dp, *next;
-
- for (dp = *list; dp; dp = next) {
- next = dp->next;
- free(dp->name);
- free(dp);
- }
- *list = 0;
-}
-
-static int scan_dir(char *dir_name, dev_t device, struct dir_list **list,
- char **ret_path)
-{
- DIR *dir;
- struct dirent *dp;
- char path[1024], *cp;
- int dirlen;
- struct stat st;
-
- dirlen = strlen(dir_name);
- if ((dir = opendir(dir_name)) == NULL)
- return errno;
- dp = readdir(dir);
- while (dp) {
- if (dirlen + strlen(dp->d_name) + 2 >= sizeof(path))
- goto skip_to_next;
- if (dp->d_name[0] == '.' &&
- ((dp->d_name[1] == 0) ||
- ((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
- goto skip_to_next;
- sprintf(path, "%s/%s", dir_name, dp->d_name);
- if (stat(path, &st) < 0)
- goto skip_to_next;
- if (S_ISDIR(st.st_mode))
- add_to_dirlist(path, list);
- if (S_ISBLK(st.st_mode) && st.st_rdev == device) {
- cp = xmalloc(strlen(path)+1);
- strcpy(cp, path);
- *ret_path = cp;
- goto success;
- }
- skip_to_next:
- dp = readdir(dir);
- }
-success:
- closedir(dir);
- return 0;
-}
-
-/*
- * This function finds the pathname to a block device with a given
- * device number. It returns a pointer to allocated memory to the
- * pathname on success, and NULL on failure.
- */
-char *ext2fs_find_block_device(dev_t device)
-{
- struct dir_list *list = NULL, *new_list = NULL;
- struct dir_list *current;
- char *ret_path = NULL;
-
- /*
- * Add the starting directories to search...
- */
- add_to_dirlist("/devices", &list);
- add_to_dirlist("/devfs", &list);
- add_to_dirlist("/dev", &list);
-
- while (list) {
- current = list;
- list = list->next;
-#ifdef DEBUG
- printf("Scanning directory %s\n", current->name);
-#endif
- scan_dir(current->name, device, &new_list, &ret_path);
- free(current->name);
- free(current);
- if (ret_path)
- break;
- /*
- * If we're done checking at this level, descend to
- * the next level of subdirectories. (breadth-first)
- */
- if (list == 0) {
- list = new_list;
- new_list = 0;
- }
- }
- free_dirlist(&list);
- free_dirlist(&new_list);
- return ret_path;
-}
-
-
-#ifdef DEBUG
-int main(int argc, char** argv)
-{
- char *devname, *tmp;
- int major, minor;
- dev_t device;
- const char *errmsg = "Cannot parse %s: %s\n";
-
- if ((argc != 2) && (argc != 3)) {
- fprintf(stderr, "Usage: %s device_number\n", argv[0]);
- fprintf(stderr, "\t: %s major minor\n", argv[0]);
- exit(1);
- }
- if (argc == 2) {
- device = strtoul(argv[1], &tmp, 0);
- if (*tmp) {
- fprintf(stderr, errmsg, "device number", argv[1]);
- exit(1);
- }
- } else {
- major = strtoul(argv[1], &tmp, 0);
- if (*tmp) {
- fprintf(stderr, errmsg, "major number", argv[1]);
- exit(1);
- }
- minor = strtoul(argv[2], &tmp, 0);
- if (*tmp) {
- fprintf(stderr, errmsg, "minor number", argv[2]);
- exit(1);
- }
- device = makedev(major, minor);
- printf("Looking for device 0x%04x (%d:%d)\n", device,
- major, minor);
- }
- devname = ext2fs_find_block_device(device);
- if (devname) {
- printf("Found device! %s\n", devname);
- free(devname);
- } else {
- printf("Cannot find device.\n");
- }
- return 0;
-}
-
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/flushb.c b/release/src/router/busybox/e2fsprogs/ext2fs/flushb.c
deleted file mode 100644
index 45ed76512d..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/flushb.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * flushb.c --- Hides system-dependent information for both syncing a
- * device to disk and to flush any buffers from disk cache.
- *
- * Copyright (C) 2000 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#if HAVE_SYS_MOUNT_H
-#include <sys/param.h>
-#include <sys/mount.h> /* This may define BLKFLSBUF */
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * For Linux, define BLKFLSBUF and FDFLUSH if necessary, since
- * not all portable header file does so for us. This really should be
- * fixed in the glibc header files. (Recent glibcs appear to define
- * BLKFLSBUF in sys/mount.h, but FDFLUSH still doesn't seem to be
- * defined anywhere portable.) Until then....
- */
-#ifdef __linux__
-#ifndef BLKFLSBUF
-#define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
-#endif
-#ifndef FDFLUSH
-#define FDFLUSH _IO(2,0x4b) /* flush floppy disk */
-#endif
-#endif
-
-/*
- * This function will sync a device/file, and optionally attempt to
- * flush the buffer cache. The latter is basically only useful for
- * system benchmarks and for torturing systems in burn-in tests. :)
- */
-errcode_t ext2fs_sync_device(int fd, int flushb)
-{
- /*
- * We always sync the device in case we're running on old
- * kernels for which we can lose data if we don't. (There
- * still is a race condition for those kernels, but this
- * reduces it greatly.)
- */
- if (fsync (fd) == -1)
- return errno;
-
- if (flushb) {
-
-#ifdef BLKFLSBUF
- if (ioctl (fd, BLKFLSBUF, 0) == 0)
- return 0;
-#else
-#ifdef __GNUC__
-# warning BLKFLSBUF not defined
-#endif /* __GNUC__ */
-#endif
-#ifdef FDFLUSH
- ioctl (fd, FDFLUSH, 0); /* In case this is a floppy */
-#else
-#ifdef __GNUC__
-# warning FDFLUSH not defined
-#endif /* __GNUC__ */
-#endif
- }
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/freefs.c b/release/src/router/busybox/e2fsprogs/ext2fs/freefs.c
deleted file mode 100644
index 0c5d48b113..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/freefs.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * freefs.c --- free an ext2 filesystem
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fsP.h"
-
-static void ext2fs_free_inode_cache(struct ext2_inode_cache *icache);
-
-void ext2fs_free(ext2_filsys fs)
-{
- if (!fs || (fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS))
- return;
- if (fs->image_io != fs->io) {
- if (fs->image_io)
- io_channel_close(fs->image_io);
- }
- if (fs->io) {
- io_channel_close(fs->io);
- }
- ext2fs_free_mem(&fs->device_name);
- ext2fs_free_mem(&fs->super);
- ext2fs_free_mem(&fs->orig_super);
- ext2fs_free_mem(&fs->group_desc);
- ext2fs_free_block_bitmap(fs->block_map);
- ext2fs_free_inode_bitmap(fs->inode_map);
-
- ext2fs_badblocks_list_free(fs->badblocks);
- fs->badblocks = 0;
-
- ext2fs_free_dblist(fs->dblist);
-
- if (fs->icache)
- ext2fs_free_inode_cache(fs->icache);
-
- fs->magic = 0;
-
- ext2fs_free_mem(&fs);
-}
-
-void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap)
-{
- if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_GENERIC_BITMAP))
- return;
-
- bitmap->magic = 0;
- ext2fs_free_mem(&bitmap->description);
- ext2fs_free_mem(&bitmap->bitmap);
- ext2fs_free_mem(&bitmap);
-}
-
-void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap)
-{
- if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_INODE_BITMAP))
- return;
-
- bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
- ext2fs_free_generic_bitmap(bitmap);
-}
-
-void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap)
-{
- if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_BLOCK_BITMAP))
- return;
-
- bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
- ext2fs_free_generic_bitmap(bitmap);
-}
-
-/*
- * Free the inode cache structure
- */
-static void ext2fs_free_inode_cache(struct ext2_inode_cache *icache)
-{
- if (--icache->refcount)
- return;
- ext2fs_free_mem(&icache->buffer);
- ext2fs_free_mem(&icache->cache);
- icache->buffer_blk = 0;
- ext2fs_free_mem(&icache);
-}
-
-/*
- * This procedure frees a badblocks list.
- */
-void ext2fs_u32_list_free(ext2_u32_list bb)
-{
- if (!bb || bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
- return;
-
- ext2fs_free_mem(&bb->list);
- ext2fs_free_mem(&bb);
-}
-
-void ext2fs_badblocks_list_free(ext2_badblocks_list bb)
-{
- ext2fs_u32_list_free((ext2_u32_list) bb);
-}
-
-
-/*
- * Free a directory block list
- */
-void ext2fs_free_dblist(ext2_dblist dblist)
-{
- if (!dblist || (dblist->magic != EXT2_ET_MAGIC_DBLIST))
- return;
-
- ext2fs_free_mem(&dblist->list);
- if (dblist->fs && dblist->fs->dblist == dblist)
- dblist->fs->dblist = 0;
- dblist->magic = 0;
- ext2fs_free_mem(&dblist);
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/gen_bitmap.c b/release/src/router/busybox/e2fsprogs/ext2fs/gen_bitmap.c
deleted file mode 100644
index d0869c9191..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/gen_bitmap.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * gen_bitmap.c --- Generic bitmap routines that used to be inlined.
- *
- * Copyright (C) 2001 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
- __u32 bitno)
-{
- if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
- ext2fs_warn_bitmap2(bitmap, EXT2FS_MARK_ERROR, bitno);
- return 0;
- }
- return ext2fs_set_bit(bitno - bitmap->start, bitmap->bitmap);
-}
-
-int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
- blk_t bitno)
-{
- if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
- ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno);
- return 0;
- }
- return ext2fs_clear_bit(bitno - bitmap->start, bitmap->bitmap);
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/get_pathname.c b/release/src/router/busybox/e2fsprogs/ext2fs/get_pathname.c
deleted file mode 100644
index 2bb1cc25ec..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/get_pathname.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * get_pathname.c --- do directry/inode -> name translation
- *
- * Copyright (C) 1993, 1994, 1995 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- *
- * ext2fs_get_pathname(fs, dir, ino, name)
- *
- * This function translates takes two inode numbers into a
- * string, placing the result in <name>. <dir> is the containing
- * directory inode, and <ino> is the inode number itself. If
- * <ino> is zero, then ext2fs_get_pathname will return pathname
- * of the directory <dir>.
- *
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-struct get_pathname_struct {
- ext2_ino_t search_ino;
- ext2_ino_t parent;
- char *name;
- errcode_t errcode;
-};
-
-#ifdef __TURBOC__
-# pragma argsused
-#endif
-static int get_pathname_proc(struct ext2_dir_entry *dirent,
- int offset EXT2FS_ATTR((unused)),
- int blocksize EXT2FS_ATTR((unused)),
- char *buf EXT2FS_ATTR((unused)),
- void *priv_data)
-{
- struct get_pathname_struct *gp;
- errcode_t retval;
-
- gp = (struct get_pathname_struct *) priv_data;
-
- if (((dirent->name_len & 0xFF) == 2) &&
- !strncmp(dirent->name, "..", 2))
- gp->parent = dirent->inode;
- if (dirent->inode == gp->search_ino) {
- retval = ext2fs_get_mem((dirent->name_len & 0xFF) + 1,
- &gp->name);
- if (retval) {
- gp->errcode = retval;
- return DIRENT_ABORT;
- }
- strncpy(gp->name, dirent->name, (dirent->name_len & 0xFF));
- gp->name[dirent->name_len & 0xFF] = '\0';
- return DIRENT_ABORT;
- }
- return 0;
-}
-
-static errcode_t ext2fs_get_pathname_int(ext2_filsys fs, ext2_ino_t dir,
- ext2_ino_t ino, int maxdepth,
- char *buf, char **name)
-{
- struct get_pathname_struct gp;
- char *parent_name, *ret;
- errcode_t retval;
-
- if (dir == ino) {
- retval = ext2fs_get_mem(2, name);
- if (retval)
- return retval;
- strcpy(*name, (dir == EXT2_ROOT_INO) ? "/" : ".");
- return 0;
- }
-
- if (!dir || (maxdepth < 0)) {
- retval = ext2fs_get_mem(4, name);
- if (retval)
- return retval;
- strcpy(*name, "...");
- return 0;
- }
-
- gp.search_ino = ino;
- gp.parent = 0;
- gp.name = 0;
- gp.errcode = 0;
-
- retval = ext2fs_dir_iterate(fs, dir, 0, buf, get_pathname_proc, &gp);
- if (retval)
- goto cleanup;
- if (gp.errcode) {
- retval = gp.errcode;
- goto cleanup;
- }
-
- retval = ext2fs_get_pathname_int(fs, gp.parent, dir, maxdepth-1,
- buf, &parent_name);
- if (retval)
- goto cleanup;
- if (!ino) {
- *name = parent_name;
- return 0;
- }
-
- if (gp.name)
- retval = ext2fs_get_mem(strlen(parent_name)+strlen(gp.name)+2,
- &ret);
- else
- retval = ext2fs_get_mem(strlen(parent_name)+5, &ret);
- if (retval)
- goto cleanup;
-
- ret[0] = 0;
- if (parent_name[1])
- strcat(ret, parent_name);
- strcat(ret, "/");
- if (gp.name)
- strcat(ret, gp.name);
- else
- strcat(ret, "???");
- *name = ret;
- ext2fs_free_mem(&parent_name);
- retval = 0;
-
-cleanup:
- ext2fs_free_mem(&gp.name);
- return retval;
-}
-
-errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino,
- char **name)
-{
- char *buf;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- retval = ext2fs_get_mem(fs->blocksize, &buf);
- if (retval)
- return retval;
- if (dir == ino)
- ino = 0;
- retval = ext2fs_get_pathname_int(fs, dir, ino, 32, buf, name);
- ext2fs_free_mem(&buf);
- return retval;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/getsectsize.c b/release/src/router/busybox/e2fsprogs/ext2fs/getsectsize.c
deleted file mode 100644
index 163ec65e5b..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/getsectsize.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * getsectsize.c --- get the sector size of a device.
- *
- * Copyright (C) 1995, 1995 Theodore Ts'o.
- * Copyright (C) 2003 VMware, Inc.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <fcntl.h>
-#ifdef HAVE_LINUX_FD_H
-#include <sys/ioctl.h>
-#include <linux/fd.h>
-#endif
-
-#if defined(__linux__) && defined(_IO) && !defined(BLKSSZGET)
-#define BLKSSZGET _IO(0x12,104)/* get block device sector size */
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * Returns the number of blocks in a partition
- */
-errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize)
-{
- int fd;
-
-#ifdef CONFIG_LFS
- fd = open64(file, O_RDONLY);
-#else
- fd = open(file, O_RDONLY);
-#endif
- if (fd < 0)
- return errno;
-
-#ifdef BLKSSZGET
- if (ioctl(fd, BLKSSZGET, sectsize) >= 0) {
- close(fd);
- return 0;
- }
-#endif
- *sectsize = 0;
- close(fd);
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/getsize.c b/release/src/router/busybox/e2fsprogs/ext2fs/getsize.c
deleted file mode 100644
index 923334facc..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/getsize.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * getsize.c --- get the size of a partition.
- *
- * Copyright (C) 1995, 1995 Theodore Ts'o.
- * Copyright (C) 2003 VMware, Inc.
- *
- * Windows version of ext2fs_get_device_size by Chris Li, VMware.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <fcntl.h>
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#ifdef HAVE_LINUX_FD_H
-#include <linux/fd.h>
-#endif
-#ifdef HAVE_SYS_DISKLABEL_H
-#include <sys/disklabel.h>
-#endif
-#ifdef HAVE_SYS_DISK_H
-#ifdef HAVE_SYS_QUEUE_H
-#include <sys/queue.h> /* for LIST_HEAD */
-#endif
-#include <sys/disk.h>
-#endif
-#ifdef __linux__
-#include <sys/utsname.h>
-#endif
-
-#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
-#define BLKGETSIZE _IO(0x12,96) /* return device size */
-#endif
-
-#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
-#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
-#endif
-
-#ifdef APPLE_DARWIN
-#define BLKGETSIZE DKIOCGETBLOCKCOUNT32
-#endif /* APPLE_DARWIN */
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-#if defined(__CYGWIN__) || defined(WIN32)
-#include <windows.h>
-#include <winioctl.h>
-
-#if (_WIN32_WINNT >= 0x0500)
-#define HAVE_GET_FILE_SIZE_EX 1
-#endif
-
-errcode_t ext2fs_get_device_size(const char *file, int blocksize,
- blk_t *retblocks)
-{
- HANDLE dev;
- PARTITION_INFORMATION pi;
- DISK_GEOMETRY gi;
- DWORD retbytes;
-#ifdef HAVE_GET_FILE_SIZE_EX
- LARGE_INTEGER filesize;
-#else
- DWORD filesize;
-#endif /* HAVE_GET_FILE_SIZE_EX */
-
- dev = CreateFile(file, GENERIC_READ,
- FILE_SHARE_READ | FILE_SHARE_WRITE ,
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-
- if (dev == INVALID_HANDLE_VALUE)
- return EBADF;
- if (DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO,
- &pi, sizeof(PARTITION_INFORMATION),
- &pi, sizeof(PARTITION_INFORMATION),
- &retbytes, NULL)) {
-
- *retblocks = pi.PartitionLength.QuadPart / blocksize;
-
- } else if (DeviceIoControl(dev, IOCTL_DISK_GET_DRIVE_GEOMETRY,
- &gi, sizeof(DISK_GEOMETRY),
- &gi, sizeof(DISK_GEOMETRY),
- &retbytes, NULL)) {
-
- *retblocks = gi.BytesPerSector *
- gi.SectorsPerTrack *
- gi.TracksPerCylinder *
- gi.Cylinders.QuadPart / blocksize;
-
-#ifdef HAVE_GET_FILE_SIZE_EX
- } else if (GetFileSizeEx(dev, &filesize)) {
- *retblocks = filesize.QuadPart / blocksize;
- }
-#else
- } else {
- filesize = GetFileSize(dev, NULL);
- if (INVALID_FILE_SIZE != filesize) {
- *retblocks = filesize / blocksize;
- }
- }
-#endif /* HAVE_GET_FILE_SIZE_EX */
-
- CloseHandle(dev);
- return 0;
-}
-
-#else
-
-static int valid_offset (int fd, ext2_loff_t offset)
-{
- char ch;
-
- if (ext2fs_llseek (fd, offset, 0) < 0)
- return 0;
- if (read (fd, &ch, 1) < 1)
- return 0;
- return 1;
-}
-
-/*
- * Returns the number of blocks in a partition
- */
-errcode_t ext2fs_get_device_size(const char *file, int blocksize,
- blk_t *retblocks)
-{
- int fd;
- int valid_blkgetsize64 = 1;
-#ifdef __linux__
- struct utsname ut;
-#endif
- unsigned long long size64;
- unsigned long size;
- ext2_loff_t high, low;
-#ifdef FDGETPRM
- struct floppy_struct this_floppy;
-#endif
-#ifdef HAVE_SYS_DISKLABEL_H
- int part;
- struct disklabel lab;
- struct partition *pp;
- char ch;
-#endif /* HAVE_SYS_DISKLABEL_H */
-
-#ifdef CONFIG_LFS
- fd = open64(file, O_RDONLY);
-#else
- fd = open(file, O_RDONLY);
-#endif
- if (fd < 0)
- return errno;
-
-#ifdef DKIOCGETBLOCKCOUNT /* For Apple Darwin */
- if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) {
- if ((sizeof(*retblocks) < sizeof(unsigned long long))
- && ((size64 / (blocksize / 512)) > 0xFFFFFFFF))
- return EFBIG;
- close(fd);
- *retblocks = size64 / (blocksize / 512);
- return 0;
- }
-#endif
-
-#ifdef BLKGETSIZE64
-#ifdef __linux__
- uname(&ut);
- if ((ut.release[0] == '2') && (ut.release[1] == '.') &&
- (ut.release[2] < '6') && (ut.release[3] == '.'))
- valid_blkgetsize64 = 0;
-#endif
- if (valid_blkgetsize64 &&
- ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
- if ((sizeof(*retblocks) < sizeof(unsigned long long))
- && ((size64 / blocksize) > 0xFFFFFFFF))
- return EFBIG;
- close(fd);
- *retblocks = size64 / blocksize;
- return 0;
- }
-#endif
-
-#ifdef BLKGETSIZE
- if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
- close(fd);
- *retblocks = size / (blocksize / 512);
- return 0;
- }
-#endif
-
-#ifdef FDGETPRM
- if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) {
- close(fd);
- *retblocks = this_floppy.size / (blocksize / 512);
- return 0;
- }
-#endif
-
-#ifdef HAVE_SYS_DISKLABEL_H
-#if defined(DIOCGMEDIASIZE)
- {
- off_t ms;
- u_int bs;
- if (ioctl(fd, DIOCGMEDIASIZE, &ms) >= 0) {
- close(fd);
- *retblocks = ms / blocksize;
- return 0;
- }
- }
-#elif defined(DIOCGDINFO)
- /* old disklabel interface */
- part = strlen(file) - 1;
- if (part >= 0) {
- ch = file[part];
- if (isdigit(ch))
- part = 0;
- else if (ch >= 'a' && ch <= 'h')
- part = ch - 'a';
- else
- part = -1;
- }
- if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
- pp = &lab.d_partitions[part];
- if (pp->p_size) {
- close(fd);
- *retblocks = pp->p_size / (blocksize / 512);
- return 0;
- }
- }
-#endif /* defined(DIOCG*) */
-#endif /* HAVE_SYS_DISKLABEL_H */
-
- /*
- * OK, we couldn't figure it out by using a specialized ioctl,
- * which is generally the best way. So do binary search to
- * find the size of the partition.
- */
- low = 0;
- for (high = 1024; valid_offset (fd, high); high *= 2)
- low = high;
- while (low < high - 1)
- {
- const ext2_loff_t mid = (low + high) / 2;
-
- if (valid_offset (fd, mid))
- low = mid;
- else
- high = mid;
- }
- valid_offset (fd, 0);
- close(fd);
- size64 = low + 1;
- if ((sizeof(*retblocks) < sizeof(unsigned long long))
- && ((size64 / blocksize) > 0xFFFFFFFF))
- return EFBIG;
- *retblocks = size64 / blocksize;
- return 0;
-}
-
-#endif /* WIN32 */
-
-#ifdef DEBUG
-int main(int argc, char **argv)
-{
- blk_t blocks;
- int retval;
-
- if (argc < 2) {
- fprintf(stderr, "Usage: %s device\n", argv[0]);
- exit(1);
- }
-
- retval = ext2fs_get_device_size(argv[1], 1024, &blocks);
- if (retval) {
- com_err(argv[0], retval,
- "while calling ext2fs_get_device_size");
- exit(1);
- }
- printf("Device %s has %d 1k blocks.\n", argv[1], blocks);
- exit(0);
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/icount.c b/release/src/router/busybox/e2fsprogs/ext2fs/icount.c
deleted file mode 100644
index 7ab5f51f48..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/icount.c
+++ /dev/null
@@ -1,467 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * icount.c --- an efficient inode count abstraction
- *
- * Copyright (C) 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <string.h>
-#include <stdio.h>
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * The data storage strategy used by icount relies on the observation
- * that most inode counts are either zero (for non-allocated inodes),
- * one (for most files), and only a few that are two or more
- * (directories and files that are linked to more than one directory).
- *
- * Also, e2fsck tends to load the icount data sequentially.
- *
- * So, we use an inode bitmap to indicate which inodes have a count of
- * one, and then use a sorted list to store the counts for inodes
- * which are greater than one.
- *
- * We also use an optional bitmap to indicate which inodes are already
- * in the sorted list, to speed up the use of this abstraction by
- * e2fsck's pass 2. Pass 2 increments inode counts as it finds them,
- * so this extra bitmap avoids searching the sorted list to see if a
- * particular inode is on the sorted list already.
- */
-
-struct ext2_icount_el {
- ext2_ino_t ino;
- __u16 count;
-};
-
-struct ext2_icount {
- errcode_t magic;
- ext2fs_inode_bitmap single;
- ext2fs_inode_bitmap multiple;
- ext2_ino_t count;
- ext2_ino_t size;
- ext2_ino_t num_inodes;
- ext2_ino_t cursor;
- struct ext2_icount_el *list;
-};
-
-void ext2fs_free_icount(ext2_icount_t icount)
-{
- if (!icount)
- return;
-
- icount->magic = 0;
- ext2fs_free_mem(&icount->list);
- ext2fs_free_inode_bitmap(icount->single);
- ext2fs_free_inode_bitmap(icount->multiple);
- ext2fs_free_mem(&icount);
-}
-
-errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, unsigned int size,
- ext2_icount_t hint, ext2_icount_t *ret)
-{
- ext2_icount_t icount;
- errcode_t retval;
- size_t bytes;
- ext2_ino_t i;
-
- if (hint) {
- EXT2_CHECK_MAGIC(hint, EXT2_ET_MAGIC_ICOUNT);
- if (hint->size > size)
- size = (size_t) hint->size;
- }
-
- retval = ext2fs_get_mem(sizeof(struct ext2_icount), &icount);
- if (retval)
- return retval;
- memset(icount, 0, sizeof(struct ext2_icount));
-
- retval = ext2fs_allocate_inode_bitmap(fs, 0,
- &icount->single);
- if (retval)
- goto errout;
-
- if (flags & EXT2_ICOUNT_OPT_INCREMENT) {
- retval = ext2fs_allocate_inode_bitmap(fs, 0,
- &icount->multiple);
- if (retval)
- goto errout;
- } else
- icount->multiple = 0;
-
- if (size) {
- icount->size = size;
- } else {
- /*
- * Figure out how many special case inode counts we will
- * have. We know we will need one for each directory;
- * we also need to reserve some extra room for file links
- */
- retval = ext2fs_get_num_dirs(fs, &icount->size);
- if (retval)
- goto errout;
- icount->size += fs->super->s_inodes_count / 50;
- }
-
- bytes = (size_t) (icount->size * sizeof(struct ext2_icount_el));
- retval = ext2fs_get_mem(bytes, &icount->list);
- if (retval)
- goto errout;
- memset(icount->list, 0, bytes);
-
- icount->magic = EXT2_ET_MAGIC_ICOUNT;
- icount->count = 0;
- icount->cursor = 0;
- icount->num_inodes = fs->super->s_inodes_count;
-
- /*
- * Populate the sorted list with those entries which were
- * found in the hint icount (since those are ones which will
- * likely need to be in the sorted list this time around).
- */
- if (hint) {
- for (i=0; i < hint->count; i++)
- icount->list[i].ino = hint->list[i].ino;
- icount->count = hint->count;
- }
-
- *ret = icount;
- return 0;
-
-errout:
- ext2fs_free_icount(icount);
- return retval;
-}
-
-errcode_t ext2fs_create_icount(ext2_filsys fs, int flags,
- unsigned int size,
- ext2_icount_t *ret)
-{
- return ext2fs_create_icount2(fs, flags, size, 0, ret);
-}
-
-/*
- * insert_icount_el() --- Insert a new entry into the sorted list at a
- * specified position.
- */
-static struct ext2_icount_el *insert_icount_el(ext2_icount_t icount,
- ext2_ino_t ino, int pos)
-{
- struct ext2_icount_el *el;
- errcode_t retval;
- ext2_ino_t new_size = 0;
- int num;
-
- if (icount->count >= icount->size) {
- if (icount->count) {
- new_size = icount->list[(unsigned)icount->count-1].ino;
- new_size = (ext2_ino_t) (icount->count *
- ((float) icount->num_inodes / new_size));
- }
- if (new_size < (icount->size + 100))
- new_size = icount->size + 100;
- retval = ext2fs_resize_mem((size_t) icount->size *
- sizeof(struct ext2_icount_el),
- (size_t) new_size *
- sizeof(struct ext2_icount_el),
- &icount->list);
- if (retval)
- return 0;
- icount->size = new_size;
- }
- num = (int) icount->count - pos;
- if (num < 0)
- return 0; /* should never happen */
- if (num) {
- memmove(&icount->list[pos+1], &icount->list[pos],
- sizeof(struct ext2_icount_el) * num);
- }
- icount->count++;
- el = &icount->list[pos];
- el->count = 0;
- el->ino = ino;
- return el;
-}
-
-/*
- * get_icount_el() --- given an inode number, try to find icount
- * information in the sorted list. If the create flag is set,
- * and we can't find an entry, create one in the sorted list.
- */
-static struct ext2_icount_el *get_icount_el(ext2_icount_t icount,
- ext2_ino_t ino, int create)
-{
- float range;
- int low, high, mid;
- ext2_ino_t lowval, highval;
-
- if (!icount || !icount->list)
- return 0;
-
- if (create && ((icount->count == 0) ||
- (ino > icount->list[(unsigned)icount->count-1].ino))) {
- return insert_icount_el(icount, ino, (unsigned) icount->count);
- }
- if (icount->count == 0)
- return 0;
-
- if (icount->cursor >= icount->count)
- icount->cursor = 0;
- if (ino == icount->list[icount->cursor].ino)
- return &icount->list[icount->cursor++];
- low = 0;
- high = (int) icount->count-1;
- while (low <= high) {
- if (low == high)
- mid = low;
- else {
- /* Interpolate for efficiency */
- lowval = icount->list[low].ino;
- highval = icount->list[high].ino;
-
- if (ino < lowval)
- range = 0;
- else if (ino > highval)
- range = 1;
- else
- range = ((float) (ino - lowval)) /
- (highval - lowval);
- mid = low + ((int) (range * (high-low)));
- }
- if (ino == icount->list[mid].ino) {
- icount->cursor = mid+1;
- return &icount->list[mid];
- }
- if (ino < icount->list[mid].ino)
- high = mid-1;
- else
- low = mid+1;
- }
- /*
- * If we need to create a new entry, it should be right at
- * low (where high will be left at low-1).
- */
- if (create)
- return insert_icount_el(icount, ino, low);
- return 0;
-}
-
-errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *out)
-{
- errcode_t ret = 0;
- unsigned int i;
- const char *bad = "bad icount";
-
- EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
-
- if (icount->count > icount->size) {
- fprintf(out, "%s: count > size\n", bad);
- return EXT2_ET_INVALID_ARGUMENT;
- }
- for (i=1; i < icount->count; i++) {
- if (icount->list[i-1].ino >= icount->list[i].ino) {
- fprintf(out, "%s: list[%d].ino=%u, list[%d].ino=%u\n",
- bad, i-1, icount->list[i-1].ino,
- i, icount->list[i].ino);
- ret = EXT2_ET_INVALID_ARGUMENT;
- }
- }
- return ret;
-}
-
-errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, __u16 *ret)
-{
- struct ext2_icount_el *el;
-
- EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
-
- if (!ino || (ino > icount->num_inodes))
- return EXT2_ET_INVALID_ARGUMENT;
-
- if (ext2fs_test_inode_bitmap(icount->single, ino)) {
- *ret = 1;
- return 0;
- }
- if (icount->multiple &&
- !ext2fs_test_inode_bitmap(icount->multiple, ino)) {
- *ret = 0;
- return 0;
- }
- el = get_icount_el(icount, ino, 0);
- if (!el) {
- *ret = 0;
- return 0;
- }
- *ret = el->count;
- return 0;
-}
-
-errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino,
- __u16 *ret)
-{
- struct ext2_icount_el *el;
-
- EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
-
- if (!ino || (ino > icount->num_inodes))
- return EXT2_ET_INVALID_ARGUMENT;
-
- if (ext2fs_test_inode_bitmap(icount->single, ino)) {
- /*
- * If the existing count is 1, then we know there is
- * no entry in the list.
- */
- el = get_icount_el(icount, ino, 1);
- if (!el)
- return EXT2_ET_NO_MEMORY;
- ext2fs_unmark_inode_bitmap(icount->single, ino);
- el->count = 2;
- } else if (icount->multiple) {
- /*
- * The count is either zero or greater than 1; if the
- * inode is set in icount->multiple, then there should
- * be an entry in the list, so find it using
- * get_icount_el().
- */
- if (ext2fs_test_inode_bitmap(icount->multiple, ino)) {
- el = get_icount_el(icount, ino, 1);
- if (!el)
- return EXT2_ET_NO_MEMORY;
- el->count++;
- } else {
- /*
- * The count was zero; mark the single bitmap
- * and return.
- */
- zero_count:
- ext2fs_mark_inode_bitmap(icount->single, ino);
- if (ret)
- *ret = 1;
- return 0;
- }
- } else {
- /*
- * The count is either zero or greater than 1; try to
- * find an entry in the list to determine which.
- */
- el = get_icount_el(icount, ino, 0);
- if (!el) {
- /* No entry means the count was zero */
- goto zero_count;
- }
- el = get_icount_el(icount, ino, 1);
- if (!el)
- return EXT2_ET_NO_MEMORY;
- el->count++;
- }
- if (icount->multiple)
- ext2fs_mark_inode_bitmap(icount->multiple, ino);
- if (ret)
- *ret = el->count;
- return 0;
-}
-
-errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
- __u16 *ret)
-{
- struct ext2_icount_el *el;
-
- if (!ino || (ino > icount->num_inodes))
- return EXT2_ET_INVALID_ARGUMENT;
-
- EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
-
- if (ext2fs_test_inode_bitmap(icount->single, ino)) {
- ext2fs_unmark_inode_bitmap(icount->single, ino);
- if (icount->multiple)
- ext2fs_unmark_inode_bitmap(icount->multiple, ino);
- else {
- el = get_icount_el(icount, ino, 0);
- if (el)
- el->count = 0;
- }
- if (ret)
- *ret = 0;
- return 0;
- }
-
- if (icount->multiple &&
- !ext2fs_test_inode_bitmap(icount->multiple, ino))
- return EXT2_ET_INVALID_ARGUMENT;
-
- el = get_icount_el(icount, ino, 0);
- if (!el || el->count == 0)
- return EXT2_ET_INVALID_ARGUMENT;
-
- el->count--;
- if (el->count == 1)
- ext2fs_mark_inode_bitmap(icount->single, ino);
- if ((el->count == 0) && icount->multiple)
- ext2fs_unmark_inode_bitmap(icount->multiple, ino);
-
- if (ret)
- *ret = el->count;
- return 0;
-}
-
-errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
- __u16 count)
-{
- struct ext2_icount_el *el;
-
- if (!ino || (ino > icount->num_inodes))
- return EXT2_ET_INVALID_ARGUMENT;
-
- EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
-
- if (count == 1) {
- ext2fs_mark_inode_bitmap(icount->single, ino);
- if (icount->multiple)
- ext2fs_unmark_inode_bitmap(icount->multiple, ino);
- return 0;
- }
- if (count == 0) {
- ext2fs_unmark_inode_bitmap(icount->single, ino);
- if (icount->multiple) {
- /*
- * If the icount->multiple bitmap is enabled,
- * we can just clear both bitmaps and we're done
- */
- ext2fs_unmark_inode_bitmap(icount->multiple, ino);
- } else {
- el = get_icount_el(icount, ino, 0);
- if (el)
- el->count = 0;
- }
- return 0;
- }
-
- /*
- * Get the icount element
- */
- el = get_icount_el(icount, ino, 1);
- if (!el)
- return EXT2_ET_NO_MEMORY;
- el->count = count;
- ext2fs_unmark_inode_bitmap(icount->single, ino);
- if (icount->multiple)
- ext2fs_mark_inode_bitmap(icount->multiple, ino);
- return 0;
-}
-
-ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount)
-{
- if (!icount || icount->magic != EXT2_ET_MAGIC_ICOUNT)
- return 0;
-
- return icount->size;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/imager.c b/release/src/router/busybox/e2fsprogs/ext2fs/imager.c
deleted file mode 100644
index 0f9cfcfafb..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/imager.c
+++ /dev/null
@@ -1,377 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * image.c --- writes out the critical parts of the filesystem as a
- * flat file.
- *
- * Copyright (C) 2000 Theodore Ts'o.
- *
- * Note: this uses the POSIX IO interfaces, unlike most of the other
- * functions in this library. So sue me.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-#ifndef HAVE_TYPE_SSIZE_T
-typedef int ssize_t;
-#endif
-
-/*
- * This function returns 1 if the specified block is all zeros
- */
-static int check_zero_block(char *buf, int blocksize)
-{
- char *cp = buf;
- int left = blocksize;
-
- while (left > 0) {
- if (*cp++)
- return 0;
- left--;
- }
- return 1;
-}
-
-/*
- * Write the inode table out as a single block.
- */
-#define BUF_BLOCKS 32
-
-errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags)
-{
- unsigned int group, left, c, d;
- char *buf, *cp;
- blk_t blk;
- ssize_t actual;
- errcode_t retval;
-
- buf = xmalloc(fs->blocksize * BUF_BLOCKS);
-
- for (group = 0; group < fs->group_desc_count; group++) {
- blk = fs->group_desc[(unsigned)group].bg_inode_table;
- if (!blk)
- return EXT2_ET_MISSING_INODE_TABLE;
- left = fs->inode_blocks_per_group;
- while (left) {
- c = BUF_BLOCKS;
- if (c > left)
- c = left;
- retval = io_channel_read_blk(fs->io, blk, c, buf);
- if (retval)
- goto errout;
- cp = buf;
- while (c) {
- if (!(flags & IMAGER_FLAG_SPARSEWRITE)) {
- d = c;
- goto skip_sparse;
- }
- /* Skip zero blocks */
- if (check_zero_block(cp, fs->blocksize)) {
- c--;
- blk++;
- left--;
- cp += fs->blocksize;
- lseek(fd, fs->blocksize, SEEK_CUR);
- continue;
- }
- /* Find non-zero blocks */
- for (d=1; d < c; d++) {
- if (check_zero_block(cp + d*fs->blocksize, fs->blocksize))
- break;
- }
- skip_sparse:
- actual = write(fd, cp, fs->blocksize * d);
- if (actual == -1) {
- retval = errno;
- goto errout;
- }
- if (actual != (ssize_t) (fs->blocksize * d)) {
- retval = EXT2_ET_SHORT_WRITE;
- goto errout;
- }
- blk += d;
- left -= d;
- cp += fs->blocksize * d;
- c -= d;
- }
- }
- }
- retval = 0;
-
-errout:
- free(buf);
- return retval;
-}
-
-/*
- * Read in the inode table and stuff it into place
- */
-errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd,
- int flags EXT2FS_ATTR((unused)))
-{
- unsigned int group, c, left;
- char *buf;
- blk_t blk;
- ssize_t actual;
- errcode_t retval;
-
- buf = xmalloc(fs->blocksize * BUF_BLOCKS);
-
- for (group = 0; group < fs->group_desc_count; group++) {
- blk = fs->group_desc[(unsigned)group].bg_inode_table;
- if (!blk) {
- retval = EXT2_ET_MISSING_INODE_TABLE;
- goto errout;
- }
- left = fs->inode_blocks_per_group;
- while (left) {
- c = BUF_BLOCKS;
- if (c > left)
- c = left;
- actual = read(fd, buf, fs->blocksize * c);
- if (actual == -1) {
- retval = errno;
- goto errout;
- }
- if (actual != (ssize_t) (fs->blocksize * c)) {
- retval = EXT2_ET_SHORT_READ;
- goto errout;
- }
- retval = io_channel_write_blk(fs->io, blk, c, buf);
- if (retval)
- goto errout;
-
- blk += c;
- left -= c;
- }
- }
- retval = ext2fs_flush_icache(fs);
-
-errout:
- free(buf);
- return retval;
-}
-
-/*
- * Write out superblock and group descriptors
- */
-errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd,
- int flags EXT2FS_ATTR((unused)))
-{
- char *buf, *cp;
- ssize_t actual;
- errcode_t retval;
-
- buf = xmalloc(fs->blocksize);
-
- /*
- * Write out the superblock
- */
- memset(buf, 0, fs->blocksize);
- memcpy(buf, fs->super, SUPERBLOCK_SIZE);
- actual = write(fd, buf, fs->blocksize);
- if (actual == -1) {
- retval = errno;
- goto errout;
- }
- if (actual != (ssize_t) fs->blocksize) {
- retval = EXT2_ET_SHORT_WRITE;
- goto errout;
- }
-
- /*
- * Now write out the block group descriptors
- */
- cp = (char *) fs->group_desc;
- actual = write(fd, cp, fs->blocksize * fs->desc_blocks);
- if (actual == -1) {
- retval = errno;
- goto errout;
- }
- if (actual != (ssize_t) (fs->blocksize * fs->desc_blocks)) {
- retval = EXT2_ET_SHORT_WRITE;
- goto errout;
- }
-
- retval = 0;
-
-errout:
- free(buf);
- return retval;
-}
-
-/*
- * Read the superblock and group descriptors and overwrite them.
- */
-errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd,
- int flags EXT2FS_ATTR((unused)))
-{
- char *buf;
- ssize_t actual, size;
- errcode_t retval;
-
- size = fs->blocksize * (fs->group_desc_count + 1);
- buf = xmalloc(size);
-
- /*
- * Read it all in.
- */
- actual = read(fd, buf, size);
- if (actual == -1) {
- retval = errno;
- goto errout;
- }
- if (actual != size) {
- retval = EXT2_ET_SHORT_READ;
- goto errout;
- }
-
- /*
- * Now copy in the superblock and group descriptors
- */
- memcpy(fs->super, buf, SUPERBLOCK_SIZE);
-
- memcpy(fs->group_desc, buf + fs->blocksize,
- fs->blocksize * fs->group_desc_count);
-
- retval = 0;
-
-errout:
- free(buf);
- return retval;
-}
-
-/*
- * Write the block/inode bitmaps.
- */
-errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
-{
- char *ptr;
- int c, size;
- char zero_buf[1024];
- ssize_t actual;
- errcode_t retval;
-
- if (flags & IMAGER_FLAG_INODEMAP) {
- if (!fs->inode_map) {
- retval = ext2fs_read_inode_bitmap(fs);
- if (retval)
- return retval;
- }
- ptr = fs->inode_map->bitmap;
- size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
- } else {
- if (!fs->block_map) {
- retval = ext2fs_read_block_bitmap(fs);
- if (retval)
- return retval;
- }
- ptr = fs->block_map->bitmap;
- size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
- }
- size = size * fs->group_desc_count;
-
- actual = write(fd, ptr, size);
- if (actual == -1) {
- retval = errno;
- goto errout;
- }
- if (actual != size) {
- retval = EXT2_ET_SHORT_WRITE;
- goto errout;
- }
- size = size % fs->blocksize;
- memset(zero_buf, 0, sizeof(zero_buf));
- if (size) {
- size = fs->blocksize - size;
- while (size) {
- c = size;
- if (c > (int) sizeof(zero_buf))
- c = sizeof(zero_buf);
- actual = write(fd, zero_buf, c);
- if (actual == -1) {
- retval = errno;
- goto errout;
- }
- if (actual != c) {
- retval = EXT2_ET_SHORT_WRITE;
- goto errout;
- }
- size -= c;
- }
- }
- retval = 0;
-errout:
- return retval;
-}
-
-
-/*
- * Read the block/inode bitmaps.
- */
-errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
-{
- char *ptr, *buf = NULL;
- int size;
- ssize_t actual;
- errcode_t retval;
-
- if (flags & IMAGER_FLAG_INODEMAP) {
- if (!fs->inode_map) {
- retval = ext2fs_read_inode_bitmap(fs);
- if (retval)
- return retval;
- }
- ptr = fs->inode_map->bitmap;
- size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
- } else {
- if (!fs->block_map) {
- retval = ext2fs_read_block_bitmap(fs);
- if (retval)
- return retval;
- }
- ptr = fs->block_map->bitmap;
- size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
- }
- size = size * fs->group_desc_count;
-
- buf = xmalloc(size);
-
- actual = read(fd, buf, size);
- if (actual == -1) {
- retval = errno;
- goto errout;
- }
- if (actual != size) {
- retval = EXT2_ET_SHORT_WRITE;
- goto errout;
- }
- memcpy(ptr, buf, size);
-
- retval = 0;
-errout:
- free(buf);
- return retval;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/ind_block.c b/release/src/router/busybox/e2fsprogs/ext2fs/ind_block.c
deleted file mode 100644
index a1038300b3..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/ind_block.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * ind_block.c --- indirect block I/O routines
- *
- * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- * 2001, 2002, 2003, 2004, 2005 by Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf)
-{
- errcode_t retval;
-#if BB_BIG_ENDIAN
- blk_t *block_nr;
- int i;
- int limit = fs->blocksize >> 2;
-#endif
-
- if ((fs->flags & EXT2_FLAG_IMAGE_FILE) &&
- (fs->io != fs->image_io))
- memset(buf, 0, fs->blocksize);
- else {
- retval = io_channel_read_blk(fs->io, blk, 1, buf);
- if (retval)
- return retval;
- }
-#if BB_BIG_ENDIAN
- if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_READ)) {
- block_nr = (blk_t *) buf;
- for (i = 0; i < limit; i++, block_nr++)
- *block_nr = ext2fs_swab32(*block_nr);
- }
-#endif
- return 0;
-}
-
-errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf)
-{
-#if BB_BIG_ENDIAN
- blk_t *block_nr;
- int i;
- int limit = fs->blocksize >> 2;
-#endif
-
- if (fs->flags & EXT2_FLAG_IMAGE_FILE)
- return 0;
-
-#if BB_BIG_ENDIAN
- if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_WRITE)) {
- block_nr = (blk_t *) buf;
- for (i = 0; i < limit; i++, block_nr++)
- *block_nr = ext2fs_swab32(*block_nr);
- }
-#endif
- return io_channel_write_blk(fs->io, blk, 1, buf);
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/initialize.c b/release/src/router/busybox/e2fsprogs/ext2fs/initialize.c
deleted file mode 100644
index da2d151375..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/initialize.c
+++ /dev/null
@@ -1,388 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * initialize.c --- initialize a filesystem handle given superblock
- * parameters. Used by mke2fs when initializing a filesystem.
- *
- * Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-#if defined(__linux__) && defined(EXT2_OS_LINUX)
-#define CREATOR_OS EXT2_OS_LINUX
-#else
-#if defined(__GNU__) && defined(EXT2_OS_HURD)
-#define CREATOR_OS EXT2_OS_HURD
-#else
-#if defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD)
-#define CREATOR_OS EXT2_OS_FREEBSD
-#else
-#if defined(LITES) && defined(EXT2_OS_LITES)
-#define CREATOR_OS EXT2_OS_LITES
-#else
-#define CREATOR_OS EXT2_OS_LINUX /* by default */
-#endif /* defined(LITES) && defined(EXT2_OS_LITES) */
-#endif /* defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD) */
-#endif /* defined(__GNU__) && defined(EXT2_OS_HURD) */
-#endif /* defined(__linux__) && defined(EXT2_OS_LINUX) */
-
-/*
- * Note we override the kernel include file's idea of what the default
- * check interval (never) should be. It's a good idea to check at
- * least *occasionally*, specially since servers will never rarely get
- * to reboot, since Linux is so robust these days. :-)
- *
- * 180 days (six months) seems like a good value.
- */
-#ifdef EXT2_DFL_CHECKINTERVAL
-#undef EXT2_DFL_CHECKINTERVAL
-#endif
-#define EXT2_DFL_CHECKINTERVAL (86400L * 180L)
-
-/*
- * Calculate the number of GDT blocks to reserve for online filesystem growth.
- * The absolute maximum number of GDT blocks we can reserve is determined by
- * the number of block pointers that can fit into a single block.
- */
-static int calc_reserved_gdt_blocks(ext2_filsys fs)
-{
- struct ext2_super_block *sb = fs->super;
- unsigned long bpg = sb->s_blocks_per_group;
- unsigned int gdpb = fs->blocksize / sizeof(struct ext2_group_desc);
- unsigned long max_blocks = 0xffffffff;
- unsigned long rsv_groups;
- int rsv_gdb;
-
- /* We set it at 1024x the current filesystem size, or
- * the upper block count limit (2^32), whichever is lower.
- */
- if (sb->s_blocks_count < max_blocks / 1024)
- max_blocks = sb->s_blocks_count * 1024;
- rsv_groups = (max_blocks - sb->s_first_data_block + bpg - 1) / bpg;
- rsv_gdb = (rsv_groups + gdpb - 1) / gdpb - fs->desc_blocks;
- if (rsv_gdb > EXT2_ADDR_PER_BLOCK(sb))
- rsv_gdb = EXT2_ADDR_PER_BLOCK(sb);
-#ifdef RES_GDT_DEBUG
- printf("max_blocks %lu, rsv_groups = %lu, rsv_gdb = %lu\n",
- max_blocks, rsv_groups, rsv_gdb);
-#endif
-
- return rsv_gdb;
-}
-
-errcode_t ext2fs_initialize(const char *name, int flags,
- struct ext2_super_block *param,
- io_manager manager, ext2_filsys *ret_fs)
-{
- ext2_filsys fs;
- errcode_t retval;
- struct ext2_super_block *super;
- int frags_per_block;
- unsigned int rem;
- unsigned int overhead = 0;
- blk_t group_block;
- unsigned int ipg;
- dgrp_t i;
- blk_t numblocks;
- int rsv_gdt;
- char *buf;
-
- if (!param || !param->s_blocks_count)
- return EXT2_ET_INVALID_ARGUMENT;
-
- retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
- if (retval)
- return retval;
-
- memset(fs, 0, sizeof(struct struct_ext2_filsys));
- fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS;
- fs->flags = flags | EXT2_FLAG_RW;
- fs->umask = 022;
-#ifdef WORDS_BIGENDIAN
- fs->flags |= EXT2_FLAG_SWAP_BYTES;
-#endif
- retval = manager->open(name, IO_FLAG_RW, &fs->io);
- if (retval)
- goto cleanup;
- fs->image_io = fs->io;
- fs->io->app_data = fs;
- retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name);
- if (retval)
- goto cleanup;
-
- strcpy(fs->device_name, name);
- retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super);
- if (retval)
- goto cleanup;
- fs->super = super;
-
- memset(super, 0, SUPERBLOCK_SIZE);
-
-#define set_field(field, default) (super->field = param->field ? \
- param->field : (default))
-
- super->s_magic = EXT2_SUPER_MAGIC;
- super->s_state = EXT2_VALID_FS;
-
- set_field(s_log_block_size, 0); /* default blocksize: 1024 bytes */
- set_field(s_log_frag_size, 0); /* default fragsize: 1024 bytes */
- set_field(s_first_data_block, super->s_log_block_size ? 0 : 1);
- set_field(s_max_mnt_count, EXT2_DFL_MAX_MNT_COUNT);
- set_field(s_errors, EXT2_ERRORS_DEFAULT);
- set_field(s_feature_compat, 0);
- set_field(s_feature_incompat, 0);
- set_field(s_feature_ro_compat, 0);
- set_field(s_first_meta_bg, 0);
- if (super->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) {
- retval = EXT2_ET_UNSUPP_FEATURE;
- goto cleanup;
- }
- if (super->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
- retval = EXT2_ET_RO_UNSUPP_FEATURE;
- goto cleanup;
- }
-
- set_field(s_rev_level, EXT2_GOOD_OLD_REV);
- if (super->s_rev_level >= EXT2_DYNAMIC_REV) {
- set_field(s_first_ino, EXT2_GOOD_OLD_FIRST_INO);
- set_field(s_inode_size, EXT2_GOOD_OLD_INODE_SIZE);
- }
-
- set_field(s_checkinterval, EXT2_DFL_CHECKINTERVAL);
- super->s_mkfs_time = super->s_lastcheck = time(NULL);
-
- super->s_creator_os = CREATOR_OS;
-
- fs->blocksize = EXT2_BLOCK_SIZE(super);
- fs->fragsize = EXT2_FRAG_SIZE(super);
- frags_per_block = fs->blocksize / fs->fragsize;
-
- /* default: (fs->blocksize*8) blocks/group, up to 2^16 (GDT limit) */
- set_field(s_blocks_per_group, fs->blocksize * 8);
- if (super->s_blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(super))
- super->s_blocks_per_group = EXT2_MAX_BLOCKS_PER_GROUP(super);
- super->s_frags_per_group = super->s_blocks_per_group * frags_per_block;
-
- super->s_blocks_count = param->s_blocks_count;
- super->s_r_blocks_count = param->s_r_blocks_count;
- if (super->s_r_blocks_count >= param->s_blocks_count) {
- retval = EXT2_ET_INVALID_ARGUMENT;
- goto cleanup;
- }
-
- /*
- * If we're creating an external journal device, we don't need
- * to bother with the rest.
- */
- if (super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
- fs->group_desc_count = 0;
- ext2fs_mark_super_dirty(fs);
- *ret_fs = fs;
- return 0;
- }
-
-retry:
- fs->group_desc_count = (super->s_blocks_count -
- super->s_first_data_block +
- EXT2_BLOCKS_PER_GROUP(super) - 1)
- / EXT2_BLOCKS_PER_GROUP(super);
- if (fs->group_desc_count == 0) {
- retval = EXT2_ET_TOOSMALL;
- goto cleanup;
- }
- fs->desc_blocks = (fs->group_desc_count +
- EXT2_DESC_PER_BLOCK(super) - 1)
- / EXT2_DESC_PER_BLOCK(super);
-
- i = fs->blocksize >= 4096 ? 1 : 4096 / fs->blocksize;
- set_field(s_inodes_count, super->s_blocks_count / i);
-
- /*
- * Make sure we have at least EXT2_FIRST_INO + 1 inodes, so
- * that we have enough inodes for the filesystem(!)
- */
- if (super->s_inodes_count < EXT2_FIRST_INODE(super)+1)
- super->s_inodes_count = EXT2_FIRST_INODE(super)+1;
-
- /*
- * There should be at least as many inodes as the user
- * requested. Figure out how many inodes per group that
- * should be. But make sure that we don't allocate more than
- * one bitmap's worth of inodes each group.
- */
- ipg = (super->s_inodes_count + fs->group_desc_count - 1) /
- fs->group_desc_count;
- if (ipg > fs->blocksize * 8) {
- if (super->s_blocks_per_group >= 256) {
- /* Try again with slightly different parameters */
- super->s_blocks_per_group -= 8;
- super->s_blocks_count = param->s_blocks_count;
- super->s_frags_per_group = super->s_blocks_per_group *
- frags_per_block;
- goto retry;
- } else
- return EXT2_ET_TOO_MANY_INODES;
- }
-
- if (ipg > (unsigned) EXT2_MAX_INODES_PER_GROUP(super))
- ipg = EXT2_MAX_INODES_PER_GROUP(super);
-
- super->s_inodes_per_group = ipg;
- if (super->s_inodes_count > ipg * fs->group_desc_count)
- super->s_inodes_count = ipg * fs->group_desc_count;
-
- /*
- * Make sure the number of inodes per group completely fills
- * the inode table blocks in the descriptor. If not, add some
- * additional inodes/group. Waste not, want not...
- */
- fs->inode_blocks_per_group = (((super->s_inodes_per_group *
- EXT2_INODE_SIZE(super)) +
- EXT2_BLOCK_SIZE(super) - 1) /
- EXT2_BLOCK_SIZE(super));
- super->s_inodes_per_group = ((fs->inode_blocks_per_group *
- EXT2_BLOCK_SIZE(super)) /
- EXT2_INODE_SIZE(super));
- /*
- * Finally, make sure the number of inodes per group is a
- * multiple of 8. This is needed to simplify the bitmap
- * splicing code.
- */
- super->s_inodes_per_group &= ~7;
- fs->inode_blocks_per_group = (((super->s_inodes_per_group *
- EXT2_INODE_SIZE(super)) +
- EXT2_BLOCK_SIZE(super) - 1) /
- EXT2_BLOCK_SIZE(super));
-
- /*
- * adjust inode count to reflect the adjusted inodes_per_group
- */
- super->s_inodes_count = super->s_inodes_per_group *
- fs->group_desc_count;
- super->s_free_inodes_count = super->s_inodes_count;
-
- /*
- * check the number of reserved group descriptor table blocks
- */
- if (super->s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INO)
- rsv_gdt = calc_reserved_gdt_blocks(fs);
- else
- rsv_gdt = 0;
- set_field(s_reserved_gdt_blocks, rsv_gdt);
- if (super->s_reserved_gdt_blocks > EXT2_ADDR_PER_BLOCK(super)) {
- retval = EXT2_ET_RES_GDT_BLOCKS;
- goto cleanup;
- }
-
- /*
- * Overhead is the number of bookkeeping blocks per group. It
- * includes the superblock backup, the group descriptor
- * backups, the inode bitmap, the block bitmap, and the inode
- * table.
- */
-
- overhead = (int) (2 + fs->inode_blocks_per_group);
-
- if (ext2fs_bg_has_super(fs, fs->group_desc_count - 1))
- overhead += 1 + fs->desc_blocks + super->s_reserved_gdt_blocks;
-
- /* This can only happen if the user requested too many inodes */
- if (overhead > super->s_blocks_per_group)
- return EXT2_ET_TOO_MANY_INODES;
-
- /*
- * See if the last group is big enough to support the
- * necessary data structures. If not, we need to get rid of
- * it.
- */
- rem = ((super->s_blocks_count - super->s_first_data_block) %
- super->s_blocks_per_group);
- if ((fs->group_desc_count == 1) && rem && (rem < overhead))
- return EXT2_ET_TOOSMALL;
- if (rem && (rem < overhead+50)) {
- super->s_blocks_count -= rem;
- goto retry;
- }
-
- /*
- * At this point we know how big the filesystem will be. So
- * we can do any and all allocations that depend on the block
- * count.
- */
-
- retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
- if (retval)
- goto cleanup;
-
- sprintf(buf, "block bitmap for %s", fs->device_name);
- retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
- if (retval)
- goto cleanup;
-
- sprintf(buf, "inode bitmap for %s", fs->device_name);
- retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
- if (retval)
- goto cleanup;
-
- ext2fs_free_mem(&buf);
-
- retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize,
- &fs->group_desc);
- if (retval)
- goto cleanup;
-
- memset(fs->group_desc, 0, (size_t) fs->desc_blocks * fs->blocksize);
-
- /*
- * Reserve the superblock and group descriptors for each
- * group, and fill in the correct group statistics for group.
- * Note that although the block bitmap, inode bitmap, and
- * inode table have not been allocated (and in fact won't be
- * by this routine), they are accounted for nevertheless.
- */
- group_block = super->s_first_data_block;
- super->s_free_blocks_count = 0;
- for (i = 0; i < fs->group_desc_count; i++) {
- numblocks = ext2fs_reserve_super_and_bgd(fs, i, fs->block_map);
-
- super->s_free_blocks_count += numblocks;
- fs->group_desc[i].bg_free_blocks_count = numblocks;
- fs->group_desc[i].bg_free_inodes_count =
- fs->super->s_inodes_per_group;
- fs->group_desc[i].bg_used_dirs_count = 0;
-
- group_block += super->s_blocks_per_group;
- }
-
- ext2fs_mark_super_dirty(fs);
- ext2fs_mark_bb_dirty(fs);
- ext2fs_mark_ib_dirty(fs);
-
- io_channel_set_blksize(fs->io, fs->blocksize);
-
- *ret_fs = fs;
- return 0;
-cleanup:
- ext2fs_free(fs);
- return retval;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/inline.c b/release/src/router/busybox/e2fsprogs/ext2fs/inline.c
deleted file mode 100644
index 7457b93962..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/inline.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * inline.c --- Includes the inlined functions defined in the header
- * files as standalone functions, in case the application program
- * is compiled with inlining turned off.
- *
- * Copyright (C) 1993, 1994 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#define INCLUDE_INLINE_FUNCS
-#include "ext2fs.h"
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/inode.c b/release/src/router/busybox/e2fsprogs/ext2fs/inode.c
deleted file mode 100644
index 7a1d5c94bb..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/inode.c
+++ /dev/null
@@ -1,766 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * inode.c --- utility routines to read and write inodes
- *
- * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fsP.h"
-#include "e2image.h"
-
-struct ext2_struct_inode_scan {
- errcode_t magic;
- ext2_filsys fs;
- ext2_ino_t current_inode;
- blk_t current_block;
- dgrp_t current_group;
- ext2_ino_t inodes_left;
- blk_t blocks_left;
- dgrp_t groups_left;
- blk_t inode_buffer_blocks;
- char * inode_buffer;
- int inode_size;
- char * ptr;
- int bytes_left;
- char *temp_buffer;
- errcode_t (*done_group)(ext2_filsys fs,
- dgrp_t group,
- void * priv_data);
- void * done_group_data;
- int bad_block_ptr;
- int scan_flags;
- int reserved[6];
-};
-
-/*
- * This routine flushes the icache, if it exists.
- */
-errcode_t ext2fs_flush_icache(ext2_filsys fs)
-{
- int i;
-
- if (!fs->icache)
- return 0;
-
- for (i=0; i < fs->icache->cache_size; i++)
- fs->icache->cache[i].ino = 0;
-
- fs->icache->buffer_blk = 0;
- return 0;
-}
-
-static errcode_t create_icache(ext2_filsys fs)
-{
- errcode_t retval;
-
- if (fs->icache)
- return 0;
- retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache), &fs->icache);
- if (retval)
- return retval;
-
- memset(fs->icache, 0, sizeof(struct ext2_inode_cache));
- retval = ext2fs_get_mem(fs->blocksize, &fs->icache->buffer);
- if (retval) {
- ext2fs_free_mem(&fs->icache);
- return retval;
- }
- fs->icache->buffer_blk = 0;
- fs->icache->cache_last = -1;
- fs->icache->cache_size = 4;
- fs->icache->refcount = 1;
- retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache_ent)
- * fs->icache->cache_size,
- &fs->icache->cache);
- if (retval) {
- ext2fs_free_mem(&fs->icache->buffer);
- ext2fs_free_mem(&fs->icache);
- return retval;
- }
- ext2fs_flush_icache(fs);
- return 0;
-}
-
-errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
- ext2_inode_scan *ret_scan)
-{
- ext2_inode_scan scan;
- errcode_t retval;
- errcode_t (*save_get_blocks)(ext2_filsys f, ext2_ino_t ino, blk_t *blocks);
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- /*
- * If fs->badblocks isn't set, then set it --- since the inode
- * scanning functions require it.
- */
- if (fs->badblocks == 0) {
- /*
- * Temporarly save fs->get_blocks and set it to zero,
- * for compatibility with old e2fsck's.
- */
- save_get_blocks = fs->get_blocks;
- fs->get_blocks = 0;
- retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
- if (retval) {
- ext2fs_badblocks_list_free(fs->badblocks);
- fs->badblocks = 0;
- }
- fs->get_blocks = save_get_blocks;
- }
-
- retval = ext2fs_get_mem(sizeof(struct ext2_struct_inode_scan), &scan);
- if (retval)
- return retval;
- memset(scan, 0, sizeof(struct ext2_struct_inode_scan));
-
- scan->magic = EXT2_ET_MAGIC_INODE_SCAN;
- scan->fs = fs;
- scan->inode_size = EXT2_INODE_SIZE(fs->super);
- scan->bytes_left = 0;
- scan->current_group = 0;
- scan->groups_left = fs->group_desc_count - 1;
- scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : 8;
- scan->current_block = scan->fs->
- group_desc[scan->current_group].bg_inode_table;
- scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
- scan->blocks_left = scan->fs->inode_blocks_per_group;
- retval = ext2fs_get_mem((size_t) (scan->inode_buffer_blocks *
- fs->blocksize),
- &scan->inode_buffer);
- scan->done_group = 0;
- scan->done_group_data = 0;
- scan->bad_block_ptr = 0;
- if (retval) {
- ext2fs_free_mem(&scan);
- return retval;
- }
- retval = ext2fs_get_mem(scan->inode_size, &scan->temp_buffer);
- if (retval) {
- ext2fs_free_mem(&scan->inode_buffer);
- ext2fs_free_mem(&scan);
- return retval;
- }
- if (scan->fs->badblocks && scan->fs->badblocks->num)
- scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS;
- *ret_scan = scan;
- return 0;
-}
-
-void ext2fs_close_inode_scan(ext2_inode_scan scan)
-{
- if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
- return;
-
- ext2fs_free_mem(&scan->inode_buffer);
- scan->inode_buffer = NULL;
- ext2fs_free_mem(&scan->temp_buffer);
- scan->temp_buffer = NULL;
- ext2fs_free_mem(&scan);
-}
-
-void ext2fs_set_inode_callback(ext2_inode_scan scan,
- errcode_t (*done_group)(ext2_filsys fs,
- dgrp_t group,
- void * priv_data),
- void *done_group_data)
-{
- if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
- return;
-
- scan->done_group = done_group;
- scan->done_group_data = done_group_data;
-}
-
-int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags,
- int clear_flags)
-{
- int old_flags;
-
- if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
- return 0;
-
- old_flags = scan->scan_flags;
- scan->scan_flags &= ~clear_flags;
- scan->scan_flags |= set_flags;
- return old_flags;
-}
-
-/*
- * This function is called by ext2fs_get_next_inode when it needs to
- * get ready to read in a new blockgroup.
- */
-static errcode_t get_next_blockgroup(ext2_inode_scan scan)
-{
- scan->current_group++;
- scan->groups_left--;
-
- scan->current_block = scan->fs->
- group_desc[scan->current_group].bg_inode_table;
-
- scan->current_inode = scan->current_group *
- EXT2_INODES_PER_GROUP(scan->fs->super);
-
- scan->bytes_left = 0;
- scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
- scan->blocks_left = scan->fs->inode_blocks_per_group;
- return 0;
-}
-
-errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,
- int group)
-{
- scan->current_group = group - 1;
- scan->groups_left = scan->fs->group_desc_count - group;
- return get_next_blockgroup(scan);
-}
-
-/*
- * This function is called by get_next_blocks() to check for bad
- * blocks in the inode table.
- *
- * This function assumes that badblocks_list->list is sorted in
- * increasing order.
- */
-static errcode_t check_for_inode_bad_blocks(ext2_inode_scan scan,
- blk_t *num_blocks)
-{
- blk_t blk = scan->current_block;
- badblocks_list bb = scan->fs->badblocks;
-
- /*
- * If the inode table is missing, then obviously there are no
- * bad blocks. :-)
- */
- if (blk == 0)
- return 0;
-
- /*
- * If the current block is greater than the bad block listed
- * in the bad block list, then advance the pointer until this
- * is no longer the case. If we run out of bad blocks, then
- * we don't need to do any more checking!
- */
- while (blk > bb->list[scan->bad_block_ptr]) {
- if (++scan->bad_block_ptr >= bb->num) {
- scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
- return 0;
- }
- }
-
- /*
- * If the current block is equal to the bad block listed in
- * the bad block list, then handle that one block specially.
- * (We could try to handle runs of bad blocks, but that
- * only increases CPU efficiency by a small amount, at the
- * expense of a huge expense of code complexity, and for an
- * uncommon case at that.)
- */
- if (blk == bb->list[scan->bad_block_ptr]) {
- scan->scan_flags |= EXT2_SF_BAD_INODE_BLK;
- *num_blocks = 1;
- if (++scan->bad_block_ptr >= bb->num)
- scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
- return 0;
- }
-
- /*
- * If there is a bad block in the range that we're about to
- * read in, adjust the number of blocks to read so that we we
- * don't read in the bad block. (Then the next block to read
- * will be the bad block, which is handled in the above case.)
- */
- if ((blk + *num_blocks) > bb->list[scan->bad_block_ptr])
- *num_blocks = (int) (bb->list[scan->bad_block_ptr] - blk);
-
- return 0;
-}
-
-/*
- * This function is called by ext2fs_get_next_inode when it needs to
- * read in more blocks from the current blockgroup's inode table.
- */
-static errcode_t get_next_blocks(ext2_inode_scan scan)
-{
- blk_t num_blocks;
- errcode_t retval;
-
- /*
- * Figure out how many blocks to read; we read at most
- * inode_buffer_blocks, and perhaps less if there aren't that
- * many blocks left to read.
- */
- num_blocks = scan->inode_buffer_blocks;
- if (num_blocks > scan->blocks_left)
- num_blocks = scan->blocks_left;
-
- /*
- * If the past block "read" was a bad block, then mark the
- * left-over extra bytes as also being bad.
- */
- if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) {
- if (scan->bytes_left)
- scan->scan_flags |= EXT2_SF_BAD_EXTRA_BYTES;
- scan->scan_flags &= ~EXT2_SF_BAD_INODE_BLK;
- }
-
- /*
- * Do inode bad block processing, if necessary.
- */
- if (scan->scan_flags & EXT2_SF_CHK_BADBLOCKS) {
- retval = check_for_inode_bad_blocks(scan, &num_blocks);
- if (retval)
- return retval;
- }
-
- if ((scan->scan_flags & EXT2_SF_BAD_INODE_BLK) ||
- (scan->current_block == 0)) {
- memset(scan->inode_buffer, 0,
- (size_t) num_blocks * scan->fs->blocksize);
- } else {
- retval = io_channel_read_blk(scan->fs->io,
- scan->current_block,
- (int) num_blocks,
- scan->inode_buffer);
- if (retval)
- return EXT2_ET_NEXT_INODE_READ;
- }
- scan->ptr = scan->inode_buffer;
- scan->bytes_left = num_blocks * scan->fs->blocksize;
-
- scan->blocks_left -= num_blocks;
- if (scan->current_block)
- scan->current_block += num_blocks;
- return 0;
-}
-
-errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, ext2_ino_t *ino,
- struct ext2_inode *inode, int bufsize)
-{
- errcode_t retval;
- int extra_bytes = 0;
-
- EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN);
-
- /*
- * Do we need to start reading a new block group?
- */
- if (scan->inodes_left <= 0) {
- force_new_group:
- if (scan->done_group) {
- retval = (scan->done_group)
- (scan->fs, scan->current_group,
- scan->done_group_data);
- if (retval)
- return retval;
- }
- if (scan->groups_left <= 0) {
- *ino = 0;
- return 0;
- }
- retval = get_next_blockgroup(scan);
- if (retval)
- return retval;
- }
- /*
- * This is done outside the above if statement so that the
- * check can be done for block group #0.
- */
- if (scan->current_block == 0) {
- if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) {
- goto force_new_group;
- } else
- return EXT2_ET_MISSING_INODE_TABLE;
- }
-
-
- /*
- * Have we run out of space in the inode buffer? If so, we
- * need to read in more blocks.
- */
- if (scan->bytes_left < scan->inode_size) {
- memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left);
- extra_bytes = scan->bytes_left;
-
- retval = get_next_blocks(scan);
- if (retval)
- return retval;
-#if 0
- /*
- * XXX test Need check for used inode somehow.
- * (Note: this is hard.)
- */
- if (is_empty_scan(scan))
- goto force_new_group;
-#endif
- }
-
- retval = 0;
- if (extra_bytes) {
- memcpy(scan->temp_buffer+extra_bytes, scan->ptr,
- scan->inode_size - extra_bytes);
- scan->ptr += scan->inode_size - extra_bytes;
- scan->bytes_left -= scan->inode_size - extra_bytes;
-
-#if BB_BIG_ENDIAN
- if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
- ext2fs_swap_inode_full(scan->fs,
- (struct ext2_inode_large *) inode,
- (struct ext2_inode_large *) scan->temp_buffer,
- 0, bufsize);
- else
-#endif
- *inode = *((struct ext2_inode *) scan->temp_buffer);
- if (scan->scan_flags & EXT2_SF_BAD_EXTRA_BYTES)
- retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
- scan->scan_flags &= ~EXT2_SF_BAD_EXTRA_BYTES;
- } else {
-#if BB_BIG_ENDIAN
- if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
- ext2fs_swap_inode_full(scan->fs,
- (struct ext2_inode_large *) inode,
- (struct ext2_inode_large *) scan->ptr,
- 0, bufsize);
- else
-#endif
- memcpy(inode, scan->ptr, bufsize);
- scan->ptr += scan->inode_size;
- scan->bytes_left -= scan->inode_size;
- if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK)
- retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
- }
-
- scan->inodes_left--;
- scan->current_inode++;
- *ino = scan->current_inode;
- return retval;
-}
-
-errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino,
- struct ext2_inode *inode)
-{
- return ext2fs_get_next_inode_full(scan, ino, inode,
- sizeof(struct ext2_inode));
-}
-
-/*
- * Functions to read and write a single inode.
- */
-errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode * inode, int bufsize)
-{
- unsigned long group, block, block_nr, offset;
- char *ptr;
- errcode_t retval;
- int clen, i, inodes_per_block, length;
- io_channel io;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- /* Check to see if user has an override function */
- if (fs->read_inode) {
- retval = (fs->read_inode)(fs, ino, inode);
- if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
- return retval;
- }
- /* Create inode cache if not present */
- if (!fs->icache) {
- retval = create_icache(fs);
- if (retval)
- return retval;
- }
- /* Check to see if it's in the inode cache */
- if (bufsize == sizeof(struct ext2_inode)) {
- /* only old good inode can be retrieve from the cache */
- for (i=0; i < fs->icache->cache_size; i++) {
- if (fs->icache->cache[i].ino == ino) {
- *inode = fs->icache->cache[i].inode;
- return 0;
- }
- }
- }
- if ((ino == 0) || (ino > fs->super->s_inodes_count))
- return EXT2_ET_BAD_INODE_NUM;
- if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
- inodes_per_block = fs->blocksize / EXT2_INODE_SIZE(fs->super);
- block_nr = fs->image_header->offset_inode / fs->blocksize;
- block_nr += (ino - 1) / inodes_per_block;
- offset = ((ino - 1) % inodes_per_block) *
- EXT2_INODE_SIZE(fs->super);
- io = fs->image_io;
- } else {
- group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
- offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
- EXT2_INODE_SIZE(fs->super);
- block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
- if (!fs->group_desc[(unsigned)group].bg_inode_table)
- return EXT2_ET_MISSING_INODE_TABLE;
- block_nr = fs->group_desc[(unsigned)group].bg_inode_table +
- block;
- io = fs->io;
- }
- offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
-
- length = EXT2_INODE_SIZE(fs->super);
- if (bufsize < length)
- length = bufsize;
-
- ptr = (char *) inode;
- while (length) {
- clen = length;
- if ((offset + length) > fs->blocksize)
- clen = fs->blocksize - offset;
-
- if (block_nr != fs->icache->buffer_blk) {
- retval = io_channel_read_blk(io, block_nr, 1,
- fs->icache->buffer);
- if (retval)
- return retval;
- fs->icache->buffer_blk = block_nr;
- }
-
- memcpy(ptr, ((char *) fs->icache->buffer) + (unsigned) offset,
- clen);
-
- offset = 0;
- length -= clen;
- ptr += clen;
- block_nr++;
- }
-
-#if BB_BIG_ENDIAN
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
- ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) inode,
- (struct ext2_inode_large *) inode,
- 0, length);
-#endif
-
- /* Update the inode cache */
- fs->icache->cache_last = (fs->icache->cache_last + 1) %
- fs->icache->cache_size;
- fs->icache->cache[fs->icache->cache_last].ino = ino;
- fs->icache->cache[fs->icache->cache_last].inode = *inode;
-
- return 0;
-}
-
-errcode_t ext2fs_read_inode(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode * inode)
-{
- return ext2fs_read_inode_full(fs, ino, inode,
- sizeof(struct ext2_inode));
-}
-
-errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode * inode, int bufsize)
-{
- unsigned long group, block, block_nr, offset;
- errcode_t retval = 0;
- struct ext2_inode_large temp_inode, *w_inode;
- char *ptr;
- int clen, i, length;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- /* Check to see if user provided an override function */
- if (fs->write_inode) {
- retval = (fs->write_inode)(fs, ino, inode);
- if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
- return retval;
- }
-
- /* Check to see if the inode cache needs to be updated */
- if (fs->icache) {
- for (i=0; i < fs->icache->cache_size; i++) {
- if (fs->icache->cache[i].ino == ino) {
- fs->icache->cache[i].inode = *inode;
- break;
- }
- }
- } else {
- retval = create_icache(fs);
- if (retval)
- return retval;
- }
-
- if (!(fs->flags & EXT2_FLAG_RW))
- return EXT2_ET_RO_FILSYS;
-
- if ((ino == 0) || (ino > fs->super->s_inodes_count))
- return EXT2_ET_BAD_INODE_NUM;
-
- length = bufsize;
- if (length < EXT2_INODE_SIZE(fs->super))
- length = EXT2_INODE_SIZE(fs->super);
-
- if (length > (int) sizeof(struct ext2_inode_large)) {
- w_inode = xmalloc(length);
- } else
- w_inode = &temp_inode;
- memset(w_inode, 0, length);
-
-#if BB_BIG_ENDIAN
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
- ext2fs_swap_inode_full(fs, w_inode,
- (struct ext2_inode_large *) inode,
- 1, bufsize);
- else
-#endif
- memcpy(w_inode, inode, bufsize);
-
- group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
- offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
- EXT2_INODE_SIZE(fs->super);
- block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
- if (!fs->group_desc[(unsigned) group].bg_inode_table)
- return EXT2_ET_MISSING_INODE_TABLE;
- block_nr = fs->group_desc[(unsigned) group].bg_inode_table + block;
-
- offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
-
- length = EXT2_INODE_SIZE(fs->super);
- if (length > bufsize)
- length = bufsize;
-
- ptr = (char *) w_inode;
-
- while (length) {
- clen = length;
- if ((offset + length) > fs->blocksize)
- clen = fs->blocksize - offset;
-
- if (fs->icache->buffer_blk != block_nr) {
- retval = io_channel_read_blk(fs->io, block_nr, 1,
- fs->icache->buffer);
- if (retval)
- goto errout;
- fs->icache->buffer_blk = block_nr;
- }
-
-
- memcpy((char *) fs->icache->buffer + (unsigned) offset,
- ptr, clen);
-
- retval = io_channel_write_blk(fs->io, block_nr, 1,
- fs->icache->buffer);
- if (retval)
- goto errout;
-
- offset = 0;
- ptr += clen;
- length -= clen;
- block_nr++;
- }
-
- fs->flags |= EXT2_FLAG_CHANGED;
-errout:
- if (w_inode && w_inode != &temp_inode)
- free(w_inode);
- return retval;
-}
-
-errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode)
-{
- return ext2fs_write_inode_full(fs, ino, inode,
- sizeof(struct ext2_inode));
-}
-
-/*
- * This function should be called when writing a new inode. It makes
- * sure that extra part of large inodes is initialized properly.
- */
-errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode)
-{
- struct ext2_inode *buf;
- int size = EXT2_INODE_SIZE(fs->super);
- struct ext2_inode_large *large_inode;
-
- if (size == sizeof(struct ext2_inode))
- return ext2fs_write_inode_full(fs, ino, inode,
- sizeof(struct ext2_inode));
-
- buf = xmalloc(size);
-
- memset(buf, 0, size);
- *buf = *inode;
-
- large_inode = (struct ext2_inode_large *) buf;
- large_inode->i_extra_isize = sizeof(struct ext2_inode_large) -
- EXT2_GOOD_OLD_INODE_SIZE;
-
- return ext2fs_write_inode_full(fs, ino, buf, size);
-}
-
-
-errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks)
-{
- struct ext2_inode inode;
- int i;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (ino > fs->super->s_inodes_count)
- return EXT2_ET_BAD_INODE_NUM;
-
- if (fs->get_blocks) {
- if (!(*fs->get_blocks)(fs, ino, blocks))
- return 0;
- }
- retval = ext2fs_read_inode(fs, ino, &inode);
- if (retval)
- return retval;
- for (i=0; i < EXT2_N_BLOCKS; i++)
- blocks[i] = inode.i_block[i];
- return 0;
-}
-
-errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino)
-{
- struct ext2_inode inode;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (ino > fs->super->s_inodes_count)
- return EXT2_ET_BAD_INODE_NUM;
-
- if (fs->check_directory) {
- retval = (fs->check_directory)(fs, ino);
- if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
- return retval;
- }
- retval = ext2fs_read_inode(fs, ino, &inode);
- if (retval)
- return retval;
- if (!LINUX_S_ISDIR(inode.i_mode))
- return EXT2_ET_NO_DIRECTORY;
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/inode_io.c b/release/src/router/busybox/e2fsprogs/ext2fs/inode_io.c
deleted file mode 100644
index b861d5ff69..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/inode_io.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * inode_io.c --- This is allows an inode in an ext2 filesystem image
- * to be accessed via the I/O manager interface.
- *
- * Copyright (C) 2002 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <time.h>
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * For checking structure magic numbers...
- */
-
-#define EXT2_CHECK_MAGIC(struct, code) \
- if ((struct)->magic != (code)) return (code)
-
-struct inode_private_data {
- int magic;
- char name[32];
- ext2_file_t file;
- ext2_filsys fs;
- ext2_ino_t ino;
- struct ext2_inode inode;
- int flags;
- struct inode_private_data *next;
-};
-
-#define CHANNEL_HAS_INODE 0x8000
-
-static struct inode_private_data *top_intern;
-static int ino_unique = 0;
-
-static errcode_t inode_open(const char *name, int flags, io_channel *channel);
-static errcode_t inode_close(io_channel channel);
-static errcode_t inode_set_blksize(io_channel channel, int blksize);
-static errcode_t inode_read_blk(io_channel channel, unsigned long block,
- int count, void *data);
-static errcode_t inode_write_blk(io_channel channel, unsigned long block,
- int count, const void *data);
-static errcode_t inode_flush(io_channel channel);
-static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
- int size, const void *data);
-
-static struct struct_io_manager struct_inode_manager = {
- EXT2_ET_MAGIC_IO_MANAGER,
- "Inode I/O Manager",
- inode_open,
- inode_close,
- inode_set_blksize,
- inode_read_blk,
- inode_write_blk,
- inode_flush,
- inode_write_byte
-};
-
-io_manager inode_io_manager = &struct_inode_manager;
-
-errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode,
- char **name)
-{
- struct inode_private_data *data;
- errcode_t retval;
-
- if ((retval = ext2fs_get_mem(sizeof(struct inode_private_data),
- &data)))
- return retval;
- data->magic = EXT2_ET_MAGIC_INODE_IO_CHANNEL;
- sprintf(data->name, "%u:%d", ino, ino_unique++);
- data->file = 0;
- data->fs = fs;
- data->ino = ino;
- data->flags = 0;
- if (inode) {
- memcpy(&data->inode, inode, sizeof(struct ext2_inode));
- data->flags |= CHANNEL_HAS_INODE;
- }
- data->next = top_intern;
- top_intern = data;
- *name = data->name;
- return 0;
-}
-
-errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino,
- char **name)
-{
- return ext2fs_inode_io_intern2(fs, ino, NULL, name);
-}
-
-
-static errcode_t inode_open(const char *name, int flags, io_channel *channel)
-{
- io_channel io = NULL;
- struct inode_private_data *prev, *data = NULL;
- errcode_t retval;
- int open_flags;
-
- if (name == 0)
- return EXT2_ET_BAD_DEVICE_NAME;
-
- for (data = top_intern, prev = NULL; data;
- prev = data, data = data->next)
- if (strcmp(name, data->name) == 0)
- break;
- if (!data)
- return ENOENT;
- if (prev)
- prev->next = data->next;
- else
- top_intern = data->next;
-
- retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
- if (retval)
- goto cleanup;
- memset(io, 0, sizeof(struct struct_io_channel));
-
- io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
- io->manager = inode_io_manager;
- retval = ext2fs_get_mem(strlen(name)+1, &io->name);
- if (retval)
- goto cleanup;
-
- strcpy(io->name, name);
- io->private_data = data;
- io->block_size = 1024;
- io->read_error = 0;
- io->write_error = 0;
- io->refcount = 1;
-
- open_flags = (flags & IO_FLAG_RW) ? EXT2_FILE_WRITE : 0;
- retval = ext2fs_file_open2(data->fs, data->ino,
- (data->flags & CHANNEL_HAS_INODE) ?
- &data->inode : 0, open_flags,
- &data->file);
- if (retval)
- goto cleanup;
-
- *channel = io;
- return 0;
-
-cleanup:
- if (data) {
- ext2fs_free_mem(&data);
- }
- if (io)
- ext2fs_free_mem(&io);
- return retval;
-}
-
-static errcode_t inode_close(io_channel channel)
-{
- struct inode_private_data *data;
- errcode_t retval = 0;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct inode_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
-
- if (--channel->refcount > 0)
- return 0;
-
- retval = ext2fs_file_close(data->file);
-
- ext2fs_free_mem(&channel->private_data);
- if (channel->name)
- ext2fs_free_mem(&channel->name);
- ext2fs_free_mem(&channel);
- return retval;
-}
-
-static errcode_t inode_set_blksize(io_channel channel, int blksize)
-{
- struct inode_private_data *data;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct inode_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
-
- channel->block_size = blksize;
- return 0;
-}
-
-
-static errcode_t inode_read_blk(io_channel channel, unsigned long block,
- int count, void *buf)
-{
- struct inode_private_data *data;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct inode_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
-
- if ((retval = ext2fs_file_lseek(data->file,
- block * channel->block_size,
- EXT2_SEEK_SET, 0)))
- return retval;
-
- count = (count < 0) ? -count : (count * channel->block_size);
-
- return ext2fs_file_read(data->file, buf, count, 0);
-}
-
-static errcode_t inode_write_blk(io_channel channel, unsigned long block,
- int count, const void *buf)
-{
- struct inode_private_data *data;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct inode_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
-
- if ((retval = ext2fs_file_lseek(data->file,
- block * channel->block_size,
- EXT2_SEEK_SET, 0)))
- return retval;
-
- count = (count < 0) ? -count : (count * channel->block_size);
-
- return ext2fs_file_write(data->file, buf, count, 0);
-}
-
-static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
- int size, const void *buf)
-{
- struct inode_private_data *data;
- errcode_t retval = 0;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct inode_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
-
- if ((retval = ext2fs_file_lseek(data->file, offset,
- EXT2_SEEK_SET, 0)))
- return retval;
-
- return ext2fs_file_write(data->file, buf, size, 0);
-}
-
-/*
- * Flush data buffers to disk.
- */
-static errcode_t inode_flush(io_channel channel)
-{
- struct inode_private_data *data;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct inode_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
-
- return ext2fs_file_flush(data->file);
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/io_manager.c b/release/src/router/busybox/e2fsprogs/ext2fs/io_manager.c
deleted file mode 100644
index b47038602a..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/io_manager.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * io_manager.c --- the I/O manager abstraction
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-errcode_t io_channel_set_options(io_channel channel, const char *opts)
-{
- errcode_t retval = 0;
- char *next, *ptr, *options, *arg;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
-
- if (!opts)
- return 0;
-
- if (!channel->manager->set_option)
- return EXT2_ET_INVALID_ARGUMENT;
-
- options = malloc(strlen(opts)+1);
- if (!options)
- return EXT2_ET_NO_MEMORY;
- strcpy(options, opts);
- ptr = options;
-
- while (ptr && *ptr) {
- next = strchr(ptr, '&');
- if (next)
- *next++ = 0;
-
- arg = strchr(ptr, '=');
- if (arg)
- *arg++ = 0;
-
- retval = (channel->manager->set_option)(channel, ptr, arg);
- if (retval)
- break;
- ptr = next;
- }
- free(options);
- return retval;
-}
-
-errcode_t io_channel_write_byte(io_channel channel, unsigned long offset,
- int count, const void *data)
-{
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
-
- if (channel->manager->write_byte)
- return channel->manager->write_byte(channel, offset,
- count, data);
-
- return EXT2_ET_UNIMPLEMENTED;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/irel.h b/release/src/router/busybox/e2fsprogs/ext2fs/irel.h
deleted file mode 100644
index 91d1d89d5f..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/irel.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * irel.h
- *
- * Copyright (C) 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-struct ext2_inode_reference {
- blk_t block;
- __u16 offset;
-};
-
-struct ext2_inode_relocate_entry {
- ext2_ino_t new;
- ext2_ino_t orig;
- __u16 flags;
- __u16 max_refs;
-};
-
-typedef struct ext2_inode_relocation_table *ext2_irel;
-
-struct ext2_inode_relocation_table {
- __u32 magic;
- char *name;
- ext2_ino_t current;
- void *priv_data;
-
- /*
- * Add an inode relocation entry.
- */
- errcode_t (*put)(ext2_irel irel, ext2_ino_t old,
- struct ext2_inode_relocate_entry *ent);
- /*
- * Get an inode relocation entry.
- */
- errcode_t (*get)(ext2_irel irel, ext2_ino_t old,
- struct ext2_inode_relocate_entry *ent);
-
- /*
- * Get an inode relocation entry by its original inode number
- */
- errcode_t (*get_by_orig)(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old,
- struct ext2_inode_relocate_entry *ent);
-
- /*
- * Initialize for iterating over the inode relocation entries.
- */
- errcode_t (*start_iter)(ext2_irel irel);
-
- /*
- * The iterator function for the inode relocation entries.
- * Returns an inode number of 0 when out of entries.
- */
- errcode_t (*next)(ext2_irel irel, ext2_ino_t *old,
- struct ext2_inode_relocate_entry *ent);
-
- /*
- * Add an inode reference (i.e., note the fact that a
- * particular block/offset contains a reference to an inode)
- */
- errcode_t (*add_ref)(ext2_irel irel, ext2_ino_t ino,
- struct ext2_inode_reference *ref);
-
- /*
- * Initialize for iterating over the inode references for a
- * particular inode.
- */
- errcode_t (*start_iter_ref)(ext2_irel irel, ext2_ino_t ino);
-
- /*
- * The iterator function for the inode references for an
- * inode. The references for only one inode can be interator
- * over at a time, as the iterator state is stored in ext2_irel.
- */
- errcode_t (*next_ref)(ext2_irel irel,
- struct ext2_inode_reference *ref);
-
- /*
- * Move the inode relocation table from one inode number to
- * another. Note that the inode references also must move.
- */
- errcode_t (*move)(ext2_irel irel, ext2_ino_t old, ext2_ino_t new);
-
- /*
- * Remove an inode relocation entry, along with all of the
- * inode references.
- */
- errcode_t (*delete)(ext2_irel irel, ext2_ino_t old);
-
- /*
- * Free the inode relocation table.
- */
- errcode_t (*free)(ext2_irel irel);
-};
-
-errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode,
- ext2_irel *irel);
-
-#define ext2fs_irel_put(irel, old, ent) ((irel)->put((irel), old, ent))
-#define ext2fs_irel_get(irel, old, ent) ((irel)->get((irel), old, ent))
-#define ext2fs_irel_get_by_orig(irel, orig, old, ent) \
- ((irel)->get_by_orig((irel), orig, old, ent))
-#define ext2fs_irel_start_iter(irel) ((irel)->start_iter((irel)))
-#define ext2fs_irel_next(irel, old, ent) ((irel)->next((irel), old, ent))
-#define ext2fs_irel_add_ref(irel, ino, ref) ((irel)->add_ref((irel), ino, ref))
-#define ext2fs_irel_start_iter_ref(irel, ino) ((irel)->start_iter_ref((irel), ino))
-#define ext2fs_irel_next_ref(irel, ref) ((irel)->next_ref((irel), ref))
-#define ext2fs_irel_move(irel, old, new) ((irel)->move((irel), old, new))
-#define ext2fs_irel_delete(irel, old) ((irel)->delete((irel), old))
-#define ext2fs_irel_free(irel) ((irel)->free((irel)))
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/irel_ma.c b/release/src/router/busybox/e2fsprogs/ext2fs/irel_ma.c
deleted file mode 100644
index c871b18919..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/irel_ma.c
+++ /dev/null
@@ -1,367 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * irel_ma.c
- *
- * Copyright (C) 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-#include "irel.h"
-
-static errcode_t ima_put(ext2_irel irel, ext2_ino_t old,
- struct ext2_inode_relocate_entry *ent);
-static errcode_t ima_get(ext2_irel irel, ext2_ino_t old,
- struct ext2_inode_relocate_entry *ent);
-static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old,
- struct ext2_inode_relocate_entry *ent);
-static errcode_t ima_start_iter(ext2_irel irel);
-static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old,
- struct ext2_inode_relocate_entry *ent);
-static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino,
- struct ext2_inode_reference *ref);
-static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino);
-static errcode_t ima_next_ref(ext2_irel irel, struct ext2_inode_reference *ref);
-static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new);
-static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old);
-static errcode_t ima_free(ext2_irel irel);
-
-/*
- * This data structure stores the array of inode references; there is
- * a structure for each inode.
- */
-struct inode_reference_entry {
- __u16 num;
- struct ext2_inode_reference *refs;
-};
-
-struct irel_ma {
- __u32 magic;
- ext2_ino_t max_inode;
- ext2_ino_t ref_current;
- int ref_iter;
- ext2_ino_t *orig_map;
- struct ext2_inode_relocate_entry *entries;
- struct inode_reference_entry *ref_entries;
-};
-
-errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode,
- ext2_irel *new_irel)
-{
- ext2_irel irel = 0;
- errcode_t retval;
- struct irel_ma *ma = 0;
- size_t size;
-
- *new_irel = 0;
-
- /*
- * Allocate memory structures
- */
- retval = ext2fs_get_mem(sizeof(struct ext2_inode_relocation_table),
- &irel);
- if (retval)
- goto errout;
- memset(irel, 0, sizeof(struct ext2_inode_relocation_table));
-
- retval = ext2fs_get_mem(strlen(name)+1, &irel->name);
- if (retval)
- goto errout;
- strcpy(irel->name, name);
-
- retval = ext2fs_get_mem(sizeof(struct irel_ma), &ma);
- if (retval)
- goto errout;
- memset(ma, 0, sizeof(struct irel_ma));
- irel->priv_data = ma;
-
- size = (size_t) (sizeof(ext2_ino_t) * (max_inode+1));
- retval = ext2fs_get_mem(size, &ma->orig_map);
- if (retval)
- goto errout;
- memset(ma->orig_map, 0, size);
-
- size = (size_t) (sizeof(struct ext2_inode_relocate_entry) *
- (max_inode+1));
- retval = ext2fs_get_mem(size, &ma->entries);
- if (retval)
- goto errout;
- memset(ma->entries, 0, size);
-
- size = (size_t) (sizeof(struct inode_reference_entry) *
- (max_inode+1));
- retval = ext2fs_get_mem(size, &ma->ref_entries);
- if (retval)
- goto errout;
- memset(ma->ref_entries, 0, size);
- ma->max_inode = max_inode;
-
- /*
- * Fill in the irel data structure
- */
- irel->put = ima_put;
- irel->get = ima_get;
- irel->get_by_orig = ima_get_by_orig;
- irel->start_iter = ima_start_iter;
- irel->next = ima_next;
- irel->add_ref = ima_add_ref;
- irel->start_iter_ref = ima_start_iter_ref;
- irel->next_ref = ima_next_ref;
- irel->move = ima_move;
- irel->delete = ima_delete;
- irel->free = ima_free;
-
- *new_irel = irel;
- return 0;
-
-errout:
- ima_free(irel);
- return retval;
-}
-
-static errcode_t ima_put(ext2_irel irel, ext2_ino_t old,
- struct ext2_inode_relocate_entry *ent)
-{
- struct inode_reference_entry *ref_ent;
- struct irel_ma *ma;
- errcode_t retval;
- size_t size, old_size;
-
- ma = irel->priv_data;
- if (old > ma->max_inode)
- return EXT2_ET_INVALID_ARGUMENT;
-
- /*
- * Force the orig field to the correct value; the application
- * program shouldn't be messing with this field.
- */
- if (ma->entries[(unsigned) old].new == 0)
- ent->orig = old;
- else
- ent->orig = ma->entries[(unsigned) old].orig;
-
- /*
- * If max_refs has changed, reallocate the refs array
- */
- ref_ent = ma->ref_entries + (unsigned) old;
- if (ref_ent->refs && ent->max_refs !=
- ma->entries[(unsigned) old].max_refs) {
- size = (sizeof(struct ext2_inode_reference) * ent->max_refs);
- old_size = (sizeof(struct ext2_inode_reference) *
- ma->entries[(unsigned) old].max_refs);
- retval = ext2fs_resize_mem(old_size, size, &ref_ent->refs);
- if (retval)
- return retval;
- }
-
- ma->entries[(unsigned) old] = *ent;
- ma->orig_map[(unsigned) ent->orig] = old;
- return 0;
-}
-
-static errcode_t ima_get(ext2_irel irel, ext2_ino_t old,
- struct ext2_inode_relocate_entry *ent)
-{
- struct irel_ma *ma;
-
- ma = irel->priv_data;
- if (old > ma->max_inode)
- return EXT2_ET_INVALID_ARGUMENT;
- if (ma->entries[(unsigned) old].new == 0)
- return ENOENT;
- *ent = ma->entries[(unsigned) old];
- return 0;
-}
-
-static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old,
- struct ext2_inode_relocate_entry *ent)
-{
- struct irel_ma *ma;
- ext2_ino_t ino;
-
- ma = irel->priv_data;
- if (orig > ma->max_inode)
- return EXT2_ET_INVALID_ARGUMENT;
- ino = ma->orig_map[(unsigned) orig];
- if (ino == 0)
- return ENOENT;
- *old = ino;
- *ent = ma->entries[(unsigned) ino];
- return 0;
-}
-
-static errcode_t ima_start_iter(ext2_irel irel)
-{
- irel->current = 0;
- return 0;
-}
-
-static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old,
- struct ext2_inode_relocate_entry *ent)
-{
- struct irel_ma *ma;
-
- ma = irel->priv_data;
- while (++irel->current < ma->max_inode) {
- if (ma->entries[(unsigned) irel->current].new == 0)
- continue;
- *old = irel->current;
- *ent = ma->entries[(unsigned) irel->current];
- return 0;
- }
- *old = 0;
- return 0;
-}
-
-static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino,
- struct ext2_inode_reference *ref)
-{
- struct irel_ma *ma;
- size_t size;
- struct inode_reference_entry *ref_ent;
- struct ext2_inode_relocate_entry *ent;
- errcode_t retval;
-
- ma = irel->priv_data;
- if (ino > ma->max_inode)
- return EXT2_ET_INVALID_ARGUMENT;
-
- ref_ent = ma->ref_entries + (unsigned) ino;
- ent = ma->entries + (unsigned) ino;
-
- /*
- * If the inode reference array doesn't exist, create it.
- */
- if (ref_ent->refs == 0) {
- size = (size_t) ((sizeof(struct ext2_inode_reference) *
- ent->max_refs));
- retval = ext2fs_get_mem(size, &ref_ent->refs);
- if (retval)
- return retval;
- memset(ref_ent->refs, 0, size);
- ref_ent->num = 0;
- }
-
- if (ref_ent->num >= ent->max_refs)
- return EXT2_ET_TOO_MANY_REFS;
-
- ref_ent->refs[(unsigned) ref_ent->num++] = *ref;
- return 0;
-}
-
-static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino)
-{
- struct irel_ma *ma;
-
- ma = irel->priv_data;
- if (ino > ma->max_inode)
- return EXT2_ET_INVALID_ARGUMENT;
- if (ma->entries[(unsigned) ino].new == 0)
- return ENOENT;
- ma->ref_current = ino;
- ma->ref_iter = 0;
- return 0;
-}
-
-static errcode_t ima_next_ref(ext2_irel irel,
- struct ext2_inode_reference *ref)
-{
- struct irel_ma *ma;
- struct inode_reference_entry *ref_ent;
-
- ma = irel->priv_data;
-
- ref_ent = ma->ref_entries + ma->ref_current;
-
- if ((ref_ent->refs == NULL) ||
- (ma->ref_iter >= ref_ent->num)) {
- ref->block = 0;
- ref->offset = 0;
- return 0;
- }
- *ref = ref_ent->refs[ma->ref_iter++];
- return 0;
-}
-
-
-static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new)
-{
- struct irel_ma *ma;
-
- ma = irel->priv_data;
- if ((old > ma->max_inode) || (new > ma->max_inode))
- return EXT2_ET_INVALID_ARGUMENT;
- if (ma->entries[(unsigned) old].new == 0)
- return ENOENT;
-
- ma->entries[(unsigned) new] = ma->entries[(unsigned) old];
- ext2fs_free_mem(&ma->ref_entries[(unsigned) new].refs);
- ma->ref_entries[(unsigned) new] = ma->ref_entries[(unsigned) old];
-
- ma->entries[(unsigned) old].new = 0;
- ma->ref_entries[(unsigned) old].num = 0;
- ma->ref_entries[(unsigned) old].refs = 0;
-
- ma->orig_map[ma->entries[new].orig] = new;
- return 0;
-}
-
-static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old)
-{
- struct irel_ma *ma;
-
- ma = irel->priv_data;
- if (old > ma->max_inode)
- return EXT2_ET_INVALID_ARGUMENT;
- if (ma->entries[(unsigned) old].new == 0)
- return ENOENT;
-
- ma->entries[old].new = 0;
- ext2fs_free_mem(&ma->ref_entries[(unsigned) old].refs);
- ma->orig_map[ma->entries[(unsigned) old].orig] = 0;
-
- ma->ref_entries[(unsigned) old].num = 0;
- ma->ref_entries[(unsigned) old].refs = 0;
- return 0;
-}
-
-static errcode_t ima_free(ext2_irel irel)
-{
- struct irel_ma *ma;
- ext2_ino_t ino;
-
- if (!irel)
- return 0;
-
- ma = irel->priv_data;
-
- if (ma) {
- ext2fs_free_mem(&ma->orig_map);
- ext2fs_free_mem(&ma->entries);
- if (ma->ref_entries) {
- for (ino = 0; ino <= ma->max_inode; ino++) {
- ext2fs_free_mem(&ma->ref_entries[(unsigned) ino].refs);
- }
- ext2fs_free_mem(&ma->ref_entries);
- }
- ext2fs_free_mem(&ma);
- }
- ext2fs_free_mem(&irel->name);
- ext2fs_free_mem(&irel);
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/ismounted.c b/release/src/router/busybox/e2fsprogs/ext2fs/ismounted.c
deleted file mode 100644
index 58dab79b1d..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/ismounted.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * ismounted.c --- Check to see if the filesystem was mounted
- *
- * Copyright (C) 1995,1996,1997,1998,1999,2000 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <fcntl.h>
-#ifdef HAVE_LINUX_FD_H
-#include <linux/fd.h>
-#endif
-#ifdef HAVE_MNTENT_H
-#include <mntent.h>
-#endif
-#ifdef HAVE_GETMNTINFO
-#include <paths.h>
-#include <sys/param.h>
-#include <sys/mount.h>
-#endif /* HAVE_GETMNTINFO */
-#include <string.h>
-#include <sys/stat.h>
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-#ifdef HAVE_MNTENT_H
-/*
- * Helper function which checks a file in /etc/mtab format to see if a
- * filesystem is mounted. Returns an error if the file doesn't exist
- * or can't be opened.
- */
-static errcode_t check_mntent_file(const char *mtab_file, const char *file,
- int *mount_flags, char *mtpt, int mtlen)
-{
- struct mntent *mnt;
- struct stat st_buf;
- errcode_t retval = 0;
- dev_t file_dev=0, file_rdev=0;
- ino_t file_ino=0;
- FILE *f;
- int fd;
-
- *mount_flags = 0;
- if ((f = setmntent (mtab_file, "r")) == NULL)
- return errno;
- if (stat(file, &st_buf) == 0) {
- if (S_ISBLK(st_buf.st_mode)) {
-#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
- file_rdev = st_buf.st_rdev;
-#endif /* __GNU__ */
- } else {
- file_dev = st_buf.st_dev;
- file_ino = st_buf.st_ino;
- }
- }
- while ((mnt = getmntent (f)) != NULL) {
- if (strcmp(file, mnt->mnt_fsname) == 0)
- break;
- if (stat(mnt->mnt_fsname, &st_buf) == 0) {
- if (S_ISBLK(st_buf.st_mode)) {
-#ifndef __GNU__
- if (file_rdev && (file_rdev == st_buf.st_rdev))
- break;
-#endif /* __GNU__ */
- } else {
- if (file_dev && ((file_dev == st_buf.st_dev) &&
- (file_ino == st_buf.st_ino)))
- break;
- }
- }
- }
-
- if (mnt == 0) {
-#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
- /*
- * Do an extra check to see if this is the root device. We
- * can't trust /etc/mtab, and /proc/mounts will only list
- * /dev/root for the root filesystem. Argh. Instead we
- * check if the given device has the same major/minor number
- * as the device that the root directory is on.
- */
- if (file_rdev && stat("/", &st_buf) == 0) {
- if (st_buf.st_dev == file_rdev) {
- *mount_flags = EXT2_MF_MOUNTED;
- if (mtpt)
- strncpy(mtpt, "/", mtlen);
- goto is_root;
- }
- }
-#endif /* __GNU__ */
- goto errout;
- }
-#ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */
- /* Validate the entry in case /etc/mtab is out of date */
- /*
- * We need to be paranoid, because some broken distributions
- * (read: Slackware) don't initialize /etc/mtab before checking
- * all of the non-root filesystems on the disk.
- */
- if (stat(mnt->mnt_dir, &st_buf) < 0) {
- retval = errno;
- if (retval == ENOENT) {
-#ifdef DEBUG
- printf("Bogus entry in %s! (%s does not exist)\n",
- mtab_file, mnt->mnt_dir);
-#endif /* DEBUG */
- retval = 0;
- }
- goto errout;
- }
- if (file_rdev && (st_buf.st_dev != file_rdev)) {
-#ifdef DEBUG
- printf("Bogus entry in %s! (%s not mounted on %s)\n",
- mtab_file, file, mnt->mnt_dir);
-#endif /* DEBUG */
- goto errout;
- }
-#endif /* __GNU__ */
- *mount_flags = EXT2_MF_MOUNTED;
-
-#ifdef MNTOPT_RO
- /* Check to see if the ro option is set */
- if (hasmntopt(mnt, MNTOPT_RO))
- *mount_flags |= EXT2_MF_READONLY;
-#endif
-
- if (mtpt)
- strncpy(mtpt, mnt->mnt_dir, mtlen);
- /*
- * Check to see if we're referring to the root filesystem.
- * If so, do a manual check to see if we can open /etc/mtab
- * read/write, since if the root is mounted read/only, the
- * contents of /etc/mtab may not be accurate.
- */
- if (LONE_CHAR(mnt->mnt_dir, '/')) {
-is_root:
-#define TEST_FILE "/.ismount-test-file"
- *mount_flags |= EXT2_MF_ISROOT;
- fd = open(TEST_FILE, O_RDWR|O_CREAT);
- if (fd < 0) {
- if (errno == EROFS)
- *mount_flags |= EXT2_MF_READONLY;
- } else
- close(fd);
- (void) unlink(TEST_FILE);
- }
- retval = 0;
-errout:
- endmntent (f);
- return retval;
-}
-
-static errcode_t check_mntent(const char *file, int *mount_flags,
- char *mtpt, int mtlen)
-{
- errcode_t retval;
-
-#ifdef DEBUG
- retval = check_mntent_file("/tmp/mtab", file, mount_flags,
- mtpt, mtlen);
- if (retval == 0)
- return 0;
-#endif /* DEBUG */
-#ifdef __linux__
- retval = check_mntent_file("/proc/mounts", file, mount_flags,
- mtpt, mtlen);
- return retval;
-#endif /* __linux__ */
-#if defined(MOUNTED) || defined(_PATH_MOUNTED)
-#ifndef MOUNTED
-#define MOUNTED _PATH_MOUNTED
-#endif /* MOUNTED */
- retval = check_mntent_file(MOUNTED, file, mount_flags, mtpt, mtlen);
- return retval;
-#else
- *mount_flags = 0;
- return 0;
-#endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */
-}
-
-#else
-#if defined(HAVE_GETMNTINFO)
-
-static errcode_t check_getmntinfo(const char *file, int *mount_flags,
- char *mtpt, int mtlen)
-{
- struct statfs *mp;
- int len, n;
- const char *s1;
- char *s2;
-
- n = getmntinfo(&mp, MNT_NOWAIT);
- if (n == 0)
- return errno;
-
- len = sizeof(_PATH_DEV) - 1;
- s1 = file;
- if (strncmp(_PATH_DEV, s1, len) == 0)
- s1 += len;
-
- *mount_flags = 0;
- while (--n >= 0) {
- s2 = mp->f_mntfromname;
- if (strncmp(_PATH_DEV, s2, len) == 0) {
- s2 += len - 1;
- *s2 = 'r';
- }
- if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) {
- *mount_flags = EXT2_MF_MOUNTED;
- break;
- }
- ++mp;
- }
- if (mtpt)
- strncpy(mtpt, mp->f_mntonname, mtlen);
- return 0;
-}
-#endif /* HAVE_GETMNTINFO */
-#endif /* HAVE_MNTENT_H */
-
-/*
- * Check to see if we're dealing with the swap device.
- */
-static int is_swap_device(const char *file)
-{
- FILE *f;
- char buf[1024], *cp;
- dev_t file_dev;
- struct stat st_buf;
- int ret = 0;
-
- file_dev = 0;
-#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
- if ((stat(file, &st_buf) == 0) &&
- S_ISBLK(st_buf.st_mode))
- file_dev = st_buf.st_rdev;
-#endif /* __GNU__ */
-
- if (!(f = fopen_for_read("/proc/swaps")))
- return 0;
- /* Skip the first line */
- fgets(buf, sizeof(buf), f);
- while (!feof(f)) {
- if (!fgets(buf, sizeof(buf), f))
- break;
- if ((cp = strchr(buf, ' ')) != NULL)
- *cp = 0;
- if ((cp = strchr(buf, '\t')) != NULL)
- *cp = 0;
- if (strcmp(buf, file) == 0) {
- ret++;
- break;
- }
-#ifndef __GNU__
- if (file_dev && (stat(buf, &st_buf) == 0) &&
- S_ISBLK(st_buf.st_mode) &&
- file_dev == st_buf.st_rdev) {
- ret++;
- break;
- }
-#endif /* __GNU__ */
- }
- fclose(f);
- return ret;
-}
-
-
-/*
- * ext2fs_check_mount_point() returns 1 if the device is mounted, 0
- * otherwise. If mtpt is non-NULL, the directory where the device is
- * mounted is copied to where mtpt is pointing, up to mtlen
- * characters.
- */
-#ifdef __TURBOC__
-# pragma argsused
-#endif
-errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags,
- char *mtpt, int mtlen)
-{
- if (is_swap_device(device)) {
- *mount_flags = EXT2_MF_MOUNTED | EXT2_MF_SWAP;
- strncpy(mtpt, "<swap>", mtlen);
- return 0;
- }
-#ifdef HAVE_MNTENT_H
- return check_mntent(device, mount_flags, mtpt, mtlen);
-#else
-#ifdef HAVE_GETMNTINFO
- return check_getmntinfo(device, mount_flags, mtpt, mtlen);
-#else
-#ifdef __GNUC__
- #warning "Can't use getmntent or getmntinfo to check for mounted filesystems!"
-#endif
- *mount_flags = 0;
- return 0;
-#endif /* HAVE_GETMNTINFO */
-#endif /* HAVE_MNTENT_H */
-}
-
-/*
- * ext2fs_check_if_mounted() sets the mount_flags EXT2_MF_MOUNTED,
- * EXT2_MF_READONLY, and EXT2_MF_ROOT
- *
- */
-errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags)
-{
- return ext2fs_check_mount_point(file, mount_flags, NULL, 0);
-}
-
-#ifdef DEBUG
-int main(int argc, char **argv)
-{
- int retval, mount_flags;
- char mntpt[80];
-
- if (argc < 2) {
- fprintf(stderr, "Usage: %s device\n", argv[0]);
- exit(1);
- }
-
- mntpt[0] = 0;
- retval = ext2fs_check_mount_point(argv[1], &mount_flags,
- mntpt, sizeof(mntpt));
- if (retval) {
- com_err(argv[0], retval,
- "while calling ext2fs_check_if_mounted");
- exit(1);
- }
- printf("Device %s reports flags %02x\n", argv[1], mount_flags);
- if (mount_flags & EXT2_MF_BUSY)
- printf("\t%s is apparently in use.\n", argv[1]);
- if (mount_flags & EXT2_MF_MOUNTED)
- printf("\t%s is mounted.\n", argv[1]);
- if (mount_flags & EXT2_MF_SWAP)
- printf("\t%s is a swap device.\n", argv[1]);
- if (mount_flags & EXT2_MF_READONLY)
- printf("\t%s is read-only.\n", argv[1]);
- if (mount_flags & EXT2_MF_ISROOT)
- printf("\t%s is the root filesystem.\n", argv[1]);
- if (mntpt[0])
- printf("\t%s is mounted on %s.\n", argv[1], mntpt);
- exit(0);
-}
-#endif /* DEBUG */
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/jfs_dat.h b/release/src/router/busybox/e2fsprogs/ext2fs/jfs_dat.h
deleted file mode 100644
index 17c586a29b..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/jfs_dat.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * jfs_dat.h --- stripped down header file which only contains the JFS
- * on-disk data structures
- */
-
-#define JFS_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */
-
-/*
- * On-disk structures
- */
-
-/*
- * Descriptor block types:
- */
-
-#define JFS_DESCRIPTOR_BLOCK 1
-#define JFS_COMMIT_BLOCK 2
-#define JFS_SUPERBLOCK 3
-
-/*
- * Standard header for all descriptor blocks:
- */
-typedef struct journal_header_s
-{
- __u32 h_magic;
- __u32 h_blocktype;
- __u32 h_sequence;
-} journal_header_t;
-
-
-/*
- * The block tag: used to describe a single buffer in the journal
- */
-typedef struct journal_block_tag_s
-{
- __u32 t_blocknr; /* The on-disk block number */
- __u32 t_flags; /* See below */
-} journal_block_tag_t;
-
-/* Definitions for the journal tag flags word: */
-#define JFS_FLAG_ESCAPE 1 /* on-disk block is escaped */
-#define JFS_FLAG_SAME_UUID 2 /* block has same uuid as previous */
-#define JFS_FLAG_DELETED 4 /* block deleted by this transaction */
-#define JFS_FLAG_LAST_TAG 8 /* last tag in this descriptor block */
-
-
-/*
- * The journal superblock
- */
-typedef struct journal_superblock_s
-{
- journal_header_t s_header;
-
- /* Static information describing the journal */
- __u32 s_blocksize; /* journal device blocksize */
- __u32 s_maxlen; /* total blocks in journal file */
- __u32 s_first; /* first block of log information */
-
- /* Dynamic information describing the current state of the log */
- __u32 s_sequence; /* first commit ID expected in log */
- __u32 s_start; /* blocknr of start of log */
-} journal_superblock_t;
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/kernel-jbd.h b/release/src/router/busybox/e2fsprogs/ext2fs/kernel-jbd.h
deleted file mode 100644
index 853d97ac7f..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/kernel-jbd.h
+++ /dev/null
@@ -1,235 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * linux/include/linux/jbd.h
- *
- * Written by Stephen C. Tweedie <sct@redhat.com>
- *
- * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved
- *
- * This file is part of the Linux kernel and is made available under
- * the terms of the GNU General Public License, version 2, or at your
- * option, any later version, incorporated herein by reference.
- *
- * Definitions for transaction data structures for the buffer cache
- * filesystem journaling support.
- */
-#ifndef LINUX_JBD_H
-#define LINUX_JBD_H 1
-
-#include <sys/types.h>
-#include <linux/types.h>
-#include "ext2fs.h"
-
-/*
- * Standard header for all descriptor blocks:
- */
-
-typedef struct journal_header_s
-{
- __u32 h_magic;
- __u32 h_blocktype;
- __u32 h_sequence;
-} journal_header_t;
-
-/*
- * This is the global e2fsck structure.
- */
-typedef struct e2fsck_struct *e2fsck_t;
-
-
-struct inode {
- e2fsck_t i_ctx;
- ext2_ino_t i_ino;
- struct ext2_inode i_ext2;
-};
-
-
-/*
- * The journal superblock. All fields are in big-endian byte order.
- */
-typedef struct journal_superblock_s
-{
-/* 0x0000 */
- journal_header_t s_header;
-
-/* 0x000C */
- /* Static information describing the journal */
- __u32 s_blocksize; /* journal device blocksize */
- __u32 s_maxlen; /* total blocks in journal file */
- __u32 s_first; /* first block of log information */
-
-/* 0x0018 */
- /* Dynamic information describing the current state of the log */
- __u32 s_sequence; /* first commit ID expected in log */
- __u32 s_start; /* blocknr of start of log */
-
-/* 0x0020 */
- /* Error value, as set by journal_abort(). */
- __s32 s_errno;
-
-/* 0x0024 */
- /* Remaining fields are only valid in a version-2 superblock */
- __u32 s_feature_compat; /* compatible feature set */
- __u32 s_feature_incompat; /* incompatible feature set */
- __u32 s_feature_ro_compat; /* readonly-compatible feature set */
-/* 0x0030 */
- __u8 s_uuid[16]; /* 128-bit uuid for journal */
-
-/* 0x0040 */
- __u32 s_nr_users; /* Nr of filesystems sharing log */
-
- __u32 s_dynsuper; /* Blocknr of dynamic superblock copy*/
-
-/* 0x0048 */
- __u32 s_max_transaction; /* Limit of journal blocks per trans.*/
- __u32 s_max_trans_data; /* Limit of data blocks per trans. */
-
-/* 0x0050 */
- __u32 s_padding[44];
-
-/* 0x0100 */
- __u8 s_users[16*48]; /* ids of all fs'es sharing the log */
-/* 0x0400 */
-} journal_superblock_t;
-
-
-extern int journal_blocks_per_page(struct inode *inode);
-extern int jbd_blocks_per_page(struct inode *inode);
-
-#define JFS_MIN_JOURNAL_BLOCKS 1024
-
-
-/*
- * Internal structures used by the logging mechanism:
- */
-
-#define JFS_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */
-
-/*
- * Descriptor block types:
- */
-
-#define JFS_DESCRIPTOR_BLOCK 1
-#define JFS_COMMIT_BLOCK 2
-#define JFS_SUPERBLOCK_V1 3
-#define JFS_SUPERBLOCK_V2 4
-#define JFS_REVOKE_BLOCK 5
-
-/*
- * The block tag: used to describe a single buffer in the journal
- */
-typedef struct journal_block_tag_s
-{
- __u32 t_blocknr; /* The on-disk block number */
- __u32 t_flags; /* See below */
-} journal_block_tag_t;
-
-/*
- * The revoke descriptor: used on disk to describe a series of blocks to
- * be revoked from the log
- */
-typedef struct journal_revoke_header_s
-{
- journal_header_t r_header;
- int r_count; /* Count of bytes used in the block */
-} journal_revoke_header_t;
-
-
-/* Definitions for the journal tag flags word: */
-#define JFS_FLAG_ESCAPE 1 /* on-disk block is escaped */
-#define JFS_FLAG_SAME_UUID 2 /* block has same uuid as previous */
-#define JFS_FLAG_DELETED 4 /* block deleted by this transaction */
-#define JFS_FLAG_LAST_TAG 8 /* last tag in this descriptor block */
-
-
-
-
-#define JFS_HAS_COMPAT_FEATURE(j,mask) \
- ((j)->j_format_version >= 2 && \
- ((j)->j_superblock->s_feature_compat & cpu_to_be32((mask))))
-#define JFS_HAS_RO_COMPAT_FEATURE(j,mask) \
- ((j)->j_format_version >= 2 && \
- ((j)->j_superblock->s_feature_ro_compat & cpu_to_be32((mask))))
-#define JFS_HAS_INCOMPAT_FEATURE(j,mask) \
- ((j)->j_format_version >= 2 && \
- ((j)->j_superblock->s_feature_incompat & cpu_to_be32((mask))))
-
-#define JFS_FEATURE_INCOMPAT_REVOKE 0x00000001
-
-/* Features known to this kernel version: */
-#define JFS_KNOWN_COMPAT_FEATURES 0
-#define JFS_KNOWN_ROCOMPAT_FEATURES 0
-#define JFS_KNOWN_INCOMPAT_FEATURES JFS_FEATURE_INCOMPAT_REVOKE
-
-/* Comparison functions for transaction IDs: perform comparisons using
- * modulo arithmetic so that they work over sequence number wraps. */
-
-
-/*
- * Definitions which augment the buffer_head layer
- */
-
-/* journaling buffer types */
-#define BJ_None 0 /* Not journaled */
-#define BJ_SyncData 1 /* Normal data: flush before commit */
-#define BJ_AsyncData 2 /* writepage data: wait on it before commit */
-#define BJ_Metadata 3 /* Normal journaled metadata */
-#define BJ_Forget 4 /* Buffer superceded by this transaction */
-#define BJ_IO 5 /* Buffer is for temporary IO use */
-#define BJ_Shadow 6 /* Buffer contents being shadowed to the log */
-#define BJ_LogCtl 7 /* Buffer contains log descriptors */
-#define BJ_Reserved 8 /* Buffer is reserved for access by journal */
-#define BJ_Types 9
-
-
-struct kdev_s {
- e2fsck_t k_ctx;
- int k_dev;
-};
-
-typedef struct kdev_s *kdev_t;
-typedef unsigned int tid_t;
-
-struct journal_s
-{
- unsigned long j_flags;
- int j_errno;
- struct buffer_head * j_sb_buffer;
- struct journal_superblock_s *j_superblock;
- int j_format_version;
- unsigned long j_head;
- unsigned long j_tail;
- unsigned long j_free;
- unsigned long j_first, j_last;
- kdev_t j_dev;
- kdev_t j_fs_dev;
- int j_blocksize;
- unsigned int j_blk_offset;
- unsigned int j_maxlen;
- struct inode * j_inode;
- tid_t j_tail_sequence;
- tid_t j_transaction_sequence;
- __u8 j_uuid[16];
- struct jbd_revoke_table_s *j_revoke;
-};
-
-typedef struct journal_s journal_t;
-
-extern int journal_recover (journal_t *journal);
-extern int journal_skip_recovery (journal_t *);
-
-/* Primary revoke support */
-extern int journal_init_revoke(journal_t *, int);
-extern void journal_destroy_revoke_caches(void);
-extern int journal_init_revoke_caches(void);
-
-/* Recovery revoke support */
-extern int journal_set_revoke(journal_t *, unsigned long, tid_t);
-extern int journal_test_revoke(journal_t *, unsigned long, tid_t);
-extern void journal_clear_revoke(journal_t *);
-extern void journal_brelse_array(struct buffer_head *b[], int n);
-
-extern void journal_destroy_revoke(journal_t *);
-
-
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/kernel-list.h b/release/src/router/busybox/e2fsprogs/ext2fs/kernel-list.h
deleted file mode 100644
index d80716a454..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/kernel-list.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/* vi: set sw=4 ts=4: */
-#ifndef LINUX_LIST_H
-#define LINUX_LIST_H 1
-
-/*
- * Simple doubly linked list implementation.
- *
- * Some of the internal functions ("__xxx") are useful when
- * manipulating whole lists rather than single entries, as
- * sometimes we already know the next/prev entries and we can
- * generate better code by using them directly rather than
- * using the generic single-entry routines.
- */
-
-struct list_head {
- struct list_head *next, *prev;
-};
-
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define LIST_HEAD(name) \
- struct list_head name = { &name, &name }
-
-#define INIT_LIST_HEAD(ptr) do { \
- (ptr)->next = (ptr); (ptr)->prev = (ptr); \
-} while (0)
-
-#if (!defined(__GNUC__) && !defined(__WATCOMC__))
-#define __inline__
-#endif
-
-/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static __inline__ void __list_add(struct list_head * new,
- struct list_head * prev,
- struct list_head * next)
-{
- next->prev = new;
- new->next = next;
- new->prev = prev;
- prev->next = new;
-}
-
-/*
- * Insert a new entry after the specified head..
- */
-static __inline__ void list_add(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head, head->next);
-}
-
-/*
- * Insert a new entry at the tail
- */
-static __inline__ void list_add_tail(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head->prev, head);
-}
-
-/*
- * Delete a list entry by making the prev/next entries
- * point to each other.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static __inline__ void __list_del(struct list_head * prev,
- struct list_head * next)
-{
- next->prev = prev;
- prev->next = next;
-}
-
-static __inline__ void list_del(struct list_head *entry)
-{
- __list_del(entry->prev, entry->next);
-}
-
-static __inline__ int list_empty(struct list_head *head)
-{
- return head->next == head;
-}
-
-/*
- * Splice in "list" into "head"
- */
-static __inline__ void list_splice(struct list_head *list, struct list_head *head)
-{
- struct list_head *first = list->next;
-
- if (first != list) {
- struct list_head *last = list->prev;
- struct list_head *at = head->next;
-
- first->prev = head;
- head->next = first;
-
- last->next = at;
- at->prev = last;
- }
-}
-
-#define list_entry(ptr, type, member) \
- ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
-
-#define list_for_each(pos, head) \
- for (pos = (head)->next; pos != (head); pos = pos->next)
-
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/link.c b/release/src/router/busybox/e2fsprogs/ext2fs/link.c
deleted file mode 100644
index 08b2e96738..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/link.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * link.c --- create links in a ext2fs directory
- *
- * Copyright (C) 1993, 1994 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-struct link_struct {
- const char *name;
- int namelen;
- ext2_ino_t inode;
- int flags;
- int done;
- struct ext2_super_block *sb;
-};
-
-static int link_proc(struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *priv_data)
-{
- struct link_struct *ls = (struct link_struct *) priv_data;
- struct ext2_dir_entry *next;
- int rec_len, min_rec_len;
- int ret = 0;
-
- rec_len = EXT2_DIR_REC_LEN(ls->namelen);
-
- /*
- * See if the following directory entry (if any) is unused;
- * if so, absorb it into this one.
- */
- next = (struct ext2_dir_entry *) (buf + offset + dirent->rec_len);
- if ((offset + dirent->rec_len < blocksize - 8) &&
- (next->inode == 0) &&
- (offset + dirent->rec_len + next->rec_len <= blocksize)) {
- dirent->rec_len += next->rec_len;
- ret = DIRENT_CHANGED;
- }
-
- /*
- * If the directory entry is used, see if we can split the
- * directory entry to make room for the new name. If so,
- * truncate it and return.
- */
- if (dirent->inode) {
- min_rec_len = EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
- if (dirent->rec_len < (min_rec_len + rec_len))
- return ret;
- rec_len = dirent->rec_len - min_rec_len;
- dirent->rec_len = min_rec_len;
- next = (struct ext2_dir_entry *) (buf + offset +
- dirent->rec_len);
- next->inode = 0;
- next->name_len = 0;
- next->rec_len = rec_len;
- return DIRENT_CHANGED;
- }
-
- /*
- * If we get this far, then the directory entry is not used.
- * See if we can fit the request entry in. If so, do it.
- */
- if (dirent->rec_len < rec_len)
- return ret;
- dirent->inode = ls->inode;
- dirent->name_len = ls->namelen;
- strncpy(dirent->name, ls->name, ls->namelen);
- if (ls->sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
- dirent->name_len |= (ls->flags & 0x7) << 8;
-
- ls->done++;
- return DIRENT_ABORT|DIRENT_CHANGED;
-}
-
-/*
- * Note: the low 3 bits of the flags field are used as the directory
- * entry filetype.
- */
-#ifdef __TURBOC__
-# pragma argsused
-#endif
-errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name,
- ext2_ino_t ino, int flags)
-{
- errcode_t retval;
- struct link_struct ls;
- struct ext2_inode inode;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!(fs->flags & EXT2_FLAG_RW))
- return EXT2_ET_RO_FILSYS;
-
- ls.name = name;
- ls.namelen = name ? strlen(name) : 0;
- ls.inode = ino;
- ls.flags = flags;
- ls.done = 0;
- ls.sb = fs->super;
-
- retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY,
- 0, link_proc, &ls);
- if (retval)
- return retval;
-
- if (!ls.done)
- return EXT2_ET_DIR_NO_SPACE;
-
- if ((retval = ext2fs_read_inode(fs, dir, &inode)) != 0)
- return retval;
-
- if (inode.i_flags & EXT2_INDEX_FL) {
- inode.i_flags &= ~EXT2_INDEX_FL;
- if ((retval = ext2fs_write_inode(fs, dir, &inode)) != 0)
- return retval;
- }
-
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/lookup.c b/release/src/router/busybox/e2fsprogs/ext2fs/lookup.c
deleted file mode 100644
index b2e8de8ec5..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/lookup.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * lookup.c --- ext2fs directory lookup operations
- *
- * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-struct lookup_struct {
- const char *name;
- int len;
- ext2_ino_t *inode;
- int found;
-};
-
-#ifdef __TURBOC__
-# pragma argsused
-#endif
-static int lookup_proc(struct ext2_dir_entry *dirent,
- int offset EXT2FS_ATTR((unused)),
- int blocksize EXT2FS_ATTR((unused)),
- char *buf EXT2FS_ATTR((unused)),
- void *priv_data)
-{
- struct lookup_struct *ls = (struct lookup_struct *) priv_data;
-
- if (ls->len != (dirent->name_len & 0xFF))
- return 0;
- if (strncmp(ls->name, dirent->name, (dirent->name_len & 0xFF)))
- return 0;
- *ls->inode = dirent->inode;
- ls->found++;
- return DIRENT_ABORT;
-}
-
-
-errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name,
- int namelen, char *buf, ext2_ino_t *inode)
-{
- errcode_t retval;
- struct lookup_struct ls;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- ls.name = name;
- ls.len = namelen;
- ls.inode = inode;
- ls.found = 0;
-
- retval = ext2fs_dir_iterate(fs, dir, 0, buf, lookup_proc, &ls);
- if (retval)
- return retval;
-
- return (ls.found) ? 0 : EXT2_ET_FILE_NOT_FOUND;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/mkdir.c b/release/src/router/busybox/e2fsprogs/ext2fs/mkdir.c
deleted file mode 100644
index a86ac8e938..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/mkdir.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * mkdir.c --- make a directory in the filesystem
- *
- * Copyright (C) 1994, 1995 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-#ifndef EXT2_FT_DIR
-#define EXT2_FT_DIR 2
-#endif
-
-errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
- const char *name)
-{
- errcode_t retval;
- struct ext2_inode parent_inode, inode;
- ext2_ino_t ino = inum;
- ext2_ino_t scratch_ino;
- blk_t blk;
- char *block = NULL;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- /*
- * Allocate an inode, if necessary
- */
- if (!ino) {
- retval = ext2fs_new_inode(fs, parent, LINUX_S_IFDIR | 0755,
- 0, &ino);
- if (retval)
- goto cleanup;
- }
-
- /*
- * Allocate a data block for the directory
- */
- retval = ext2fs_new_block(fs, 0, 0, &blk);
- if (retval)
- goto cleanup;
-
- /*
- * Create a scratch template for the directory
- */
- retval = ext2fs_new_dir_block(fs, ino, parent, &block);
- if (retval)
- goto cleanup;
-
- /*
- * Get the parent's inode, if necessary
- */
- if (parent != ino) {
- retval = ext2fs_read_inode(fs, parent, &parent_inode);
- if (retval)
- goto cleanup;
- } else
- memset(&parent_inode, 0, sizeof(parent_inode));
-
- /*
- * Create the inode structure....
- */
- memset(&inode, 0, sizeof(struct ext2_inode));
- inode.i_mode = LINUX_S_IFDIR | (0777 & ~fs->umask);
- inode.i_uid = inode.i_gid = 0;
- inode.i_blocks = fs->blocksize / 512;
- inode.i_block[0] = blk;
- inode.i_links_count = 2;
- inode.i_ctime = inode.i_atime = inode.i_mtime = time(NULL);
- inode.i_size = fs->blocksize;
-
- /*
- * Write out the inode and inode data block
- */
- retval = ext2fs_write_dir_block(fs, blk, block);
- if (retval)
- goto cleanup;
- retval = ext2fs_write_new_inode(fs, ino, &inode);
- if (retval)
- goto cleanup;
-
- /*
- * Link the directory into the filesystem hierarchy
- */
- if (name) {
- retval = ext2fs_lookup(fs, parent, name, strlen(name), 0,
- &scratch_ino);
- if (!retval) {
- retval = EXT2_ET_DIR_EXISTS;
- name = 0;
- goto cleanup;
- }
- if (retval != EXT2_ET_FILE_NOT_FOUND)
- goto cleanup;
- retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_DIR);
- if (retval)
- goto cleanup;
- }
-
- /*
- * Update parent inode's counts
- */
- if (parent != ino) {
- parent_inode.i_links_count++;
- retval = ext2fs_write_inode(fs, parent, &parent_inode);
- if (retval)
- goto cleanup;
- }
-
- /*
- * Update accounting....
- */
- ext2fs_block_alloc_stats(fs, blk, +1);
- ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
-
-cleanup:
- ext2fs_free_mem(&block);
- return retval;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/mkjournal.c b/release/src/router/busybox/e2fsprogs/ext2fs/mkjournal.c
deleted file mode 100644
index 748d9abc70..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/mkjournal.c
+++ /dev/null
@@ -1,426 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * mkjournal.c --- make a journal for a filesystem
- *
- * Copyright (C) 2000 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#if HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#if HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-
-#include "ext2_fs.h"
-#include "../e2p/e2p.h"
-#include "../e2fsck.h"
-#include "ext2fs.h"
-#include "kernel-jbd.h"
-
-/*
- * This function automatically sets up the journal superblock and
- * returns it as an allocated block.
- */
-errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
- __u32 size, int flags,
- char **ret_jsb)
-{
- errcode_t retval;
- journal_superblock_t *jsb;
-
- if (size < 1024)
- return EXT2_ET_JOURNAL_TOO_SMALL;
-
- if ((retval = ext2fs_get_mem(fs->blocksize, &jsb)))
- return retval;
-
- memset (jsb, 0, fs->blocksize);
-
- jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
- if (flags & EXT2_MKJOURNAL_V1_SUPER)
- jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V1);
- else
- jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
- jsb->s_blocksize = htonl(fs->blocksize);
- jsb->s_maxlen = htonl(size);
- jsb->s_nr_users = htonl(1);
- jsb->s_first = htonl(1);
- jsb->s_sequence = htonl(1);
- memcpy(jsb->s_uuid, fs->super->s_uuid, sizeof(fs->super->s_uuid));
- /*
- * If we're creating an external journal device, we need to
- * adjust these fields.
- */
- if (fs->super->s_feature_incompat &
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
- jsb->s_nr_users = 0;
- if (fs->blocksize == 1024)
- jsb->s_first = htonl(3);
- else
- jsb->s_first = htonl(2);
- }
-
- *ret_jsb = (char *) jsb;
- return 0;
-}
-
-/*
- * This function writes a journal using POSIX routines. It is used
- * for creating external journals and creating journals on live
- * filesystems.
- */
-static errcode_t write_journal_file(ext2_filsys fs, char *filename,
- blk_t size, int flags)
-{
- errcode_t retval;
- char *buf = NULL;
- int fd, ret_size;
- blk_t i;
-
- if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf)))
- return retval;
-
- /* Open the device or journal file */
- if ((fd = open(filename, O_WRONLY)) < 0) {
- retval = errno;
- goto errout;
- }
-
- /* Write the superblock out */
- retval = EXT2_ET_SHORT_WRITE;
- ret_size = write(fd, buf, fs->blocksize);
- if (ret_size < 0) {
- retval = errno;
- goto errout;
- }
- if (ret_size != (int) fs->blocksize)
- goto errout;
- memset(buf, 0, fs->blocksize);
-
- for (i = 1; i < size; i++) {
- ret_size = write(fd, buf, fs->blocksize);
- if (ret_size < 0) {
- retval = errno;
- goto errout;
- }
- if (ret_size != (int) fs->blocksize)
- goto errout;
- }
- close(fd);
-
- retval = 0;
-errout:
- ext2fs_free_mem(&buf);
- return retval;
-}
-
-/*
- * Helper function for creating the journal using direct I/O routines
- */
-struct mkjournal_struct {
- int num_blocks;
- int newblocks;
- char *buf;
- errcode_t err;
-};
-
-static int mkjournal_proc(ext2_filsys fs,
- blk_t *blocknr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block EXT2FS_ATTR((unused)),
- int ref_offset EXT2FS_ATTR((unused)),
- void *priv_data)
-{
- struct mkjournal_struct *es = (struct mkjournal_struct *) priv_data;
- blk_t new_blk;
- static blk_t last_blk = 0;
- errcode_t retval;
-
- if (*blocknr) {
- last_blk = *blocknr;
- return 0;
- }
- retval = ext2fs_new_block(fs, last_blk, 0, &new_blk);
- if (retval) {
- es->err = retval;
- return BLOCK_ABORT;
- }
- if (blockcnt > 0)
- es->num_blocks--;
-
- es->newblocks++;
- retval = io_channel_write_blk(fs->io, new_blk, 1, es->buf);
-
- if (blockcnt == 0)
- memset(es->buf, 0, fs->blocksize);
-
- if (retval) {
- es->err = retval;
- return BLOCK_ABORT;
- }
- *blocknr = new_blk;
- last_blk = new_blk;
- ext2fs_block_alloc_stats(fs, new_blk, +1);
-
- if (es->num_blocks == 0)
- return (BLOCK_CHANGED | BLOCK_ABORT);
- else
- return BLOCK_CHANGED;
-}
-
-/*
- * This function creates a journal using direct I/O routines.
- */
-static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
- blk_t size, int flags)
-{
- char *buf;
- errcode_t retval;
- struct ext2_inode inode;
- struct mkjournal_struct es;
-
- if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf)))
- return retval;
-
- if ((retval = ext2fs_read_bitmaps(fs)))
- return retval;
-
- if ((retval = ext2fs_read_inode(fs, journal_ino, &inode)))
- return retval;
-
- if (inode.i_blocks > 0)
- return EEXIST;
-
- es.num_blocks = size;
- es.newblocks = 0;
- es.buf = buf;
- es.err = 0;
-
- retval = ext2fs_block_iterate2(fs, journal_ino, BLOCK_FLAG_APPEND,
- 0, mkjournal_proc, &es);
- if (es.err) {
- retval = es.err;
- goto errout;
- }
-
- if ((retval = ext2fs_read_inode(fs, journal_ino, &inode)))
- goto errout;
-
- inode.i_size += fs->blocksize * size;
- inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
- inode.i_mtime = inode.i_ctime = time(NULL);
- inode.i_links_count = 1;
- inode.i_mode = LINUX_S_IFREG | 0600;
-
- if ((retval = ext2fs_write_inode(fs, journal_ino, &inode)))
- goto errout;
- retval = 0;
-
- memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4);
- fs->super->s_jnl_blocks[16] = inode.i_size;
- fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
- ext2fs_mark_super_dirty(fs);
-
-errout:
- ext2fs_free_mem(&buf);
- return retval;
-}
-
-/*
- * This function adds a journal device to a filesystem
- */
-errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev)
-{
- struct stat st;
- errcode_t retval;
- char buf[1024];
- journal_superblock_t *jsb;
- int start;
- __u32 i, nr_users;
-
- /* Make sure the device exists and is a block device */
- if (stat(journal_dev->device_name, &st) < 0)
- return errno;
-
- if (!S_ISBLK(st.st_mode))
- return EXT2_ET_JOURNAL_NOT_BLOCK; /* Must be a block device */
-
- /* Get the journal superblock */
- start = 1;
- if (journal_dev->blocksize == 1024)
- start++;
- if ((retval = io_channel_read_blk(journal_dev->io, start, -1024, buf)))
- return retval;
-
- jsb = (journal_superblock_t *) buf;
- if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) ||
- (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2)))
- return EXT2_ET_NO_JOURNAL_SB;
-
- if (ntohl(jsb->s_blocksize) != (unsigned long) fs->blocksize)
- return EXT2_ET_UNEXPECTED_BLOCK_SIZE;
-
- /* Check and see if this filesystem has already been added */
- nr_users = ntohl(jsb->s_nr_users);
- for (i=0; i < nr_users; i++) {
- if (memcmp(fs->super->s_uuid,
- &jsb->s_users[i*16], 16) == 0)
- break;
- }
- if (i >= nr_users) {
- memcpy(&jsb->s_users[nr_users*16],
- fs->super->s_uuid, 16);
- jsb->s_nr_users = htonl(nr_users+1);
- }
-
- /* Writeback the journal superblock */
- if ((retval = io_channel_write_blk(journal_dev->io, start, -1024, buf)))
- return retval;
-
- fs->super->s_journal_inum = 0;
- fs->super->s_journal_dev = st.st_rdev;
- memcpy(fs->super->s_journal_uuid, jsb->s_uuid,
- sizeof(fs->super->s_journal_uuid));
- fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
- ext2fs_mark_super_dirty(fs);
- return 0;
-}
-
-/*
- * This function adds a journal inode to a filesystem, using either
- * POSIX routines if the filesystem is mounted, or using direct I/O
- * functions if it is not.
- */
-errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size, int flags)
-{
- errcode_t retval;
- ext2_ino_t journal_ino;
- struct stat st;
- char jfile[1024];
- int fd, mount_flags, f;
-
- retval = ext2fs_check_mount_point(fs->device_name, &mount_flags,
- jfile, sizeof(jfile)-10);
- if (retval)
- return retval;
-
- if (mount_flags & EXT2_MF_MOUNTED) {
- strcat(jfile, "/.journal");
-
- /*
- * If .../.journal already exists, make sure any
- * immutable or append-only flags are cleared.
- */
-#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP)
- (void) chflags (jfile, 0);
-#else
-#if HAVE_EXT2_IOCTLS
- fd = open(jfile, O_RDONLY);
- if (fd >= 0) {
- f = 0;
- ioctl(fd, EXT2_IOC_SETFLAGS, &f);
- close(fd);
- }
-#endif
-#endif
-
- /* Create the journal file */
- if ((fd = open(jfile, O_CREAT|O_WRONLY, 0600)) < 0)
- return errno;
-
- if ((retval = write_journal_file(fs, jfile, size, flags)))
- goto errout;
-
- /* Get inode number of the journal file */
- if (fstat(fd, &st) < 0)
- goto errout;
-
-#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP)
- retval = fchflags (fd, UF_NODUMP|UF_IMMUTABLE);
-#else
-#if HAVE_EXT2_IOCTLS
- f = EXT2_NODUMP_FL | EXT2_IMMUTABLE_FL;
- retval = ioctl(fd, EXT2_IOC_SETFLAGS, &f);
-#endif
-#endif
- if (retval)
- goto errout;
-
- close(fd);
- journal_ino = st.st_ino;
- } else {
- journal_ino = EXT2_JOURNAL_INO;
- if ((retval = write_journal_inode(fs, journal_ino,
- size, flags)))
- return retval;
- }
-
- fs->super->s_journal_inum = journal_ino;
- fs->super->s_journal_dev = 0;
- memset(fs->super->s_journal_uuid, 0,
- sizeof(fs->super->s_journal_uuid));
- fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
-
- ext2fs_mark_super_dirty(fs);
- return 0;
-errout:
- close(fd);
- return retval;
-}
-
-#ifdef DEBUG
-main(int argc, char **argv)
-{
- errcode_t retval;
- char *device_name;
- ext2_filsys fs;
-
- if (argc < 2) {
- fprintf(stderr, "Usage: %s filesystem\n", argv[0]);
- exit(1);
- }
- device_name = argv[1];
-
- retval = ext2fs_open (device_name, EXT2_FLAG_RW, 0, 0,
- unix_io_manager, &fs);
- if (retval) {
- com_err(argv[0], retval, "while opening %s", device_name);
- exit(1);
- }
-
- retval = ext2fs_add_journal_inode(fs, 1024);
- if (retval) {
- com_err(argv[0], retval, "while adding journal to %s",
- device_name);
- exit(1);
- }
- retval = ext2fs_flush(fs);
- if (retval) {
- printf("Warning, had trouble writing out superblocks.\n");
- }
- ext2fs_close(fs);
- exit(0);
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/namei.c b/release/src/router/busybox/e2fsprogs/ext2fs/namei.c
deleted file mode 100644
index 18244613c6..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/namei.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * namei.c --- ext2fs directory lookup operations
- *
- * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-/* #define NAMEI_DEBUG */
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base,
- const char *pathname, size_t pathlen, int follow,
- int link_count, char *buf, ext2_ino_t *res_inode);
-
-static errcode_t follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir,
- ext2_ino_t inode, int link_count,
- char *buf, ext2_ino_t *res_inode)
-{
- char *pathname;
- char *buffer = NULL;
- errcode_t retval;
- struct ext2_inode ei;
-
-#ifdef NAMEI_DEBUG
- printf("follow_link: root=%lu, dir=%lu, inode=%lu, lc=%d\n",
- root, dir, inode, link_count);
-
-#endif
- retval = ext2fs_read_inode (fs, inode, &ei);
- if (retval) return retval;
- if (!LINUX_S_ISLNK (ei.i_mode)) {
- *res_inode = inode;
- return 0;
- }
- if (link_count++ > 5) {
- return EXT2_ET_SYMLINK_LOOP;
- }
- if (ext2fs_inode_data_blocks(fs, &ei)) {
- retval = ext2fs_get_mem(fs->blocksize, &buffer);
- if (retval)
- return retval;
- retval = io_channel_read_blk(fs->io, ei.i_block[0], 1, buffer);
- if (retval) {
- ext2fs_free_mem(&buffer);
- return retval;
- }
- pathname = buffer;
- } else
- pathname = (char *)&(ei.i_block[0]);
- retval = open_namei(fs, root, dir, pathname, ei.i_size, 1,
- link_count, buf, res_inode);
- ext2fs_free_mem(&buffer);
- return retval;
-}
-
-/*
- * This routine interprets a pathname in the context of the current
- * directory and the root directory, and returns the inode of the
- * containing directory, and a pointer to the filename of the file
- * (pointing into the pathname) and the length of the filename.
- */
-static errcode_t dir_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir,
- const char *pathname, int pathlen,
- int link_count, char *buf,
- const char **name, int *namelen,
- ext2_ino_t *res_inode)
-{
- char c;
- const char *thisname;
- int len;
- ext2_ino_t inode;
- errcode_t retval;
-
- if ((c = *pathname) == '/') {
- dir = root;
- pathname++;
- pathlen--;
- }
- while (1) {
- thisname = pathname;
- for (len=0; --pathlen >= 0;len++) {
- c = *(pathname++);
- if (c == '/')
- break;
- }
- if (pathlen < 0)
- break;
- retval = ext2fs_lookup (fs, dir, thisname, len, buf, &inode);
- if (retval) return retval;
- retval = follow_link (fs, root, dir, inode,
- link_count, buf, &dir);
- if (retval) return retval;
- }
- *name = thisname;
- *namelen = len;
- *res_inode = dir;
- return 0;
-}
-
-static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base,
- const char *pathname, size_t pathlen, int follow,
- int link_count, char *buf, ext2_ino_t *res_inode)
-{
- const char *basename;
- int namelen;
- ext2_ino_t dir, inode;
- errcode_t retval;
-
-#ifdef NAMEI_DEBUG
- printf("open_namei: root=%lu, dir=%lu, path=%*s, lc=%d\n",
- root, base, pathlen, pathname, link_count);
-#endif
- retval = dir_namei(fs, root, base, pathname, pathlen,
- link_count, buf, &basename, &namelen, &dir);
- if (retval) return retval;
- if (!namelen) { /* special case: '/usr/' etc */
- *res_inode=dir;
- return 0;
- }
- retval = ext2fs_lookup (fs, dir, basename, namelen, buf, &inode);
- if (retval)
- return retval;
- if (follow) {
- retval = follow_link(fs, root, dir, inode, link_count,
- buf, &inode);
- if (retval)
- return retval;
- }
-#ifdef NAMEI_DEBUG
- printf("open_namei: (link_count=%d) returns %lu\n",
- link_count, inode);
-#endif
- *res_inode = inode;
- return 0;
-}
-
-errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
- const char *name, ext2_ino_t *inode)
-{
- char *buf;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- retval = ext2fs_get_mem(fs->blocksize, &buf);
- if (retval)
- return retval;
-
- retval = open_namei(fs, root, cwd, name, strlen(name), 0, 0,
- buf, inode);
-
- ext2fs_free_mem(&buf);
- return retval;
-}
-
-errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
- const char *name, ext2_ino_t *inode)
-{
- char *buf;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- retval = ext2fs_get_mem(fs->blocksize, &buf);
- if (retval)
- return retval;
-
- retval = open_namei(fs, root, cwd, name, strlen(name), 1, 0,
- buf, inode);
-
- ext2fs_free_mem(&buf);
- return retval;
-}
-
-errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
- ext2_ino_t inode, ext2_ino_t *res_inode)
-{
- char *buf;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- retval = ext2fs_get_mem(fs->blocksize, &buf);
- if (retval)
- return retval;
-
- retval = follow_link(fs, root, cwd, inode, 0, buf, res_inode);
-
- ext2fs_free_mem(&buf);
- return retval;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/newdir.c b/release/src/router/busybox/e2fsprogs/ext2fs/newdir.c
deleted file mode 100644
index 9f156626d8..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/newdir.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * newdir.c --- create a new directory block
- *
- * Copyright (C) 1994, 1995 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-#ifndef EXT2_FT_DIR
-#define EXT2_FT_DIR 2
-#endif
-
-/*
- * Create new directory block
- */
-errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino,
- ext2_ino_t parent_ino, char **block)
-{
- struct ext2_dir_entry *dir = NULL;
- errcode_t retval;
- char *buf;
- int rec_len;
- int filetype = 0;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- retval = ext2fs_get_mem(fs->blocksize, &buf);
- if (retval)
- return retval;
- memset(buf, 0, fs->blocksize);
- dir = (struct ext2_dir_entry *) buf;
- dir->rec_len = fs->blocksize;
-
- if (dir_ino) {
- if (fs->super->s_feature_incompat &
- EXT2_FEATURE_INCOMPAT_FILETYPE)
- filetype = EXT2_FT_DIR << 8;
- /*
- * Set up entry for '.'
- */
- dir->inode = dir_ino;
- dir->name_len = 1 | filetype;
- dir->name[0] = '.';
- rec_len = dir->rec_len - EXT2_DIR_REC_LEN(1);
- dir->rec_len = EXT2_DIR_REC_LEN(1);
-
- /*
- * Set up entry for '..'
- */
- dir = (struct ext2_dir_entry *) (buf + dir->rec_len);
- dir->rec_len = rec_len;
- dir->inode = parent_ino;
- dir->name_len = 2 | filetype;
- dir->name[0] = '.';
- dir->name[1] = '.';
- }
- *block = buf;
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/openfs.c b/release/src/router/busybox/e2fsprogs/ext2fs/openfs.c
deleted file mode 100644
index 1b271196b1..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/openfs.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * openfs.c --- open an ext2 filesystem
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-
-
-#include "ext2fs.h"
-#include "e2image.h"
-
-blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, dgrp_t i)
-{
- int bg;
- int has_super = 0;
- int ret_blk;
-
- if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
- (i < fs->super->s_first_meta_bg))
- return (group_block + i + 1);
-
- bg = (fs->blocksize / sizeof (struct ext2_group_desc)) * i;
- if (ext2fs_bg_has_super(fs, bg))
- has_super = 1;
- ret_blk = (fs->super->s_first_data_block + has_super +
- (bg * fs->super->s_blocks_per_group));
- /*
- * If group_block is not the normal value, we're trying to use
- * the backup group descriptors and superblock --- so use the
- * alternate location of the second block group in the
- * metablock group. Ideally we should be testing each bg
- * descriptor block individually for correctness, but we don't
- * have the infrastructure in place to do that.
- */
- if (group_block != fs->super->s_first_data_block &&
- ((ret_blk + fs->super->s_blocks_per_group) <
- fs->super->s_blocks_count))
- ret_blk += fs->super->s_blocks_per_group;
- return ret_blk;
-}
-
-errcode_t ext2fs_open(const char *name, int flags, int superblock,
- unsigned int block_size, io_manager manager,
- ext2_filsys *ret_fs)
-{
- return ext2fs_open2(name, 0, flags, superblock, block_size,
- manager, ret_fs);
-}
-
-/*
- * Note: if superblock is non-zero, block-size must also be non-zero.
- * Superblock and block_size can be zero to use the default size.
- *
- * Valid flags for ext2fs_open()
- *
- * EXT2_FLAG_RW - Open the filesystem for read/write.
- * EXT2_FLAG_FORCE - Open the filesystem even if some of the
- * features aren't supported.
- * EXT2_FLAG_JOURNAL_DEV_OK - Open an ext3 journal device
- */
-errcode_t ext2fs_open2(const char *name, const char *io_options,
- int flags, int superblock,
- unsigned int block_size, io_manager manager,
- ext2_filsys *ret_fs)
-{
- ext2_filsys fs;
- errcode_t retval;
- unsigned long i;
- int groups_per_block, blocks_per_group;
- blk_t group_block, blk;
- char *dest, *cp;
-#if BB_BIG_ENDIAN
- int j;
- struct ext2_group_desc *gdp;
-#endif
-
- EXT2_CHECK_MAGIC(manager, EXT2_ET_MAGIC_IO_MANAGER);
-
- retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
- if (retval)
- return retval;
-
- memset(fs, 0, sizeof(struct struct_ext2_filsys));
- fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS;
- fs->flags = flags;
- fs->umask = 022;
- retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name);
- if (retval)
- goto cleanup;
- strcpy(fs->device_name, name);
- cp = strchr(fs->device_name, '?');
- if (!io_options && cp) {
- *cp++ = 0;
- io_options = cp;
- }
-
- retval = manager->open(fs->device_name,
- (flags & EXT2_FLAG_RW) ? IO_FLAG_RW : 0,
- &fs->io);
- if (retval)
- goto cleanup;
- if (io_options &&
- (retval = io_channel_set_options(fs->io, io_options)))
- goto cleanup;
- fs->image_io = fs->io;
- fs->io->app_data = fs;
- retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->super);
- if (retval)
- goto cleanup;
- if (flags & EXT2_FLAG_IMAGE_FILE) {
- retval = ext2fs_get_mem(sizeof(struct ext2_image_hdr),
- &fs->image_header);
- if (retval)
- goto cleanup;
- retval = io_channel_read_blk(fs->io, 0,
- -(int)sizeof(struct ext2_image_hdr),
- fs->image_header);
- if (retval)
- goto cleanup;
- if (fs->image_header->magic_number != EXT2_ET_MAGIC_E2IMAGE)
- return EXT2_ET_MAGIC_E2IMAGE;
- superblock = 1;
- block_size = fs->image_header->fs_blocksize;
- }
-
- /*
- * If the user specifies a specific block # for the
- * superblock, then he/she must also specify the block size!
- * Otherwise, read the master superblock located at offset
- * SUPERBLOCK_OFFSET from the start of the partition.
- *
- * Note: we only save a backup copy of the superblock if we
- * are reading the superblock from the primary superblock location.
- */
- if (superblock) {
- if (!block_size) {
- retval = EXT2_ET_INVALID_ARGUMENT;
- goto cleanup;
- }
- io_channel_set_blksize(fs->io, block_size);
- group_block = superblock;
- fs->orig_super = 0;
- } else {
- io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET);
- superblock = 1;
- group_block = 0;
- retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super);
- if (retval)
- goto cleanup;
- }
- retval = io_channel_read_blk(fs->io, superblock, -SUPERBLOCK_SIZE,
- fs->super);
- if (retval)
- goto cleanup;
- if (fs->orig_super)
- memcpy(fs->orig_super, fs->super, SUPERBLOCK_SIZE);
-
-#if BB_BIG_ENDIAN
- if ((fs->super->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC)) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES)) {
- fs->flags |= EXT2_FLAG_SWAP_BYTES;
-
- ext2fs_swap_super(fs->super);
- }
-#endif
-
- if (fs->super->s_magic != EXT2_SUPER_MAGIC) {
- retval = EXT2_ET_BAD_MAGIC;
- goto cleanup;
- }
- if (fs->super->s_rev_level > EXT2_LIB_CURRENT_REV) {
- retval = EXT2_ET_REV_TOO_HIGH;
- goto cleanup;
- }
-
- /*
- * Check for feature set incompatibility
- */
- if (!(flags & EXT2_FLAG_FORCE)) {
- if (fs->super->s_feature_incompat &
- ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) {
- retval = EXT2_ET_UNSUPP_FEATURE;
- goto cleanup;
- }
- if ((flags & EXT2_FLAG_RW) &&
- (fs->super->s_feature_ro_compat &
- ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP)) {
- retval = EXT2_ET_RO_UNSUPP_FEATURE;
- goto cleanup;
- }
- if (!(flags & EXT2_FLAG_JOURNAL_DEV_OK) &&
- (fs->super->s_feature_incompat &
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
- retval = EXT2_ET_UNSUPP_FEATURE;
- goto cleanup;
- }
- }
-
- fs->blocksize = EXT2_BLOCK_SIZE(fs->super);
- if (fs->blocksize == 0) {
- retval = EXT2_ET_CORRUPT_SUPERBLOCK;
- goto cleanup;
- }
- fs->fragsize = EXT2_FRAG_SIZE(fs->super);
- fs->inode_blocks_per_group = ((fs->super->s_inodes_per_group *
- EXT2_INODE_SIZE(fs->super) +
- EXT2_BLOCK_SIZE(fs->super) - 1) /
- EXT2_BLOCK_SIZE(fs->super));
- if (block_size) {
- if (block_size != fs->blocksize) {
- retval = EXT2_ET_UNEXPECTED_BLOCK_SIZE;
- goto cleanup;
- }
- }
- /*
- * Set the blocksize to the filesystem's blocksize.
- */
- io_channel_set_blksize(fs->io, fs->blocksize);
-
- /*
- * If this is an external journal device, don't try to read
- * the group descriptors, because they're not there.
- */
- if (fs->super->s_feature_incompat &
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
- fs->group_desc_count = 0;
- *ret_fs = fs;
- return 0;
- }
-
- /*
- * Read group descriptors
- */
- blocks_per_group = EXT2_BLOCKS_PER_GROUP(fs->super);
- if (blocks_per_group == 0 ||
- blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(fs->super) ||
- fs->inode_blocks_per_group > EXT2_MAX_INODES_PER_GROUP(fs->super)) {
- retval = EXT2_ET_CORRUPT_SUPERBLOCK;
- goto cleanup;
- }
- fs->group_desc_count = (fs->super->s_blocks_count -
- fs->super->s_first_data_block +
- blocks_per_group - 1) / blocks_per_group;
- fs->desc_blocks = (fs->group_desc_count +
- EXT2_DESC_PER_BLOCK(fs->super) - 1)
- / EXT2_DESC_PER_BLOCK(fs->super);
- retval = ext2fs_get_mem(fs->desc_blocks * fs->blocksize,
- &fs->group_desc);
- if (retval)
- goto cleanup;
- if (!group_block)
- group_block = fs->super->s_first_data_block;
- dest = (char *) fs->group_desc;
- groups_per_block = fs->blocksize / sizeof(struct ext2_group_desc);
- for (i = 0; i < fs->desc_blocks; i++) {
- blk = ext2fs_descriptor_block_loc(fs, group_block, i);
- retval = io_channel_read_blk(fs->io, blk, 1, dest);
- if (retval)
- goto cleanup;
-#if BB_BIG_ENDIAN
- if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
- gdp = (struct ext2_group_desc *) dest;
- for (j=0; j < groups_per_block; j++)
- ext2fs_swap_group_desc(gdp++);
- }
-#endif
- dest += fs->blocksize;
- }
-
- *ret_fs = fs;
- return 0;
-cleanup:
- ext2fs_free(fs);
- return retval;
-}
-
-/*
- * Set/get the filesystem data I/O channel.
- *
- * These functions are only valid if EXT2_FLAG_IMAGE_FILE is true.
- */
-errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io)
-{
- if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0)
- return EXT2_ET_NOT_IMAGE_FILE;
- if (old_io) {
- *old_io = (fs->image_io == fs->io) ? 0 : fs->io;
- }
- return 0;
-}
-
-errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io)
-{
- if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0)
- return EXT2_ET_NOT_IMAGE_FILE;
- fs->io = new_io ? new_io : fs->image_io;
- return 0;
-}
-
-errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io)
-{
- if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0)
- return EXT2_ET_NOT_IMAGE_FILE;
- fs->io = fs->image_io = new_io;
- fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_RW |
- EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
- fs->flags &= ~EXT2_FLAG_IMAGE_FILE;
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/read_bb.c b/release/src/router/busybox/e2fsprogs/ext2fs/read_bb.c
deleted file mode 100644
index ce77bc9f6b..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/read_bb.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * read_bb --- read the bad blocks inode
- *
- * Copyright (C) 1994 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-struct read_bb_record {
- ext2_badblocks_list bb_list;
- errcode_t err;
-};
-
-/*
- * Helper function for ext2fs_read_bb_inode()
- */
-#ifdef __TURBOC__
-# pragma argsused
-#endif
-static int mark_bad_block(ext2_filsys fs, blk_t *block_nr,
- e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
- blk_t ref_block EXT2FS_ATTR((unused)),
- int ref_offset EXT2FS_ATTR((unused)),
- void *priv_data)
-{
- struct read_bb_record *rb = (struct read_bb_record *) priv_data;
-
- if (blockcnt < 0)
- return 0;
-
- if ((*block_nr < fs->super->s_first_data_block) ||
- (*block_nr >= fs->super->s_blocks_count))
- return 0; /* Ignore illegal blocks */
-
- rb->err = ext2fs_badblocks_list_add(rb->bb_list, *block_nr);
- if (rb->err)
- return BLOCK_ABORT;
- return 0;
-}
-
-/*
- * Reads the current bad blocks from the bad blocks inode.
- */
-errcode_t ext2fs_read_bb_inode(ext2_filsys fs, ext2_badblocks_list *bb_list)
-{
- errcode_t retval;
- struct read_bb_record rb;
- struct ext2_inode inode;
- blk_t numblocks;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!*bb_list) {
- retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode);
- if (retval)
- return retval;
- if (inode.i_blocks < 500)
- numblocks = (inode.i_blocks /
- (fs->blocksize / 512)) + 20;
- else
- numblocks = 500;
- retval = ext2fs_badblocks_list_create(bb_list, numblocks);
- if (retval)
- return retval;
- }
-
- rb.bb_list = *bb_list;
- rb.err = 0;
- retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, 0, 0,
- mark_bad_block, &rb);
- if (retval)
- return retval;
-
- return rb.err;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/read_bb_file.c b/release/src/router/busybox/e2fsprogs/ext2fs/read_bb_file.c
deleted file mode 100644
index bf1fc328be..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/read_bb_file.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * read_bb_file.c --- read a list of bad blocks from a FILE *
- *
- * Copyright (C) 1994, 1995, 2000 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * Reads a list of bad blocks from a FILE *
- */
-errcode_t ext2fs_read_bb_FILE2(ext2_filsys fs, FILE *f,
- ext2_badblocks_list *bb_list,
- void *priv_data,
- void (*invalid)(ext2_filsys fs,
- blk_t blk,
- char *badstr,
- void *priv_data))
-{
- errcode_t retval;
- blk_t blockno;
- int count;
- char buf[128];
-
- if (fs)
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!*bb_list) {
- retval = ext2fs_badblocks_list_create(bb_list, 10);
- if (retval)
- return retval;
- }
-
- while (!feof (f)) {
- if (fgets(buf, sizeof(buf), f) == NULL)
- break;
- count = sscanf(buf, "%u", &blockno);
- if (count <= 0)
- continue;
- if (fs &&
- ((blockno < fs->super->s_first_data_block) ||
- (blockno >= fs->super->s_blocks_count))) {
- if (invalid)
- (invalid)(fs, blockno, buf, priv_data);
- continue;
- }
- retval = ext2fs_badblocks_list_add(*bb_list, blockno);
- if (retval)
- return retval;
- }
- return 0;
-}
-
-static void call_compat_invalid(ext2_filsys fs, blk_t blk,
- char *badstr EXT2FS_ATTR((unused)),
- void *priv_data)
-{
- void (*invalid)(ext2_filsys, blk_t);
-
- invalid = (void (*)(ext2_filsys, blk_t)) priv_data;
- if (invalid)
- invalid(fs, blk);
-}
-
-
-/*
- * Reads a list of bad blocks from a FILE *
- */
-errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f,
- ext2_badblocks_list *bb_list,
- void (*invalid)(ext2_filsys fs, blk_t blk))
-{
- return ext2fs_read_bb_FILE2(fs, f, bb_list, (void *) invalid,
- call_compat_invalid);
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/res_gdt.c b/release/src/router/busybox/e2fsprogs/ext2fs/res_gdt.c
deleted file mode 100644
index 403463a90f..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/res_gdt.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * res_gdt.c --- reserve blocks for growing the group descriptor table
- * during online resizing.
- *
- * Copyright (C) 2002 Andreas Dilger
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * Iterate through the groups which hold BACKUP superblock/GDT copies in an
- * ext3 filesystem. The counters should be initialized to 1, 5, and 7 before
- * calling this for the first time. In a sparse filesystem it will be the
- * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ...
- * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ...
- */
-static unsigned int list_backups(ext2_filsys fs, unsigned int *three,
- unsigned int *five, unsigned int *seven)
-{
- unsigned int *min = three;
- int mult = 3;
- unsigned int ret;
-
- if (!(fs->super->s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
- ret = *min;
- *min += 1;
- return ret;
- }
-
- if (*five < *min) {
- min = five;
- mult = 5;
- }
- if (*seven < *min) {
- min = seven;
- mult = 7;
- }
-
- ret = *min;
- *min *= mult;
-
- return ret;
-}
-
-/*
- * This code assumes that the reserved blocks have already been marked in-use
- * during ext2fs_initialize(), so that they are not allocated for other
- * uses before we can add them to the resize inode (which has to come
- * after the creation of the inode table).
- */
-errcode_t ext2fs_create_resize_inode(ext2_filsys fs)
-{
- errcode_t retval, retval2;
- struct ext2_super_block *sb;
- struct ext2_inode inode;
- __u32 *dindir_buf, *gdt_buf;
- int rsv_add;
- unsigned long long apb, inode_size;
- blk_t dindir_blk, rsv_off, gdt_off, gdt_blk;
- int dindir_dirty = 0, inode_dirty = 0;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- sb = fs->super;
-
- retval = ext2fs_get_mem(2 * fs->blocksize, (void *)&dindir_buf);
- if (retval)
- goto out_free;
- gdt_buf = (__u32 *)((char *)dindir_buf + fs->blocksize);
-
- retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
- if (retval)
- goto out_free;
-
- /* Maximum possible file size (we donly use the dindirect blocks) */
- apb = EXT2_ADDR_PER_BLOCK(sb);
- rsv_add = fs->blocksize / 512;
- if ((dindir_blk = inode.i_block[EXT2_DIND_BLOCK])) {
-#ifdef RES_GDT_DEBUG
- printf("reading GDT dindir %u\n", dindir_blk);
-#endif
- retval = ext2fs_read_ind_block(fs, dindir_blk, dindir_buf);
- if (retval)
- goto out_inode;
- } else {
- blk_t goal = 3 + sb->s_reserved_gdt_blocks +
- fs->desc_blocks + fs->inode_blocks_per_group;
-
- retval = ext2fs_alloc_block(fs, goal, 0, &dindir_blk);
- if (retval)
- goto out_free;
- inode.i_mode = LINUX_S_IFREG | 0600;
- inode.i_links_count = 1;
- inode.i_block[EXT2_DIND_BLOCK] = dindir_blk;
- inode.i_blocks = rsv_add;
- memset(dindir_buf, 0, fs->blocksize);
-#ifdef RES_GDT_DEBUG
- printf("allocated GDT dindir %u\n", dindir_blk);
-#endif
- dindir_dirty = inode_dirty = 1;
- inode_size = apb*apb + apb + EXT2_NDIR_BLOCKS;
- inode_size *= fs->blocksize;
- inode.i_size = inode_size & 0xFFFFFFFF;
- inode.i_size_high = (inode_size >> 32) & 0xFFFFFFFF;
- if (inode.i_size_high) {
- sb->s_feature_ro_compat |=
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
- }
- inode.i_ctime = time(NULL);
- }
-
- for (rsv_off = 0, gdt_off = fs->desc_blocks,
- gdt_blk = sb->s_first_data_block + 1 + fs->desc_blocks;
- rsv_off < sb->s_reserved_gdt_blocks;
- rsv_off++, gdt_off++, gdt_blk++) {
- unsigned int three = 1, five = 5, seven = 7;
- unsigned int grp, last = 0;
- int gdt_dirty = 0;
-
- gdt_off %= apb;
- if (!dindir_buf[gdt_off]) {
- /* FIXME XXX XXX
- blk_t new_blk;
-
- retval = ext2fs_new_block(fs, gdt_blk, 0, &new_blk);
- if (retval)
- goto out_free;
- if (new_blk != gdt_blk) {
- // XXX free block
- retval = -1; // XXX
- }
- */
- gdt_dirty = dindir_dirty = inode_dirty = 1;
- memset(gdt_buf, 0, fs->blocksize);
- dindir_buf[gdt_off] = gdt_blk;
- inode.i_blocks += rsv_add;
-#ifdef RES_GDT_DEBUG
- printf("added primary GDT block %u at %u[%u]\n",
- gdt_blk, dindir_blk, gdt_off);
-#endif
- } else if (dindir_buf[gdt_off] == gdt_blk) {
-#ifdef RES_GDT_DEBUG
- printf("reading primary GDT block %u\n", gdt_blk);
-#endif
- retval = ext2fs_read_ind_block(fs, gdt_blk, gdt_buf);
- if (retval)
- goto out_dindir;
- } else {
-#ifdef RES_GDT_DEBUG
- printf("bad primary GDT %u != %u at %u[%u]\n",
- dindir_buf[gdt_off], gdt_blk,dindir_blk,gdt_off);
-#endif
- retval = EXT2_ET_RESIZE_INODE_CORRUPT;
- goto out_dindir;
- }
-
- while ((grp = list_backups(fs, &three, &five, &seven)) <
- fs->group_desc_count) {
- blk_t expect = gdt_blk + grp * sb->s_blocks_per_group;
-
- if (!gdt_buf[last]) {
-#ifdef RES_GDT_DEBUG
- printf("added backup GDT %u grp %u@%u[%u]\n",
- expect, grp, gdt_blk, last);
-#endif
- gdt_buf[last] = expect;
- inode.i_blocks += rsv_add;
- gdt_dirty = inode_dirty = 1;
- } else if (gdt_buf[last] != expect) {
-#ifdef RES_GDT_DEBUG
- printf("bad backup GDT %u != %u at %u[%u]\n",
- gdt_buf[last], expect, gdt_blk, last);
-#endif
- retval = EXT2_ET_RESIZE_INODE_CORRUPT;
- goto out_dindir;
- }
- last++;
- }
- if (gdt_dirty) {
-#ifdef RES_GDT_DEBUG
- printf("writing primary GDT block %u\n", gdt_blk);
-#endif
- retval = ext2fs_write_ind_block(fs, gdt_blk, gdt_buf);
- if (retval)
- goto out_dindir;
- }
- }
-
-out_dindir:
- if (dindir_dirty) {
- retval2 = ext2fs_write_ind_block(fs, dindir_blk, dindir_buf);
- if (!retval)
- retval = retval2;
- }
-out_inode:
-#ifdef RES_GDT_DEBUG
- printf("inode.i_blocks = %u, i_size = %u\n", inode.i_blocks,
- inode.i_size);
-#endif
- if (inode_dirty) {
- inode.i_atime = inode.i_mtime = time(NULL);
- retval2 = ext2fs_write_inode(fs, EXT2_RESIZE_INO, &inode);
- if (!retval)
- retval = retval2;
- }
-out_free:
- ext2fs_free_mem((void *)&dindir_buf);
- return retval;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/rs_bitmap.c b/release/src/router/busybox/e2fsprogs/ext2fs/rs_bitmap.c
deleted file mode 100644
index 32e87b77a9..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/rs_bitmap.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * rs_bitmap.c --- routine for changing the size of a bitmap
- *
- * Copyright (C) 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-errcode_t ext2fs_resize_generic_bitmap(__u32 new_end, __u32 new_real_end,
- ext2fs_generic_bitmap bmap)
-{
- errcode_t retval;
- size_t size, new_size;
- __u32 bitno;
-
- if (!bmap)
- return EXT2_ET_INVALID_ARGUMENT;
-
- EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_GENERIC_BITMAP);
-
- /*
- * If we're expanding the bitmap, make sure all of the new
- * parts of the bitmap are zero.
- */
- if (new_end > bmap->end) {
- bitno = bmap->real_end;
- if (bitno > new_end)
- bitno = new_end;
- for (; bitno > bmap->end; bitno--)
- ext2fs_clear_bit(bitno - bmap->start, bmap->bitmap);
- }
- if (new_real_end == bmap->real_end) {
- bmap->end = new_end;
- return 0;
- }
-
- size = ((bmap->real_end - bmap->start) / 8) + 1;
- new_size = ((new_real_end - bmap->start) / 8) + 1;
-
- if (size != new_size) {
- retval = ext2fs_resize_mem(size, new_size, &bmap->bitmap);
- if (retval)
- return retval;
- }
- if (new_size > size)
- memset(bmap->bitmap + size, 0, new_size - size);
-
- bmap->end = new_end;
- bmap->real_end = new_real_end;
- return 0;
-}
-
-errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
- ext2fs_inode_bitmap bmap)
-{
- errcode_t retval;
-
- if (!bmap)
- return EXT2_ET_INVALID_ARGUMENT;
-
- EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_INODE_BITMAP);
-
- bmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
- retval = ext2fs_resize_generic_bitmap(new_end, new_real_end,
- bmap);
- bmap->magic = EXT2_ET_MAGIC_INODE_BITMAP;
- return retval;
-}
-
-errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
- ext2fs_block_bitmap bmap)
-{
- errcode_t retval;
-
- if (!bmap)
- return EXT2_ET_INVALID_ARGUMENT;
-
- EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_BLOCK_BITMAP);
-
- bmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
- retval = ext2fs_resize_generic_bitmap(new_end, new_real_end,
- bmap);
- bmap->magic = EXT2_ET_MAGIC_BLOCK_BITMAP;
- return retval;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/rw_bitmaps.c b/release/src/router/busybox/e2fsprogs/ext2fs/rw_bitmaps.c
deleted file mode 100644
index bba4326796..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/rw_bitmaps.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * rw_bitmaps.c --- routines to read and write the inode and block bitmaps.
- *
- * Copyright (C) 1993, 1994, 1994, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-#include "e2image.h"
-
-#if defined(__powerpc__) && BB_BIG_ENDIAN
-/*
- * On the PowerPC, the big-endian variant of the ext2 filesystem
- * has its bitmaps stored as 32-bit words with bit 0 as the LSB
- * of each word. Thus a bitmap with only bit 0 set would be, as
- * a string of bytes, 00 00 00 01 00 ...
- * To cope with this, we byte-reverse each word of a bitmap if
- * we have a big-endian filesystem, that is, if we are *not*
- * byte-swapping other word-sized numbers.
- */
-#define EXT2_BIG_ENDIAN_BITMAPS
-#endif
-
-#ifdef EXT2_BIG_ENDIAN_BITMAPS
-static void ext2fs_swap_bitmap(ext2_filsys fs, char *bitmap, int nbytes)
-{
- __u32 *p = (__u32 *) bitmap;
- int n;
-
- for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
- *p = ext2fs_swab32(*p);
-}
-#endif
-
-errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs)
-{
- dgrp_t i;
- size_t nbytes;
- errcode_t retval;
- char * inode_bitmap = fs->inode_map->bitmap;
- char * bitmap_block = NULL;
- blk_t blk;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!(fs->flags & EXT2_FLAG_RW))
- return EXT2_ET_RO_FILSYS;
- if (!inode_bitmap)
- return 0;
- nbytes = (size_t) ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8);
-
- retval = ext2fs_get_mem(fs->blocksize, &bitmap_block);
- if (retval)
- return retval;
- memset(bitmap_block, 0xff, fs->blocksize);
- for (i = 0; i < fs->group_desc_count; i++) {
- memcpy(bitmap_block, inode_bitmap, nbytes);
- blk = fs->group_desc[i].bg_inode_bitmap;
- if (blk) {
-#ifdef EXT2_BIG_ENDIAN_BITMAPS
- if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
- ext2fs_swap_bitmap(fs, bitmap_block, nbytes);
-#endif
- retval = io_channel_write_blk(fs->io, blk, 1,
- bitmap_block);
- if (retval)
- return EXT2_ET_INODE_BITMAP_WRITE;
- }
- inode_bitmap += nbytes;
- }
- fs->flags &= ~EXT2_FLAG_IB_DIRTY;
- ext2fs_free_mem(&bitmap_block);
- return 0;
-}
-
-errcode_t ext2fs_write_block_bitmap (ext2_filsys fs)
-{
- dgrp_t i;
- unsigned int j;
- int nbytes;
- unsigned int nbits;
- errcode_t retval;
- char * block_bitmap = fs->block_map->bitmap;
- char * bitmap_block = NULL;
- blk_t blk;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!(fs->flags & EXT2_FLAG_RW))
- return EXT2_ET_RO_FILSYS;
- if (!block_bitmap)
- return 0;
- nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
- retval = ext2fs_get_mem(fs->blocksize, &bitmap_block);
- if (retval)
- return retval;
- memset(bitmap_block, 0xff, fs->blocksize);
- for (i = 0; i < fs->group_desc_count; i++) {
- memcpy(bitmap_block, block_bitmap, nbytes);
- if (i == fs->group_desc_count - 1) {
- /* Force bitmap padding for the last group */
- nbits = ((fs->super->s_blocks_count
- - fs->super->s_first_data_block)
- % EXT2_BLOCKS_PER_GROUP(fs->super));
- if (nbits)
- for (j = nbits; j < fs->blocksize * 8; j++)
- ext2fs_set_bit(j, bitmap_block);
- }
- blk = fs->group_desc[i].bg_block_bitmap;
- if (blk) {
-#ifdef EXT2_BIG_ENDIAN_BITMAPS
- if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
- ext2fs_swap_bitmap(fs, bitmap_block, nbytes);
-#endif
- retval = io_channel_write_blk(fs->io, blk, 1,
- bitmap_block);
- if (retval)
- return EXT2_ET_BLOCK_BITMAP_WRITE;
- }
- block_bitmap += nbytes;
- }
- fs->flags &= ~EXT2_FLAG_BB_DIRTY;
- ext2fs_free_mem(&bitmap_block);
- return 0;
-}
-
-static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
-{
- dgrp_t i;
- char *block_bitmap = NULL, *inode_bitmap = NULL;
- char *buf;
- errcode_t retval;
- int block_nbytes = (int) EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
- int inode_nbytes = (int) EXT2_INODES_PER_GROUP(fs->super) / 8;
- blk_t blk;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- fs->write_bitmaps = ext2fs_write_bitmaps;
-
- retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
- if (retval)
- return retval;
- if (do_block) {
- ext2fs_free_block_bitmap(fs->block_map);
- sprintf(buf, "block bitmap for %s", fs->device_name);
- retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
- if (retval)
- goto cleanup;
- block_bitmap = fs->block_map->bitmap;
- }
- if (do_inode) {
- ext2fs_free_inode_bitmap(fs->inode_map);
- sprintf(buf, "inode bitmap for %s", fs->device_name);
- retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
- if (retval)
- goto cleanup;
- inode_bitmap = fs->inode_map->bitmap;
- }
- ext2fs_free_mem(&buf);
-
- if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
- if (inode_bitmap) {
- blk = (fs->image_header->offset_inodemap /
- fs->blocksize);
- retval = io_channel_read_blk(fs->image_io, blk,
- -(inode_nbytes * fs->group_desc_count),
- inode_bitmap);
- if (retval)
- goto cleanup;
- }
- if (block_bitmap) {
- blk = (fs->image_header->offset_blockmap /
- fs->blocksize);
- retval = io_channel_read_blk(fs->image_io, blk,
- -(block_nbytes * fs->group_desc_count),
- block_bitmap);
- if (retval)
- goto cleanup;
- }
- return 0;
- }
-
- for (i = 0; i < fs->group_desc_count; i++) {
- if (block_bitmap) {
- blk = fs->group_desc[i].bg_block_bitmap;
- if (blk) {
- retval = io_channel_read_blk(fs->io, blk,
- -block_nbytes, block_bitmap);
- if (retval) {
- retval = EXT2_ET_BLOCK_BITMAP_READ;
- goto cleanup;
- }
-#ifdef EXT2_BIG_ENDIAN_BITMAPS
- if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)))
- ext2fs_swap_bitmap(fs, block_bitmap, block_nbytes);
-#endif
- } else
- memset(block_bitmap, 0, block_nbytes);
- block_bitmap += block_nbytes;
- }
- if (inode_bitmap) {
- blk = fs->group_desc[i].bg_inode_bitmap;
- if (blk) {
- retval = io_channel_read_blk(fs->io, blk,
- -inode_nbytes, inode_bitmap);
- if (retval) {
- retval = EXT2_ET_INODE_BITMAP_READ;
- goto cleanup;
- }
-#ifdef EXT2_BIG_ENDIAN_BITMAPS
- if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)))
- ext2fs_swap_bitmap(fs, inode_bitmap, inode_nbytes);
-#endif
- } else
- memset(inode_bitmap, 0, inode_nbytes);
- inode_bitmap += inode_nbytes;
- }
- }
- return 0;
-
-cleanup:
- if (do_block) {
- ext2fs_free_mem(&fs->block_map);
- }
- if (do_inode) {
- ext2fs_free_mem(&fs->inode_map);
- }
- ext2fs_free_mem(&buf);
- return retval;
-}
-
-errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs)
-{
- return read_bitmaps(fs, 1, 0);
-}
-
-errcode_t ext2fs_read_block_bitmap(ext2_filsys fs)
-{
- return read_bitmaps(fs, 0, 1);
-}
-
-errcode_t ext2fs_read_bitmaps(ext2_filsys fs)
-{
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (fs->inode_map && fs->block_map)
- return 0;
-
- return read_bitmaps(fs, !fs->inode_map, !fs->block_map);
-}
-
-errcode_t ext2fs_write_bitmaps(ext2_filsys fs)
-{
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (fs->block_map && ext2fs_test_bb_dirty(fs)) {
- retval = ext2fs_write_block_bitmap(fs);
- if (retval)
- return retval;
- }
- if (fs->inode_map && ext2fs_test_ib_dirty(fs)) {
- retval = ext2fs_write_inode_bitmap(fs);
- if (retval)
- return retval;
- }
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/sparse.c b/release/src/router/busybox/e2fsprogs/ext2fs/sparse.c
deleted file mode 100644
index b3d3071e98..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/sparse.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * sparse.c --- find the groups in an ext2 filesystem with metadata backups
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- * Copyright (C) 2002 Andreas Dilger.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-
-#include "ext2_fs.h"
-#include "ext2fsP.h"
-
-static int test_root(int a, int b)
-{
- if (a == 0)
- return 1;
- while (1) {
- if (a == 1)
- return 1;
- if (a % b)
- return 0;
- a = a / b;
- }
-}
-
-int ext2fs_bg_has_super(ext2_filsys fs, int group_block)
-{
- if (!(fs->super->s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
- return 1;
-
- if (test_root(group_block, 3) || (test_root(group_block, 5)) ||
- test_root(group_block, 7))
- return 1;
-
- return 0;
-}
-
-/*
- * Iterate through the groups which hold BACKUP superblock/GDT copies in an
- * ext3 filesystem. The counters should be initialized to 1, 5, and 7 before
- * calling this for the first time. In a sparse filesystem it will be the
- * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ...
- * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ...
- */
-unsigned int ext2fs_list_backups(ext2_filsys fs, unsigned int *three,
- unsigned int *five, unsigned int *seven)
-{
- unsigned int *min = three;
- int mult = 3;
- unsigned int ret;
-
- if (!(fs->super->s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
- ret = *min;
- *min += 1;
- return ret;
- }
-
- if (*five < *min) {
- min = five;
- mult = 5;
- }
- if (*seven < *min) {
- min = seven;
- mult = 7;
- }
-
- ret = *min;
- *min *= mult;
-
- return ret;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/swapfs.c b/release/src/router/busybox/e2fsprogs/ext2fs/swapfs.c
deleted file mode 100644
index 07b757abd2..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/swapfs.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * swapfs.c --- swap ext2 filesystem data structures
- *
- * Copyright (C) 1995, 1996, 2002 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <time.h>
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-#include "ext2_ext_attr.h"
-
-#if BB_BIG_ENDIAN
-void ext2fs_swap_super(struct ext2_super_block * sb)
-{
- int i;
- sb->s_inodes_count = ext2fs_swab32(sb->s_inodes_count);
- sb->s_blocks_count = ext2fs_swab32(sb->s_blocks_count);
- sb->s_r_blocks_count = ext2fs_swab32(sb->s_r_blocks_count);
- sb->s_free_blocks_count = ext2fs_swab32(sb->s_free_blocks_count);
- sb->s_free_inodes_count = ext2fs_swab32(sb->s_free_inodes_count);
- sb->s_first_data_block = ext2fs_swab32(sb->s_first_data_block);
- sb->s_log_block_size = ext2fs_swab32(sb->s_log_block_size);
- sb->s_log_frag_size = ext2fs_swab32(sb->s_log_frag_size);
- sb->s_blocks_per_group = ext2fs_swab32(sb->s_blocks_per_group);
- sb->s_frags_per_group = ext2fs_swab32(sb->s_frags_per_group);
- sb->s_inodes_per_group = ext2fs_swab32(sb->s_inodes_per_group);
- sb->s_mtime = ext2fs_swab32(sb->s_mtime);
- sb->s_wtime = ext2fs_swab32(sb->s_wtime);
- sb->s_mnt_count = ext2fs_swab16(sb->s_mnt_count);
- sb->s_max_mnt_count = ext2fs_swab16(sb->s_max_mnt_count);
- sb->s_magic = ext2fs_swab16(sb->s_magic);
- sb->s_state = ext2fs_swab16(sb->s_state);
- sb->s_errors = ext2fs_swab16(sb->s_errors);
- sb->s_minor_rev_level = ext2fs_swab16(sb->s_minor_rev_level);
- sb->s_lastcheck = ext2fs_swab32(sb->s_lastcheck);
- sb->s_checkinterval = ext2fs_swab32(sb->s_checkinterval);
- sb->s_creator_os = ext2fs_swab32(sb->s_creator_os);
- sb->s_rev_level = ext2fs_swab32(sb->s_rev_level);
- sb->s_def_resuid = ext2fs_swab16(sb->s_def_resuid);
- sb->s_def_resgid = ext2fs_swab16(sb->s_def_resgid);
- sb->s_first_ino = ext2fs_swab32(sb->s_first_ino);
- sb->s_inode_size = ext2fs_swab16(sb->s_inode_size);
- sb->s_block_group_nr = ext2fs_swab16(sb->s_block_group_nr);
- sb->s_feature_compat = ext2fs_swab32(sb->s_feature_compat);
- sb->s_feature_incompat = ext2fs_swab32(sb->s_feature_incompat);
- sb->s_feature_ro_compat = ext2fs_swab32(sb->s_feature_ro_compat);
- sb->s_algorithm_usage_bitmap = ext2fs_swab32(sb->s_algorithm_usage_bitmap);
- sb->s_reserved_gdt_blocks = ext2fs_swab16(sb->s_reserved_gdt_blocks);
- sb->s_journal_inum = ext2fs_swab32(sb->s_journal_inum);
- sb->s_journal_dev = ext2fs_swab32(sb->s_journal_dev);
- sb->s_last_orphan = ext2fs_swab32(sb->s_last_orphan);
- sb->s_default_mount_opts = ext2fs_swab32(sb->s_default_mount_opts);
- sb->s_first_meta_bg = ext2fs_swab32(sb->s_first_meta_bg);
- sb->s_mkfs_time = ext2fs_swab32(sb->s_mkfs_time);
- for (i=0; i < 4; i++)
- sb->s_hash_seed[i] = ext2fs_swab32(sb->s_hash_seed[i]);
- for (i=0; i < 17; i++)
- sb->s_jnl_blocks[i] = ext2fs_swab32(sb->s_jnl_blocks[i]);
-}
-
-void ext2fs_swap_group_desc(struct ext2_group_desc *gdp)
-{
- gdp->bg_block_bitmap = ext2fs_swab32(gdp->bg_block_bitmap);
- gdp->bg_inode_bitmap = ext2fs_swab32(gdp->bg_inode_bitmap);
- gdp->bg_inode_table = ext2fs_swab32(gdp->bg_inode_table);
- gdp->bg_free_blocks_count = ext2fs_swab16(gdp->bg_free_blocks_count);
- gdp->bg_free_inodes_count = ext2fs_swab16(gdp->bg_free_inodes_count);
- gdp->bg_used_dirs_count = ext2fs_swab16(gdp->bg_used_dirs_count);
-}
-
-void ext2fs_swap_ext_attr(char *to, char *from, int bufsize, int has_header)
-{
- struct ext2_ext_attr_header *from_header =
- (struct ext2_ext_attr_header *)from;
- struct ext2_ext_attr_header *to_header =
- (struct ext2_ext_attr_header *)to;
- struct ext2_ext_attr_entry *from_entry, *to_entry;
- char *from_end = (char *)from_header + bufsize;
- int n;
-
- if (to_header != from_header)
- memcpy(to_header, from_header, bufsize);
-
- from_entry = (struct ext2_ext_attr_entry *)from_header;
- to_entry = (struct ext2_ext_attr_entry *)to_header;
-
- if (has_header) {
- to_header->h_magic = ext2fs_swab32(from_header->h_magic);
- to_header->h_blocks = ext2fs_swab32(from_header->h_blocks);
- to_header->h_refcount = ext2fs_swab32(from_header->h_refcount);
- for (n=0; n<4; n++)
- to_header->h_reserved[n] =
- ext2fs_swab32(from_header->h_reserved[n]);
- from_entry = (struct ext2_ext_attr_entry *)(from_header+1);
- to_entry = (struct ext2_ext_attr_entry *)(to_header+1);
- }
-
- while ((char *)from_entry < from_end && *(__u32 *)from_entry) {
- to_entry->e_value_offs =
- ext2fs_swab16(from_entry->e_value_offs);
- to_entry->e_value_block =
- ext2fs_swab32(from_entry->e_value_block);
- to_entry->e_value_size =
- ext2fs_swab32(from_entry->e_value_size);
- from_entry = EXT2_EXT_ATTR_NEXT(from_entry);
- to_entry = EXT2_EXT_ATTR_NEXT(to_entry);
- }
-}
-
-void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t,
- struct ext2_inode_large *f, int hostorder,
- int bufsize)
-{
- unsigned i;
- int islnk = 0;
- __u32 *eaf, *eat;
-
- if (hostorder && LINUX_S_ISLNK(f->i_mode))
- islnk = 1;
- t->i_mode = ext2fs_swab16(f->i_mode);
- if (!hostorder && LINUX_S_ISLNK(t->i_mode))
- islnk = 1;
- t->i_uid = ext2fs_swab16(f->i_uid);
- t->i_size = ext2fs_swab32(f->i_size);
- t->i_atime = ext2fs_swab32(f->i_atime);
- t->i_ctime = ext2fs_swab32(f->i_ctime);
- t->i_mtime = ext2fs_swab32(f->i_mtime);
- t->i_dtime = ext2fs_swab32(f->i_dtime);
- t->i_gid = ext2fs_swab16(f->i_gid);
- t->i_links_count = ext2fs_swab16(f->i_links_count);
- t->i_blocks = ext2fs_swab32(f->i_blocks);
- t->i_flags = ext2fs_swab32(f->i_flags);
- t->i_file_acl = ext2fs_swab32(f->i_file_acl);
- t->i_dir_acl = ext2fs_swab32(f->i_dir_acl);
- if (!islnk || ext2fs_inode_data_blocks(fs, (struct ext2_inode *)t)) {
- for (i = 0; i < EXT2_N_BLOCKS; i++)
- t->i_block[i] = ext2fs_swab32(f->i_block[i]);
- } else if (t != f) {
- for (i = 0; i < EXT2_N_BLOCKS; i++)
- t->i_block[i] = f->i_block[i];
- }
- t->i_generation = ext2fs_swab32(f->i_generation);
- t->i_faddr = ext2fs_swab32(f->i_faddr);
-
- switch (fs->super->s_creator_os) {
- case EXT2_OS_LINUX:
- t->osd1.linux1.l_i_reserved1 =
- ext2fs_swab32(f->osd1.linux1.l_i_reserved1);
- t->osd2.linux2.l_i_frag = f->osd2.linux2.l_i_frag;
- t->osd2.linux2.l_i_fsize = f->osd2.linux2.l_i_fsize;
- t->osd2.linux2.i_pad1 = ext2fs_swab16(f->osd2.linux2.i_pad1);
- t->osd2.linux2.l_i_uid_high =
- ext2fs_swab16 (f->osd2.linux2.l_i_uid_high);
- t->osd2.linux2.l_i_gid_high =
- ext2fs_swab16 (f->osd2.linux2.l_i_gid_high);
- t->osd2.linux2.l_i_reserved2 =
- ext2fs_swab32(f->osd2.linux2.l_i_reserved2);
- break;
- case EXT2_OS_HURD:
- t->osd1.hurd1.h_i_translator =
- ext2fs_swab32 (f->osd1.hurd1.h_i_translator);
- t->osd2.hurd2.h_i_frag = f->osd2.hurd2.h_i_frag;
- t->osd2.hurd2.h_i_fsize = f->osd2.hurd2.h_i_fsize;
- t->osd2.hurd2.h_i_mode_high =
- ext2fs_swab16 (f->osd2.hurd2.h_i_mode_high);
- t->osd2.hurd2.h_i_uid_high =
- ext2fs_swab16 (f->osd2.hurd2.h_i_uid_high);
- t->osd2.hurd2.h_i_gid_high =
- ext2fs_swab16 (f->osd2.hurd2.h_i_gid_high);
- t->osd2.hurd2.h_i_author =
- ext2fs_swab32 (f->osd2.hurd2.h_i_author);
- break;
- case EXT2_OS_MASIX:
- t->osd1.masix1.m_i_reserved1 =
- ext2fs_swab32(f->osd1.masix1.m_i_reserved1);
- t->osd2.masix2.m_i_frag = f->osd2.masix2.m_i_frag;
- t->osd2.masix2.m_i_fsize = f->osd2.masix2.m_i_fsize;
- t->osd2.masix2.m_pad1 = ext2fs_swab16(f->osd2.masix2.m_pad1);
- t->osd2.masix2.m_i_reserved2[0] =
- ext2fs_swab32(f->osd2.masix2.m_i_reserved2[0]);
- t->osd2.masix2.m_i_reserved2[1] =
- ext2fs_swab32(f->osd2.masix2.m_i_reserved2[1]);
- break;
- }
-
- if (bufsize < (int) (sizeof(struct ext2_inode) + sizeof(__u16)))
- return; /* no i_extra_isize field */
-
- t->i_extra_isize = ext2fs_swab16(f->i_extra_isize);
- if (t->i_extra_isize > EXT2_INODE_SIZE(fs->super) -
- sizeof(struct ext2_inode)) {
- /* this is error case: i_extra_size is too large */
- return;
- }
-
- i = sizeof(struct ext2_inode) + t->i_extra_isize + sizeof(__u32);
- if (bufsize < (int) i)
- return; /* no space for EA magic */
-
- eaf = (__u32 *) (((char *) f) + sizeof(struct ext2_inode) +
- f->i_extra_isize);
-
- if (ext2fs_swab32(*eaf) != EXT2_EXT_ATTR_MAGIC)
- return; /* it seems no magic here */
-
- eat = (__u32 *) (((char *) t) + sizeof(struct ext2_inode) +
- f->i_extra_isize);
- *eat = ext2fs_swab32(*eaf);
-
- /* convert EA(s) */
- ext2fs_swap_ext_attr((char *) (eat + 1), (char *) (eaf + 1),
- bufsize - sizeof(struct ext2_inode) -
- t->i_extra_isize - sizeof(__u32), 0);
-}
-
-void ext2fs_swap_inode(ext2_filsys fs, struct ext2_inode *t,
- struct ext2_inode *f, int hostorder)
-{
- ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) t,
- (struct ext2_inode_large *) f, hostorder,
- sizeof(struct ext2_inode));
-}
-
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/test_io.c b/release/src/router/busybox/e2fsprogs/ext2fs/test_io.c
deleted file mode 100644
index 3d40d9a97f..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/test_io.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * test_io.c --- This is the Test I/O interface.
- *
- * Copyright (C) 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * For checking structure magic numbers...
- */
-
-#define EXT2_CHECK_MAGIC(struct, code) \
- if ((struct)->magic != (code)) return (code)
-
-struct test_private_data {
- int magic;
- io_channel real;
- int flags;
- FILE *outfile;
- unsigned long block;
- int read_abort_count, write_abort_count;
- void (*read_blk)(unsigned long block, int count, errcode_t err);
- void (*write_blk)(unsigned long block, int count, errcode_t err);
- void (*set_blksize)(int blksize, errcode_t err);
- void (*write_byte)(unsigned long block, int count, errcode_t err);
-};
-
-static errcode_t test_open(const char *name, int flags, io_channel *channel);
-static errcode_t test_close(io_channel channel);
-static errcode_t test_set_blksize(io_channel channel, int blksize);
-static errcode_t test_read_blk(io_channel channel, unsigned long block,
- int count, void *data);
-static errcode_t test_write_blk(io_channel channel, unsigned long block,
- int count, const void *data);
-static errcode_t test_flush(io_channel channel);
-static errcode_t test_write_byte(io_channel channel, unsigned long offset,
- int count, const void *buf);
-static errcode_t test_set_option(io_channel channel, const char *option,
- const char *arg);
-
-static struct struct_io_manager struct_test_manager = {
- EXT2_ET_MAGIC_IO_MANAGER,
- "Test I/O Manager",
- test_open,
- test_close,
- test_set_blksize,
- test_read_blk,
- test_write_blk,
- test_flush,
- test_write_byte,
- test_set_option
-};
-
-io_manager test_io_manager = &struct_test_manager;
-
-/*
- * These global variable can be set by the test program as
- * necessary *before* calling test_open
- */
-io_manager test_io_backing_manager = 0;
-void (*test_io_cb_read_blk)
- (unsigned long block, int count, errcode_t err) = 0;
-void (*test_io_cb_write_blk)
- (unsigned long block, int count, errcode_t err) = 0;
-void (*test_io_cb_set_blksize)
- (int blksize, errcode_t err) = 0;
-void (*test_io_cb_write_byte)
- (unsigned long block, int count, errcode_t err) = 0;
-
-/*
- * Test flags
- */
-#define TEST_FLAG_READ 0x01
-#define TEST_FLAG_WRITE 0x02
-#define TEST_FLAG_SET_BLKSIZE 0x04
-#define TEST_FLAG_FLUSH 0x08
-#define TEST_FLAG_DUMP 0x10
-#define TEST_FLAG_SET_OPTION 0x20
-
-static void test_dump_block(io_channel channel,
- struct test_private_data *data,
- unsigned long block, const void *buf)
-{
- const unsigned char *cp;
- FILE *f = data->outfile;
- int i;
- unsigned long cksum = 0;
-
- for (i=0, cp = buf; i < channel->block_size; i++, cp++) {
- cksum += *cp;
- }
- fprintf(f, "Contents of block %lu, checksum %08lu:\n", block, cksum);
- for (i=0, cp = buf; i < channel->block_size; i++, cp++) {
- if ((i % 16) == 0)
- fprintf(f, "%04x: ", i);
- fprintf(f, "%02x%c", *cp, ((i % 16) == 15) ? '\n' : ' ');
- }
-}
-
-static void test_abort(io_channel channel, unsigned long block)
-{
- struct test_private_data *data;
- FILE *f;
-
- data = (struct test_private_data *) channel->private_data;
- f = data->outfile;
- test_flush(channel);
-
- fprintf(f, "Aborting due to I/O to block %lu\n", block);
- fflush(f);
- abort();
-}
-
-static errcode_t test_open(const char *name, int flags, io_channel *channel)
-{
- io_channel io = NULL;
- struct test_private_data *data = NULL;
- errcode_t retval;
- char *value;
-
- if (name == 0)
- return EXT2_ET_BAD_DEVICE_NAME;
- retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
- if (retval)
- return retval;
- memset(io, 0, sizeof(struct struct_io_channel));
- io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
- retval = ext2fs_get_mem(sizeof(struct test_private_data), &data);
- if (retval) {
- retval = EXT2_ET_NO_MEMORY;
- goto cleanup;
- }
- io->manager = test_io_manager;
- retval = ext2fs_get_mem(strlen(name)+1, &io->name);
- if (retval)
- goto cleanup;
-
- strcpy(io->name, name);
- io->private_data = data;
- io->block_size = 1024;
- io->read_error = 0;
- io->write_error = 0;
- io->refcount = 1;
-
- memset(data, 0, sizeof(struct test_private_data));
- data->magic = EXT2_ET_MAGIC_TEST_IO_CHANNEL;
- if (test_io_backing_manager) {
- retval = test_io_backing_manager->open(name, flags,
- &data->real);
- if (retval)
- goto cleanup;
- } else
- data->real = 0;
- data->read_blk = test_io_cb_read_blk;
- data->write_blk = test_io_cb_write_blk;
- data->set_blksize = test_io_cb_set_blksize;
- data->write_byte = test_io_cb_write_byte;
-
- data->outfile = NULL;
- if ((value = getenv("TEST_IO_LOGFILE")) != NULL)
- data->outfile = fopen_for_write(value);
- if (!data->outfile)
- data->outfile = stderr;
-
- data->flags = 0;
- if ((value = getenv("TEST_IO_FLAGS")) != NULL)
- data->flags = strtoul(value, NULL, 0);
-
- data->block = 0;
- if ((value = getenv("TEST_IO_BLOCK")) != NULL)
- data->block = strtoul(value, NULL, 0);
-
- data->read_abort_count = 0;
- if ((value = getenv("TEST_IO_READ_ABORT")) != NULL)
- data->read_abort_count = strtoul(value, NULL, 0);
-
- data->write_abort_count = 0;
- if ((value = getenv("TEST_IO_WRITE_ABORT")) != NULL)
- data->write_abort_count = strtoul(value, NULL, 0);
-
- *channel = io;
- return 0;
-
-cleanup:
- ext2fs_free_mem(&io);
- ext2fs_free_mem(&data);
- return retval;
-}
-
-static errcode_t test_close(io_channel channel)
-{
- struct test_private_data *data;
- errcode_t retval = 0;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct test_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
-
- if (--channel->refcount > 0)
- return 0;
-
- if (data->real)
- retval = io_channel_close(data->real);
-
- if (data->outfile && data->outfile != stderr)
- fclose(data->outfile);
-
- ext2fs_free_mem(&channel->private_data);
- ext2fs_free_mem(&channel->name);
- ext2fs_free_mem(&channel);
- return retval;
-}
-
-static errcode_t test_set_blksize(io_channel channel, int blksize)
-{
- struct test_private_data *data;
- errcode_t retval = 0;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct test_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
-
- if (data->real)
- retval = io_channel_set_blksize(data->real, blksize);
- if (data->set_blksize)
- data->set_blksize(blksize, retval);
- if (data->flags & TEST_FLAG_SET_BLKSIZE)
- fprintf(data->outfile,
- "Test_io: set_blksize(%d) returned %s\n",
- blksize, retval ? error_message(retval) : "OK");
- channel->block_size = blksize;
- return retval;
-}
-
-
-static errcode_t test_read_blk(io_channel channel, unsigned long block,
- int count, void *buf)
-{
- struct test_private_data *data;
- errcode_t retval = 0;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct test_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
-
- if (data->real)
- retval = io_channel_read_blk(data->real, block, count, buf);
- if (data->read_blk)
- data->read_blk(block, count, retval);
- if (data->flags & TEST_FLAG_READ)
- fprintf(data->outfile,
- "Test_io: read_blk(%lu, %d) returned %s\n",
- block, count, retval ? error_message(retval) : "OK");
- if (data->block && data->block == block) {
- if (data->flags & TEST_FLAG_DUMP)
- test_dump_block(channel, data, block, buf);
- if (--data->read_abort_count == 0)
- test_abort(channel, block);
- }
- return retval;
-}
-
-static errcode_t test_write_blk(io_channel channel, unsigned long block,
- int count, const void *buf)
-{
- struct test_private_data *data;
- errcode_t retval = 0;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct test_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
-
- if (data->real)
- retval = io_channel_write_blk(data->real, block, count, buf);
- if (data->write_blk)
- data->write_blk(block, count, retval);
- if (data->flags & TEST_FLAG_WRITE)
- fprintf(data->outfile,
- "Test_io: write_blk(%lu, %d) returned %s\n",
- block, count, retval ? error_message(retval) : "OK");
- if (data->block && data->block == block) {
- if (data->flags & TEST_FLAG_DUMP)
- test_dump_block(channel, data, block, buf);
- if (--data->write_abort_count == 0)
- test_abort(channel, block);
- }
- return retval;
-}
-
-static errcode_t test_write_byte(io_channel channel, unsigned long offset,
- int count, const void *buf)
-{
- struct test_private_data *data;
- errcode_t retval = 0;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct test_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
-
- if (data->real && data->real->manager->write_byte)
- retval = io_channel_write_byte(data->real, offset, count, buf);
- if (data->write_byte)
- data->write_byte(offset, count, retval);
- if (data->flags & TEST_FLAG_WRITE)
- fprintf(data->outfile,
- "Test_io: write_byte(%lu, %d) returned %s\n",
- offset, count, retval ? error_message(retval) : "OK");
- return retval;
-}
-
-/*
- * Flush data buffers to disk.
- */
-static errcode_t test_flush(io_channel channel)
-{
- struct test_private_data *data;
- errcode_t retval = 0;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct test_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
-
- if (data->real)
- retval = io_channel_flush(data->real);
-
- if (data->flags & TEST_FLAG_FLUSH)
- fprintf(data->outfile, "Test_io: flush() returned %s\n",
- retval ? error_message(retval) : "OK");
-
- return retval;
-}
-
-static errcode_t test_set_option(io_channel channel, const char *option,
- const char *arg)
-{
- struct test_private_data *data;
- errcode_t retval = 0;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct test_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
-
-
- if (data->flags & TEST_FLAG_SET_OPTION)
- fprintf(data->outfile, "Test_io: set_option(%s, %s) ",
- option, arg);
- if (data->real && data->real->manager->set_option) {
- retval = (data->real->manager->set_option)(data->real,
- option, arg);
- if (data->flags & TEST_FLAG_SET_OPTION)
- fprintf(data->outfile, "returned %s\n",
- retval ? error_message(retval) : "OK");
- } else {
- if (data->flags & TEST_FLAG_SET_OPTION)
- fprintf(data->outfile, "not implemented\n");
- }
- return retval;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/unix_io.c b/release/src/router/busybox/e2fsprogs/ext2fs/unix_io.c
deleted file mode 100644
index 8dde4c7322..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/unix_io.c
+++ /dev/null
@@ -1,703 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * unix_io.c --- This is the Unix (well, really POSIX) implementation
- * of the I/O manager.
- *
- * Implements a one-block write-through cache.
- *
- * Includes support for Windows NT support under Cygwin.
- *
- * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- * 2002 by Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#ifdef __linux__
-#include <sys/utsname.h>
-#endif
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#include <sys/resource.h>
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * For checking structure magic numbers...
- */
-
-#define EXT2_CHECK_MAGIC(struct, code) \
- if ((struct)->magic != (code)) return (code)
-
-struct unix_cache {
- char *buf;
- unsigned long block;
- int access_time;
- unsigned dirty:1;
- unsigned in_use:1;
-};
-
-#define CACHE_SIZE 8
-#define WRITE_DIRECT_SIZE 4 /* Must be smaller than CACHE_SIZE */
-#define READ_DIRECT_SIZE 4 /* Should be smaller than CACHE_SIZE */
-
-struct unix_private_data {
- int magic;
- int dev;
- int flags;
- int access_time;
- ext2_loff_t offset;
- struct unix_cache cache[CACHE_SIZE];
-};
-
-static errcode_t unix_open(const char *name, int flags, io_channel *channel);
-static errcode_t unix_close(io_channel channel);
-static errcode_t unix_set_blksize(io_channel channel, int blksize);
-static errcode_t unix_read_blk(io_channel channel, unsigned long block,
- int count, void *data);
-static errcode_t unix_write_blk(io_channel channel, unsigned long block,
- int count, const void *data);
-static errcode_t unix_flush(io_channel channel);
-static errcode_t unix_write_byte(io_channel channel, unsigned long offset,
- int size, const void *data);
-static errcode_t unix_set_option(io_channel channel, const char *option,
- const char *arg);
-
-static void reuse_cache(io_channel channel, struct unix_private_data *data,
- struct unix_cache *cache, unsigned long block);
-
-/* __FreeBSD_kernel__ is defined by GNU/kFreeBSD - the FreeBSD kernel
- * does not know buffered block devices - everything is raw. */
-#if defined(__CYGWIN__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-#define NEED_BOUNCE_BUFFER
-#else
-#undef NEED_BOUNCE_BUFFER
-#endif
-
-static struct struct_io_manager struct_unix_manager = {
- EXT2_ET_MAGIC_IO_MANAGER,
- "Unix I/O Manager",
- unix_open,
- unix_close,
- unix_set_blksize,
- unix_read_blk,
- unix_write_blk,
- unix_flush,
-#ifdef NEED_BOUNCE_BUFFER
- 0,
-#else
- unix_write_byte,
-#endif
- unix_set_option
-};
-
-io_manager unix_io_manager = &struct_unix_manager;
-
-/*
- * Here are the raw I/O functions
- */
-#ifndef NEED_BOUNCE_BUFFER
-static errcode_t raw_read_blk(io_channel channel,
- struct unix_private_data *data,
- unsigned long block,
- int count, void *buf)
-{
- errcode_t retval;
- ssize_t size;
- ext2_loff_t location;
- int actual = 0;
-
- size = (count < 0) ? -count : count * channel->block_size;
- location = ((ext2_loff_t) block * channel->block_size) + data->offset;
- if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
- retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
- goto error_out;
- }
- actual = read(data->dev, buf, size);
- if (actual != size) {
- if (actual < 0)
- actual = 0;
- retval = EXT2_ET_SHORT_READ;
- goto error_out;
- }
- return 0;
-
-error_out:
- memset((char *) buf+actual, 0, size-actual);
- if (channel->read_error)
- retval = (channel->read_error)(channel, block, count, buf,
- size, actual, retval);
- return retval;
-}
-#else /* NEED_BOUNCE_BUFFER */
-/*
- * Windows and FreeBSD block devices only allow sector alignment IO in offset and size
- */
-static errcode_t raw_read_blk(io_channel channel,
- struct unix_private_data *data,
- unsigned long block,
- int count, void *buf)
-{
- errcode_t retval;
- size_t size, alignsize, fragment;
- ext2_loff_t location;
- int total = 0, actual;
-#define BLOCKALIGN 512
- char sector[BLOCKALIGN];
-
- size = (count < 0) ? -count : count * channel->block_size;
- location = ((ext2_loff_t) block * channel->block_size) + data->offset;
-#ifdef DEBUG
- printf("count=%d, size=%d, block=%d, blk_size=%d, location=%lx\n",
- count, size, block, channel->block_size, location);
-#endif
- if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
- retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
- goto error_out;
- }
- fragment = size % BLOCKALIGN;
- alignsize = size - fragment;
- if (alignsize) {
- actual = read(data->dev, buf, alignsize);
- if (actual != alignsize)
- goto short_read;
- }
- if (fragment) {
- actual = read(data->dev, sector, BLOCKALIGN);
- if (actual != BLOCKALIGN)
- goto short_read;
- memcpy(buf+alignsize, sector, fragment);
- }
- return 0;
-
-short_read:
- if (actual>0)
- total += actual;
- retval = EXT2_ET_SHORT_READ;
-
-error_out:
- memset((char *) buf+total, 0, size-actual);
- if (channel->read_error)
- retval = (channel->read_error)(channel, block, count, buf,
- size, actual, retval);
- return retval;
-}
-#endif
-
-static errcode_t raw_write_blk(io_channel channel,
- struct unix_private_data *data,
- unsigned long block,
- int count, const void *buf)
-{
- ssize_t size;
- ext2_loff_t location;
- int actual = 0;
- errcode_t retval;
-
- if (count == 1)
- size = channel->block_size;
- else {
- if (count < 0)
- size = -count;
- else
- size = count * channel->block_size;
- }
-
- location = ((ext2_loff_t) block * channel->block_size) + data->offset;
- if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
- retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
- goto error_out;
- }
-
- actual = write(data->dev, buf, size);
- if (actual != size) {
- retval = EXT2_ET_SHORT_WRITE;
- goto error_out;
- }
- return 0;
-
-error_out:
- if (channel->write_error)
- retval = (channel->write_error)(channel, block, count, buf,
- size, actual, retval);
- return retval;
-}
-
-
-/*
- * Here we implement the cache functions
- */
-
-/* Allocate the cache buffers */
-static errcode_t alloc_cache(io_channel channel,
- struct unix_private_data *data)
-{
- errcode_t retval;
- struct unix_cache *cache;
- int i;
-
- data->access_time = 0;
- for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
- cache->block = 0;
- cache->access_time = 0;
- cache->dirty = 0;
- cache->in_use = 0;
- if ((retval = ext2fs_get_mem(channel->block_size,
- &cache->buf)))
- return retval;
- }
- return 0;
-}
-
-/* Free the cache buffers */
-static void free_cache(struct unix_private_data *data)
-{
- struct unix_cache *cache;
- int i;
-
- data->access_time = 0;
- for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
- cache->block = 0;
- cache->access_time = 0;
- cache->dirty = 0;
- cache->in_use = 0;
- ext2fs_free_mem(&cache->buf);
- cache->buf = 0;
- }
-}
-
-#ifndef NO_IO_CACHE
-/*
- * Try to find a block in the cache. If the block is not found, and
- * eldest is a non-zero pointer, then fill in eldest with the cache
- * entry to that should be reused.
- */
-static struct unix_cache *find_cached_block(struct unix_private_data *data,
- unsigned long block,
- struct unix_cache **eldest)
-{
- struct unix_cache *cache, *unused_cache, *oldest_cache;
- int i;
-
- unused_cache = oldest_cache = 0;
- for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
- if (!cache->in_use) {
- if (!unused_cache)
- unused_cache = cache;
- continue;
- }
- if (cache->block == block) {
- cache->access_time = ++data->access_time;
- return cache;
- }
- if (!oldest_cache ||
- (cache->access_time < oldest_cache->access_time))
- oldest_cache = cache;
- }
- if (eldest)
- *eldest = (unused_cache) ? unused_cache : oldest_cache;
- return 0;
-}
-
-/*
- * Reuse a particular cache entry for another block.
- */
-static void reuse_cache(io_channel channel, struct unix_private_data *data,
- struct unix_cache *cache, unsigned long block)
-{
- if (cache->dirty && cache->in_use)
- raw_write_blk(channel, data, cache->block, 1, cache->buf);
-
- cache->in_use = 1;
- cache->dirty = 0;
- cache->block = block;
- cache->access_time = ++data->access_time;
-}
-
-/*
- * Flush all of the blocks in the cache
- */
-static errcode_t flush_cached_blocks(io_channel channel,
- struct unix_private_data *data,
- int invalidate)
-
-{
- struct unix_cache *cache;
- errcode_t retval, retval2;
- int i;
-
- retval2 = 0;
- for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
- if (!cache->in_use)
- continue;
-
- if (invalidate)
- cache->in_use = 0;
-
- if (!cache->dirty)
- continue;
-
- retval = raw_write_blk(channel, data,
- cache->block, 1, cache->buf);
- if (retval)
- retval2 = retval;
- else
- cache->dirty = 0;
- }
- return retval2;
-}
-#endif /* NO_IO_CACHE */
-
-static errcode_t unix_open(const char *name, int flags, io_channel *channel)
-{
- io_channel io = NULL;
- struct unix_private_data *data = NULL;
- errcode_t retval;
- int open_flags;
- struct stat st;
-#ifdef __linux__
- struct utsname ut;
-#endif
-
- if (name == 0)
- return EXT2_ET_BAD_DEVICE_NAME;
- retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
- if (retval)
- return retval;
- memset(io, 0, sizeof(struct struct_io_channel));
- io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
- retval = ext2fs_get_mem(sizeof(struct unix_private_data), &data);
- if (retval)
- goto cleanup;
-
- io->manager = unix_io_manager;
- retval = ext2fs_get_mem(strlen(name)+1, &io->name);
- if (retval)
- goto cleanup;
-
- strcpy(io->name, name);
- io->private_data = data;
- io->block_size = 1024;
- io->read_error = 0;
- io->write_error = 0;
- io->refcount = 1;
-
- memset(data, 0, sizeof(struct unix_private_data));
- data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL;
-
- if ((retval = alloc_cache(io, data)))
- goto cleanup;
-
- open_flags = (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY;
-#ifdef CONFIG_LFS
- data->dev = open64(io->name, open_flags);
-#else
- data->dev = open(io->name, open_flags);
-#endif
- if (data->dev < 0) {
- retval = errno;
- goto cleanup;
- }
-
-#ifdef __linux__
-#undef RLIM_INFINITY
-#if (defined(__alpha__) || (defined(__sparc__) && (__WORDSIZE == 32)) || (defined(__mips__) && (_MIPS_SZLONG == 32)))
-#define RLIM_INFINITY ((unsigned long)(~0UL>>1))
-#else
-#define RLIM_INFINITY (~0UL)
-#endif
- /*
- * Work around a bug in 2.4.10-2.4.18 kernels where writes to
- * block devices are wrongly getting hit by the filesize
- * limit. This workaround isn't perfect, since it won't work
- * if glibc wasn't built against 2.2 header files. (Sigh.)
- *
- */
- if ((flags & IO_FLAG_RW) &&
- (uname(&ut) == 0) &&
- ((ut.release[0] == '2') && (ut.release[1] == '.') &&
- (ut.release[2] == '4') && (ut.release[3] == '.') &&
- (ut.release[4] == '1') && (ut.release[5] >= '0') &&
- (ut.release[5] < '8')) &&
- (fstat(data->dev, &st) == 0) &&
- (S_ISBLK(st.st_mode))) {
- struct rlimit rlim;
-
- rlim.rlim_cur = rlim.rlim_max = (unsigned long) RLIM_INFINITY;
- setrlimit(RLIMIT_FSIZE, &rlim);
- getrlimit(RLIMIT_FSIZE, &rlim);
- if (((unsigned long) rlim.rlim_cur) <
- ((unsigned long) rlim.rlim_max)) {
- rlim.rlim_cur = rlim.rlim_max;
- setrlimit(RLIMIT_FSIZE, &rlim);
- }
- }
-#endif
- *channel = io;
- return 0;
-
-cleanup:
- if (data) {
- free_cache(data);
- ext2fs_free_mem(&data);
- }
- ext2fs_free_mem(&io);
- return retval;
-}
-
-static errcode_t unix_close(io_channel channel)
-{
- struct unix_private_data *data;
- errcode_t retval = 0;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct unix_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
-
- if (--channel->refcount > 0)
- return 0;
-
-#ifndef NO_IO_CACHE
- retval = flush_cached_blocks(channel, data, 0);
-#endif
-
- if (close(data->dev) < 0)
- retval = errno;
- free_cache(data);
-
- ext2fs_free_mem(&channel->private_data);
- ext2fs_free_mem(&channel->name);
- ext2fs_free_mem(&channel);
- return retval;
-}
-
-static errcode_t unix_set_blksize(io_channel channel, int blksize)
-{
- struct unix_private_data *data;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct unix_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
-
- if (channel->block_size != blksize) {
-#ifndef NO_IO_CACHE
- if ((retval = flush_cached_blocks(channel, data, 0)))
- return retval;
-#endif
-
- channel->block_size = blksize;
- free_cache(data);
- if ((retval = alloc_cache(channel, data)))
- return retval;
- }
- return 0;
-}
-
-
-static errcode_t unix_read_blk(io_channel channel, unsigned long block,
- int count, void *buf)
-{
- struct unix_private_data *data;
- struct unix_cache *cache, *reuse[READ_DIRECT_SIZE];
- errcode_t retval;
- char *cp;
- int i, j;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct unix_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
-
-#ifdef NO_IO_CACHE
- return raw_read_blk(channel, data, block, count, buf);
-#else
- /*
- * If we're doing an odd-sized read or a very large read,
- * flush out the cache and then do a direct read.
- */
- if (count < 0 || count > WRITE_DIRECT_SIZE) {
- if ((retval = flush_cached_blocks(channel, data, 0)))
- return retval;
- return raw_read_blk(channel, data, block, count, buf);
- }
-
- cp = buf;
- while (count > 0) {
- /* If it's in the cache, use it! */
- if ((cache = find_cached_block(data, block, &reuse[0]))) {
-#ifdef DEBUG
- printf("Using cached block %d\n", block);
-#endif
- memcpy(cp, cache->buf, channel->block_size);
- count--;
- block++;
- cp += channel->block_size;
- continue;
- }
- /*
- * Find the number of uncached blocks so we can do a
- * single read request
- */
- for (i=1; i < count; i++)
- if (find_cached_block(data, block+i, &reuse[i]))
- break;
-#ifdef DEBUG
- printf("Reading %d blocks starting at %d\n", i, block);
-#endif
- if ((retval = raw_read_blk(channel, data, block, i, cp)))
- return retval;
-
- /* Save the results in the cache */
- for (j=0; j < i; j++) {
- count--;
- cache = reuse[j];
- reuse_cache(channel, data, cache, block++);
- memcpy(cache->buf, cp, channel->block_size);
- cp += channel->block_size;
- }
- }
- return 0;
-#endif /* NO_IO_CACHE */
-}
-
-static errcode_t unix_write_blk(io_channel channel, unsigned long block,
- int count, const void *buf)
-{
- struct unix_private_data *data;
- struct unix_cache *cache, *reuse;
- errcode_t retval = 0;
- const char *cp;
- int writethrough;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct unix_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
-
-#ifdef NO_IO_CACHE
- return raw_write_blk(channel, data, block, count, buf);
-#else
- /*
- * If we're doing an odd-sized write or a very large write,
- * flush out the cache completely and then do a direct write.
- */
- if (count < 0 || count > WRITE_DIRECT_SIZE) {
- if ((retval = flush_cached_blocks(channel, data, 1)))
- return retval;
- return raw_write_blk(channel, data, block, count, buf);
- }
-
- /*
- * For a moderate-sized multi-block write, first force a write
- * if we're in write-through cache mode, and then fill the
- * cache with the blocks.
- */
- writethrough = channel->flags & CHANNEL_FLAGS_WRITETHROUGH;
- if (writethrough)
- retval = raw_write_blk(channel, data, block, count, buf);
-
- cp = buf;
- while (count > 0) {
- cache = find_cached_block(data, block, &reuse);
- if (!cache) {
- cache = reuse;
- reuse_cache(channel, data, cache, block);
- }
- memcpy(cache->buf, cp, channel->block_size);
- cache->dirty = !writethrough;
- count--;
- block++;
- cp += channel->block_size;
- }
- return retval;
-#endif /* NO_IO_CACHE */
-}
-
-static errcode_t unix_write_byte(io_channel channel, unsigned long offset,
- int size, const void *buf)
-{
- struct unix_private_data *data;
- errcode_t retval = 0;
- ssize_t actual;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct unix_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
-
-#ifndef NO_IO_CACHE
- /*
- * Flush out the cache completely
- */
- if ((retval = flush_cached_blocks(channel, data, 1)))
- return retval;
-#endif
-
- if (lseek(data->dev, offset + data->offset, SEEK_SET) < 0)
- return errno;
-
- actual = write(data->dev, buf, size);
- if (actual != size)
- return EXT2_ET_SHORT_WRITE;
-
- return 0;
-}
-
-/*
- * Flush data buffers to disk.
- */
-static errcode_t unix_flush(io_channel channel)
-{
- struct unix_private_data *data;
- errcode_t retval = 0;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct unix_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
-
-#ifndef NO_IO_CACHE
- retval = flush_cached_blocks(channel, data, 0);
-#endif
- fsync(data->dev);
- return retval;
-}
-
-static errcode_t unix_set_option(io_channel channel, const char *option,
- const char *arg)
-{
- struct unix_private_data *data;
- unsigned long tmp;
- char *end;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct unix_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
-
- if (!strcmp(option, "offset")) {
- if (!arg)
- return EXT2_ET_INVALID_ARGUMENT;
-
- tmp = strtoul(arg, &end, 0);
- if (*end)
- return EXT2_ET_INVALID_ARGUMENT;
- data->offset = tmp;
- return 0;
- }
- return EXT2_ET_INVALID_ARGUMENT;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/unlink.c b/release/src/router/busybox/e2fsprogs/ext2fs/unlink.c
deleted file mode 100644
index 71a9ffcb9b..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/unlink.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * unlink.c --- delete links in a ext2fs directory
- *
- * Copyright (C) 1993, 1994, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-struct link_struct {
- const char *name;
- int namelen;
- ext2_ino_t inode;
- int flags;
- struct ext2_dir_entry *prev;
- int done;
-};
-
-#ifdef __TURBOC__
-# pragma argsused
-#endif
-static int unlink_proc(struct ext2_dir_entry *dirent,
- int offset EXT2FS_ATTR((unused)),
- int blocksize EXT2FS_ATTR((unused)),
- char *buf EXT2FS_ATTR((unused)),
- void *priv_data)
-{
- struct link_struct *ls = (struct link_struct *) priv_data;
- struct ext2_dir_entry *prev;
-
- prev = ls->prev;
- ls->prev = dirent;
-
- if (ls->name) {
- if ((dirent->name_len & 0xFF) != ls->namelen)
- return 0;
- if (strncmp(ls->name, dirent->name, dirent->name_len & 0xFF))
- return 0;
- }
- if (ls->inode) {
- if (dirent->inode != ls->inode)
- return 0;
- } else {
- if (!dirent->inode)
- return 0;
- }
-
- if (prev)
- prev->rec_len += dirent->rec_len;
- else
- dirent->inode = 0;
- ls->done++;
- return DIRENT_ABORT|DIRENT_CHANGED;
-}
-
-#ifdef __TURBOC__
- #pragma argsused
-#endif
-errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir,
- const char *name, ext2_ino_t ino,
- int flags EXT2FS_ATTR((unused)))
-{
- errcode_t retval;
- struct link_struct ls;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!name && !ino)
- return EXT2_ET_INVALID_ARGUMENT;
-
- if (!(fs->flags & EXT2_FLAG_RW))
- return EXT2_ET_RO_FILSYS;
-
- ls.name = name;
- ls.namelen = name ? strlen(name) : 0;
- ls.inode = ino;
- ls.flags = 0;
- ls.done = 0;
- ls.prev = 0;
-
- retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY,
- 0, unlink_proc, &ls);
- if (retval)
- return retval;
-
- return (ls.done) ? 0 : EXT2_ET_DIR_NO_SPACE;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/valid_blk.c b/release/src/router/busybox/e2fsprogs/ext2fs/valid_blk.c
deleted file mode 100644
index 8ed77ae2ac..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/valid_blk.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * valid_blk.c --- does the inode have valid blocks?
- *
- * Copyright 1997 by Theodore Ts'o
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- *
- */
-
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <string.h>
-#include <time.h>
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * This function returns 1 if the inode's block entries actually
- * contain block entries.
- */
-int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode)
-{
- /*
- * Only directories, regular files, and some symbolic links
- * have valid block entries.
- */
- if (!LINUX_S_ISDIR(inode->i_mode) && !LINUX_S_ISREG(inode->i_mode) &&
- !LINUX_S_ISLNK(inode->i_mode))
- return 0;
-
- /*
- * If the symbolic link is a "fast symlink", then the symlink
- * target is stored in the block entries.
- */
- if (LINUX_S_ISLNK (inode->i_mode)) {
- if (inode->i_file_acl == 0) {
- /* With no EA block, we can rely on i_blocks */
- if (inode->i_blocks == 0)
- return 0;
- } else {
- /* With an EA block, life gets more tricky */
- if (inode->i_size >= EXT2_N_BLOCKS*4)
- return 1; /* definitely using i_block[] */
- if (inode->i_size > 4 && inode->i_block[1] == 0)
- return 1; /* definitely using i_block[] */
- return 0; /* Probably a fast symlink */
- }
- }
- return 1;
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/version.c b/release/src/router/busybox/e2fsprogs/ext2fs/version.c
deleted file mode 100644
index d2981e867e..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/version.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * version.c --- Return the version of the ext2 library
- *
- * Copyright (C) 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-static const char *lib_version = E2FSPROGS_VERSION;
-static const char *lib_date = E2FSPROGS_DATE;
-
-int ext2fs_parse_version_string(const char *ver_string)
-{
- const char *cp;
- int version = 0;
-
- for (cp = ver_string; *cp; cp++) {
- if (*cp == '.')
- continue;
- if (!isdigit(*cp))
- break;
- version = (version * 10) + (*cp - '0');
- }
- return version;
-}
-
-
-int ext2fs_get_library_version(const char **ver_string,
- const char **date_string)
-{
- if (ver_string)
- *ver_string = lib_version;
- if (date_string)
- *date_string = lib_date;
-
- return ext2fs_parse_version_string(lib_version);
-}
diff --git a/release/src/router/busybox/e2fsprogs/ext2fs/write_bb_file.c b/release/src/router/busybox/e2fsprogs/ext2fs/write_bb_file.c
deleted file mode 100644
index 5b19eefa09..0000000000
--- a/release/src/router/busybox/e2fsprogs/ext2fs/write_bb_file.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * write_bb_file.c --- write a list of bad blocks to a FILE *
- *
- * Copyright (C) 1994, 1995 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list,
- unsigned int flags EXT2FS_ATTR((unused)),
- FILE *f)
-{
- badblocks_iterate bb_iter;
- blk_t blk;
- errcode_t retval;
-
- retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter);
- if (retval)
- return retval;
-
- while (ext2fs_badblocks_list_iterate(bb_iter, &blk)) {
- fprintf(f, "%d\n", blk);
- }
- ext2fs_badblocks_list_iterate_end(bb_iter);
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/fsck.c b/release/src/router/busybox/e2fsprogs/fsck.c
index 3a0743bb12..59514a1a6c 100644
--- a/release/src/router/busybox/e2fsprogs/fsck.c
+++ b/release/src/router/busybox/e2fsprogs/fsck.c
@@ -1,6 +1,6 @@
/* vi: set sw=4 ts=4: */
/*
- * pfsck --- A generic, parallelizing front-end for the fsck program.
+ * fsck --- A generic, parallelizing front-end for the fsck program.
* It will automatically try to run fsck programs in parallel if the
* devices are on separate spindles. It is based on the same ideas as
* the generic front end for fsck by David Engel and Fred van Kempen,
@@ -23,79 +23,160 @@
* Licensed under GPLv2, see file LICENSE in this source tree.
*/
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <limits.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#include <time.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <paths.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-
-#include "fsck.h"
-#include "blkid/blkid.h"
-
-#include "e2fsbb.h"
+/* All filesystem specific hooks have been removed.
+ * If filesystem cannot be determined, we will execute
+ * "fsck.auto". Currently this also happens if you specify
+ * UUID=xxx or LABEL=xxx as an object to check.
+ * Detection code for that is also probably has to be in fsck.auto.
+ *
+ * In other words, this is _really_ is just a driver program which
+ * spawns actual fsck.something for each filesystem to check.
+ * It doesn't guess filesystem types from on-disk format.
+ */
+//config:config FSCK
+//config: bool "fsck"
+//config: default y
+//config: help
+//config: fsck is used to check and optionally repair one or more filesystems.
+//config: In actuality, fsck is simply a front-end for the various file system
+//config: checkers (fsck.fstype) available under Linux.
+
+//applet:IF_FSCK(APPLET(fsck, BB_DIR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_FSCK) += fsck.o
+
+//usage:#define fsck_trivial_usage
+//usage: "[-ANPRTV] [-t FSTYPE] [FS_OPTS] [BLOCKDEV]..."
+//usage:#define fsck_full_usage "\n\n"
+//usage: "Check and repair filesystems\n"
+//usage: "\n -A Walk /etc/fstab and check all filesystems"
+//usage: "\n -N Don't execute, just show what would be done"
+//usage: "\n -P With -A, check filesystems in parallel"
+//usage: "\n -R With -A, skip the root filesystem"
+//usage: "\n -T Don't show title on startup"
+//usage: "\n -V Verbose"
+//DO_PROGRESS_INDICATOR is off:
+////usage: "\n -C FD Write status information to specified file descriptor"
+//usage: "\n -t TYPE List of filesystem types to check"
#include "libbb.h"
-
-#ifndef _PATH_MNTTAB
-#define _PATH_MNTTAB "/etc/fstab"
-#endif
-
-/*
- * fsck.h
+#include "common_bufsiz.h"
+
+/* "progress indicator" code is somewhat buggy and ext[23] specific.
+ * We should be filesystem agnostic. IOW: there should be a well-defined
+ * API for fsck.something, NOT ad-hoc hacks in generic fsck. */
+#define DO_PROGRESS_INDICATOR 0
+
+/* fsck 1.41.4 (27-Jan-2009) manpage says:
+ * 0 - No errors
+ * 1 - File system errors corrected
+ * 2 - System should be rebooted
+ * 4 - File system errors left uncorrected
+ * 8 - Operational error
+ * 16 - Usage or syntax error
+ * 32 - Fsck canceled by user request
+ * 128 - Shared library error
*/
-
-#ifndef DEFAULT_FSTYPE
-#define DEFAULT_FSTYPE "ext2"
-#endif
-
-#define MAX_DEVICES 32
-#define MAX_ARGS 32
+#define EXIT_OK 0
+#define EXIT_NONDESTRUCT 1
+#define EXIT_DESTRUCT 2
+#define EXIT_UNCORRECTED 4
+#define EXIT_ERROR 8
+#define EXIT_USAGE 16
+#define FSCK_CANCELED 32 /* Aborted with a signal or ^C */
/*
- * Internal structure for mount tabel entries.
+ * Internal structure for mount table entries.
*/
-
struct fs_info {
- char *device;
- char *mountpt;
- char *type;
- char *opts;
- int freq;
- int passno;
- int flags;
struct fs_info *next;
+ char *device;
+ char *mountpt;
+ char *type;
+ char *opts;
+ int passno;
+ int flags;
};
#define FLAG_DONE 1
#define FLAG_PROGRESS 2
-
/*
* Structure to allow exit codes to be stored
*/
struct fsck_instance {
+ struct fsck_instance *next;
int pid;
int flags;
- int exit_status;
+#if DO_PROGRESS_INDICATOR
time_t start_time;
- char * prog;
- char * type;
- char * device;
- char * base_device;
- struct fsck_instance *next;
+#endif
+ char *prog;
+ char *device;
+ char *base_device; /* /dev/hda for /dev/hdaN etc */
};
+static const char ignored_types[] ALIGN1 =
+ "ignore\0"
+ "iso9660\0"
+ "nfs\0"
+ "proc\0"
+ "sw\0"
+ "swap\0"
+ "tmpfs\0"
+ "devpts\0";
+
+#if 0
+static const char really_wanted[] ALIGN1 =
+ "minix\0"
+ "ext2\0"
+ "ext3\0"
+ "jfs\0"
+ "reiserfs\0"
+ "xiafs\0"
+ "xfs\0";
+#endif
+
+#define BASE_MD "/dev/md"
+
+struct globals {
+ char **args;
+ int num_args;
+ int verbose;
+
+#define FS_TYPE_FLAG_NORMAL 0
+#define FS_TYPE_FLAG_OPT 1
+#define FS_TYPE_FLAG_NEGOPT 2
+ char **fs_type_list;
+ uint8_t *fs_type_flag;
+ smallint fs_type_negated;
+
+ smallint noexecute;
+ smallint serialize;
+ smallint skip_root;
+ /* smallint like_mount; */
+ smallint parallel_root;
+ smallint force_all_parallel;
+ smallint kill_sent;
+
+#if DO_PROGRESS_INDICATOR
+ smallint progress;
+ int progress_fd;
+#endif
+
+ int num_running;
+ int max_running;
+ char *fstype;
+ struct fs_info *filesys_info;
+ struct fs_info *filesys_last;
+ struct fsck_instance *instance_list;
+} FIX_ALIASING;
+#define G (*(struct globals*)bb_common_bufsiz1)
+#define INIT_G() do { \
+ setup_common_bufsiz(); \
+ BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
+} while (0)
+
/*
- * base_device.c
- *
* Return the "base device" given a particular device; this is used to
* assure that we only fsck one partition on a particular drive at any
* one time. Otherwise, the disk heads will be seeking all over the
@@ -103,57 +184,53 @@ struct fsck_instance {
*
* The base_device() function returns an allocated string which must
* be freed.
- *
*/
-
-
-#ifdef CONFIG_FEATURE_DEVFS
+#if ENABLE_FEATURE_DEVFS
/*
* Required for the uber-silly devfs /dev/ide/host1/bus2/target3/lun3
* pathames.
*/
static const char *const devfs_hier[] = {
- "host", "bus", "target", "lun", 0
+ "host", "bus", "target", "lun", NULL
};
#endif
static char *base_device(const char *device)
{
char *str, *cp;
-#ifdef CONFIG_FEATURE_DEVFS
+#if ENABLE_FEATURE_DEVFS
const char *const *hier;
const char *disk;
int len;
#endif
+ str = xstrdup(device);
- cp = str = xstrdup(device);
-
- /* Skip over /dev/; if it's not present, give up. */
- if (strncmp(cp, "/dev/", 5) != 0)
+ /* Skip over "/dev/"; if it's not present, give up */
+ cp = skip_dev_pfx(str);
+ if (cp == str)
goto errout;
- cp += 5;
/*
* For md devices, we treat them all as if they were all
* on one disk, since we don't know how to parallelize them.
*/
if (cp[0] == 'm' && cp[1] == 'd') {
- *(cp+2) = 0;
+ cp[2] = 0;
return str;
}
/* Handle DAC 960 devices */
- if (strncmp(cp, "rd/", 3) == 0) {
+ if (is_prefixed_with(cp, "rd/")) {
cp += 3;
- if (cp[0] != 'c' || cp[2] != 'd' ||
- !isdigit(cp[1]) || !isdigit(cp[3]))
+ if (cp[0] != 'c' || !isdigit(cp[1])
+ || cp[2] != 'd' || !isdigit(cp[3]))
goto errout;
- *(cp+4) = 0;
+ cp[4] = 0;
return str;
}
/* Now let's handle /dev/hd* and /dev/sd* devices.... */
- if ((cp[0] == 'h' || cp[0] == 's') && (cp[1] == 'd')) {
+ if ((cp[0] == 'h' || cp[0] == 's') && cp[1] == 'd') {
cp += 2;
/* If there's a single number after /dev/hd, skip it */
if (isdigit(*cp))
@@ -161,16 +238,16 @@ static char *base_device(const char *device)
/* What follows must be an alpha char, or give up */
if (!isalpha(*cp))
goto errout;
- *(cp + 1) = 0;
+ cp[1] = 0;
return str;
}
-#ifdef CONFIG_FEATURE_DEVFS
+#if ENABLE_FEATURE_DEVFS
/* Now let's handle devfs (ugh) names */
len = 0;
- if (strncmp(cp, "ide/", 4) == 0)
+ if (is_prefixed_with(cp, "ide/"))
len = 4;
- if (strncmp(cp, "scsi/", 5) == 0)
+ if (is_prefixed_with(cp, "scsi/"))
len = 5;
if (len) {
cp += len;
@@ -181,323 +258,103 @@ static char *base_device(const char *device)
* some number of digits at each level, abort.
*/
for (hier = devfs_hier; *hier; hier++) {
- len = strlen(*hier);
- if (strncmp(cp, *hier, len) != 0)
+ cp = is_prefixed_with(cp, *hier);
+ if (!cp)
goto errout;
- cp += len;
- while (*cp != '/' && *cp != 0) {
+ while (*cp != '/' && *cp != '\0') {
if (!isdigit(*cp))
goto errout;
cp++;
}
+//FIXME: what if *cp = '\0' now? cp++ moves past it!!!
cp++;
}
- *(cp - 1) = 0;
+ cp[-1] = '\0';
return str;
}
/* Now handle devfs /dev/disc or /dev/disk names */
- disk = 0;
- if (strncmp(cp, "discs/", 6) == 0)
+ disk = NULL;
+ if (is_prefixed_with(cp, "discs/"))
disk = "disc";
- else if (strncmp(cp, "disks/", 6) == 0)
+ else if (is_prefixed_with(cp, "disks/"))
disk = "disk";
if (disk) {
cp += 6;
- if (strncmp(cp, disk, 4) != 0)
+ cp = is_prefixed_with(cp, disk);
+ if (!cp)
goto errout;
- cp += 4;
- while (*cp != '/' && *cp != 0) {
+ while (*cp != '/' && *cp != '\0') {
if (!isdigit(*cp))
goto errout;
cp++;
}
- *cp = 0;
+ *cp = '\0';
return str;
}
#endif
-
-errout:
+ errout:
free(str);
return NULL;
}
-
-static const char *const ignored_types[] = {
- "ignore",
- "iso9660",
- "nfs",
- "proc",
- "sw",
- "swap",
- "tmpfs",
- "devpts",
- NULL
-};
-
-static const char *const really_wanted[] = {
- "minix",
- "ext2",
- "ext3",
- "jfs",
- "reiserfs",
- "xiafs",
- "xfs",
- NULL
-};
-
-#define BASE_MD "/dev/md"
-
-/*
- * Global variables for options
- */
-static char *devices[MAX_DEVICES];
-static char *args[MAX_ARGS];
-static int num_devices, num_args;
-
-static int verbose;
-static int doall;
-static int noexecute;
-static int serialize;
-static int skip_root;
-static int like_mount;
-static int notitle;
-static int parallel_root;
-static int progress;
-static int progress_fd;
-static int force_all_parallel;
-static int num_running;
-static int max_running;
-static volatile int cancel_requested;
-static int kill_sent;
-static char *fstype;
-static struct fs_info *filesys_info, *filesys_last;
-static struct fsck_instance *instance_list;
-static char *fsck_path;
-static blkid_cache cache;
-
-static char *string_copy(const char *s)
-{
- char *ret;
-
- if (!s)
- return 0;
- ret = xstrdup(s);
- return ret;
-}
-
-static int string_to_int(const char *s)
-{
- long l;
- char *p;
-
- l = strtol(s, &p, 0);
- if (*p || l == LONG_MIN || l == LONG_MAX || l < 0 || l > INT_MAX)
- return -1;
- else
- return (int) l;
-}
-
-static char *skip_over_blank(char *cp)
-{
- while (*cp && isspace(*cp))
- cp++;
- return cp;
-}
-
-static char *skip_over_word(char *cp)
-{
- while (*cp && !isspace(*cp))
- cp++;
- return cp;
-}
-
-static void strip_line(char *line)
+static void free_instance(struct fsck_instance *p)
{
- char *p;
-
- while (*line) {
- p = line + strlen(line) - 1;
- if ((*p == '\n') || (*p == '\r'))
- *p = 0;
- else
- break;
- }
-}
-
-static char *parse_word(char **buf)
-{
- char *word, *next;
-
- word = *buf;
- if (*word == 0)
- return 0;
-
- word = skip_over_blank(word);
- next = skip_over_word(word);
- if (*next)
- *next++ = 0;
- *buf = next;
- return word;
-}
-
-static void parse_escape(char *word)
-{
- char *q, c;
- const char *p;
-
- if (!word)
- return;
-
- strcpy_and_process_escape_sequences(word, word);
-}
-
-static void free_instance(struct fsck_instance *i)
-{
- if (i->prog)
- free(i->prog);
- if (i->device)
- free(i->device);
- if (i->base_device)
- free(i->base_device);
- free(i);
+ free(p->prog);
+ free(p->device);
+ free(p->base_device);
+ free(p);
}
static struct fs_info *create_fs_device(const char *device, const char *mntpnt,
const char *type, const char *opts,
- int freq, int passno)
+ int passno)
{
struct fs_info *fs;
- fs = xmalloc(sizeof(struct fs_info));
-
- fs->device = string_copy(device);
- fs->mountpt = string_copy(mntpnt);
- fs->type = string_copy(type);
- fs->opts = string_copy(opts ? opts : "");
- fs->freq = freq;
- fs->passno = passno;
- fs->flags = 0;
- fs->next = NULL;
-
- if (!filesys_info)
- filesys_info = fs;
+ fs = xzalloc(sizeof(*fs));
+ fs->device = xstrdup(device);
+ fs->mountpt = xstrdup(mntpnt);
+ if (strchr(type, ','))
+ type = (char *)"auto";
+ fs->type = xstrdup(type);
+ fs->opts = xstrdup(opts ? opts : "");
+ fs->passno = passno < 0 ? 1 : passno;
+ /*fs->flags = 0; */
+ /*fs->next = NULL; */
+
+ if (!G.filesys_info)
+ G.filesys_info = fs;
else
- filesys_last->next = fs;
- filesys_last = fs;
+ G.filesys_last->next = fs;
+ G.filesys_last = fs;
return fs;
}
-
-
-static int parse_fstab_line(char *line, struct fs_info **ret_fs)
-{
- char *dev, *device, *mntpnt, *type, *opts, *freq, *passno, *cp;
- struct fs_info *fs;
-
- *ret_fs = 0;
- strip_line(line);
- if ((cp = strchr(line, '#')))
- *cp = 0; /* Ignore everything after the comment char */
- cp = line;
-
- device = parse_word(&cp);
- mntpnt = parse_word(&cp);
- type = parse_word(&cp);
- opts = parse_word(&cp);
- freq = parse_word(&cp);
- passno = parse_word(&cp);
-
- if (!device)
- return 0; /* Allow blank lines */
-
- if (!mntpnt || !type)
- return -1;
-
- parse_escape(device);
- parse_escape(mntpnt);
- parse_escape(type);
- parse_escape(opts);
- parse_escape(freq);
- parse_escape(passno);
-
- dev = blkid_get_devname(cache, device, NULL);
- if (dev)
- device = dev;
-
- if (strchr(type, ','))
- type = 0;
-
- fs = create_fs_device(device, mntpnt, type ? type : "auto", opts,
- freq ? atoi(freq) : -1,
- passno ? atoi(passno) : -1);
- if (dev)
- free(dev);
-
- if (!fs)
- return -1;
- *ret_fs = fs;
- return 0;
-}
-
-static void interpret_type(struct fs_info *fs)
-{
- char *t;
-
- if (strcmp(fs->type, "auto") != 0)
- return;
- t = blkid_get_tag_value(cache, "TYPE", fs->device);
- if (t) {
- free(fs->type);
- fs->type = t;
- }
-}
-
-/*
- * Load the filesystem database from /etc/fstab
- */
+/* Load the filesystem database from /etc/fstab */
static void load_fs_info(const char *filename)
{
- FILE *f;
- char buf[1024];
- int lineno = 0;
- int old_fstab = 1;
- struct fs_info *fs;
+ FILE *fstab;
+ struct mntent mte;
+ char buf[1024];
- if ((f = fopen_or_warn(filename, "r")) == NULL) {
+ fstab = setmntent(filename, "r");
+ if (!fstab) {
+ bb_perror_msg("can't read '%s'", filename);
return;
}
- while (!feof(f)) {
- lineno++;
- if (!fgets(buf, sizeof(buf), f))
- break;
- buf[sizeof(buf)-1] = 0;
- if (parse_fstab_line(buf, &fs) < 0) {
- bb_error_msg("WARNING: bad format "
- "on line %d of %s\n", lineno, filename);
- continue;
- }
- if (!fs)
- continue;
- if (fs->passno < 0)
- fs->passno = 0;
- else
- old_fstab = 0;
- }
- fclose(f);
-
- if (old_fstab) {
- fputs("\007\007\007"
- "WARNING: Your /etc/fstab does not contain the fsck passno\n"
- " field. I will kludge around things for you, but you\n"
- " should fix your /etc/fstab file as soon as you can.\n\n", stderr);
-
- for (fs = filesys_info; fs; fs = fs->next) {
- fs->passno = 1;
- }
+ // Loop through entries
+ while (getmntent_r(fstab, &mte, buf, sizeof(buf))) {
+ //bb_error_msg("CREATE[%s][%s][%s][%s][%d]", mte.mnt_fsname, mte.mnt_dir,
+ // mte.mnt_type, mte.mnt_opts,
+ // mte.mnt_passno);
+ create_fs_device(mte.mnt_fsname, mte.mnt_dir,
+ mte.mnt_type, mte.mnt_opts,
+ mte.mnt_passno);
}
+ endmntent(fstab);
}
/* Lookup filesys in /etc/fstab and return the corresponding entry. */
@@ -505,44 +362,22 @@ static struct fs_info *lookup(char *filesys)
{
struct fs_info *fs;
- /* No filesys name given. */
- if (filesys == NULL)
- return NULL;
-
- for (fs = filesys_info; fs; fs = fs->next) {
- if (!strcmp(filesys, fs->device) ||
- (fs->mountpt && !strcmp(filesys, fs->mountpt)))
+ for (fs = G.filesys_info; fs; fs = fs->next) {
+ if (strcmp(filesys, fs->device) == 0
+ || (fs->mountpt && strcmp(filesys, fs->mountpt) == 0)
+ )
break;
}
return fs;
}
-/* Find fsck program for a given fs type. */
-static char *find_fsck(char *type)
-{
- char *s;
- const char *tpl;
- char *p = string_copy(fsck_path);
- struct stat st;
-
- /* Are we looking for a program or just a type? */
- tpl = (strncmp(type, "fsck.", 5) ? "%s/fsck.%s" : "%s/%s");
-
- for (s = strtok(p, ":"); s; s = strtok(NULL, ":")) {
- s = xasprintf(tpl, s, type);
- if (stat(s, &st) == 0) break;
- free(s);
- }
- free(p);
- return s;
-}
-
+#if DO_PROGRESS_INDICATOR
static int progress_active(void)
{
struct fsck_instance *inst;
- for (inst = instance_list; inst; inst = inst->next) {
+ for (inst = G.instance_list; inst; inst = inst->next) {
if (inst->flags & FLAG_DONE)
continue;
if (inst->flags & FLAG_PROGRESS)
@@ -550,248 +385,206 @@ static int progress_active(void)
}
return 0;
}
+#endif
-/*
- * Execute a particular fsck program, and link it into the list of
- * child processes we are waiting for.
- */
-static int execute(const char *type, const char *device, const char *mntpt,
- int interactive)
-{
- char *s, *argv[80];
- char *prog;
- int argc, i;
- struct fsck_instance *inst, *p;
- pid_t pid;
-
- inst = xzalloc(sizeof(struct fsck_instance));
-
- prog = xasprintf("fsck.%s", type);
- argv[0] = prog;
- argc = 1;
-
- for (i=0; i <num_args; i++)
- argv[argc++] = string_copy(args[i]);
-
- if (progress && !progress_active()) {
- if ((strcmp(type, "ext2") == 0) ||
- (strcmp(type, "ext3") == 0)) {
- char tmp[80];
- snprintf(tmp, 80, "-C%d", progress_fd);
- argv[argc++] = string_copy(tmp);
- inst->flags |= FLAG_PROGRESS;
- }
- }
-
- argv[argc++] = string_copy(device);
- argv[argc] = 0;
-
- s = find_fsck(prog);
- if (s == NULL) {
- bb_error_msg("%s: not found", prog);
- return ENOENT;
- }
-
- if (verbose || noexecute) {
- printf("[%s (%d) -- %s] ", s, num_running,
- mntpt ? mntpt : device);
- for (i=0; i < argc; i++)
- printf("%s ", argv[i]);
- bb_putchar('\n');
- }
-
- /* Fork and execute the correct program. */
- if (noexecute)
- pid = -1;
- else if ((pid = fork()) < 0) {
- perror("vfork"+1);
- return errno;
- } else if (pid == 0) {
- if (!interactive)
- close(0);
- (void) execv(s, argv);
- bb_simple_perror_msg_and_die(argv[0]);
- }
-
- for (i = 1; i < argc; i++)
- free(argv[i]);
-
- free(s);
- inst->pid = pid;
- inst->prog = prog;
- inst->type = string_copy(type);
- inst->device = string_copy(device);
- inst->base_device = base_device(device);
- inst->start_time = time(0);
- inst->next = NULL;
-
- /*
- * Find the end of the list, so we add the instance on at the end.
- */
- for (p = instance_list; p && p->next; p = p->next);
-
- if (p)
- p->next = inst;
- else
- instance_list = inst;
-
- return 0;
-}
/*
* Send a signal to all outstanding fsck child processes
*/
-static int kill_all(int signum)
+static void kill_all_if_got_signal(void)
{
struct fsck_instance *inst;
- int n = 0;
- for (inst = instance_list; inst; inst = inst->next) {
+ if (!bb_got_signal || G.kill_sent)
+ return;
+
+ for (inst = G.instance_list; inst; inst = inst->next) {
if (inst->flags & FLAG_DONE)
continue;
- kill(inst->pid, signum);
- n++;
+ kill(inst->pid, SIGTERM);
}
- return n;
+ G.kill_sent = 1;
}
/*
* Wait for one child process to exit; when it does, unlink it from
- * the list of executing child processes, and return it.
+ * the list of executing child processes, free, and return its exit status.
+ * If there is no exited child, return -1.
*/
-static struct fsck_instance *wait_one(int flags)
+static int wait_one(int flags)
{
- int status;
- int sig;
- struct fsck_instance *inst, *inst2, *prev;
- pid_t pid;
-
- if (!instance_list)
- return NULL;
-
- if (noexecute) {
- inst = instance_list;
- prev = 0;
-#ifdef RANDOM_DEBUG
- while (inst->next && (random() & 1)) {
- prev = inst;
- inst = inst->next;
- }
-#endif
- inst->exit_status = 0;
- goto ret_inst;
- }
+ int status;
+ int sig;
+ struct fsck_instance *inst, *prev;
+ pid_t pid;
- /*
- * gcc -Wall fails saving throw against stupidity
- * (inst and prev are thought to be uninitialized variables)
- */
- inst = prev = NULL;
+ if (!G.instance_list)
+ return -1;
+ /* if (G.noexecute) { already returned -1; } */
- do {
+ while (1) {
pid = waitpid(-1, &status, flags);
- if (cancel_requested && !kill_sent) {
- kill_all(SIGTERM);
- kill_sent++;
- }
- if ((pid == 0) && (flags & WNOHANG))
- return NULL;
+ kill_all_if_got_signal();
+ if (pid == 0) /* flags == WNOHANG and no children exited */
+ return -1;
if (pid < 0) {
- if ((errno == EINTR) || (errno == EAGAIN))
+ if (errno == EINTR)
continue;
- if (errno == ECHILD) {
- bb_error_msg("wait: no more child process?!?");
- return NULL;
+ if (errno == ECHILD) { /* paranoia */
+ bb_error_msg("wait: no more children");
+ return -1;
}
- perror("wait");
+ bb_perror_msg("wait");
continue;
}
- for (prev = 0, inst = instance_list;
- inst;
- prev = inst, inst = inst->next) {
+ prev = NULL;
+ inst = G.instance_list;
+ do {
if (inst->pid == pid)
- break;
- }
- } while (!inst);
+ goto child_died;
+ prev = inst;
+ inst = inst->next;
+ } while (inst);
+ }
+ child_died:
- if (WIFEXITED(status))
- status = WEXITSTATUS(status);
- else if (WIFSIGNALED(status)) {
+ status = WEXITSTATUS(status);
+ if (WIFSIGNALED(status)) {
sig = WTERMSIG(status);
- if (sig == SIGINT) {
- status = EXIT_UNCORRECTED;
- } else {
- printf("Warning... %s for device %s exited "
- "with signal %d.\n",
- inst->prog, inst->device, sig);
+ status = EXIT_UNCORRECTED;
+ if (sig != SIGINT) {
+ printf("Warning: %s %s terminated "
+ "by signal %d\n",
+ inst->prog, inst->device, sig);
status = EXIT_ERROR;
}
- } else {
- printf("%s %s: status is %x, should never happen.\n",
- inst->prog, inst->device, status);
- status = EXIT_ERROR;
}
- inst->exit_status = status;
- if (progress && (inst->flags & FLAG_PROGRESS) &&
- !progress_active()) {
- for (inst2 = instance_list; inst2; inst2 = inst2->next) {
+
+#if DO_PROGRESS_INDICATOR
+ if (progress && (inst->flags & FLAG_PROGRESS) && !progress_active()) {
+ struct fsck_instance *inst2;
+ for (inst2 = G.instance_list; inst2; inst2 = inst2->next) {
if (inst2->flags & FLAG_DONE)
continue;
- if (strcmp(inst2->type, "ext2") &&
- strcmp(inst2->type, "ext3"))
+ if (strcmp(inst2->type, "ext2") != 0
+ && strcmp(inst2->type, "ext3") != 0
+ ) {
continue;
- /*
+ }
+ /* ext[23], we will send USR1
+ * (request to start displaying progress bar)
+ *
* If we've just started the fsck, wait a tiny
* bit before sending the kill, to give it
* time to set up the signal handler
*/
- if (inst2->start_time < time(0)+2) {
- if (fork() == 0) {
- sleep(1);
- kill(inst2->pid, SIGUSR1);
- exit(0);
- }
- } else
- kill(inst2->pid, SIGUSR1);
+ if (inst2->start_time >= time(NULL) - 1)
+ sleep(1);
+ kill(inst2->pid, SIGUSR1);
inst2->flags |= FLAG_PROGRESS;
break;
}
}
-ret_inst:
+#endif
+
if (prev)
prev->next = inst->next;
else
- instance_list = inst->next;
- if (verbose > 1)
+ G.instance_list = inst->next;
+ if (G.verbose > 1)
printf("Finished with %s (exit status %d)\n",
- inst->device, inst->exit_status);
- num_running--;
- return inst;
+ inst->device, status);
+ G.num_running--;
+ free_instance(inst);
+
+ return status;
}
-#define FLAG_WAIT_ALL 0
-#define FLAG_WAIT_ATLEAST_ONE 1
/*
* Wait until all executing child processes have exited; return the
* logical OR of all of their exit code values.
*/
+#define FLAG_WAIT_ALL 0
+#define FLAG_WAIT_ATLEAST_ONE WNOHANG
static int wait_many(int flags)
{
+ int exit_status;
+ int global_status = 0;
+ int wait_flags = 0;
+
+ while ((exit_status = wait_one(wait_flags)) != -1) {
+ global_status |= exit_status;
+ wait_flags |= flags;
+ }
+ return global_status;
+}
+
+/*
+ * Execute a particular fsck program, and link it into the list of
+ * child processes we are waiting for.
+ */
+static void execute(const char *type, const char *device,
+ const char *mntpt /*, int interactive */)
+{
+ int i;
struct fsck_instance *inst;
- int global_status = 0;
- int wait_flags = 0;
-
- while ((inst = wait_one(wait_flags))) {
- global_status |= inst->exit_status;
- free_instance(inst);
-#ifdef RANDOM_DEBUG
- if (noexecute && (flags & WNOHANG) && !(random() % 3))
- break;
+ pid_t pid;
+
+ G.args[0] = xasprintf("fsck.%s", type);
+
+#if DO_PROGRESS_INDICATOR
+ if (progress && !progress_active()) {
+ if (strcmp(type, "ext2") == 0
+ || strcmp(type, "ext3") == 0
+ ) {
+ G.args[XXX] = xasprintf("-C%d", progress_fd); /* 1 */
+ inst->flags |= FLAG_PROGRESS;
+ }
+ }
#endif
- if (flags & FLAG_WAIT_ATLEAST_ONE)
- wait_flags = WNOHANG;
+
+ G.args[G.num_args - 2] = (char*)device;
+ /* G.args[G.num_args - 1] = NULL; - already is */
+
+ if (G.verbose || G.noexecute) {
+ printf("[%s (%d) -- %s]", G.args[0], G.num_running,
+ mntpt ? mntpt : device);
+ for (i = 0; G.args[i]; i++)
+ printf(" %s", G.args[i]);
+ bb_putchar('\n');
}
- return global_status;
+
+ /* Fork and execute the correct program. */
+ pid = -1;
+ if (!G.noexecute) {
+ pid = spawn(G.args);
+ if (pid < 0)
+ bb_simple_perror_msg(G.args[0]);
+ }
+
+#if DO_PROGRESS_INDICATOR
+ free(G.args[XXX]);
+#endif
+
+ /* No child, so don't record an instance */
+ if (pid <= 0) {
+ free(G.args[0]);
+ return;
+ }
+
+ inst = xzalloc(sizeof(*inst));
+ inst->pid = pid;
+ inst->prog = G.args[0];
+ inst->device = xstrdup(device);
+ inst->base_device = base_device(device);
+#if DO_PROGRESS_INDICATOR
+ inst->start_time = time(NULL);
+#endif
+
+ /* Add to the list of running fsck's.
+ * (was adding to the end, but adding to the front is simpler...) */
+ inst->next = G.instance_list;
+ G.instance_list = inst;
}
/*
@@ -802,104 +595,77 @@ static int wait_many(int flags)
* use that type regardless of what is specified in /etc/fstab.
*
* If the type isn't specified by the user, then use either the type
- * specified in /etc/fstab, or DEFAULT_FSTYPE.
+ * specified in /etc/fstab, or "auto".
*/
-static void fsck_device(struct fs_info *fs, int interactive)
+static void fsck_device(struct fs_info *fs /*, int interactive */)
{
const char *type;
- int retval;
-
- interpret_type(fs);
- if (strcmp(fs->type, "auto") != 0)
+ if (strcmp(fs->type, "auto") != 0) {
type = fs->type;
- else if (fstype && strncmp(fstype, "no", 2) &&
- strncmp(fstype, "opts=", 5) && strncmp(fstype, "loop", 4) &&
- !strchr(fstype, ','))
- type = fstype;
- else
- type = DEFAULT_FSTYPE;
-
- num_running++;
- retval = execute(type, fs->device, fs->mountpt, interactive);
- if (retval) {
- bb_error_msg("error %d while executing fsck.%s for %s",
- retval, type, fs->device);
- num_running--;
+ if (G.verbose > 2)
+ printf("using filesystem type '%s' %s\n",
+ type, "from fstab");
+ } else if (G.fstype
+ && (G.fstype[0] != 'n' || G.fstype[1] != 'o') /* != "no" */
+ && !is_prefixed_with(G.fstype, "opts=")
+ && !is_prefixed_with(G.fstype, "loop")
+ && !strchr(G.fstype, ',')
+ ) {
+ type = G.fstype;
+ if (G.verbose > 2)
+ printf("using filesystem type '%s' %s\n",
+ type, "from -t");
+ } else {
+ type = "auto";
+ if (G.verbose > 2)
+ printf("using filesystem type '%s' %s\n",
+ type, "(default)");
}
-}
+ G.num_running++;
+ execute(type, fs->device, fs->mountpt /*, interactive */);
+}
/*
- * Deal with the fsck -t argument.
+ * Returns TRUE if a partition on the same disk is already being
+ * checked.
*/
-struct fs_type_compile {
- char **list;
- int *type;
- int negate;
-} fs_type_compiled;
-
-#define FS_TYPE_NORMAL 0
-#define FS_TYPE_OPT 1
-#define FS_TYPE_NEGOPT 2
+static int device_already_active(char *device)
+{
+ struct fsck_instance *inst;
+ char *base;
-static const char fs_type_syntax_error[] =
-"Either all or none of the filesystem types passed to -t must be prefixed\n"
- "with 'no' or '!'.";
+ if (G.force_all_parallel)
+ return 0;
-static void compile_fs_type(char *fs_type, struct fs_type_compile *cmp)
-{
- char *cp, *list, *s;
- int num = 2;
- int negate, first_negate = 1;
-
- if (fs_type) {
- for (cp=fs_type; *cp; cp++) {
- if (*cp == ',')
- num++;
- }
+#ifdef BASE_MD
+ /* Don't check a soft raid disk with any other disk */
+ if (G.instance_list
+ && (is_prefixed_with(G.instance_list->device, BASE_MD)
+ || is_prefixed_with(device, BASE_MD))
+ ) {
+ return 1;
}
+#endif
- cmp->list = xzalloc(num * sizeof(char *));
- cmp->type = xzalloc(num * sizeof(int));
- cmp->negate = 0;
-
- if (!fs_type)
- return;
+ base = base_device(device);
+ /*
+ * If we don't know the base device, assume that the device is
+ * already active if there are any fsck instances running.
+ */
+ if (!base)
+ return (G.instance_list != NULL);
- list = string_copy(fs_type);
- num = 0;
- s = strtok(list, ",");
- while (s) {
- negate = 0;
- if (strncmp(s, "no", 2) == 0) {
- s += 2;
- negate = 1;
- } else if (*s == '!') {
- s++;
- negate = 1;
- }
- if (strcmp(s, "loop") == 0)
- /* loop is really short-hand for opts=loop */
- goto loop_special_case;
- else if (strncmp(s, "opts=", 5) == 0) {
- s += 5;
- loop_special_case:
- cmp->type[num] = negate ? FS_TYPE_NEGOPT : FS_TYPE_OPT;
- } else {
- if (first_negate) {
- cmp->negate = negate;
- first_negate = 0;
- }
- if ((negate && !cmp->negate) ||
- (!negate && cmp->negate)) {
- bb_error_msg_and_die("%s", fs_type_syntax_error);
- }
+ for (inst = G.instance_list; inst; inst = inst->next) {
+ if (!inst->base_device || !strcmp(base, inst->base_device)) {
+ free(base);
+ return 1;
}
- cmp->list[num++] = string_copy(s);
- s = strtok(NULL, ",");
}
- free(list);
+
+ free(base);
+ return 0;
}
/*
@@ -908,199 +674,157 @@ static void compile_fs_type(char *fs_type, struct fs_type_compile *cmp)
*/
static int opt_in_list(char *opt, char *optlist)
{
- char *list, *s;
+ char *s;
+ int len;
if (!optlist)
return 0;
- list = string_copy(optlist);
- s = strtok(list, ",");
- while (s) {
- if (strcmp(s, opt) == 0) {
- free(list);
- return 1;
- }
- s = strtok(NULL, ",");
+ len = strlen(opt);
+ s = optlist - 1;
+ while (1) {
+ s = strstr(s + 1, opt);
+ if (!s)
+ return 0;
+ /* neither "opt.." nor "xxx,opt.."? */
+ if (s != optlist && s[-1] != ',')
+ continue;
+ /* neither "..opt" nor "..opt,xxx"? */
+ if (s[len] != '\0' && s[len] != ',')
+ continue;
+ return 1;
}
- free(list);
- return 0;
}
/* See if the filesystem matches the criteria given by the -t option */
-static int fs_match(struct fs_info *fs, struct fs_type_compile *cmp)
+static int fs_match(struct fs_info *fs)
{
- int n, ret = 0, checked_type = 0;
+ int n, ret, checked_type;
char *cp;
- if (cmp->list == 0 || cmp->list[0] == 0)
+ if (!G.fs_type_list)
return 1;
- for (n=0; (cp = cmp->list[n]); n++) {
- switch (cmp->type[n]) {
- case FS_TYPE_NORMAL:
+ ret = 0;
+ checked_type = 0;
+ n = 0;
+ while (1) {
+ cp = G.fs_type_list[n];
+ if (!cp)
+ break;
+ switch (G.fs_type_flag[n]) {
+ case FS_TYPE_FLAG_NORMAL:
checked_type++;
- if (strcmp(cp, fs->type) == 0) {
+ if (strcmp(cp, fs->type) == 0)
ret = 1;
- }
break;
- case FS_TYPE_NEGOPT:
+ case FS_TYPE_FLAG_NEGOPT:
if (opt_in_list(cp, fs->opts))
return 0;
break;
- case FS_TYPE_OPT:
+ case FS_TYPE_FLAG_OPT:
if (!opt_in_list(cp, fs->opts))
return 0;
break;
}
+ n++;
}
if (checked_type == 0)
return 1;
- return (cmp->negate ? !ret : ret);
+
+ return (G.fs_type_negated ? !ret : ret);
}
/* Check if we should ignore this filesystem. */
static int ignore(struct fs_info *fs)
{
- int wanted;
- char *s;
-
/*
* If the pass number is 0, ignore it.
*/
if (fs->passno == 0)
return 1;
- interpret_type(fs);
-
/*
* If a specific fstype is specified, and it doesn't match,
* ignore it.
*/
- if (!fs_match(fs, &fs_type_compiled)) return 1;
-
- /* Are we ignoring this type? */
- if (index_in_str_array(ignored_types, fs->type) >= 0)
+ if (!fs_match(fs))
return 1;
- /* Do we really really want to check this fs? */
- wanted = index_in_str_array(really_wanted, fs->type) >= 0;
-
- /* See if the <fsck.fs> program is available. */
- s = find_fsck(fs->type);
- if (s == NULL) {
- if (wanted)
- bb_error_msg("can't check %s: fsck.%s not found",
- fs->device, fs->type);
+ /* Are we ignoring this type? */
+ if (index_in_strings(ignored_types, fs->type) >= 0)
return 1;
- }
- free(s);
/* We can and want to check this file system type. */
return 0;
}
-/*
- * Returns TRUE if a partition on the same disk is already being
- * checked.
- */
-static int device_already_active(char *device)
-{
- struct fsck_instance *inst;
- char *base;
-
- if (force_all_parallel)
- return 0;
-
-#ifdef BASE_MD
- /* Don't check a soft raid disk with any other disk */
- if (instance_list &&
- (!strncmp(instance_list->device, BASE_MD, sizeof(BASE_MD)-1) ||
- !strncmp(device, BASE_MD, sizeof(BASE_MD)-1)))
- return 1;
-#endif
-
- base = base_device(device);
- /*
- * If we don't know the base device, assume that the device is
- * already active if there are any fsck instances running.
- */
- if (!base)
- return (instance_list != 0);
- for (inst = instance_list; inst; inst = inst->next) {
- if (!inst->base_device || !strcmp(base, inst->base_device)) {
- free(base);
- return 1;
- }
- }
- free(base);
- return 0;
-}
-
/* Check all file systems, using the /etc/fstab table. */
static int check_all(void)
{
- struct fs_info *fs = NULL;
+ struct fs_info *fs;
int status = EXIT_OK;
- int not_done_yet = 1;
- int passno = 1;
- int pass_done;
+ smallint not_done_yet;
+ smallint pass_done;
+ int passno;
- if (verbose)
- fputs("Checking all file systems.\n", stdout);
+ if (G.verbose)
+ puts("Checking all filesystems");
/*
* Do an initial scan over the filesystem; mark filesystems
* which should be ignored as done, and resolve any "auto"
* filesystem types (done as a side-effect of calling ignore()).
*/
- for (fs = filesys_info; fs; fs = fs->next) {
+ for (fs = G.filesys_info; fs; fs = fs->next)
if (ignore(fs))
fs->flags |= FLAG_DONE;
- }
/*
* Find and check the root filesystem.
*/
- if (!parallel_root) {
- for (fs = filesys_info; fs; fs = fs->next) {
- if (LONE_CHAR(fs->mountpt, '/'))
+ if (!G.parallel_root) {
+ for (fs = G.filesys_info; fs; fs = fs->next) {
+ if (LONE_CHAR(fs->mountpt, '/')) {
+ if (!G.skip_root && !ignore(fs)) {
+ fsck_device(fs /*, 1*/);
+ status |= wait_many(FLAG_WAIT_ALL);
+ if (status > EXIT_NONDESTRUCT)
+ return status;
+ }
+ fs->flags |= FLAG_DONE;
break;
- }
- if (fs) {
- if (!skip_root && !ignore(fs)) {
- fsck_device(fs, 1);
- status |= wait_many(FLAG_WAIT_ALL);
- if (status > EXIT_NONDESTRUCT)
- return status;
}
- fs->flags |= FLAG_DONE;
}
}
/*
- * This is for the bone-headed user who enters the root
- * filesystem twice. Skip root will skep all root entries.
+ * This is for the bone-headed user who has root
+ * filesystem listed twice.
+ * "Skip root" will skip _all_ root entries.
*/
- if (skip_root)
- for (fs = filesys_info; fs; fs = fs->next)
+ if (G.skip_root)
+ for (fs = G.filesys_info; fs; fs = fs->next)
if (LONE_CHAR(fs->mountpt, '/'))
fs->flags |= FLAG_DONE;
+ not_done_yet = 1;
+ passno = 1;
while (not_done_yet) {
not_done_yet = 0;
pass_done = 1;
- for (fs = filesys_info; fs; fs = fs->next) {
- if (cancel_requested)
+ for (fs = G.filesys_info; fs; fs = fs->next) {
+ if (bb_got_signal)
break;
if (fs->flags & FLAG_DONE)
continue;
/*
* If the filesystem's pass number is higher
- * than the current pass number, then we don't
+ * than the current pass number, then we didn't
* do it yet.
*/
if (fs->passno > passno) {
- not_done_yet++;
+ not_done_yet = 1;
continue;
}
/*
@@ -1115,7 +839,7 @@ static int check_all(void)
/*
* Spawn off the fsck process
*/
- fsck_device(fs, serialize);
+ fsck_device(fs /*, G.serialize*/);
fs->flags |= FLAG_DONE;
/*
@@ -1123,254 +847,268 @@ static int check_all(void)
* have a limit on the number of fsck's extant
* at one time, apply that limit.
*/
- if (serialize ||
- (max_running && (num_running >= max_running))) {
+ if (G.serialize
+ || (G.num_running >= G.max_running)
+ ) {
pass_done = 0;
break;
}
}
- if (cancel_requested)
+ if (bb_got_signal)
break;
- if (verbose > 1)
+ if (G.verbose > 1)
printf("--waiting-- (pass %d)\n", passno);
status |= wait_many(pass_done ? FLAG_WAIT_ALL :
- FLAG_WAIT_ATLEAST_ONE);
+ FLAG_WAIT_ATLEAST_ONE);
if (pass_done) {
- if (verbose > 1)
- printf("----------------------------------\n");
+ if (G.verbose > 1)
+ puts("----------------------------------");
passno++;
} else
- not_done_yet++;
- }
- if (cancel_requested && !kill_sent) {
- kill_all(SIGTERM);
- kill_sent++;
+ not_done_yet = 1;
}
+ kill_all_if_got_signal();
status |= wait_many(FLAG_WAIT_ATLEAST_ONE);
return status;
}
-static void signal_cancel(int sig FSCK_ATTR((unused)))
+/*
+ * Deal with the fsck -t argument.
+ * Huh, for mount "-t novfat,nfs" means "neither vfat nor nfs"!
+ * Why here we require "-t novfat,nonfs" ??
+ */
+static void compile_fs_type(char *fs_type)
+{
+ char *s;
+ int num = 2;
+ smallint negate;
+
+ s = fs_type;
+ while ((s = strchr(s, ','))) {
+ num++;
+ s++;
+ }
+
+ G.fs_type_list = xzalloc(num * sizeof(G.fs_type_list[0]));
+ G.fs_type_flag = xzalloc(num * sizeof(G.fs_type_flag[0]));
+ G.fs_type_negated = -1; /* not yet known is it negated or not */
+
+ num = 0;
+ s = fs_type;
+ while (1) {
+ char *comma;
+
+ negate = 0;
+ if (s[0] == 'n' && s[1] == 'o') { /* "no.." */
+ s += 2;
+ negate = 1;
+ } else if (s[0] == '!') {
+ s++;
+ negate = 1;
+ }
+
+ if (strcmp(s, "loop") == 0)
+ /* loop is really short-hand for opts=loop */
+ goto loop_special_case;
+ if (is_prefixed_with(s, "opts=")) {
+ s += 5;
+ loop_special_case:
+ G.fs_type_flag[num] = negate ? FS_TYPE_FLAG_NEGOPT : FS_TYPE_FLAG_OPT;
+ } else {
+ if (G.fs_type_negated == -1)
+ G.fs_type_negated = negate;
+ if (G.fs_type_negated != negate)
+ bb_error_msg_and_die(
+"either all or none of the filesystem types passed to -t must be prefixed "
+"with 'no' or '!'");
+ }
+ comma = strchrnul(s, ',');
+ G.fs_type_list[num++] = xstrndup(s, comma-s);
+ if (*comma == '\0')
+ break;
+ s = comma + 1;
+ }
+}
+
+static char **new_args(void)
{
- cancel_requested++;
+ G.args = xrealloc_vector(G.args, 2, G.num_args);
+ return &G.args[G.num_args++];
}
-static void PRS(int argc, char **argv)
+int fsck_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int fsck_main(int argc UNUSED_PARAM, char **argv)
{
- int i, j;
- char *arg, *dev, *tmp = NULL;
- char options[128];
- int opt = 0;
- int opts_for_fsck = 0;
- struct sigaction sa;
+ int i, status;
+ /*int interactive;*/
+ struct fs_info *fs;
+ const char *fstab;
+ char *tmp;
+ char **devices;
+ int num_devices;
+ smallint opts_for_fsck;
+ smallint doall;
+ smallint notitle;
- /*
- * Set up signal action
- */
- memset(&sa, 0, sizeof(struct sigaction));
- sa.sa_handler = signal_cancel;
- sigaction(SIGINT, &sa, 0);
- sigaction(SIGTERM, &sa, 0);
+ INIT_G();
+ /* we want wait() to be interruptible */
+ signal_no_SA_RESTART_empty_mask(SIGINT, record_signo);
+ signal_no_SA_RESTART_empty_mask(SIGTERM, record_signo);
+
+ setbuf(stdout, NULL);
+
+ opts_for_fsck = doall = notitle = 0;
+ devices = NULL;
num_devices = 0;
- num_args = 0;
- instance_list = 0;
+ new_args(); /* G.args[0] = NULL, will be replaced by fsck.<type> */
+ /* G.instance_list = NULL; - in bss, so already zeroed */
- for (i=1; i < argc; i++) {
- arg = argv[i];
- if (!arg)
- continue;
+ while (*++argv) {
+ int j;
+ int optpos;
+ char *options;
+ char *arg = *argv;
+
+ /* "/dev/blk" or "/path" or "UUID=xxx" or "LABEL=xxx" */
if ((arg[0] == '/' && !opts_for_fsck) || strchr(arg, '=')) {
- if (num_devices >= MAX_DEVICES) {
- bb_error_msg_and_die("too many devices");
- }
- dev = blkid_get_devname(cache, arg, NULL);
- if (!dev && strchr(arg, '=')) {
- /*
- * Check to see if we failed because
- * /proc/partitions isn't found.
- */
- if (access("/proc/partitions", R_OK) < 0) {
- bb_perror_msg_and_die("can't open /proc/partitions "
- "(is /proc mounted?)");
- }
- /*
- * Check to see if this is because
- * we're not running as root
- */
- if (geteuid())
- bb_error_msg_and_die(
- "must be root to scan for matching filesystems: %s\n", arg);
- else
- bb_error_msg_and_die(
- "can't find matching filesystem: %s", arg);
- }
- devices[num_devices++] = dev ? dev : string_copy(arg);
+// FIXME: must check that arg is a blkdev, or resolve
+// "/path", "UUID=xxx" or "LABEL=xxx" into block device name
+// ("UUID=xxx"/"LABEL=xxx" can probably shifted to fsck.auto duties)
+ devices = xrealloc_vector(devices, 2, num_devices);
+ devices[num_devices++] = arg;
continue;
}
+
if (arg[0] != '-' || opts_for_fsck) {
- if (num_args >= MAX_ARGS) {
- bb_error_msg_and_die("too many arguments");
- }
- args[num_args++] = string_copy(arg);
+ *new_args() = arg;
continue;
}
- for (j=1; arg[j]; j++) {
- if (opts_for_fsck) {
- options[++opt] = arg[j];
- continue;
- }
+
+ if (LONE_CHAR(arg + 1, '-')) { /* "--" ? */
+ opts_for_fsck = 1;
+ continue;
+ }
+
+ optpos = 0;
+ options = NULL;
+ for (j = 1; arg[j]; j++) {
switch (arg[j]) {
case 'A':
- doall++;
+ doall = 1;
break;
+#if DO_PROGRESS_INDICATOR
case 'C':
- progress++;
- if (arg[j+1]) {
- progress_fd = string_to_int(arg+j+1);
- if (progress_fd < 0)
- progress_fd = 0;
- else
- goto next_arg;
- } else if ((i+1) < argc
- && argv[i+1][0] != '-') {
- progress_fd = string_to_int(argv[i]);
- if (progress_fd < 0)
- progress_fd = 0;
- else {
- goto next_arg;
- i++;
- }
+ progress = 1;
+ if (arg[++j]) { /* -Cn */
+ progress_fd = xatoi_positive(&arg[j]);
+ goto next_arg;
}
- break;
+ /* -C n */
+ if (!*++argv)
+ bb_show_usage();
+ progress_fd = xatoi_positive(*argv);
+ goto next_arg;
+#endif
case 'V':
- verbose++;
+ G.verbose++;
break;
case 'N':
- noexecute++;
+ G.noexecute = 1;
break;
case 'R':
- skip_root++;
+ G.skip_root = 1;
break;
case 'T':
- notitle++;
- break;
- case 'M':
- like_mount++;
+ notitle = 1;
break;
+/* case 'M':
+ like_mount = 1;
+ break; */
case 'P':
- parallel_root++;
+ G.parallel_root = 1;
break;
case 's':
- serialize++;
+ G.serialize = 1;
break;
case 't':
- tmp = 0;
- if (fstype)
+ if (G.fstype)
bb_show_usage();
- if (arg[j+1])
- tmp = arg+j+1;
- else if ((i+1) < argc)
- tmp = argv[++i];
+ if (arg[++j])
+ tmp = &arg[j];
+ else if (*++argv)
+ tmp = *argv;
else
bb_show_usage();
- fstype = string_copy(tmp);
- compile_fs_type(fstype, &fs_type_compiled);
+ G.fstype = xstrdup(tmp);
+ compile_fs_type(G.fstype);
goto next_arg;
- case '-':
- opts_for_fsck++;
- break;
case '?':
bb_show_usage();
break;
default:
- options[++opt] = arg[j];
+ optpos++;
+ /* one extra for '\0' */
+ options = xrealloc(options, optpos + 2);
+ options[optpos] = arg[j];
break;
}
}
- next_arg:
- if (opt) {
+ next_arg:
+ if (optpos) {
options[0] = '-';
- options[++opt] = '\0';
- if (num_args >= MAX_ARGS) {
- bb_error_msg("too many arguments");
- }
- args[num_args++] = string_copy(options);
- opt = 0;
+ options[optpos + 1] = '\0';
+ *new_args() = options;
}
}
if (getenv("FSCK_FORCE_ALL_PARALLEL"))
- force_all_parallel++;
- if ((tmp = getenv("FSCK_MAX_INST")))
- max_running = atoi(tmp);
-}
-
-int fsck_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int fsck_main(int argc, char **argv)
-{
- int i, status = 0;
- int interactive = 0;
- const char *fstab;
- struct fs_info *fs;
-
- setvbuf(stdout, NULL, _IONBF, BUFSIZ);
- setvbuf(stderr, NULL, _IONBF, BUFSIZ);
-
- blkid_get_cache(&cache, NULL);
- PRS(argc, argv);
+ G.force_all_parallel = 1;
+ tmp = getenv("FSCK_MAX_INST");
+ G.max_running = INT_MAX;
+ if (tmp)
+ G.max_running = xatoi(tmp);
+ new_args(); /* G.args[G.num_args - 2] will be replaced by <device> */
+ new_args(); /* G.args[G.num_args - 1] is the last, NULL element */
if (!notitle)
- printf("fsck %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE);
+ puts("fsck (busybox "BB_VER", "BB_BT")");
+ /* Even plain "fsck /dev/hda1" needs fstab to get fs type,
+ * so we are scanning it anyway */
fstab = getenv("FSTAB_FILE");
if (!fstab)
- fstab = _PATH_MNTTAB;
+ fstab = "/etc/fstab";
load_fs_info(fstab);
- fsck_path = e2fs_set_sbin_path();
+ /*interactive = (num_devices == 1) | G.serialize;*/
- if ((num_devices == 1) || (serialize))
- interactive = 1;
-
- /* If -A was specified ("check all"), do that! */
+ if (num_devices == 0)
+ /*interactive =*/ G.serialize = doall = 1;
if (doall)
return check_all();
- if (num_devices == 0) {
- serialize++;
- interactive++;
- return check_all();
- }
+ status = 0;
for (i = 0; i < num_devices; i++) {
- if (cancel_requested) {
- if (!kill_sent) {
- kill_all(SIGTERM);
- kill_sent++;
- }
+ if (bb_got_signal) {
+ kill_all_if_got_signal();
break;
}
+
fs = lookup(devices[i]);
- if (!fs) {
- fs = create_fs_device(devices[i], 0, "auto",
- 0, -1, -1);
- if (!fs)
- continue;
- }
- fsck_device(fs, interactive);
- if (serialize ||
- (max_running && (num_running >= max_running))) {
- struct fsck_instance *inst;
-
- inst = wait_one(0);
- if (inst) {
- status |= inst->exit_status;
- free_instance(inst);
- }
- if (verbose > 1)
- printf("----------------------------------\n");
+ if (!fs)
+ fs = create_fs_device(devices[i], "", "auto", NULL, -1);
+ fsck_device(fs /*, interactive */);
+
+ if (G.serialize
+ || (G.num_running >= G.max_running)
+ ) {
+ int exit_status = wait_one(0);
+ if (exit_status >= 0)
+ status |= exit_status;
+ if (G.verbose > 1)
+ puts("----------------------------------");
}
}
status |= wait_many(FLAG_WAIT_ALL);
- blkid_put_cache(cache);
return status;
}
diff --git a/release/src/router/busybox/e2fsprogs/fsck.h b/release/src/router/busybox/e2fsprogs/fsck.h
deleted file mode 100644
index 2ca2af7da8..0000000000
--- a/release/src/router/busybox/e2fsprogs/fsck.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * fsck.h
- */
-
-#define FSCK_ATTR(x) __attribute__(x)
-
-#define EXIT_OK 0
-#define EXIT_NONDESTRUCT 1
-#define EXIT_DESTRUCT 2
-#define EXIT_UNCORRECTED 4
-#define EXIT_ERROR 8
-#define EXIT_USAGE 16
-#define FSCK_CANCELED 32 /* Aborted with a signal or ^C */
-
-extern char *e2fs_set_sbin_path(void);
diff --git a/release/src/router/busybox/e2fsprogs/lsattr.c b/release/src/router/busybox/e2fsprogs/lsattr.c
index 9e0e4cb602..d2348b5f74 100644
--- a/release/src/router/busybox/e2fsprogs/lsattr.c
+++ b/release/src/router/busybox/e2fsprogs/lsattr.c
@@ -9,52 +9,53 @@
* This file can be redistributed under the terms of the GNU General
* Public License
*/
-
-/*
- * History:
- * 93/10/30 - Creation
- * 93/11/13 - Replace stat() calls by lstat() to avoid loops
- * 94/02/27 - Integrated in Ted's distribution
- * 98/12/29 - Display version info only when -V specified (G M Sipe)
- */
-
-#include <sys/types.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-
-#include "ext2fs/ext2_fs.h"
-#include "e2fsbb.h"
-#include "e2p/e2p.h"
-
-#define OPT_RECUR 1
-#define OPT_ALL 2
-#define OPT_DIRS_OPT 4
-#define OPT_PF_LONG 8
-#define OPT_GENERATION 16
-static int flags;
+//config:config LSATTR
+//config: bool "lsattr"
+//config: default y
+//config: select PLATFORM_LINUX
+//config: help
+//config: lsattr lists the file attributes on a second extended file system.
+
+//applet:IF_LSATTR(APPLET(lsattr, BB_DIR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_LSATTR) += lsattr.o e2fs_lib.o
+
+//usage:#define lsattr_trivial_usage
+//usage: "[-Radlv] [FILE]..."
+//usage:#define lsattr_full_usage "\n\n"
+//usage: "List ext2 file attributes\n"
+//usage: "\n -R Recurse"
+//usage: "\n -a Don't hide entries starting with ."
+//usage: "\n -d List directory entries instead of contents"
+//usage: "\n -l List long flag names"
+//usage: "\n -v List version/generation number"
+
+#include "libbb.h"
+#include "e2fs_lib.h"
+
+enum {
+ OPT_RECUR = 0x1,
+ OPT_ALL = 0x2,
+ OPT_DIRS_OPT = 0x4,
+ OPT_PF_LONG = 0x8,
+ OPT_GENERATION = 0x10,
+};
static void list_attributes(const char *name)
{
unsigned long fsflags;
unsigned long generation;
- if (fgetflags(name, &fsflags) == -1)
+ if (fgetflags(name, &fsflags) != 0)
goto read_err;
- if (flags & OPT_GENERATION) {
- if (fgetversion(name, &generation) == -1)
+
+ if (option_mask32 & OPT_GENERATION) {
+ if (fgetversion(name, &generation) != 0)
goto read_err;
printf("%5lu ", generation);
}
- if (flags & OPT_PF_LONG) {
+ if (option_mask32 & OPT_PF_LONG) {
printf("%-28s ", name);
print_e2flags(stdout, fsflags, PFOPT_LONG);
bb_putchar('\n');
@@ -64,66 +65,58 @@ static void list_attributes(const char *name)
}
return;
-read_err:
+ read_err:
bb_perror_msg("reading %s", name);
}
-static int lsattr_dir_proc(const char *, struct dirent *, void *);
-
-static void lsattr_args(const char *name)
-{
- struct stat st;
-
- if (lstat(name, &st) == -1) {
- bb_perror_msg("stating %s", name);
- } else {
- if (S_ISDIR(st.st_mode) && !(flags & OPT_DIRS_OPT))
- iterate_on_dir(name, lsattr_dir_proc, NULL);
- else
- list_attributes(name);
- }
-}
-
-static int lsattr_dir_proc(const char *dir_name, struct dirent *de,
- void *private)
+static int FAST_FUNC lsattr_dir_proc(const char *dir_name,
+ struct dirent *de,
+ void *private UNUSED_PARAM)
{
struct stat st;
char *path;
path = concat_path_file(dir_name, de->d_name);
- if (lstat(path, &st) == -1)
- bb_perror_msg(path);
- else {
- if (de->d_name[0] != '.' || (flags & OPT_ALL)) {
- list_attributes(path);
- if (S_ISDIR(st.st_mode) && (flags & OPT_RECUR) &&
- (de->d_name[0] != '.' && (de->d_name[1] != '\0' ||
- (de->d_name[1] != '.' && de->d_name[2] != '\0')))) {
- printf("\n%s:\n", path);
- iterate_on_dir(path, lsattr_dir_proc, NULL);
- bb_putchar('\n');
- }
+ if (lstat(path, &st) != 0)
+ bb_perror_msg("stat %s", path);
+ else if (de->d_name[0] != '.' || (option_mask32 & OPT_ALL)) {
+ list_attributes(path);
+ if (S_ISDIR(st.st_mode) && (option_mask32 & OPT_RECUR)
+ && !DOT_OR_DOTDOT(de->d_name)
+ ) {
+ printf("\n%s:\n", path);
+ iterate_on_dir(path, lsattr_dir_proc, NULL);
+ bb_putchar('\n');
}
}
free(path);
-
return 0;
}
-int lsattr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int lsattr_main(int argc, char **argv)
+static void lsattr_args(const char *name)
{
- int i;
+ struct stat st;
- flags = getopt32(argv, "Radlv");
+ if (lstat(name, &st) == -1) {
+ bb_perror_msg("stat %s", name);
+ } else if (S_ISDIR(st.st_mode) && !(option_mask32 & OPT_DIRS_OPT)) {
+ iterate_on_dir(name, lsattr_dir_proc, NULL);
+ } else {
+ list_attributes(name);
+ }
+}
+
+int lsattr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int lsattr_main(int argc UNUSED_PARAM, char **argv)
+{
+ getopt32(argv, "Radlv");
+ argv += optind;
- if (optind > argc - 1)
- lsattr_args(".");
- else
- for (i = optind; i < argc; i++)
- lsattr_args(argv[i]);
+ if (!*argv)
+ *--argv = (char*)".";
+ do lsattr_args(*argv++); while (*argv);
return EXIT_SUCCESS;
}
diff --git a/release/src/router/busybox/e2fsprogs/mke2fs.c b/release/src/router/busybox/e2fsprogs/mke2fs.c
deleted file mode 100644
index c2c1836a2b..0000000000
--- a/release/src/router/busybox/e2fsprogs/mke2fs.c
+++ /dev/null
@@ -1,1370 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * mke2fs.c - Make a ext2fs filesystem.
- *
- * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- * 2003, 2004, 2005 by Theodore Ts'o.
- *
- * Licensed under GPLv2, see file LICENSE in this source tree.
- */
-
-//usage:#define mkfs_ext2_trivial_usage
-//usage: "[-Fn] "
-//usage: "[-c|-l filename] "
-//usage: "[-b BLK_SIZE] "
-//usage: "[-f fragment-size] [-g blocks-per-group] "
-//usage: "[-i INODE_RATIO] [-I INODE_SIZE] "
-//usage: "[-j] [-J journal-options] [-N number-of-inodes] "
-//usage: "[-m RESERVED_PERCENT] "
-//usage: "[-o creator-os] [-O feature[,...]] [-q] "
-//usage: "[r fs-revision-level] [-E extended-options] [-v] [-F] "
-//usage: "[-L LABEL] "
-//usage: "[-M last-mounted-directory] [-S] [-T filesystem-type] "
-//usage: "BLOCKDEV [KBYTES]"
-//usage:#define mkfs_ext2_full_usage "\n\n"
-//usage: " -b BLK_SIZE Block size, bytes"
-//usage: "\n -c Check device for bad blocks"
-//usage: "\n -E opts Set extended options"
-//usage: "\n -f size Fragment size in bytes"
-//usage: "\n -F Force"
-//usage: "\n -g N Number of blocks in a block group"
-//usage: "\n -i RATIO Max number of files is filesystem_size / RATIO"
-//usage: "\n -I BYTES Inode size (min 128)"
-//usage: "\n -j Create a journal (ext3)"
-//usage: "\n -J opts Set journal options (size/device)"
-//usage: "\n -l file Read bad blocks list from file"
-//usage: "\n -L LBL Volume label"
-//usage: "\n -m PERCENT Percent of blocks to reserve for admin"
-//usage: "\n -M dir Set last mounted directory"
-//usage: "\n -n Dry run"
-//usage: "\n -N N Number of inodes to create"
-//usage: "\n -o os Set the 'creator os' field"
-//usage: "\n -O features Dir_index/filetype/has_journal/journal_dev/sparse_super"
-//usage: "\n -q Quiet"
-//usage: "\n -r rev Set filesystem revision"
-//usage: "\n -S Write superblock and group descriptors only"
-//usage: "\n -T fs-type Set usage type (news/largefile/largefile4)"
-//usage: "\n -v Verbose"
-
-//usage:#define mkfs_ext3_trivial_usage NOUSAGE_STR
-//usage:#define mkfs_ext3_full_usage ""
-
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <time.h>
-#include <getopt.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <mntent.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-
-#include "e2fsbb.h"
-#include "ext2fs/ext2_fs.h"
-#include "e2fs_lib.h"
-#include "e2p/e2p.h"
-#include "ext2fs/ext2fs.h"
-#include "util.h"
-
-#define STRIDE_LENGTH 8
-
-#ifndef __sparc__
-#define ZAP_BOOTBLOCK
-#endif
-
-static const char * device_name;
-
-/* Command line options */
-static int cflag;
-static int quiet;
-static int super_only;
-static int force;
-static int noaction;
-static int journal_size;
-static int journal_flags;
-static const char *bad_blocks_filename;
-static __u32 fs_stride;
-
-static struct ext2_super_block param;
-static char *creator_os;
-static char *volume_label;
-static char *mount_dir;
-static char *journal_device = NULL;
-static int sync_kludge; /* Set using the MKE2FS_SYNC env. option */
-
-static int sys_page_size = 4096;
-static int linux_version_code = 0;
-
-static int int_log2(int arg)
-{
- int l = 0;
-
- arg >>= 1;
- while (arg) {
- l++;
- arg >>= 1;
- }
- return l;
-}
-
-static int int_log10(unsigned int arg)
-{
- int l;
-
- for (l = 0; arg; l++)
- arg = arg / 10;
- return l;
-}
-
-/*
- * This function sets the default parameters for a filesystem
- *
- * The type is specified by the user. The size is the maximum size
- * (in megabytes) for which a set of parameters applies, with a size
- * of zero meaning that it is the default parameter for the type.
- * Note that order is important in the table below.
- */
-#define DEF_MAX_BLOCKSIZE -1
-static const char default_str[] = "default";
-struct mke2fs_defaults {
- const char *type;
- int size;
- int blocksize;
- int inode_ratio;
-};
-
-static const struct mke2fs_defaults settings[] = {
- { default_str, 0, 4096, 8192 },
- { default_str, 512, 1024, 4096 },
- { default_str, 3, 1024, 8192 },
- { "journal", 0, 4096, 8192 },
- { "news", 0, 4096, 4096 },
- { "largefile", 0, 4096, 1024 * 1024 },
- { "largefile4", 0, 4096, 4096 * 1024 },
- { 0, 0, 0, 0},
-};
-
-static void set_fs_defaults(const char *fs_type,
- struct ext2_super_block *super,
- int blocksize, int sector_size,
- int *inode_ratio)
-{
- int megs;
- int ratio = 0;
- const struct mke2fs_defaults *p;
- int use_bsize = 1024;
-
- megs = super->s_blocks_count * (EXT2_BLOCK_SIZE(super) / 1024) / 1024;
- if (inode_ratio)
- ratio = *inode_ratio;
- if (!fs_type)
- fs_type = default_str;
- for (p = settings; p->type; p++) {
- if ((strcmp(p->type, fs_type) != 0) &&
- (strcmp(p->type, default_str) != 0))
- continue;
- if ((p->size != 0) && (megs > p->size))
- continue;
- if (ratio == 0)
- *inode_ratio = p->inode_ratio < blocksize ?
- blocksize : p->inode_ratio;
- use_bsize = p->blocksize;
- }
- if (blocksize <= 0) {
- if (use_bsize == DEF_MAX_BLOCKSIZE) {
- use_bsize = sys_page_size;
- if ((linux_version_code < (2*65536 + 6*256)) &&
- (use_bsize > 4096))
- use_bsize = 4096;
- }
- if (sector_size && use_bsize < sector_size)
- use_bsize = sector_size;
- if ((blocksize < 0) && (use_bsize < (-blocksize)))
- use_bsize = -blocksize;
- blocksize = use_bsize;
- super->s_blocks_count /= blocksize / 1024;
- }
- super->s_log_frag_size = super->s_log_block_size =
- int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
-}
-
-
-/*
- * Helper function for read_bb_file and test_disk
- */
-static void invalid_block(ext2_filsys fs EXT2FS_ATTR((unused)), blk_t blk)
-{
- bb_error_msg("Bad block %u out of range; ignored", blk);
-}
-
-/*
- * Busybox stuff
- */
-static void mke2fs_error_msg_and_die(int retval, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
-static void mke2fs_error_msg_and_die(int retval, const char *fmt, ...)
-{
- va_list ap;
-
- if (retval) {
- va_start(ap, fmt);
- fprintf(stderr, "\nCould not ");
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
- va_end(ap);
- exit(EXIT_FAILURE);
- }
-}
-
-static void mke2fs_verbose(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
-static void mke2fs_verbose(const char *fmt, ...)
-{
- va_list ap;
-
- if (!quiet) {
- va_start(ap, fmt);
- vfprintf(stdout, fmt, ap);
- fflush(stdout);
- va_end(ap);
- }
-}
-
-static void mke2fs_verbose_done(void)
-{
- mke2fs_verbose("done\n");
-}
-
-static void mke2fs_warning_msg(int retval, const char *fmt, ... ) __attribute__ ((format (printf, 2, 3)));
-static void mke2fs_warning_msg(int retval, const char *fmt, ... )
-{
- va_list ap;
-
- if (retval) {
- va_start(ap, fmt);
- fprintf(stderr, "\nWarning: ");
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
- va_end(ap);
- }
-}
-
-/*
- * Reads the bad blocks list from a file
- */
-static void read_bb_file(ext2_filsys fs, badblocks_list *bb_list,
- const char *bad_blocks_file)
-{
- FILE *f;
- errcode_t retval;
-
- f = xfopen_for_read(bad_blocks_file);
- retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block);
- fclose (f);
- mke2fs_error_msg_and_die(retval, "read bad blocks from list");
-}
-
-/*
- * Runs the badblocks program to test the disk
- */
-static void test_disk(ext2_filsys fs, badblocks_list *bb_list)
-{
- FILE *f;
- errcode_t retval;
- char buf[1024];
-
- sprintf(buf, "badblocks -b %d %s%s%s %d", fs->blocksize,
- quiet ? "" : "-s ", (cflag > 1) ? "-w " : "",
- fs->device_name, fs->super->s_blocks_count);
- mke2fs_verbose("Running command: %s\n", buf);
- f = popen(buf, "r");
- if (!f) {
- bb_perror_msg_and_die("can't run '%s'", buf);
- }
- retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block);
- pclose(f);
- mke2fs_error_msg_and_die(retval, "read bad blocks from program");
-}
-
-static void handle_bad_blocks(ext2_filsys fs, badblocks_list bb_list)
-{
- dgrp_t i;
- blk_t j;
- unsigned must_be_good;
- blk_t blk;
- badblocks_iterate bb_iter;
- errcode_t retval;
- blk_t group_block;
- int group;
- int group_bad;
-
- if (!bb_list)
- return;
-
- /*
- * The primary superblock and group descriptors *must* be
- * good; if not, abort.
- */
- must_be_good = fs->super->s_first_data_block + 1 + fs->desc_blocks;
- for (i = fs->super->s_first_data_block; i <= must_be_good; i++) {
- if (ext2fs_badblocks_list_test(bb_list, i)) {
- bb_error_msg_and_die(
- "Block %d in primary superblock/group descriptor area bad\n"
- "Blocks %d through %d must be good in order to build a filesystem\n"
- "Aborting ...", i, fs->super->s_first_data_block, must_be_good);
- }
- }
-
- /*
- * See if any of the bad blocks are showing up in the backup
- * superblocks and/or group descriptors. If so, issue a
- * warning and adjust the block counts appropriately.
- */
- group_block = fs->super->s_first_data_block +
- fs->super->s_blocks_per_group;
-
- for (i = 1; i < fs->group_desc_count; i++) {
- group_bad = 0;
- for (j=0; j < fs->desc_blocks+1; j++) {
- if (ext2fs_badblocks_list_test(bb_list,
- group_block + j)) {
- mke2fs_warning_msg(!group_bad,
- "the backup superblock/group descriptors at block %d contain\n"
- "bad blocks\n", group_block);
- group_bad++;
- group = ext2fs_group_of_blk(fs, group_block+j);
- fs->group_desc[group].bg_free_blocks_count++;
- fs->super->s_free_blocks_count++;
- }
- }
- group_block += fs->super->s_blocks_per_group;
- }
-
- /*
- * Mark all the bad blocks as used...
- */
- retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter);
- mke2fs_error_msg_and_die(retval, "mark bad blocks as used");
-
- while (ext2fs_badblocks_list_iterate(bb_iter, &blk))
- ext2fs_mark_block_bitmap(fs->block_map, blk);
- ext2fs_badblocks_list_iterate_end(bb_iter);
-}
-
-/*
- * These functions implement a generalized progress meter.
- */
-struct progress_struct {
- char format[20];
- char backup[80];
- __u32 max;
- int skip_progress;
-};
-
-static void progress_init(struct progress_struct *progress,
- const char *label,__u32 max)
-{
- int i;
-
- memset(progress, 0, sizeof(struct progress_struct));
- if (quiet)
- return;
-
- /*
- * Figure out how many digits we need
- */
- i = int_log10(max);
- sprintf(progress->format, "%%%dd/%%%dld", i, i);
- memset(progress->backup, '\b', sizeof(progress->backup)-1);
- progress->backup[sizeof(progress->backup)-1] = 0;
- if ((2*i)+1 < (int) sizeof(progress->backup))
- progress->backup[(2*i)+1] = 0;
- progress->max = max;
-
- progress->skip_progress = 0;
- if (getenv("MKE2FS_SKIP_PROGRESS"))
- progress->skip_progress++;
-
- fputs(label, stdout);
- fflush(stdout);
-}
-
-static void progress_update(struct progress_struct *progress, __u32 val)
-{
- if ((progress->format[0] == 0) || progress->skip_progress)
- return;
- printf(progress->format, val, progress->max);
- fputs(progress->backup, stdout);
-}
-
-static void progress_close(struct progress_struct *progress)
-{
- if (progress->format[0] == 0)
- return;
- printf("%-28s\n", "done");
-}
-
-
-/*
- * Helper function which zeros out _num_ blocks starting at _blk_. In
- * case of an error, the details of the error is returned via _ret_blk_
- * and _ret_count_ if they are non-NULL pointers. Returns 0 on
- * success, and an error code on an error.
- *
- * As a special case, if the first argument is NULL, then it will
- * attempt to free the static zeroizing buffer. (This is to keep
- * programs that check for memory leaks happy.)
- */
-static errcode_t zero_blocks(ext2_filsys fs, blk_t blk, int num,
- struct progress_struct *progress,
- blk_t *ret_blk, int *ret_count)
-{
- int j, count, next_update, next_update_incr;
- static char *buf;
- errcode_t retval;
-
- /* If fs is null, clean up the static buffer and return */
- if (!fs) {
- if (buf) {
- free(buf);
- buf = 0;
- }
- return 0;
- }
- /* Allocate the zeroizing buffer if necessary */
- if (!buf) {
- buf = xzalloc(fs->blocksize * STRIDE_LENGTH);
- }
- /* OK, do the write loop */
- next_update = 0;
- next_update_incr = num / 100;
- if (next_update_incr < 1)
- next_update_incr = 1;
- for (j=0; j < num; j += STRIDE_LENGTH, blk += STRIDE_LENGTH) {
- count = num - j;
- if (count > STRIDE_LENGTH)
- count = STRIDE_LENGTH;
- retval = io_channel_write_blk(fs->io, blk, count, buf);
- if (retval) {
- if (ret_count)
- *ret_count = count;
- if (ret_blk)
- *ret_blk = blk;
- return retval;
- }
- if (progress && j > next_update) {
- next_update += num / 100;
- progress_update(progress, blk);
- }
- }
- return 0;
-}
-
-static void write_inode_tables(ext2_filsys fs)
-{
- errcode_t retval;
- blk_t blk;
- dgrp_t i;
- int num;
- struct progress_struct progress;
-
- if (quiet)
- memset(&progress, 0, sizeof(progress));
- else
- progress_init(&progress, "Writing inode tables: ",
- fs->group_desc_count);
-
- for (i = 0; i < fs->group_desc_count; i++) {
- progress_update(&progress, i);
-
- blk = fs->group_desc[i].bg_inode_table;
- num = fs->inode_blocks_per_group;
-
- retval = zero_blocks(fs, blk, num, 0, &blk, &num);
- mke2fs_error_msg_and_die(retval,
- "write %d blocks in inode table starting at %d.",
- num, blk);
- if (sync_kludge) {
- if (sync_kludge == 1)
- sync();
- else if ((i % sync_kludge) == 0)
- sync();
- }
- }
- zero_blocks(0, 0, 0, 0, 0, 0);
- progress_close(&progress);
-}
-
-static void create_root_dir(ext2_filsys fs)
-{
- errcode_t retval;
- struct ext2_inode inode;
-
- retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, 0);
- mke2fs_error_msg_and_die(retval, "create root dir");
- if (geteuid()) {
- retval = ext2fs_read_inode(fs, EXT2_ROOT_INO, &inode);
- mke2fs_error_msg_and_die(retval, "read root inode");
- inode.i_uid = getuid();
- if (inode.i_uid)
- inode.i_gid = getgid();
- retval = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
- mke2fs_error_msg_and_die(retval, "set root inode ownership");
- }
-}
-
-static void create_lost_and_found(ext2_filsys fs)
-{
- errcode_t retval;
- ext2_ino_t ino;
- const char *name = "lost+found";
- int i = 1;
- const char *msg = "create";
- int lpf_size = 0;
-
- fs->umask = 077;
- retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, 0, name);
- if (retval) {
- goto CREATE_LOST_AND_FOUND_ERROR;
- }
-
- retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name, strlen(name), 0, &ino);
- if (retval) {
- msg = "lookup";
- goto CREATE_LOST_AND_FOUND_ERROR;
- }
-
- for (; i < EXT2_NDIR_BLOCKS; i++) {
- if ((lpf_size += fs->blocksize) >= 16*1024)
- break;
- retval = ext2fs_expand_dir(fs, ino);
- msg = "expand";
-CREATE_LOST_AND_FOUND_ERROR:
- mke2fs_error_msg_and_die(retval, "%s %s", msg, name);
- }
-}
-
-static void create_bad_block_inode(ext2_filsys fs, badblocks_list bb_list)
-{
- errcode_t retval;
-
- ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_BAD_INO);
- fs->group_desc[0].bg_free_inodes_count--;
- fs->super->s_free_inodes_count--;
- retval = ext2fs_update_bb_inode(fs, bb_list);
- mke2fs_error_msg_and_die(retval, "set bad block inode");
-}
-
-static void reserve_inodes(ext2_filsys fs)
-{
- ext2_ino_t i;
- int group;
-
- for (i = EXT2_ROOT_INO + 1; i < EXT2_FIRST_INODE(fs->super); i++) {
- ext2fs_mark_inode_bitmap(fs->inode_map, i);
- group = ext2fs_group_of_ino(fs, i);
- fs->group_desc[group].bg_free_inodes_count--;
- fs->super->s_free_inodes_count--;
- }
- ext2fs_mark_ib_dirty(fs);
-}
-
-#define BSD_DISKMAGIC (0x82564557UL) /* The disk magic number */
-#define BSD_MAGICDISK (0x57455682UL) /* The disk magic number reversed */
-#define BSD_LABEL_OFFSET 64
-
-static void zap_sector(ext2_filsys fs, int sect, int nsect)
-{
- char *buf;
- const char *fmt = "could not %s %d";
- int retval;
- unsigned int *magic;
-
- buf = xmalloc(512*nsect);
-
- if (sect == 0) {
- /* Check for a BSD disklabel, and don't erase it if so */
- retval = io_channel_read_blk(fs->io, 0, -512, buf);
- if (retval)
- mke2fs_warning_msg(retval, fmt, "read block", 0);
- else {
- magic = (unsigned int *) (buf + BSD_LABEL_OFFSET);
- if ((*magic == BSD_DISKMAGIC) ||
- (*magic == BSD_MAGICDISK))
- return;
- }
- }
-
- memset(buf, 0, 512*nsect);
- io_channel_set_blksize(fs->io, 512);
- retval = io_channel_write_blk(fs->io, sect, -512*nsect, buf);
- io_channel_set_blksize(fs->io, fs->blocksize);
- free(buf);
- mke2fs_warning_msg(retval, fmt, "erase sector", sect);
-}
-
-static void create_journal_dev(ext2_filsys fs)
-{
- struct progress_struct progress;
- errcode_t retval;
- char *buf;
- const char *fmt = "%s journal superblock";
- blk_t blk;
- int count;
-
- retval = ext2fs_create_journal_superblock(fs,
- fs->super->s_blocks_count, 0, &buf);
- mke2fs_error_msg_and_die(retval, fmt, "init");
- if (quiet)
- memset(&progress, 0, sizeof(progress));
- else
- progress_init(&progress, "Zeroing journal device: ",
- fs->super->s_blocks_count);
-
- retval = zero_blocks(fs, 0, fs->super->s_blocks_count,
- &progress, &blk, &count);
- mke2fs_error_msg_and_die(retval, "zero journal device (block %u, count %d)",
- blk, count);
- zero_blocks(0, 0, 0, 0, 0, 0);
-
- retval = io_channel_write_blk(fs->io,
- fs->super->s_first_data_block+1,
- 1, buf);
- mke2fs_error_msg_and_die(retval, fmt, "write");
- progress_close(&progress);
-}
-
-static void show_stats(ext2_filsys fs)
-{
- struct ext2_super_block *s = fs->super;
- char *os;
- blk_t group_block;
- dgrp_t i;
- int need, col_left;
-
- mke2fs_warning_msg((param.s_blocks_count != s->s_blocks_count),
- "%d blocks unused\n", param.s_blocks_count - s->s_blocks_count);
- os = e2p_os2string(fs->super->s_creator_os);
- printf( "Filesystem label=%.*s\n"
- "OS type: %s\n"
- "Block size=%u (log=%u)\n"
- "Fragment size=%u (log=%u)\n"
- "%u inodes, %u blocks\n"
- "%u blocks (%2.2f%%) reserved for the super user\n"
- "First data block=%u\n",
- (int) sizeof(s->s_volume_name),
- s->s_volume_name,
- os,
- fs->blocksize, s->s_log_block_size,
- fs->fragsize, s->s_log_frag_size,
- s->s_inodes_count, s->s_blocks_count,
- s->s_r_blocks_count, 100.0 * s->s_r_blocks_count / s->s_blocks_count,
- s->s_first_data_block);
- free(os);
- if (s->s_reserved_gdt_blocks) {
- printf("Maximum filesystem blocks=%lu\n",
- (s->s_reserved_gdt_blocks + fs->desc_blocks) *
- (fs->blocksize / sizeof(struct ext2_group_desc)) *
- s->s_blocks_per_group);
- }
- printf( "%u block group%s\n"
- "%u blocks per group, %u fragments per group\n"
- "%u inodes per group\n",
- fs->group_desc_count, (fs->group_desc_count > 1) ? "s" : "",
- s->s_blocks_per_group, s->s_frags_per_group,
- s->s_inodes_per_group);
- if (fs->group_desc_count == 1) {
- bb_putchar('\n');
- return;
- }
-
- printf("Superblock backups stored on blocks: ");
- group_block = s->s_first_data_block;
- col_left = 0;
- for (i = 1; i < fs->group_desc_count; i++) {
- group_block += s->s_blocks_per_group;
- if (!ext2fs_bg_has_super(fs, i))
- continue;
- if (i != 1)
- printf(", ");
- need = int_log10(group_block) + 2;
- if (need > col_left) {
- printf("\n\t");
- col_left = 72;
- }
- col_left -= need;
- printf("%u", group_block);
- }
- puts("\n");
-}
-
-/*
- * Set the S_CREATOR_OS field. Return true if OS is known,
- * otherwise, 0.
- */
-static int set_os(struct ext2_super_block *sb, char *os)
-{
- if (isdigit (*os)) {
- sb->s_creator_os = atoi(os);
- return 1;
- }
-
- if ((sb->s_creator_os = e2p_string2os(os)) >= 0) {
- return 1;
- } else if (!strcasecmp("GNU", os)) {
- sb->s_creator_os = EXT2_OS_HURD;
- return 1;
- }
- return 0;
-}
-
-static void parse_extended_opts(struct ext2_super_block *sb_param,
- const char *opts)
-{
- char *buf, *token, *next, *p, *arg;
- int r_usage = 0;
-
- buf = xstrdup(opts);
- for (token = buf; token && *token; token = next) {
- p = strchr(token, ',');
- next = 0;
- if (p) {
- *p = 0;
- next = p+1;
- }
- arg = strchr(token, '=');
- if (arg) {
- *arg = 0;
- arg++;
- }
- if (strcmp(token, "stride") == 0) {
- if (!arg) {
- r_usage++;
- continue;
- }
- fs_stride = strtoul(arg, &p, 0);
- if (*p || (fs_stride == 0)) {
- bb_error_msg("Invalid stride parameter: %s", arg);
- r_usage++;
- continue;
- }
- } else if (!strcmp(token, "resize")) {
- unsigned long resize, bpg, rsv_groups;
- unsigned long group_desc_count, desc_blocks;
- unsigned int gdpb, blocksize;
- int rsv_gdb;
-
- if (!arg) {
- r_usage++;
- continue;
- }
-
- resize = parse_num_blocks(arg,
- sb_param->s_log_block_size);
-
- if (resize == 0) {
- bb_error_msg("Invalid resize parameter: %s", arg);
- r_usage++;
- continue;
- }
- if (resize <= sb_param->s_blocks_count) {
- bb_error_msg("The resize maximum must be greater "
- "than the filesystem size");
- r_usage++;
- continue;
- }
-
- blocksize = EXT2_BLOCK_SIZE(sb_param);
- bpg = sb_param->s_blocks_per_group;
- if (!bpg)
- bpg = blocksize * 8;
- gdpb = blocksize / sizeof(struct ext2_group_desc);
- group_desc_count = (sb_param->s_blocks_count +
- bpg - 1) / bpg;
- desc_blocks = (group_desc_count +
- gdpb - 1) / gdpb;
- rsv_groups = (resize + bpg - 1) / bpg;
- rsv_gdb = (rsv_groups + gdpb - 1) / gdpb -
- desc_blocks;
- if (rsv_gdb > EXT2_ADDR_PER_BLOCK(sb_param))
- rsv_gdb = EXT2_ADDR_PER_BLOCK(sb_param);
-
- if (rsv_gdb > 0) {
- sb_param->s_feature_compat |=
- EXT2_FEATURE_COMPAT_RESIZE_INO;
-
- sb_param->s_reserved_gdt_blocks = rsv_gdb;
- }
- } else
- r_usage++;
- }
- if (r_usage) {
- bb_error_msg_and_die(
- "\nBad options specified.\n\n"
- "Extended options are separated by commas, "
- "and may take an argument which\n"
- "\tis set off by an equals ('=') sign.\n\n"
- "Valid extended options are:\n"
- "\tstride=<stride length in blocks>\n"
- "\tresize=<resize maximum size in blocks>\n");
- }
-}
-
-static __u32 ok_features[3] = {
- EXT3_FEATURE_COMPAT_HAS_JOURNAL |
- EXT2_FEATURE_COMPAT_RESIZE_INO |
- EXT2_FEATURE_COMPAT_DIR_INDEX, /* Compat */
- EXT2_FEATURE_INCOMPAT_FILETYPE| /* Incompat */
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|
- EXT2_FEATURE_INCOMPAT_META_BG,
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER /* R/O compat */
-};
-
-static int PRS(int argc, char **argv)
-{
- int c;
- int size;
- char * tmp;
- int blocksize = 0;
- int inode_ratio = 0;
- int inode_size = 0;
- int reserved_ratio = 5;
- int sector_size = 0;
- int show_version_only = 0;
- ext2_ino_t num_inodes = 0;
- errcode_t retval;
- char * extended_opts = NULL;
- const char * fs_type = NULL;
- blk_t dev_size;
- long sysval;
-
- /* Update our PATH to include /sbin */
- e2fs_set_sbin_path();
-
- tmp = getenv("MKE2FS_SYNC");
- if (tmp)
- sync_kludge = atoi(tmp);
-
- /* Determine the system page size if possible */
-#if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE))
-#define _SC_PAGESIZE _SC_PAGE_SIZE
-#endif
-#ifdef _SC_PAGESIZE
- sysval = sysconf(_SC_PAGESIZE);
- if (sysval > 0)
- sys_page_size = sysval;
-#endif /* _SC_PAGESIZE */
-
- setbuf(stdout, NULL);
- setbuf(stderr, NULL);
- memset(&param, 0, sizeof(struct ext2_super_block));
- param.s_rev_level = 1; /* Create revision 1 filesystems now */
- param.s_feature_incompat |= EXT2_FEATURE_INCOMPAT_FILETYPE;
- param.s_feature_ro_compat |= EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
-
-#ifdef __linux__
- linux_version_code = get_linux_version_code();
- if (linux_version_code && linux_version_code < KERNEL_VERSION(2,2,0)) {
- param.s_rev_level = 0;
- param.s_feature_incompat = 0;
- param.s_feature_compat = 0;
- param.s_feature_ro_compat = 0;
- }
-#endif
-
- /* If called as mkfs.ext3, create a journal inode */
- if (last_char_is(applet_name, '3'))
- journal_size = -1;
-
- while ((c = getopt (argc, argv,
- "b:cE:f:g:i:jl:m:no:qr:R:s:tvI:J:ST:FL:M:N:O:V")) != EOF) {
- switch (c) {
- case 'b':
- blocksize = xatou_range(optarg, EXT2_MIN_BLOCK_SIZE, EXT2_MAX_BLOCK_SIZE);
- mke2fs_warning_msg((blocksize > 4096),
- "blocksize %d not usable on most systems",
- blocksize);
- param.s_log_block_size =
- int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
- break;
- case 'c': /* Check for bad blocks */
- case 't': /* deprecated */
- cflag++;
- break;
- case 'f':
- size = xatou_range(optarg, EXT2_MIN_BLOCK_SIZE, EXT2_MAX_BLOCK_SIZE);
- param.s_log_frag_size =
- int_log2(size >> EXT2_MIN_BLOCK_LOG_SIZE);
- mke2fs_warning_msg(1, "fragments not supported. Ignoring -f option");
- break;
- case 'g':
- param.s_blocks_per_group = xatou32(optarg);
- if ((param.s_blocks_per_group % 8) != 0) {
- bb_error_msg_and_die("blocks per group must be multiple of 8");
- }
- break;
- case 'i':
- /* Huh? is "* 1024" correct? */
- inode_ratio = xatou_range(optarg, EXT2_MIN_BLOCK_SIZE, EXT2_MAX_BLOCK_SIZE * 1024);
- break;
- case 'J':
- parse_journal_opts(&journal_device, &journal_flags, &journal_size, optarg);
- break;
- case 'j':
- param.s_feature_compat |=
- EXT3_FEATURE_COMPAT_HAS_JOURNAL;
- if (!journal_size)
- journal_size = -1;
- break;
- case 'l':
- bad_blocks_filename = optarg;
- break;
- case 'm':
- reserved_ratio = xatou_range(optarg, 0, 50);
- break;
- case 'n':
- noaction++;
- break;
- case 'o':
- creator_os = optarg;
- break;
- case 'r':
- param.s_rev_level = xatoi_positive(optarg);
- if (param.s_rev_level == EXT2_GOOD_OLD_REV) {
- param.s_feature_incompat = 0;
- param.s_feature_compat = 0;
- param.s_feature_ro_compat = 0;
- }
- break;
- case 's': /* deprecated */
- if (xatou(optarg))
- param.s_feature_ro_compat |=
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
- else
- param.s_feature_ro_compat &=
- ~EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
- break;
-#ifdef EXT2_DYNAMIC_REV
- case 'I':
- inode_size = xatoi_positive(optarg);
- break;
-#endif
- case 'N':
- num_inodes = xatoi_positive(optarg);
- break;
- case 'v':
- quiet = 0;
- break;
- case 'q':
- quiet = 1;
- break;
- case 'F':
- force = 1;
- break;
- case 'L':
- volume_label = optarg;
- break;
- case 'M':
- mount_dir = optarg;
- break;
- case 'O':
- if (!strcmp(optarg, "none")) {
- param.s_feature_compat = 0;
- param.s_feature_incompat = 0;
- param.s_feature_ro_compat = 0;
- break;
- }
- if (e2p_edit_feature(optarg,
- &param.s_feature_compat,
- ok_features)) {
- bb_error_msg_and_die("Invalid filesystem option set: %s", optarg);
- }
- break;
- case 'E':
- case 'R':
- extended_opts = optarg;
- break;
- case 'S':
- super_only = 1;
- break;
- case 'T':
- fs_type = optarg;
- break;
- case 'V':
- /* Print version number and exit */
- show_version_only = 1;
- quiet = 0;
- break;
- default:
- bb_show_usage();
- }
- }
- if ((optind == argc) /*&& !show_version_only*/)
- bb_show_usage();
- device_name = argv[optind++];
-
- mke2fs_verbose("mke2fs %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE);
-
- if (show_version_only) {
- return 0;
- }
-
- /*
- * If there's no blocksize specified and there is a journal
- * device, use it to figure out the blocksize
- */
- if (blocksize <= 0 && journal_device) {
- ext2_filsys jfs;
- io_manager io_ptr;
-
-#ifdef CONFIG_TESTIO_DEBUG
- io_ptr = test_io_manager;
- test_io_backing_manager = unix_io_manager;
-#else
- io_ptr = unix_io_manager;
-#endif
- retval = ext2fs_open(journal_device,
- EXT2_FLAG_JOURNAL_DEV_OK, 0,
- 0, io_ptr, &jfs);
- mke2fs_error_msg_and_die(retval, "open journal device %s", journal_device);
- if ((blocksize < 0) && (jfs->blocksize < (unsigned) (-blocksize))) {
- bb_error_msg_and_die(
- "Journal dev blocksize (%d) smaller than "
- "minimum blocksize %d\n", jfs->blocksize,
- -blocksize);
- }
- blocksize = jfs->blocksize;
- param.s_log_block_size =
- int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
- ext2fs_close(jfs);
- }
-
- if (blocksize > sys_page_size) {
- mke2fs_warning_msg(1, "%d-byte blocks too big for system (max %d)",
- blocksize, sys_page_size);
- if (!force) {
- proceed_question();
- }
- bb_error_msg("Forced to continue");
- }
- mke2fs_warning_msg(((blocksize > 4096) &&
- (param.s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)),
- "some 2.4 kernels do not support "
- "blocksizes greater than 4096 using ext3.\n"
- "Use -b 4096 if this is an issue for you\n");
-
- if (optind < argc) {
- param.s_blocks_count = parse_num_blocks(argv[optind++],
- param.s_log_block_size);
- mke2fs_error_msg_and_die(!param.s_blocks_count, "invalid blocks count - %s", argv[optind - 1]);
- }
- if (optind < argc)
- bb_show_usage();
-
- if (param.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
- if (!fs_type)
- fs_type = "journal";
- reserved_ratio = 0;
- param.s_feature_incompat = EXT3_FEATURE_INCOMPAT_JOURNAL_DEV;
- param.s_feature_compat = 0;
- param.s_feature_ro_compat = 0;
- }
- if (param.s_rev_level == EXT2_GOOD_OLD_REV &&
- (param.s_feature_compat || param.s_feature_ro_compat ||
- param.s_feature_incompat))
- param.s_rev_level = 1; /* Create a revision 1 filesystem */
-
- check_plausibility(device_name , force);
- check_mount(device_name, force, "filesystem");
-
- param.s_log_frag_size = param.s_log_block_size;
-
- if (noaction && param.s_blocks_count) {
- dev_size = param.s_blocks_count;
- retval = 0;
- } else {
- retry:
- retval = ext2fs_get_device_size(device_name,
- EXT2_BLOCK_SIZE(&param),
- &dev_size);
- if ((retval == EFBIG) &&
- (blocksize == 0) &&
- (param.s_log_block_size == 0)) {
- param.s_log_block_size = 2;
- blocksize = 4096;
- goto retry;
- }
- }
-
- mke2fs_error_msg_and_die((retval && (retval != EXT2_ET_UNIMPLEMENTED)),"determine filesystem size");
-
- if (!param.s_blocks_count) {
- if (retval == EXT2_ET_UNIMPLEMENTED) {
- mke2fs_error_msg_and_die(1,
- "determine device size; you "
- "must specify\nthe size of the "
- "filesystem");
- } else {
- if (dev_size == 0) {
- bb_error_msg_and_die(
- "Device size reported to be zero. "
- "Invalid partition specified, or\n\t"
- "partition table wasn't reread "
- "after running fdisk, due to\n\t"
- "a modified partition being busy "
- "and in use. You may need to reboot\n\t"
- "to re-read your partition table.\n"
- );
- }
- param.s_blocks_count = dev_size;
- if (sys_page_size > EXT2_BLOCK_SIZE(&param))
- param.s_blocks_count &= ~((sys_page_size /
- EXT2_BLOCK_SIZE(&param))-1);
- }
-
- } else if (!force && (param.s_blocks_count > dev_size)) {
- bb_error_msg("Filesystem larger than apparent device size");
- proceed_question();
- }
-
- /*
- * If the user asked for HAS_JOURNAL, then make sure a journal
- * gets created.
- */
- if ((param.s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
- !journal_size)
- journal_size = -1;
-
- /* Set first meta blockgroup via an environment variable */
- /* (this is mostly for debugging purposes) */
- if ((param.s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) &&
- ((tmp = getenv("MKE2FS_FIRST_META_BG"))))
- param.s_first_meta_bg = atoi(tmp);
-
- /* Get the hardware sector size, if available */
- retval = ext2fs_get_device_sectsize(device_name, &sector_size);
- mke2fs_error_msg_and_die(retval, "determine hardware sector size");
-
- if ((tmp = getenv("MKE2FS_DEVICE_SECTSIZE")) != NULL)
- sector_size = atoi(tmp);
-
- set_fs_defaults(fs_type, &param, blocksize, sector_size, &inode_ratio);
- blocksize = EXT2_BLOCK_SIZE(&param);
-
- if (extended_opts)
- parse_extended_opts(&param, extended_opts);
-
- /* Since sparse_super is the default, we would only have a problem
- * here if it was explicitly disabled.
- */
- if ((param.s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INO) &&
- !(param.s_feature_ro_compat&EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
- bb_error_msg_and_die("reserved online resize blocks not supported "
- "on non-sparse filesystem");
- }
-
- if (param.s_blocks_per_group) {
- if (param.s_blocks_per_group < 256 ||
- param.s_blocks_per_group > 8 * (unsigned) blocksize) {
- bb_error_msg_and_die("blocks per group count out of range");
- }
- }
-
- if (!force && param.s_blocks_count >= (1 << 31)) {
- bb_error_msg_and_die("Filesystem too large. No more than 2**31-1 blocks\n"
- "\t (8TB using a blocksize of 4k) are currently supported.");
- }
-
- if (inode_size) {
- if (inode_size < EXT2_GOOD_OLD_INODE_SIZE ||
- inode_size > EXT2_BLOCK_SIZE(&param) ||
- inode_size & (inode_size - 1)) {
- bb_error_msg_and_die("invalid inode size %d (min %d/max %d)",
- inode_size, EXT2_GOOD_OLD_INODE_SIZE,
- blocksize);
- }
- mke2fs_warning_msg((inode_size != EXT2_GOOD_OLD_INODE_SIZE),
- "%d-byte inodes not usable on most systems",
- inode_size);
- param.s_inode_size = inode_size;
- }
-
- /*
- * Calculate number of inodes based on the inode ratio
- */
- param.s_inodes_count = num_inodes ? num_inodes :
- ((__u64) param.s_blocks_count * blocksize)
- / inode_ratio;
-
- /*
- * Calculate number of blocks to reserve
- */
- param.s_r_blocks_count = (param.s_blocks_count * reserved_ratio) / 100;
- return 1;
-}
-
-static void mke2fs_clean_up(void)
-{
- if (ENABLE_FEATURE_CLEAN_UP && journal_device) free(journal_device);
-}
-
-int mkfs_ext2_main (int argc, char **argv);
-int mkfs_ext2_main (int argc, char **argv)
-{
- errcode_t retval;
- ext2_filsys fs;
- badblocks_list bb_list = 0;
- unsigned int i;
- int val;
- io_manager io_ptr;
-
- if (ENABLE_FEATURE_CLEAN_UP)
- atexit(mke2fs_clean_up);
- if (!PRS(argc, argv))
- return 0;
-
-#ifdef CONFIG_TESTIO_DEBUG
- io_ptr = test_io_manager;
- test_io_backing_manager = unix_io_manager;
-#else
- io_ptr = unix_io_manager;
-#endif
-
- /*
- * Initialize the superblock....
- */
- retval = ext2fs_initialize(device_name, 0, &param,
- io_ptr, &fs);
- mke2fs_error_msg_and_die(retval, "set up superblock");
-
- /*
- * Wipe out the old on-disk superblock
- */
- if (!noaction)
- zap_sector(fs, 2, 6);
-
- /*
- * Generate a UUID for it...
- */
- generate_uuid(fs->super->s_uuid);
-
- /*
- * Initialize the directory index variables
- */
- fs->super->s_def_hash_version = EXT2_HASH_TEA;
- generate_uuid((uint8_t *) fs->super->s_hash_seed);
-
- /*
- * Add "jitter" to the superblock's check interval so that we
- * don't check all the filesystems at the same time. We use a
- * kludgy hack of using the UUID to derive a random jitter value.
- */
- for (i = 0, val = 0; i < sizeof(fs->super->s_uuid); i++)
- val += fs->super->s_uuid[i];
- fs->super->s_max_mnt_count += val % EXT2_DFL_MAX_MNT_COUNT;
-
- /*
- * Override the creator OS, if applicable
- */
- if (creator_os && !set_os(fs->super, creator_os)) {
- bb_error_msg_and_die("unknown os - %s", creator_os);
- }
-
- /*
- * For the Hurd, we will turn off filetype since it doesn't
- * support it.
- */
- if (fs->super->s_creator_os == EXT2_OS_HURD)
- fs->super->s_feature_incompat &=
- ~EXT2_FEATURE_INCOMPAT_FILETYPE;
-
- /*
- * Set the volume label...
- */
- if (volume_label) {
- snprintf(fs->super->s_volume_name, sizeof(fs->super->s_volume_name), "%s", volume_label);
- }
-
- /*
- * Set the last mount directory
- */
- if (mount_dir) {
- snprintf(fs->super->s_last_mounted, sizeof(fs->super->s_last_mounted), "%s", mount_dir);
- }
-
- if (!quiet || noaction)
- show_stats(fs);
-
- if (noaction)
- return 0;
-
- if (fs->super->s_feature_incompat &
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
- create_journal_dev(fs);
- return (ext2fs_close(fs) ? 1 : 0);
- }
-
- if (bad_blocks_filename)
- read_bb_file(fs, &bb_list, bad_blocks_filename);
- if (cflag)
- test_disk(fs, &bb_list);
-
- handle_bad_blocks(fs, bb_list);
- fs->stride = fs_stride;
- retval = ext2fs_allocate_tables(fs);
- mke2fs_error_msg_and_die(retval, "allocate filesystem tables");
- if (super_only) {
- fs->super->s_state |= EXT2_ERROR_FS;
- fs->flags &= ~(EXT2_FLAG_IB_DIRTY|EXT2_FLAG_BB_DIRTY);
- } else {
- /* rsv must be a power of two (64kB is MD RAID sb alignment) */
- unsigned int rsv = 65536 / fs->blocksize;
- unsigned long blocks = fs->super->s_blocks_count;
- unsigned long start;
- blk_t ret_blk;
-
-#ifdef ZAP_BOOTBLOCK
- zap_sector(fs, 0, 2);
-#endif
-
- /*
- * Wipe out any old MD RAID (or other) metadata at the end
- * of the device. This will also verify that the device is
- * as large as we think. Be careful with very small devices.
- */
- start = (blocks & ~(rsv - 1));
- if (start > rsv)
- start -= rsv;
- if (start > 0)
- retval = zero_blocks(fs, start, blocks - start,
- NULL, &ret_blk, NULL);
-
- mke2fs_warning_msg(retval, "can't zero block %u at end of filesystem", ret_blk);
- write_inode_tables(fs);
- create_root_dir(fs);
- create_lost_and_found(fs);
- reserve_inodes(fs);
- create_bad_block_inode(fs, bb_list);
- if (fs->super->s_feature_compat &
- EXT2_FEATURE_COMPAT_RESIZE_INO) {
- retval = ext2fs_create_resize_inode(fs);
- mke2fs_error_msg_and_die(retval, "reserve blocks for online resize");
- }
- }
-
- if (journal_device) {
- make_journal_device(journal_device, fs, quiet, force);
- } else if (journal_size) {
- make_journal_blocks(fs, journal_size, journal_flags, quiet);
- }
-
- mke2fs_verbose("Writing superblocks and filesystem accounting information: ");
- retval = ext2fs_flush(fs);
- mke2fs_warning_msg(retval, "had trouble writing out superblocks");
- mke2fs_verbose_done();
- if (!quiet && !getenv("MKE2FS_SKIP_CHECK_MSG"))
- print_check_message(fs);
- val = ext2fs_close(fs);
- return (retval || val) ? 1 : 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/Config.src b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/Config.src
deleted file mode 100644
index a113378fb4..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/Config.src
+++ /dev/null
@@ -1,64 +0,0 @@
-#
-# For a description of the syntax of this configuration file,
-# see scripts/kbuild/config-language.txt.
-#
-
-menu "Linux Ext2 FS Progs"
-
-INSERT
-
-config CHATTR
- bool "chattr"
- default n
- help
- chattr changes the file attributes on a second extended file system.
-
-config E2FSCK
- bool "e2fsck"
- default n
- select VOLUMEID
- help
- e2fsck is used to check Linux second extended file systems (ext2fs).
- e2fsck also supports ext2 filesystems countaining a journal (ext3).
- The normal compat symlinks 'fsck.ext2' and 'fsck.ext3' are also
- provided.
-
-config FSCK
- bool "fsck"
- default n
- help
- fsck is used to check and optionally repair one or more filesystems.
- In actuality, fsck is simply a front-end for the various file system
- checkers (fsck.fstype) available under Linux.
-
-config LSATTR
- bool "lsattr"
- default n
- help
- lsattr lists the file attributes on a second extended file system.
-
-config MKE2FS
- bool "mke2fs"
- default n
- select VOLUMEID
- help
- mke2fs is used to create an ext2/ext3 filesystem. The normal compat
- symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided.
-
-config TUNE2FS
- bool "tune2fs"
- default n
- select VOLUMEID
- help
- tune2fs allows the system administrator to adjust various tunable
- filesystem parameters on Linux ext2/ext3 filesystems.
-
-config E2LABEL
- bool "e2label"
- default n
- depends on TUNE2FS
- help
- e2label will display or change the filesystem label on the ext2
- filesystem located on device.
-
-endmenu
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/Kbuild.src b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/Kbuild.src
deleted file mode 100644
index 8df2b17504..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/Kbuild.src
+++ /dev/null
@@ -1,18 +0,0 @@
-# Makefile for busybox
-#
-# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
-#
-# Licensed under GPLv2, see file LICENSE in this source tree.
-
-lib-y:=
-
-INSERT
-
-lib-$(CONFIG_CHATTR) += chattr.o e2fs_lib.o
-lib-$(CONFIG_E2FSCK) += e2fsck.o util.o e2fs_lib.o
-lib-$(CONFIG_FSCK) += fsck.o
-lib-$(CONFIG_LSATTR) += lsattr.o e2fs_lib.o
-lib-$(CONFIG_MKE2FS) += mke2fs.o util.o e2fs_lib.o
-lib-$(CONFIG_TUNE2FS) += tune2fs.o util.o e2fs_lib.o
-
-CFLAGS += -include $(srctree)/e2fsprogs/e2fsbb.h
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/README b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/README
deleted file mode 100644
index fac0901931..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/README
+++ /dev/null
@@ -1,3 +0,0 @@
-This is a pretty straight rip from the e2fsprogs pkg.
-
-See README's in subdirs for specific info.
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/Kbuild.src b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/Kbuild.src
deleted file mode 100644
index 02b4d24961..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/Kbuild.src
+++ /dev/null
@@ -1,26 +0,0 @@
-# Makefile for busybox
-#
-# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
-#
-# Licensed under GPLv2, see file LICENSE in this source tree.
-
-NEEDED-$(CONFIG_E2FSCK) = y
-NEEDED-$(CONFIG_FSCK) = y
-NEEDED-$(CONFIG_MKE2FS) = y
-NEEDED-$(CONFIG_TUNE2FS) = y
-
-lib-y:=
-
-INSERT
-
-lib-$(NEEDED-y) += cache.o dev.o devname.o devno.o blkid_getsize.o \
- probe.o read.o resolve.o save.o tag.o list.o
-
-CFLAGS_dev.o := -include $(srctree)/include/busybox.h
-CFLAGS_devname.o := -include $(srctree)/include/busybox.h
-CFLAGS_devno.o := -include $(srctree)/include/busybox.h
-CFLAGS_blkid_getsize.o := -include $(srctree)/include/busybox.h
-CFLAGS_probe.o := -include $(srctree)/include/busybox.h
-CFLAGS_save.o := -include $(srctree)/include/busybox.h
-CFLAGS_tag.o := -include $(srctree)/include/busybox.h
-CFLAGS_list.o := -include $(srctree)/include/busybox.h
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/blkid.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/blkid.h
deleted file mode 100644
index 9a3c2afdbd..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/blkid.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * blkid.h - Interface for libblkid, a library to identify block devices
- *
- * Copyright (C) 2001 Andreas Dilger
- * Copyright (C) 2003 Theodore Ts'o
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-#ifndef BLKID_BLKID_H
-#define BLKID_BLKID_H 1
-
-#include <sys/types.h>
-#include <linux/types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define BLKID_VERSION "1.0.0"
-#define BLKID_DATE "12-Feb-2003"
-
-typedef struct blkid_struct_dev *blkid_dev;
-typedef struct blkid_struct_cache *blkid_cache;
-typedef __s64 blkid_loff_t;
-
-typedef struct blkid_struct_tag_iterate *blkid_tag_iterate;
-typedef struct blkid_struct_dev_iterate *blkid_dev_iterate;
-
-/*
- * Flags for blkid_get_dev
- *
- * BLKID_DEV_CREATE Create an empty device structure if not found
- * in the cache.
- * BLKID_DEV_VERIFY Make sure the device structure corresponds
- * with reality.
- * BLKID_DEV_FIND Just look up a device entry, and return NULL
- * if it is not found.
- * BLKID_DEV_NORMAL Get a valid device structure, either from the
- * cache or by probing the device.
- */
-#define BLKID_DEV_FIND 0x0000
-#define BLKID_DEV_CREATE 0x0001
-#define BLKID_DEV_VERIFY 0x0002
-#define BLKID_DEV_NORMAL (BLKID_DEV_CREATE | BLKID_DEV_VERIFY)
-
-/* cache.c */
-extern void blkid_put_cache(blkid_cache cache);
-extern int blkid_get_cache(blkid_cache *cache, const char *filename);
-
-/* dev.c */
-extern const char *blkid_dev_devname(blkid_dev dev);
-
-extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache);
-extern int blkid_dev_set_search(blkid_dev_iterate iter,
- char *search_type, char *search_value);
-extern int blkid_dev_next(blkid_dev_iterate iterate, blkid_dev *dev);
-extern void blkid_dev_iterate_end(blkid_dev_iterate iterate);
-
-/* devno.c */
-extern char *blkid_devno_to_devname(dev_t devno);
-
-/* devname.c */
-extern int blkid_probe_all(blkid_cache cache);
-extern int blkid_probe_all_new(blkid_cache cache);
-extern blkid_dev blkid_get_dev(blkid_cache cache, const char *devname,
- int flags);
-
-/* getsize.c */
-extern blkid_loff_t blkid_get_dev_size(int fd);
-
-/* probe.c */
-int blkid_known_fstype(const char *fstype);
-extern blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev);
-
-/* read.c */
-
-/* resolve.c */
-extern char *blkid_get_tag_value(blkid_cache cache, const char *tagname,
- const char *devname);
-extern char *blkid_get_devname(blkid_cache cache, const char *token,
- const char *value);
-
-/* tag.c */
-extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev);
-extern int blkid_tag_next(blkid_tag_iterate iterate,
- const char **type, const char **value);
-extern void blkid_tag_iterate_end(blkid_tag_iterate iterate);
-extern int blkid_dev_has_tag(blkid_dev dev, const char *type,
- const char *value);
-extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
- const char *type,
- const char *value);
-extern int blkid_parse_tag_string(const char *token, char **ret_type,
- char **ret_val);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/blkidP.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/blkidP.h
deleted file mode 100644
index d6b2b42cc5..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/blkidP.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * blkidP.h - Internal interfaces for libblkid
- *
- * Copyright (C) 2001 Andreas Dilger
- * Copyright (C) 2003 Theodore Ts'o
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-#ifndef BLKID_BLKIDP_H
-#define BLKID_BLKIDP_H 1
-
-#include <sys/types.h>
-#include <stdio.h>
-
-#include "blkid.h"
-#include "list.h"
-
-#ifdef __GNUC__
-#define __BLKID_ATTR(x) __attribute__(x)
-#else
-#define __BLKID_ATTR(x)
-#endif
-
-
-/*
- * This describes the attributes of a specific device.
- * We can traverse all of the tags by bid_tags (linking to the tag bit_names).
- * The bid_label and bid_uuid fields are shortcuts to the LABEL and UUID tag
- * values, if they exist.
- */
-struct blkid_struct_dev
-{
- struct list_head bid_devs; /* All devices in the cache */
- struct list_head bid_tags; /* All tags for this device */
- blkid_cache bid_cache; /* Dev belongs to this cache */
- char *bid_name; /* Device inode pathname */
- char *bid_type; /* Preferred device TYPE */
- int bid_pri; /* Device priority */
- dev_t bid_devno; /* Device major/minor number */
- time_t bid_time; /* Last update time of device */
- unsigned int bid_flags; /* Device status bitflags */
- char *bid_label; /* Shortcut to device LABEL */
- char *bid_uuid; /* Shortcut to binary UUID */
-};
-
-#define BLKID_BID_FL_VERIFIED 0x0001 /* Device data validated from disk */
-#define BLKID_BID_FL_INVALID 0x0004 /* Device is invalid */
-
-/*
- * Each tag defines a NAME=value pair for a particular device. The tags
- * are linked via bit_names for a single device, so that traversing the
- * names list will get you a list of all tags associated with a device.
- * They are also linked via bit_values for all devices, so one can easily
- * search all tags with a given NAME for a specific value.
- */
-struct blkid_struct_tag
-{
- struct list_head bit_tags; /* All tags for this device */
- struct list_head bit_names; /* All tags with given NAME */
- char *bit_name; /* NAME of tag (shared) */
- char *bit_val; /* value of tag */
- blkid_dev bit_dev; /* pointer to device */
-};
-typedef struct blkid_struct_tag *blkid_tag;
-
-/*
- * Minimum number of seconds between device probes, even when reading
- * from the cache. This is to avoid re-probing all devices which were
- * just probed by another program that does not share the cache.
- */
-#define BLKID_PROBE_MIN 2
-
-/*
- * Time in seconds an entry remains verified in the in-memory cache
- * before being reverified (in case of long-running processes that
- * keep a cache in memory and continue to use it for a long time).
- */
-#define BLKID_PROBE_INTERVAL 200
-
-/* This describes an entire blkid cache file and probed devices.
- * We can traverse all of the found devices via bic_list.
- * We can traverse all of the tag types by bic_tags, which hold empty tags
- * for each tag type. Those tags can be used as list_heads for iterating
- * through all devices with a specific tag type (e.g. LABEL).
- */
-struct blkid_struct_cache
-{
- struct list_head bic_devs; /* List head of all devices */
- struct list_head bic_tags; /* List head of all tag types */
- time_t bic_time; /* Last probe time */
- time_t bic_ftime; /* Mod time of the cachefile */
- unsigned int bic_flags; /* Status flags of the cache */
- char *bic_filename; /* filename of cache */
-};
-
-#define BLKID_BIC_FL_PROBED 0x0002 /* We probed /proc/partition devices */
-#define BLKID_BIC_FL_CHANGED 0x0004 /* Cache has changed from disk */
-
-extern char *blkid_strdup(const char *s);
-extern char *blkid_strndup(const char *s, const int length);
-
-#define BLKID_CACHE_FILE "/etc/blkid.tab"
-extern const char *blkid_devdirs[];
-
-#define BLKID_ERR_IO 5
-#define BLKID_ERR_PROC 9
-#define BLKID_ERR_MEM 12
-#define BLKID_ERR_CACHE 14
-#define BLKID_ERR_DEV 19
-#define BLKID_ERR_PARAM 22
-#define BLKID_ERR_BIG 27
-
-/*
- * Priority settings for different types of devices
- */
-#define BLKID_PRI_EVMS 30
-#define BLKID_PRI_LVM 20
-#define BLKID_PRI_MD 10
-
-#if defined(TEST_PROGRAM) && !defined(CONFIG_BLKID_DEBUG)
-#define CONFIG_BLKID_DEBUG
-#endif
-
-#define DEBUG_CACHE 0x0001
-#define DEBUG_DUMP 0x0002
-#define DEBUG_DEV 0x0004
-#define DEBUG_DEVNAME 0x0008
-#define DEBUG_DEVNO 0x0010
-#define DEBUG_PROBE 0x0020
-#define DEBUG_READ 0x0040
-#define DEBUG_RESOLVE 0x0080
-#define DEBUG_SAVE 0x0100
-#define DEBUG_TAG 0x0200
-#define DEBUG_INIT 0x8000
-#define DEBUG_ALL 0xFFFF
-
-#ifdef CONFIG_BLKID_DEBUG
-#include <stdio.h>
-extern int blkid_debug_mask;
-#define DBG(m,x) if ((m) & blkid_debug_mask) x;
-#else
-#define DBG(m,x)
-#endif
-
-#ifdef CONFIG_BLKID_DEBUG
-extern void blkid_debug_dump_dev(blkid_dev dev);
-extern void blkid_debug_dump_tag(blkid_tag tag);
-#endif
-
-/* lseek.c */
-/* extern blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence); */
-#ifdef CONFIG_LFS
-# define blkid_llseek lseek64
-#else
-# define blkid_llseek lseek
-#endif
-
-/* read.c */
-extern void blkid_read_cache(blkid_cache cache);
-
-/* save.c */
-extern int blkid_flush_cache(blkid_cache cache);
-
-/*
- * Functions to create and find a specific tag type: tag.c
- */
-extern void blkid_free_tag(blkid_tag tag);
-extern blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type);
-extern int blkid_set_tag(blkid_dev dev, const char *name,
- const char *value, const int vlength);
-
-/*
- * Functions to create and find a specific tag type: dev.c
- */
-extern blkid_dev blkid_new_dev(void);
-extern void blkid_free_dev(blkid_dev dev);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/blkid_getsize.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/blkid_getsize.c
deleted file mode 100644
index e1f6ba6d2a..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/blkid_getsize.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * getsize.c --- get the size of a partition.
- *
- * Copyright (C) 1995, 1995 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-
-/* include this before sys/queues.h! */
-#include "blkidP.h"
-
-#include <stdio.h>
-#include <unistd.h>
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <fcntl.h>
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#ifdef HAVE_LINUX_FD_H
-#include <linux/fd.h>
-#endif
-#ifdef HAVE_SYS_DISKLABEL_H
-#include <sys/disklabel.h>
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_DISK_H
-#ifdef HAVE_SYS_QUEUE_H
-#include <sys/queue.h> /* for LIST_HEAD */
-#endif
-#include <sys/disk.h>
-#endif
-#ifdef __linux__
-#include <sys/utsname.h>
-#endif
-
-#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
-#define BLKGETSIZE _IO(0x12,96) /* return device size */
-#endif
-
-#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
-#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
-#endif
-
-#ifdef APPLE_DARWIN
-#define BLKGETSIZE DKIOCGETBLOCKCOUNT32
-#endif /* APPLE_DARWIN */
-
-static int valid_offset(int fd, blkid_loff_t offset)
-{
- char ch;
-
- if (blkid_llseek(fd, offset, 0) < 0)
- return 0;
- if (read(fd, &ch, 1) < 1)
- return 0;
- return 1;
-}
-
-/*
- * Returns the number of blocks in a partition
- */
-blkid_loff_t blkid_get_dev_size(int fd)
-{
- int valid_blkgetsize64 = 1;
-#ifdef __linux__
- struct utsname ut;
-#endif
- unsigned long long size64;
- unsigned long size;
- blkid_loff_t high, low;
-#ifdef FDGETPRM
- struct floppy_struct this_floppy;
-#endif
-#ifdef HAVE_SYS_DISKLABEL_H
- int part = -1;
- struct disklabel lab;
- struct partition *pp;
- char ch;
- struct stat st;
-#endif /* HAVE_SYS_DISKLABEL_H */
-
-#ifdef DKIOCGETBLOCKCOUNT /* For Apple Darwin */
- if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) {
- if ((sizeof(blkid_loff_t) < sizeof(unsigned long long))
- && (size64 << 9 > 0xFFFFFFFF))
- return 0; /* EFBIG */
- return (blkid_loff_t) size64 << 9;
- }
-#endif
-
-#ifdef BLKGETSIZE64
-#ifdef __linux__
- uname(&ut);
- if ((ut.release[0] == '2') && (ut.release[1] == '.') &&
- (ut.release[2] < '6') && (ut.release[3] == '.'))
- valid_blkgetsize64 = 0;
-#endif
- if (valid_blkgetsize64 &&
- ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
- if ((sizeof(blkid_loff_t) < sizeof(unsigned long long))
- && ((size64) > 0xFFFFFFFF))
- return 0; /* EFBIG */
- return size64;
- }
-#endif
-
-#ifdef BLKGETSIZE
- if (ioctl(fd, BLKGETSIZE, &size) >= 0)
- return (blkid_loff_t)size << 9;
-#endif
-
-#ifdef FDGETPRM
- if (ioctl(fd, FDGETPRM, &this_floppy) >= 0)
- return (blkid_loff_t)this_floppy.size << 9;
-#endif
-#ifdef HAVE_SYS_DISKLABEL_H
-#if 0
- /*
- * This should work in theory but I haven't tested it. Anyone
- * on a BSD system want to test this for me? In the meantime,
- * binary search mechanism should work just fine.
- */
- if ((fstat(fd, &st) >= 0) && S_ISBLK(st.st_mode))
- part = st.st_rdev & 7;
- if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
- pp = &lab.d_partitions[part];
- if (pp->p_size)
- return pp->p_size << 9;
- }
-#endif
-#endif /* HAVE_SYS_DISKLABEL_H */
-
- /*
- * OK, we couldn't figure it out by using a specialized ioctl,
- * which is generally the best way. So do binary search to
- * find the size of the partition.
- */
- low = 0;
- for (high = 1024; valid_offset(fd, high); high *= 2)
- low = high;
- while (low < high - 1)
- {
- const blkid_loff_t mid = (low + high) / 2;
-
- if (valid_offset(fd, mid))
- low = mid;
- else
- high = mid;
- }
- return low + 1;
-}
-
-#ifdef TEST_PROGRAM
-int main(int argc, char **argv)
-{
- blkid_loff_t bytes;
- int fd;
-
- if (argc < 2) {
- fprintf(stderr, "Usage: %s device\n"
- "Determine the size of a device\n", argv[0]);
- return 1;
- }
-
- if ((fd = open(argv[1], O_RDONLY)) < 0)
- perror(argv[0]);
-
- bytes = blkid_get_dev_size(fd);
- printf("Device %s has %lld 1k blocks.\n", argv[1], bytes >> 10);
-
- return 0;
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/cache.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/cache.c
deleted file mode 100644
index d1d29146b3..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/cache.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * cache.c - allocation/initialization/free routines for cache
- *
- * Copyright (C) 2001 Andreas Dilger
- * Copyright (C) 2003 Theodore Ts'o
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include "blkidP.h"
-
-int blkid_debug_mask = 0;
-
-int blkid_get_cache(blkid_cache *ret_cache, const char *filename)
-{
- blkid_cache cache;
-
-#ifdef CONFIG_BLKID_DEBUG
- if (!(blkid_debug_mask & DEBUG_INIT)) {
- char *dstr = getenv("BLKID_DEBUG");
-
- if (dstr)
- blkid_debug_mask = strtoul(dstr, 0, 0);
- blkid_debug_mask |= DEBUG_INIT;
- }
-#endif
-
- DBG(DEBUG_CACHE, printf("creating blkid cache (using %s)\n",
- filename ? filename : "default cache"));
-
- cache = xzalloc(sizeof(struct blkid_struct_cache));
-
- INIT_LIST_HEAD(&cache->bic_devs);
- INIT_LIST_HEAD(&cache->bic_tags);
-
- if (filename && !strlen(filename))
- filename = 0;
- if (!filename && (getuid() == geteuid()))
- filename = getenv("BLKID_FILE");
- if (!filename)
- filename = BLKID_CACHE_FILE;
- cache->bic_filename = blkid_strdup(filename);
-
- blkid_read_cache(cache);
-
- *ret_cache = cache;
- return 0;
-}
-
-void blkid_put_cache(blkid_cache cache)
-{
- if (!cache)
- return;
-
- (void) blkid_flush_cache(cache);
-
- DBG(DEBUG_CACHE, printf("freeing cache struct\n"));
-
- /* DBG(DEBUG_CACHE, blkid_debug_dump_cache(cache)); */
-
- while (!list_empty(&cache->bic_devs)) {
- blkid_dev dev = list_entry(cache->bic_devs.next,
- struct blkid_struct_dev,
- bid_devs);
- blkid_free_dev(dev);
- }
-
- while (!list_empty(&cache->bic_tags)) {
- blkid_tag tag = list_entry(cache->bic_tags.next,
- struct blkid_struct_tag,
- bit_tags);
-
- while (!list_empty(&tag->bit_names)) {
- blkid_tag bad = list_entry(tag->bit_names.next,
- struct blkid_struct_tag,
- bit_names);
-
- DBG(DEBUG_CACHE, printf("warning: unfreed tag %s=%s\n",
- bad->bit_name, bad->bit_val));
- blkid_free_tag(bad);
- }
- blkid_free_tag(tag);
- }
- free(cache->bic_filename);
-
- free(cache);
-}
-
-#ifdef TEST_PROGRAM
-int main(int argc, char** argv)
-{
- blkid_cache cache = NULL;
- int ret;
-
- blkid_debug_mask = DEBUG_ALL;
- if ((argc > 2)) {
- fprintf(stderr, "Usage: %s [filename]\n", argv[0]);
- exit(1);
- }
-
- if ((ret = blkid_get_cache(&cache, argv[1])) < 0) {
- fprintf(stderr, "error %d parsing cache file %s\n", ret,
- argv[1] ? argv[1] : BLKID_CACHE_FILE);
- exit(1);
- }
- if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
- fprintf(stderr, "%s: error creating cache (%d)\n",
- argv[0], ret);
- exit(1);
- }
- if ((ret = blkid_probe_all(cache) < 0))
- fprintf(stderr, "error probing devices\n");
-
- blkid_put_cache(cache);
-
- return ret;
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/dev.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/dev.c
deleted file mode 100644
index bb0cc914a0..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/dev.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * dev.c - allocation/initialization/free routines for dev
- *
- * Copyright (C) 2001 Andreas Dilger
- * Copyright (C) 2003 Theodore Ts'o
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "blkidP.h"
-
-blkid_dev blkid_new_dev(void)
-{
- blkid_dev dev;
-
- dev = xzalloc(sizeof(struct blkid_struct_dev));
-
- INIT_LIST_HEAD(&dev->bid_devs);
- INIT_LIST_HEAD(&dev->bid_tags);
-
- return dev;
-}
-
-void blkid_free_dev(blkid_dev dev)
-{
- if (!dev)
- return;
-
- DBG(DEBUG_DEV,
- printf(" freeing dev %s (%s)\n", dev->bid_name, dev->bid_type));
- DBG(DEBUG_DEV, blkid_debug_dump_dev(dev));
-
- list_del(&dev->bid_devs);
- while (!list_empty(&dev->bid_tags)) {
- blkid_tag tag = list_entry(dev->bid_tags.next,
- struct blkid_struct_tag,
- bit_tags);
- blkid_free_tag(tag);
- }
- if (dev->bid_name)
- free(dev->bid_name);
- free(dev);
-}
-
-/*
- * Given a blkid device, return its name
- */
-const char *blkid_dev_devname(blkid_dev dev)
-{
- return dev->bid_name;
-}
-
-#ifdef CONFIG_BLKID_DEBUG
-void blkid_debug_dump_dev(blkid_dev dev)
-{
- struct list_head *p;
-
- if (!dev) {
- printf(" dev: NULL\n");
- return;
- }
-
- printf(" dev: name = %s\n", dev->bid_name);
- printf(" dev: DEVNO=\"0x%0llx\"\n", dev->bid_devno);
- printf(" dev: TIME=\"%lu\"\n", dev->bid_time);
- printf(" dev: PRI=\"%d\"\n", dev->bid_pri);
- printf(" dev: flags = 0x%08X\n", dev->bid_flags);
-
- list_for_each(p, &dev->bid_tags) {
- blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
- if (tag)
- printf(" tag: %s=\"%s\"\n", tag->bit_name,
- tag->bit_val);
- else
- printf(" tag: NULL\n");
- }
- bb_putchar('\n');
-}
-#endif
-
-/*
- * dev iteration routines for the public libblkid interface.
- *
- * These routines do not expose the list.h implementation, which are a
- * contamination of the namespace, and which force us to reveal far, far
- * too much of our internal implemenation. I'm not convinced I want
- * to keep list.h in the long term, anyway. It's fine for kernel
- * programming, but performance is not the #1 priority for this
- * library, and I really don't like the tradeoff of type-safety for
- * performance for this application. [tytso:20030125.2007EST]
- */
-
-/*
- * This series of functions iterate over all devices in a blkid cache
- */
-#define DEV_ITERATE_MAGIC 0x01a5284c
-
-struct blkid_struct_dev_iterate {
- int magic;
- blkid_cache cache;
- struct list_head *p;
-};
-
-blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache)
-{
- blkid_dev_iterate iter;
-
- iter = xmalloc(sizeof(struct blkid_struct_dev_iterate));
- iter->magic = DEV_ITERATE_MAGIC;
- iter->cache = cache;
- iter->p = cache->bic_devs.next;
- return iter;
-}
-
-/*
- * Return 0 on success, -1 on error
- */
-extern int blkid_dev_next(blkid_dev_iterate iter,
- blkid_dev *dev)
-{
- *dev = 0;
- if (!iter || iter->magic != DEV_ITERATE_MAGIC ||
- iter->p == &iter->cache->bic_devs)
- return -1;
- *dev = list_entry(iter->p, struct blkid_struct_dev, bid_devs);
- iter->p = iter->p->next;
- return 0;
-}
-
-void blkid_dev_iterate_end(blkid_dev_iterate iter)
-{
- if (!iter || iter->magic != DEV_ITERATE_MAGIC)
- return;
- iter->magic = 0;
- free(iter);
-}
-
-#ifdef TEST_PROGRAM
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#else
-extern char *optarg;
-extern int optind;
-#endif
-
-void usage(char *prog)
-{
- fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask]\n", prog);
- fprintf(stderr, "\tList all devices and exit\n", prog);
- exit(1);
-}
-
-int main(int argc, char **argv)
-{
- blkid_dev_iterate iter;
- blkid_cache cache = NULL;
- blkid_dev dev;
- int c, ret;
- char *tmp;
- char *file = NULL;
- char *search_type = NULL;
- char *search_value = NULL;
-
- while ((c = getopt (argc, argv, "m:f:")) != EOF)
- switch (c) {
- case 'f':
- file = optarg;
- break;
- case 'm':
- blkid_debug_mask = strtoul (optarg, &tmp, 0);
- if (*tmp) {
- fprintf(stderr, "Invalid debug mask: %d\n",
- optarg);
- exit(1);
- }
- break;
- case '?':
- usage(argv[0]);
- }
- if (argc >= optind+2) {
- search_type = argv[optind];
- search_value = argv[optind+1];
- optind += 2;
- }
- if (argc != optind)
- usage(argv[0]);
-
- if ((ret = blkid_get_cache(&cache, file)) != 0) {
- fprintf(stderr, "%s: error creating cache (%d)\n",
- argv[0], ret);
- exit(1);
- }
-
- iter = blkid_dev_iterate_begin(cache);
- if (search_type)
- blkid_dev_set_search(iter, search_type, search_value);
- while (blkid_dev_next(iter, &dev) == 0) {
- printf("Device: %s\n", blkid_dev_devname(dev));
- }
- blkid_dev_iterate_end(iter);
-
-
- blkid_put_cache(cache);
- return 0;
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/devname.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/devname.c
deleted file mode 100644
index fad92cb313..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/devname.c
+++ /dev/null
@@ -1,367 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * devname.c - get a dev by its device inode name
- *
- * Copyright (C) Andries Brouwer
- * Copyright (C) 1999, 2000, 2001, 2002, 2003 Theodore Ts'o
- * Copyright (C) 2001 Andreas Dilger
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#include <sys/stat.h>
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_SYS_MKDEV_H
-#include <sys/mkdev.h>
-#endif
-#include <time.h>
-
-#include "blkidP.h"
-
-/*
- * Find a dev struct in the cache by device name, if available.
- *
- * If there is no entry with the specified device name, and the create
- * flag is set, then create an empty device entry.
- */
-blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags)
-{
- blkid_dev dev = NULL, tmp;
- struct list_head *p;
-
- if (!cache || !devname)
- return NULL;
-
- list_for_each(p, &cache->bic_devs) {
- tmp = list_entry(p, struct blkid_struct_dev, bid_devs);
- if (strcmp(tmp->bid_name, devname))
- continue;
-
- DBG(DEBUG_DEVNAME,
- printf("found devname %s in cache\n", tmp->bid_name));
- dev = tmp;
- break;
- }
-
- if (!dev && (flags & BLKID_DEV_CREATE)) {
- dev = blkid_new_dev();
- if (!dev)
- return NULL;
- dev->bid_name = blkid_strdup(devname);
- dev->bid_cache = cache;
- list_add_tail(&dev->bid_devs, &cache->bic_devs);
- cache->bic_flags |= BLKID_BIC_FL_CHANGED;
- }
-
- if (flags & BLKID_DEV_VERIFY)
- dev = blkid_verify(cache, dev);
- return dev;
-}
-
-/*
- * Probe a single block device to add to the device cache.
- */
-static void probe_one(blkid_cache cache, const char *ptname,
- dev_t devno, int pri)
-{
- blkid_dev dev = NULL;
- struct list_head *p;
- const char **dir;
- char *devname = NULL;
-
- /* See if we already have this device number in the cache. */
- list_for_each(p, &cache->bic_devs) {
- blkid_dev tmp = list_entry(p, struct blkid_struct_dev,
- bid_devs);
- if (tmp->bid_devno == devno) {
- dev = blkid_verify(cache, tmp);
- break;
- }
- }
- if (dev && dev->bid_devno == devno)
- goto set_pri;
-
- /*
- * Take a quick look at /dev/ptname for the device number. We check
- * all of the likely device directories. If we don't find it, or if
- * the stat information doesn't check out, use blkid_devno_to_devname()
- * to find it via an exhaustive search for the device major/minor.
- */
- for (dir = blkid_devdirs; *dir; dir++) {
- struct stat st;
- char device[256];
-
- sprintf(device, "%s/%s", *dir, ptname);
- if ((dev = blkid_get_dev(cache, device, BLKID_DEV_FIND)) &&
- dev->bid_devno == devno)
- goto set_pri;
-
- if (stat(device, &st) == 0 && S_ISBLK(st.st_mode) &&
- st.st_rdev == devno) {
- devname = blkid_strdup(device);
- break;
- }
- }
- if (!devname) {
- devname = blkid_devno_to_devname(devno);
- if (!devname)
- return;
- }
- dev = blkid_get_dev(cache, devname, BLKID_DEV_NORMAL);
- free(devname);
-
-set_pri:
- if (!pri && !strncmp(ptname, "md", 2))
- pri = BLKID_PRI_MD;
- if (dev)
- dev->bid_pri = pri;
-}
-
-#define PROC_PARTITIONS "/proc/partitions"
-#define VG_DIR "/proc/lvm/VGs"
-
-/*
- * This function initializes the UUID cache with devices from the LVM
- * proc hierarchy. We currently depend on the names of the LVM
- * hierarchy giving us the device structure in /dev. (XXX is this a
- * safe thing to do?)
- */
-#ifdef VG_DIR
-#include <dirent.h>
-static dev_t lvm_get_devno(const char *lvm_device)
-{
- FILE *lvf;
- char buf[1024];
- int ma, mi;
- dev_t ret = 0;
-
- DBG(DEBUG_DEVNAME, printf("opening %s\n", lvm_device));
- if ((lvf = fopen_for_read(lvm_device)) == NULL) {
- DBG(DEBUG_DEVNAME, printf("%s: (%d) %s\n", lvm_device, errno,
- strerror(errno)));
- return 0;
- }
-
- while (fgets(buf, sizeof(buf), lvf)) {
- if (sscanf(buf, "device: %d:%d", &ma, &mi) == 2) {
- ret = makedev(ma, mi);
- break;
- }
- }
- fclose(lvf);
-
- return ret;
-}
-
-static void lvm_probe_all(blkid_cache cache)
-{
- DIR *vg_list;
- struct dirent *vg_iter;
- int vg_len = strlen(VG_DIR);
- dev_t dev;
-
- if ((vg_list = opendir(VG_DIR)) == NULL)
- return;
-
- DBG(DEBUG_DEVNAME, printf("probing LVM devices under %s\n", VG_DIR));
-
- while ((vg_iter = readdir(vg_list)) != NULL) {
- DIR *lv_list;
- char *vdirname;
- char *vg_name;
- struct dirent *lv_iter;
-
- vg_name = vg_iter->d_name;
- if (LONE_CHAR(vg_name, '.') || !strcmp(vg_name, ".."))
- continue;
- vdirname = xmalloc(vg_len + strlen(vg_name) + 8);
- sprintf(vdirname, "%s/%s/LVs", VG_DIR, vg_name);
-
- lv_list = opendir(vdirname);
- free(vdirname);
- if (lv_list == NULL)
- continue;
-
- while ((lv_iter = readdir(lv_list)) != NULL) {
- char *lv_name, *lvm_device;
-
- lv_name = lv_iter->d_name;
- if (LONE_CHAR(lv_name, '.') || !strcmp(lv_name, ".."))
- continue;
-
- lvm_device = xmalloc(vg_len + strlen(vg_name) +
- strlen(lv_name) + 8);
- sprintf(lvm_device, "%s/%s/LVs/%s", VG_DIR, vg_name,
- lv_name);
- dev = lvm_get_devno(lvm_device);
- sprintf(lvm_device, "%s/%s", vg_name, lv_name);
- DBG(DEBUG_DEVNAME, printf("LVM dev %s: devno 0x%04X\n",
- lvm_device,
- (unsigned int) dev));
- probe_one(cache, lvm_device, dev, BLKID_PRI_LVM);
- free(lvm_device);
- }
- closedir(lv_list);
- }
- closedir(vg_list);
-}
-#endif
-
-#define PROC_EVMS_VOLUMES "/proc/evms/volumes"
-
-static int
-evms_probe_all(blkid_cache cache)
-{
- char line[100];
- int ma, mi, sz, num = 0;
- FILE *procpt;
- char device[110];
-
- procpt = fopen_for_read(PROC_EVMS_VOLUMES);
- if (!procpt)
- return 0;
- while (fgets(line, sizeof(line), procpt)) {
- if (sscanf(line, " %d %d %d %*s %*s %[^\n ]",
- &ma, &mi, &sz, device) != 4)
- continue;
-
- DBG(DEBUG_DEVNAME, printf("Checking partition %s (%d, %d)\n",
- device, ma, mi));
-
- probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS);
- num++;
- }
- fclose(procpt);
- return num;
-}
-
-/*
- * Read the device data for all available block devices in the system.
- */
-int blkid_probe_all(blkid_cache cache)
-{
- FILE *proc;
- char line[1024];
- char ptname0[128], ptname1[128], *ptname = NULL;
- char *ptnames[2];
- dev_t devs[2];
- int ma, mi;
- unsigned long long sz;
- int lens[2] = { 0, 0 };
- int which = 0, last = 0;
-
- ptnames[0] = ptname0;
- ptnames[1] = ptname1;
-
- if (!cache)
- return -BLKID_ERR_PARAM;
-
- if (cache->bic_flags & BLKID_BIC_FL_PROBED &&
- time(NULL) - cache->bic_time < BLKID_PROBE_INTERVAL)
- return 0;
-
- blkid_read_cache(cache);
- evms_probe_all(cache);
-#ifdef VG_DIR
- lvm_probe_all(cache);
-#endif
-
- proc = fopen_for_read(PROC_PARTITIONS);
- if (!proc)
- return -BLKID_ERR_PROC;
-
- while (fgets(line, sizeof(line), proc)) {
- last = which;
- which ^= 1;
- ptname = ptnames[which];
-
- if (sscanf(line, " %d %d %llu %128[^\n ]",
- &ma, &mi, &sz, ptname) != 4)
- continue;
- devs[which] = makedev(ma, mi);
-
- DBG(DEBUG_DEVNAME, printf("read partition name %s\n", ptname));
-
- /* Skip whole disk devs unless they have no partitions
- * If we don't have a partition on this dev, also
- * check previous dev to see if it didn't have a partn.
- * heuristic: partition name ends in a digit.
- *
- * Skip extended partitions.
- * heuristic: size is 1
- *
- * FIXME: skip /dev/{ida,cciss,rd} whole-disk devs
- */
-
- lens[which] = strlen(ptname);
- if (isdigit(ptname[lens[which] - 1])) {
- DBG(DEBUG_DEVNAME,
- printf("partition dev %s, devno 0x%04X\n",
- ptname, (unsigned int) devs[which]));
-
- if (sz > 1)
- probe_one(cache, ptname, devs[which], 0);
- lens[which] = 0;
- lens[last] = 0;
- } else if (lens[last] && strncmp(ptnames[last], ptname,
- lens[last])) {
- DBG(DEBUG_DEVNAME,
- printf("whole dev %s, devno 0x%04X\n",
- ptnames[last], (unsigned int) devs[last]));
- probe_one(cache, ptnames[last], devs[last], 0);
- lens[last] = 0;
- }
- }
-
- /* Handle the last device if it wasn't partitioned */
- if (lens[which])
- probe_one(cache, ptname, devs[which], 0);
-
- fclose(proc);
-
- cache->bic_time = time(NULL);
- cache->bic_flags |= BLKID_BIC_FL_PROBED;
- blkid_flush_cache(cache);
- return 0;
-}
-
-#ifdef TEST_PROGRAM
-int main(int argc, char **argv)
-{
- blkid_cache cache = NULL;
- int ret;
-
- blkid_debug_mask = DEBUG_ALL;
- if (argc != 1) {
- fprintf(stderr, "Usage: %s\n"
- "Probe all devices and exit\n", argv[0]);
- exit(1);
- }
- if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
- fprintf(stderr, "%s: error creating cache (%d)\n",
- argv[0], ret);
- exit(1);
- }
- if (blkid_probe_all(cache) < 0)
- printf("%s: error probing devices\n", argv[0]);
-
- blkid_put_cache(cache);
- return 0;
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/devno.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/devno.c
deleted file mode 100644
index ae326f81a0..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/devno.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * devno.c - find a particular device by its device number (major/minor)
- *
- * Copyright (C) 2000, 2001, 2003 Theodore Ts'o
- * Copyright (C) 2001 Andreas Dilger
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#include <sys/stat.h>
-#include <dirent.h>
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_SYS_MKDEV_H
-#include <sys/mkdev.h>
-#endif
-
-#include "blkidP.h"
-
-struct dir_list {
- char *name;
- struct dir_list *next;
-};
-
-char *blkid_strndup(const char *s, int length)
-{
- char *ret;
-
- if (!s)
- return NULL;
-
- if (!length)
- length = strlen(s);
-
- ret = xmalloc(length + 1);
- strncpy(ret, s, length);
- ret[length] = '\0';
- return ret;
-}
-
-char *blkid_strdup(const char *s)
-{
- return blkid_strndup(s, 0);
-}
-
-/*
- * This function adds an entry to the directory list
- */
-static void add_to_dirlist(const char *name, struct dir_list **list)
-{
- struct dir_list *dp;
-
- dp = xmalloc(sizeof(struct dir_list));
- dp->name = blkid_strdup(name);
- dp->next = *list;
- *list = dp;
-}
-
-/*
- * This function frees a directory list
- */
-static void free_dirlist(struct dir_list **list)
-{
- struct dir_list *dp, *next;
-
- for (dp = *list; dp; dp = next) {
- next = dp->next;
- free(dp->name);
- free(dp);
- }
- *list = NULL;
-}
-
-static void scan_dir(char *dir_name, dev_t devno, struct dir_list **list,
- char **devname)
-{
- DIR *dir;
- struct dirent *dp;
- char path[1024];
- int dirlen;
- struct stat st;
-
- if ((dir = opendir(dir_name)) == NULL)
- return;
- dirlen = strlen(dir_name) + 2;
- while ((dp = readdir(dir)) != 0) {
- if (dirlen + strlen(dp->d_name) >= sizeof(path))
- continue;
-
- if (dp->d_name[0] == '.' &&
- ((dp->d_name[1] == 0) ||
- ((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
- continue;
-
- sprintf(path, "%s/%s", dir_name, dp->d_name);
- if (stat(path, &st) < 0)
- continue;
-
- if (S_ISDIR(st.st_mode))
- add_to_dirlist(path, list);
- else if (S_ISBLK(st.st_mode) && st.st_rdev == devno) {
- *devname = blkid_strdup(path);
- DBG(DEBUG_DEVNO,
- printf("found 0x%llx at %s (%p)\n", devno,
- path, *devname));
- break;
- }
- }
- closedir(dir);
-}
-
-/* Directories where we will try to search for device numbers */
-const char *blkid_devdirs[] = { "/devices", "/devfs", "/dev", NULL };
-
-/*
- * This function finds the pathname to a block device with a given
- * device number. It returns a pointer to allocated memory to the
- * pathname on success, and NULL on failure.
- */
-char *blkid_devno_to_devname(dev_t devno)
-{
- struct dir_list *list = NULL, *new_list = NULL;
- char *devname = NULL;
- const char **dir;
-
- /*
- * Add the starting directories to search in reverse order of
- * importance, since we are using a stack...
- */
- for (dir = blkid_devdirs; *dir; dir++)
- add_to_dirlist(*dir, &list);
-
- while (list) {
- struct dir_list *current = list;
-
- list = list->next;
- DBG(DEBUG_DEVNO, printf("directory %s\n", current->name));
- scan_dir(current->name, devno, &new_list, &devname);
- free(current->name);
- free(current);
- if (devname)
- break;
- /*
- * If we're done checking at this level, descend to
- * the next level of subdirectories. (breadth-first)
- */
- if (list == NULL) {
- list = new_list;
- new_list = NULL;
- }
- }
- free_dirlist(&list);
- free_dirlist(&new_list);
-
- if (!devname) {
- DBG(DEBUG_DEVNO,
- printf("blkid: cannot find devno 0x%04lx\n",
- (unsigned long) devno));
- } else {
- DBG(DEBUG_DEVNO,
- printf("found devno 0x%04llx as %s\n", devno, devname));
- }
-
-
- return devname;
-}
-
-#ifdef TEST_PROGRAM
-int main(int argc, char** argv)
-{
- char *devname, *tmp;
- int major, minor;
- dev_t devno;
- const char *errmsg = "Cannot parse %s: %s\n";
-
- blkid_debug_mask = DEBUG_ALL;
- if ((argc != 2) && (argc != 3)) {
- fprintf(stderr, "Usage:\t%s device_number\n\t%s major minor\n"
- "Resolve a device number to a device name\n",
- argv[0], argv[0]);
- exit(1);
- }
- if (argc == 2) {
- devno = strtoul(argv[1], &tmp, 0);
- if (*tmp) {
- fprintf(stderr, errmsg, "device number", argv[1]);
- exit(1);
- }
- } else {
- major = strtoul(argv[1], &tmp, 0);
- if (*tmp) {
- fprintf(stderr, errmsg, "major number", argv[1]);
- exit(1);
- }
- minor = strtoul(argv[2], &tmp, 0);
- if (*tmp) {
- fprintf(stderr, errmsg, "minor number", argv[2]);
- exit(1);
- }
- devno = makedev(major, minor);
- }
- printf("Looking for device 0x%04Lx\n", devno);
- devname = blkid_devno_to_devname(devno);
- free(devname);
- return 0;
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/list.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/list.c
deleted file mode 100644
index 04d61a19ba..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/list.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/* vi: set sw=4 ts=4: */
-
-#include "list.h"
-
-/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-void __list_add(struct list_head * add,
- struct list_head * prev,
- struct list_head * next)
-{
- next->prev = add;
- add->next = next;
- add->prev = prev;
- prev->next = add;
-}
-
-/*
- * list_add - add a new entry
- * @add: new entry to be added
- * @head: list head to add it after
- *
- * Insert a new entry after the specified head.
- * This is good for implementing stacks.
- */
-void list_add(struct list_head *add, struct list_head *head)
-{
- __list_add(add, head, head->next);
-}
-
-/*
- * list_add_tail - add a new entry
- * @add: new entry to be added
- * @head: list head to add it before
- *
- * Insert a new entry before the specified head.
- * This is useful for implementing queues.
- */
-void list_add_tail(struct list_head *add, struct list_head *head)
-{
- __list_add(add, head->prev, head);
-}
-
-/*
- * Delete a list entry by making the prev/next entries
- * point to each other.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-void __list_del(struct list_head * prev, struct list_head * next)
-{
- next->prev = prev;
- prev->next = next;
-}
-
-/*
- * list_del - deletes entry from list.
- * @entry: the element to delete from the list.
- *
- * list_empty() on @entry does not return true after this, @entry is
- * in an undefined state.
- */
-void list_del(struct list_head *entry)
-{
- __list_del(entry->prev, entry->next);
-}
-
-/*
- * list_del_init - deletes entry from list and reinitialize it.
- * @entry: the element to delete from the list.
- */
-void list_del_init(struct list_head *entry)
-{
- __list_del(entry->prev, entry->next);
- INIT_LIST_HEAD(entry);
-}
-
-/*
- * list_empty - tests whether a list is empty
- * @head: the list to test.
- */
-int list_empty(struct list_head *head)
-{
- return head->next == head;
-}
-
-/*
- * list_splice - join two lists
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- */
-void list_splice(struct list_head *list, struct list_head *head)
-{
- struct list_head *first = list->next;
-
- if (first != list) {
- struct list_head *last = list->prev;
- struct list_head *at = head->next;
-
- first->prev = head;
- head->next = first;
-
- last->next = at;
- at->prev = last;
- }
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/list.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/list.h
deleted file mode 100644
index a24baaa912..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/list.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* vi: set sw=4 ts=4: */
-#if !defined(_BLKID_LIST_H) && !defined(LIST_HEAD)
-#define BLKID_LIST_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Simple doubly linked list implementation.
- *
- * Some of the internal functions ("__xxx") are useful when
- * manipulating whole lists rather than single entries, as
- * sometimes we already know the next/prev entries and we can
- * generate better code by using them directly rather than
- * using the generic single-entry routines.
- */
-
-struct list_head {
- struct list_head *next, *prev;
-};
-
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define LIST_HEAD(name) \
- struct list_head name = LIST_HEAD_INIT(name)
-
-#define INIT_LIST_HEAD(ptr) do { \
- (ptr)->next = (ptr); (ptr)->prev = (ptr); \
-} while (0)
-
-void __list_add(struct list_head * add, struct list_head * prev, struct list_head * next);
-void list_add(struct list_head *add, struct list_head *head);
-void list_add_tail(struct list_head *add, struct list_head *head);
-void __list_del(struct list_head * prev, struct list_head * next);
-void list_del(struct list_head *entry);
-void list_del_init(struct list_head *entry);
-int list_empty(struct list_head *head);
-void list_splice(struct list_head *list, struct list_head *head);
-
-/**
- * list_entry - get the struct for this entry
- * @ptr: the &struct list_head pointer.
- * @type: the type of the struct this is embedded in.
- * @member: the name of the list_struct within the struct.
- */
-#define list_entry(ptr, type, member) \
- ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
-
-/**
- * list_for_each - iterate over elements in a list
- * @pos: the &struct list_head to use as a loop counter.
- * @head: the head for your list.
- */
-#define list_for_each(pos, head) \
- for (pos = (head)->next; pos != (head); pos = pos->next)
-
-/**
- * list_for_each_safe - iterate over elements in a list, but don't dereference
- * pos after the body is done (in case it is freed)
- * @pos: the &struct list_head to use as a loop counter.
- * @pnext: the &struct list_head to use as a pointer to the next item.
- * @head: the head for your list (not included in iteration).
- */
-#define list_for_each_safe(pos, pnext, head) \
- for (pos = (head)->next, pnext = pos->next; pos != (head); \
- pos = pnext, pnext = pos->next)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/probe.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/probe.c
deleted file mode 100644
index 651193b426..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/probe.c
+++ /dev/null
@@ -1,726 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * probe.c - identify a block device by its contents, and return a dev
- * struct with the details
- *
- * Copyright (C) 1999 by Andries Brouwer
- * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
- * Copyright (C) 2001 by Andreas Dilger
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_MKDEV_H
-#include <sys/mkdev.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include "blkidP.h"
-#include "../uuid/uuid.h"
-#include "probe.h"
-
-/*
- * This is a special case code to check for an MDRAID device. We do
- * this special since it requires checking for a superblock at the end
- * of the device.
- */
-static int check_mdraid(int fd, unsigned char *ret_uuid)
-{
- struct mdp_superblock_s *md;
- blkid_loff_t offset;
- char buf[4096];
-
- if (fd < 0)
- return -BLKID_ERR_PARAM;
-
- offset = (blkid_get_dev_size(fd) & ~((blkid_loff_t)65535)) - 65536;
-
- if (blkid_llseek(fd, offset, 0) < 0 ||
- read(fd, buf, 4096) != 4096)
- return -BLKID_ERR_IO;
-
- /* Check for magic number */
- if (memcmp("\251+N\374", buf, 4))
- return -BLKID_ERR_PARAM;
-
- if (!ret_uuid)
- return 0;
- *ret_uuid = 0;
-
- /* The MD UUID is not contiguous in the superblock, make it so */
- md = (struct mdp_superblock_s *)buf;
- if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) {
- memcpy(ret_uuid, &md->set_uuid0, 4);
- memcpy(ret_uuid, &md->set_uuid1, 12);
- }
- return 0;
-}
-
-static void set_uuid(blkid_dev dev, uuid_t uuid)
-{
- char str[37];
-
- if (!uuid_is_null(uuid)) {
- uuid_unparse(uuid, str);
- blkid_set_tag(dev, "UUID", str, sizeof(str));
- }
-}
-
-static void get_ext2_info(blkid_dev dev, unsigned char *buf)
-{
- struct ext2_super_block *es = (struct ext2_super_block *) buf;
- const char *label = NULL;
-
- DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n",
- blkid_le32(es->s_feature_compat),
- blkid_le32(es->s_feature_incompat),
- blkid_le32(es->s_feature_ro_compat)));
-
- if (strlen(es->s_volume_name))
- label = es->s_volume_name;
- blkid_set_tag(dev, "LABEL", label, sizeof(es->s_volume_name));
-
- set_uuid(dev, es->s_uuid);
-}
-
-static int probe_ext3(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct ext2_super_block *es;
-
- es = (struct ext2_super_block *)buf;
-
- /* Distinguish between jbd and ext2/3 fs */
- if (blkid_le32(es->s_feature_incompat) &
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
- return -BLKID_ERR_PARAM;
-
- /* Distinguish between ext3 and ext2 */
- if (!(blkid_le32(es->s_feature_compat) &
- EXT3_FEATURE_COMPAT_HAS_JOURNAL))
- return -BLKID_ERR_PARAM;
-
- get_ext2_info(dev, buf);
-
- blkid_set_tag(dev, "SEC_TYPE", "ext2", sizeof("ext2"));
-
- return 0;
-}
-
-static int probe_ext2(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct ext2_super_block *es;
-
- es = (struct ext2_super_block *)buf;
-
- /* Distinguish between jbd and ext2/3 fs */
- if (blkid_le32(es->s_feature_incompat) &
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
- return -BLKID_ERR_PARAM;
-
- get_ext2_info(dev, buf);
-
- return 0;
-}
-
-static int probe_jbd(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct ext2_super_block *es = (struct ext2_super_block *) buf;
-
- if (!(blkid_le32(es->s_feature_incompat) &
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV))
- return -BLKID_ERR_PARAM;
-
- get_ext2_info(dev, buf);
-
- return 0;
-}
-
-static int probe_vfat(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct vfat_super_block *vs;
- char serno[10];
- const char *label = NULL;
- int label_len = 0;
-
- vs = (struct vfat_super_block *)buf;
-
- if (strncmp(vs->vs_label, "NO NAME", 7)) {
- char *end = vs->vs_label + sizeof(vs->vs_label) - 1;
-
- while (*end == ' ' && end >= vs->vs_label)
- --end;
- if (end >= vs->vs_label) {
- label = vs->vs_label;
- label_len = end - vs->vs_label + 1;
- }
- }
-
- /* We can't just print them as %04X, because they are unaligned */
- sprintf(serno, "%02X%02X-%02X%02X", vs->vs_serno[3], vs->vs_serno[2],
- vs->vs_serno[1], vs->vs_serno[0]);
- blkid_set_tag(dev, "LABEL", label, label_len);
- blkid_set_tag(dev, "UUID", serno, sizeof(serno));
-
- return 0;
-}
-
-static int probe_msdos(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct msdos_super_block *ms = (struct msdos_super_block *) buf;
- char serno[10];
- const char *label = NULL;
- int label_len = 0;
-
- if (strncmp(ms->ms_label, "NO NAME", 7)) {
- char *end = ms->ms_label + sizeof(ms->ms_label) - 1;
-
- while (*end == ' ' && end >= ms->ms_label)
- --end;
- if (end >= ms->ms_label) {
- label = ms->ms_label;
- label_len = end - ms->ms_label + 1;
- }
- }
-
- /* We can't just print them as %04X, because they are unaligned */
- sprintf(serno, "%02X%02X-%02X%02X", ms->ms_serno[3], ms->ms_serno[2],
- ms->ms_serno[1], ms->ms_serno[0]);
- blkid_set_tag(dev, "UUID", serno, 0);
- blkid_set_tag(dev, "LABEL", label, label_len);
- blkid_set_tag(dev, "SEC_TYPE", "msdos", sizeof("msdos"));
-
- return 0;
-}
-
-static int probe_xfs(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct xfs_super_block *xs;
- const char *label = NULL;
-
- xs = (struct xfs_super_block *)buf;
-
- if (strlen(xs->xs_fname))
- label = xs->xs_fname;
- blkid_set_tag(dev, "LABEL", label, sizeof(xs->xs_fname));
- set_uuid(dev, xs->xs_uuid);
- return 0;
-}
-
-static int probe_reiserfs(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id, unsigned char *buf)
-{
- struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf;
- unsigned int blocksize;
- const char *label = NULL;
-
- blocksize = blkid_le16(rs->rs_blocksize);
-
- /* If the superblock is inside the journal, we have the wrong one */
- if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block))
- return -BLKID_ERR_BIG;
-
- /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */
- if (!strcmp(id->bim_magic, "ReIsEr2Fs") ||
- !strcmp(id->bim_magic, "ReIsEr3Fs")) {
- if (strlen(rs->rs_label))
- label = rs->rs_label;
- set_uuid(dev, rs->rs_uuid);
- }
- blkid_set_tag(dev, "LABEL", label, sizeof(rs->rs_label));
-
- return 0;
-}
-
-static int probe_jfs(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct jfs_super_block *js;
- const char *label = NULL;
-
- js = (struct jfs_super_block *)buf;
-
- if (strlen((char *) js->js_label))
- label = (char *) js->js_label;
- blkid_set_tag(dev, "LABEL", label, sizeof(js->js_label));
- set_uuid(dev, js->js_uuid);
- return 0;
-}
-
-static int probe_romfs(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct romfs_super_block *ros;
- const char *label = NULL;
-
- ros = (struct romfs_super_block *)buf;
-
- if (strlen((char *) ros->ros_volume))
- label = (char *) ros->ros_volume;
- blkid_set_tag(dev, "LABEL", label, 0);
- return 0;
-}
-
-static int probe_cramfs(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct cramfs_super_block *csb;
- const char *label = NULL;
-
- csb = (struct cramfs_super_block *)buf;
-
- if (strlen((char *) csb->name))
- label = (char *) csb->name;
- blkid_set_tag(dev, "LABEL", label, 0);
- return 0;
-}
-
-static int probe_swap0(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf __BLKID_ATTR((unused)))
-{
- blkid_set_tag(dev, "UUID", 0, 0);
- blkid_set_tag(dev, "LABEL", 0, 0);
- return 0;
-}
-
-static int probe_swap1(int fd,
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf __BLKID_ATTR((unused)))
-{
- struct swap_id_block *sws;
-
- probe_swap0(fd, cache, dev, id, buf);
- /*
- * Version 1 swap headers are always located at offset of 1024
- * bytes, although the swap signature itself is located at the
- * end of the page (which may vary depending on hardware
- * pagesize).
- */
- if (lseek(fd, 1024, SEEK_SET) < 0) return 1;
- sws = xmalloc(1024);
- if (read(fd, sws, 1024) != 1024) {
- free(sws);
- return 1;
- }
-
- /* arbitrary sanity check.. is there any garbage down there? */
- if (sws->sws_pad[32] == 0 && sws->sws_pad[33] == 0) {
- if (sws->sws_volume[0])
- blkid_set_tag(dev, "LABEL", (const char*)sws->sws_volume,
- sizeof(sws->sws_volume));
- if (sws->sws_uuid[0])
- set_uuid(dev, sws->sws_uuid);
- }
- free(sws);
-
- return 0;
-}
-
-static const char
-* const udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
- "NSR03", "TEA01", 0 };
-
-static int probe_udf(int fd, blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev __BLKID_ATTR((unused)),
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf __BLKID_ATTR((unused)))
-{
- int j, bs;
- struct iso_volume_descriptor isosb;
- const char *const *m;
-
- /* determine the block size by scanning in 2K increments
- (block sizes larger than 2K will be null padded) */
- for (bs = 1; bs < 16; bs++) {
- lseek(fd, bs*2048+32768, SEEK_SET);
- if (read(fd, (char *)&isosb, sizeof(isosb)) != sizeof(isosb))
- return 1;
- if (isosb.id[0])
- break;
- }
-
- /* Scan up to another 64 blocks looking for additional VSD's */
- for (j = 1; j < 64; j++) {
- if (j > 1) {
- lseek(fd, j*bs*2048+32768, SEEK_SET);
- if (read(fd, (char *)&isosb, sizeof(isosb))
- != sizeof(isosb))
- return 1;
- }
- /* If we find NSR0x then call it udf:
- NSR01 for UDF 1.00
- NSR02 for UDF 1.50
- NSR03 for UDF 2.00 */
- if (!strncmp(isosb.id, "NSR0", 4))
- return 0;
- for (m = udf_magic; *m; m++)
- if (!strncmp(*m, isosb.id, 5))
- break;
- if (*m == 0)
- return 1;
- }
- return 1;
-}
-
-static int probe_ocfs(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct ocfs_volume_header ovh;
- struct ocfs_volume_label ovl;
- __u32 major;
-
- memcpy(&ovh, buf, sizeof(ovh));
- memcpy(&ovl, buf+512, sizeof(ovl));
-
- major = ocfsmajor(ovh);
- if (major == 1)
- blkid_set_tag(dev, "SEC_TYPE", "ocfs1", sizeof("ocfs1"));
- else if (major >= 9)
- blkid_set_tag(dev, "SEC_TYPE", "ntocfs", sizeof("ntocfs"));
-
- blkid_set_tag(dev, "LABEL", (const char*)ovl.label, ocfslabellen(ovl));
- blkid_set_tag(dev, "MOUNT", (const char*)ovh.mount, ocfsmountlen(ovh));
- set_uuid(dev, ovl.vol_id);
- return 0;
-}
-
-static int probe_ocfs2(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct ocfs2_super_block *osb;
-
- osb = (struct ocfs2_super_block *)buf;
-
- blkid_set_tag(dev, "LABEL", (const char*)osb->s_label, sizeof(osb->s_label));
- set_uuid(dev, osb->s_uuid);
- return 0;
-}
-
-static int probe_oracleasm(int fd __BLKID_ATTR((unused)),
- blkid_cache cache __BLKID_ATTR((unused)),
- blkid_dev dev,
- const struct blkid_magic *id __BLKID_ATTR((unused)),
- unsigned char *buf)
-{
- struct oracle_asm_disk_label *dl;
-
- dl = (struct oracle_asm_disk_label *)buf;
-
- blkid_set_tag(dev, "LABEL", dl->dl_id, sizeof(dl->dl_id));
- return 0;
-}
-
-/*
- * BLKID_BLK_OFFS is at least as large as the highest bim_kboff defined
- * in the type_array table below + bim_kbalign.
- *
- * When probing for a lot of magics, we handle everything in 1kB buffers so
- * that we don't have to worry about reading each combination of block sizes.
- */
-#define BLKID_BLK_OFFS 64 /* currently reiserfs */
-
-/*
- * Various filesystem magics that we can check for. Note that kboff and
- * sboff are in kilobytes and bytes respectively. All magics are in
- * byte strings so we don't worry about endian issues.
- */
-static const struct blkid_magic type_array[] = {
-/* type kboff sboff len magic probe */
- { "oracleasm", 0, 32, 8, "ORCLDISK", probe_oracleasm },
- { "ntfs", 0, 3, 8, "NTFS ", 0 },
- { "jbd", 1, 0x38, 2, "\123\357", probe_jbd },
- { "ext3", 1, 0x38, 2, "\123\357", probe_ext3 },
- { "ext2", 1, 0x38, 2, "\123\357", probe_ext2 },
- { "reiserfs", 8, 0x34, 8, "ReIsErFs", probe_reiserfs },
- { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", probe_reiserfs },
- { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", probe_reiserfs },
- { "reiserfs", 64, 0x34, 8, "ReIsErFs", probe_reiserfs },
- { "reiserfs", 8, 20, 8, "ReIsErFs", probe_reiserfs },
- { "vfat", 0, 0x52, 5, "MSWIN", probe_vfat },
- { "vfat", 0, 0x52, 8, "FAT32 ", probe_vfat },
- { "vfat", 0, 0x36, 5, "MSDOS", probe_msdos },
- { "vfat", 0, 0x36, 8, "FAT16 ", probe_msdos },
- { "vfat", 0, 0x36, 8, "FAT12 ", probe_msdos },
- { "minix", 1, 0x10, 2, "\177\023", 0 },
- { "minix", 1, 0x10, 2, "\217\023", 0 },
- { "minix", 1, 0x10, 2, "\150\044", 0 },
- { "minix", 1, 0x10, 2, "\170\044", 0 },
- { "vxfs", 1, 0, 4, "\365\374\001\245", 0 },
- { "xfs", 0, 0, 4, "XFSB", probe_xfs },
- { "romfs", 0, 0, 8, "-rom1fs-", probe_romfs },
- { "bfs", 0, 0, 4, "\316\372\173\033", 0 },
- { "cramfs", 0, 0, 4, "E=\315\050", probe_cramfs },
- { "qnx4", 0, 4, 6, "QNX4FS", 0 },
- { "udf", 32, 1, 5, "BEA01", probe_udf },
- { "udf", 32, 1, 5, "BOOT2", probe_udf },
- { "udf", 32, 1, 5, "CD001", probe_udf },
- { "udf", 32, 1, 5, "CDW02", probe_udf },
- { "udf", 32, 1, 5, "NSR02", probe_udf },
- { "udf", 32, 1, 5, "NSR03", probe_udf },
- { "udf", 32, 1, 5, "TEA01", probe_udf },
- { "iso9660", 32, 1, 5, "CD001", 0 },
- { "iso9660", 32, 9, 5, "CDROM", 0 },
- { "jfs", 32, 0, 4, "JFS1", probe_jfs },
- { "hfs", 1, 0, 2, "BD", 0 },
- { "ufs", 8, 0x55c, 4, "T\031\001\000", 0 },
- { "hpfs", 8, 0, 4, "I\350\225\371", 0 },
- { "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 },
- { "swap", 0, 0xff6, 10, "SWAP-SPACE", probe_swap0 },
- { "swap", 0, 0xff6, 10, "SWAPSPACE2", probe_swap1 },
- { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", probe_swap0 },
- { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", probe_swap1 },
- { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", probe_swap0 },
- { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", probe_swap1 },
- { "swap", 0, 0x7ff6, 10, "SWAP-SPACE", probe_swap0 },
- { "swap", 0, 0x7ff6, 10, "SWAPSPACE2", probe_swap1 },
- { "swap", 0, 0xfff6, 10, "SWAP-SPACE", probe_swap0 },
- { "swap", 0, 0xfff6, 10, "SWAPSPACE2", probe_swap1 },
- { "ocfs", 0, 8, 9, "OracleCFS", probe_ocfs },
- { "ocfs2", 1, 0, 6, "OCFSV2", probe_ocfs2 },
- { "ocfs2", 2, 0, 6, "OCFSV2", probe_ocfs2 },
- { "ocfs2", 4, 0, 6, "OCFSV2", probe_ocfs2 },
- { "ocfs2", 8, 0, 6, "OCFSV2", probe_ocfs2 },
- { NULL, 0, 0, 0, NULL, NULL }
-};
-
-/*
- * Verify that the data in dev is consistent with what is on the actual
- * block device (using the devname field only). Normally this will be
- * called when finding items in the cache, but for long running processes
- * is also desirable to revalidate an item before use.
- *
- * If we are unable to revalidate the data, we return the old data and
- * do not set the BLKID_BID_FL_VERIFIED flag on it.
- */
-blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
-{
- const struct blkid_magic *id;
- unsigned char *bufs[BLKID_BLK_OFFS + 1], *buf;
- const char *type;
- struct stat st;
- time_t diff, now;
- int fd, idx;
-
- if (!dev)
- return NULL;
-
- now = time(NULL);
- diff = now - dev->bid_time;
-
- if ((now < dev->bid_time) ||
- (diff < BLKID_PROBE_MIN) ||
- (dev->bid_flags & BLKID_BID_FL_VERIFIED &&
- diff < BLKID_PROBE_INTERVAL))
- return dev;
-
- DBG(DEBUG_PROBE,
- printf("need to revalidate %s (time since last check %lu)\n",
- dev->bid_name, diff));
-
- fd = open(dev->bid_name, O_RDONLY);
- if (fd < 0
- || fstat(fd, &st) < 0
- ) {
- if (fd >= 0)
- close(fd);
- if (errno == ENXIO || errno == ENODEV || errno == ENOENT) {
- blkid_free_dev(dev);
- return NULL;
- }
- /* We don't have read permission, just return cache data. */
- DBG(DEBUG_PROBE,
- printf("returning unverified data for %s\n",
- dev->bid_name));
- return dev;
- }
-
- memset(bufs, 0, sizeof(bufs));
-
- /*
- * Iterate over the type array. If we already know the type,
- * then try that first. If it doesn't work, then blow away
- * the type information, and try again.
- *
- */
-try_again:
- type = 0;
- if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) {
- uuid_t uuid;
-
- if (check_mdraid(fd, uuid) == 0) {
- set_uuid(dev, uuid);
- type = "mdraid";
- goto found_type;
- }
- }
- for (id = type_array; id->bim_type; id++) {
- if (dev->bid_type &&
- strcmp(id->bim_type, dev->bid_type))
- continue;
-
- idx = id->bim_kboff + (id->bim_sboff >> 10);
- if (idx > BLKID_BLK_OFFS || idx < 0)
- continue;
- buf = bufs[idx];
- if (!buf) {
- if (lseek(fd, idx << 10, SEEK_SET) < 0)
- continue;
-
- buf = xmalloc(1024);
-
- if (read(fd, buf, 1024) != 1024) {
- free(buf);
- continue;
- }
- bufs[idx] = buf;
- }
-
- if (memcmp(id->bim_magic, buf + (id->bim_sboff&0x3ff),
- id->bim_len))
- continue;
-
- if ((id->bim_probe == NULL) ||
- (id->bim_probe(fd, cache, dev, id, buf) == 0)) {
- type = id->bim_type;
- goto found_type;
- }
- }
-
- if (!id->bim_type && dev->bid_type) {
- /*
- * Zap the device filesystem type and try again
- */
- blkid_set_tag(dev, "TYPE", 0, 0);
- blkid_set_tag(dev, "SEC_TYPE", 0, 0);
- blkid_set_tag(dev, "LABEL", 0, 0);
- blkid_set_tag(dev, "UUID", 0, 0);
- goto try_again;
- }
-
- if (!dev->bid_type) {
- blkid_free_dev(dev);
- close(fd);
- return NULL;
- }
-
-found_type:
- if (dev && type) {
- dev->bid_devno = st.st_rdev;
- dev->bid_time = time(NULL);
- dev->bid_flags |= BLKID_BID_FL_VERIFIED;
- cache->bic_flags |= BLKID_BIC_FL_CHANGED;
-
- blkid_set_tag(dev, "TYPE", type, 0);
-
- DBG(DEBUG_PROBE, printf("%s: devno 0x%04llx, type %s\n",
- dev->bid_name, st.st_rdev, type));
- }
-
- close(fd);
-
- return dev;
-}
-
-int blkid_known_fstype(const char *fstype)
-{
- const struct blkid_magic *id;
-
- for (id = type_array; id->bim_type; id++) {
- if (strcmp(fstype, id->bim_type) == 0)
- return 1;
- }
- return 0;
-}
-
-#ifdef TEST_PROGRAM
-int main(int argc, char **argv)
-{
- blkid_dev dev;
- blkid_cache cache;
- int ret;
-
- blkid_debug_mask = DEBUG_ALL;
- if (argc != 2) {
- fprintf(stderr, "Usage: %s device\n"
- "Probe a single device to determine type\n", argv[0]);
- exit(1);
- }
- if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
- fprintf(stderr, "%s: error creating cache (%d)\n",
- argv[0], ret);
- exit(1);
- }
- dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL);
- if (!dev) {
- printf("%s: %s has an unsupported type\n", argv[0], argv[1]);
- return 1;
- }
- printf("%s is type %s\n", argv[1], dev->bid_type ?
- dev->bid_type : "(null)");
- if (dev->bid_label)
- printf("\tlabel is '%s'\n", dev->bid_label);
- if (dev->bid_uuid)
- printf("\tuuid is %s\n", dev->bid_uuid);
-
- blkid_free_dev(dev);
- return 0;
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/probe.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/probe.h
deleted file mode 100644
index b6d8f8e7dd..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/probe.h
+++ /dev/null
@@ -1,374 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * probe.h - constants and on-disk structures for extracting device data
- *
- * Copyright (C) 1999 by Andries Brouwer
- * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
- * Copyright (C) 2001 by Andreas Dilger
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-#ifndef BLKID_PROBE_H
-#define BLKID_PROBE_H 1
-
-#include <linux/types.h>
-
-struct blkid_magic;
-
-typedef int (*blkid_probe_t)(int fd, blkid_cache cache, blkid_dev dev,
- const struct blkid_magic *id, unsigned char *buf);
-
-struct blkid_magic {
- const char *bim_type; /* type name for this magic */
- long bim_kboff; /* kilobyte offset of superblock */
- unsigned bim_sboff; /* byte offset within superblock */
- unsigned bim_len; /* length of magic */
- const char *bim_magic; /* magic string */
- blkid_probe_t bim_probe; /* probe function */
-};
-
-/*
- * Structures for each of the content types we want to extract information
- * from. We do not necessarily need the magic field here, because we have
- * already identified the content type before we get this far. It may still
- * be useful if there are probe functions which handle multiple content types.
- */
-struct ext2_super_block {
- __u32 s_inodes_count;
- __u32 s_blocks_count;
- __u32 s_r_blocks_count;
- __u32 s_free_blocks_count;
- __u32 s_free_inodes_count;
- __u32 s_first_data_block;
- __u32 s_log_block_size;
- __u32 s_dummy3[7];
- unsigned char s_magic[2];
- __u16 s_state;
- __u32 s_dummy5[8];
- __u32 s_feature_compat;
- __u32 s_feature_incompat;
- __u32 s_feature_ro_compat;
- unsigned char s_uuid[16];
- char s_volume_name[16];
-};
-#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x00000004
-#define EXT3_FEATURE_INCOMPAT_RECOVER 0x00000004
-#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x00000008
-
-struct xfs_super_block {
- unsigned char xs_magic[4];
- __u32 xs_blocksize;
- __u64 xs_dblocks;
- __u64 xs_rblocks;
- __u32 xs_dummy1[2];
- unsigned char xs_uuid[16];
- __u32 xs_dummy2[15];
- char xs_fname[12];
- __u32 xs_dummy3[2];
- __u64 xs_icount;
- __u64 xs_ifree;
- __u64 xs_fdblocks;
-};
-
-struct reiserfs_super_block {
- __u32 rs_blocks_count;
- __u32 rs_free_blocks;
- __u32 rs_root_block;
- __u32 rs_journal_block;
- __u32 rs_journal_dev;
- __u32 rs_orig_journal_size;
- __u32 rs_dummy2[5];
- __u16 rs_blocksize;
- __u16 rs_dummy3[3];
- unsigned char rs_magic[12];
- __u32 rs_dummy4[5];
- unsigned char rs_uuid[16];
- char rs_label[16];
-};
-
-struct jfs_super_block {
- unsigned char js_magic[4];
- __u32 js_version;
- __u64 js_size;
- __u32 js_bsize;
- __u32 js_dummy1;
- __u32 js_pbsize;
- __u32 js_dummy2[27];
- unsigned char js_uuid[16];
- unsigned char js_label[16];
- unsigned char js_loguuid[16];
-};
-
-struct romfs_super_block {
- unsigned char ros_magic[8];
- __u32 ros_dummy1[2];
- unsigned char ros_volume[16];
-};
-
-struct cramfs_super_block {
- __u8 magic[4];
- __u32 size;
- __u32 flags;
- __u32 future;
- __u8 signature[16];
- struct cramfs_info {
- __u32 crc;
- __u32 edition;
- __u32 blocks;
- __u32 files;
- } info;
- __u8 name[16];
-};
-
-struct swap_id_block {
-/* unsigned char sws_boot[1024]; */
- __u32 sws_version;
- __u32 sws_lastpage;
- __u32 sws_nrbad;
- unsigned char sws_uuid[16];
- char sws_volume[16];
- unsigned char sws_pad[117];
- __u32 sws_badpg;
-};
-
-/* Yucky misaligned values */
-struct vfat_super_block {
-/* 00*/ unsigned char vs_ignored[3];
-/* 03*/ unsigned char vs_sysid[8];
-/* 0b*/ unsigned char vs_sector_size[2];
-/* 0d*/ __u8 vs_cluster_size;
-/* 0e*/ __u16 vs_reserved;
-/* 10*/ __u8 vs_fats;
-/* 11*/ unsigned char vs_dir_entries[2];
-/* 13*/ unsigned char vs_sectors[2];
-/* 15*/ unsigned char vs_media;
-/* 16*/ __u16 vs_fat_length;
-/* 18*/ __u16 vs_secs_track;
-/* 1a*/ __u16 vs_heads;
-/* 1c*/ __u32 vs_hidden;
-/* 20*/ __u32 vs_total_sect;
-/* 24*/ __u32 vs_fat32_length;
-/* 28*/ __u16 vs_flags;
-/* 2a*/ __u8 vs_version[2];
-/* 2c*/ __u32 vs_root_cluster;
-/* 30*/ __u16 vs_insfo_sector;
-/* 32*/ __u16 vs_backup_boot;
-/* 34*/ __u16 vs_reserved2[6];
-/* 40*/ unsigned char vs_unknown[3];
-/* 43*/ unsigned char vs_serno[4];
-/* 47*/ char vs_label[11];
-/* 52*/ unsigned char vs_magic[8];
-/* 5a*/ unsigned char vs_dummy2[164];
-/*1fe*/ unsigned char vs_pmagic[2];
-};
-
-/* Yucky misaligned values */
-struct msdos_super_block {
-/* 00*/ unsigned char ms_ignored[3];
-/* 03*/ unsigned char ms_sysid[8];
-/* 0b*/ unsigned char ms_sector_size[2];
-/* 0d*/ __u8 ms_cluster_size;
-/* 0e*/ __u16 ms_reserved;
-/* 10*/ __u8 ms_fats;
-/* 11*/ unsigned char ms_dir_entries[2];
-/* 13*/ unsigned char ms_sectors[2];
-/* 15*/ unsigned char ms_media;
-/* 16*/ __u16 ms_fat_length;
-/* 18*/ __u16 ms_secs_track;
-/* 1a*/ __u16 ms_heads;
-/* 1c*/ __u32 ms_hidden;
-/* 20*/ __u32 ms_total_sect;
-/* 24*/ unsigned char ms_unknown[3];
-/* 27*/ unsigned char ms_serno[4];
-/* 2b*/ char ms_label[11];
-/* 36*/ unsigned char ms_magic[8];
-/* 3d*/ unsigned char ms_dummy2[192];
-/*1fe*/ unsigned char ms_pmagic[2];
-};
-
-struct minix_super_block {
- __u16 ms_ninodes;
- __u16 ms_nzones;
- __u16 ms_imap_blocks;
- __u16 ms_zmap_blocks;
- __u16 ms_firstdatazone;
- __u16 ms_log_zone_size;
- __u32 ms_max_size;
- unsigned char ms_magic[2];
- __u16 ms_state;
- __u32 ms_zones;
-};
-
-struct mdp_superblock_s {
- __u32 md_magic;
- __u32 major_version;
- __u32 minor_version;
- __u32 patch_version;
- __u32 gvalid_words;
- __u32 set_uuid0;
- __u32 ctime;
- __u32 level;
- __u32 size;
- __u32 nr_disks;
- __u32 raid_disks;
- __u32 md_minor;
- __u32 not_persistent;
- __u32 set_uuid1;
- __u32 set_uuid2;
- __u32 set_uuid3;
-};
-
-struct hfs_super_block {
- char h_magic[2];
- char h_dummy[18];
- __u32 h_blksize;
-};
-
-struct ocfs_volume_header {
- unsigned char minor_version[4];
- unsigned char major_version[4];
- unsigned char signature[128];
- char mount[128];
- unsigned char mount_len[2];
-};
-
-struct ocfs_volume_label {
- unsigned char disk_lock[48];
- char label[64];
- unsigned char label_len[2];
- unsigned char vol_id[16];
- unsigned char vol_id_len[2];
-};
-
-#define ocfsmajor(o) ((__u32)o.major_version[0] \
- + (((__u32) o.major_version[1]) << 8) \
- + (((__u32) o.major_version[2]) << 16) \
- + (((__u32) o.major_version[3]) << 24))
-#define ocfslabellen(o) ((__u32)o.label_len[0] + (((__u32) o.label_len[1]) << 8))
-#define ocfsmountlen(o) ((__u32)o.mount_len[0] + (((__u32) o.mount_len[1])<<8))
-
-#define OCFS_MAGIC "OracleCFS"
-
-struct ocfs2_super_block {
- unsigned char signature[8];
- unsigned char s_dummy1[184];
- unsigned char s_dummy2[80];
- char s_label[64];
- unsigned char s_uuid[16];
-};
-
-#define OCFS2_MIN_BLOCKSIZE 512
-#define OCFS2_MAX_BLOCKSIZE 4096
-
-#define OCFS2_SUPER_BLOCK_BLKNO 2
-
-#define OCFS2_SUPER_BLOCK_SIGNATURE "OCFSV2"
-
-struct oracle_asm_disk_label {
- char dummy[32];
- char dl_tag[8];
- char dl_id[24];
-};
-
-#define ORACLE_ASM_DISK_LABEL_MARKED "ORCLDISK"
-#define ORACLE_ASM_DISK_LABEL_OFFSET 32
-
-#define ISODCL(from, to) (to - from + 1)
-struct iso_volume_descriptor {
- char type[ISODCL(1,1)]; /* 711 */
- char id[ISODCL(2,6)];
- char version[ISODCL(7,7)];
- char data[ISODCL(8,2048)];
-};
-
-/*
- * Byte swap functions
- */
-#ifdef __GNUC__
-#define _INLINE_ static __inline__
-#else /* For Watcom C */
-#define _INLINE_ static inline
-#endif
-
-static __u16 blkid_swab16(__u16 val);
-static __u32 blkid_swab32(__u32 val);
-static __u64 blkid_swab64(__u64 val);
-
-#if ((defined __GNUC__) && \
- (defined(__i386__) || defined(__i486__) || defined(__i586__)))
-
-#define _BLKID_HAVE_ASM_BITOPS_
-
-_INLINE_ __u32 blkid_swab32(__u32 val)
-{
-#ifdef EXT2FS_REQUIRE_486
- __asm__("bswap %0" : "=r" (val) : "0" (val));
-#else
- __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
- "rorl $16,%0\n\t" /* swap words */
- "xchgb %b0,%h0" /* swap higher bytes */
- :"=q" (val)
- : "0" (val));
-#endif
- return val;
-}
-
-_INLINE_ __u16 blkid_swab16(__u16 val)
-{
- __asm__("xchgb %b0,%h0" /* swap bytes */
- : "=q" (val)
- : "0" (val));
- return val;
-}
-
-_INLINE_ __u64 blkid_swab64(__u64 val)
-{
- return blkid_swab32(val >> 32) |
- ( ((__u64)blkid_swab32((__u32)val)) << 32 );
-}
-#endif
-
-#if !defined(_BLKID_HAVE_ASM_BITOPS_)
-
-_INLINE_ __u16 blkid_swab16(__u16 val)
-{
- return (val >> 8) | (val << 8);
-}
-
-_INLINE_ __u32 blkid_swab32(__u32 val)
-{
- return (val>>24) | ((val>>8) & 0xFF00) |
- ((val<<8) & 0xFF0000) | (val<<24);
-}
-
-_INLINE_ __u64 blkid_swab64(__u64 val)
-{
- return blkid_swab32(val >> 32) |
- ( ((__u64)blkid_swab32((__u32)val)) << 32 );
-}
-#endif
-
-
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-#define blkid_le16(x) blkid_swab16(x)
-#define blkid_le32(x) blkid_swab32(x)
-#define blkid_le64(x) blkid_swab64(x)
-#define blkid_be16(x) (x)
-#define blkid_be32(x) (x)
-#define blkid_be64(x) (x)
-#else
-#define blkid_le16(x) (x)
-#define blkid_le32(x) (x)
-#define blkid_le64(x) (x)
-#define blkid_be16(x) blkid_swab16(x)
-#define blkid_be32(x) blkid_swab32(x)
-#define blkid_be64(x) blkid_swab64(x)
-#endif
-
-#undef _INLINE_
-
-#endif /* _BLKID_PROBE_H */
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/read.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/read.c
deleted file mode 100644
index f795a5d145..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/read.c
+++ /dev/null
@@ -1,459 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * read.c - read the blkid cache from disk, to avoid scanning all devices
- *
- * Copyright (C) 2001, 2003 Theodore Y. Ts'o
- * Copyright (C) 2001 Andreas Dilger
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include "blkidP.h"
-#include "../uuid/uuid.h"
-
-#ifdef HAVE_STRTOULL
-#define __USE_ISOC9X
-#define STRTOULL strtoull /* defined in stdlib.h if you try hard enough */
-#else
-/* FIXME: need to support real strtoull here */
-#define STRTOULL strtoul
-#endif
-
-#include <stdlib.h>
-
-#ifdef TEST_PROGRAM
-#define blkid_debug_dump_dev(dev) (debug_dump_dev(dev))
-static void debug_dump_dev(blkid_dev dev);
-#endif
-
-/*
- * File format:
- *
- * <device [<NAME="value"> ...]>device_name</device>
- *
- * The following tags are required for each entry:
- * <ID="id"> unique (within this file) ID number of this device
- * <TIME="time"> (ascii time_t) time this entry was last read from disk
- * <TYPE="type"> (detected) type of filesystem/data for this partition
- *
- * The following tags may be present, depending on the device contents
- * <LABEL="label"> (user supplied) label (volume name, etc)
- * <UUID="uuid"> (generated) universally unique identifier (serial no)
- */
-
-static char *skip_over_blank(char *cp)
-{
- while (*cp && isspace(*cp))
- cp++;
- return cp;
-}
-
-static char *skip_over_word(char *cp)
-{
- char ch;
-
- while ((ch = *cp)) {
- /* If we see a backslash, skip the next character */
- if (ch == '\\') {
- cp++;
- if (*cp == '\0')
- break;
- cp++;
- continue;
- }
- if (isspace(ch) || ch == '<' || ch == '>')
- break;
- cp++;
- }
- return cp;
-}
-
-static char *strip_line(char *line)
-{
- char *p;
-
- line = skip_over_blank(line);
-
- p = line + strlen(line) - 1;
-
- while (*line) {
- if (isspace(*p))
- *p-- = '\0';
- else
- break;
- }
-
- return line;
-}
-
-/*
- * Start parsing a new line from the cache.
- *
- * line starts with "<device" return 1 -> continue parsing line
- * line starts with "<foo", empty, or # return 0 -> skip line
- * line starts with other, return -BLKID_ERR_CACHE -> error
- */
-static int parse_start(char **cp)
-{
- char *p;
-
- p = strip_line(*cp);
-
- /* Skip comment or blank lines. We can't just NUL the first '#' char,
- * in case it is inside quotes, or escaped.
- */
- if (*p == '\0' || *p == '#')
- return 0;
-
- if (!strncmp(p, "<device", 7)) {
- DBG(DEBUG_READ, printf("found device header: %8s\n", p));
- p += 7;
-
- *cp = p;
- return 1;
- }
-
- if (*p == '<')
- return 0;
-
- return -BLKID_ERR_CACHE;
-}
-
-/* Consume the remaining XML on the line (cosmetic only) */
-static int parse_end(char **cp)
-{
- *cp = skip_over_blank(*cp);
-
- if (!strncmp(*cp, "</device>", 9)) {
- DBG(DEBUG_READ, printf("found device trailer %9s\n", *cp));
- *cp += 9;
- return 0;
- }
-
- return -BLKID_ERR_CACHE;
-}
-
-/*
- * Allocate a new device struct with device name filled in. Will handle
- * finding the device on lines of the form:
- * <device foo=bar>devname</device>
- * <device>devname<foo>bar</foo></device>
- */
-static int parse_dev(blkid_cache cache, blkid_dev *dev, char **cp)
-{
- char *start, *tmp, *end, *name;
- int ret;
-
- if ((ret = parse_start(cp)) <= 0)
- return ret;
-
- start = tmp = strchr(*cp, '>');
- if (!start) {
- DBG(DEBUG_READ,
- printf("blkid: short line parsing dev: %s\n", *cp));
- return -BLKID_ERR_CACHE;
- }
- start = skip_over_blank(start + 1);
- end = skip_over_word(start);
-
- DBG(DEBUG_READ, printf("device should be %*s\n", end - start, start));
-
- if (**cp == '>')
- *cp = end;
- else
- (*cp)++;
-
- *tmp = '\0';
-
- if (!(tmp = strrchr(end, '<')) || parse_end(&tmp) < 0) {
- DBG(DEBUG_READ,
- printf("blkid: missing </device> ending: %s\n", end));
- } else if (tmp)
- *tmp = '\0';
-
- if (end - start <= 1) {
- DBG(DEBUG_READ, printf("blkid: empty device name: %s\n", *cp));
- return -BLKID_ERR_CACHE;
- }
-
- name = blkid_strndup(start, end-start);
- if (name == NULL)
- return -BLKID_ERR_MEM;
-
- DBG(DEBUG_READ, printf("found dev %s\n", name));
-
- if (!(*dev = blkid_get_dev(cache, name, BLKID_DEV_CREATE)))
- return -BLKID_ERR_MEM;
-
- free(name);
- return 1;
-}
-
-/*
- * Extract a tag of the form NAME="value" from the line.
- */
-static int parse_token(char **name, char **value, char **cp)
-{
- char *end;
-
- if (!name || !value || !cp)
- return -BLKID_ERR_PARAM;
-
- if (!(*value = strchr(*cp, '=')))
- return 0;
-
- **value = '\0';
- *name = strip_line(*cp);
- *value = skip_over_blank(*value + 1);
-
- if (**value == '"') {
- end = strchr(*value + 1, '"');
- if (!end) {
- DBG(DEBUG_READ,
- printf("unbalanced quotes at: %s\n", *value));
- *cp = *value;
- return -BLKID_ERR_CACHE;
- }
- (*value)++;
- *end = '\0';
- end++;
- } else {
- end = skip_over_word(*value);
- if (*end) {
- *end = '\0';
- end++;
- }
- }
- *cp = end;
-
- return 1;
-}
-
-/*
- * Extract a tag of the form <NAME>value</NAME> from the line.
- */
-/*
-static int parse_xml(char **name, char **value, char **cp)
-{
- char *end;
-
- if (!name || !value || !cp)
- return -BLKID_ERR_PARAM;
-
- *name = strip_line(*cp);
-
- if ((*name)[0] != '<' || (*name)[1] == '/')
- return 0;
-
- FIXME: finish this.
-}
-*/
-
-/*
- * Extract a tag from the line.
- *
- * Return 1 if a valid tag was found.
- * Return 0 if no tag found.
- * Return -ve error code.
- */
-static int parse_tag(blkid_cache cache, blkid_dev dev, char **cp)
-{
- char *name;
- char *value;
- int ret;
-
- if (!cache || !dev)
- return -BLKID_ERR_PARAM;
-
- if ((ret = parse_token(&name, &value, cp)) <= 0 /* &&
- (ret = parse_xml(&name, &value, cp)) <= 0 */)
- return ret;
-
- /* Some tags are stored directly in the device struct */
- if (!strcmp(name, "DEVNO"))
- dev->bid_devno = STRTOULL(value, 0, 0);
- else if (!strcmp(name, "PRI"))
- dev->bid_pri = strtol(value, 0, 0);
- else if (!strcmp(name, "TIME"))
- /* FIXME: need to parse a long long eventually */
- dev->bid_time = strtol(value, 0, 0);
- else
- ret = blkid_set_tag(dev, name, value, strlen(value));
-
- DBG(DEBUG_READ, printf(" tag: %s=\"%s\"\n", name, value));
-
- return ret < 0 ? ret : 1;
-}
-
-/*
- * Parse a single line of data, and return a newly allocated dev struct.
- * Add the new device to the cache struct, if one was read.
- *
- * Lines are of the form <device [TAG="value" ...]>/dev/foo</device>
- *
- * Returns -ve value on error.
- * Returns 0 otherwise.
- * If a valid device was read, *dev_p is non-NULL, otherwise it is NULL
- * (e.g. comment lines, unknown XML content, etc).
- */
-static int blkid_parse_line(blkid_cache cache, blkid_dev *dev_p, char *cp)
-{
- blkid_dev dev;
- int ret;
-
- if (!cache || !dev_p)
- return -BLKID_ERR_PARAM;
-
- *dev_p = NULL;
-
- DBG(DEBUG_READ, printf("line: %s\n", cp));
-
- if ((ret = parse_dev(cache, dev_p, &cp)) <= 0)
- return ret;
-
- dev = *dev_p;
-
- while ((ret = parse_tag(cache, dev, &cp)) > 0) {
- ;
- }
-
- if (dev->bid_type == NULL) {
- DBG(DEBUG_READ,
- printf("blkid: device %s has no TYPE\n",dev->bid_name));
- blkid_free_dev(dev);
- }
-
- DBG(DEBUG_READ, blkid_debug_dump_dev(dev));
-
- return ret;
-}
-
-/*
- * Parse the specified filename, and return the data in the supplied or
- * a newly allocated cache struct. If the file doesn't exist, return a
- * new empty cache struct.
- */
-void blkid_read_cache(blkid_cache cache)
-{
- FILE *file;
- char buf[4096];
- int fd, lineno = 0;
- struct stat st;
-
- if (!cache)
- return;
-
- /*
- * If the file doesn't exist, then we just return an empty
- * struct so that the cache can be populated.
- */
- if ((fd = open(cache->bic_filename, O_RDONLY)) < 0)
- return;
- if (fstat(fd, &st) < 0)
- goto errout;
- if ((st.st_mtime == cache->bic_ftime) ||
- (cache->bic_flags & BLKID_BIC_FL_CHANGED)) {
- DBG(DEBUG_CACHE, printf("skipping re-read of %s\n",
- cache->bic_filename));
- goto errout;
- }
-
- DBG(DEBUG_CACHE, printf("reading cache file %s\n",
- cache->bic_filename));
-
- file = xfdopen_for_read(fd);
-
- while (fgets(buf, sizeof(buf), file)) {
- blkid_dev dev;
- unsigned int end;
-
- lineno++;
- if (buf[0] == 0)
- continue;
- end = strlen(buf) - 1;
- /* Continue reading next line if it ends with a backslash */
- while (buf[end] == '\\' && end < sizeof(buf) - 2 &&
- fgets(buf + end, sizeof(buf) - end, file)) {
- end = strlen(buf) - 1;
- lineno++;
- }
-
- if (blkid_parse_line(cache, &dev, buf) < 0) {
- DBG(DEBUG_READ,
- printf("blkid: bad format on line %d\n", lineno));
- continue;
- }
- }
- fclose(file);
-
- /*
- * Initially we do not need to write out the cache file.
- */
- cache->bic_flags &= ~BLKID_BIC_FL_CHANGED;
- cache->bic_ftime = st.st_mtime;
-
- return;
-errout:
- close(fd);
-}
-
-#ifdef TEST_PROGRAM
-static void debug_dump_dev(blkid_dev dev)
-{
- struct list_head *p;
-
- if (!dev) {
- printf(" dev: NULL\n");
- return;
- }
-
- printf(" dev: name = %s\n", dev->bid_name);
- printf(" dev: DEVNO=\"0x%0llx\"\n", dev->bid_devno);
- printf(" dev: TIME=\"%lu\"\n", dev->bid_time);
- printf(" dev: PRI=\"%d\"\n", dev->bid_pri);
- printf(" dev: flags = 0x%08X\n", dev->bid_flags);
-
- list_for_each(p, &dev->bid_tags) {
- blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
- if (tag)
- printf(" tag: %s=\"%s\"\n", tag->bit_name,
- tag->bit_val);
- else
- printf(" tag: NULL\n");
- }
- bb_putchar('\n');
-}
-
-int main(int argc, char**argv)
-{
- blkid_cache cache = NULL;
- int ret;
-
- blkid_debug_mask = DEBUG_ALL;
- if (argc > 2) {
- fprintf(stderr, "Usage: %s [filename]\n"
- "Test parsing of the cache (filename)\n", argv[0]);
- exit(1);
- }
- if ((ret = blkid_get_cache(&cache, argv[1])) < 0)
- fprintf(stderr, "error %d reading cache file %s\n", ret,
- argv[1] ? argv[1] : BLKID_CACHE_FILE);
-
- blkid_put_cache(cache);
-
- return ret;
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/resolve.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/resolve.c
deleted file mode 100644
index 295ca61bff..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/resolve.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * resolve.c - resolve names and tags into specific devices
- *
- * Copyright (C) 2001, 2003 Theodore Ts'o.
- * Copyright (C) 2001 Andreas Dilger
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <stdlib.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "blkidP.h"
-#include "probe.h"
-
-/*
- * Find a tagname (e.g. LABEL or UUID) on a specific device.
- */
-char *blkid_get_tag_value(blkid_cache cache, const char *tagname,
- const char *devname)
-{
- blkid_tag found;
- blkid_dev dev;
- blkid_cache c = cache;
- char *ret = NULL;
-
- DBG(DEBUG_RESOLVE, printf("looking for %s on %s\n", tagname, devname));
-
- if (!devname)
- return NULL;
-
- if (!cache) {
- if (blkid_get_cache(&c, NULL) < 0)
- return NULL;
- }
-
- if ((dev = blkid_get_dev(c, devname, BLKID_DEV_NORMAL)) &&
- (found = blkid_find_tag_dev(dev, tagname)))
- ret = blkid_strdup(found->bit_val);
-
- if (!cache)
- blkid_put_cache(c);
-
- return ret;
-}
-
-/*
- * Locate a device name from a token (NAME=value string), or (name, value)
- * pair. In the case of a token, value is ignored. If the "token" is not
- * of the form "NAME=value" and there is no value given, then it is assumed
- * to be the actual devname and a copy is returned.
- */
-char *blkid_get_devname(blkid_cache cache, const char *token,
- const char *value)
-{
- blkid_dev dev;
- blkid_cache c = cache;
- char *t = NULL, *v = NULL;
- char *ret = NULL;
-
- if (!token)
- return NULL;
-
- if (!cache) {
- if (blkid_get_cache(&c, NULL) < 0)
- return NULL;
- }
-
- DBG(DEBUG_RESOLVE,
- printf("looking for %s%s%s %s\n", token, value ? "=" : "",
- value ? value : "", cache ? "in cache" : "from disk"));
-
- if (!value) {
- if (!strchr(token, '='))
- return blkid_strdup(token);
- blkid_parse_tag_string(token, &t, &v);
- if (!t || !v)
- goto errout;
- token = t;
- value = v;
- }
-
- dev = blkid_find_dev_with_tag(c, token, value);
- if (!dev)
- goto errout;
-
- ret = blkid_strdup(blkid_dev_devname(dev));
-
-errout:
- free(t);
- free(v);
- if (!cache) {
- blkid_put_cache(c);
- }
- return ret;
-}
-
-#ifdef TEST_PROGRAM
-int main(int argc, char **argv)
-{
- char *value;
- blkid_cache cache;
-
- blkid_debug_mask = DEBUG_ALL;
- if (argc != 2 && argc != 3) {
- fprintf(stderr, "Usage:\t%s tagname=value\n"
- "\t%s tagname devname\n"
- "Find which device holds a given token or\n"
- "Find what the value of a tag is in a device\n",
- argv[0], argv[0]);
- exit(1);
- }
- if (blkid_get_cache(&cache, bb_dev_null) < 0) {
- fprintf(stderr, "Can't get blkid cache\n");
- exit(1);
- }
-
- if (argv[2]) {
- value = blkid_get_tag_value(cache, argv[1], argv[2]);
- printf("%s has tag %s=%s\n", argv[2], argv[1],
- value ? value : "<missing>");
- } else {
- value = blkid_get_devname(cache, argv[1], NULL);
- printf("%s has tag %s\n", value ? value : "<none>", argv[1]);
- }
- blkid_put_cache(cache);
- return value ? 0 : 1;
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/save.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/save.c
deleted file mode 100644
index e60cca445f..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/save.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * save.c - write the cache struct to disk
- *
- * Copyright (C) 2001 by Andreas Dilger
- * Copyright (C) 2003 Theodore Ts'o
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_MKDEV_H
-#include <sys/mkdev.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include "blkidP.h"
-
-static int save_dev(blkid_dev dev, FILE *file)
-{
- struct list_head *p;
-
- if (!dev || dev->bid_name[0] != '/')
- return 0;
-
- DBG(DEBUG_SAVE,
- printf("device %s, type %s\n", dev->bid_name, dev->bid_type));
-
- fprintf(file,
- "<device DEVNO=\"0x%04lx\" TIME=\"%lu\"",
- (unsigned long) dev->bid_devno, dev->bid_time);
- if (dev->bid_pri)
- fprintf(file, " PRI=\"%d\"", dev->bid_pri);
- list_for_each(p, &dev->bid_tags) {
- blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
- fprintf(file, " %s=\"%s\"", tag->bit_name,tag->bit_val);
- }
- fprintf(file, ">%s</device>\n", dev->bid_name);
-
- return 0;
-}
-
-/*
- * Write out the cache struct to the cache file on disk.
- */
-int blkid_flush_cache(blkid_cache cache)
-{
- struct list_head *p;
- char *tmp = NULL;
- const char *opened = NULL;
- const char *filename;
- FILE *file = NULL;
- int fd, ret = 0;
- struct stat st;
-
- if (!cache)
- return -BLKID_ERR_PARAM;
-
- if (list_empty(&cache->bic_devs) ||
- !(cache->bic_flags & BLKID_BIC_FL_CHANGED)) {
- DBG(DEBUG_SAVE, printf("skipping cache file write\n"));
- return 0;
- }
-
- filename = cache->bic_filename ? cache->bic_filename: BLKID_CACHE_FILE;
-
- /* If we can't write to the cache file, then don't even try */
- if (((ret = stat(filename, &st)) < 0 && errno != ENOENT) ||
- (ret == 0 && access(filename, W_OK) < 0)) {
- DBG(DEBUG_SAVE,
- printf("can't write to cache file %s\n", filename));
- return 0;
- }
-
- /*
- * Try and create a temporary file in the same directory so
- * that in case of error we don't overwrite the cache file.
- * If the cache file doesn't yet exist, it isn't a regular
- * file (e.g. /dev/null or a socket), or we couldn't create
- * a temporary file then we open it directly.
- */
- if (ret == 0 && S_ISREG(st.st_mode)) {
- tmp = xmalloc(strlen(filename) + 8);
- sprintf(tmp, "%s-XXXXXX", filename);
- fd = mkstemp(tmp);
- if (fd >= 0) {
- file = xfdopen_for_write(fd);
- opened = tmp;
- }
- fchmod(fd, 0644);
- }
-
- if (!file) {
- file = fopen_for_write(filename);
- opened = filename;
- }
-
- DBG(DEBUG_SAVE,
- printf("writing cache file %s (really %s)\n",
- filename, opened));
-
- if (!file) {
- ret = errno;
- goto errout;
- }
-
- list_for_each(p, &cache->bic_devs) {
- blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs);
- if (!dev->bid_type)
- continue;
- if ((ret = save_dev(dev, file)) < 0)
- break;
- }
-
- if (ret >= 0) {
- cache->bic_flags &= ~BLKID_BIC_FL_CHANGED;
- ret = 1;
- }
-
- fclose(file);
- if (opened != filename) {
- if (ret < 0) {
- unlink(opened);
- DBG(DEBUG_SAVE,
- printf("unlinked temp cache %s\n", opened));
- } else {
- char *backup;
-
- backup = xmalloc(strlen(filename) + 5);
- sprintf(backup, "%s.old", filename);
- unlink(backup);
- link(filename, backup);
- free(backup);
- rename(opened, filename);
- DBG(DEBUG_SAVE,
- printf("moved temp cache %s\n", opened));
- }
- }
-
-errout:
- free(tmp);
- return ret;
-}
-
-#ifdef TEST_PROGRAM
-int main(int argc, char **argv)
-{
- blkid_cache cache = NULL;
- int ret;
-
- blkid_debug_mask = DEBUG_ALL;
- if (argc > 2) {
- fprintf(stderr, "Usage: %s [filename]\n"
- "Test loading/saving a cache (filename)\n", argv[0]);
- exit(1);
- }
-
- if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
- fprintf(stderr, "%s: error creating cache (%d)\n",
- argv[0], ret);
- exit(1);
- }
- if ((ret = blkid_probe_all(cache)) < 0) {
- fprintf(stderr, "error (%d) probing devices\n", ret);
- exit(1);
- }
- cache->bic_filename = blkid_strdup(argv[1]);
-
- if ((ret = blkid_flush_cache(cache)) < 0) {
- fprintf(stderr, "error (%d) saving cache\n", ret);
- exit(1);
- }
-
- blkid_put_cache(cache);
-
- return ret;
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/tag.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/tag.c
deleted file mode 100644
index 8337b46b6b..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/tag.c
+++ /dev/null
@@ -1,431 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * tag.c - allocation/initialization/free routines for tag structs
- *
- * Copyright (C) 2001 Andreas Dilger
- * Copyright (C) 2003 Theodore Ts'o
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- * %End-Header%
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "blkidP.h"
-
-static blkid_tag blkid_new_tag(void)
-{
- blkid_tag tag;
-
- tag = xzalloc(sizeof(struct blkid_struct_tag));
-
- INIT_LIST_HEAD(&tag->bit_tags);
- INIT_LIST_HEAD(&tag->bit_names);
-
- return tag;
-}
-
-#ifdef CONFIG_BLKID_DEBUG
-void blkid_debug_dump_tag(blkid_tag tag)
-{
- if (!tag) {
- printf(" tag: NULL\n");
- return;
- }
-
- printf(" tag: %s=\"%s\"\n", tag->bit_name, tag->bit_val);
-}
-#endif
-
-void blkid_free_tag(blkid_tag tag)
-{
- if (!tag)
- return;
-
- DBG(DEBUG_TAG, printf(" freeing tag %s=%s\n", tag->bit_name,
- tag->bit_val ? tag->bit_val : "(NULL)"));
- DBG(DEBUG_TAG, blkid_debug_dump_tag(tag));
-
- list_del(&tag->bit_tags); /* list of tags for this device */
- list_del(&tag->bit_names); /* list of tags with this type */
-
- free(tag->bit_name);
- free(tag->bit_val);
- free(tag);
-}
-
-/*
- * Find the desired tag on a device. If value is NULL, then the
- * first such tag is returned, otherwise return only exact tag if found.
- */
-blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type)
-{
- struct list_head *p;
-
- if (!dev || !type)
- return NULL;
-
- list_for_each(p, &dev->bid_tags) {
- blkid_tag tmp = list_entry(p, struct blkid_struct_tag,
- bit_tags);
-
- if (!strcmp(tmp->bit_name, type))
- return tmp;
- }
- return NULL;
-}
-
-/*
- * Find the desired tag type in the cache.
- * We return the head tag for this tag type.
- */
-static blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type)
-{
- blkid_tag head = NULL, tmp;
- struct list_head *p;
-
- if (!cache || !type)
- return NULL;
-
- list_for_each(p, &cache->bic_tags) {
- tmp = list_entry(p, struct blkid_struct_tag, bit_tags);
- if (!strcmp(tmp->bit_name, type)) {
- DBG(DEBUG_TAG,
- printf(" found cache tag head %s\n", type));
- head = tmp;
- break;
- }
- }
- return head;
-}
-
-/*
- * Set a tag on an existing device.
- *
- * If value is NULL, then delete the tagsfrom the device.
- */
-int blkid_set_tag(blkid_dev dev, const char *name,
- const char *value, const int vlength)
-{
- blkid_tag t = 0, head = 0;
- char *val = NULL;
-
- if (!dev || !name)
- return -BLKID_ERR_PARAM;
-
- if (!(val = blkid_strndup(value, vlength)) && value)
- return -BLKID_ERR_MEM;
- t = blkid_find_tag_dev(dev, name);
- if (!value) {
- blkid_free_tag(t);
- } else if (t) {
- if (!strcmp(t->bit_val, val)) {
- /* Same thing, exit */
- free(val);
- return 0;
- }
- free(t->bit_val);
- t->bit_val = val;
- } else {
- /* Existing tag not present, add to device */
- if (!(t = blkid_new_tag()))
- goto errout;
- t->bit_name = blkid_strdup(name);
- t->bit_val = val;
- t->bit_dev = dev;
-
- list_add_tail(&t->bit_tags, &dev->bid_tags);
-
- if (dev->bid_cache) {
- head = blkid_find_head_cache(dev->bid_cache,
- t->bit_name);
- if (!head) {
- head = blkid_new_tag();
- if (!head)
- goto errout;
-
- DBG(DEBUG_TAG,
- printf(" creating new cache tag head %s\n", name));
- head->bit_name = blkid_strdup(name);
- if (!head->bit_name)
- goto errout;
- list_add_tail(&head->bit_tags,
- &dev->bid_cache->bic_tags);
- }
- list_add_tail(&t->bit_names, &head->bit_names);
- }
- }
-
- /* Link common tags directly to the device struct */
- if (!strcmp(name, "TYPE"))
- dev->bid_type = val;
- else if (!strcmp(name, "LABEL"))
- dev->bid_label = val;
- else if (!strcmp(name, "UUID"))
- dev->bid_uuid = val;
-
- if (dev->bid_cache)
- dev->bid_cache->bic_flags |= BLKID_BIC_FL_CHANGED;
- return 0;
-
-errout:
- blkid_free_tag(t);
- if (!t)
- free(val);
- blkid_free_tag(head);
- return -BLKID_ERR_MEM;
-}
-
-
-/*
- * Parse a "NAME=value" string. This is slightly different than
- * parse_token, because that will end an unquoted value at a space, while
- * this will assume that an unquoted value is the rest of the token (e.g.
- * if we are passed an already quoted string from the command-line we don't
- * have to both quote and escape quote so that the quotes make it to
- * us).
- *
- * Returns 0 on success, and -1 on failure.
- */
-int blkid_parse_tag_string(const char *token, char **ret_type, char **ret_val)
-{
- char *name, *value, *cp;
-
- DBG(DEBUG_TAG, printf("trying to parse '%s' as a tag\n", token));
-
- if (!token || !(cp = strchr(token, '=')))
- return -1;
-
- name = blkid_strdup(token);
- if (!name)
- return -1;
- value = name + (cp - token);
- *value++ = '\0';
- if (*value == '"' || *value == '\'') {
- char c = *value++;
- if (!(cp = strrchr(value, c)))
- goto errout; /* missing closing quote */
- *cp = '\0';
- }
- value = blkid_strdup(value);
- if (!value)
- goto errout;
-
- *ret_type = name;
- *ret_val = value;
-
- return 0;
-
-errout:
- free(name);
- return -1;
-}
-
-/*
- * Tag iteration routines for the public libblkid interface.
- *
- * These routines do not expose the list.h implementation, which are a
- * contamination of the namespace, and which force us to reveal far, far
- * too much of our internal implemenation. I'm not convinced I want
- * to keep list.h in the long term, anyway. It's fine for kernel
- * programming, but performance is not the #1 priority for this
- * library, and I really don't like the tradeoff of type-safety for
- * performance for this application. [tytso:20030125.2007EST]
- */
-
-/*
- * This series of functions iterate over all tags in a device
- */
-#define TAG_ITERATE_MAGIC 0x01a5284c
-
-struct blkid_struct_tag_iterate {
- int magic;
- blkid_dev dev;
- struct list_head *p;
-};
-
-blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev)
-{
- blkid_tag_iterate iter;
-
- iter = xmalloc(sizeof(struct blkid_struct_tag_iterate));
- iter->magic = TAG_ITERATE_MAGIC;
- iter->dev = dev;
- iter->p = dev->bid_tags.next;
- return iter;
-}
-
-/*
- * Return 0 on success, -1 on error
- */
-extern int blkid_tag_next(blkid_tag_iterate iter,
- const char **type, const char **value)
-{
- blkid_tag tag;
-
- *type = 0;
- *value = 0;
- if (!iter || iter->magic != TAG_ITERATE_MAGIC ||
- iter->p == &iter->dev->bid_tags)
- return -1;
- tag = list_entry(iter->p, struct blkid_struct_tag, bit_tags);
- *type = tag->bit_name;
- *value = tag->bit_val;
- iter->p = iter->p->next;
- return 0;
-}
-
-void blkid_tag_iterate_end(blkid_tag_iterate iter)
-{
- if (!iter || iter->magic != TAG_ITERATE_MAGIC)
- return;
- iter->magic = 0;
- free(iter);
-}
-
-/*
- * This function returns a device which matches a particular
- * type/value pair. If there is more than one device that matches the
- * search specification, it returns the one with the highest priority
- * value. This allows us to give preference to EVMS or LVM devices.
- *
- * XXX there should also be an interface which uses an iterator so we
- * can get all of the devices which match a type/value search parameter.
- */
-extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
- const char *type,
- const char *value)
-{
- blkid_tag head;
- blkid_dev dev;
- int pri;
- struct list_head *p;
-
- if (!cache || !type || !value)
- return NULL;
-
- blkid_read_cache(cache);
-
- DBG(DEBUG_TAG, printf("looking for %s=%s in cache\n", type, value));
-
-try_again:
- pri = -1;
- dev = 0;
- head = blkid_find_head_cache(cache, type);
-
- if (head) {
- list_for_each(p, &head->bit_names) {
- blkid_tag tmp = list_entry(p, struct blkid_struct_tag,
- bit_names);
-
- if (!strcmp(tmp->bit_val, value) &&
- tmp->bit_dev->bid_pri > pri) {
- dev = tmp->bit_dev;
- pri = dev->bid_pri;
- }
- }
- }
- if (dev && !(dev->bid_flags & BLKID_BID_FL_VERIFIED)) {
- dev = blkid_verify(cache, dev);
- if (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED))
- goto try_again;
- }
-
- if (!dev && !(cache->bic_flags & BLKID_BIC_FL_PROBED)) {
- if (blkid_probe_all(cache) < 0)
- return NULL;
- goto try_again;
- }
- return dev;
-}
-
-#ifdef TEST_PROGRAM
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#else
-extern char *optarg;
-extern int optind;
-#endif
-
-void usage(char *prog)
-{
- fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask] device "
- "[type value]\n",
- prog);
- fprintf(stderr, "\tList all tags for a device and exit\n", prog);
- exit(1);
-}
-
-int main(int argc, char **argv)
-{
- blkid_tag_iterate iter;
- blkid_cache cache = NULL;
- blkid_dev dev;
- int c, ret, found;
- int flags = BLKID_DEV_FIND;
- char *tmp;
- char *file = NULL;
- char *devname = NULL;
- char *search_type = NULL;
- char *search_value = NULL;
- const char *type, *value;
-
- while ((c = getopt (argc, argv, "m:f:")) != EOF)
- switch (c) {
- case 'f':
- file = optarg;
- break;
- case 'm':
- blkid_debug_mask = strtoul (optarg, &tmp, 0);
- if (*tmp) {
- fprintf(stderr, "Invalid debug mask: %d\n",
- optarg);
- exit(1);
- }
- break;
- case '?':
- usage(argv[0]);
- }
- if (argc > optind)
- devname = argv[optind++];
- if (argc > optind)
- search_type = argv[optind++];
- if (argc > optind)
- search_value = argv[optind++];
- if (!devname || (argc != optind))
- usage(argv[0]);
-
- if ((ret = blkid_get_cache(&cache, file)) != 0) {
- fprintf(stderr, "%s: error creating cache (%d)\n",
- argv[0], ret);
- exit(1);
- }
-
- dev = blkid_get_dev(cache, devname, flags);
- if (!dev) {
- fprintf(stderr, "%s: cannot find device in blkid cache\n");
- exit(1);
- }
- if (search_type) {
- found = blkid_dev_has_tag(dev, search_type, search_value);
- printf("Device %s: (%s, %s) %s\n", blkid_dev_devname(dev),
- search_type, search_value ? search_value : "NULL",
- found ? "FOUND" : "NOT FOUND");
- return !found;
- }
- printf("Device %s...\n", blkid_dev_devname(dev));
-
- iter = blkid_tag_iterate_begin(dev);
- while (blkid_tag_next(iter, &type, &value) == 0) {
- printf("\tTag %s has value %s\n", type, value);
- }
- blkid_tag_iterate_end(iter);
-
- blkid_put_cache(cache);
- return 0;
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/chattr.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/chattr.c
deleted file mode 100644
index ae39d92245..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/chattr.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * chattr.c - Change file attributes on an ext2 file system
- *
- * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
- * Laboratoire MASI, Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * This file can be redistributed under the terms of the GNU General
- * Public License
- */
-
-/*
- * History:
- * 93/10/30 - Creation
- * 93/11/13 - Replace stat() calls by lstat() to avoid loops
- * 94/02/27 - Integrated in Ted's distribution
- * 98/12/29 - Ignore symlinks when working recursively (G M Sipe)
- * 98/12/29 - Display version info only when -V specified (G M Sipe)
- */
-
-#include <sys/types.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include "ext2fs/ext2_fs.h"
-
-#ifdef __GNUC__
-# define EXT2FS_ATTR(x) __attribute__(x)
-#else
-# define EXT2FS_ATTR(x)
-#endif
-
-#include "e2fsbb.h"
-#include "e2p/e2p.h"
-
-#define OPT_ADD 1
-#define OPT_REM 2
-#define OPT_SET 4
-#define OPT_SET_VER 8
-static int flags;
-static int recursive;
-
-static unsigned long version;
-
-static unsigned long af;
-static unsigned long rf;
-static unsigned long sf;
-
-struct flags_char {
- unsigned long flag;
- char optchar;
-};
-
-static const struct flags_char flags_array[] = {
- { EXT2_NOATIME_FL, 'A' },
- { EXT2_SYNC_FL, 'S' },
- { EXT2_DIRSYNC_FL, 'D' },
- { EXT2_APPEND_FL, 'a' },
- { EXT2_COMPR_FL, 'c' },
- { EXT2_NODUMP_FL, 'd' },
- { EXT2_IMMUTABLE_FL, 'i' },
- { EXT3_JOURNAL_DATA_FL, 'j' },
- { EXT2_SECRM_FL, 's' },
- { EXT2_UNRM_FL, 'u' },
- { EXT2_NOTAIL_FL, 't' },
- { EXT2_TOPDIR_FL, 'T' },
- { 0, 0 }
-};
-
-static unsigned long get_flag(char c)
-{
- const struct flags_char *fp;
- for (fp = flags_array; fp->flag; fp++)
- if (fp->optchar == c)
- return fp->flag;
- bb_show_usage();
- return 0;
-}
-
-static int decode_arg(char *arg)
-{
- unsigned long *fl;
- char opt = *arg++;
-
- if (opt == '-') {
- flags |= OPT_REM;
- fl = &rf;
- } else if (opt == '+') {
- flags |= OPT_ADD;
- fl = &af;
- } else if (opt == '=') {
- flags |= OPT_SET;
- fl = &sf;
- } else
- return EOF;
-
- for (; *arg; ++arg)
- (*fl) |= get_flag(*arg);
-
- return 1;
-}
-
-static int chattr_dir_proc(const char *, struct dirent *, void *);
-
-static void change_attributes(const char * name)
-{
- unsigned long fsflags;
- struct stat st;
-
- if (lstat(name, &st) == -1) {
- bb_error_msg("stat %s failed", name);
- return;
- }
- if (S_ISLNK(st.st_mode) && recursive)
- return;
-
- /* Don't try to open device files, fifos etc. We probably
- * ought to display an error if the file was explicitly given
- * on the command line (whether or not recursive was
- * requested). */
- if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode))
- return;
-
- if (flags & OPT_SET_VER)
- if (fsetversion(name, version) == -1)
- bb_error_msg("setting version on %s", name);
-
- if (flags & OPT_SET) {
- fsflags = sf;
- } else {
- if (fgetflags(name, &fsflags) == -1) {
- bb_error_msg("reading flags on %s", name);
- goto skip_setflags;
- }
- if (flags & OPT_REM)
- fsflags &= ~rf;
- if (flags & OPT_ADD)
- fsflags |= af;
- if (!S_ISDIR(st.st_mode))
- fsflags &= ~EXT2_DIRSYNC_FL;
- }
- if (fsetflags(name, fsflags) == -1)
- bb_error_msg("setting flags on %s", name);
-
-skip_setflags:
- if (S_ISDIR(st.st_mode) && recursive)
- iterate_on_dir(name, chattr_dir_proc, NULL);
-}
-
-static int chattr_dir_proc(const char *dir_name, struct dirent *de,
- void *private EXT2FS_ATTR((unused)))
-{
- /*if (strcmp(de->d_name, ".") || strcmp(de->d_name, "..")) {*/
- if (de->d_name[0] == '.'
- && (!de->d_name[1] || (de->d_name[1] == '.' && !de->d_name[2]))
- ) {
- char *path = concat_subpath_file(dir_name, de->d_name);
- if (path) {
- change_attributes(path);
- free(path);
- }
- }
- return 0;
-}
-
-int chattr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int chattr_main(int argc, char **argv)
-{
- int i;
- char *arg;
-
- /* parse the args */
- for (i = 1; i < argc; ++i) {
- arg = argv[i];
-
- /* take care of -R and -v <version> */
- if (arg[0] == '-') {
- if (arg[1] == 'R' && arg[2] == '\0') {
- recursive = 1;
- continue;
- } else if (arg[1] == 'v' && arg[2] == '\0') {
- char *tmp;
- ++i;
- if (i >= argc)
- bb_show_usage();
- version = strtol(argv[i], &tmp, 0);
- if (*tmp)
- bb_error_msg_and_die("bad version '%s'", arg);
- flags |= OPT_SET_VER;
- continue;
- }
- }
-
- if (decode_arg(arg) == EOF)
- break;
- }
-
- /* run sanity checks on all the arguments given us */
- if (i >= argc)
- bb_show_usage();
- if ((flags & OPT_SET) && ((flags & OPT_ADD) || (flags & OPT_REM)))
- bb_error_msg_and_die("= is incompatible with - and +");
- if ((rf & af) != 0)
- bb_error_msg_and_die("Can't set and unset a flag");
- if (!flags)
- bb_error_msg_and_die("Must use '-v', =, - or +");
-
- /* now run chattr on all the files passed to us */
- while (i < argc)
- change_attributes(argv[i++]);
-
- return EXIT_SUCCESS;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2fsbb.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2fsbb.h
deleted file mode 100644
index d31c319556..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2fsbb.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * File: e2fsbb.h
- *
- * Redefine a bunch of e2fsprogs stuff to use busybox routines
- * instead. This makes upgrade between e2fsprogs versions easy.
- */
-
-#ifndef E2FSBB_H
-#define E2FSBB_H 1
-
-#include "libbb.h"
-
-/* version we've last synced against */
-#define E2FSPROGS_VERSION "1.38"
-#define E2FSPROGS_DATE "30-Jun-2005"
-
-typedef long errcode_t;
-#define ERRCODE_RANGE 8
-#define error_message(code) strerror((int) (code & ((1<<ERRCODE_RANGE)-1)))
-
-/* header defines */
-#define ENABLE_HTREE 1
-#define HAVE_ERRNO_H 1
-#define HAVE_EXT2_IOCTLS 1
-#define HAVE_LINUX_FD_H 1
-#define HAVE_MNTENT_H 1
-#define HAVE_NETINET_IN_H 1
-#define HAVE_NET_IF_H 1
-#define HAVE_SYS_IOCTL_H 1
-#define HAVE_SYS_MOUNT_H 1
-#define HAVE_SYS_QUEUE_H 1
-#define HAVE_SYS_STAT_H 1
-#define HAVE_SYS_TYPES_H 1
-#define HAVE_UNISTD_H 1
-
-/* Endianness */
-#if BB_BIG_ENDIAN
-#define ENABLE_SWAPFS 1
-#define WORDS_BIGENDIAN 1
-#endif
-
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2fsck.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2fsck.c
deleted file mode 100644
index db9f8ce965..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2fsck.c
+++ /dev/null
@@ -1,13521 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * e2fsck
- *
- * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
- * Copyright (C) 2006 Garrett Kajmowicz
- *
- * Dictionary Abstract Data Type
- * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
- * Free Software License:
- * All rights are reserved by the author, with the following exceptions:
- * Permission is granted to freely reproduce and distribute this software,
- * possibly in exchange for a fee, provided that this copyright notice appears
- * intact. Permission is also granted to adapt this software to produce
- * derivative works, as long as the modified versions carry this copyright
- * notice and additional notices stating that the work has been modified.
- * This source code may be translated into executable form and incorporated
- * into proprietary software; there is no requirement for such software to
- * contain a copyright notice related to this source.
- *
- * linux/fs/recovery and linux/fs/revoke
- * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
- *
- * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
- *
- * Journal recovery routines for the generic filesystem journaling code;
- * part of the ext2fs journaling system.
- *
- * Licensed under GPLv2 or later, see file LICENSE in this source tree.
- */
-
-//usage:#define e2fsck_trivial_usage
-//usage: "[-panyrcdfvstDFSV] [-b superblock] [-B blocksize] "
-//usage: "[-I inode_buffer_blocks] [-P process_inode_size] "
-//usage: "[-l|-L bad_blocks_file] [-C fd] [-j external_journal] "
-//usage: "[-E extended-options] device"
-//usage:#define e2fsck_full_usage "\n\n"
-//usage: "Check ext2/ext3 file system\n"
-//usage: "\n -p Automatic repair (no questions)"
-//usage: "\n -n Make no changes to the filesystem"
-//usage: "\n -y Assume 'yes' to all questions"
-//usage: "\n -c Check for bad blocks and add them to the badblock list"
-//usage: "\n -f Force checking even if filesystem is marked clean"
-//usage: "\n -v Verbose"
-//usage: "\n -b superblock Use alternative superblock"
-//usage: "\n -B blocksize Force blocksize when looking for superblock"
-//usage: "\n -j journal Set location of the external journal"
-//usage: "\n -l file Add to badblocks list"
-//usage: "\n -L file Set badblocks list"
-
-//usage:#define fsck_ext2_trivial_usage NOUSAGE_STR
-//usage:#define fsck_ext2_full_usage ""
-
-//usage:#define fsck_ext3_trivial_usage NOUSAGE_STR
-//usage:#define fsck_ext3_full_usage ""
-
-#include "e2fsck.h" /*Put all of our defines here to clean things up*/
-
-#define _(x) x
-#define N_(x) x
-
-/*
- * Procedure declarations
- */
-
-static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
-
-/* pass1.c */
-static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int fl_bool);
-
-/* pass2.c */
-static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
- ext2_ino_t ino, char *buf);
-
-/* pass3.c */
-static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
-static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
- int num, int gauranteed_size);
-static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
-static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
- int adj);
-
-/* rehash.c */
-static void e2fsck_rehash_directories(e2fsck_t ctx);
-
-/* util.c */
-static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
- const char *description);
-static int ask(e2fsck_t ctx, const char * string, int def);
-static void e2fsck_read_bitmaps(e2fsck_t ctx);
-static void preenhalt(e2fsck_t ctx);
-static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
- struct ext2_inode * inode, const char * proc);
-static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
- struct ext2_inode * inode, const char * proc);
-static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
- const char *name, io_manager manager);
-
-/* unix.c */
-static void e2fsck_clear_progbar(e2fsck_t ctx);
-static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
- float percent, unsigned int dpynum);
-
-
-/*
- * problem.h --- e2fsck problem error codes
- */
-
-typedef __u32 problem_t;
-
-struct problem_context {
- errcode_t errcode;
- ext2_ino_t ino, ino2, dir;
- struct ext2_inode *inode;
- struct ext2_dir_entry *dirent;
- blk_t blk, blk2;
- e2_blkcnt_t blkcount;
- int group;
- __u64 num;
- const char *str;
-};
-
-
-/*
- * Function declarations
- */
-static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
-static int end_problem_latch(e2fsck_t ctx, int mask);
-static int set_latch_flags(int mask, int setflags, int clearflags);
-static void clear_problem_context(struct problem_context *ctx);
-
-/*
- * Dictionary Abstract Data Type
- * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
- *
- * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
- * kazlib_1_20
- */
-
-#ifndef DICT_H
-#define DICT_H
-
-/*
- * Blurb for inclusion into C++ translation units
- */
-
-typedef unsigned long dictcount_t;
-#define DICTCOUNT_T_MAX ULONG_MAX
-
-/*
- * The dictionary is implemented as a red-black tree
- */
-
-typedef enum { dnode_red, dnode_black } dnode_color_t;
-
-typedef struct dnode_t {
- struct dnode_t *dict_left;
- struct dnode_t *dict_right;
- struct dnode_t *dict_parent;
- dnode_color_t dict_color;
- const void *dict_key;
- void *dict_data;
-} dnode_t;
-
-typedef int (*dict_comp_t)(const void *, const void *);
-typedef void (*dnode_free_t)(dnode_t *);
-
-typedef struct dict_t {
- dnode_t dict_nilnode;
- dictcount_t dict_nodecount;
- dictcount_t dict_maxcount;
- dict_comp_t dict_compare;
- dnode_free_t dict_freenode;
- int dict_dupes;
-} dict_t;
-
-typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
-
-typedef struct dict_load_t {
- dict_t *dict_dictptr;
- dnode_t dict_nilnode;
-} dict_load_t;
-
-#define dict_count(D) ((D)->dict_nodecount)
-#define dnode_get(N) ((N)->dict_data)
-#define dnode_getkey(N) ((N)->dict_key)
-
-#endif
-
-/*
- * Compatibility header file for e2fsck which should be included
- * instead of linux/jfs.h
- *
- * Copyright (C) 2000 Stephen C. Tweedie
- */
-
-/*
- * Pull in the definition of the e2fsck context structure
- */
-
-struct buffer_head {
- char b_data[8192];
- e2fsck_t b_ctx;
- io_channel b_io;
- int b_size;
- blk_t b_blocknr;
- int b_dirty;
- int b_uptodate;
- int b_err;
-};
-
-
-#define K_DEV_FS 1
-#define K_DEV_JOURNAL 2
-
-#define lock_buffer(bh) do {} while (0)
-#define unlock_buffer(bh) do {} while (0)
-#define buffer_req(bh) 1
-#define do_readahead(journal, start) do {} while (0)
-
-static e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
-
-typedef struct {
- int object_length;
-} kmem_cache_t;
-
-#define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
-
-/*
- * We use the standard libext2fs portability tricks for inline
- * functions.
- */
-
-static kmem_cache_t * do_cache_create(int len)
-{
- kmem_cache_t *new_cache;
-
- new_cache = xmalloc(sizeof(*new_cache));
- new_cache->object_length = len;
- return new_cache;
-}
-
-static void do_cache_destroy(kmem_cache_t *cache)
-{
- free(cache);
-}
-
-
-/*
- * Dictionary Abstract Data Type
- */
-
-
-/*
- * These macros provide short convenient names for structure members,
- * which are embellished with dict_ prefixes so that they are
- * properly confined to the documented namespace. It's legal for a
- * program which uses dict to define, for instance, a macro called ``parent''.
- * Such a macro would interfere with the dnode_t struct definition.
- * In general, highly portable and reusable C modules which expose their
- * structures need to confine structure member names to well-defined spaces.
- * The resulting identifiers aren't necessarily convenient to use, nor
- * readable, in the implementation, however!
- */
-
-#define left dict_left
-#define right dict_right
-#define parent dict_parent
-#define color dict_color
-#define key dict_key
-#define data dict_data
-
-#define nilnode dict_nilnode
-#define maxcount dict_maxcount
-#define compare dict_compare
-#define dupes dict_dupes
-
-#define dict_root(D) ((D)->nilnode.left)
-#define dict_nil(D) (&(D)->nilnode)
-
-static void dnode_free(dnode_t *node);
-
-/*
- * Perform a ``left rotation'' adjustment on the tree. The given node P and
- * its right child C are rearranged so that the P instead becomes the left
- * child of C. The left subtree of C is inherited as the new right subtree
- * for P. The ordering of the keys within the tree is thus preserved.
- */
-
-static void rotate_left(dnode_t *upper)
-{
- dnode_t *lower, *lowleft, *upparent;
-
- lower = upper->right;
- upper->right = lowleft = lower->left;
- lowleft->parent = upper;
-
- lower->parent = upparent = upper->parent;
-
- /* don't need to check for root node here because root->parent is
- the sentinel nil node, and root->parent->left points back to root */
-
- if (upper == upparent->left) {
- upparent->left = lower;
- } else {
- assert (upper == upparent->right);
- upparent->right = lower;
- }
-
- lower->left = upper;
- upper->parent = lower;
-}
-
-/*
- * This operation is the ``mirror'' image of rotate_left. It is
- * the same procedure, but with left and right interchanged.
- */
-
-static void rotate_right(dnode_t *upper)
-{
- dnode_t *lower, *lowright, *upparent;
-
- lower = upper->left;
- upper->left = lowright = lower->right;
- lowright->parent = upper;
-
- lower->parent = upparent = upper->parent;
-
- if (upper == upparent->right) {
- upparent->right = lower;
- } else {
- assert (upper == upparent->left);
- upparent->left = lower;
- }
-
- lower->right = upper;
- upper->parent = lower;
-}
-
-/*
- * Do a postorder traversal of the tree rooted at the specified
- * node and free everything under it. Used by dict_free().
- */
-
-static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
-{
- if (node == nil)
- return;
- free_nodes(dict, node->left, nil);
- free_nodes(dict, node->right, nil);
- dict->dict_freenode(node);
-}
-
-/*
- * Verify that the tree contains the given node. This is done by
- * traversing all of the nodes and comparing their pointers to the
- * given pointer. Returns 1 if the node is found, otherwise
- * returns zero. It is intended for debugging purposes.
- */
-
-static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
-{
- if (root != nil) {
- return root == node
- || verify_dict_has_node(nil, root->left, node)
- || verify_dict_has_node(nil, root->right, node);
- }
- return 0;
-}
-
-
-/*
- * Select a different set of node allocator routines.
- */
-
-static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
-{
- assert(dict_count(dict) == 0);
- dict->dict_freenode = fr;
-}
-
-/*
- * Free all the nodes in the dictionary by using the dictionary's
- * installed free routine. The dictionary is emptied.
- */
-
-static void dict_free_nodes(dict_t *dict)
-{
- dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
- free_nodes(dict, root, nil);
- dict->dict_nodecount = 0;
- dict->nilnode.left = &dict->nilnode;
- dict->nilnode.right = &dict->nilnode;
-}
-
-/*
- * Initialize a user-supplied dictionary object.
- */
-
-static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
-{
- dict->compare = comp;
- dict->dict_freenode = dnode_free;
- dict->dict_nodecount = 0;
- dict->maxcount = maxcount;
- dict->nilnode.left = &dict->nilnode;
- dict->nilnode.right = &dict->nilnode;
- dict->nilnode.parent = &dict->nilnode;
- dict->nilnode.color = dnode_black;
- dict->dupes = 0;
- return dict;
-}
-
-/*
- * Locate a node in the dictionary having the given key.
- * If the node is not found, a null a pointer is returned (rather than
- * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
- * located node is returned.
- */
-
-static dnode_t *dict_lookup(dict_t *dict, const void *key)
-{
- dnode_t *root = dict_root(dict);
- dnode_t *nil = dict_nil(dict);
- dnode_t *saved;
- int result;
-
- /* simple binary search adapted for trees that contain duplicate keys */
-
- while (root != nil) {
- result = dict->compare(key, root->key);
- if (result < 0)
- root = root->left;
- else if (result > 0)
- root = root->right;
- else {
- if (!dict->dupes) { /* no duplicates, return match */
- return root;
- } else { /* could be dupes, find leftmost one */
- do {
- saved = root;
- root = root->left;
- while (root != nil && dict->compare(key, root->key))
- root = root->right;
- } while (root != nil);
- return saved;
- }
- }
- }
-
- return NULL;
-}
-
-/*
- * Insert a node into the dictionary. The node should have been
- * initialized with a data field. All other fields are ignored.
- * The behavior is undefined if the user attempts to insert into
- * a dictionary that is already full (for which the dict_isfull()
- * function returns true).
- */
-
-static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
-{
- dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
- dnode_t *parent = nil, *uncle, *grandpa;
- int result = -1;
-
- node->key = key;
-
- /* basic binary tree insert */
-
- while (where != nil) {
- parent = where;
- result = dict->compare(key, where->key);
- /* trap attempts at duplicate key insertion unless it's explicitly allowed */
- assert(dict->dupes || result != 0);
- if (result < 0)
- where = where->left;
- else
- where = where->right;
- }
-
- assert(where == nil);
-
- if (result < 0)
- parent->left = node;
- else
- parent->right = node;
-
- node->parent = parent;
- node->left = nil;
- node->right = nil;
-
- dict->dict_nodecount++;
-
- /* red black adjustments */
-
- node->color = dnode_red;
-
- while (parent->color == dnode_red) {
- grandpa = parent->parent;
- if (parent == grandpa->left) {
- uncle = grandpa->right;
- if (uncle->color == dnode_red) { /* red parent, red uncle */
- parent->color = dnode_black;
- uncle->color = dnode_black;
- grandpa->color = dnode_red;
- node = grandpa;
- parent = grandpa->parent;
- } else { /* red parent, black uncle */
- if (node == parent->right) {
- rotate_left(parent);
- parent = node;
- assert (grandpa == parent->parent);
- /* rotation between parent and child preserves grandpa */
- }
- parent->color = dnode_black;
- grandpa->color = dnode_red;
- rotate_right(grandpa);
- break;
- }
- } else { /* symmetric cases: parent == parent->parent->right */
- uncle = grandpa->left;
- if (uncle->color == dnode_red) {
- parent->color = dnode_black;
- uncle->color = dnode_black;
- grandpa->color = dnode_red;
- node = grandpa;
- parent = grandpa->parent;
- } else {
- if (node == parent->left) {
- rotate_right(parent);
- parent = node;
- assert (grandpa == parent->parent);
- }
- parent->color = dnode_black;
- grandpa->color = dnode_red;
- rotate_left(grandpa);
- break;
- }
- }
- }
-
- dict_root(dict)->color = dnode_black;
-}
-
-/*
- * Allocate a node using the dictionary's allocator routine, give it
- * the data item.
- */
-
-static dnode_t *dnode_init(dnode_t *dnode, void *data)
-{
- dnode->data = data;
- dnode->parent = NULL;
- dnode->left = NULL;
- dnode->right = NULL;
- return dnode;
-}
-
-static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
-{
- dnode_t *node = xmalloc(sizeof(dnode_t));
-
- dnode_init(node, data);
- dict_insert(dict, node, key);
- return 1;
-}
-
-/*
- * Return the node with the lowest (leftmost) key. If the dictionary is empty
- * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
- */
-
-static dnode_t *dict_first(dict_t *dict)
-{
- dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
-
- if (root != nil)
- while ((left = root->left) != nil)
- root = left;
-
- return (root == nil) ? NULL : root;
-}
-
-/*
- * Return the given node's successor node---the node which has the
- * next key in the left to right ordering. If the node has
- * no successor, a null pointer is returned rather than a pointer to
- * the nil node.
- */
-
-static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
-{
- dnode_t *nil = dict_nil(dict), *parent, *left;
-
- if (curr->right != nil) {
- curr = curr->right;
- while ((left = curr->left) != nil)
- curr = left;
- return curr;
- }
-
- parent = curr->parent;
-
- while (parent != nil && curr == parent->right) {
- curr = parent;
- parent = curr->parent;
- }
-
- return (parent == nil) ? NULL : parent;
-}
-
-
-static void dnode_free(dnode_t *node)
-{
- free(node);
-}
-
-
-#undef left
-#undef right
-#undef parent
-#undef color
-#undef key
-#undef data
-
-#undef nilnode
-#undef maxcount
-#undef compare
-#undef dupes
-
-
-/*
- * dirinfo.c --- maintains the directory information table for e2fsck.
- */
-
-/*
- * This subroutine is called during pass1 to create a directory info
- * entry. During pass1, the passed-in parent is 0; it will get filled
- * in during pass2.
- */
-static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
-{
- struct dir_info *dir;
- int i, j;
- ext2_ino_t num_dirs;
- errcode_t retval;
- unsigned long old_size;
-
- if (!ctx->dir_info) {
- ctx->dir_info_count = 0;
- retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
- if (retval)
- num_dirs = 1024; /* Guess */
- ctx->dir_info_size = num_dirs + 10;
- ctx->dir_info = (struct dir_info *)
- e2fsck_allocate_memory(ctx, ctx->dir_info_size
- * sizeof (struct dir_info),
- "directory map");
- }
-
- if (ctx->dir_info_count >= ctx->dir_info_size) {
- old_size = ctx->dir_info_size * sizeof(struct dir_info);
- ctx->dir_info_size += 10;
- retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
- sizeof(struct dir_info),
- &ctx->dir_info);
- if (retval) {
- ctx->dir_info_size -= 10;
- return;
- }
- }
-
- /*
- * Normally, add_dir_info is called with each inode in
- * sequential order; but once in a while (like when pass 3
- * needs to recreate the root directory or lost+found
- * directory) it is called out of order. In those cases, we
- * need to move the dir_info entries down to make room, since
- * the dir_info array needs to be sorted by inode number for
- * get_dir_info()'s sake.
- */
- if (ctx->dir_info_count &&
- ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
- for (i = ctx->dir_info_count-1; i > 0; i--)
- if (ctx->dir_info[i-1].ino < ino)
- break;
- dir = &ctx->dir_info[i];
- if (dir->ino != ino)
- for (j = ctx->dir_info_count++; j > i; j--)
- ctx->dir_info[j] = ctx->dir_info[j-1];
- } else
- dir = &ctx->dir_info[ctx->dir_info_count++];
-
- dir->ino = ino;
- dir->dotdot = parent;
- dir->parent = parent;
-}
-
-/*
- * get_dir_info() --- given an inode number, try to find the directory
- * information entry for it.
- */
-static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
-{
- int low, high, mid;
-
- low = 0;
- high = ctx->dir_info_count-1;
- if (!ctx->dir_info)
- return 0;
- if (ino == ctx->dir_info[low].ino)
- return &ctx->dir_info[low];
- if (ino == ctx->dir_info[high].ino)
- return &ctx->dir_info[high];
-
- while (low < high) {
- mid = (low+high)/2;
- if (mid == low || mid == high)
- break;
- if (ino == ctx->dir_info[mid].ino)
- return &ctx->dir_info[mid];
- if (ino < ctx->dir_info[mid].ino)
- high = mid;
- else
- low = mid;
- }
- return 0;
-}
-
-/*
- * Free the dir_info structure when it isn't needed any more.
- */
-static void e2fsck_free_dir_info(e2fsck_t ctx)
-{
- ext2fs_free_mem(&ctx->dir_info);
- ctx->dir_info_size = 0;
- ctx->dir_info_count = 0;
-}
-
-/*
- * Return the count of number of directories in the dir_info structure
- */
-static int e2fsck_get_num_dirinfo(e2fsck_t ctx)
-{
- return ctx->dir_info_count;
-}
-
-/*
- * A simple interator function
- */
-static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
-{
- if (*control >= ctx->dir_info_count)
- return 0;
-
- return ctx->dir_info + (*control)++;
-}
-
-/*
- * dirinfo.c --- maintains the directory information table for e2fsck.
- *
- */
-
-#ifdef ENABLE_HTREE
-
-/*
- * This subroutine is called during pass1 to create a directory info
- * entry. During pass1, the passed-in parent is 0; it will get filled
- * in during pass2.
- */
-static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
-{
- struct dx_dir_info *dir;
- int i, j;
- errcode_t retval;
- unsigned long old_size;
-
- if (!ctx->dx_dir_info) {
- ctx->dx_dir_info_count = 0;
- ctx->dx_dir_info_size = 100; /* Guess */
- ctx->dx_dir_info = (struct dx_dir_info *)
- e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
- * sizeof (struct dx_dir_info),
- "directory map");
- }
-
- if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
- old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
- ctx->dx_dir_info_size += 10;
- retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
- sizeof(struct dx_dir_info),
- &ctx->dx_dir_info);
- if (retval) {
- ctx->dx_dir_info_size -= 10;
- return;
- }
- }
-
- /*
- * Normally, add_dx_dir_info is called with each inode in
- * sequential order; but once in a while (like when pass 3
- * needs to recreate the root directory or lost+found
- * directory) it is called out of order. In those cases, we
- * need to move the dx_dir_info entries down to make room, since
- * the dx_dir_info array needs to be sorted by inode number for
- * get_dx_dir_info()'s sake.
- */
- if (ctx->dx_dir_info_count &&
- ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
- for (i = ctx->dx_dir_info_count-1; i > 0; i--)
- if (ctx->dx_dir_info[i-1].ino < ino)
- break;
- dir = &ctx->dx_dir_info[i];
- if (dir->ino != ino)
- for (j = ctx->dx_dir_info_count++; j > i; j--)
- ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
- } else
- dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
-
- dir->ino = ino;
- dir->numblocks = num_blocks;
- dir->hashversion = 0;
- dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
- * sizeof (struct dx_dirblock_info),
- "dx_block info array");
-}
-
-/*
- * get_dx_dir_info() --- given an inode number, try to find the directory
- * information entry for it.
- */
-static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
-{
- int low, high, mid;
-
- low = 0;
- high = ctx->dx_dir_info_count-1;
- if (!ctx->dx_dir_info)
- return 0;
- if (ino == ctx->dx_dir_info[low].ino)
- return &ctx->dx_dir_info[low];
- if (ino == ctx->dx_dir_info[high].ino)
- return &ctx->dx_dir_info[high];
-
- while (low < high) {
- mid = (low+high)/2;
- if (mid == low || mid == high)
- break;
- if (ino == ctx->dx_dir_info[mid].ino)
- return &ctx->dx_dir_info[mid];
- if (ino < ctx->dx_dir_info[mid].ino)
- high = mid;
- else
- low = mid;
- }
- return 0;
-}
-
-/*
- * Free the dx_dir_info structure when it isn't needed any more.
- */
-static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
-{
- int i;
- struct dx_dir_info *dir;
-
- if (ctx->dx_dir_info) {
- dir = ctx->dx_dir_info;
- for (i=0; i < ctx->dx_dir_info_count; i++) {
- ext2fs_free_mem(&dir->dx_block);
- }
- ext2fs_free_mem(&ctx->dx_dir_info);
- }
- ctx->dx_dir_info_size = 0;
- ctx->dx_dir_info_count = 0;
-}
-
-/*
- * A simple interator function
- */
-static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
-{
- if (*control >= ctx->dx_dir_info_count)
- return 0;
-
- return ctx->dx_dir_info + (*control)++;
-}
-
-#endif /* ENABLE_HTREE */
-/*
- * e2fsck.c - a consistency checker for the new extended file system.
- *
- */
-
-/*
- * This function allocates an e2fsck context
- */
-static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
-{
- e2fsck_t context;
- errcode_t retval;
-
- retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
- if (retval)
- return retval;
-
- memset(context, 0, sizeof(struct e2fsck_struct));
-
- context->process_inode_size = 256;
- context->ext_attr_ver = 2;
-
- *ret = context;
- return 0;
-}
-
-struct ea_refcount_el {
- blk_t ea_blk;
- int ea_count;
-};
-
-struct ea_refcount {
- blk_t count;
- blk_t size;
- blk_t cursor;
- struct ea_refcount_el *list;
-};
-
-static void ea_refcount_free(ext2_refcount_t refcount)
-{
- if (!refcount)
- return;
-
- ext2fs_free_mem(&refcount->list);
- ext2fs_free_mem(&refcount);
-}
-
-/*
- * This function resets an e2fsck context; it is called when e2fsck
- * needs to be restarted.
- */
-static errcode_t e2fsck_reset_context(e2fsck_t ctx)
-{
- ctx->flags = 0;
- ctx->lost_and_found = 0;
- ctx->bad_lost_and_found = 0;
- ext2fs_free_inode_bitmap(ctx->inode_used_map);
- ctx->inode_used_map = 0;
- ext2fs_free_inode_bitmap(ctx->inode_dir_map);
- ctx->inode_dir_map = 0;
- ext2fs_free_inode_bitmap(ctx->inode_reg_map);
- ctx->inode_reg_map = 0;
- ext2fs_free_block_bitmap(ctx->block_found_map);
- ctx->block_found_map = 0;
- ext2fs_free_icount(ctx->inode_link_info);
- ctx->inode_link_info = 0;
- if (ctx->journal_io) {
- if (ctx->fs && ctx->fs->io != ctx->journal_io)
- io_channel_close(ctx->journal_io);
- ctx->journal_io = 0;
- }
- if (ctx->fs) {
- ext2fs_free_dblist(ctx->fs->dblist);
- ctx->fs->dblist = 0;
- }
- e2fsck_free_dir_info(ctx);
-#ifdef ENABLE_HTREE
- e2fsck_free_dx_dir_info(ctx);
-#endif
- ea_refcount_free(ctx->refcount);
- ctx->refcount = 0;
- ea_refcount_free(ctx->refcount_extra);
- ctx->refcount_extra = 0;
- ext2fs_free_block_bitmap(ctx->block_dup_map);
- ctx->block_dup_map = 0;
- ext2fs_free_block_bitmap(ctx->block_ea_map);
- ctx->block_ea_map = 0;
- ext2fs_free_inode_bitmap(ctx->inode_bad_map);
- ctx->inode_bad_map = 0;
- ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
- ctx->inode_imagic_map = 0;
- ext2fs_u32_list_free(ctx->dirs_to_hash);
- ctx->dirs_to_hash = 0;
-
- /*
- * Clear the array of invalid meta-data flags
- */
- ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
- ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
- ext2fs_free_mem(&ctx->invalid_inode_table_flag);
-
- /* Clear statistic counters */
- ctx->fs_directory_count = 0;
- ctx->fs_regular_count = 0;
- ctx->fs_blockdev_count = 0;
- ctx->fs_chardev_count = 0;
- ctx->fs_links_count = 0;
- ctx->fs_symlinks_count = 0;
- ctx->fs_fast_symlinks_count = 0;
- ctx->fs_fifo_count = 0;
- ctx->fs_total_count = 0;
- ctx->fs_sockets_count = 0;
- ctx->fs_ind_count = 0;
- ctx->fs_dind_count = 0;
- ctx->fs_tind_count = 0;
- ctx->fs_fragmented = 0;
- ctx->large_files = 0;
-
- /* Reset the superblock to the user's requested value */
- ctx->superblock = ctx->use_superblock;
-
- return 0;
-}
-
-static void e2fsck_free_context(e2fsck_t ctx)
-{
- if (!ctx)
- return;
-
- e2fsck_reset_context(ctx);
-
- ext2fs_free_mem(&ctx);
-}
-
-/*
- * ea_refcount.c
- */
-
-/*
- * The strategy we use for keeping track of EA refcounts is as
- * follows. We keep a sorted array of first EA blocks and its
- * reference counts. Once the refcount has dropped to zero, it is
- * removed from the array to save memory space. Once the EA block is
- * checked, its bit is set in the block_ea_map bitmap.
- */
-
-
-static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
-{
- ext2_refcount_t refcount;
- errcode_t retval;
- size_t bytes;
-
- retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
- if (retval)
- return retval;
- memset(refcount, 0, sizeof(struct ea_refcount));
-
- if (!size)
- size = 500;
- refcount->size = size;
- bytes = (size_t) (size * sizeof(struct ea_refcount_el));
-#ifdef DEBUG
- printf("Refcount allocated %d entries, %d bytes.\n",
- refcount->size, bytes);
-#endif
- retval = ext2fs_get_mem(bytes, &refcount->list);
- if (retval)
- goto errout;
- memset(refcount->list, 0, bytes);
-
- refcount->count = 0;
- refcount->cursor = 0;
-
- *ret = refcount;
- return 0;
-
-errout:
- ea_refcount_free(refcount);
- return retval;
-}
-
-/*
- * collapse_refcount() --- go through the refcount array, and get rid
- * of any count == zero entries
- */
-static void refcount_collapse(ext2_refcount_t refcount)
-{
- unsigned int i, j;
- struct ea_refcount_el *list;
-
- list = refcount->list;
- for (i = 0, j = 0; i < refcount->count; i++) {
- if (list[i].ea_count) {
- if (i != j)
- list[j] = list[i];
- j++;
- }
- }
-#if defined(DEBUG) || defined(TEST_PROGRAM)
- printf("Refcount_collapse: size was %d, now %d\n",
- refcount->count, j);
-#endif
- refcount->count = j;
-}
-
-
-/*
- * insert_refcount_el() --- Insert a new entry into the sorted list at a
- * specified position.
- */
-static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
- blk_t blk, int pos)
-{
- struct ea_refcount_el *el;
- errcode_t retval;
- blk_t new_size = 0;
- int num;
-
- if (refcount->count >= refcount->size) {
- new_size = refcount->size + 100;
-#ifdef DEBUG
- printf("Reallocating refcount %d entries...\n", new_size);
-#endif
- retval = ext2fs_resize_mem((size_t) refcount->size *
- sizeof(struct ea_refcount_el),
- (size_t) new_size *
- sizeof(struct ea_refcount_el),
- &refcount->list);
- if (retval)
- return 0;
- refcount->size = new_size;
- }
- num = (int) refcount->count - pos;
- if (num < 0)
- return 0; /* should never happen */
- if (num) {
- memmove(&refcount->list[pos+1], &refcount->list[pos],
- sizeof(struct ea_refcount_el) * num);
- }
- refcount->count++;
- el = &refcount->list[pos];
- el->ea_count = 0;
- el->ea_blk = blk;
- return el;
-}
-
-
-/*
- * get_refcount_el() --- given an block number, try to find refcount
- * information in the sorted list. If the create flag is set,
- * and we can't find an entry, create one in the sorted list.
- */
-static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
- blk_t blk, int create)
-{
- float range;
- int low, high, mid;
- blk_t lowval, highval;
-
- if (!refcount || !refcount->list)
- return 0;
-retry:
- low = 0;
- high = (int) refcount->count-1;
- if (create && ((refcount->count == 0) ||
- (blk > refcount->list[high].ea_blk))) {
- if (refcount->count >= refcount->size)
- refcount_collapse(refcount);
-
- return insert_refcount_el(refcount, blk,
- (unsigned) refcount->count);
- }
- if (refcount->count == 0)
- return 0;
-
- if (refcount->cursor >= refcount->count)
- refcount->cursor = 0;
- if (blk == refcount->list[refcount->cursor].ea_blk)
- return &refcount->list[refcount->cursor++];
-#ifdef DEBUG
- printf("Non-cursor get_refcount_el: %u\n", blk);
-#endif
- while (low <= high) {
- if (low == high)
- mid = low;
- else {
- /* Interpolate for efficiency */
- lowval = refcount->list[low].ea_blk;
- highval = refcount->list[high].ea_blk;
-
- if (blk < lowval)
- range = 0;
- else if (blk > highval)
- range = 1;
- else
- range = ((float) (blk - lowval)) /
- (highval - lowval);
- mid = low + ((int) (range * (high-low)));
- }
-
- if (blk == refcount->list[mid].ea_blk) {
- refcount->cursor = mid+1;
- return &refcount->list[mid];
- }
- if (blk < refcount->list[mid].ea_blk)
- high = mid-1;
- else
- low = mid+1;
- }
- /*
- * If we need to create a new entry, it should be right at
- * low (where high will be left at low-1).
- */
- if (create) {
- if (refcount->count >= refcount->size) {
- refcount_collapse(refcount);
- if (refcount->count < refcount->size)
- goto retry;
- }
- return insert_refcount_el(refcount, blk, low);
- }
- return 0;
-}
-
-static errcode_t
-ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
-{
- struct ea_refcount_el *el;
-
- el = get_refcount_el(refcount, blk, 1);
- if (!el)
- return EXT2_ET_NO_MEMORY;
- el->ea_count++;
-
- if (ret)
- *ret = el->ea_count;
- return 0;
-}
-
-static errcode_t
-ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
-{
- struct ea_refcount_el *el;
-
- el = get_refcount_el(refcount, blk, 0);
- if (!el || el->ea_count == 0)
- return EXT2_ET_INVALID_ARGUMENT;
-
- el->ea_count--;
-
- if (ret)
- *ret = el->ea_count;
- return 0;
-}
-
-static errcode_t
-ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
-{
- struct ea_refcount_el *el;
-
- /*
- * Get the refcount element
- */
- el = get_refcount_el(refcount, blk, count ? 1 : 0);
- if (!el)
- return count ? EXT2_ET_NO_MEMORY : 0;
- el->ea_count = count;
- return 0;
-}
-
-static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
-{
- refcount->cursor = 0;
-}
-
-
-static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
-{
- struct ea_refcount_el *list;
-
- while (1) {
- if (refcount->cursor >= refcount->count)
- return 0;
- list = refcount->list;
- if (list[refcount->cursor].ea_count) {
- if (ret)
- *ret = list[refcount->cursor].ea_count;
- return list[refcount->cursor++].ea_blk;
- }
- refcount->cursor++;
- }
-}
-
-
-/*
- * ehandler.c --- handle bad block errors which come up during the
- * course of an e2fsck session.
- */
-
-
-static const char *operation;
-
-static errcode_t
-e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
- void *data, size_t size FSCK_ATTR((unused)),
- int actual FSCK_ATTR((unused)), errcode_t error)
-{
- int i;
- char *p;
- ext2_filsys fs = (ext2_filsys) channel->app_data;
- e2fsck_t ctx;
-
- ctx = (e2fsck_t) fs->priv_data;
-
- /*
- * If more than one block was read, try reading each block
- * separately. We could use the actual bytes read to figure
- * out where to start, but we don't bother.
- */
- if (count > 1) {
- p = (char *) data;
- for (i=0; i < count; i++, p += channel->block_size, block++) {
- error = io_channel_read_blk(channel, block,
- 1, p);
- if (error)
- return error;
- }
- return 0;
- }
- if (operation)
- printf(_("Error reading block %lu (%s) while %s. "), block,
- error_message(error), operation);
- else
- printf(_("Error reading block %lu (%s). "), block,
- error_message(error));
- preenhalt(ctx);
- if (ask(ctx, _("Ignore error"), 1)) {
- if (ask(ctx, _("Force rewrite"), 1))
- io_channel_write_blk(channel, block, 1, data);
- return 0;
- }
-
- return error;
-}
-
-static errcode_t
-e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
- const void *data, size_t size FSCK_ATTR((unused)),
- int actual FSCK_ATTR((unused)), errcode_t error)
-{
- int i;
- const char *p;
- ext2_filsys fs = (ext2_filsys) channel->app_data;
- e2fsck_t ctx;
-
- ctx = (e2fsck_t) fs->priv_data;
-
- /*
- * If more than one block was written, try writing each block
- * separately. We could use the actual bytes read to figure
- * out where to start, but we don't bother.
- */
- if (count > 1) {
- p = (const char *) data;
- for (i=0; i < count; i++, p += channel->block_size, block++) {
- error = io_channel_write_blk(channel, block,
- 1, p);
- if (error)
- return error;
- }
- return 0;
- }
-
- if (operation)
- printf(_("Error writing block %lu (%s) while %s. "), block,
- error_message(error), operation);
- else
- printf(_("Error writing block %lu (%s). "), block,
- error_message(error));
- preenhalt(ctx);
- if (ask(ctx, _("Ignore error"), 1))
- return 0;
-
- return error;
-}
-
-static const char *ehandler_operation(const char *op)
-{
- const char *ret = operation;
-
- operation = op;
- return ret;
-}
-
-static void ehandler_init(io_channel channel)
-{
- channel->read_error = e2fsck_handle_read_error;
- channel->write_error = e2fsck_handle_write_error;
-}
-
-/*
- * journal.c --- code for handling the "ext3" journal
- *
- * Copyright (C) 2000 Andreas Dilger
- * Copyright (C) 2000 Theodore Ts'o
- *
- * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
- * Copyright (C) 1999 Red Hat Software
- *
- * This file may be redistributed under the terms of the
- * GNU General Public License version 2 or at your discretion
- * any later version.
- */
-
-/*
- * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
- * This creates a larger static binary, and a smaller binary using
- * shared libraries. It's also probably slightly less CPU-efficient,
- * which is why it's not on by default. But, it's a good way of
- * testing the functions in inode_io.c and fileio.c.
- */
-#undef USE_INODE_IO
-
-/* Kernel compatibility functions for handling the journal. These allow us
- * to use the recovery.c file virtually unchanged from the kernel, so we
- * don't have to do much to keep kernel and user recovery in sync.
- */
-static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
-{
-#ifdef USE_INODE_IO
- *phys = block;
- return 0;
-#else
- struct inode *inode = journal->j_inode;
- errcode_t retval;
- blk_t pblk;
-
- if (!inode) {
- *phys = block;
- return 0;
- }
-
- retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
- &inode->i_ext2, NULL, 0, block, &pblk);
- *phys = pblk;
- return retval;
-#endif
-}
-
-static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
-{
- struct buffer_head *bh;
-
- bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
- if (!bh)
- return NULL;
-
- bh->b_ctx = kdev->k_ctx;
- if (kdev->k_dev == K_DEV_FS)
- bh->b_io = kdev->k_ctx->fs->io;
- else
- bh->b_io = kdev->k_ctx->journal_io;
- bh->b_size = blocksize;
- bh->b_blocknr = blocknr;
-
- return bh;
-}
-
-static void sync_blockdev(kdev_t kdev)
-{
- io_channel io;
-
- if (kdev->k_dev == K_DEV_FS)
- io = kdev->k_ctx->fs->io;
- else
- io = kdev->k_ctx->journal_io;
-
- io_channel_flush(io);
-}
-
-static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
-{
- int retval;
- struct buffer_head *bh;
-
- for (; nr > 0; --nr) {
- bh = *bhp++;
- if (rw == READ && !bh->b_uptodate) {
- retval = io_channel_read_blk(bh->b_io,
- bh->b_blocknr,
- 1, bh->b_data);
- if (retval) {
- bb_error_msg("while reading block %lu",
- (unsigned long) bh->b_blocknr);
- bh->b_err = retval;
- continue;
- }
- bh->b_uptodate = 1;
- } else if (rw == WRITE && bh->b_dirty) {
- retval = io_channel_write_blk(bh->b_io,
- bh->b_blocknr,
- 1, bh->b_data);
- if (retval) {
- bb_error_msg("while writing block %lu",
- (unsigned long) bh->b_blocknr);
- bh->b_err = retval;
- continue;
- }
- bh->b_dirty = 0;
- bh->b_uptodate = 1;
- }
- }
-}
-
-static void mark_buffer_dirty(struct buffer_head *bh)
-{
- bh->b_dirty = 1;
-}
-
-static inline void mark_buffer_clean(struct buffer_head * bh)
-{
- bh->b_dirty = 0;
-}
-
-static void brelse(struct buffer_head *bh)
-{
- if (bh->b_dirty)
- ll_rw_block(WRITE, 1, &bh);
- ext2fs_free_mem(&bh);
-}
-
-static int buffer_uptodate(struct buffer_head *bh)
-{
- return bh->b_uptodate;
-}
-
-static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
-{
- bh->b_uptodate = val;
-}
-
-static void wait_on_buffer(struct buffer_head *bh)
-{
- if (!bh->b_uptodate)
- ll_rw_block(READ, 1, &bh);
-}
-
-
-static void e2fsck_clear_recover(e2fsck_t ctx, int error)
-{
- ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
-
- /* if we had an error doing journal recovery, we need a full fsck */
- if (error)
- ctx->fs->super->s_state &= ~EXT2_VALID_FS;
- ext2fs_mark_super_dirty(ctx->fs);
-}
-
-static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
-{
- struct ext2_super_block *sb = ctx->fs->super;
- struct ext2_super_block jsuper;
- struct problem_context pctx;
- struct buffer_head *bh;
- struct inode *j_inode = NULL;
- struct kdev_s *dev_fs = NULL, *dev_journal;
- const char *journal_name = NULL;
- journal_t *journal = NULL;
- errcode_t retval = 0;
- io_manager io_ptr = 0;
- unsigned long start = 0;
- blk_t blk;
- int ext_journal = 0;
- int tried_backup_jnl = 0;
- int i;
-
- clear_problem_context(&pctx);
-
- journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
- if (!journal) {
- return EXT2_ET_NO_MEMORY;
- }
-
- dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
- if (!dev_fs) {
- retval = EXT2_ET_NO_MEMORY;
- goto errout;
- }
- dev_journal = dev_fs+1;
-
- dev_fs->k_ctx = dev_journal->k_ctx = ctx;
- dev_fs->k_dev = K_DEV_FS;
- dev_journal->k_dev = K_DEV_JOURNAL;
-
- journal->j_dev = dev_journal;
- journal->j_fs_dev = dev_fs;
- journal->j_inode = NULL;
- journal->j_blocksize = ctx->fs->blocksize;
-
- if (uuid_is_null(sb->s_journal_uuid)) {
- if (!sb->s_journal_inum)
- return EXT2_ET_BAD_INODE_NUM;
- j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
- "journal inode");
- if (!j_inode) {
- retval = EXT2_ET_NO_MEMORY;
- goto errout;
- }
-
- j_inode->i_ctx = ctx;
- j_inode->i_ino = sb->s_journal_inum;
-
- if ((retval = ext2fs_read_inode(ctx->fs,
- sb->s_journal_inum,
- &j_inode->i_ext2))) {
- try_backup_journal:
- if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
- tried_backup_jnl)
- goto errout;
- memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
- memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
- EXT2_N_BLOCKS*4);
- j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
- j_inode->i_ext2.i_links_count = 1;
- j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
- tried_backup_jnl++;
- }
- if (!j_inode->i_ext2.i_links_count ||
- !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
- retval = EXT2_ET_NO_JOURNAL;
- goto try_backup_journal;
- }
- if (j_inode->i_ext2.i_size / journal->j_blocksize <
- JFS_MIN_JOURNAL_BLOCKS) {
- retval = EXT2_ET_JOURNAL_TOO_SMALL;
- goto try_backup_journal;
- }
- for (i=0; i < EXT2_N_BLOCKS; i++) {
- blk = j_inode->i_ext2.i_block[i];
- if (!blk) {
- if (i < EXT2_NDIR_BLOCKS) {
- retval = EXT2_ET_JOURNAL_TOO_SMALL;
- goto try_backup_journal;
- }
- continue;
- }
- if (blk < sb->s_first_data_block ||
- blk >= sb->s_blocks_count) {
- retval = EXT2_ET_BAD_BLOCK_NUM;
- goto try_backup_journal;
- }
- }
- journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
-
-#ifdef USE_INODE_IO
- retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
- &j_inode->i_ext2,
- &journal_name);
- if (retval)
- goto errout;
-
- io_ptr = inode_io_manager;
-#else
- journal->j_inode = j_inode;
- ctx->journal_io = ctx->fs->io;
- if ((retval = journal_bmap(journal, 0, &start)) != 0)
- goto errout;
-#endif
- } else {
- ext_journal = 1;
- if (!ctx->journal_name) {
- char uuid[37];
-
- unparse_uuid(sb->s_journal_uuid, uuid);
- ctx->journal_name = get_devname_from_uuid(uuid);
- if (!ctx->journal_name)
- ctx->journal_name = get_devname_from_device(sb->s_journal_dev);
- }
- journal_name = ctx->journal_name;
-
- if (!journal_name) {
- fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
- return EXT2_ET_LOAD_EXT_JOURNAL;
- }
-
- io_ptr = unix_io_manager;
- }
-
-#ifndef USE_INODE_IO
- if (ext_journal)
-#endif
- retval = io_ptr->open(journal_name, IO_FLAG_RW,
- &ctx->journal_io);
- if (retval)
- goto errout;
-
- io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
-
- if (ext_journal) {
- if (ctx->fs->blocksize == 1024)
- start = 1;
- bh = getblk(dev_journal, start, ctx->fs->blocksize);
- if (!bh) {
- retval = EXT2_ET_NO_MEMORY;
- goto errout;
- }
- ll_rw_block(READ, 1, &bh);
- if ((retval = bh->b_err) != 0)
- goto errout;
- memcpy(&jsuper, start ? bh->b_data : bh->b_data + 1024,
- sizeof(jsuper));
- brelse(bh);
-#if BB_BIG_ENDIAN
- if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
- ext2fs_swap_super(&jsuper);
-#endif
- if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
- !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
- fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
- retval = EXT2_ET_LOAD_EXT_JOURNAL;
- goto errout;
- }
- /* Make sure the journal UUID is correct */
- if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
- sizeof(jsuper.s_uuid))) {
- fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
- retval = EXT2_ET_LOAD_EXT_JOURNAL;
- goto errout;
- }
-
- journal->j_maxlen = jsuper.s_blocks_count;
- start++;
- }
-
- if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
- retval = EXT2_ET_NO_MEMORY;
- goto errout;
- }
-
- journal->j_sb_buffer = bh;
- journal->j_superblock = (journal_superblock_t *)bh->b_data;
-
-#ifdef USE_INODE_IO
- ext2fs_free_mem(&j_inode);
-#endif
-
- *ret_journal = journal;
- return 0;
-
-errout:
- ext2fs_free_mem(&dev_fs);
- ext2fs_free_mem(&j_inode);
- ext2fs_free_mem(&journal);
- return retval;
-}
-
-static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
- struct problem_context *pctx)
-{
- struct ext2_super_block *sb = ctx->fs->super;
- int recover = ctx->fs->super->s_feature_incompat &
- EXT3_FEATURE_INCOMPAT_RECOVER;
- int has_journal = ctx->fs->super->s_feature_compat &
- EXT3_FEATURE_COMPAT_HAS_JOURNAL;
-
- if (has_journal || sb->s_journal_inum) {
- /* The journal inode is bogus, remove and force full fsck */
- pctx->ino = sb->s_journal_inum;
- if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
- if (has_journal && sb->s_journal_inum)
- printf("*** ext3 journal has been deleted - "
- "filesystem is now ext2 only ***\n\n");
- sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
- sb->s_journal_inum = 0;
- ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
- e2fsck_clear_recover(ctx, 1);
- return 0;
- }
- return EXT2_ET_BAD_INODE_NUM;
- } else if (recover) {
- if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
- e2fsck_clear_recover(ctx, 1);
- return 0;
- }
- return EXT2_ET_UNSUPP_FEATURE;
- }
- return 0;
-}
-
-#define V1_SB_SIZE 0x0024
-static void clear_v2_journal_fields(journal_t *journal)
-{
- e2fsck_t ctx = journal->j_dev->k_ctx;
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
-
- if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
- return;
-
- memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
- ctx->fs->blocksize-V1_SB_SIZE);
- mark_buffer_dirty(journal->j_sb_buffer);
-}
-
-
-static errcode_t e2fsck_journal_load(journal_t *journal)
-{
- e2fsck_t ctx = journal->j_dev->k_ctx;
- journal_superblock_t *jsb;
- struct buffer_head *jbh = journal->j_sb_buffer;
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
-
- ll_rw_block(READ, 1, &jbh);
- if (jbh->b_err) {
- bb_error_msg(_("reading journal superblock"));
- return jbh->b_err;
- }
-
- jsb = journal->j_superblock;
- /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
- if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
- return e2fsck_journal_fix_bad_inode(ctx, &pctx);
-
- switch (ntohl(jsb->s_header.h_blocktype)) {
- case JFS_SUPERBLOCK_V1:
- journal->j_format_version = 1;
- if (jsb->s_feature_compat ||
- jsb->s_feature_incompat ||
- jsb->s_feature_ro_compat ||
- jsb->s_nr_users)
- clear_v2_journal_fields(journal);
- break;
-
- case JFS_SUPERBLOCK_V2:
- journal->j_format_version = 2;
- if (ntohl(jsb->s_nr_users) > 1 &&
- uuid_is_null(ctx->fs->super->s_journal_uuid))
- clear_v2_journal_fields(journal);
- if (ntohl(jsb->s_nr_users) > 1) {
- fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
- return EXT2_ET_JOURNAL_UNSUPP_VERSION;
- }
- break;
-
- /*
- * These should never appear in a journal super block, so if
- * they do, the journal is badly corrupted.
- */
- case JFS_DESCRIPTOR_BLOCK:
- case JFS_COMMIT_BLOCK:
- case JFS_REVOKE_BLOCK:
- return EXT2_ET_CORRUPT_SUPERBLOCK;
-
- /* If we don't understand the superblock major type, but there
- * is a magic number, then it is likely to be a new format we
- * just don't understand, so leave it alone. */
- default:
- return EXT2_ET_JOURNAL_UNSUPP_VERSION;
- }
-
- if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
- return EXT2_ET_UNSUPP_FEATURE;
-
- if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
- return EXT2_ET_RO_UNSUPP_FEATURE;
-
- /* We have now checked whether we know enough about the journal
- * format to be able to proceed safely, so any other checks that
- * fail we should attempt to recover from. */
- if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
- bb_error_msg(_("%s: no valid journal superblock found"),
- ctx->device_name);
- return EXT2_ET_CORRUPT_SUPERBLOCK;
- }
-
- if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
- journal->j_maxlen = ntohl(jsb->s_maxlen);
- else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
- bb_error_msg(_("%s: journal too short"),
- ctx->device_name);
- return EXT2_ET_CORRUPT_SUPERBLOCK;
- }
-
- journal->j_tail_sequence = ntohl(jsb->s_sequence);
- journal->j_transaction_sequence = journal->j_tail_sequence;
- journal->j_tail = ntohl(jsb->s_start);
- journal->j_first = ntohl(jsb->s_first);
- journal->j_last = ntohl(jsb->s_maxlen);
-
- return 0;
-}
-
-static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
- journal_t *journal)
-{
- char *p;
- union {
- __u8 uuid[16];
- __u32 val[4];
- } u;
- __u32 new_seq = 0;
- int i;
-
- /* Leave a valid existing V1 superblock signature alone.
- * Anything unrecognizable we overwrite with a new V2
- * signature. */
-
- if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
- jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
- jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
- jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
- }
-
- /* Zero out everything else beyond the superblock header */
-
- p = ((char *) jsb) + sizeof(journal_header_t);
- memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
-
- jsb->s_blocksize = htonl(ctx->fs->blocksize);
- jsb->s_maxlen = htonl(journal->j_maxlen);
- jsb->s_first = htonl(1);
-
- /* Initialize the journal sequence number so that there is "no"
- * chance we will find old "valid" transactions in the journal.
- * This avoids the need to zero the whole journal (slow to do,
- * and risky when we are just recovering the filesystem).
- */
- generate_uuid(u.uuid);
- for (i = 0; i < 4; i ++)
- new_seq ^= u.val[i];
- jsb->s_sequence = htonl(new_seq);
-
- mark_buffer_dirty(journal->j_sb_buffer);
- ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
-}
-
-static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
- journal_t *journal,
- struct problem_context *pctx)
-{
- struct ext2_super_block *sb = ctx->fs->super;
- int recover = ctx->fs->super->s_feature_incompat &
- EXT3_FEATURE_INCOMPAT_RECOVER;
-
- if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
- if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
- e2fsck_journal_reset_super(ctx, journal->j_superblock,
- journal);
- journal->j_transaction_sequence = 1;
- e2fsck_clear_recover(ctx, recover);
- return 0;
- }
- return EXT2_ET_CORRUPT_SUPERBLOCK;
- } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
- return EXT2_ET_CORRUPT_SUPERBLOCK;
-
- return 0;
-}
-
-static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
- int reset, int drop)
-{
- journal_superblock_t *jsb;
-
- if (drop)
- mark_buffer_clean(journal->j_sb_buffer);
- else if (!(ctx->options & E2F_OPT_READONLY)) {
- jsb = journal->j_superblock;
- jsb->s_sequence = htonl(journal->j_transaction_sequence);
- if (reset)
- jsb->s_start = 0; /* this marks the journal as empty */
- mark_buffer_dirty(journal->j_sb_buffer);
- }
- brelse(journal->j_sb_buffer);
-
- if (ctx->journal_io) {
- if (ctx->fs && ctx->fs->io != ctx->journal_io)
- io_channel_close(ctx->journal_io);
- ctx->journal_io = 0;
- }
-
-#ifndef USE_INODE_IO
- ext2fs_free_mem(&journal->j_inode);
-#endif
- ext2fs_free_mem(&journal->j_fs_dev);
- ext2fs_free_mem(&journal);
-}
-
-/*
- * This function makes sure that the superblock fields regarding the
- * journal are consistent.
- */
-static int e2fsck_check_ext3_journal(e2fsck_t ctx)
-{
- struct ext2_super_block *sb = ctx->fs->super;
- journal_t *journal;
- int recover = ctx->fs->super->s_feature_incompat &
- EXT3_FEATURE_INCOMPAT_RECOVER;
- struct problem_context pctx;
- problem_t problem;
- int reset = 0, force_fsck = 0;
- int retval;
-
- /* If we don't have any journal features, don't do anything more */
- if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
- !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
- uuid_is_null(sb->s_journal_uuid))
- return 0;
-
- clear_problem_context(&pctx);
- pctx.num = sb->s_journal_inum;
-
- retval = e2fsck_get_journal(ctx, &journal);
- if (retval) {
- if ((retval == EXT2_ET_BAD_INODE_NUM) ||
- (retval == EXT2_ET_BAD_BLOCK_NUM) ||
- (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
- (retval == EXT2_ET_NO_JOURNAL))
- return e2fsck_journal_fix_bad_inode(ctx, &pctx);
- return retval;
- }
-
- retval = e2fsck_journal_load(journal);
- if (retval) {
- if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
- ((retval == EXT2_ET_UNSUPP_FEATURE) &&
- (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
- &pctx))) ||
- ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
- (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
- &pctx))) ||
- ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
- (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
- retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
- &pctx);
- e2fsck_journal_release(ctx, journal, 0, 1);
- return retval;
- }
-
- /*
- * We want to make the flags consistent here. We will not leave with
- * needs_recovery set but has_journal clear. We can't get in a loop
- * with -y, -n, or -p, only if a user isn't making up their mind.
- */
-no_has_journal:
- if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
- recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
- pctx.str = "inode";
- if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
- if (recover &&
- !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
- goto no_has_journal;
- /*
- * Need a full fsck if we are releasing a
- * journal stored on a reserved inode.
- */
- force_fsck = recover ||
- (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
- /* Clear all of the journal fields */
- sb->s_journal_inum = 0;
- sb->s_journal_dev = 0;
- memset(sb->s_journal_uuid, 0,
- sizeof(sb->s_journal_uuid));
- e2fsck_clear_recover(ctx, force_fsck);
- } else if (!(ctx->options & E2F_OPT_READONLY)) {
- sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
- ext2fs_mark_super_dirty(ctx->fs);
- }
- }
-
- if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
- !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
- journal->j_superblock->s_start != 0) {
- /* Print status information */
- fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
- if (ctx->superblock)
- problem = PR_0_JOURNAL_RUN_DEFAULT;
- else
- problem = PR_0_JOURNAL_RUN;
- if (fix_problem(ctx, problem, &pctx)) {
- ctx->options |= E2F_OPT_FORCE;
- sb->s_feature_incompat |=
- EXT3_FEATURE_INCOMPAT_RECOVER;
- ext2fs_mark_super_dirty(ctx->fs);
- } else if (fix_problem(ctx,
- PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
- reset = 1;
- sb->s_state &= ~EXT2_VALID_FS;
- ext2fs_mark_super_dirty(ctx->fs);
- }
- /*
- * If the user answers no to the above question, we
- * ignore the fact that journal apparently has data;
- * accidentally replaying over valid data would be far
- * worse than skipping a questionable recovery.
- *
- * XXX should we abort with a fatal error here? What
- * will the ext3 kernel code do if a filesystem with
- * !NEEDS_RECOVERY but with a non-zero
- * journal->j_superblock->s_start is mounted?
- */
- }
-
- e2fsck_journal_release(ctx, journal, reset, 0);
- return retval;
-}
-
-static errcode_t recover_ext3_journal(e2fsck_t ctx)
-{
- journal_t *journal;
- int retval;
-
- journal_init_revoke_caches();
- retval = e2fsck_get_journal(ctx, &journal);
- if (retval)
- return retval;
-
- retval = e2fsck_journal_load(journal);
- if (retval)
- goto errout;
-
- retval = journal_init_revoke(journal, 1024);
- if (retval)
- goto errout;
-
- retval = -journal_recover(journal);
- if (retval)
- goto errout;
-
- if (journal->j_superblock->s_errno) {
- ctx->fs->super->s_state |= EXT2_ERROR_FS;
- ext2fs_mark_super_dirty(ctx->fs);
- journal->j_superblock->s_errno = 0;
- mark_buffer_dirty(journal->j_sb_buffer);
- }
-
-errout:
- journal_destroy_revoke(journal);
- journal_destroy_revoke_caches();
- e2fsck_journal_release(ctx, journal, 1, 0);
- return retval;
-}
-
-static int e2fsck_run_ext3_journal(e2fsck_t ctx)
-{
- io_manager io_ptr = ctx->fs->io->manager;
- int blocksize = ctx->fs->blocksize;
- errcode_t retval, recover_retval;
-
- printf(_("%s: recovering journal\n"), ctx->device_name);
- if (ctx->options & E2F_OPT_READONLY) {
- printf(_("%s: won't do journal recovery while read-only\n"),
- ctx->device_name);
- return EXT2_ET_FILE_RO;
- }
-
- if (ctx->fs->flags & EXT2_FLAG_DIRTY)
- ext2fs_flush(ctx->fs); /* Force out any modifications */
-
- recover_retval = recover_ext3_journal(ctx);
-
- /*
- * Reload the filesystem context to get up-to-date data from disk
- * because journal recovery will change the filesystem under us.
- */
- ext2fs_close(ctx->fs);
- retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
- ctx->superblock, blocksize, io_ptr,
- &ctx->fs);
-
- if (retval) {
- bb_error_msg(_("while trying to re-open %s"),
- ctx->device_name);
- bb_error_msg_and_die(0);
- }
- ctx->fs->priv_data = ctx;
-
- /* Set the superblock flags */
- e2fsck_clear_recover(ctx, recover_retval);
- return recover_retval;
-}
-
-/*
- * This function will move the journal inode from a visible file in
- * the filesystem directory hierarchy to the reserved inode if necessary.
- */
-static const char *const journal_names[] = {
- ".journal", "journal", ".journal.dat", "journal.dat", 0 };
-
-static void e2fsck_move_ext3_journal(e2fsck_t ctx)
-{
- struct ext2_super_block *sb = ctx->fs->super;
- struct problem_context pctx;
- struct ext2_inode inode;
- ext2_filsys fs = ctx->fs;
- ext2_ino_t ino;
- errcode_t retval;
- const char *const * cpp;
- int group, mount_flags;
-
- clear_problem_context(&pctx);
-
- /*
- * If the filesystem is opened read-only, or there is no
- * journal, then do nothing.
- */
- if ((ctx->options & E2F_OPT_READONLY) ||
- (sb->s_journal_inum == 0) ||
- !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
- return;
-
- /*
- * Read in the journal inode
- */
- if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
- return;
-
- /*
- * If it's necessary to backup the journal inode, do so.
- */
- if ((sb->s_jnl_backup_type == 0) ||
- ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
- memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
- if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
- memcpy(sb->s_jnl_blocks, inode.i_block,
- EXT2_N_BLOCKS*4);
- sb->s_jnl_blocks[16] = inode.i_size;
- sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
- ext2fs_mark_super_dirty(fs);
- fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
- }
- }
-
- /*
- * If the journal is already the hidden inode, then do nothing
- */
- if (sb->s_journal_inum == EXT2_JOURNAL_INO)
- return;
-
- /*
- * The journal inode had better have only one link and not be readable.
- */
- if (inode.i_links_count != 1)
- return;
-
- /*
- * If the filesystem is mounted, or we can't tell whether
- * or not it's mounted, do nothing.
- */
- retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
- if (retval || (mount_flags & EXT2_MF_MOUNTED))
- return;
-
- /*
- * If we can't find the name of the journal inode, then do
- * nothing.
- */
- for (cpp = journal_names; *cpp; cpp++) {
- retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
- strlen(*cpp), 0, &ino);
- if ((retval == 0) && (ino == sb->s_journal_inum))
- break;
- }
- if (*cpp == 0)
- return;
-
- /* We need the inode bitmap to be loaded */
- retval = ext2fs_read_bitmaps(fs);
- if (retval)
- return;
-
- pctx.str = *cpp;
- if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
- return;
-
- /*
- * OK, we've done all the checks, let's actually move the
- * journal inode. Errors at this point mean we need to force
- * an ext2 filesystem check.
- */
- if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
- goto err_out;
- if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
- goto err_out;
- sb->s_journal_inum = EXT2_JOURNAL_INO;
- ext2fs_mark_super_dirty(fs);
- fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
- inode.i_links_count = 0;
- inode.i_dtime = time(NULL);
- if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
- goto err_out;
-
- group = ext2fs_group_of_ino(fs, ino);
- ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
- ext2fs_mark_ib_dirty(fs);
- fs->group_desc[group].bg_free_inodes_count++;
- fs->super->s_free_inodes_count++;
- return;
-
-err_out:
- pctx.errcode = retval;
- fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
- fs->super->s_state &= ~EXT2_VALID_FS;
- ext2fs_mark_super_dirty(fs);
-}
-
-/*
- * message.c --- print e2fsck messages (with compression)
- *
- * print_e2fsck_message() prints a message to the user, using
- * compression techniques and expansions of abbreviations.
- *
- * The following % expansions are supported:
- *
- * %b <blk> block number
- * %B <blkcount> integer
- * %c <blk2> block number
- * %Di <dirent>->ino inode number
- * %Dn <dirent>->name string
- * %Dr <dirent>->rec_len
- * %Dl <dirent>->name_len
- * %Dt <dirent>->filetype
- * %d <dir> inode number
- * %g <group> integer
- * %i <ino> inode number
- * %Is <inode> -> i_size
- * %IS <inode> -> i_extra_isize
- * %Ib <inode> -> i_blocks
- * %Il <inode> -> i_links_count
- * %Im <inode> -> i_mode
- * %IM <inode> -> i_mtime
- * %IF <inode> -> i_faddr
- * %If <inode> -> i_file_acl
- * %Id <inode> -> i_dir_acl
- * %Iu <inode> -> i_uid
- * %Ig <inode> -> i_gid
- * %j <ino2> inode number
- * %m <com_err error message>
- * %N <num>
- * %p ext2fs_get_pathname of directory <ino>
- * %P ext2fs_get_pathname of <dirent>->ino with <ino2> as
- * the containing directory. (If dirent is NULL
- * then return the pathname of directory <ino2>)
- * %q ext2fs_get_pathname of directory <dir>
- * %Q ext2fs_get_pathname of directory <ino> with <dir> as
- * the containing directory.
- * %s <str> miscellaneous string
- * %S backup superblock
- * %X <num> hexadecimal format
- *
- * The following '@' expansions are supported:
- *
- * @a extended attribute
- * @A error allocating
- * @b block
- * @B bitmap
- * @c compress
- * @C conflicts with some other fs block
- * @D deleted
- * @d directory
- * @e entry
- * @E Entry '%Dn' in %p (%i)
- * @f filesystem
- * @F for @i %i (%Q) is
- * @g group
- * @h HTREE directory inode
- * @i inode
- * @I illegal
- * @j journal
- * @l lost+found
- * @L is a link
- * @m multiply-claimed
- * @n invalid
- * @o orphaned
- * @p problem in
- * @r root inode
- * @s should be
- * @S superblock
- * @u unattached
- * @v device
- * @z zero-length
- */
-
-
-/*
- * This structure defines the abbreviations used by the text strings
- * below. The first character in the string is the index letter. An
- * abbreviation of the form '@<i>' is expanded by looking up the index
- * letter <i> in the table below.
- */
-static const char *const abbrevs[] = {
- N_("aextended attribute"),
- N_("Aerror allocating"),
- N_("bblock"),
- N_("Bbitmap"),
- N_("ccompress"),
- N_("Cconflicts with some other fs @b"),
- N_("iinode"),
- N_("Iillegal"),
- N_("jjournal"),
- N_("Ddeleted"),
- N_("ddirectory"),
- N_("eentry"),
- N_("E@e '%Dn' in %p (%i)"),
- N_("ffilesystem"),
- N_("Ffor @i %i (%Q) is"),
- N_("ggroup"),
- N_("hHTREE @d @i"),
- N_("llost+found"),
- N_("Lis a link"),
- N_("mmultiply-claimed"),
- N_("ninvalid"),
- N_("oorphaned"),
- N_("pproblem in"),
- N_("rroot @i"),
- N_("sshould be"),
- N_("Ssuper@b"),
- N_("uunattached"),
- N_("vdevice"),
- N_("zzero-length"),
- "@@",
- 0
- };
-
-/*
- * Give more user friendly names to the "special" inodes.
- */
-#define num_special_inodes 11
-static const char *const special_inode_name[] =
-{
- N_("<The NULL inode>"), /* 0 */
- N_("<The bad blocks inode>"), /* 1 */
- "/", /* 2 */
- N_("<The ACL index inode>"), /* 3 */
- N_("<The ACL data inode>"), /* 4 */
- N_("<The boot loader inode>"), /* 5 */
- N_("<The undelete directory inode>"), /* 6 */
- N_("<The group descriptor inode>"), /* 7 */
- N_("<The journal inode>"), /* 8 */
- N_("<Reserved inode 9>"), /* 9 */
- N_("<Reserved inode 10>"), /* 10 */
-};
-
-/*
- * This function does "safe" printing. It will convert non-printable
- * ASCII characters using '^' and M- notation.
- */
-static void safe_print(const char *cp, int len)
-{
- unsigned char ch;
-
- if (len < 0)
- len = strlen(cp);
-
- while (len--) {
- ch = *cp++;
- if (ch > 128) {
- fputs("M-", stdout);
- ch -= 128;
- }
- if ((ch < 32) || (ch == 0x7f)) {
- bb_putchar('^');
- ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
- }
- bb_putchar(ch);
- }
-}
-
-
-/*
- * This function prints a pathname, using the ext2fs_get_pathname
- * function
- */
-static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
-{
- errcode_t retval;
- char *path;
-
- if (!dir && (ino < num_special_inodes)) {
- fputs(_(special_inode_name[ino]), stdout);
- return;
- }
-
- retval = ext2fs_get_pathname(fs, dir, ino, &path);
- if (retval)
- fputs("???", stdout);
- else {
- safe_print(path, -1);
- ext2fs_free_mem(&path);
- }
-}
-
-static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
- struct problem_context *pctx, int first);
-/*
- * This function handles the '@' expansion. We allow recursive
- * expansion; an @ expression can contain further '@' and '%'
- * expressions.
- */
-static void expand_at_expression(e2fsck_t ctx, char ch,
- struct problem_context *pctx,
- int *first)
-{
- const char *const *cpp;
- const char *str;
-
- /* Search for the abbreviation */
- for (cpp = abbrevs; *cpp; cpp++) {
- if (ch == *cpp[0])
- break;
- }
- if (*cpp) {
- str = _(*cpp) + 1;
- if (*first && islower(*str)) {
- *first = 0;
- bb_putchar(toupper(*str++));
- }
- print_e2fsck_message(ctx, str, pctx, *first);
- } else
- printf("@%c", ch);
-}
-
-/*
- * This function expands '%IX' expressions
- */
-static void expand_inode_expression(char ch,
- struct problem_context *ctx)
-{
- struct ext2_inode *inode;
- struct ext2_inode_large *large_inode;
- char * time_str;
- time_t t;
- int do_gmt = -1;
-
- if (!ctx || !ctx->inode)
- goto no_inode;
-
- inode = ctx->inode;
- large_inode = (struct ext2_inode_large *) inode;
-
- switch (ch) {
- case 's':
- if (LINUX_S_ISDIR(inode->i_mode))
- printf("%u", inode->i_size);
- else {
- printf("%"PRIu64, (inode->i_size |
- ((uint64_t) inode->i_size_high << 32)));
- }
- break;
- case 'S':
- printf("%u", large_inode->i_extra_isize);
- break;
- case 'b':
- printf("%u", inode->i_blocks);
- break;
- case 'l':
- printf("%d", inode->i_links_count);
- break;
- case 'm':
- printf("0%o", inode->i_mode);
- break;
- case 'M':
- /* The diet libc doesn't respect the TZ environemnt variable */
- if (do_gmt == -1) {
- time_str = getenv("TZ");
- if (!time_str)
- time_str = (char *)"";
- do_gmt = !strcmp(time_str, "GMT");
- }
- t = inode->i_mtime;
- time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
- printf("%.24s", time_str);
- break;
- case 'F':
- printf("%u", inode->i_faddr);
- break;
- case 'f':
- printf("%u", inode->i_file_acl);
- break;
- case 'd':
- printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
- inode->i_dir_acl : 0));
- break;
- case 'u':
- printf("%d", (inode->i_uid |
- (inode->osd2.linux2.l_i_uid_high << 16)));
- break;
- case 'g':
- printf("%d", (inode->i_gid |
- (inode->osd2.linux2.l_i_gid_high << 16)));
- break;
- default:
- no_inode:
- printf("%%I%c", ch);
- break;
- }
-}
-
-/*
- * This function expands '%dX' expressions
- */
-static void expand_dirent_expression(char ch,
- struct problem_context *ctx)
-{
- struct ext2_dir_entry *dirent;
- int len;
-
- if (!ctx || !ctx->dirent)
- goto no_dirent;
-
- dirent = ctx->dirent;
-
- switch (ch) {
- case 'i':
- printf("%u", dirent->inode);
- break;
- case 'n':
- len = dirent->name_len & 0xFF;
- if (len > EXT2_NAME_LEN)
- len = EXT2_NAME_LEN;
- if (len > dirent->rec_len)
- len = dirent->rec_len;
- safe_print(dirent->name, len);
- break;
- case 'r':
- printf("%u", dirent->rec_len);
- break;
- case 'l':
- printf("%u", dirent->name_len & 0xFF);
- break;
- case 't':
- printf("%u", dirent->name_len >> 8);
- break;
- default:
- no_dirent:
- printf("%%D%c", ch);
- break;
- }
-}
-
-static void expand_percent_expression(ext2_filsys fs, char ch,
- struct problem_context *ctx)
-{
- if (!ctx)
- goto no_context;
-
- switch (ch) {
- case '%':
- bb_putchar('%');
- break;
- case 'b':
- printf("%u", ctx->blk);
- break;
- case 'B':
- printf("%"PRIi64, ctx->blkcount);
- break;
- case 'c':
- printf("%u", ctx->blk2);
- break;
- case 'd':
- printf("%u", ctx->dir);
- break;
- case 'g':
- printf("%d", ctx->group);
- break;
- case 'i':
- printf("%u", ctx->ino);
- break;
- case 'j':
- printf("%u", ctx->ino2);
- break;
- case 'm':
- fputs(error_message(ctx->errcode), stdout);
- break;
- case 'N':
- printf("%"PRIi64, ctx->num);
- break;
- case 'p':
- print_pathname(fs, ctx->ino, 0);
- break;
- case 'P':
- print_pathname(fs, ctx->ino2,
- ctx->dirent ? ctx->dirent->inode : 0);
- break;
- case 'q':
- print_pathname(fs, ctx->dir, 0);
- break;
- case 'Q':
- print_pathname(fs, ctx->dir, ctx->ino);
- break;
- case 'S':
- printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
- break;
- case 's':
- fputs((ctx->str ? ctx->str : "NULL"), stdout);
- break;
- case 'X':
- printf("0x%"PRIi64, ctx->num);
- break;
- default:
- no_context:
- printf("%%%c", ch);
- break;
- }
-}
-
-
-static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
- struct problem_context *pctx, int first)
-{
- ext2_filsys fs = ctx->fs;
- const char * cp;
- int i;
-
- e2fsck_clear_progbar(ctx);
- for (cp = msg; *cp; cp++) {
- if (cp[0] == '@') {
- cp++;
- expand_at_expression(ctx, *cp, pctx, &first);
- } else if (cp[0] == '%' && cp[1] == 'I') {
- cp += 2;
- expand_inode_expression(*cp, pctx);
- } else if (cp[0] == '%' && cp[1] == 'D') {
- cp += 2;
- expand_dirent_expression(*cp, pctx);
- } else if ((cp[0] == '%')) {
- cp++;
- expand_percent_expression(fs, *cp, pctx);
- } else {
- for (i=0; cp[i]; i++)
- if ((cp[i] == '@') || cp[i] == '%')
- break;
- printf("%.*s", i, cp);
- cp += i-1;
- }
- first = 0;
- }
-}
-
-
-/*
- * region.c --- code which manages allocations within a region.
- */
-
-struct region_el {
- region_addr_t start;
- region_addr_t end;
- struct region_el *next;
-};
-
-struct region_struct {
- region_addr_t min;
- region_addr_t max;
- struct region_el *allocated;
-};
-
-static region_t region_create(region_addr_t min, region_addr_t max)
-{
- region_t region;
-
- region = xzalloc(sizeof(struct region_struct));
- region->min = min;
- region->max = max;
- return region;
-}
-
-static void region_free(region_t region)
-{
- struct region_el *r, *next;
-
- for (r = region->allocated; r; r = next) {
- next = r->next;
- free(r);
- }
- memset(region, 0, sizeof(struct region_struct));
- free(region);
-}
-
-static int region_allocate(region_t region, region_addr_t start, int n)
-{
- struct region_el *r, *new_region, *prev, *next;
- region_addr_t end;
-
- end = start+n;
- if ((start < region->min) || (end > region->max))
- return -1;
- if (n == 0)
- return 1;
-
- /*
- * Search through the linked list. If we find that it
- * conflicts witih something that's already allocated, return
- * 1; if we can find an existing region which we can grow, do
- * so. Otherwise, stop when we find the appropriate place
- * insert a new region element into the linked list.
- */
- for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
- if (((start >= r->start) && (start < r->end)) ||
- ((end > r->start) && (end <= r->end)) ||
- ((start <= r->start) && (end >= r->end)))
- return 1;
- if (end == r->start) {
- r->start = start;
- return 0;
- }
- if (start == r->end) {
- if ((next = r->next)) {
- if (end > next->start)
- return 1;
- if (end == next->start) {
- r->end = next->end;
- r->next = next->next;
- free(next);
- return 0;
- }
- }
- r->end = end;
- return 0;
- }
- if (start < r->start)
- break;
- }
- /*
- * Insert a new region element structure into the linked list
- */
- new_region = xmalloc(sizeof(struct region_el));
- new_region->start = start;
- new_region->end = start + n;
- new_region->next = r;
- if (prev)
- prev->next = new_region;
- else
- region->allocated = new_region;
- return 0;
-}
-
-/*
- * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
- *
- * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
- * and applies the following tests to each inode:
- *
- * - The mode field of the inode must be legal.
- * - The size and block count fields of the inode are correct.
- * - A data block must not be used by another inode
- *
- * Pass 1 also gathers the collects the following information:
- *
- * - A bitmap of which inodes are in use. (inode_used_map)
- * - A bitmap of which inodes are directories. (inode_dir_map)
- * - A bitmap of which inodes are regular files. (inode_reg_map)
- * - A bitmap of which inodes have bad fields. (inode_bad_map)
- * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
- * - A bitmap of which blocks are in use. (block_found_map)
- * - A bitmap of which blocks are in use by two inodes (block_dup_map)
- * - The data blocks of the directory inodes. (dir_map)
- *
- * Pass 1 is designed to stash away enough information so that the
- * other passes should not need to read in the inode information
- * during the normal course of a filesystem check. (Althogh if an
- * inconsistency is detected, other passes may need to read in an
- * inode to fix it.)
- *
- * Note that pass 1B will be invoked if there are any duplicate blocks
- * found.
- */
-
-
-static int process_block(ext2_filsys fs, blk_t *blocknr,
- e2_blkcnt_t blockcnt, blk_t ref_blk,
- int ref_offset, void *priv_data);
-static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
- e2_blkcnt_t blockcnt, blk_t ref_blk,
- int ref_offset, void *priv_data);
-static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
- char *block_buf);
-static void mark_table_blocks(e2fsck_t ctx);
-static void alloc_imagic_map(e2fsck_t ctx);
-static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
-static void handle_fs_bad_blocks(e2fsck_t ctx);
-static void process_inodes(e2fsck_t ctx, char *block_buf);
-static int process_inode_cmp(const void *a, const void *b);
-static errcode_t scan_callback(ext2_filsys fs,
- dgrp_t group, void * priv_data);
-static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
- char *block_buf, int adjust_sign);
-/* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
-
-static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
- struct ext2_inode * inode, int bufsize,
- const char *proc);
-
-struct process_block_struct_1 {
- ext2_ino_t ino;
- unsigned is_dir:1, is_reg:1, clear:1, suppress:1,
- fragmented:1, compressed:1, bbcheck:1;
- blk_t num_blocks;
- blk_t max_blocks;
- e2_blkcnt_t last_block;
- int num_illegal_blocks;
- blk_t previous_block;
- struct ext2_inode *inode;
- struct problem_context *pctx;
- ext2fs_block_bitmap fs_meta_blocks;
- e2fsck_t ctx;
-};
-
-struct process_inode_block {
- ext2_ino_t ino;
- struct ext2_inode inode;
-};
-
-struct scan_callback_struct {
- e2fsck_t ctx;
- char *block_buf;
-};
-
-/*
- * For the inodes to process list.
- */
-static struct process_inode_block *inodes_to_process;
-static int process_inode_count;
-
-static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
- EXT2_MIN_BLOCK_LOG_SIZE + 1];
-
-/*
- * Free all memory allocated by pass1 in preparation for restarting
- * things.
- */
-static void unwind_pass1(void)
-{
- ext2fs_free_mem(&inodes_to_process);
-}
-
-/*
- * Check to make sure a device inode is real. Returns 1 if the device
- * checks out, 0 if not.
- *
- * Note: this routine is now also used to check FIFO's and Sockets,
- * since they have the same requirement; the i_block fields should be
- * zero.
- */
-static int
-e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
-{
- int i;
-
- /*
- * If i_blocks is non-zero, or the index flag is set, then
- * this is a bogus device/fifo/socket
- */
- if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
- (inode->i_flags & EXT2_INDEX_FL))
- return 0;
-
- /*
- * We should be able to do the test below all the time, but
- * because the kernel doesn't forcibly clear the device
- * inode's additional i_block fields, there are some rare
- * occasions when a legitimate device inode will have non-zero
- * additional i_block fields. So for now, we only complain
- * when the immutable flag is set, which should never happen
- * for devices. (And that's when the problem is caused, since
- * you can't set or clear immutable flags for devices.) Once
- * the kernel has been fixed we can change this...
- */
- if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
- for (i=4; i < EXT2_N_BLOCKS; i++)
- if (inode->i_block[i])
- return 0;
- }
- return 1;
-}
-
-/*
- * Check to make sure a symlink inode is real. Returns 1 if the symlink
- * checks out, 0 if not.
- */
-static int
-e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
-{
- unsigned int len;
- int i;
- blk_t blocks;
-
- if ((inode->i_size_high || inode->i_size == 0) ||
- (inode->i_flags & EXT2_INDEX_FL))
- return 0;
-
- blocks = ext2fs_inode_data_blocks(fs, inode);
- if (blocks) {
- if ((inode->i_size >= fs->blocksize) ||
- (blocks != fs->blocksize >> 9) ||
- (inode->i_block[0] < fs->super->s_first_data_block) ||
- (inode->i_block[0] >= fs->super->s_blocks_count))
- return 0;
-
- for (i = 1; i < EXT2_N_BLOCKS; i++)
- if (inode->i_block[i])
- return 0;
-
- if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
- return 0;
-
- len = strnlen(buf, fs->blocksize);
- if (len == fs->blocksize)
- return 0;
- } else {
- if (inode->i_size >= sizeof(inode->i_block))
- return 0;
-
- len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
- if (len == sizeof(inode->i_block))
- return 0;
- }
- if (len != inode->i_size)
- return 0;
- return 1;
-}
-
-/*
- * If the immutable (or append-only) flag is set on the inode, offer
- * to clear it.
- */
-#define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
-static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
-{
- if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
- return;
-
- if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
- return;
-
- pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
- e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
-}
-
-/*
- * If device, fifo or socket, check size is zero -- if not offer to
- * clear it
- */
-static void check_size(e2fsck_t ctx, struct problem_context *pctx)
-{
- struct ext2_inode *inode = pctx->inode;
-
- if ((inode->i_size == 0) && (inode->i_size_high == 0))
- return;
-
- if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
- return;
-
- inode->i_size = 0;
- inode->i_size_high = 0;
- e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
-}
-
-static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
-{
- struct ext2_super_block *sb = ctx->fs->super;
- struct ext2_inode_large *inode;
- struct ext2_ext_attr_entry *entry;
- char *start, *end;
- int storage_size, remain, offs;
- int problem = 0;
-
- inode = (struct ext2_inode_large *) pctx->inode;
- storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
- inode->i_extra_isize;
- start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
- inode->i_extra_isize + sizeof(__u32);
- end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
- entry = (struct ext2_ext_attr_entry *) start;
-
- /* scan all entry's headers first */
-
- /* take finish entry 0UL into account */
- remain = storage_size - sizeof(__u32);
- offs = end - start;
-
- while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
-
- /* header eats this space */
- remain -= sizeof(struct ext2_ext_attr_entry);
-
- /* is attribute name valid? */
- if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
- pctx->num = entry->e_name_len;
- problem = PR_1_ATTR_NAME_LEN;
- goto fix;
- }
-
- /* attribute len eats this space */
- remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
-
- /* check value size */
- if (entry->e_value_size == 0 || entry->e_value_size > remain) {
- pctx->num = entry->e_value_size;
- problem = PR_1_ATTR_VALUE_SIZE;
- goto fix;
- }
-
- /* check value placement */
- if (entry->e_value_offs +
- EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
- printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
- pctx->num = entry->e_value_offs;
- problem = PR_1_ATTR_VALUE_OFFSET;
- goto fix;
- }
-
- /* e_value_block must be 0 in inode's ea */
- if (entry->e_value_block != 0) {
- pctx->num = entry->e_value_block;
- problem = PR_1_ATTR_VALUE_BLOCK;
- goto fix;
- }
-
- /* e_hash must be 0 in inode's ea */
- if (entry->e_hash != 0) {
- pctx->num = entry->e_hash;
- problem = PR_1_ATTR_HASH;
- goto fix;
- }
-
- remain -= entry->e_value_size;
- offs -= EXT2_XATTR_SIZE(entry->e_value_size);
-
- entry = EXT2_EXT_ATTR_NEXT(entry);
- }
-fix:
- /*
- * it seems like a corruption. it's very unlikely we could repair
- * EA(s) in automatic fashion -bzzz
- */
- if (problem == 0 || !fix_problem(ctx, problem, pctx))
- return;
-
- /* simple remove all possible EA(s) */
- *((__u32 *)start) = 0UL;
- e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
- EXT2_INODE_SIZE(sb), "pass1");
-}
-
-static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
-{
- struct ext2_super_block *sb = ctx->fs->super;
- struct ext2_inode_large *inode;
- __u32 *eamagic;
- int min, max;
-
- inode = (struct ext2_inode_large *) pctx->inode;
- if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
- /* this isn't large inode. so, nothing to check */
- return;
- }
-
- /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
- min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
- max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
- /*
- * For now we will allow i_extra_isize to be 0, but really
- * implementations should never allow i_extra_isize to be 0
- */
- if (inode->i_extra_isize &&
- (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
- if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
- return;
- inode->i_extra_isize = min;
- e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
- EXT2_INODE_SIZE(sb), "pass1");
- return;
- }
-
- eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
- inode->i_extra_isize);
- if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
- /* it seems inode has an extended attribute(s) in body */
- check_ea_in_inode(ctx, pctx);
- }
-}
-
-static void e2fsck_pass1(e2fsck_t ctx)
-{
- int i;
- __u64 max_sizes;
- ext2_filsys fs = ctx->fs;
- ext2_ino_t ino;
- struct ext2_inode *inode;
- ext2_inode_scan scan;
- char *block_buf;
- unsigned char frag, fsize;
- struct problem_context pctx;
- struct scan_callback_struct scan_struct;
- struct ext2_super_block *sb = ctx->fs->super;
- int imagic_fs;
- int busted_fs_time = 0;
- int inode_size;
-
- clear_problem_context(&pctx);
-
- if (!(ctx->options & E2F_OPT_PREEN))
- fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
-
- if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
- !(ctx->options & E2F_OPT_NO)) {
- if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
- ctx->dirs_to_hash = 0;
- }
-
- /* Pass 1 */
-
-#define EXT2_BPP(bits) (1ULL << ((bits) - 2))
-
- for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
- max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
- max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
- max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
- max_sizes = (max_sizes * (1UL << i)) - 1;
- ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
- }
-#undef EXT2_BPP
-
- imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
-
- /*
- * Allocate bitmaps structures
- */
- pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
- &ctx->inode_used_map);
- if (pctx.errcode) {
- pctx.num = 1;
- fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
- _("directory inode map"), &ctx->inode_dir_map);
- if (pctx.errcode) {
- pctx.num = 2;
- fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
- _("regular file inode map"), &ctx->inode_reg_map);
- if (pctx.errcode) {
- pctx.num = 6;
- fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
- &ctx->block_found_map);
- if (pctx.errcode) {
- pctx.num = 1;
- fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
- &ctx->inode_link_info);
- if (pctx.errcode) {
- fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- inode_size = EXT2_INODE_SIZE(fs->super);
- inode = (struct ext2_inode *)
- e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
-
- inodes_to_process = (struct process_inode_block *)
- e2fsck_allocate_memory(ctx,
- (ctx->process_inode_size *
- sizeof(struct process_inode_block)),
- "array of inodes to process");
- process_inode_count = 0;
-
- pctx.errcode = ext2fs_init_dblist(fs, 0);
- if (pctx.errcode) {
- fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-
- /*
- * If the last orphan field is set, clear it, since the pass1
- * processing will automatically find and clear the orphans.
- * In the future, we may want to try using the last_orphan
- * linked list ourselves, but for now, we clear it so that the
- * ext3 mount code won't get confused.
- */
- if (!(ctx->options & E2F_OPT_READONLY)) {
- if (fs->super->s_last_orphan) {
- fs->super->s_last_orphan = 0;
- ext2fs_mark_super_dirty(fs);
- }
- }
-
- mark_table_blocks(ctx);
- block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
- "block interate buffer");
- e2fsck_use_inode_shortcuts(ctx, 1);
- ehandler_operation(_("doing inode scan"));
- pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
- &scan);
- if (pctx.errcode) {
- fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
- ctx->stashed_inode = inode;
- scan_struct.ctx = ctx;
- scan_struct.block_buf = block_buf;
- ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
- if (ctx->progress)
- if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
- return;
- if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
- (fs->super->s_mtime < fs->super->s_inodes_count))
- busted_fs_time = 1;
-
- while (1) {
- pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
- inode, inode_size);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
- if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
- continue;
- }
- if (pctx.errcode) {
- fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- if (!ino)
- break;
- pctx.ino = ino;
- pctx.inode = inode;
- ctx->stashed_ino = ino;
- if (inode->i_links_count) {
- pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
- ino, inode->i_links_count);
- if (pctx.errcode) {
- pctx.num = inode->i_links_count;
- fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- }
- if (ino == EXT2_BAD_INO) {
- struct process_block_struct_1 pb;
-
- pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
- &pb.fs_meta_blocks);
- if (pctx.errcode) {
- pctx.num = 4;
- fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- pb.ino = EXT2_BAD_INO;
- pb.num_blocks = pb.last_block = 0;
- pb.num_illegal_blocks = 0;
- pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
- pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
- pb.inode = inode;
- pb.pctx = &pctx;
- pb.ctx = ctx;
- pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
- block_buf, process_bad_block, &pb);
- ext2fs_free_block_bitmap(pb.fs_meta_blocks);
- if (pctx.errcode) {
- fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- if (pb.bbcheck)
- if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
- clear_problem_context(&pctx);
- continue;
- } else if (ino == EXT2_ROOT_INO) {
- /*
- * Make sure the root inode is a directory; if
- * not, offer to clear it. It will be
- * regnerated in pass #3.
- */
- if (!LINUX_S_ISDIR(inode->i_mode)) {
- if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
- inode->i_dtime = time(NULL);
- inode->i_links_count = 0;
- ext2fs_icount_store(ctx->inode_link_info,
- ino, 0);
- e2fsck_write_inode(ctx, ino, inode,
- "pass1");
- }
- }
- /*
- * If dtime is set, offer to clear it. mke2fs
- * version 0.2b created filesystems with the
- * dtime field set for the root and lost+found
- * directories. We won't worry about
- * /lost+found, since that can be regenerated
- * easily. But we will fix the root directory
- * as a special case.
- */
- if (inode->i_dtime && inode->i_links_count) {
- if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
- inode->i_dtime = 0;
- e2fsck_write_inode(ctx, ino, inode,
- "pass1");
- }
- }
- } else if (ino == EXT2_JOURNAL_INO) {
- ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
- if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
- if (!LINUX_S_ISREG(inode->i_mode) &&
- fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
- &pctx)) {
- inode->i_mode = LINUX_S_IFREG;
- e2fsck_write_inode(ctx, ino, inode,
- "pass1");
- }
- check_blocks(ctx, &pctx, block_buf);
- continue;
- }
- if ((inode->i_links_count || inode->i_blocks ||
- inode->i_blocks || inode->i_block[0]) &&
- fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
- &pctx)) {
- memset(inode, 0, inode_size);
- ext2fs_icount_store(ctx->inode_link_info,
- ino, 0);
- e2fsck_write_inode_full(ctx, ino, inode,
- inode_size, "pass1");
- }
- } else if (ino < EXT2_FIRST_INODE(fs->super)) {
- int problem = 0;
-
- ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
- if (ino == EXT2_BOOT_LOADER_INO) {
- if (LINUX_S_ISDIR(inode->i_mode))
- problem = PR_1_RESERVED_BAD_MODE;
- } else if (ino == EXT2_RESIZE_INO) {
- if (inode->i_mode &&
- !LINUX_S_ISREG(inode->i_mode))
- problem = PR_1_RESERVED_BAD_MODE;
- } else {
- if (inode->i_mode != 0)
- problem = PR_1_RESERVED_BAD_MODE;
- }
- if (problem) {
- if (fix_problem(ctx, problem, &pctx)) {
- inode->i_mode = 0;
- e2fsck_write_inode(ctx, ino, inode,
- "pass1");
- }
- }
- check_blocks(ctx, &pctx, block_buf);
- continue;
- }
- /*
- * Check for inodes who might have been part of the
- * orphaned list linked list. They should have gotten
- * dealt with by now, unless the list had somehow been
- * corrupted.
- *
- * FIXME: In the future, inodes which are still in use
- * (and which are therefore) pending truncation should
- * be handled specially. Right now we just clear the
- * dtime field, and the normal e2fsck handling of
- * inodes where i_size and the inode blocks are
- * inconsistent is to fix i_size, instead of releasing
- * the extra blocks. This won't catch the inodes that
- * was at the end of the orphan list, but it's better
- * than nothing. The right answer is that there
- * shouldn't be any bugs in the orphan list handling. :-)
- */
- if (inode->i_dtime && !busted_fs_time &&
- inode->i_dtime < ctx->fs->super->s_inodes_count) {
- if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
- inode->i_dtime = inode->i_links_count ?
- 0 : time(NULL);
- e2fsck_write_inode(ctx, ino, inode,
- "pass1");
- }
- }
-
- /*
- * This code assumes that deleted inodes have
- * i_links_count set to 0.
- */
- if (!inode->i_links_count) {
- if (!inode->i_dtime && inode->i_mode) {
- if (fix_problem(ctx,
- PR_1_ZERO_DTIME, &pctx)) {
- inode->i_dtime = time(NULL);
- e2fsck_write_inode(ctx, ino, inode,
- "pass1");
- }
- }
- continue;
- }
- /*
- * n.b. 0.3c ext2fs code didn't clear i_links_count for
- * deleted files. Oops.
- *
- * Since all new ext2 implementations get this right,
- * we now assume that the case of non-zero
- * i_links_count and non-zero dtime means that we
- * should keep the file, not delete it.
- *
- */
- if (inode->i_dtime) {
- if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
- inode->i_dtime = 0;
- e2fsck_write_inode(ctx, ino, inode, "pass1");
- }
- }
-
- ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
- switch (fs->super->s_creator_os) {
- case EXT2_OS_LINUX:
- frag = inode->osd2.linux2.l_i_frag;
- fsize = inode->osd2.linux2.l_i_fsize;
- break;
- case EXT2_OS_HURD:
- frag = inode->osd2.hurd2.h_i_frag;
- fsize = inode->osd2.hurd2.h_i_fsize;
- break;
- case EXT2_OS_MASIX:
- frag = inode->osd2.masix2.m_i_frag;
- fsize = inode->osd2.masix2.m_i_fsize;
- break;
- default:
- frag = fsize = 0;
- }
-
- if (inode->i_faddr || frag || fsize ||
- (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
- mark_inode_bad(ctx, ino);
- if (inode->i_flags & EXT2_IMAGIC_FL) {
- if (imagic_fs) {
- if (!ctx->inode_imagic_map)
- alloc_imagic_map(ctx);
- ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
- ino);
- } else {
- if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
- inode->i_flags &= ~EXT2_IMAGIC_FL;
- e2fsck_write_inode(ctx, ino,
- inode, "pass1");
- }
- }
- }
-
- check_inode_extra_space(ctx, &pctx);
-
- if (LINUX_S_ISDIR(inode->i_mode)) {
- ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
- e2fsck_add_dir_info(ctx, ino, 0);
- ctx->fs_directory_count++;
- } else if (LINUX_S_ISREG (inode->i_mode)) {
- ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
- ctx->fs_regular_count++;
- } else if (LINUX_S_ISCHR (inode->i_mode) &&
- e2fsck_pass1_check_device_inode(fs, inode)) {
- check_immutable(ctx, &pctx);
- check_size(ctx, &pctx);
- ctx->fs_chardev_count++;
- } else if (LINUX_S_ISBLK (inode->i_mode) &&
- e2fsck_pass1_check_device_inode(fs, inode)) {
- check_immutable(ctx, &pctx);
- check_size(ctx, &pctx);
- ctx->fs_blockdev_count++;
- } else if (LINUX_S_ISLNK (inode->i_mode) &&
- e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
- check_immutable(ctx, &pctx);
- ctx->fs_symlinks_count++;
- if (ext2fs_inode_data_blocks(fs, inode) == 0) {
- ctx->fs_fast_symlinks_count++;
- check_blocks(ctx, &pctx, block_buf);
- continue;
- }
- }
- else if (LINUX_S_ISFIFO (inode->i_mode) &&
- e2fsck_pass1_check_device_inode(fs, inode)) {
- check_immutable(ctx, &pctx);
- check_size(ctx, &pctx);
- ctx->fs_fifo_count++;
- } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
- e2fsck_pass1_check_device_inode(fs, inode)) {
- check_immutable(ctx, &pctx);
- check_size(ctx, &pctx);
- ctx->fs_sockets_count++;
- } else
- mark_inode_bad(ctx, ino);
- if (inode->i_block[EXT2_IND_BLOCK])
- ctx->fs_ind_count++;
- if (inode->i_block[EXT2_DIND_BLOCK])
- ctx->fs_dind_count++;
- if (inode->i_block[EXT2_TIND_BLOCK])
- ctx->fs_tind_count++;
- if (inode->i_block[EXT2_IND_BLOCK] ||
- inode->i_block[EXT2_DIND_BLOCK] ||
- inode->i_block[EXT2_TIND_BLOCK] ||
- inode->i_file_acl) {
- inodes_to_process[process_inode_count].ino = ino;
- inodes_to_process[process_inode_count].inode = *inode;
- process_inode_count++;
- } else
- check_blocks(ctx, &pctx, block_buf);
-
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
-
- if (process_inode_count >= ctx->process_inode_size) {
- process_inodes(ctx, block_buf);
-
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
- }
- }
- process_inodes(ctx, block_buf);
- ext2fs_close_inode_scan(scan);
- ehandler_operation(0);
-
- /*
- * If any extended attribute blocks' reference counts need to
- * be adjusted, either up (ctx->refcount_extra), or down
- * (ctx->refcount), then fix them.
- */
- if (ctx->refcount) {
- adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
- ea_refcount_free(ctx->refcount);
- ctx->refcount = 0;
- }
- if (ctx->refcount_extra) {
- adjust_extattr_refcount(ctx, ctx->refcount_extra,
- block_buf, +1);
- ea_refcount_free(ctx->refcount_extra);
- ctx->refcount_extra = 0;
- }
-
- if (ctx->invalid_bitmaps)
- handle_fs_bad_blocks(ctx);
-
- /* We don't need the block_ea_map any more */
- ext2fs_free_block_bitmap(ctx->block_ea_map);
- ctx->block_ea_map = 0;
-
- if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
- ext2fs_block_bitmap save_bmap;
-
- save_bmap = fs->block_map;
- fs->block_map = ctx->block_found_map;
- clear_problem_context(&pctx);
- pctx.errcode = ext2fs_create_resize_inode(fs);
- if (pctx.errcode) {
- fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
- /* Should never get here */
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
- "recreate inode");
- inode->i_mtime = time(NULL);
- e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
- "recreate inode");
- fs->block_map = save_bmap;
- ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
- }
-
- if (ctx->flags & E2F_FLAG_RESTART) {
- /*
- * Only the master copy of the superblock and block
- * group descriptors are going to be written during a
- * restart, so set the superblock to be used to be the
- * master superblock.
- */
- ctx->use_superblock = 0;
- unwind_pass1();
- goto endit;
- }
-
- if (ctx->block_dup_map) {
- if (ctx->options & E2F_OPT_PREEN) {
- clear_problem_context(&pctx);
- fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
- }
- e2fsck_pass1_dupblocks(ctx, block_buf);
- }
- ext2fs_free_mem(&inodes_to_process);
-endit:
- e2fsck_use_inode_shortcuts(ctx, 0);
-
- ext2fs_free_mem(&block_buf);
- ext2fs_free_mem(&inode);
-}
-
-/*
- * When the inode_scan routines call this callback at the end of the
- * glock group, call process_inodes.
- */
-static errcode_t scan_callback(ext2_filsys fs,
- dgrp_t group, void * priv_data)
-{
- struct scan_callback_struct *scan_struct;
- e2fsck_t ctx;
-
- scan_struct = (struct scan_callback_struct *) priv_data;
- ctx = scan_struct->ctx;
-
- process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
-
- if (ctx->progress)
- if ((ctx->progress)(ctx, 1, group+1,
- ctx->fs->group_desc_count))
- return EXT2_ET_CANCEL_REQUESTED;
-
- return 0;
-}
-
-/*
- * Process the inodes in the "inodes to process" list.
- */
-static void process_inodes(e2fsck_t ctx, char *block_buf)
-{
- int i;
- struct ext2_inode *old_stashed_inode;
- ext2_ino_t old_stashed_ino;
- const char *old_operation;
- char buf[80];
- struct problem_context pctx;
-
- /* begin process_inodes */
- if (process_inode_count == 0)
- return;
- old_operation = ehandler_operation(0);
- old_stashed_inode = ctx->stashed_inode;
- old_stashed_ino = ctx->stashed_ino;
- qsort(inodes_to_process, process_inode_count,
- sizeof(struct process_inode_block), process_inode_cmp);
- clear_problem_context(&pctx);
- for (i=0; i < process_inode_count; i++) {
- pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
- pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
- sprintf(buf, _("reading indirect blocks of inode %u"),
- pctx.ino);
- ehandler_operation(buf);
- check_blocks(ctx, &pctx, block_buf);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- break;
- }
- ctx->stashed_inode = old_stashed_inode;
- ctx->stashed_ino = old_stashed_ino;
- process_inode_count = 0;
- /* end process inodes */
-
- ehandler_operation(old_operation);
-}
-
-static int process_inode_cmp(const void *a, const void *b)
-{
- const struct process_inode_block *ib_a =
- (const struct process_inode_block *) a;
- const struct process_inode_block *ib_b =
- (const struct process_inode_block *) b;
- int ret;
-
- ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
- ib_b->inode.i_block[EXT2_IND_BLOCK]);
- if (ret == 0)
- ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
- return ret;
-}
-
-/*
- * Mark an inode as being bad in some what
- */
-static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
-{
- struct problem_context pctx;
-
- if (!ctx->inode_bad_map) {
- clear_problem_context(&pctx);
-
- pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
- _("bad inode map"), &ctx->inode_bad_map);
- if (pctx.errcode) {
- pctx.num = 3;
- fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
- /* Should never get here */
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- }
- ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
-}
-
-
-/*
- * This procedure will allocate the inode imagic table
- */
-static void alloc_imagic_map(e2fsck_t ctx)
-{
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
- pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
- _("imagic inode map"),
- &ctx->inode_imagic_map);
- if (pctx.errcode) {
- pctx.num = 5;
- fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
- /* Should never get here */
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-}
-
-/*
- * Marks a block as in use, setting the dup_map if it's been set
- * already. Called by process_block and process_bad_block.
- *
- * WARNING: Assumes checks have already been done to make sure block
- * is valid. This is true in both process_block and process_bad_block.
- */
-static void mark_block_used(e2fsck_t ctx, blk_t block)
-{
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
-
- if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
- if (!ctx->block_dup_map) {
- pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
- _("multiply claimed block map"),
- &ctx->block_dup_map);
- if (pctx.errcode) {
- pctx.num = 3;
- fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
- &pctx);
- /* Should never get here */
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- }
- ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
- } else {
- ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
- }
-}
-
-/*
- * Adjust the extended attribute block's reference counts at the end
- * of pass 1, either by subtracting out references for EA blocks that
- * are still referenced in ctx->refcount, or by adding references for
- * EA blocks that had extra references as accounted for in
- * ctx->refcount_extra.
- */
-static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
- char *block_buf, int adjust_sign)
-{
- struct ext2_ext_attr_header *header;
- struct problem_context pctx;
- ext2_filsys fs = ctx->fs;
- blk_t blk;
- __u32 should_be;
- int count;
-
- clear_problem_context(&pctx);
-
- ea_refcount_intr_begin(refcount);
- while (1) {
- if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
- break;
- pctx.blk = blk;
- pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
- if (pctx.errcode) {
- fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
- return;
- }
- header = (struct ext2_ext_attr_header *) block_buf;
- pctx.blkcount = header->h_refcount;
- should_be = header->h_refcount + adjust_sign * count;
- pctx.num = should_be;
- if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
- header->h_refcount = should_be;
- pctx.errcode = ext2fs_write_ext_attr(fs, blk,
- block_buf);
- if (pctx.errcode) {
- fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
- continue;
- }
- }
- }
-}
-
-/*
- * Handle processing the extended attribute blocks
- */
-static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
- char *block_buf)
-{
- ext2_filsys fs = ctx->fs;
- ext2_ino_t ino = pctx->ino;
- struct ext2_inode *inode = pctx->inode;
- blk_t blk;
- char * end;
- struct ext2_ext_attr_header *header;
- struct ext2_ext_attr_entry *entry;
- int count;
- region_t region;
-
- blk = inode->i_file_acl;
- if (blk == 0)
- return 0;
-
- /*
- * If the Extended attribute flag isn't set, then a non-zero
- * file acl means that the inode is corrupted.
- *
- * Or if the extended attribute block is an invalid block,
- * then the inode is also corrupted.
- */
- if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
- (blk < fs->super->s_first_data_block) ||
- (blk >= fs->super->s_blocks_count)) {
- mark_inode_bad(ctx, ino);
- return 0;
- }
-
- /* If ea bitmap hasn't been allocated, create it */
- if (!ctx->block_ea_map) {
- pctx->errcode = ext2fs_allocate_block_bitmap(fs,
- _("ext attr block map"),
- &ctx->block_ea_map);
- if (pctx->errcode) {
- pctx->num = 2;
- fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return 0;
- }
- }
-
- /* Create the EA refcount structure if necessary */
- if (!ctx->refcount) {
- pctx->errcode = ea_refcount_create(0, &ctx->refcount);
- if (pctx->errcode) {
- pctx->num = 1;
- fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return 0;
- }
- }
-
- /* Have we seen this EA block before? */
- if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
- if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
- return 1;
- /* Ooops, this EA was referenced more than it stated */
- if (!ctx->refcount_extra) {
- pctx->errcode = ea_refcount_create(0,
- &ctx->refcount_extra);
- if (pctx->errcode) {
- pctx->num = 2;
- fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return 0;
- }
- }
- ea_refcount_increment(ctx->refcount_extra, blk, 0);
- return 1;
- }
-
- /*
- * OK, we haven't seen this EA block yet. So we need to
- * validate it
- */
- pctx->blk = blk;
- pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
- if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
- goto clear_extattr;
- header = (struct ext2_ext_attr_header *) block_buf;
- pctx->blk = inode->i_file_acl;
- if (((ctx->ext_attr_ver == 1) &&
- (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
- ((ctx->ext_attr_ver == 2) &&
- (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
- if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
- goto clear_extattr;
- }
-
- if (header->h_blocks != 1) {
- if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
- goto clear_extattr;
- }
-
- region = region_create(0, fs->blocksize);
- if (!region) {
- fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return 0;
- }
- if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
- if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
- goto clear_extattr;
- }
-
- entry = (struct ext2_ext_attr_entry *)(header+1);
- end = block_buf + fs->blocksize;
- while ((char *)entry < end && *(__u32 *)entry) {
- if (region_allocate(region, (char *)entry - (char *)header,
- EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
- if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
- goto clear_extattr;
- }
- if ((ctx->ext_attr_ver == 1 &&
- (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
- (ctx->ext_attr_ver == 2 &&
- entry->e_name_index == 0)) {
- if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
- goto clear_extattr;
- }
- if (entry->e_value_block != 0) {
- if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
- goto clear_extattr;
- }
- if (entry->e_value_size &&
- region_allocate(region, entry->e_value_offs,
- EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
- if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
- goto clear_extattr;
- }
- entry = EXT2_EXT_ATTR_NEXT(entry);
- }
- if (region_allocate(region, (char *)entry - (char *)header, 4)) {
- if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
- goto clear_extattr;
- }
- region_free(region);
-
- count = header->h_refcount - 1;
- if (count)
- ea_refcount_store(ctx->refcount, blk, count);
- mark_block_used(ctx, blk);
- ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
-
- return 1;
-
-clear_extattr:
- inode->i_file_acl = 0;
- e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
- return 0;
-}
-
-/* Returns 1 if bad htree, 0 if OK */
-static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
- ext2_ino_t ino FSCK_ATTR((unused)),
- struct ext2_inode *inode,
- char *block_buf)
-{
- struct ext2_dx_root_info *root;
- ext2_filsys fs = ctx->fs;
- errcode_t retval;
- blk_t blk;
-
- if ((!LINUX_S_ISDIR(inode->i_mode) &&
- fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
- (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
- fix_problem(ctx, PR_1_HTREE_SET, pctx)))
- return 1;
-
- blk = inode->i_block[0];
- if (((blk == 0) ||
- (blk < fs->super->s_first_data_block) ||
- (blk >= fs->super->s_blocks_count)) &&
- fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
- return 1;
-
- retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
- if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
- return 1;
-
- /* XXX should check that beginning matches a directory */
- root = (struct ext2_dx_root_info *) (block_buf + 24);
-
- if ((root->reserved_zero || root->info_length < 8) &&
- fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
- return 1;
-
- pctx->num = root->hash_version;
- if ((root->hash_version != EXT2_HASH_LEGACY) &&
- (root->hash_version != EXT2_HASH_HALF_MD4) &&
- (root->hash_version != EXT2_HASH_TEA) &&
- fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
- return 1;
-
- if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
- fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
- return 1;
-
- pctx->num = root->indirect_levels;
- if ((root->indirect_levels > 1) &&
- fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
- return 1;
-
- return 0;
-}
-
-/*
- * This subroutine is called on each inode to account for all of the
- * blocks used by that inode.
- */
-static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
- char *block_buf)
-{
- ext2_filsys fs = ctx->fs;
- struct process_block_struct_1 pb;
- ext2_ino_t ino = pctx->ino;
- struct ext2_inode *inode = pctx->inode;
- int bad_size = 0;
- int dirty_inode = 0;
- __u64 size;
-
- pb.ino = ino;
- pb.num_blocks = 0;
- pb.last_block = -1;
- pb.num_illegal_blocks = 0;
- pb.suppress = 0; pb.clear = 0;
- pb.fragmented = 0;
- pb.compressed = 0;
- pb.previous_block = 0;
- pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
- pb.is_reg = LINUX_S_ISREG(inode->i_mode);
- pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
- pb.inode = inode;
- pb.pctx = pctx;
- pb.ctx = ctx;
- pctx->ino = ino;
- pctx->errcode = 0;
-
- if (inode->i_flags & EXT2_COMPRBLK_FL) {
- if (fs->super->s_feature_incompat &
- EXT2_FEATURE_INCOMPAT_COMPRESSION)
- pb.compressed = 1;
- else {
- if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
- inode->i_flags &= ~EXT2_COMPRBLK_FL;
- dirty_inode++;
- }
- }
- }
-
- if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
- pb.num_blocks++;
-
- if (ext2fs_inode_has_valid_blocks(inode))
- pctx->errcode = ext2fs_block_iterate2(fs, ino,
- pb.is_dir ? BLOCK_FLAG_HOLE : 0,
- block_buf, process_block, &pb);
- end_problem_latch(ctx, PR_LATCH_BLOCK);
- end_problem_latch(ctx, PR_LATCH_TOOBIG);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- goto out;
- if (pctx->errcode)
- fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
-
- if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
- ctx->fs_fragmented++;
-
- if (pb.clear) {
- inode->i_links_count = 0;
- ext2fs_icount_store(ctx->inode_link_info, ino, 0);
- inode->i_dtime = time(NULL);
- dirty_inode++;
- ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
- ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
- ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
- /*
- * The inode was probably partially accounted for
- * before processing was aborted, so we need to
- * restart the pass 1 scan.
- */
- ctx->flags |= E2F_FLAG_RESTART;
- goto out;
- }
-
- if (inode->i_flags & EXT2_INDEX_FL) {
- if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
- inode->i_flags &= ~EXT2_INDEX_FL;
- dirty_inode++;
- } else {
-#ifdef ENABLE_HTREE
- e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
-#endif
- }
- }
- if (ctx->dirs_to_hash && pb.is_dir &&
- !(inode->i_flags & EXT2_INDEX_FL) &&
- ((inode->i_size / fs->blocksize) >= 3))
- ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
-
- if (!pb.num_blocks && pb.is_dir) {
- if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
- inode->i_links_count = 0;
- ext2fs_icount_store(ctx->inode_link_info, ino, 0);
- inode->i_dtime = time(NULL);
- dirty_inode++;
- ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
- ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
- ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
- ctx->fs_directory_count--;
- goto out;
- }
- }
-
- pb.num_blocks *= (fs->blocksize / 512);
-
- if (pb.is_dir) {
- int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
- if (nblock > (pb.last_block + 1))
- bad_size = 1;
- else if (nblock < (pb.last_block + 1)) {
- if (((pb.last_block + 1) - nblock) >
- fs->super->s_prealloc_dir_blocks)
- bad_size = 2;
- }
- } else {
- size = EXT2_I_SIZE(inode);
- if ((pb.last_block >= 0) &&
- (size < (__u64) pb.last_block * fs->blocksize))
- bad_size = 3;
- else if (size > ext2_max_sizes[fs->super->s_log_block_size])
- bad_size = 4;
- }
- /* i_size for symlinks is checked elsewhere */
- if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
- pctx->num = (pb.last_block+1) * fs->blocksize;
- if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
- inode->i_size = pctx->num;
- if (!LINUX_S_ISDIR(inode->i_mode))
- inode->i_size_high = pctx->num >> 32;
- dirty_inode++;
- }
- pctx->num = 0;
- }
- if (LINUX_S_ISREG(inode->i_mode) &&
- (inode->i_size_high || inode->i_size & 0x80000000UL))
- ctx->large_files++;
- if (pb.num_blocks != inode->i_blocks) {
- pctx->num = pb.num_blocks;
- if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
- inode->i_blocks = pb.num_blocks;
- dirty_inode++;
- }
- pctx->num = 0;
- }
-out:
- if (dirty_inode)
- e2fsck_write_inode(ctx, ino, inode, "check_blocks");
-}
-
-
-/*
- * This is a helper function for check_blocks().
- */
-static int process_block(ext2_filsys fs,
- blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block FSCK_ATTR((unused)),
- int ref_offset FSCK_ATTR((unused)),
- void *priv_data)
-{
- struct process_block_struct_1 *p;
- struct problem_context *pctx;
- blk_t blk = *block_nr;
- int ret_code = 0;
- int problem = 0;
- e2fsck_t ctx;
-
- p = (struct process_block_struct_1 *) priv_data;
- pctx = p->pctx;
- ctx = p->ctx;
-
- if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
- /* todo: Check that the comprblk_fl is high, that the
- blkaddr pattern looks right (all non-holes up to
- first EXT2FS_COMPRESSED_BLKADDR, then all
- EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
- that the feature_incompat bit is high, and that the
- inode is a regular file. If we're doing a "full
- check" (a concept introduced to e2fsck by e2compr,
- meaning that we look at data blocks as well as
- metadata) then call some library routine that
- checks the compressed data. I'll have to think
- about this, because one particularly important
- problem to be able to fix is to recalculate the
- cluster size if necessary. I think that perhaps
- we'd better do most/all e2compr-specific checks
- separately, after the non-e2compr checks. If not
- doing a full check, it may be useful to test that
- the personality is linux; e.g. if it isn't then
- perhaps this really is just an illegal block. */
- return 0;
- }
-
- if (blk == 0) {
- if (p->is_dir == 0) {
- /*
- * Should never happen, since only directories
- * get called with BLOCK_FLAG_HOLE
- */
-#ifdef DEBUG_E2FSCK
- printf("process_block() called with blk == 0, "
- "blockcnt=%d, inode %lu???\n",
- blockcnt, p->ino);
-#endif
- return 0;
- }
- if (blockcnt < 0)
- return 0;
- if (blockcnt * fs->blocksize < p->inode->i_size) {
- goto mark_dir;
- }
- return 0;
- }
-
- /*
- * Simplistic fragmentation check. We merely require that the
- * file be contiguous. (Which can never be true for really
- * big files that are greater than a block group.)
- */
- if (!HOLE_BLKADDR(p->previous_block)) {
- if (p->previous_block+1 != blk)
- p->fragmented = 1;
- }
- p->previous_block = blk;
-
- if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
- problem = PR_1_TOOBIG_DIR;
- if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
- problem = PR_1_TOOBIG_REG;
- if (!p->is_dir && !p->is_reg && blockcnt > 0)
- problem = PR_1_TOOBIG_SYMLINK;
-
- if (blk < fs->super->s_first_data_block ||
- blk >= fs->super->s_blocks_count)
- problem = PR_1_ILLEGAL_BLOCK_NUM;
-
- if (problem) {
- p->num_illegal_blocks++;
- if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
- if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
- p->clear = 1;
- return BLOCK_ABORT;
- }
- if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
- p->suppress = 1;
- set_latch_flags(PR_LATCH_BLOCK,
- PRL_SUPPRESS, 0);
- }
- }
- pctx->blk = blk;
- pctx->blkcount = blockcnt;
- if (fix_problem(ctx, problem, pctx)) {
- blk = *block_nr = 0;
- ret_code = BLOCK_CHANGED;
- goto mark_dir;
- } else
- return 0;
- }
-
- if (p->ino == EXT2_RESIZE_INO) {
- /*
- * The resize inode has already be sanity checked
- * during pass #0 (the superblock checks). All we
- * have to do is mark the double indirect block as
- * being in use; all of the other blocks are handled
- * by mark_table_blocks()).
- */
- if (blockcnt == BLOCK_COUNT_DIND)
- mark_block_used(ctx, blk);
- } else
- mark_block_used(ctx, blk);
- p->num_blocks++;
- if (blockcnt >= 0)
- p->last_block = blockcnt;
-mark_dir:
- if (p->is_dir && (blockcnt >= 0)) {
- pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
- blk, blockcnt);
- if (pctx->errcode) {
- pctx->blk = blk;
- pctx->num = blockcnt;
- fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
- /* Should never get here */
- ctx->flags |= E2F_FLAG_ABORT;
- return BLOCK_ABORT;
- }
- }
- return ret_code;
-}
-
-static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)),
- blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block FSCK_ATTR((unused)),
- int ref_offset FSCK_ATTR((unused)),
- void *priv_data EXT2FS_ATTR((unused)))
-{
- /*
- * Note: This function processes blocks for the bad blocks
- * inode, which is never compressed. So we don't use HOLE_BLKADDR().
- */
-
- printf("Unrecoverable Error: Found %"PRIi64" bad blocks starting at block number: %u\n", blockcnt, *block_nr);
- return BLOCK_ERROR;
-}
-
-/*
- * This routine gets called at the end of pass 1 if bad blocks are
- * detected in the superblock, group descriptors, inode_bitmaps, or
- * block bitmaps. At this point, all of the blocks have been mapped
- * out, so we can try to allocate new block(s) to replace the bad
- * blocks.
- */
-static void handle_fs_bad_blocks(e2fsck_t ctx EXT2FS_ATTR((unused)))
-{
- printf("Bad blocks detected on your filesystem\n"
- "You should get your data off as the device will soon die\n");
-}
-
-/*
- * This routine marks all blocks which are used by the superblock,
- * group descriptors, inode bitmaps, and block bitmaps.
- */
-static void mark_table_blocks(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- blk_t block, b;
- dgrp_t i;
- int j;
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
-
- block = fs->super->s_first_data_block;
- for (i = 0; i < fs->group_desc_count; i++) {
- pctx.group = i;
-
- ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
-
- /*
- * Mark the blocks used for the inode table
- */
- if (fs->group_desc[i].bg_inode_table) {
- for (j = 0, b = fs->group_desc[i].bg_inode_table;
- j < fs->inode_blocks_per_group;
- j++, b++) {
- if (ext2fs_test_block_bitmap(ctx->block_found_map,
- b)) {
- pctx.blk = b;
- if (fix_problem(ctx,
- PR_1_ITABLE_CONFLICT, &pctx)) {
- ctx->invalid_inode_table_flag[i]++;
- ctx->invalid_bitmaps++;
- }
- } else {
- ext2fs_mark_block_bitmap(ctx->block_found_map, b);
- }
- }
- }
-
- /*
- * Mark block used for the block bitmap
- */
- if (fs->group_desc[i].bg_block_bitmap) {
- if (ext2fs_test_block_bitmap(ctx->block_found_map,
- fs->group_desc[i].bg_block_bitmap)) {
- pctx.blk = fs->group_desc[i].bg_block_bitmap;
- if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
- ctx->invalid_block_bitmap_flag[i]++;
- ctx->invalid_bitmaps++;
- }
- } else {
- ext2fs_mark_block_bitmap(ctx->block_found_map,
- fs->group_desc[i].bg_block_bitmap);
- }
- }
- /*
- * Mark block used for the inode bitmap
- */
- if (fs->group_desc[i].bg_inode_bitmap) {
- if (ext2fs_test_block_bitmap(ctx->block_found_map,
- fs->group_desc[i].bg_inode_bitmap)) {
- pctx.blk = fs->group_desc[i].bg_inode_bitmap;
- if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
- ctx->invalid_inode_bitmap_flag[i]++;
- ctx->invalid_bitmaps++;
- }
- } else {
- ext2fs_mark_block_bitmap(ctx->block_found_map,
- fs->group_desc[i].bg_inode_bitmap);
- }
- }
- block += fs->super->s_blocks_per_group;
- }
-}
-
-/*
- * Thes subroutines short circuits ext2fs_get_blocks and
- * ext2fs_check_directory; we use them since we already have the inode
- * structure, so there's no point in letting the ext2fs library read
- * the inode again.
- */
-static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
- blk_t *blocks)
-{
- e2fsck_t ctx = (e2fsck_t) fs->priv_data;
- int i;
-
- if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
- return EXT2_ET_CALLBACK_NOTHANDLED;
-
- for (i=0; i < EXT2_N_BLOCKS; i++)
- blocks[i] = ctx->stashed_inode->i_block[i];
- return 0;
-}
-
-static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode)
-{
- e2fsck_t ctx = (e2fsck_t) fs->priv_data;
-
- if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
- return EXT2_ET_CALLBACK_NOTHANDLED;
- *inode = *ctx->stashed_inode;
- return 0;
-}
-
-static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode)
-{
- e2fsck_t ctx = (e2fsck_t) fs->priv_data;
-
- if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
- *ctx->stashed_inode = *inode;
- return EXT2_ET_CALLBACK_NOTHANDLED;
-}
-
-static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
-{
- e2fsck_t ctx = (e2fsck_t) fs->priv_data;
-
- if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
- return EXT2_ET_CALLBACK_NOTHANDLED;
-
- if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
- return EXT2_ET_NO_DIRECTORY;
- return 0;
-}
-
-void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int fl_bool)
-{
- ext2_filsys fs = ctx->fs;
-
- if (fl_bool) {
- fs->get_blocks = pass1_get_blocks;
- fs->check_directory = pass1_check_directory;
- fs->read_inode = pass1_read_inode;
- fs->write_inode = pass1_write_inode;
- ctx->stashed_ino = 0;
- } else {
- fs->get_blocks = 0;
- fs->check_directory = 0;
- fs->read_inode = 0;
- fs->write_inode = 0;
- }
-}
-
-/*
- * pass1b.c --- Pass #1b of e2fsck
- *
- * This file contains pass1B, pass1C, and pass1D of e2fsck. They are
- * only invoked if pass 1 discovered blocks which are in use by more
- * than one inode.
- *
- * Pass1B scans the data blocks of all the inodes again, generating a
- * complete list of duplicate blocks and which inodes have claimed
- * them.
- *
- * Pass1C does a tree-traversal of the filesystem, to determine the
- * parent directories of these inodes. This step is necessary so that
- * e2fsck can print out the pathnames of affected inodes.
- *
- * Pass1D is a reconciliation pass. For each inode with duplicate
- * blocks, the user is prompted if s/he would like to clone the file
- * (so that the file gets a fresh copy of the duplicated blocks) or
- * simply to delete the file.
- *
- */
-
-
-/* Needed for architectures where sizeof(int) != sizeof(void *) */
-#define INT_TO_VOIDPTR(val) ((void *)(intptr_t)(val))
-#define VOIDPTR_TO_INT(ptr) ((int)(intptr_t)(ptr))
-
-/* Define an extension to the ext2 library's block count information */
-#define BLOCK_COUNT_EXTATTR (-5)
-
-struct block_el {
- blk_t block;
- struct block_el *next;
-};
-
-struct inode_el {
- ext2_ino_t inode;
- struct inode_el *next;
-};
-
-struct dup_block {
- int num_bad;
- struct inode_el *inode_list;
-};
-
-/*
- * This structure stores information about a particular inode which
- * is sharing blocks with other inodes. This information is collected
- * to display to the user, so that the user knows what files he or she
- * is dealing with, when trying to decide how to resolve the conflict
- * of multiply-claimed blocks.
- */
-struct dup_inode {
- ext2_ino_t dir;
- int num_dupblocks;
- struct ext2_inode inode;
- struct block_el *block_list;
-};
-
-static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
- e2_blkcnt_t blockcnt, blk_t ref_blk,
- int ref_offset, void *priv_data);
-static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
- struct dup_inode *dp, char *block_buf);
-static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
- struct dup_inode *dp, char* block_buf);
-static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
-
-static void pass1b(e2fsck_t ctx, char *block_buf);
-static void pass1c(e2fsck_t ctx, char *block_buf);
-static void pass1d(e2fsck_t ctx, char *block_buf);
-
-static int dup_inode_count = 0;
-
-static dict_t blk_dict, ino_dict;
-
-static ext2fs_inode_bitmap inode_dup_map;
-
-static int dict_int_cmp(const void *a, const void *b)
-{
- intptr_t ia, ib;
-
- ia = (intptr_t)a;
- ib = (intptr_t)b;
-
- return (ia-ib);
-}
-
-/*
- * Add a duplicate block record
- */
-static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
- struct ext2_inode *inode)
-{
- dnode_t *n;
- struct dup_block *db;
- struct dup_inode *di;
- struct block_el *blk_el;
- struct inode_el *ino_el;
-
- n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
- if (n)
- db = (struct dup_block *) dnode_get(n);
- else {
- db = (struct dup_block *) e2fsck_allocate_memory(ctx,
- sizeof(struct dup_block), "duplicate block header");
- db->num_bad = 0;
- db->inode_list = 0;
- dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
- }
- ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
- sizeof(struct inode_el), "inode element");
- ino_el->inode = ino;
- ino_el->next = db->inode_list;
- db->inode_list = ino_el;
- db->num_bad++;
-
- n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
- if (n)
- di = (struct dup_inode *) dnode_get(n);
- else {
- di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
- sizeof(struct dup_inode), "duplicate inode header");
- di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0;
- di->num_dupblocks = 0;
- di->block_list = 0;
- di->inode = *inode;
- dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
- }
- blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
- sizeof(struct block_el), "block element");
- blk_el->block = blk;
- blk_el->next = di->block_list;
- di->block_list = blk_el;
- di->num_dupblocks++;
-}
-
-/*
- * Free a duplicate inode record
- */
-static void inode_dnode_free(dnode_t *node)
-{
- struct dup_inode *di;
- struct block_el *p, *next;
-
- di = (struct dup_inode *) dnode_get(node);
- for (p = di->block_list; p; p = next) {
- next = p->next;
- free(p);
- }
- free(node);
-}
-
-/*
- * Free a duplicate block record
- */
-static void block_dnode_free(dnode_t *node)
-{
- struct dup_block *db;
- struct inode_el *p, *next;
-
- db = (struct dup_block *) dnode_get(node);
- for (p = db->inode_list; p; p = next) {
- next = p->next;
- free(p);
- }
- free(node);
-}
-
-
-/*
- * Main procedure for handling duplicate blocks
- */
-void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
-{
- ext2_filsys fs = ctx->fs;
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
-
- pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
- _("multiply claimed inode map"), &inode_dup_map);
- if (pctx.errcode) {
- fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-
- dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
- dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
- dict_set_allocator(&ino_dict, inode_dnode_free);
- dict_set_allocator(&blk_dict, block_dnode_free);
-
- pass1b(ctx, block_buf);
- pass1c(ctx, block_buf);
- pass1d(ctx, block_buf);
-
- /*
- * Time to free all of the accumulated data structures that we
- * don't need anymore.
- */
- dict_free_nodes(&ino_dict);
- dict_free_nodes(&blk_dict);
-}
-
-/*
- * Scan the inodes looking for inodes that contain duplicate blocks.
- */
-struct process_block_struct_1b {
- e2fsck_t ctx;
- ext2_ino_t ino;
- int dup_blocks;
- struct ext2_inode *inode;
- struct problem_context *pctx;
-};
-
-static void pass1b(e2fsck_t ctx, char *block_buf)
-{
- ext2_filsys fs = ctx->fs;
- ext2_ino_t ino;
- struct ext2_inode inode;
- ext2_inode_scan scan;
- struct process_block_struct_1b pb;
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
-
- if (!(ctx->options & E2F_OPT_PREEN))
- fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
- pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
- &scan);
- if (pctx.errcode) {
- fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- ctx->stashed_inode = &inode;
- pb.ctx = ctx;
- pb.pctx = &pctx;
- pctx.str = "pass1b";
- while (1) {
- pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
- if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
- continue;
- if (pctx.errcode) {
- fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- if (!ino)
- break;
- pctx.ino = ctx->stashed_ino = ino;
- if ((ino != EXT2_BAD_INO) &&
- !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
- continue;
-
- pb.ino = ino;
- pb.dup_blocks = 0;
- pb.inode = &inode;
-
- if (ext2fs_inode_has_valid_blocks(&inode) ||
- (ino == EXT2_BAD_INO))
- pctx.errcode = ext2fs_block_iterate2(fs, ino,
- 0, block_buf, process_pass1b_block, &pb);
- if (inode.i_file_acl)
- process_pass1b_block(fs, &inode.i_file_acl,
- BLOCK_COUNT_EXTATTR, 0, 0, &pb);
- if (pb.dup_blocks) {
- end_problem_latch(ctx, PR_LATCH_DBLOCK);
- if (ino >= EXT2_FIRST_INODE(fs->super) ||
- ino == EXT2_ROOT_INO)
- dup_inode_count++;
- }
- if (pctx.errcode)
- fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
- }
- ext2fs_close_inode_scan(scan);
- e2fsck_use_inode_shortcuts(ctx, 0);
-}
-
-static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
- blk_t *block_nr,
- e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
- blk_t ref_blk FSCK_ATTR((unused)),
- int ref_offset FSCK_ATTR((unused)),
- void *priv_data)
-{
- struct process_block_struct_1b *p;
- e2fsck_t ctx;
-
- if (HOLE_BLKADDR(*block_nr))
- return 0;
- p = (struct process_block_struct_1b *) priv_data;
- ctx = p->ctx;
-
- if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
- return 0;
-
- /* OK, this is a duplicate block */
- if (p->ino != EXT2_BAD_INO) {
- p->pctx->blk = *block_nr;
- fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
- }
- p->dup_blocks++;
- ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
-
- add_dupe(ctx, p->ino, *block_nr, p->inode);
-
- return 0;
-}
-
-/*
- * Pass 1c: Scan directories for inodes with duplicate blocks. This
- * is used so that we can print pathnames when prompting the user for
- * what to do.
- */
-struct search_dir_struct {
- int count;
- ext2_ino_t first_inode;
- ext2_ino_t max_inode;
-};
-
-static int search_dirent_proc(ext2_ino_t dir, int entry,
- struct ext2_dir_entry *dirent,
- int offset FSCK_ATTR((unused)),
- int blocksize FSCK_ATTR((unused)),
- char *buf FSCK_ATTR((unused)),
- void *priv_data)
-{
- struct search_dir_struct *sd;
- struct dup_inode *p;
- dnode_t *n;
-
- sd = (struct search_dir_struct *) priv_data;
-
- if (dirent->inode > sd->max_inode)
- /* Should abort this inode, but not everything */
- return 0;
-
- if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
- !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
- return 0;
-
- n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
- if (!n)
- return 0;
- p = (struct dup_inode *) dnode_get(n);
- p->dir = dir;
- sd->count--;
-
- return sd->count ? 0 : DIRENT_ABORT;
-}
-
-
-static void pass1c(e2fsck_t ctx, char *block_buf)
-{
- ext2_filsys fs = ctx->fs;
- struct search_dir_struct sd;
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
-
- if (!(ctx->options & E2F_OPT_PREEN))
- fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
-
- /*
- * Search through all directories to translate inodes to names
- * (by searching for the containing directory for that inode.)
- */
- sd.count = dup_inode_count;
- sd.first_inode = EXT2_FIRST_INODE(fs->super);
- sd.max_inode = fs->super->s_inodes_count;
- ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
- search_dirent_proc, &sd);
-}
-
-static void pass1d(e2fsck_t ctx, char *block_buf)
-{
- ext2_filsys fs = ctx->fs;
- struct dup_inode *p, *t;
- struct dup_block *q;
- ext2_ino_t *shared, ino;
- int shared_len;
- int i;
- int file_ok;
- int meta_data = 0;
- struct problem_context pctx;
- dnode_t *n, *m;
- struct block_el *s;
- struct inode_el *r;
-
- clear_problem_context(&pctx);
-
- if (!(ctx->options & E2F_OPT_PREEN))
- fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
- e2fsck_read_bitmaps(ctx);
-
- pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
- fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
- shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
- sizeof(ext2_ino_t) * dict_count(&ino_dict),
- "Shared inode list");
- for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
- p = (struct dup_inode *) dnode_get(n);
- shared_len = 0;
- file_ok = 1;
- ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
- if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
- continue;
-
- /*
- * Find all of the inodes which share blocks with this
- * one. First we find all of the duplicate blocks
- * belonging to this inode, and then search each block
- * get the list of inodes, and merge them together.
- */
- for (s = p->block_list; s; s = s->next) {
- m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
- if (!m)
- continue; /* Should never happen... */
- q = (struct dup_block *) dnode_get(m);
- if (q->num_bad > 1)
- file_ok = 0;
- if (check_if_fs_block(ctx, s->block)) {
- file_ok = 0;
- meta_data = 1;
- }
-
- /*
- * Add all inodes used by this block to the
- * shared[] --- which is a unique list, so
- * if an inode is already in shared[], don't
- * add it again.
- */
- for (r = q->inode_list; r; r = r->next) {
- if (r->inode == ino)
- continue;
- for (i = 0; i < shared_len; i++)
- if (shared[i] == r->inode)
- break;
- if (i == shared_len) {
- shared[shared_len++] = r->inode;
- }
- }
- }
-
- /*
- * Report the inode that we are working on
- */
- pctx.inode = &p->inode;
- pctx.ino = ino;
- pctx.dir = p->dir;
- pctx.blkcount = p->num_dupblocks;
- pctx.num = meta_data ? shared_len+1 : shared_len;
- fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
- pctx.blkcount = 0;
- pctx.num = 0;
-
- if (meta_data)
- fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
-
- for (i = 0; i < shared_len; i++) {
- m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
- if (!m)
- continue; /* should never happen */
- t = (struct dup_inode *) dnode_get(m);
- /*
- * Report the inode that we are sharing with
- */
- pctx.inode = &t->inode;
- pctx.ino = shared[i];
- pctx.dir = t->dir;
- fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
- }
- if (file_ok) {
- fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
- continue;
- }
- if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
- pctx.errcode = clone_file(ctx, ino, p, block_buf);
- if (pctx.errcode)
- fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
- else
- continue;
- }
- if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
- delete_file(ctx, ino, p, block_buf);
- else
- ext2fs_unmark_valid(fs);
- }
- ext2fs_free_mem(&shared);
-}
-
-/*
- * Drop the refcount on the dup_block structure, and clear the entry
- * in the block_dup_map if appropriate.
- */
-static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
-{
- p->num_bad--;
- if (p->num_bad <= 0 ||
- (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
- ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
-}
-
-static int delete_file_block(ext2_filsys fs,
- blk_t *block_nr,
- e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
- blk_t ref_block FSCK_ATTR((unused)),
- int ref_offset FSCK_ATTR((unused)),
- void *priv_data)
-{
- struct process_block_struct_1b *pb;
- struct dup_block *p;
- dnode_t *n;
- e2fsck_t ctx;
-
- pb = (struct process_block_struct_1b *) priv_data;
- ctx = pb->ctx;
-
- if (HOLE_BLKADDR(*block_nr))
- return 0;
-
- if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
- n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
- if (n) {
- p = (struct dup_block *) dnode_get(n);
- decrement_badcount(ctx, *block_nr, p);
- } else
- bb_error_msg(_("internal error; can't find dup_blk for %d"),
- *block_nr);
- } else {
- ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
- ext2fs_block_alloc_stats(fs, *block_nr, -1);
- }
-
- return 0;
-}
-
-static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
- struct dup_inode *dp, char* block_buf)
-{
- ext2_filsys fs = ctx->fs;
- struct process_block_struct_1b pb;
- struct ext2_inode inode;
- struct problem_context pctx;
- unsigned int count;
-
- clear_problem_context(&pctx);
- pctx.ino = pb.ino = ino;
- pb.dup_blocks = dp->num_dupblocks;
- pb.ctx = ctx;
- pctx.str = "delete_file";
-
- e2fsck_read_inode(ctx, ino, &inode, "delete_file");
- if (ext2fs_inode_has_valid_blocks(&inode))
- pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
- delete_file_block, &pb);
- if (pctx.errcode)
- fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
- ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
- ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
- if (ctx->inode_bad_map)
- ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
- ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
-
- /* Inode may have changed by block_iterate, so reread it */
- e2fsck_read_inode(ctx, ino, &inode, "delete_file");
- inode.i_links_count = 0;
- inode.i_dtime = time(NULL);
- if (inode.i_file_acl &&
- (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
- count = 1;
- pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
- block_buf, -1, &count);
- if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
- pctx.errcode = 0;
- count = 1;
- }
- if (pctx.errcode) {
- pctx.blk = inode.i_file_acl;
- fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
- }
- /*
- * If the count is zero, then arrange to have the
- * block deleted. If the block is in the block_dup_map,
- * also call delete_file_block since it will take care
- * of keeping the accounting straight.
- */
- if ((count == 0) ||
- ext2fs_test_block_bitmap(ctx->block_dup_map,
- inode.i_file_acl))
- delete_file_block(fs, &inode.i_file_acl,
- BLOCK_COUNT_EXTATTR, 0, 0, &pb);
- }
- e2fsck_write_inode(ctx, ino, &inode, "delete_file");
-}
-
-struct clone_struct {
- errcode_t errcode;
- ext2_ino_t dir;
- char *buf;
- e2fsck_t ctx;
-};
-
-static int clone_file_block(ext2_filsys fs,
- blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block FSCK_ATTR((unused)),
- int ref_offset FSCK_ATTR((unused)),
- void *priv_data)
-{
- struct dup_block *p;
- blk_t new_block;
- errcode_t retval;
- struct clone_struct *cs = (struct clone_struct *) priv_data;
- dnode_t *n;
- e2fsck_t ctx;
-
- ctx = cs->ctx;
-
- if (HOLE_BLKADDR(*block_nr))
- return 0;
-
- if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
- n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
- if (n) {
- p = (struct dup_block *) dnode_get(n);
- retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
- &new_block);
- if (retval) {
- cs->errcode = retval;
- return BLOCK_ABORT;
- }
- if (cs->dir && (blockcnt >= 0)) {
- retval = ext2fs_set_dir_block(fs->dblist,
- cs->dir, new_block, blockcnt);
- if (retval) {
- cs->errcode = retval;
- return BLOCK_ABORT;
- }
- }
-
- retval = io_channel_read_blk(fs->io, *block_nr, 1,
- cs->buf);
- if (retval) {
- cs->errcode = retval;
- return BLOCK_ABORT;
- }
- retval = io_channel_write_blk(fs->io, new_block, 1,
- cs->buf);
- if (retval) {
- cs->errcode = retval;
- return BLOCK_ABORT;
- }
- decrement_badcount(ctx, *block_nr, p);
- *block_nr = new_block;
- ext2fs_mark_block_bitmap(ctx->block_found_map,
- new_block);
- ext2fs_mark_block_bitmap(fs->block_map, new_block);
- return BLOCK_CHANGED;
- } else
- bb_error_msg(_("internal error; can't find dup_blk for %d"),
- *block_nr);
- }
- return 0;
-}
-
-static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
- struct dup_inode *dp, char* block_buf)
-{
- ext2_filsys fs = ctx->fs;
- errcode_t retval;
- struct clone_struct cs;
- struct problem_context pctx;
- blk_t blk;
- dnode_t *n;
- struct inode_el *ino_el;
- struct dup_block *db;
- struct dup_inode *di;
-
- clear_problem_context(&pctx);
- cs.errcode = 0;
- cs.dir = 0;
- cs.ctx = ctx;
- retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
- if (retval)
- return retval;
-
- if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
- cs.dir = ino;
-
- pctx.ino = ino;
- pctx.str = "clone_file";
- if (ext2fs_inode_has_valid_blocks(&dp->inode))
- pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
- clone_file_block, &cs);
- ext2fs_mark_bb_dirty(fs);
- if (pctx.errcode) {
- fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
- retval = pctx.errcode;
- goto errout;
- }
- if (cs.errcode) {
- bb_error_msg(_("returned from clone_file_block"));
- retval = cs.errcode;
- goto errout;
- }
- /* The inode may have changed on disk, so we have to re-read it */
- e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
- blk = dp->inode.i_file_acl;
- if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
- BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
- BLOCK_CHANGED)) {
- e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
- /*
- * If we cloned the EA block, find all other inodes
- * which refered to that EA block, and modify
- * them to point to the new EA block.
- */
- n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
- db = (struct dup_block *) dnode_get(n);
- for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
- if (ino_el->inode == ino)
- continue;
- n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
- di = (struct dup_inode *) dnode_get(n);
- if (di->inode.i_file_acl == blk) {
- di->inode.i_file_acl = dp->inode.i_file_acl;
- e2fsck_write_inode(ctx, ino_el->inode,
- &di->inode, "clone file EA");
- decrement_badcount(ctx, blk, db);
- }
- }
- }
- retval = 0;
-errout:
- ext2fs_free_mem(&cs.buf);
- return retval;
-}
-
-/*
- * This routine returns 1 if a block overlaps with one of the superblocks,
- * group descriptors, inode bitmaps, or block bitmaps.
- */
-static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
-{
- ext2_filsys fs = ctx->fs;
- blk_t block;
- dgrp_t i;
-
- block = fs->super->s_first_data_block;
- for (i = 0; i < fs->group_desc_count; i++) {
-
- /* Check superblocks/block group descriptros */
- if (ext2fs_bg_has_super(fs, i)) {
- if (test_block >= block &&
- (test_block <= block + fs->desc_blocks))
- return 1;
- }
-
- /* Check the inode table */
- if ((fs->group_desc[i].bg_inode_table) &&
- (test_block >= fs->group_desc[i].bg_inode_table) &&
- (test_block < (fs->group_desc[i].bg_inode_table +
- fs->inode_blocks_per_group)))
- return 1;
-
- /* Check the bitmap blocks */
- if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
- (test_block == fs->group_desc[i].bg_inode_bitmap))
- return 1;
-
- block += fs->super->s_blocks_per_group;
- }
- return 0;
-}
-/*
- * pass2.c --- check directory structure
- *
- * Pass 2 of e2fsck iterates through all active directory inodes, and
- * applies to following tests to each directory entry in the directory
- * blocks in the inodes:
- *
- * - The length of the directory entry (rec_len) should be at
- * least 8 bytes, and no more than the remaining space
- * left in the directory block.
- * - The length of the name in the directory entry (name_len)
- * should be less than (rec_len - 8).
- * - The inode number in the directory entry should be within
- * legal bounds.
- * - The inode number should refer to a in-use inode.
- * - The first entry should be '.', and its inode should be
- * the inode of the directory.
- * - The second entry should be '..'.
- *
- * To minimize disk seek time, the directory blocks are processed in
- * sorted order of block numbers.
- *
- * Pass 2 also collects the following information:
- * - The inode numbers of the subdirectories for each directory.
- *
- * Pass 2 relies on the following information from previous passes:
- * - The directory information collected in pass 1.
- * - The inode_used_map bitmap
- * - The inode_bad_map bitmap
- * - The inode_dir_map bitmap
- *
- * Pass 2 frees the following data structures
- * - The inode_bad_map bitmap
- * - The inode_reg_map bitmap
- */
-
-/*
- * Keeps track of how many times an inode is referenced.
- */
-static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
-static int check_dir_block(ext2_filsys fs,
- struct ext2_db_entry *dir_blocks_info,
- void *priv_data);
-static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
- struct problem_context *pctx);
-static int update_dir_block(ext2_filsys fs,
- blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block,
- int ref_offset,
- void *priv_data);
-static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
-static int htree_depth(struct dx_dir_info *dx_dir,
- struct dx_dirblock_info *dx_db);
-static int special_dir_block_cmp(const void *a, const void *b);
-
-struct check_dir_struct {
- char *buf;
- struct problem_context pctx;
- int count, max;
- e2fsck_t ctx;
-};
-
-static void e2fsck_pass2(e2fsck_t ctx)
-{
- struct ext2_super_block *sb = ctx->fs->super;
- struct problem_context pctx;
- ext2_filsys fs = ctx->fs;
- char *buf;
- struct dir_info *dir;
- struct check_dir_struct cd;
- struct dx_dir_info *dx_dir;
- struct dx_dirblock_info *dx_db, *dx_parent;
- int b;
- int i, depth;
- problem_t code;
- int bad_dir;
-
- clear_problem_context(&cd.pctx);
-
- /* Pass 2 */
-
- if (!(ctx->options & E2F_OPT_PREEN))
- fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
-
- cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
- 0, ctx->inode_link_info,
- &ctx->inode_count);
- if (cd.pctx.errcode) {
- fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
- "directory scan buffer");
-
- /*
- * Set up the parent pointer for the root directory, if
- * present. (If the root directory is not present, we will
- * create it in pass 3.)
- */
- dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
- if (dir)
- dir->parent = EXT2_ROOT_INO;
-
- cd.buf = buf;
- cd.ctx = ctx;
- cd.count = 1;
- cd.max = ext2fs_dblist_count(fs->dblist);
-
- if (ctx->progress)
- (void) (ctx->progress)(ctx, 2, 0, cd.max);
-
- if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
- ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
-
- cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
- &cd);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
- if (cd.pctx.errcode) {
- fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-
-#ifdef ENABLE_HTREE
- for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
- if (dx_dir->numblocks == 0)
- continue;
- clear_problem_context(&pctx);
- bad_dir = 0;
- pctx.dir = dx_dir->ino;
- dx_db = dx_dir->dx_block;
- if (dx_db->flags & DX_FLAG_REFERENCED)
- dx_db->flags |= DX_FLAG_DUP_REF;
- else
- dx_db->flags |= DX_FLAG_REFERENCED;
- /*
- * Find all of the first and last leaf blocks, and
- * update their parent's min and max hash values
- */
- for (b=0, dx_db = dx_dir->dx_block;
- b < dx_dir->numblocks;
- b++, dx_db++) {
- if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
- !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
- continue;
- dx_parent = &dx_dir->dx_block[dx_db->parent];
- /*
- * XXX Make sure dx_parent->min_hash > dx_db->min_hash
- */
- if (dx_db->flags & DX_FLAG_FIRST)
- dx_parent->min_hash = dx_db->min_hash;
- /*
- * XXX Make sure dx_parent->max_hash < dx_db->max_hash
- */
- if (dx_db->flags & DX_FLAG_LAST)
- dx_parent->max_hash = dx_db->max_hash;
- }
-
- for (b=0, dx_db = dx_dir->dx_block;
- b < dx_dir->numblocks;
- b++, dx_db++) {
- pctx.blkcount = b;
- pctx.group = dx_db->parent;
- code = 0;
- if (!(dx_db->flags & DX_FLAG_FIRST) &&
- (dx_db->min_hash < dx_db->node_min_hash)) {
- pctx.blk = dx_db->min_hash;
- pctx.blk2 = dx_db->node_min_hash;
- code = PR_2_HTREE_MIN_HASH;
- fix_problem(ctx, code, &pctx);
- bad_dir++;
- }
- if (dx_db->type == DX_DIRBLOCK_LEAF) {
- depth = htree_depth(dx_dir, dx_db);
- if (depth != dx_dir->depth) {
- code = PR_2_HTREE_BAD_DEPTH;
- fix_problem(ctx, code, &pctx);
- bad_dir++;
- }
- }
- /*
- * This test doesn't apply for the root block
- * at block #0
- */
- if (b &&
- (dx_db->max_hash > dx_db->node_max_hash)) {
- pctx.blk = dx_db->max_hash;
- pctx.blk2 = dx_db->node_max_hash;
- code = PR_2_HTREE_MAX_HASH;
- fix_problem(ctx, code, &pctx);
- bad_dir++;
- }
- if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
- code = PR_2_HTREE_NOTREF;
- fix_problem(ctx, code, &pctx);
- bad_dir++;
- } else if (dx_db->flags & DX_FLAG_DUP_REF) {
- code = PR_2_HTREE_DUPREF;
- fix_problem(ctx, code, &pctx);
- bad_dir++;
- }
- if (code == 0)
- continue;
- }
- if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
- clear_htree(ctx, dx_dir->ino);
- dx_dir->numblocks = 0;
- }
- }
-#endif
- ext2fs_free_mem(&buf);
- ext2fs_free_dblist(fs->dblist);
-
- ext2fs_free_inode_bitmap(ctx->inode_bad_map);
- ctx->inode_bad_map = 0;
- ext2fs_free_inode_bitmap(ctx->inode_reg_map);
- ctx->inode_reg_map = 0;
-
- clear_problem_context(&pctx);
- if (ctx->large_files) {
- if (!(sb->s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
- fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
- sb->s_feature_ro_compat |=
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
- ext2fs_mark_super_dirty(fs);
- }
- if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
- fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
- ext2fs_update_dynamic_rev(fs);
- ext2fs_mark_super_dirty(fs);
- }
- } else if (!ctx->large_files &&
- (sb->s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
- if (fs->flags & EXT2_FLAG_RW) {
- sb->s_feature_ro_compat &=
- ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
- ext2fs_mark_super_dirty(fs);
- }
- }
-}
-
-#define MAX_DEPTH 32000
-static int htree_depth(struct dx_dir_info *dx_dir,
- struct dx_dirblock_info *dx_db)
-{
- int depth = 0;
-
- while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
- dx_db = &dx_dir->dx_block[dx_db->parent];
- depth++;
- }
- return depth;
-}
-
-static int dict_de_cmp(const void *a, const void *b)
-{
- const struct ext2_dir_entry *de_a, *de_b;
- int a_len, b_len;
-
- de_a = (const struct ext2_dir_entry *) a;
- a_len = de_a->name_len & 0xFF;
- de_b = (const struct ext2_dir_entry *) b;
- b_len = de_b->name_len & 0xFF;
-
- if (a_len != b_len)
- return (a_len - b_len);
-
- return strncmp(de_a->name, de_b->name, a_len);
-}
-
-/*
- * This is special sort function that makes sure that directory blocks
- * with a dirblock of zero are sorted to the beginning of the list.
- * This guarantees that the root node of the htree directories are
- * processed first, so we know what hash version to use.
- */
-static int special_dir_block_cmp(const void *a, const void *b)
-{
- const struct ext2_db_entry *db_a =
- (const struct ext2_db_entry *) a;
- const struct ext2_db_entry *db_b =
- (const struct ext2_db_entry *) b;
-
- if (db_a->blockcnt && !db_b->blockcnt)
- return 1;
-
- if (!db_a->blockcnt && db_b->blockcnt)
- return -1;
-
- if (db_a->blk != db_b->blk)
- return (int) (db_a->blk - db_b->blk);
-
- if (db_a->ino != db_b->ino)
- return (int) (db_a->ino - db_b->ino);
-
- return (int) (db_a->blockcnt - db_b->blockcnt);
-}
-
-
-/*
- * Make sure the first entry in the directory is '.', and that the
- * directory entry is sane.
- */
-static int check_dot(e2fsck_t ctx,
- struct ext2_dir_entry *dirent,
- ext2_ino_t ino, struct problem_context *pctx)
-{
- struct ext2_dir_entry *nextdir;
- int status = 0;
- int created = 0;
- int new_len;
- int problem = 0;
-
- if (!dirent->inode)
- problem = PR_2_MISSING_DOT;
- else if (((dirent->name_len & 0xFF) != 1) ||
- (dirent->name[0] != '.'))
- problem = PR_2_1ST_NOT_DOT;
- else if (dirent->name[1] != '\0')
- problem = PR_2_DOT_NULL_TERM;
-
- if (problem) {
- if (fix_problem(ctx, problem, pctx)) {
- if (dirent->rec_len < 12)
- dirent->rec_len = 12;
- dirent->inode = ino;
- dirent->name_len = 1;
- dirent->name[0] = '.';
- dirent->name[1] = '\0';
- status = 1;
- created = 1;
- }
- }
- if (dirent->inode != ino) {
- if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
- dirent->inode = ino;
- status = 1;
- }
- }
- if (dirent->rec_len > 12) {
- new_len = dirent->rec_len - 12;
- if (new_len > 12) {
- if (created ||
- fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
- nextdir = (struct ext2_dir_entry *)
- ((char *) dirent + 12);
- dirent->rec_len = 12;
- nextdir->rec_len = new_len;
- nextdir->inode = 0;
- nextdir->name_len = 0;
- status = 1;
- }
- }
- }
- return status;
-}
-
-/*
- * Make sure the second entry in the directory is '..', and that the
- * directory entry is sane. We do not check the inode number of '..'
- * here; this gets done in pass 3.
- */
-static int check_dotdot(e2fsck_t ctx,
- struct ext2_dir_entry *dirent,
- struct dir_info *dir, struct problem_context *pctx)
-{
- int problem = 0;
-
- if (!dirent->inode)
- problem = PR_2_MISSING_DOT_DOT;
- else if (((dirent->name_len & 0xFF) != 2) ||
- (dirent->name[0] != '.') ||
- (dirent->name[1] != '.'))
- problem = PR_2_2ND_NOT_DOT_DOT;
- else if (dirent->name[2] != '\0')
- problem = PR_2_DOT_DOT_NULL_TERM;
-
- if (problem) {
- if (fix_problem(ctx, problem, pctx)) {
- if (dirent->rec_len < 12)
- dirent->rec_len = 12;
- /*
- * Note: we don't have the parent inode just
- * yet, so we will fill it in with the root
- * inode. This will get fixed in pass 3.
- */
- dirent->inode = EXT2_ROOT_INO;
- dirent->name_len = 2;
- dirent->name[0] = '.';
- dirent->name[1] = '.';
- dirent->name[2] = '\0';
- return 1;
- }
- return 0;
- }
- dir->dotdot = dirent->inode;
- return 0;
-}
-
-/*
- * Check to make sure a directory entry doesn't contain any illegal
- * characters.
- */
-static int check_name(e2fsck_t ctx,
- struct ext2_dir_entry *dirent,
- struct problem_context *pctx)
-{
- int i;
- int fixup = -1;
- int ret = 0;
-
- for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
- if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
- if (fixup < 0) {
- fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
- }
- if (fixup) {
- dirent->name[i] = '.';
- ret = 1;
- }
- }
- }
- return ret;
-}
-
-/*
- * Check the directory filetype (if present)
- */
-
-/*
- * Given a mode, return the ext2 file type
- */
-static int ext2_file_type(unsigned int mode)
-{
- if (LINUX_S_ISREG(mode))
- return EXT2_FT_REG_FILE;
-
- if (LINUX_S_ISDIR(mode))
- return EXT2_FT_DIR;
-
- if (LINUX_S_ISCHR(mode))
- return EXT2_FT_CHRDEV;
-
- if (LINUX_S_ISBLK(mode))
- return EXT2_FT_BLKDEV;
-
- if (LINUX_S_ISLNK(mode))
- return EXT2_FT_SYMLINK;
-
- if (LINUX_S_ISFIFO(mode))
- return EXT2_FT_FIFO;
-
- if (LINUX_S_ISSOCK(mode))
- return EXT2_FT_SOCK;
-
- return 0;
-}
-
-static int check_filetype(e2fsck_t ctx,
- struct ext2_dir_entry *dirent,
- struct problem_context *pctx)
-{
- int filetype = dirent->name_len >> 8;
- int should_be = EXT2_FT_UNKNOWN;
- struct ext2_inode inode;
-
- if (!(ctx->fs->super->s_feature_incompat &
- EXT2_FEATURE_INCOMPAT_FILETYPE)) {
- if (filetype == 0 ||
- !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
- return 0;
- dirent->name_len = dirent->name_len & 0xFF;
- return 1;
- }
-
- if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
- should_be = EXT2_FT_DIR;
- } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
- dirent->inode)) {
- should_be = EXT2_FT_REG_FILE;
- } else if (ctx->inode_bad_map &&
- ext2fs_test_inode_bitmap(ctx->inode_bad_map,
- dirent->inode))
- should_be = 0;
- else {
- e2fsck_read_inode(ctx, dirent->inode, &inode,
- "check_filetype");
- should_be = ext2_file_type(inode.i_mode);
- }
- if (filetype == should_be)
- return 0;
- pctx->num = should_be;
-
- if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
- pctx) == 0)
- return 0;
-
- dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
- return 1;
-}
-
-#ifdef ENABLE_HTREE
-static void parse_int_node(ext2_filsys fs,
- struct ext2_db_entry *db,
- struct check_dir_struct *cd,
- struct dx_dir_info *dx_dir,
- char *block_buf)
-{
- struct ext2_dx_root_info *root;
- struct ext2_dx_entry *ent;
- struct ext2_dx_countlimit *limit;
- struct dx_dirblock_info *dx_db;
- int i, expect_limit, count;
- blk_t blk;
- ext2_dirhash_t min_hash = 0xffffffff;
- ext2_dirhash_t max_hash = 0;
- ext2_dirhash_t hash = 0, prev_hash;
-
- if (db->blockcnt == 0) {
- root = (struct ext2_dx_root_info *) (block_buf + 24);
- ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
- } else {
- ent = (struct ext2_dx_entry *) (block_buf+8);
- }
- limit = (struct ext2_dx_countlimit *) ent;
-
- count = ext2fs_le16_to_cpu(limit->count);
- expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
- sizeof(struct ext2_dx_entry);
- if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
- cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
- if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
- goto clear_and_exit;
- }
- if (count > expect_limit) {
- cd->pctx.num = count;
- if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
- goto clear_and_exit;
- count = expect_limit;
- }
-
- for (i=0; i < count; i++) {
- prev_hash = hash;
- hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
- blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
- /* Check to make sure the block is valid */
- if (blk > (blk_t) dx_dir->numblocks) {
- cd->pctx.blk = blk;
- if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
- &cd->pctx))
- goto clear_and_exit;
- }
- if (hash < prev_hash &&
- fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
- goto clear_and_exit;
- dx_db = &dx_dir->dx_block[blk];
- if (dx_db->flags & DX_FLAG_REFERENCED) {
- dx_db->flags |= DX_FLAG_DUP_REF;
- } else {
- dx_db->flags |= DX_FLAG_REFERENCED;
- dx_db->parent = db->blockcnt;
- }
- if (hash < min_hash)
- min_hash = hash;
- if (hash > max_hash)
- max_hash = hash;
- dx_db->node_min_hash = hash;
- if ((i+1) < count)
- dx_db->node_max_hash =
- ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
- else {
- dx_db->node_max_hash = 0xfffffffe;
- dx_db->flags |= DX_FLAG_LAST;
- }
- if (i == 0)
- dx_db->flags |= DX_FLAG_FIRST;
- }
- dx_db = &dx_dir->dx_block[db->blockcnt];
- dx_db->min_hash = min_hash;
- dx_db->max_hash = max_hash;
- return;
-
-clear_and_exit:
- clear_htree(cd->ctx, cd->pctx.ino);
- dx_dir->numblocks = 0;
-}
-#endif /* ENABLE_HTREE */
-
-/*
- * Given a busted directory, try to salvage it somehow.
- *
- */
-static void salvage_directory(ext2_filsys fs,
- struct ext2_dir_entry *dirent,
- struct ext2_dir_entry *prev,
- unsigned int *offset)
-{
- char *cp = (char *) dirent;
- int left = fs->blocksize - *offset - dirent->rec_len;
- int name_len = dirent->name_len & 0xFF;
-
- /*
- * Special case of directory entry of size 8: copy what's left
- * of the directory block up to cover up the invalid hole.
- */
- if ((left >= 12) && (dirent->rec_len == 8)) {
- memmove(cp, cp+8, left);
- memset(cp + left, 0, 8);
- return;
- }
- /*
- * If the directory entry overruns the end of the directory
- * block, and the name is small enough to fit, then adjust the
- * record length.
- */
- if ((left < 0) &&
- (name_len + 8 <= dirent->rec_len + left) &&
- dirent->inode <= fs->super->s_inodes_count &&
- strnlen(dirent->name, name_len) == name_len) {
- dirent->rec_len += left;
- return;
- }
- /*
- * If the directory entry is a multiple of four, so it is
- * valid, let the previous directory entry absorb the invalid
- * one.
- */
- if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
- prev->rec_len += dirent->rec_len;
- *offset += dirent->rec_len;
- return;
- }
- /*
- * Default salvage method --- kill all of the directory
- * entries for the rest of the block. We will either try to
- * absorb it into the previous directory entry, or create a
- * new empty directory entry the rest of the directory block.
- */
- if (prev) {
- prev->rec_len += fs->blocksize - *offset;
- *offset = fs->blocksize;
- } else {
- dirent->rec_len = fs->blocksize - *offset;
- dirent->name_len = 0;
- dirent->inode = 0;
- }
-}
-
-static int check_dir_block(ext2_filsys fs,
- struct ext2_db_entry *db,
- void *priv_data)
-{
- struct dir_info *subdir, *dir;
- struct dx_dir_info *dx_dir;
-#ifdef ENABLE_HTREE
- struct dx_dirblock_info *dx_db = NULL;
-#endif /* ENABLE_HTREE */
- struct ext2_dir_entry *dirent, *prev;
- ext2_dirhash_t hash;
- unsigned int offset = 0;
- int dir_modified = 0;
- int dot_state;
- blk_t block_nr = db->blk;
- ext2_ino_t ino = db->ino;
- __u16 links;
- struct check_dir_struct *cd;
- char *buf;
- e2fsck_t ctx;
- int problem;
- struct ext2_dx_root_info *root;
- struct ext2_dx_countlimit *limit;
- static dict_t de_dict;
- struct problem_context pctx;
- int dups_found = 0;
-
- cd = (struct check_dir_struct *) priv_data;
- buf = cd->buf;
- ctx = cd->ctx;
-
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return DIRENT_ABORT;
-
- if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
- return DIRENT_ABORT;
-
- /*
- * Make sure the inode is still in use (could have been
- * deleted in the duplicate/bad blocks pass.
- */
- if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
- return 0;
-
- cd->pctx.ino = ino;
- cd->pctx.blk = block_nr;
- cd->pctx.blkcount = db->blockcnt;
- cd->pctx.ino2 = 0;
- cd->pctx.dirent = 0;
- cd->pctx.num = 0;
-
- if (db->blk == 0) {
- if (allocate_dir_block(ctx, db, &cd->pctx))
- return 0;
- block_nr = db->blk;
- }
-
- if (db->blockcnt)
- dot_state = 2;
- else
- dot_state = 0;
-
- if (ctx->dirs_to_hash &&
- ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
- dups_found++;
-
- cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
- if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
- cd->pctx.errcode = 0; /* We'll handle this ourselves */
- if (cd->pctx.errcode) {
- if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
- ctx->flags |= E2F_FLAG_ABORT;
- return DIRENT_ABORT;
- }
- memset(buf, 0, fs->blocksize);
- }
-#ifdef ENABLE_HTREE
- dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
- if (dx_dir && dx_dir->numblocks) {
- if (db->blockcnt >= dx_dir->numblocks) {
- printf("XXX should never happen!!!\n");
- abort();
- }
- dx_db = &dx_dir->dx_block[db->blockcnt];
- dx_db->type = DX_DIRBLOCK_LEAF;
- dx_db->phys = block_nr;
- dx_db->min_hash = ~0;
- dx_db->max_hash = 0;
-
- dirent = (struct ext2_dir_entry *) buf;
- limit = (struct ext2_dx_countlimit *) (buf+8);
- if (db->blockcnt == 0) {
- root = (struct ext2_dx_root_info *) (buf + 24);
- dx_db->type = DX_DIRBLOCK_ROOT;
- dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
- if ((root->reserved_zero ||
- root->info_length < 8 ||
- root->indirect_levels > 1) &&
- fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
- clear_htree(ctx, ino);
- dx_dir->numblocks = 0;
- dx_db = 0;
- }
- dx_dir->hashversion = root->hash_version;
- dx_dir->depth = root->indirect_levels + 1;
- } else if ((dirent->inode == 0) &&
- (dirent->rec_len == fs->blocksize) &&
- (dirent->name_len == 0) &&
- (ext2fs_le16_to_cpu(limit->limit) ==
- ((fs->blocksize-8) /
- sizeof(struct ext2_dx_entry))))
- dx_db->type = DX_DIRBLOCK_NODE;
- }
-#endif /* ENABLE_HTREE */
-
- dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
- prev = 0;
- do {
- problem = 0;
- dirent = (struct ext2_dir_entry *) (buf + offset);
- cd->pctx.dirent = dirent;
- cd->pctx.num = offset;
- if (((offset + dirent->rec_len) > fs->blocksize) ||
- (dirent->rec_len < 12) ||
- ((dirent->rec_len % 4) != 0) ||
- (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
- if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
- salvage_directory(fs, dirent, prev, &offset);
- dir_modified++;
- continue;
- } else
- goto abort_free_dict;
- }
- if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
- if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
- dirent->name_len = EXT2_NAME_LEN;
- dir_modified++;
- }
- }
-
- if (dot_state == 0) {
- if (check_dot(ctx, dirent, ino, &cd->pctx))
- dir_modified++;
- } else if (dot_state == 1) {
- dir = e2fsck_get_dir_info(ctx, ino);
- if (!dir) {
- fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
- goto abort_free_dict;
- }
- if (check_dotdot(ctx, dirent, dir, &cd->pctx))
- dir_modified++;
- } else if (dirent->inode == ino) {
- problem = PR_2_LINK_DOT;
- if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
- dirent->inode = 0;
- dir_modified++;
- goto next;
- }
- }
- if (!dirent->inode)
- goto next;
-
- /*
- * Make sure the inode listed is a legal one.
- */
- if (((dirent->inode != EXT2_ROOT_INO) &&
- (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
- (dirent->inode > fs->super->s_inodes_count)) {
- problem = PR_2_BAD_INO;
- } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
- dirent->inode))) {
- /*
- * If the inode is unused, offer to clear it.
- */
- problem = PR_2_UNUSED_INODE;
- } else if ((dot_state > 1) &&
- ((dirent->name_len & 0xFF) == 1) &&
- (dirent->name[0] == '.')) {
- /*
- * If there's a '.' entry in anything other
- * than the first directory entry, it's a
- * duplicate entry that should be removed.
- */
- problem = PR_2_DUP_DOT;
- } else if ((dot_state > 1) &&
- ((dirent->name_len & 0xFF) == 2) &&
- (dirent->name[0] == '.') &&
- (dirent->name[1] == '.')) {
- /*
- * If there's a '..' entry in anything other
- * than the second directory entry, it's a
- * duplicate entry that should be removed.
- */
- problem = PR_2_DUP_DOT_DOT;
- } else if ((dot_state > 1) &&
- (dirent->inode == EXT2_ROOT_INO)) {
- /*
- * Don't allow links to the root directory.
- * We check this specially to make sure we
- * catch this error case even if the root
- * directory hasn't been created yet.
- */
- problem = PR_2_LINK_ROOT;
- } else if ((dot_state > 1) &&
- (dirent->name_len & 0xFF) == 0) {
- /*
- * Don't allow zero-length directory names.
- */
- problem = PR_2_NULL_NAME;
- }
-
- if (problem) {
- if (fix_problem(ctx, problem, &cd->pctx)) {
- dirent->inode = 0;
- dir_modified++;
- goto next;
- } else {
- ext2fs_unmark_valid(fs);
- if (problem == PR_2_BAD_INO)
- goto next;
- }
- }
-
- /*
- * If the inode was marked as having bad fields in
- * pass1, process it and offer to fix/clear it.
- * (We wait until now so that we can display the
- * pathname to the user.)
- */
- if (ctx->inode_bad_map &&
- ext2fs_test_inode_bitmap(ctx->inode_bad_map,
- dirent->inode)) {
- if (e2fsck_process_bad_inode(ctx, ino,
- dirent->inode,
- buf + fs->blocksize)) {
- dirent->inode = 0;
- dir_modified++;
- goto next;
- }
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return DIRENT_ABORT;
- }
-
- if (check_name(ctx, dirent, &cd->pctx))
- dir_modified++;
-
- if (check_filetype(ctx, dirent, &cd->pctx))
- dir_modified++;
-
-#ifdef ENABLE_HTREE
- if (dx_db) {
- ext2fs_dirhash(dx_dir->hashversion, dirent->name,
- (dirent->name_len & 0xFF),
- fs->super->s_hash_seed, &hash, 0);
- if (hash < dx_db->min_hash)
- dx_db->min_hash = hash;
- if (hash > dx_db->max_hash)
- dx_db->max_hash = hash;
- }
-#endif
-
- /*
- * If this is a directory, then mark its parent in its
- * dir_info structure. If the parent field is already
- * filled in, then this directory has more than one
- * hard link. We assume the first link is correct,
- * and ask the user if he/she wants to clear this one.
- */
- if ((dot_state > 1) &&
- (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
- dirent->inode))) {
- subdir = e2fsck_get_dir_info(ctx, dirent->inode);
- if (!subdir) {
- cd->pctx.ino = dirent->inode;
- fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
- goto abort_free_dict;
- }
- if (subdir->parent) {
- cd->pctx.ino2 = subdir->parent;
- if (fix_problem(ctx, PR_2_LINK_DIR,
- &cd->pctx)) {
- dirent->inode = 0;
- dir_modified++;
- goto next;
- }
- cd->pctx.ino2 = 0;
- } else
- subdir->parent = ino;
- }
-
- if (dups_found) {
- ;
- } else if (dict_lookup(&de_dict, dirent)) {
- clear_problem_context(&pctx);
- pctx.ino = ino;
- pctx.dirent = dirent;
- fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
- if (!ctx->dirs_to_hash)
- ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
- if (ctx->dirs_to_hash)
- ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
- dups_found++;
- } else
- dict_alloc_insert(&de_dict, dirent, dirent);
-
- ext2fs_icount_increment(ctx->inode_count, dirent->inode,
- &links);
- if (links > 1)
- ctx->fs_links_count++;
- ctx->fs_total_count++;
- next:
- prev = dirent;
- offset += dirent->rec_len;
- dot_state++;
- } while (offset < fs->blocksize);
-#ifdef ENABLE_HTREE
- if (dx_db) {
- cd->pctx.dir = cd->pctx.ino;
- if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
- (dx_db->type == DX_DIRBLOCK_NODE))
- parse_int_node(fs, db, cd, dx_dir, buf);
- }
-#endif /* ENABLE_HTREE */
- if (offset != fs->blocksize) {
- cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
- if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
- dirent->rec_len = cd->pctx.num;
- dir_modified++;
- }
- }
- if (dir_modified) {
- cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
- if (cd->pctx.errcode) {
- if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
- &cd->pctx))
- goto abort_free_dict;
- }
- ext2fs_mark_changed(fs);
- }
- dict_free_nodes(&de_dict);
- return 0;
-abort_free_dict:
- dict_free_nodes(&de_dict);
- ctx->flags |= E2F_FLAG_ABORT;
- return DIRENT_ABORT;
-}
-
-/*
- * This function is called to deallocate a block, and is an interator
- * functioned called by deallocate inode via ext2fs_iterate_block().
- */
-static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
- e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
- blk_t ref_block FSCK_ATTR((unused)),
- int ref_offset FSCK_ATTR((unused)),
- void *priv_data)
-{
- e2fsck_t ctx = (e2fsck_t) priv_data;
-
- if (HOLE_BLKADDR(*block_nr))
- return 0;
- if ((*block_nr < fs->super->s_first_data_block) ||
- (*block_nr >= fs->super->s_blocks_count))
- return 0;
- ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
- ext2fs_block_alloc_stats(fs, *block_nr, -1);
- return 0;
-}
-
-/*
- * This fuction deallocates an inode
- */
-static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
-{
- ext2_filsys fs = ctx->fs;
- struct ext2_inode inode;
- struct problem_context pctx;
- __u32 count;
-
- ext2fs_icount_store(ctx->inode_link_info, ino, 0);
- e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
- inode.i_links_count = 0;
- inode.i_dtime = time(NULL);
- e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
- clear_problem_context(&pctx);
- pctx.ino = ino;
-
- /*
- * Fix up the bitmaps...
- */
- e2fsck_read_bitmaps(ctx);
- ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
- ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
- if (ctx->inode_bad_map)
- ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
- ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
-
- if (inode.i_file_acl &&
- (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
- pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
- block_buf, -1, &count);
- if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
- pctx.errcode = 0;
- count = 1;
- }
- if (pctx.errcode) {
- pctx.blk = inode.i_file_acl;
- fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- if (count == 0) {
- ext2fs_unmark_block_bitmap(ctx->block_found_map,
- inode.i_file_acl);
- ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
- }
- inode.i_file_acl = 0;
- }
-
- if (!ext2fs_inode_has_valid_blocks(&inode))
- return;
-
- if (LINUX_S_ISREG(inode.i_mode) &&
- (inode.i_size_high || inode.i_size & 0x80000000UL))
- ctx->large_files--;
-
- pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
- deallocate_inode_block, ctx);
- if (pctx.errcode) {
- fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-}
-
-/*
- * This fuction clears the htree flag on an inode
- */
-static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
-{
- struct ext2_inode inode;
-
- e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
- inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
- e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
- if (ctx->dirs_to_hash)
- ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
-}
-
-
-static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
- ext2_ino_t ino, char *buf)
-{
- ext2_filsys fs = ctx->fs;
- struct ext2_inode inode;
- int inode_modified = 0;
- int not_fixed = 0;
- unsigned char *frag, *fsize;
- struct problem_context pctx;
- int problem = 0;
-
- e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
-
- clear_problem_context(&pctx);
- pctx.ino = ino;
- pctx.dir = dir;
- pctx.inode = &inode;
-
- if (inode.i_file_acl &&
- !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
- fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
- inode.i_file_acl = 0;
-#if BB_BIG_ENDIAN
- /*
- * This is a special kludge to deal with long symlinks
- * on big endian systems. i_blocks had already been
- * decremented earlier in pass 1, but since i_file_acl
- * hadn't yet been cleared, ext2fs_read_inode()
- * assumed that the file was short symlink and would
- * not have byte swapped i_block[0]. Hence, we have
- * to byte-swap it here.
- */
- if (LINUX_S_ISLNK(inode.i_mode) &&
- (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
- (inode.i_blocks == fs->blocksize >> 9))
- inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
-#endif
- inode_modified++;
- } else
- not_fixed++;
-
- if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
- !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
- !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
- !(LINUX_S_ISSOCK(inode.i_mode)))
- problem = PR_2_BAD_MODE;
- else if (LINUX_S_ISCHR(inode.i_mode)
- && !e2fsck_pass1_check_device_inode(fs, &inode))
- problem = PR_2_BAD_CHAR_DEV;
- else if (LINUX_S_ISBLK(inode.i_mode)
- && !e2fsck_pass1_check_device_inode(fs, &inode))
- problem = PR_2_BAD_BLOCK_DEV;
- else if (LINUX_S_ISFIFO(inode.i_mode)
- && !e2fsck_pass1_check_device_inode(fs, &inode))
- problem = PR_2_BAD_FIFO;
- else if (LINUX_S_ISSOCK(inode.i_mode)
- && !e2fsck_pass1_check_device_inode(fs, &inode))
- problem = PR_2_BAD_SOCKET;
- else if (LINUX_S_ISLNK(inode.i_mode)
- && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
- problem = PR_2_INVALID_SYMLINK;
- }
-
- if (problem) {
- if (fix_problem(ctx, problem, &pctx)) {
- deallocate_inode(ctx, ino, 0);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return 0;
- return 1;
- } else
- not_fixed++;
- problem = 0;
- }
-
- if (inode.i_faddr) {
- if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
- inode.i_faddr = 0;
- inode_modified++;
- } else
- not_fixed++;
- }
-
- switch (fs->super->s_creator_os) {
- case EXT2_OS_LINUX:
- frag = &inode.osd2.linux2.l_i_frag;
- fsize = &inode.osd2.linux2.l_i_fsize;
- break;
- case EXT2_OS_HURD:
- frag = &inode.osd2.hurd2.h_i_frag;
- fsize = &inode.osd2.hurd2.h_i_fsize;
- break;
- case EXT2_OS_MASIX:
- frag = &inode.osd2.masix2.m_i_frag;
- fsize = &inode.osd2.masix2.m_i_fsize;
- break;
- default:
- frag = fsize = 0;
- }
- if (frag && *frag) {
- pctx.num = *frag;
- if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
- *frag = 0;
- inode_modified++;
- } else
- not_fixed++;
- pctx.num = 0;
- }
- if (fsize && *fsize) {
- pctx.num = *fsize;
- if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
- *fsize = 0;
- inode_modified++;
- } else
- not_fixed++;
- pctx.num = 0;
- }
-
- if (inode.i_file_acl &&
- ((inode.i_file_acl < fs->super->s_first_data_block) ||
- (inode.i_file_acl >= fs->super->s_blocks_count))) {
- if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
- inode.i_file_acl = 0;
- inode_modified++;
- } else
- not_fixed++;
- }
- if (inode.i_dir_acl &&
- LINUX_S_ISDIR(inode.i_mode)) {
- if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
- inode.i_dir_acl = 0;
- inode_modified++;
- } else
- not_fixed++;
- }
-
- if (inode_modified)
- e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
- if (!not_fixed)
- ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
- return 0;
-}
-
-
-/*
- * allocate_dir_block --- this function allocates a new directory
- * block for a particular inode; this is done if a directory has
- * a "hole" in it, or if a directory has a illegal block number
- * that was zeroed out and now needs to be replaced.
- */
-static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
- struct problem_context *pctx)
-{
- ext2_filsys fs = ctx->fs;
- blk_t blk;
- char *block;
- struct ext2_inode inode;
-
- if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
- return 1;
-
- /*
- * Read the inode and block bitmaps in; we'll be messing with
- * them.
- */
- e2fsck_read_bitmaps(ctx);
-
- /*
- * First, find a free block
- */
- pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
- if (pctx->errcode) {
- pctx->str = "ext2fs_new_block";
- fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
- return 1;
- }
- ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
- ext2fs_mark_block_bitmap(fs->block_map, blk);
- ext2fs_mark_bb_dirty(fs);
-
- /*
- * Now let's create the actual data block for the inode
- */
- if (db->blockcnt)
- pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
- else
- pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
- EXT2_ROOT_INO, &block);
-
- if (pctx->errcode) {
- pctx->str = "ext2fs_new_dir_block";
- fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
- return 1;
- }
-
- pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
- ext2fs_free_mem(&block);
- if (pctx->errcode) {
- pctx->str = "ext2fs_write_dir_block";
- fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
- return 1;
- }
-
- /*
- * Update the inode block count
- */
- e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
- inode.i_blocks += fs->blocksize / 512;
- if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
- inode.i_size = (db->blockcnt+1) * fs->blocksize;
- e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
-
- /*
- * Finally, update the block pointers for the inode
- */
- db->blk = blk;
- pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
- 0, update_dir_block, db);
- if (pctx->errcode) {
- pctx->str = "ext2fs_block_iterate";
- fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
- return 1;
- }
-
- return 0;
-}
-
-/*
- * This is a helper function for allocate_dir_block().
- */
-static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
- blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block FSCK_ATTR((unused)),
- int ref_offset FSCK_ATTR((unused)),
- void *priv_data)
-{
- struct ext2_db_entry *db;
-
- db = (struct ext2_db_entry *) priv_data;
- if (db->blockcnt == (int) blockcnt) {
- *block_nr = db->blk;
- return BLOCK_CHANGED;
- }
- return 0;
-}
-
-/*
- * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
- *
- * Pass #3 assures that all directories are connected to the
- * filesystem tree, using the following algorithm:
- *
- * First, the root directory is checked to make sure it exists; if
- * not, e2fsck will offer to create a new one. It is then marked as
- * "done".
- *
- * Then, pass3 interates over all directory inodes; for each directory
- * it attempts to trace up the filesystem tree, using dirinfo.parent
- * until it reaches a directory which has been marked "done". If it
- * cannot do so, then the directory must be disconnected, and e2fsck
- * will offer to reconnect it to /lost+found. While it is chasing
- * parent pointers up the filesystem tree, if pass3 sees a directory
- * twice, then it has detected a filesystem loop, and it will again
- * offer to reconnect the directory to /lost+found in to break the
- * filesystem loop.
- *
- * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
- * reconnect inodes to /lost+found; this subroutine is also used by
- * pass 4. e2fsck_reconnect_file() calls get_lost_and_found(), which
- * is responsible for creating /lost+found if it does not exist.
- *
- * Pass 3 frees the following data structures:
- * - The dirinfo directory information cache.
- */
-
-static void check_root(e2fsck_t ctx);
-static int check_directory(e2fsck_t ctx, struct dir_info *dir,
- struct problem_context *pctx);
-static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
-
-static ext2fs_inode_bitmap inode_loop_detect;
-static ext2fs_inode_bitmap inode_done_map;
-
-static void e2fsck_pass3(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- int i;
- struct problem_context pctx;
- struct dir_info *dir;
- unsigned long maxdirs, count;
-
- clear_problem_context(&pctx);
-
- /* Pass 3 */
-
- if (!(ctx->options & E2F_OPT_PREEN))
- fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
-
- /*
- * Allocate some bitmaps to do loop detection.
- */
- pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
- &inode_done_map);
- if (pctx.errcode) {
- pctx.num = 2;
- fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- goto abort_exit;
- }
- check_root(ctx);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- goto abort_exit;
-
- ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
-
- maxdirs = e2fsck_get_num_dirinfo(ctx);
- count = 1;
-
- if (ctx->progress)
- if ((ctx->progress)(ctx, 3, 0, maxdirs))
- goto abort_exit;
-
- for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- goto abort_exit;
- if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
- goto abort_exit;
- if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
- if (check_directory(ctx, dir, &pctx))
- goto abort_exit;
- }
-
- /*
- * Force the creation of /lost+found if not present
- */
- if ((ctx->flags & E2F_OPT_READONLY) == 0)
- e2fsck_get_lost_and_found(ctx, 1);
-
- /*
- * If there are any directories that need to be indexed or
- * optimized, do it here.
- */
- e2fsck_rehash_directories(ctx);
-
-abort_exit:
- e2fsck_free_dir_info(ctx);
- ext2fs_free_inode_bitmap(inode_loop_detect);
- inode_loop_detect = 0;
- ext2fs_free_inode_bitmap(inode_done_map);
- inode_done_map = 0;
-}
-
-/*
- * This makes sure the root inode is present; if not, we ask if the
- * user wants us to create it. Not creating it is a fatal error.
- */
-static void check_root(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- blk_t blk;
- struct ext2_inode inode;
- char * block;
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
-
- if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
- /*
- * If the root inode is not a directory, die here. The
- * user must have answered 'no' in pass1 when we
- * offered to clear it.
- */
- if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
- EXT2_ROOT_INO))) {
- fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- }
- return;
- }
-
- if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
- fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-
- e2fsck_read_bitmaps(ctx);
-
- /*
- * First, find a free block
- */
- pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
- if (pctx.errcode) {
- pctx.str = "ext2fs_new_block";
- fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
- ext2fs_mark_block_bitmap(fs->block_map, blk);
- ext2fs_mark_bb_dirty(fs);
-
- /*
- * Now let's create the actual data block for the inode
- */
- pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
- &block);
- if (pctx.errcode) {
- pctx.str = "ext2fs_new_dir_block";
- fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-
- pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
- if (pctx.errcode) {
- pctx.str = "ext2fs_write_dir_block";
- fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- ext2fs_free_mem(&block);
-
- /*
- * Set up the inode structure
- */
- memset(&inode, 0, sizeof(inode));
- inode.i_mode = 040755;
- inode.i_size = fs->blocksize;
- inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
- inode.i_links_count = 2;
- inode.i_blocks = fs->blocksize / 512;
- inode.i_block[0] = blk;
-
- /*
- * Write out the inode.
- */
- pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
- if (pctx.errcode) {
- pctx.str = "ext2fs_write_inode";
- fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-
- /*
- * Miscellaneous bookkeeping...
- */
- e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
- ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
- ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
-
- ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
- ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
- ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
- ext2fs_mark_ib_dirty(fs);
-}
-
-/*
- * This subroutine is responsible for making sure that a particular
- * directory is connected to the root; if it isn't we trace it up as
- * far as we can go, and then offer to connect the resulting parent to
- * the lost+found. We have to do loop detection; if we ever discover
- * a loop, we treat that as a disconnected directory and offer to
- * reparent it to lost+found.
- *
- * However, loop detection is expensive, because for very large
- * filesystems, the inode_loop_detect bitmap is huge, and clearing it
- * is non-trivial. Loops in filesystems are also a rare error case,
- * and we shouldn't optimize for error cases. So we try two passes of
- * the algorithm. The first time, we ignore loop detection and merely
- * increment a counter; if the counter exceeds some extreme threshold,
- * then we try again with the loop detection bitmap enabled.
- */
-static int check_directory(e2fsck_t ctx, struct dir_info *dir,
- struct problem_context *pctx)
-{
- ext2_filsys fs = ctx->fs;
- struct dir_info *p = dir;
- int loop_pass = 0, parent_count = 0;
-
- if (!p)
- return 0;
-
- while (1) {
- /*
- * Mark this inode as being "done"; by the time we
- * return from this function, the inode we either be
- * verified as being connected to the directory tree,
- * or we will have offered to reconnect this to
- * lost+found.
- *
- * If it was marked done already, then we've reached a
- * parent we've already checked.
- */
- if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
- break;
-
- /*
- * If this directory doesn't have a parent, or we've
- * seen the parent once already, then offer to
- * reparent it to lost+found
- */
- if (!p->parent ||
- (loop_pass &&
- (ext2fs_test_inode_bitmap(inode_loop_detect,
- p->parent)))) {
- pctx->ino = p->ino;
- if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
- if (e2fsck_reconnect_file(ctx, pctx->ino))
- ext2fs_unmark_valid(fs);
- else {
- p = e2fsck_get_dir_info(ctx, pctx->ino);
- p->parent = ctx->lost_and_found;
- fix_dotdot(ctx, p, ctx->lost_and_found);
- }
- }
- break;
- }
- p = e2fsck_get_dir_info(ctx, p->parent);
- if (!p) {
- fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
- return 0;
- }
- if (loop_pass) {
- ext2fs_mark_inode_bitmap(inode_loop_detect,
- p->ino);
- } else if (parent_count++ > 2048) {
- /*
- * If we've run into a path depth that's
- * greater than 2048, try again with the inode
- * loop bitmap turned on and start from the
- * top.
- */
- loop_pass = 1;
- if (inode_loop_detect)
- ext2fs_clear_inode_bitmap(inode_loop_detect);
- else {
- pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
- if (pctx->errcode) {
- pctx->num = 1;
- fix_problem(ctx,
- PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return -1;
- }
- }
- p = dir;
- }
- }
-
- /*
- * Make sure that .. and the parent directory are the same;
- * offer to fix it if not.
- */
- if (dir->parent != dir->dotdot) {
- pctx->ino = dir->ino;
- pctx->ino2 = dir->dotdot;
- pctx->dir = dir->parent;
- if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
- fix_dotdot(ctx, dir, dir->parent);
- }
- return 0;
-}
-
-/*
- * This routine gets the lost_and_found inode, making it a directory
- * if necessary
- */
-ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
-{
- ext2_filsys fs = ctx->fs;
- ext2_ino_t ino;
- blk_t blk;
- errcode_t retval;
- struct ext2_inode inode;
- char * block;
- static const char name[] = "lost+found";
- struct problem_context pctx;
- struct dir_info *dirinfo;
-
- if (ctx->lost_and_found)
- return ctx->lost_and_found;
-
- clear_problem_context(&pctx);
-
- retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
- sizeof(name)-1, 0, &ino);
- if (retval && !fix)
- return 0;
- if (!retval) {
- if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
- ctx->lost_and_found = ino;
- return ino;
- }
-
- /* Lost+found isn't a directory! */
- if (!fix)
- return 0;
- pctx.ino = ino;
- if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
- return 0;
-
- /* OK, unlink the old /lost+found file. */
- pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
- if (pctx.errcode) {
- pctx.str = "ext2fs_unlink";
- fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
- return 0;
- }
- dirinfo = e2fsck_get_dir_info(ctx, ino);
- if (dirinfo)
- dirinfo->parent = 0;
- e2fsck_adjust_inode_count(ctx, ino, -1);
- } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
- pctx.errcode = retval;
- fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
- }
- if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
- return 0;
-
- /*
- * Read the inode and block bitmaps in; we'll be messing with
- * them.
- */
- e2fsck_read_bitmaps(ctx);
-
- /*
- * First, find a free block
- */
- retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
- if (retval) {
- pctx.errcode = retval;
- fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
- return 0;
- }
- ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
- ext2fs_block_alloc_stats(fs, blk, +1);
-
- /*
- * Next find a free inode.
- */
- retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
- ctx->inode_used_map, &ino);
- if (retval) {
- pctx.errcode = retval;
- fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
- return 0;
- }
- ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
- ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
- ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
-
- /*
- * Now let's create the actual data block for the inode
- */
- retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
- if (retval) {
- pctx.errcode = retval;
- fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
- return 0;
- }
-
- retval = ext2fs_write_dir_block(fs, blk, block);
- ext2fs_free_mem(&block);
- if (retval) {
- pctx.errcode = retval;
- fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
- return 0;
- }
-
- /*
- * Set up the inode structure
- */
- memset(&inode, 0, sizeof(inode));
- inode.i_mode = 040700;
- inode.i_size = fs->blocksize;
- inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
- inode.i_links_count = 2;
- inode.i_blocks = fs->blocksize / 512;
- inode.i_block[0] = blk;
-
- /*
- * Next, write out the inode.
- */
- pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
- if (pctx.errcode) {
- pctx.str = "ext2fs_write_inode";
- fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
- return 0;
- }
- /*
- * Finally, create the directory link
- */
- pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
- if (pctx.errcode) {
- pctx.str = "ext2fs_link";
- fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
- return 0;
- }
-
- /*
- * Miscellaneous bookkeeping that needs to be kept straight.
- */
- e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
- e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
- ext2fs_icount_store(ctx->inode_count, ino, 2);
- ext2fs_icount_store(ctx->inode_link_info, ino, 2);
- ctx->lost_and_found = ino;
- return ino;
-}
-
-/*
- * This routine will connect a file to lost+found
- */
-int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
-{
- ext2_filsys fs = ctx->fs;
- errcode_t retval;
- char name[80];
- struct problem_context pctx;
- struct ext2_inode inode;
- int file_type = 0;
-
- clear_problem_context(&pctx);
- pctx.ino = ino;
-
- if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
- if (e2fsck_get_lost_and_found(ctx, 1) == 0)
- ctx->bad_lost_and_found++;
- }
- if (ctx->bad_lost_and_found) {
- fix_problem(ctx, PR_3_NO_LPF, &pctx);
- return 1;
- }
-
- sprintf(name, "#%u", ino);
- if (ext2fs_read_inode(fs, ino, &inode) == 0)
- file_type = ext2_file_type(inode.i_mode);
- retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
- if (retval == EXT2_ET_DIR_NO_SPACE) {
- if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
- return 1;
- retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
- 1, 0);
- if (retval) {
- pctx.errcode = retval;
- fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
- return 1;
- }
- retval = ext2fs_link(fs, ctx->lost_and_found, name,
- ino, file_type);
- }
- if (retval) {
- pctx.errcode = retval;
- fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
- return 1;
- }
- e2fsck_adjust_inode_count(ctx, ino, 1);
-
- return 0;
-}
-
-/*
- * Utility routine to adjust the inode counts on an inode.
- */
-errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
-{
- ext2_filsys fs = ctx->fs;
- errcode_t retval;
- struct ext2_inode inode;
-
- if (!ino)
- return 0;
-
- retval = ext2fs_read_inode(fs, ino, &inode);
- if (retval)
- return retval;
-
- if (adj == 1) {
- ext2fs_icount_increment(ctx->inode_count, ino, 0);
- if (inode.i_links_count == (__u16) ~0)
- return 0;
- ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
- inode.i_links_count++;
- } else if (adj == -1) {
- ext2fs_icount_decrement(ctx->inode_count, ino, 0);
- if (inode.i_links_count == 0)
- return 0;
- ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
- inode.i_links_count--;
- }
-
- retval = ext2fs_write_inode(fs, ino, &inode);
- if (retval)
- return retval;
-
- return 0;
-}
-
-/*
- * Fix parent --- this routine fixes up the parent of a directory.
- */
-struct fix_dotdot_struct {
- ext2_filsys fs;
- ext2_ino_t parent;
- int done;
- e2fsck_t ctx;
-};
-
-static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
- int offset FSCK_ATTR((unused)),
- int blocksize FSCK_ATTR((unused)),
- char *buf FSCK_ATTR((unused)),
- void *priv_data)
-{
- struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
- errcode_t retval;
- struct problem_context pctx;
-
- if ((dirent->name_len & 0xFF) != 2)
- return 0;
- if (strncmp(dirent->name, "..", 2))
- return 0;
-
- clear_problem_context(&pctx);
-
- retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
- if (retval) {
- pctx.errcode = retval;
- fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
- }
- retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
- if (retval) {
- pctx.errcode = retval;
- fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
- }
- dirent->inode = fp->parent;
-
- fp->done++;
- return DIRENT_ABORT | DIRENT_CHANGED;
-}
-
-static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
-{
- ext2_filsys fs = ctx->fs;
- errcode_t retval;
- struct fix_dotdot_struct fp;
- struct problem_context pctx;
-
- fp.fs = fs;
- fp.parent = parent;
- fp.done = 0;
- fp.ctx = ctx;
-
- retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
- 0, fix_dotdot_proc, &fp);
- if (retval || !fp.done) {
- clear_problem_context(&pctx);
- pctx.ino = dir->ino;
- pctx.errcode = retval;
- fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
- PR_3_FIX_PARENT_NOFIND, &pctx);
- ext2fs_unmark_valid(fs);
- }
- dir->dotdot = parent;
-}
-
-/*
- * These routines are responsible for expanding a /lost+found if it is
- * too small.
- */
-
-struct expand_dir_struct {
- int num;
- int guaranteed_size;
- int newblocks;
- int last_block;
- errcode_t err;
- e2fsck_t ctx;
-};
-
-static int expand_dir_proc(ext2_filsys fs,
- blk_t *blocknr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block FSCK_ATTR((unused)),
- int ref_offset FSCK_ATTR((unused)),
- void *priv_data)
-{
- struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
- blk_t new_blk;
- static blk_t last_blk = 0;
- char *block;
- errcode_t retval;
- e2fsck_t ctx;
-
- ctx = es->ctx;
-
- if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
- return BLOCK_ABORT;
-
- if (blockcnt > 0)
- es->last_block = blockcnt;
- if (*blocknr) {
- last_blk = *blocknr;
- return 0;
- }
- retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
- &new_blk);
- if (retval) {
- es->err = retval;
- return BLOCK_ABORT;
- }
- if (blockcnt > 0) {
- retval = ext2fs_new_dir_block(fs, 0, 0, &block);
- if (retval) {
- es->err = retval;
- return BLOCK_ABORT;
- }
- es->num--;
- retval = ext2fs_write_dir_block(fs, new_blk, block);
- } else {
- retval = ext2fs_get_mem(fs->blocksize, &block);
- if (retval) {
- es->err = retval;
- return BLOCK_ABORT;
- }
- memset(block, 0, fs->blocksize);
- retval = io_channel_write_blk(fs->io, new_blk, 1, block);
- }
- if (retval) {
- es->err = retval;
- return BLOCK_ABORT;
- }
- ext2fs_free_mem(&block);
- *blocknr = new_blk;
- ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
- ext2fs_block_alloc_stats(fs, new_blk, +1);
- es->newblocks++;
-
- if (es->num == 0)
- return (BLOCK_CHANGED | BLOCK_ABORT);
- else
- return BLOCK_CHANGED;
-}
-
-errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
- int num, int guaranteed_size)
-{
- ext2_filsys fs = ctx->fs;
- errcode_t retval;
- struct expand_dir_struct es;
- struct ext2_inode inode;
-
- if (!(fs->flags & EXT2_FLAG_RW))
- return EXT2_ET_RO_FILSYS;
-
- /*
- * Read the inode and block bitmaps in; we'll be messing with
- * them.
- */
- e2fsck_read_bitmaps(ctx);
-
- retval = ext2fs_check_directory(fs, dir);
- if (retval)
- return retval;
-
- es.num = num;
- es.guaranteed_size = guaranteed_size;
- es.last_block = 0;
- es.err = 0;
- es.newblocks = 0;
- es.ctx = ctx;
-
- retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
- 0, expand_dir_proc, &es);
-
- if (es.err)
- return es.err;
-
- /*
- * Update the size and block count fields in the inode.
- */
- retval = ext2fs_read_inode(fs, dir, &inode);
- if (retval)
- return retval;
-
- inode.i_size = (es.last_block + 1) * fs->blocksize;
- inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
-
- e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
-
- return 0;
-}
-
-/*
- * pass4.c -- pass #4 of e2fsck: Check reference counts
- *
- * Pass 4 frees the following data structures:
- * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
- */
-
-/*
- * This routine is called when an inode is not connected to the
- * directory tree.
- *
- * This subroutine returns 1 then the caller shouldn't bother with the
- * rest of the pass 4 tests.
- */
-static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
-{
- ext2_filsys fs = ctx->fs;
- struct ext2_inode inode;
- struct problem_context pctx;
-
- e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
- clear_problem_context(&pctx);
- pctx.ino = i;
- pctx.inode = &inode;
-
- /*
- * Offer to delete any zero-length files that does not have
- * blocks. If there is an EA block, it might have useful
- * information, so we won't prompt to delete it, but let it be
- * reconnected to lost+found.
- */
- if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
- LINUX_S_ISDIR(inode.i_mode))) {
- if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
- ext2fs_icount_store(ctx->inode_link_info, i, 0);
- inode.i_links_count = 0;
- inode.i_dtime = time(NULL);
- e2fsck_write_inode(ctx, i, &inode,
- "disconnect_inode");
- /*
- * Fix up the bitmaps...
- */
- e2fsck_read_bitmaps(ctx);
- ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
- ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
- ext2fs_inode_alloc_stats2(fs, i, -1,
- LINUX_S_ISDIR(inode.i_mode));
- return 0;
- }
- }
-
- /*
- * Prompt to reconnect.
- */
- if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
- if (e2fsck_reconnect_file(ctx, i))
- ext2fs_unmark_valid(fs);
- } else {
- /*
- * If we don't attach the inode, then skip the
- * i_links_test since there's no point in trying to
- * force i_links_count to zero.
- */
- ext2fs_unmark_valid(fs);
- return 1;
- }
- return 0;
-}
-
-
-static void e2fsck_pass4(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- ext2_ino_t i;
- struct ext2_inode inode;
- struct problem_context pctx;
- __u16 link_count, link_counted;
- char *buf = NULL;
- int group, maxgroup;
-
- /* Pass 4 */
-
- clear_problem_context(&pctx);
-
- if (!(ctx->options & E2F_OPT_PREEN))
- fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
-
- group = 0;
- maxgroup = fs->group_desc_count;
- if (ctx->progress)
- if ((ctx->progress)(ctx, 4, 0, maxgroup))
- return;
-
- for (i=1; i <= fs->super->s_inodes_count; i++) {
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
- if ((i % fs->super->s_inodes_per_group) == 0) {
- group++;
- if (ctx->progress)
- if ((ctx->progress)(ctx, 4, group, maxgroup))
- return;
- }
- if (i == EXT2_BAD_INO ||
- (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
- continue;
- if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
- (ctx->inode_imagic_map &&
- ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)))
- continue;
- ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
- ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
- if (link_counted == 0) {
- if (!buf)
- buf = e2fsck_allocate_memory(ctx,
- fs->blocksize, "bad_inode buffer");
- if (e2fsck_process_bad_inode(ctx, 0, i, buf))
- continue;
- if (disconnect_inode(ctx, i))
- continue;
- ext2fs_icount_fetch(ctx->inode_link_info, i,
- &link_count);
- ext2fs_icount_fetch(ctx->inode_count, i,
- &link_counted);
- }
- if (link_counted != link_count) {
- e2fsck_read_inode(ctx, i, &inode, "pass4");
- pctx.ino = i;
- pctx.inode = &inode;
- if (link_count != inode.i_links_count) {
- pctx.num = link_count;
- fix_problem(ctx,
- PR_4_INCONSISTENT_COUNT, &pctx);
- }
- pctx.num = link_counted;
- if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
- inode.i_links_count = link_counted;
- e2fsck_write_inode(ctx, i, &inode, "pass4");
- }
- }
- }
- ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
- ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
- ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
- ctx->inode_imagic_map = 0;
- ext2fs_free_mem(&buf);
-}
-
-/*
- * pass5.c --- check block and inode bitmaps against on-disk bitmaps
- */
-
-#define NO_BLK ((blk_t) -1)
-
-static void print_bitmap_problem(e2fsck_t ctx, int problem,
- struct problem_context *pctx)
-{
- switch (problem) {
- case PR_5_BLOCK_UNUSED:
- if (pctx->blk == pctx->blk2)
- pctx->blk2 = 0;
- else
- problem = PR_5_BLOCK_RANGE_UNUSED;
- break;
- case PR_5_BLOCK_USED:
- if (pctx->blk == pctx->blk2)
- pctx->blk2 = 0;
- else
- problem = PR_5_BLOCK_RANGE_USED;
- break;
- case PR_5_INODE_UNUSED:
- if (pctx->ino == pctx->ino2)
- pctx->ino2 = 0;
- else
- problem = PR_5_INODE_RANGE_UNUSED;
- break;
- case PR_5_INODE_USED:
- if (pctx->ino == pctx->ino2)
- pctx->ino2 = 0;
- else
- problem = PR_5_INODE_RANGE_USED;
- break;
- }
- fix_problem(ctx, problem, pctx);
- pctx->blk = pctx->blk2 = NO_BLK;
- pctx->ino = pctx->ino2 = 0;
-}
-
-static void check_block_bitmaps(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- blk_t i;
- int *free_array;
- int group = 0;
- unsigned int blocks = 0;
- unsigned int free_blocks = 0;
- int group_free = 0;
- int actual, bitmap;
- struct problem_context pctx;
- int problem, save_problem, fixit, had_problem;
- errcode_t retval;
-
- clear_problem_context(&pctx);
- free_array = (int *) e2fsck_allocate_memory(ctx,
- fs->group_desc_count * sizeof(int), "free block count array");
-
- if ((fs->super->s_first_data_block <
- ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
- (fs->super->s_blocks_count-1 >
- ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
- pctx.num = 1;
- pctx.blk = fs->super->s_first_data_block;
- pctx.blk2 = fs->super->s_blocks_count -1;
- pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
- pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
- fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
-
- ctx->flags |= E2F_FLAG_ABORT; /* fatal */
- return;
- }
-
- if ((fs->super->s_first_data_block <
- ext2fs_get_block_bitmap_start(fs->block_map)) ||
- (fs->super->s_blocks_count-1 >
- ext2fs_get_block_bitmap_end(fs->block_map))) {
- pctx.num = 2;
- pctx.blk = fs->super->s_first_data_block;
- pctx.blk2 = fs->super->s_blocks_count -1;
- pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
- pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
- fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
-
- ctx->flags |= E2F_FLAG_ABORT; /* fatal */
- return;
- }
-
-redo_counts:
- had_problem = 0;
- save_problem = 0;
- pctx.blk = pctx.blk2 = NO_BLK;
- for (i = fs->super->s_first_data_block;
- i < fs->super->s_blocks_count;
- i++) {
- actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
- bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
-
- if (actual == bitmap)
- goto do_counts;
-
- if (!actual && bitmap) {
- /*
- * Block not used, but marked in use in the bitmap.
- */
- problem = PR_5_BLOCK_UNUSED;
- } else {
- /*
- * Block used, but not marked in use in the bitmap.
- */
- problem = PR_5_BLOCK_USED;
- }
- if (pctx.blk == NO_BLK) {
- pctx.blk = pctx.blk2 = i;
- save_problem = problem;
- } else {
- if ((problem == save_problem) &&
- (pctx.blk2 == i-1))
- pctx.blk2++;
- else {
- print_bitmap_problem(ctx, save_problem, &pctx);
- pctx.blk = pctx.blk2 = i;
- save_problem = problem;
- }
- }
- ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
- had_problem++;
-
- do_counts:
- if (!bitmap) {
- group_free++;
- free_blocks++;
- }
- blocks ++;
- if ((blocks == fs->super->s_blocks_per_group) ||
- (i == fs->super->s_blocks_count-1)) {
- free_array[group] = group_free;
- group ++;
- blocks = 0;
- group_free = 0;
- if (ctx->progress)
- if ((ctx->progress)(ctx, 5, group,
- fs->group_desc_count*2))
- return;
- }
- }
- if (pctx.blk != NO_BLK)
- print_bitmap_problem(ctx, save_problem, &pctx);
- if (had_problem)
- fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
- else
- fixit = -1;
- ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
-
- if (fixit == 1) {
- ext2fs_free_block_bitmap(fs->block_map);
- retval = ext2fs_copy_bitmap(ctx->block_found_map,
- &fs->block_map);
- if (retval) {
- clear_problem_context(&pctx);
- fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- ext2fs_set_bitmap_padding(fs->block_map);
- ext2fs_mark_bb_dirty(fs);
-
- /* Redo the counts */
- blocks = 0; free_blocks = 0; group_free = 0; group = 0;
- memset(free_array, 0, fs->group_desc_count * sizeof(int));
- goto redo_counts;
- } else if (fixit == 0)
- ext2fs_unmark_valid(fs);
-
- for (i = 0; i < fs->group_desc_count; i++) {
- if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
- pctx.group = i;
- pctx.blk = fs->group_desc[i].bg_free_blocks_count;
- pctx.blk2 = free_array[i];
-
- if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
- &pctx)) {
- fs->group_desc[i].bg_free_blocks_count =
- free_array[i];
- ext2fs_mark_super_dirty(fs);
- } else
- ext2fs_unmark_valid(fs);
- }
- }
- if (free_blocks != fs->super->s_free_blocks_count) {
- pctx.group = 0;
- pctx.blk = fs->super->s_free_blocks_count;
- pctx.blk2 = free_blocks;
-
- if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
- fs->super->s_free_blocks_count = free_blocks;
- ext2fs_mark_super_dirty(fs);
- } else
- ext2fs_unmark_valid(fs);
- }
- ext2fs_free_mem(&free_array);
-}
-
-static void check_inode_bitmaps(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- ext2_ino_t i;
- unsigned int free_inodes = 0;
- int group_free = 0;
- int dirs_count = 0;
- int group = 0;
- unsigned int inodes = 0;
- int *free_array;
- int *dir_array;
- int actual, bitmap;
- errcode_t retval;
- struct problem_context pctx;
- int problem, save_problem, fixit, had_problem;
-
- clear_problem_context(&pctx);
- free_array = (int *) e2fsck_allocate_memory(ctx,
- fs->group_desc_count * sizeof(int), "free inode count array");
-
- dir_array = (int *) e2fsck_allocate_memory(ctx,
- fs->group_desc_count * sizeof(int), "directory count array");
-
- if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
- (fs->super->s_inodes_count >
- ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
- pctx.num = 3;
- pctx.blk = 1;
- pctx.blk2 = fs->super->s_inodes_count;
- pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
- pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
- fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
-
- ctx->flags |= E2F_FLAG_ABORT; /* fatal */
- return;
- }
- if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
- (fs->super->s_inodes_count >
- ext2fs_get_inode_bitmap_end(fs->inode_map))) {
- pctx.num = 4;
- pctx.blk = 1;
- pctx.blk2 = fs->super->s_inodes_count;
- pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
- pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
- fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
-
- ctx->flags |= E2F_FLAG_ABORT; /* fatal */
- return;
- }
-
-redo_counts:
- had_problem = 0;
- save_problem = 0;
- pctx.ino = pctx.ino2 = 0;
- for (i = 1; i <= fs->super->s_inodes_count; i++) {
- actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
- bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
-
- if (actual == bitmap)
- goto do_counts;
-
- if (!actual && bitmap) {
- /*
- * Inode wasn't used, but marked in bitmap
- */
- problem = PR_5_INODE_UNUSED;
- } else /* if (actual && !bitmap) */ {
- /*
- * Inode used, but not in bitmap
- */
- problem = PR_5_INODE_USED;
- }
- if (pctx.ino == 0) {
- pctx.ino = pctx.ino2 = i;
- save_problem = problem;
- } else {
- if ((problem == save_problem) &&
- (pctx.ino2 == i-1))
- pctx.ino2++;
- else {
- print_bitmap_problem(ctx, save_problem, &pctx);
- pctx.ino = pctx.ino2 = i;
- save_problem = problem;
- }
- }
- ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
- had_problem++;
-
-do_counts:
- if (!bitmap) {
- group_free++;
- free_inodes++;
- } else {
- if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
- dirs_count++;
- }
- inodes++;
- if ((inodes == fs->super->s_inodes_per_group) ||
- (i == fs->super->s_inodes_count)) {
- free_array[group] = group_free;
- dir_array[group] = dirs_count;
- group ++;
- inodes = 0;
- group_free = 0;
- dirs_count = 0;
- if (ctx->progress)
- if ((ctx->progress)(ctx, 5,
- group + fs->group_desc_count,
- fs->group_desc_count*2))
- return;
- }
- }
- if (pctx.ino)
- print_bitmap_problem(ctx, save_problem, &pctx);
-
- if (had_problem)
- fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
- else
- fixit = -1;
- ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
-
- if (fixit == 1) {
- ext2fs_free_inode_bitmap(fs->inode_map);
- retval = ext2fs_copy_bitmap(ctx->inode_used_map,
- &fs->inode_map);
- if (retval) {
- clear_problem_context(&pctx);
- fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- ext2fs_set_bitmap_padding(fs->inode_map);
- ext2fs_mark_ib_dirty(fs);
-
- /* redo counts */
- inodes = 0; free_inodes = 0; group_free = 0;
- dirs_count = 0; group = 0;
- memset(free_array, 0, fs->group_desc_count * sizeof(int));
- memset(dir_array, 0, fs->group_desc_count * sizeof(int));
- goto redo_counts;
- } else if (fixit == 0)
- ext2fs_unmark_valid(fs);
-
- for (i = 0; i < fs->group_desc_count; i++) {
- if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
- pctx.group = i;
- pctx.ino = fs->group_desc[i].bg_free_inodes_count;
- pctx.ino2 = free_array[i];
- if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
- &pctx)) {
- fs->group_desc[i].bg_free_inodes_count =
- free_array[i];
- ext2fs_mark_super_dirty(fs);
- } else
- ext2fs_unmark_valid(fs);
- }
- if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
- pctx.group = i;
- pctx.ino = fs->group_desc[i].bg_used_dirs_count;
- pctx.ino2 = dir_array[i];
-
- if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
- &pctx)) {
- fs->group_desc[i].bg_used_dirs_count =
- dir_array[i];
- ext2fs_mark_super_dirty(fs);
- } else
- ext2fs_unmark_valid(fs);
- }
- }
- if (free_inodes != fs->super->s_free_inodes_count) {
- pctx.group = -1;
- pctx.ino = fs->super->s_free_inodes_count;
- pctx.ino2 = free_inodes;
-
- if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
- fs->super->s_free_inodes_count = free_inodes;
- ext2fs_mark_super_dirty(fs);
- } else
- ext2fs_unmark_valid(fs);
- }
- ext2fs_free_mem(&free_array);
- ext2fs_free_mem(&dir_array);
-}
-
-static void check_inode_end(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- ext2_ino_t end, save_inodes_count, i;
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
-
- end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
- pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
- &save_inodes_count);
- if (pctx.errcode) {
- pctx.num = 1;
- fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT; /* fatal */
- return;
- }
- if (save_inodes_count == end)
- return;
-
- for (i = save_inodes_count + 1; i <= end; i++) {
- if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
- if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
- for (i = save_inodes_count + 1; i <= end; i++)
- ext2fs_mark_inode_bitmap(fs->inode_map,
- i);
- ext2fs_mark_ib_dirty(fs);
- } else
- ext2fs_unmark_valid(fs);
- break;
- }
- }
-
- pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
- save_inodes_count, 0);
- if (pctx.errcode) {
- pctx.num = 2;
- fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT; /* fatal */
- return;
- }
-}
-
-static void check_block_end(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- blk_t end, save_blocks_count, i;
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
-
- end = fs->block_map->start +
- (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
- pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
- &save_blocks_count);
- if (pctx.errcode) {
- pctx.num = 3;
- fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT; /* fatal */
- return;
- }
- if (save_blocks_count == end)
- return;
-
- for (i = save_blocks_count + 1; i <= end; i++) {
- if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
- if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
- for (i = save_blocks_count + 1; i <= end; i++)
- ext2fs_mark_block_bitmap(fs->block_map,
- i);
- ext2fs_mark_bb_dirty(fs);
- } else
- ext2fs_unmark_valid(fs);
- break;
- }
- }
-
- pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
- save_blocks_count, 0);
- if (pctx.errcode) {
- pctx.num = 4;
- fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT; /* fatal */
- return;
- }
-}
-
-static void e2fsck_pass5(e2fsck_t ctx)
-{
- struct problem_context pctx;
-
- /* Pass 5 */
-
- clear_problem_context(&pctx);
-
- if (!(ctx->options & E2F_OPT_PREEN))
- fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
-
- if (ctx->progress)
- if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
- return;
-
- e2fsck_read_bitmaps(ctx);
-
- check_block_bitmaps(ctx);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
- check_inode_bitmaps(ctx);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
- check_inode_end(ctx);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
- check_block_end(ctx);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
-
- ext2fs_free_inode_bitmap(ctx->inode_used_map);
- ctx->inode_used_map = 0;
- ext2fs_free_inode_bitmap(ctx->inode_dir_map);
- ctx->inode_dir_map = 0;
- ext2fs_free_block_bitmap(ctx->block_found_map);
- ctx->block_found_map = 0;
-}
-
-/*
- * problem.c --- report filesystem problems to the user
- */
-
-#define PR_PREEN_OK 0x000001 /* Don't need to do preenhalt */
-#define PR_NO_OK 0x000002 /* If user answers no, don't make fs invalid */
-#define PR_NO_DEFAULT 0x000004 /* Default to no */
-#define PR_MSG_ONLY 0x000008 /* Print message only */
-
-/* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
-
-#define PR_FATAL 0x001000 /* Fatal error */
-#define PR_AFTER_CODE 0x002000 /* After asking the first question, */
- /* ask another */
-#define PR_PREEN_NOMSG 0x004000 /* Don't print a message if we're preening */
-#define PR_NOCOLLATE 0x008000 /* Don't collate answers for this latch */
-#define PR_NO_NOMSG 0x010000 /* Don't print a message if e2fsck -n */
-#define PR_PREEN_NO 0x020000 /* Use No as an answer if preening */
-#define PR_PREEN_NOHDR 0x040000 /* Don't print the preen header */
-
-
-#define PROMPT_NONE 0
-#define PROMPT_FIX 1
-#define PROMPT_CLEAR 2
-#define PROMPT_RELOCATE 3
-#define PROMPT_ALLOCATE 4
-#define PROMPT_EXPAND 5
-#define PROMPT_CONNECT 6
-#define PROMPT_CREATE 7
-#define PROMPT_SALVAGE 8
-#define PROMPT_TRUNCATE 9
-#define PROMPT_CLEAR_INODE 10
-#define PROMPT_ABORT 11
-#define PROMPT_SPLIT 12
-#define PROMPT_CONTINUE 13
-#define PROMPT_CLONE 14
-#define PROMPT_DELETE 15
-#define PROMPT_SUPPRESS 16
-#define PROMPT_UNLINK 17
-#define PROMPT_CLEAR_HTREE 18
-#define PROMPT_RECREATE 19
-#define PROMPT_NULL 20
-
-struct e2fsck_problem {
- problem_t e2p_code;
- const char * e2p_description;
- char prompt;
- int flags;
- problem_t second_code;
-};
-
-struct latch_descr {
- int latch_code;
- problem_t question;
- problem_t end_message;
- int flags;
-};
-
-/*
- * These are the prompts which are used to ask the user if they want
- * to fix a problem.
- */
-static const char *const prompt[] = {
- N_("(no prompt)"), /* 0 */
- N_("Fix"), /* 1 */
- N_("Clear"), /* 2 */
- N_("Relocate"), /* 3 */
- N_("Allocate"), /* 4 */
- N_("Expand"), /* 5 */
- N_("Connect to /lost+found"), /* 6 */
- N_("Create"), /* 7 */
- N_("Salvage"), /* 8 */
- N_("Truncate"), /* 9 */
- N_("Clear inode"), /* 10 */
- N_("Abort"), /* 11 */
- N_("Split"), /* 12 */
- N_("Continue"), /* 13 */
- N_("Clone multiply-claimed blocks"), /* 14 */
- N_("Delete file"), /* 15 */
- N_("Suppress messages"),/* 16 */
- N_("Unlink"), /* 17 */
- N_("Clear HTree index"),/* 18 */
- N_("Recreate"), /* 19 */
- "", /* 20 */
-};
-
-/*
- * These messages are printed when we are preen mode and we will be
- * automatically fixing the problem.
- */
-static const char *const preen_msg[] = {
- N_("(NONE)"), /* 0 */
- N_("FIXED"), /* 1 */
- N_("CLEARED"), /* 2 */
- N_("RELOCATED"), /* 3 */
- N_("ALLOCATED"), /* 4 */
- N_("EXPANDED"), /* 5 */
- N_("RECONNECTED"), /* 6 */
- N_("CREATED"), /* 7 */
- N_("SALVAGED"), /* 8 */
- N_("TRUNCATED"), /* 9 */
- N_("INODE CLEARED"), /* 10 */
- N_("ABORTED"), /* 11 */
- N_("SPLIT"), /* 12 */
- N_("CONTINUING"), /* 13 */
- N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
- N_("FILE DELETED"), /* 15 */
- N_("SUPPRESSED"), /* 16 */
- N_("UNLINKED"), /* 17 */
- N_("HTREE INDEX CLEARED"),/* 18 */
- N_("WILL RECREATE"), /* 19 */
- "", /* 20 */
-};
-
-static const struct e2fsck_problem problem_table[] = {
-
- /* Pre-Pass 1 errors */
-
- /* Block bitmap not in group */
- { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g. (@b %b)\n"),
- PROMPT_RELOCATE, PR_LATCH_RELOC },
-
- /* Inode bitmap not in group */
- { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g. (@b %b)\n"),
- PROMPT_RELOCATE, PR_LATCH_RELOC },
-
- /* Inode table not in group */
- { PR_0_ITABLE_NOT_GROUP,
- N_("@i table for @g %g is not in @g. (@b %b)\n"
- "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
- PROMPT_RELOCATE, PR_LATCH_RELOC },
-
- /* Superblock corrupt */
- { PR_0_SB_CORRUPT,
- N_("\nThe @S could not be read or does not describe a correct ext2\n"
- "@f. If the @v is valid and it really contains an ext2\n"
- "@f (and not swap or ufs or something else), then the @S\n"
- "is corrupt, and you might try running e2fsck with an alternate @S:\n"
- " e2fsck -b %S <@v>\n\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Filesystem size is wrong */
- { PR_0_FS_SIZE_WRONG,
- N_("The @f size (according to the @S) is %b @bs\n"
- "The physical size of the @v is %c @bs\n"
- "Either the @S or the partition table is likely to be corrupt!\n"),
- PROMPT_ABORT, 0 },
-
- /* Fragments not supported */
- { PR_0_NO_FRAGMENTS,
- N_("@S @b_size = %b, fragsize = %c.\n"
- "This version of e2fsck does not support fragment sizes different\n"
- "from the @b size.\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Bad blocks_per_group */
- { PR_0_BLOCKS_PER_GROUP,
- N_("@S @bs_per_group = %b, should have been %c\n"),
- PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
-
- /* Bad first_data_block */
- { PR_0_FIRST_DATA_BLOCK,
- N_("@S first_data_@b = %b, should have been %c\n"),
- PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
-
- /* Adding UUID to filesystem */
- { PR_0_ADD_UUID,
- N_("@f did not have a UUID; generating one.\n\n"),
- PROMPT_NONE, 0 },
-
- /* Relocate hint */
- { PR_0_RELOCATE_HINT,
- N_("Note: if several inode or block bitmap blocks or part\n"
- "of the inode table require relocation, you may wish to try\n"
- "running e2fsck with the '-b %S' option first. The problem\n"
- "may lie only with the primary block group descriptors, and\n"
- "the backup block group descriptors may be OK.\n\n"),
- PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
-
- /* Miscellaneous superblock corruption */
- { PR_0_MISC_CORRUPT_SUPER,
- N_("Corruption found in @S. (%s = %N).\n"),
- PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
-
- /* Error determing physical device size of filesystem */
- { PR_0_GETSIZE_ERROR,
- N_("Error determining size of the physical @v: %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Inode count in superblock is incorrect */
- { PR_0_INODE_COUNT_WRONG,
- N_("@i count in @S is %i, @s %j.\n"),
- PROMPT_FIX, 0 },
-
- { PR_0_HURD_CLEAR_FILETYPE,
- N_("The Hurd does not support the filetype feature.\n"),
- PROMPT_CLEAR, 0 },
-
- /* Journal inode is invalid */
- { PR_0_JOURNAL_BAD_INODE,
- N_("@S has an @n ext3 @j (@i %i).\n"),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* The external journal has (unsupported) multiple filesystems */
- { PR_0_JOURNAL_UNSUPP_MULTIFS,
- N_("External @j has multiple @f users (unsupported).\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Can't find external journal */
- { PR_0_CANT_FIND_JOURNAL,
- N_("Can't find external @j\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* External journal has bad superblock */
- { PR_0_EXT_JOURNAL_BAD_SUPER,
- N_("External @j has bad @S\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Superblock has a bad journal UUID */
- { PR_0_JOURNAL_BAD_UUID,
- N_("External @j does not support this @f\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Journal has an unknown superblock type */
- { PR_0_JOURNAL_UNSUPP_SUPER,
- N_("Ext3 @j @S is unknown type %N (unsupported).\n"
- "It is likely that your copy of e2fsck is old and/or doesn't "
- "support this @j format.\n"
- "It is also possible the @j @S is corrupt.\n"),
- PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
-
- /* Journal superblock is corrupt */
- { PR_0_JOURNAL_BAD_SUPER,
- N_("Ext3 @j @S is corrupt.\n"),
- PROMPT_FIX, PR_PREEN_OK },
-
- /* Superblock flag should be cleared */
- { PR_0_JOURNAL_HAS_JOURNAL,
- N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* Superblock flag is incorrect */
- { PR_0_JOURNAL_RECOVER_SET,
- N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* Journal has data, but recovery flag is clear */
- { PR_0_JOURNAL_RECOVERY_CLEAR,
- N_("ext3 recovery flag is clear, but @j has data.\n"),
- PROMPT_NONE, 0 },
-
- /* Ask if we should clear the journal */
- { PR_0_JOURNAL_RESET_JOURNAL,
- N_("Clear @j"),
- PROMPT_NULL, PR_PREEN_NOMSG },
-
- /* Ask if we should run the journal anyway */
- { PR_0_JOURNAL_RUN,
- N_("Run @j anyway"),
- PROMPT_NULL, 0 },
-
- /* Run the journal by default */
- { PR_0_JOURNAL_RUN_DEFAULT,
- N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
- PROMPT_NONE, 0 },
-
- /* Clearing orphan inode */
- { PR_0_ORPHAN_CLEAR_INODE,
- N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
- PROMPT_NONE, 0 },
-
- /* Illegal block found in orphaned inode */
- { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
- N_("@I @b #%B (%b) found in @o @i %i.\n"),
- PROMPT_NONE, 0 },
-
- /* Already cleared block found in orphaned inode */
- { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
- N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
- PROMPT_NONE, 0 },
-
- /* Illegal orphan inode in superblock */
- { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
- N_("@I @o @i %i in @S.\n"),
- PROMPT_NONE, 0 },
-
- /* Illegal inode in orphaned inode list */
- { PR_0_ORPHAN_ILLEGAL_INODE,
- N_("@I @i %i in @o @i list.\n"),
- PROMPT_NONE, 0 },
-
- /* Filesystem revision is 0, but feature flags are set */
- { PR_0_FS_REV_LEVEL,
- N_("@f has feature flag(s) set, but is a revision 0 @f. "),
- PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
-
- /* Journal superblock has an unknown read-only feature flag set */
- { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
- N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
- PROMPT_ABORT, 0 },
-
- /* Journal superblock has an unknown incompatible feature flag set */
- { PR_0_JOURNAL_UNSUPP_INCOMPAT,
- N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
- PROMPT_ABORT, 0 },
-
- /* Journal has unsupported version number */
- { PR_0_JOURNAL_UNSUPP_VERSION,
- N_("@j version not supported by this e2fsck.\n"),
- PROMPT_ABORT, 0 },
-
- /* Moving journal to hidden file */
- { PR_0_MOVE_JOURNAL,
- N_("Moving @j from /%s to hidden @i.\n\n"),
- PROMPT_NONE, 0 },
-
- /* Error moving journal to hidden file */
- { PR_0_ERR_MOVE_JOURNAL,
- N_("Error moving @j: %m\n\n"),
- PROMPT_NONE, 0 },
-
- /* Clearing V2 journal superblock */
- { PR_0_CLEAR_V2_JOURNAL,
- N_("Found @n V2 @j @S fields (from V1 @j).\n"
- "Clearing fields beyond the V1 @j @S...\n\n"),
- PROMPT_NONE, 0 },
-
- /* Backup journal inode blocks */
- { PR_0_BACKUP_JNL,
- N_("Backing up @j @i @b information.\n\n"),
- PROMPT_NONE, 0 },
-
- /* Reserved blocks w/o resize_inode */
- { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
- N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
- "is %N; @s zero. "),
- PROMPT_FIX, 0 },
-
- /* Resize_inode not enabled, but resize inode is non-zero */
- { PR_0_CLEAR_RESIZE_INODE,
- N_("Resize_@i not enabled, but the resize @i is non-zero. "),
- PROMPT_CLEAR, 0 },
-
- /* Resize inode invalid */
- { PR_0_RESIZE_INODE_INVALID,
- N_("Resize @i not valid. "),
- PROMPT_RECREATE, 0 },
-
- /* Pass 1 errors */
-
- /* Pass 1: Checking inodes, blocks, and sizes */
- { PR_1_PASS_HEADER,
- N_("Pass 1: Checking @is, @bs, and sizes\n"),
- PROMPT_NONE, 0 },
-
- /* Root directory is not an inode */
- { PR_1_ROOT_NO_DIR, N_("@r is not a @d. "),
- PROMPT_CLEAR, 0 },
-
- /* Root directory has dtime set */
- { PR_1_ROOT_DTIME,
- N_("@r has dtime set (probably due to old mke2fs). "),
- PROMPT_FIX, PR_PREEN_OK },
-
- /* Reserved inode has bad mode */
- { PR_1_RESERVED_BAD_MODE,
- N_("Reserved @i %i (%Q) has @n mode. "),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* Deleted inode has zero dtime */
- { PR_1_ZERO_DTIME,
- N_("@D @i %i has zero dtime. "),
- PROMPT_FIX, PR_PREEN_OK },
-
- /* Inode in use, but dtime set */
- { PR_1_SET_DTIME,
- N_("@i %i is in use, but has dtime set. "),
- PROMPT_FIX, PR_PREEN_OK },
-
- /* Zero-length directory */
- { PR_1_ZERO_LENGTH_DIR,
- N_("@i %i is a @z @d. "),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* Block bitmap conflicts with some other fs block */
- { PR_1_BB_CONFLICT,
- N_("@g %g's @b @B at %b @C.\n"),
- PROMPT_RELOCATE, 0 },
-
- /* Inode bitmap conflicts with some other fs block */
- { PR_1_IB_CONFLICT,
- N_("@g %g's @i @B at %b @C.\n"),
- PROMPT_RELOCATE, 0 },
-
- /* Inode table conflicts with some other fs block */
- { PR_1_ITABLE_CONFLICT,
- N_("@g %g's @i table at %b @C.\n"),
- PROMPT_RELOCATE, 0 },
-
- /* Block bitmap is on a bad block */
- { PR_1_BB_BAD_BLOCK,
- N_("@g %g's @b @B (%b) is bad. "),
- PROMPT_RELOCATE, 0 },
-
- /* Inode bitmap is on a bad block */
- { PR_1_IB_BAD_BLOCK,
- N_("@g %g's @i @B (%b) is bad. "),
- PROMPT_RELOCATE, 0 },
-
- /* Inode has incorrect i_size */
- { PR_1_BAD_I_SIZE,
- N_("@i %i, i_size is %Is, @s %N. "),
- PROMPT_FIX, PR_PREEN_OK },
-
- /* Inode has incorrect i_blocks */
- { PR_1_BAD_I_BLOCKS,
- N_("@i %i, i_@bs is %Ib, @s %N. "),
- PROMPT_FIX, PR_PREEN_OK },
-
- /* Illegal blocknumber in inode */
- { PR_1_ILLEGAL_BLOCK_NUM,
- N_("@I @b #%B (%b) in @i %i. "),
- PROMPT_CLEAR, PR_LATCH_BLOCK },
-
- /* Block number overlaps fs metadata */
- { PR_1_BLOCK_OVERLAPS_METADATA,
- N_("@b #%B (%b) overlaps @f metadata in @i %i. "),
- PROMPT_CLEAR, PR_LATCH_BLOCK },
-
- /* Inode has illegal blocks (latch question) */
- { PR_1_INODE_BLOCK_LATCH,
- N_("@i %i has illegal @b(s). "),
- PROMPT_CLEAR, 0 },
-
- /* Too many bad blocks in inode */
- { PR_1_TOO_MANY_BAD_BLOCKS,
- N_("Too many illegal @bs in @i %i.\n"),
- PROMPT_CLEAR_INODE, PR_NO_OK },
-
- /* Illegal block number in bad block inode */
- { PR_1_BB_ILLEGAL_BLOCK_NUM,
- N_("@I @b #%B (%b) in bad @b @i. "),
- PROMPT_CLEAR, PR_LATCH_BBLOCK },
-
- /* Bad block inode has illegal blocks (latch question) */
- { PR_1_INODE_BBLOCK_LATCH,
- N_("Bad @b @i has illegal @b(s). "),
- PROMPT_CLEAR, 0 },
-
- /* Duplicate or bad blocks in use! */
- { PR_1_DUP_BLOCKS_PREENSTOP,
- N_("Duplicate or bad @b in use!\n"),
- PROMPT_NONE, 0 },
-
- /* Bad block used as bad block indirect block */
- { PR_1_BBINODE_BAD_METABLOCK,
- N_("Bad @b %b used as bad @b @i indirect @b. "),
- PROMPT_CLEAR, PR_LATCH_BBLOCK },
-
- /* Inconsistency can't be fixed prompt */
- { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
- N_("\nThe bad @b @i has probably been corrupted. You probably\n"
- "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
- "in the @f.\n"),
- PROMPT_CONTINUE, PR_PREEN_NOMSG },
-
- /* Bad primary block */
- { PR_1_BAD_PRIMARY_BLOCK,
- N_("\nIf the @b is really bad, the @f cannot be fixed.\n"),
- PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
-
- /* Bad primary block prompt */
- { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
- N_("You can remove this @b from the bad @b list and hope\n"
- "that the @b is really OK. But there are no guarantees.\n\n"),
- PROMPT_CLEAR, PR_PREEN_NOMSG },
-
- /* Bad primary superblock */
- { PR_1_BAD_PRIMARY_SUPERBLOCK,
- N_("The primary @S (%b) is on the bad @b list.\n"),
- PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
-
- /* Bad primary block group descriptors */
- { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
- N_("Block %b in the primary @g descriptors "
- "is on the bad @b list\n"),
- PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
-
- /* Bad superblock in group */
- { PR_1_BAD_SUPERBLOCK,
- N_("Warning: Group %g's @S (%b) is bad.\n"),
- PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Bad block group descriptors in group */
- { PR_1_BAD_GROUP_DESCRIPTORS,
- N_("Warning: Group %g's copy of the @g descriptors has a bad "
- "@b (%b).\n"),
- PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Block claimed for no reason */
- { PR_1_PROGERR_CLAIMED_BLOCK,
- N_("Programming error? @b #%b claimed for no reason in "
- "process_bad_@b.\n"),
- PROMPT_NONE, PR_PREEN_OK },
-
- /* Error allocating blocks for relocating metadata */
- { PR_1_RELOC_BLOCK_ALLOCATE,
- N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
- PROMPT_NONE, PR_PREEN_OK },
-
- /* Error allocating block buffer during relocation process */
- { PR_1_RELOC_MEMORY_ALLOCATE,
- N_("@A @b buffer for relocating %s\n"),
- PROMPT_NONE, PR_PREEN_OK },
-
- /* Relocating metadata group information from X to Y */
- { PR_1_RELOC_FROM_TO,
- N_("Relocating @g %g's %s from %b to %c...\n"),
- PROMPT_NONE, PR_PREEN_OK },
-
- /* Relocating metatdata group information to X */
- { PR_1_RELOC_TO,
- N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
- PROMPT_NONE, PR_PREEN_OK },
-
- /* Block read error during relocation process */
- { PR_1_RELOC_READ_ERR,
- N_("Warning: could not read @b %b of %s: %m\n"),
- PROMPT_NONE, PR_PREEN_OK },
-
- /* Block write error during relocation process */
- { PR_1_RELOC_WRITE_ERR,
- N_("Warning: could not write @b %b for %s: %m\n"),
- PROMPT_NONE, PR_PREEN_OK },
-
- /* Error allocating inode bitmap */
- { PR_1_ALLOCATE_IBITMAP_ERROR,
- N_("@A @i @B (%N): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error allocating block bitmap */
- { PR_1_ALLOCATE_BBITMAP_ERROR,
- N_("@A @b @B (%N): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error allocating icount structure */
- { PR_1_ALLOCATE_ICOUNT,
- N_("@A icount link information: %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error allocating dbcount */
- { PR_1_ALLOCATE_DBCOUNT,
- N_("@A @d @b array: %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error while scanning inodes */
- { PR_1_ISCAN_ERROR,
- N_("Error while scanning @is (%i): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error while iterating over blocks */
- { PR_1_BLOCK_ITERATE,
- N_("Error while iterating over @bs in @i %i: %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error while storing inode count information */
- { PR_1_ICOUNT_STORE,
- N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error while storing directory block information */
- { PR_1_ADD_DBLOCK,
- N_("Error storing @d @b information "
- "(@i=%i, @b=%b, num=%N): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error while reading inode (for clearing) */
- { PR_1_READ_INODE,
- N_("Error reading @i %i: %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Suppress messages prompt */
- { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
-
- /* Imagic flag set on an inode when filesystem doesn't support it */
- { PR_1_SET_IMAGIC,
- N_("@i %i has imagic flag set. "),
- PROMPT_CLEAR, 0 },
-
- /* Immutable flag set on a device or socket inode */
- { PR_1_SET_IMMUTABLE,
- N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
- "or append-only flag set. "),
- PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
-
- /* Compression flag set on an inode when filesystem doesn't support it */
- { PR_1_COMPR_SET,
- N_("@i %i has @cion flag set on @f without @cion support. "),
- PROMPT_CLEAR, 0 },
-
- /* Non-zero size for device, fifo or socket inode */
- { PR_1_SET_NONZSIZE,
- N_("Special (@v/socket/fifo) @i %i has non-zero size. "),
- PROMPT_FIX, PR_PREEN_OK },
-
- /* Filesystem revision is 0, but feature flags are set */
- { PR_1_FS_REV_LEVEL,
- N_("@f has feature flag(s) set, but is a revision 0 @f. "),
- PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
-
- /* Journal inode is not in use, but contains data */
- { PR_1_JOURNAL_INODE_NOT_CLEAR,
- N_("@j @i is not in use, but contains data. "),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* Journal has bad mode */
- { PR_1_JOURNAL_BAD_MODE,
- N_("@j is not regular file. "),
- PROMPT_FIX, PR_PREEN_OK },
-
- /* Deal with inodes that were part of orphan linked list */
- { PR_1_LOW_DTIME,
- N_("@i %i was part of the @o @i list. "),
- PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
-
- /* Deal with inodes that were part of corrupted orphan linked
- list (latch question) */
- { PR_1_ORPHAN_LIST_REFUGEES,
- N_("@is that were part of a corrupted orphan linked list found. "),
- PROMPT_FIX, 0 },
-
- /* Error allocating refcount structure */
- { PR_1_ALLOCATE_REFCOUNT,
- N_("@A refcount structure (%N): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error reading extended attribute block */
- { PR_1_READ_EA_BLOCK,
- N_("Error reading @a @b %b for @i %i. "),
- PROMPT_CLEAR, 0 },
-
- /* Invalid extended attribute block */
- { PR_1_BAD_EA_BLOCK,
- N_("@i %i has a bad @a @b %b. "),
- PROMPT_CLEAR, 0 },
-
- /* Error reading Extended Attribute block while fixing refcount */
- { PR_1_EXTATTR_READ_ABORT,
- N_("Error reading @a @b %b (%m). "),
- PROMPT_ABORT, 0 },
-
- /* Extended attribute reference count incorrect */
- { PR_1_EXTATTR_REFCOUNT,
- N_("@a @b %b has reference count %B, @s %N. "),
- PROMPT_FIX, 0 },
-
- /* Error writing Extended Attribute block while fixing refcount */
- { PR_1_EXTATTR_WRITE,
- N_("Error writing @a @b %b (%m). "),
- PROMPT_ABORT, 0 },
-
- /* Multiple EA blocks not supported */
- { PR_1_EA_MULTI_BLOCK,
- N_("@a @b %b has h_@bs > 1. "),
- PROMPT_CLEAR, 0},
-
- /* Error allocating EA region allocation structure */
- { PR_1_EA_ALLOC_REGION,
- N_("@A @a @b %b. "),
- PROMPT_ABORT, 0},
-
- /* Error EA allocation collision */
- { PR_1_EA_ALLOC_COLLISION,
- N_("@a @b %b is corrupt (allocation collision). "),
- PROMPT_CLEAR, 0},
-
- /* Bad extended attribute name */
- { PR_1_EA_BAD_NAME,
- N_("@a @b %b is corrupt (@n name). "),
- PROMPT_CLEAR, 0},
-
- /* Bad extended attribute value */
- { PR_1_EA_BAD_VALUE,
- N_("@a @b %b is corrupt (@n value). "),
- PROMPT_CLEAR, 0},
-
- /* Inode too big (latch question) */
- { PR_1_INODE_TOOBIG,
- N_("@i %i is too big. "), PROMPT_TRUNCATE, 0 },
-
- /* Directory too big */
- { PR_1_TOOBIG_DIR,
- N_("@b #%B (%b) causes @d to be too big. "),
- PROMPT_CLEAR, PR_LATCH_TOOBIG },
-
- /* Regular file too big */
- { PR_1_TOOBIG_REG,
- N_("@b #%B (%b) causes file to be too big. "),
- PROMPT_CLEAR, PR_LATCH_TOOBIG },
-
- /* Symlink too big */
- { PR_1_TOOBIG_SYMLINK,
- N_("@b #%B (%b) causes symlink to be too big. "),
- PROMPT_CLEAR, PR_LATCH_TOOBIG },
-
- /* INDEX_FL flag set on a non-HTREE filesystem */
- { PR_1_HTREE_SET,
- N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
- PROMPT_CLEAR_HTREE, PR_PREEN_OK },
-
- /* INDEX_FL flag set on a non-directory */
- { PR_1_HTREE_NODIR,
- N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
- PROMPT_CLEAR_HTREE, PR_PREEN_OK },
-
- /* Invalid root node in HTREE directory */
- { PR_1_HTREE_BADROOT,
- N_("@h %i has an @n root node.\n"),
- PROMPT_CLEAR_HTREE, PR_PREEN_OK },
-
- /* Unsupported hash version in HTREE directory */
- { PR_1_HTREE_HASHV,
- N_("@h %i has an unsupported hash version (%N)\n"),
- PROMPT_CLEAR_HTREE, PR_PREEN_OK },
-
- /* Incompatible flag in HTREE root node */
- { PR_1_HTREE_INCOMPAT,
- N_("@h %i uses an incompatible htree root node flag.\n"),
- PROMPT_CLEAR_HTREE, PR_PREEN_OK },
-
- /* HTREE too deep */
- { PR_1_HTREE_DEPTH,
- N_("@h %i has a tree depth (%N) which is too big\n"),
- PROMPT_CLEAR_HTREE, PR_PREEN_OK },
-
- /* Bad block has indirect block that conflicts with filesystem block */
- { PR_1_BB_FS_BLOCK,
- N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
- "@f metadata. "),
- PROMPT_CLEAR, PR_LATCH_BBLOCK },
-
- /* Resize inode failed */
- { PR_1_RESIZE_INODE_CREATE,
- N_("Resize @i (re)creation failed: %m."),
- PROMPT_ABORT, 0 },
-
- /* invalid inode->i_extra_isize */
- { PR_1_EXTRA_ISIZE,
- N_("@i %i has a extra size (%IS) which is @n\n"),
- PROMPT_FIX, PR_PREEN_OK },
-
- /* invalid ea entry->e_name_len */
- { PR_1_ATTR_NAME_LEN,
- N_("@a in @i %i has a namelen (%N) which is @n\n"),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* invalid ea entry->e_value_size */
- { PR_1_ATTR_VALUE_SIZE,
- N_("@a in @i %i has a value size (%N) which is @n\n"),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* invalid ea entry->e_value_offs */
- { PR_1_ATTR_VALUE_OFFSET,
- N_("@a in @i %i has a value offset (%N) which is @n\n"),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* invalid ea entry->e_value_block */
- { PR_1_ATTR_VALUE_BLOCK,
- N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* invalid ea entry->e_hash */
- { PR_1_ATTR_HASH,
- N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* Pass 1b errors */
-
- /* Pass 1B: Rescan for duplicate/bad blocks */
- { PR_1B_PASS_HEADER,
- N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
- "Pass 1B: Rescanning for @m @bs\n"),
- PROMPT_NONE, 0 },
-
- /* Duplicate/bad block(s) header */
- { PR_1B_DUP_BLOCK_HEADER,
- N_("@m @b(s) in @i %i:"),
- PROMPT_NONE, 0 },
-
- /* Duplicate/bad block(s) in inode */
- { PR_1B_DUP_BLOCK,
- " %b",
- PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
-
- /* Duplicate/bad block(s) end */
- { PR_1B_DUP_BLOCK_END,
- "\n",
- PROMPT_NONE, PR_PREEN_NOHDR },
-
- /* Error while scanning inodes */
- { PR_1B_ISCAN_ERROR,
- N_("Error while scanning inodes (%i): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error allocating inode bitmap */
- { PR_1B_ALLOCATE_IBITMAP_ERROR,
- N_("@A @i @B (@i_dup_map): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error while iterating over blocks */
- { PR_1B_BLOCK_ITERATE,
- N_("Error while iterating over @bs in @i %i (%s): %m\n"),
- PROMPT_NONE, 0 },
-
- /* Error adjusting EA refcount */
- { PR_1B_ADJ_EA_REFCOUNT,
- N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
- PROMPT_NONE, 0 },
-
-
- /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
- { PR_1C_PASS_HEADER,
- N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
- PROMPT_NONE, 0 },
-
-
- /* Pass 1D: Reconciling multiply-claimed blocks */
- { PR_1D_PASS_HEADER,
- N_("Pass 1D: Reconciling @m @bs\n"),
- PROMPT_NONE, 0 },
-
- /* File has duplicate blocks */
- { PR_1D_DUP_FILE,
- N_("File %Q (@i #%i, mod time %IM)\n"
- " has %B @m @b(s), shared with %N file(s):\n"),
- PROMPT_NONE, 0 },
-
- /* List of files sharing duplicate blocks */
- { PR_1D_DUP_FILE_LIST,
- N_("\t%Q (@i #%i, mod time %IM)\n"),
- PROMPT_NONE, 0 },
-
- /* File sharing blocks with filesystem metadata */
- { PR_1D_SHARE_METADATA,
- N_("\t<@f metadata>\n"),
- PROMPT_NONE, 0 },
-
- /* Report of how many duplicate/bad inodes */
- { PR_1D_NUM_DUP_INODES,
- N_("(There are %N @is containing @m @bs.)\n\n"),
- PROMPT_NONE, 0 },
-
- /* Duplicated blocks already reassigned or cloned. */
- { PR_1D_DUP_BLOCKS_DEALT,
- N_("@m @bs already reassigned or cloned.\n\n"),
- PROMPT_NONE, 0 },
-
- /* Clone duplicate/bad blocks? */
- { PR_1D_CLONE_QUESTION,
- "", PROMPT_CLONE, PR_NO_OK },
-
- /* Delete file? */
- { PR_1D_DELETE_QUESTION,
- "", PROMPT_DELETE, 0 },
-
- /* Couldn't clone file (error) */
- { PR_1D_CLONE_ERROR,
- N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
-
- /* Pass 2 errors */
-
- /* Pass 2: Checking directory structure */
- { PR_2_PASS_HEADER,
- N_("Pass 2: Checking @d structure\n"),
- PROMPT_NONE, 0 },
-
- /* Bad inode number for '.' */
- { PR_2_BAD_INODE_DOT,
- N_("@n @i number for '.' in @d @i %i.\n"),
- PROMPT_FIX, 0 },
-
- /* Directory entry has bad inode number */
- { PR_2_BAD_INO,
- N_("@E has @n @i #: %Di.\n"),
- PROMPT_CLEAR, 0 },
-
- /* Directory entry has deleted or unused inode */
- { PR_2_UNUSED_INODE,
- N_("@E has @D/unused @i %Di. "),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* Directry entry is link to '.' */
- { PR_2_LINK_DOT,
- N_("@E @L to '.' "),
- PROMPT_CLEAR, 0 },
-
- /* Directory entry points to inode now located in a bad block */
- { PR_2_BB_INODE,
- N_("@E points to @i (%Di) located in a bad @b.\n"),
- PROMPT_CLEAR, 0 },
-
- /* Directory entry contains a link to a directory */
- { PR_2_LINK_DIR,
- N_("@E @L to @d %P (%Di).\n"),
- PROMPT_CLEAR, 0 },
-
- /* Directory entry contains a link to the root directry */
- { PR_2_LINK_ROOT,
- N_("@E @L to the @r.\n"),
- PROMPT_CLEAR, 0 },
-
- /* Directory entry has illegal characters in its name */
- { PR_2_BAD_NAME,
- N_("@E has illegal characters in its name.\n"),
- PROMPT_FIX, 0 },
-
- /* Missing '.' in directory inode */
- { PR_2_MISSING_DOT,
- N_("Missing '.' in @d @i %i.\n"),
- PROMPT_FIX, 0 },
-
- /* Missing '..' in directory inode */
- { PR_2_MISSING_DOT_DOT,
- N_("Missing '..' in @d @i %i.\n"),
- PROMPT_FIX, 0 },
-
- /* First entry in directory inode doesn't contain '.' */
- { PR_2_1ST_NOT_DOT,
- N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
- PROMPT_FIX, 0 },
-
- /* Second entry in directory inode doesn't contain '..' */
- { PR_2_2ND_NOT_DOT_DOT,
- N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
- PROMPT_FIX, 0 },
-
- /* i_faddr should be zero */
- { PR_2_FADDR_ZERO,
- N_("i_faddr @F %IF, @s zero.\n"),
- PROMPT_CLEAR, 0 },
-
- /* i_file_acl should be zero */
- { PR_2_FILE_ACL_ZERO,
- N_("i_file_acl @F %If, @s zero.\n"),
- PROMPT_CLEAR, 0 },
-
- /* i_dir_acl should be zero */
- { PR_2_DIR_ACL_ZERO,
- N_("i_dir_acl @F %Id, @s zero.\n"),
- PROMPT_CLEAR, 0 },
-
- /* i_frag should be zero */
- { PR_2_FRAG_ZERO,
- N_("i_frag @F %N, @s zero.\n"),
- PROMPT_CLEAR, 0 },
-
- /* i_fsize should be zero */
- { PR_2_FSIZE_ZERO,
- N_("i_fsize @F %N, @s zero.\n"),
- PROMPT_CLEAR, 0 },
-
- /* inode has bad mode */
- { PR_2_BAD_MODE,
- N_("@i %i (%Q) has @n mode (%Im).\n"),
- PROMPT_CLEAR, 0 },
-
- /* directory corrupted */
- { PR_2_DIR_CORRUPTED,
- N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
- PROMPT_SALVAGE, 0 },
-
- /* filename too long */
- { PR_2_FILENAME_LONG,
- N_("@d @i %i, @b %B, offset %N: filename too long\n"),
- PROMPT_TRUNCATE, 0 },
-
- /* Directory inode has a missing block (hole) */
- { PR_2_DIRECTORY_HOLE,
- N_("@d @i %i has an unallocated @b #%B. "),
- PROMPT_ALLOCATE, 0 },
-
- /* '.' is not NULL terminated */
- { PR_2_DOT_NULL_TERM,
- N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
- PROMPT_FIX, 0 },
-
- /* '..' is not NULL terminated */
- { PR_2_DOT_DOT_NULL_TERM,
- N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
- PROMPT_FIX, 0 },
-
- /* Illegal character device inode */
- { PR_2_BAD_CHAR_DEV,
- N_("@i %i (%Q) is an @I character @v.\n"),
- PROMPT_CLEAR, 0 },
-
- /* Illegal block device inode */
- { PR_2_BAD_BLOCK_DEV,
- N_("@i %i (%Q) is an @I @b @v.\n"),
- PROMPT_CLEAR, 0 },
-
- /* Duplicate '.' entry */
- { PR_2_DUP_DOT,
- N_("@E is duplicate '.' @e.\n"),
- PROMPT_FIX, 0 },
-
- /* Duplicate '..' entry */
- { PR_2_DUP_DOT_DOT,
- N_("@E is duplicate '..' @e.\n"),
- PROMPT_FIX, 0 },
-
- /* Internal error: couldn't find dir_info */
- { PR_2_NO_DIRINFO,
- N_("Internal error: cannot find dir_info for %i.\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Final rec_len is wrong */
- { PR_2_FINAL_RECLEN,
- N_("@E has rec_len of %Dr, @s %N.\n"),
- PROMPT_FIX, 0 },
-
- /* Error allocating icount structure */
- { PR_2_ALLOCATE_ICOUNT,
- N_("@A icount structure: %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error iterating over directory blocks */
- { PR_2_DBLIST_ITERATE,
- N_("Error iterating over @d @bs: %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error reading directory block */
- { PR_2_READ_DIRBLOCK,
- N_("Error reading @d @b %b (@i %i): %m\n"),
- PROMPT_CONTINUE, 0 },
-
- /* Error writing directory block */
- { PR_2_WRITE_DIRBLOCK,
- N_("Error writing @d @b %b (@i %i): %m\n"),
- PROMPT_CONTINUE, 0 },
-
- /* Error allocating new directory block */
- { PR_2_ALLOC_DIRBOCK,
- N_("@A new @d @b for @i %i (%s): %m\n"),
- PROMPT_NONE, 0 },
-
- /* Error deallocating inode */
- { PR_2_DEALLOC_INODE,
- N_("Error deallocating @i %i: %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Directory entry for '.' is big. Split? */
- { PR_2_SPLIT_DOT,
- N_("@d @e for '.' is big. "),
- PROMPT_SPLIT, PR_NO_OK },
-
- /* Illegal FIFO inode */
- { PR_2_BAD_FIFO,
- N_("@i %i (%Q) is an @I FIFO.\n"),
- PROMPT_CLEAR, 0 },
-
- /* Illegal socket inode */
- { PR_2_BAD_SOCKET,
- N_("@i %i (%Q) is an @I socket.\n"),
- PROMPT_CLEAR, 0 },
-
- /* Directory filetype not set */
- { PR_2_SET_FILETYPE,
- N_("Setting filetype for @E to %N.\n"),
- PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
-
- /* Directory filetype incorrect */
- { PR_2_BAD_FILETYPE,
- N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
- PROMPT_FIX, 0 },
-
- /* Directory filetype set on filesystem */
- { PR_2_CLEAR_FILETYPE,
- N_("@E has filetype set.\n"),
- PROMPT_CLEAR, PR_PREEN_OK },
-
- /* Directory filename is null */
- { PR_2_NULL_NAME,
- N_("@E has a @z name.\n"),
- PROMPT_CLEAR, 0 },
-
- /* Invalid symlink */
- { PR_2_INVALID_SYMLINK,
- N_("Symlink %Q (@i #%i) is @n.\n"),
- PROMPT_CLEAR, 0 },
-
- /* i_file_acl (extended attribute block) is bad */
- { PR_2_FILE_ACL_BAD,
- N_("@a @b @F @n (%If).\n"),
- PROMPT_CLEAR, 0 },
-
- /* Filesystem contains large files, but has no such flag in sb */
- { PR_2_FEATURE_LARGE_FILES,
- N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
- PROMPT_FIX, 0 },
-
- /* Node in HTREE directory not referenced */
- { PR_2_HTREE_NOTREF,
- N_("@p @h %d: node (%B) not referenced\n"),
- PROMPT_NONE, 0 },
-
- /* Node in HTREE directory referenced twice */
- { PR_2_HTREE_DUPREF,
- N_("@p @h %d: node (%B) referenced twice\n"),
- PROMPT_NONE, 0 },
-
- /* Node in HTREE directory has bad min hash */
- { PR_2_HTREE_MIN_HASH,
- N_("@p @h %d: node (%B) has bad min hash\n"),
- PROMPT_NONE, 0 },
-
- /* Node in HTREE directory has bad max hash */
- { PR_2_HTREE_MAX_HASH,
- N_("@p @h %d: node (%B) has bad max hash\n"),
- PROMPT_NONE, 0 },
-
- /* Clear invalid HTREE directory */
- { PR_2_HTREE_CLEAR,
- N_("@n @h %d (%q). "), PROMPT_CLEAR, 0 },
-
- /* Bad block in htree interior node */
- { PR_2_HTREE_BADBLK,
- N_("@p @h %d (%q): bad @b number %b.\n"),
- PROMPT_CLEAR_HTREE, 0 },
-
- /* Error adjusting EA refcount */
- { PR_2_ADJ_EA_REFCOUNT,
- N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Invalid HTREE root node */
- { PR_2_HTREE_BAD_ROOT,
- N_("@p @h %d: root node is @n\n"),
- PROMPT_CLEAR_HTREE, PR_PREEN_OK },
-
- /* Invalid HTREE limit */
- { PR_2_HTREE_BAD_LIMIT,
- N_("@p @h %d: node (%B) has @n limit (%N)\n"),
- PROMPT_CLEAR_HTREE, PR_PREEN_OK },
-
- /* Invalid HTREE count */
- { PR_2_HTREE_BAD_COUNT,
- N_("@p @h %d: node (%B) has @n count (%N)\n"),
- PROMPT_CLEAR_HTREE, PR_PREEN_OK },
-
- /* HTREE interior node has out-of-order hashes in table */
- { PR_2_HTREE_HASH_ORDER,
- N_("@p @h %d: node (%B) has an unordered hash table\n"),
- PROMPT_CLEAR_HTREE, PR_PREEN_OK },
-
- /* Node in HTREE directory has invalid depth */
- { PR_2_HTREE_BAD_DEPTH,
- N_("@p @h %d: node (%B) has @n depth\n"),
- PROMPT_NONE, 0 },
-
- /* Duplicate directory entry found */
- { PR_2_DUPLICATE_DIRENT,
- N_("Duplicate @E found. "),
- PROMPT_CLEAR, 0 },
-
- /* Non-unique filename found */
- { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
- N_("@E has a non-unique filename.\nRename to %s"),
- PROMPT_NULL, 0 },
-
- /* Duplicate directory entry found */
- { PR_2_REPORT_DUP_DIRENT,
- N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
- PROMPT_NONE, 0 },
-
- /* Pass 3 errors */
-
- /* Pass 3: Checking directory connectivity */
- { PR_3_PASS_HEADER,
- N_("Pass 3: Checking @d connectivity\n"),
- PROMPT_NONE, 0 },
-
- /* Root inode not allocated */
- { PR_3_NO_ROOT_INODE,
- N_("@r not allocated. "),
- PROMPT_ALLOCATE, 0 },
-
- /* No room in lost+found */
- { PR_3_EXPAND_LF_DIR,
- N_("No room in @l @d. "),
- PROMPT_EXPAND, 0 },
-
- /* Unconnected directory inode */
- { PR_3_UNCONNECTED_DIR,
- N_("Unconnected @d @i %i (%p)\n"),
- PROMPT_CONNECT, 0 },
-
- /* /lost+found not found */
- { PR_3_NO_LF_DIR,
- N_("/@l not found. "),
- PROMPT_CREATE, PR_PREEN_OK },
-
- /* .. entry is incorrect */
- { PR_3_BAD_DOT_DOT,
- N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
- PROMPT_FIX, 0 },
-
- /* Bad or non-existent /lost+found. Cannot reconnect */
- { PR_3_NO_LPF,
- N_("Bad or non-existent /@l. Cannot reconnect.\n"),
- PROMPT_NONE, 0 },
-
- /* Could not expand /lost+found */
- { PR_3_CANT_EXPAND_LPF,
- N_("Could not expand /@l: %m\n"),
- PROMPT_NONE, 0 },
-
- /* Could not reconnect inode */
- { PR_3_CANT_RECONNECT,
- N_("Could not reconnect %i: %m\n"),
- PROMPT_NONE, 0 },
-
- /* Error while trying to find /lost+found */
- { PR_3_ERR_FIND_LPF,
- N_("Error while trying to find /@l: %m\n"),
- PROMPT_NONE, 0 },
-
- /* Error in ext2fs_new_block while creating /lost+found */
- { PR_3_ERR_LPF_NEW_BLOCK,
- N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
- PROMPT_NONE, 0 },
-
- /* Error in ext2fs_new_inode while creating /lost+found */
- { PR_3_ERR_LPF_NEW_INODE,
- N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
- PROMPT_NONE, 0 },
-
- /* Error in ext2fs_new_dir_block while creating /lost+found */
- { PR_3_ERR_LPF_NEW_DIR_BLOCK,
- N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
- PROMPT_NONE, 0 },
-
- /* Error while writing directory block for /lost+found */
- { PR_3_ERR_LPF_WRITE_BLOCK,
- N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
- PROMPT_NONE, 0 },
-
- /* Error while adjusting inode count */
- { PR_3_ADJUST_INODE,
- N_("Error while adjusting @i count on @i %i\n"),
- PROMPT_NONE, 0 },
-
- /* Couldn't fix parent directory -- error */
- { PR_3_FIX_PARENT_ERR,
- N_("Couldn't fix parent of @i %i: %m\n\n"),
- PROMPT_NONE, 0 },
-
- /* Couldn't fix parent directory -- couldn't find it */
- { PR_3_FIX_PARENT_NOFIND,
- N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
- PROMPT_NONE, 0 },
-
- /* Error allocating inode bitmap */
- { PR_3_ALLOCATE_IBITMAP_ERROR,
- N_("@A @i @B (%N): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error creating root directory */
- { PR_3_CREATE_ROOT_ERROR,
- N_("Error creating root @d (%s): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error creating lost and found directory */
- { PR_3_CREATE_LPF_ERROR,
- N_("Error creating /@l @d (%s): %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Root inode is not directory; aborting */
- { PR_3_ROOT_NOT_DIR_ABORT,
- N_("@r is not a @d; aborting.\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Cannot proceed without a root inode. */
- { PR_3_NO_ROOT_INODE_ABORT,
- N_("can't proceed without a @r.\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Internal error: couldn't find dir_info */
- { PR_3_NO_DIRINFO,
- N_("Internal error: cannot find dir_info for %i.\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Lost+found not a directory */
- { PR_3_LPF_NOTDIR,
- N_("/@l is not a @d (ino=%i)\n"),
- PROMPT_UNLINK, 0 },
-
- /* Pass 3A Directory Optimization */
-
- /* Pass 3A: Optimizing directories */
- { PR_3A_PASS_HEADER,
- N_("Pass 3A: Optimizing directories\n"),
- PROMPT_NONE, PR_PREEN_NOMSG },
-
- /* Error iterating over directories */
- { PR_3A_OPTIMIZE_ITER,
- N_("Failed to create dirs_to_hash iterator: %m"),
- PROMPT_NONE, 0 },
-
- /* Error rehash directory */
- { PR_3A_OPTIMIZE_DIR_ERR,
- N_("Failed to optimize directory %q (%d): %m"),
- PROMPT_NONE, 0 },
-
- /* Rehashing dir header */
- { PR_3A_OPTIMIZE_DIR_HEADER,
- N_("Optimizing directories: "),
- PROMPT_NONE, PR_MSG_ONLY },
-
- /* Rehashing directory %d */
- { PR_3A_OPTIMIZE_DIR,
- " %d",
- PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
-
- /* Rehashing dir end */
- { PR_3A_OPTIMIZE_DIR_END,
- "\n",
- PROMPT_NONE, PR_PREEN_NOHDR },
-
- /* Pass 4 errors */
-
- /* Pass 4: Checking reference counts */
- { PR_4_PASS_HEADER,
- N_("Pass 4: Checking reference counts\n"),
- PROMPT_NONE, 0 },
-
- /* Unattached zero-length inode */
- { PR_4_ZERO_LEN_INODE,
- N_("@u @z @i %i. "),
- PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
-
- /* Unattached inode */
- { PR_4_UNATTACHED_INODE,
- N_("@u @i %i\n"),
- PROMPT_CONNECT, 0 },
-
- /* Inode ref count wrong */
- { PR_4_BAD_REF_COUNT,
- N_("@i %i ref count is %Il, @s %N. "),
- PROMPT_FIX, PR_PREEN_OK },
-
- { PR_4_INCONSISTENT_COUNT,
- N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
- "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
- "@i_link_info[%i] is %N, @i.i_links_count is %Il. "
- "They @s the same!\n"),
- PROMPT_NONE, 0 },
-
- /* Pass 5 errors */
-
- /* Pass 5: Checking group summary information */
- { PR_5_PASS_HEADER,
- N_("Pass 5: Checking @g summary information\n"),
- PROMPT_NONE, 0 },
-
- /* Padding at end of inode bitmap is not set. */
- { PR_5_INODE_BMAP_PADDING,
- N_("Padding at end of @i @B is not set. "),
- PROMPT_FIX, PR_PREEN_OK },
-
- /* Padding at end of block bitmap is not set. */
- { PR_5_BLOCK_BMAP_PADDING,
- N_("Padding at end of @b @B is not set. "),
- PROMPT_FIX, PR_PREEN_OK },
-
- /* Block bitmap differences header */
- { PR_5_BLOCK_BITMAP_HEADER,
- N_("@b @B differences: "),
- PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
-
- /* Block not used, but marked in bitmap */
- { PR_5_BLOCK_UNUSED,
- " -%b",
- PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Block used, but not marked used in bitmap */
- { PR_5_BLOCK_USED,
- " +%b",
- PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Block bitmap differences end */
- { PR_5_BLOCK_BITMAP_END,
- "\n",
- PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Inode bitmap differences header */
- { PR_5_INODE_BITMAP_HEADER,
- N_("@i @B differences: "),
- PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Inode not used, but marked in bitmap */
- { PR_5_INODE_UNUSED,
- " -%i",
- PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Inode used, but not marked used in bitmap */
- { PR_5_INODE_USED,
- " +%i",
- PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Inode bitmap differences end */
- { PR_5_INODE_BITMAP_END,
- "\n",
- PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Free inodes count for group wrong */
- { PR_5_FREE_INODE_COUNT_GROUP,
- N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
- PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Directories count for group wrong */
- { PR_5_FREE_DIR_COUNT_GROUP,
- N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
- PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Free inodes count wrong */
- { PR_5_FREE_INODE_COUNT,
- N_("Free @is count wrong (%i, counted=%j).\n"),
- PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Free blocks count for group wrong */
- { PR_5_FREE_BLOCK_COUNT_GROUP,
- N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
- PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Free blocks count wrong */
- { PR_5_FREE_BLOCK_COUNT,
- N_("Free @bs count wrong (%b, counted=%c).\n"),
- PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Programming error: bitmap endpoints don't match */
- { PR_5_BMAP_ENDPOINTS,
- N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
- "match calculated @B endpoints (%i, %j)\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Internal error: fudging end of bitmap */
- { PR_5_FUDGE_BITMAP_ERROR,
- N_("Internal error: fudging end of bitmap (%N)\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error copying in replacement inode bitmap */
- { PR_5_COPY_IBITMAP_ERROR,
- N_("Error copying in replacement @i @B: %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Error copying in replacement block bitmap */
- { PR_5_COPY_BBITMAP_ERROR,
- N_("Error copying in replacement @b @B: %m\n"),
- PROMPT_NONE, PR_FATAL },
-
- /* Block range not used, but marked in bitmap */
- { PR_5_BLOCK_RANGE_UNUSED,
- " -(%b--%c)",
- PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Block range used, but not marked used in bitmap */
- { PR_5_BLOCK_RANGE_USED,
- " +(%b--%c)",
- PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Inode range not used, but marked in bitmap */
- { PR_5_INODE_RANGE_UNUSED,
- " -(%i--%j)",
- PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
-
- /* Inode range used, but not marked used in bitmap */
- { PR_5_INODE_RANGE_USED,
- " +(%i--%j)",
- PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
-
- { 0 }
-};
-
-/*
- * This is the latch flags register. It allows several problems to be
- * "latched" together. This means that the user has to answer but one
- * question for the set of problems, and all of the associated
- * problems will be either fixed or not fixed.
- */
-static struct latch_descr pr_latch_info[] = {
- { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
- { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
- { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
- { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
- { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
- { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
- { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
- { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
- { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
- { -1, 0, 0 },
-};
-
-static const struct e2fsck_problem *find_problem(problem_t code)
-{
- int i;
-
- for (i=0; problem_table[i].e2p_code; i++) {
- if (problem_table[i].e2p_code == code)
- return &problem_table[i];
- }
- return 0;
-}
-
-static struct latch_descr *find_latch(int code)
-{
- int i;
-
- for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
- if (pr_latch_info[i].latch_code == code)
- return &pr_latch_info[i];
- }
- return 0;
-}
-
-int end_problem_latch(e2fsck_t ctx, int mask)
-{
- struct latch_descr *ldesc;
- struct problem_context pctx;
- int answer = -1;
-
- ldesc = find_latch(mask);
- if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
- clear_problem_context(&pctx);
- answer = fix_problem(ctx, ldesc->end_message, &pctx);
- }
- ldesc->flags &= ~(PRL_VARIABLE);
- return answer;
-}
-
-int set_latch_flags(int mask, int setflags, int clearflags)
-{
- struct latch_descr *ldesc;
-
- ldesc = find_latch(mask);
- if (!ldesc)
- return -1;
- ldesc->flags |= setflags;
- ldesc->flags &= ~clearflags;
- return 0;
-}
-
-void clear_problem_context(struct problem_context *ctx)
-{
- memset(ctx, 0, sizeof(struct problem_context));
- ctx->blkcount = -1;
- ctx->group = -1;
-}
-
-int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
-{
- ext2_filsys fs = ctx->fs;
- const struct e2fsck_problem *ptr;
- struct latch_descr *ldesc = NULL;
- const char *message;
- int def_yn, answer, ans;
- int print_answer = 0;
- int suppress = 0;
-
- ptr = find_problem(code);
- if (!ptr) {
- printf(_("Unhandled error code (0x%x)!\n"), code);
- return 0;
- }
- def_yn = 1;
- if ((ptr->flags & PR_NO_DEFAULT) ||
- ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
- (ctx->options & E2F_OPT_NO))
- def_yn= 0;
-
- /*
- * Do special latch processing. This is where we ask the
- * latch question, if it exists
- */
- if (ptr->flags & PR_LATCH_MASK) {
- ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
- if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
- ans = fix_problem(ctx, ldesc->question, pctx);
- if (ans == 1)
- ldesc->flags |= PRL_YES;
- if (ans == 0)
- ldesc->flags |= PRL_NO;
- ldesc->flags |= PRL_LATCHED;
- }
- if (ldesc->flags & PRL_SUPPRESS)
- suppress++;
- }
- if ((ptr->flags & PR_PREEN_NOMSG) &&
- (ctx->options & E2F_OPT_PREEN))
- suppress++;
- if ((ptr->flags & PR_NO_NOMSG) &&
- (ctx->options & E2F_OPT_NO))
- suppress++;
- if (!suppress) {
- message = ptr->e2p_description;
- if ((ctx->options & E2F_OPT_PREEN) &&
- !(ptr->flags & PR_PREEN_NOHDR)) {
- printf("%s: ", ctx->device_name ?
- ctx->device_name : ctx->filesystem_name);
- }
- if (*message)
- print_e2fsck_message(ctx, _(message), pctx, 1);
- }
- if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
- preenhalt(ctx);
-
- if (ptr->flags & PR_FATAL)
- bb_error_msg_and_die(0);
-
- if (ptr->prompt == PROMPT_NONE) {
- if (ptr->flags & PR_NOCOLLATE)
- answer = -1;
- else
- answer = def_yn;
- } else {
- if (ctx->options & E2F_OPT_PREEN) {
- answer = def_yn;
- if (!(ptr->flags & PR_PREEN_NOMSG))
- print_answer = 1;
- } else if ((ptr->flags & PR_LATCH_MASK) &&
- (ldesc->flags & (PRL_YES | PRL_NO))) {
- if (!suppress)
- print_answer = 1;
- if (ldesc->flags & PRL_YES)
- answer = 1;
- else
- answer = 0;
- } else
- answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
- if (!answer && !(ptr->flags & PR_NO_OK))
- ext2fs_unmark_valid(fs);
-
- if (print_answer)
- printf("%s.\n", answer ?
- _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
- }
-
- if ((ptr->prompt == PROMPT_ABORT) && answer)
- bb_error_msg_and_die(0);
-
- if (ptr->flags & PR_AFTER_CODE)
- answer = fix_problem(ctx, ptr->second_code, pctx);
-
- return answer;
-}
-
-/*
- * linux/fs/recovery.c
- *
- * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
- */
-
-/*
- * Maintain information about the progress of the recovery job, so that
- * the different passes can carry information between them.
- */
-struct recovery_info
-{
- tid_t start_transaction;
- tid_t end_transaction;
-
- int nr_replays;
- int nr_revokes;
- int nr_revoke_hits;
-};
-
-enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
-static int do_one_pass(journal_t *journal,
- struct recovery_info *info, enum passtype pass);
-static int scan_revoke_records(journal_t *, struct buffer_head *,
- tid_t, struct recovery_info *);
-
-/*
- * Read a block from the journal
- */
-
-static int jread(struct buffer_head **bhp, journal_t *journal,
- unsigned int offset)
-{
- int err;
- unsigned long blocknr;
- struct buffer_head *bh;
-
- *bhp = NULL;
-
- err = journal_bmap(journal, offset, &blocknr);
-
- if (err) {
- printf("JBD: bad block at offset %u\n", offset);
- return err;
- }
-
- bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
- if (!bh)
- return -ENOMEM;
-
- if (!buffer_uptodate(bh)) {
- /* If this is a brand new buffer, start readahead.
- Otherwise, we assume we are already reading it. */
- if (!buffer_req(bh))
- do_readahead(journal, offset);
- wait_on_buffer(bh);
- }
-
- if (!buffer_uptodate(bh)) {
- printf("JBD: Failed to read block at offset %u\n", offset);
- brelse(bh);
- return -EIO;
- }
-
- *bhp = bh;
- return 0;
-}
-
-
-/*
- * Count the number of in-use tags in a journal descriptor block.
- */
-
-static int count_tags(struct buffer_head *bh, int size)
-{
- char * tagp;
- journal_block_tag_t * tag;
- int nr = 0;
-
- tagp = &bh->b_data[sizeof(journal_header_t)];
-
- while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
- tag = (journal_block_tag_t *) tagp;
-
- nr++;
- tagp += sizeof(journal_block_tag_t);
- if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
- tagp += 16;
-
- if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
- break;
- }
-
- return nr;
-}
-
-
-/* Make sure we wrap around the log correctly! */
-#define wrap(journal, var) \
-do { \
- if (var >= (journal)->j_last) \
- var -= ((journal)->j_last - (journal)->j_first); \
-} while (0)
-
-/**
- * int journal_recover(journal_t *journal) - recovers a on-disk journal
- * @journal: the journal to recover
- *
- * The primary function for recovering the log contents when mounting a
- * journaled device.
- *
- * Recovery is done in three passes. In the first pass, we look for the
- * end of the log. In the second, we assemble the list of revoke
- * blocks. In the third and final pass, we replay any un-revoked blocks
- * in the log.
- */
-int journal_recover(journal_t *journal)
-{
- int err;
- journal_superblock_t * sb;
-
- struct recovery_info info;
-
- memset(&info, 0, sizeof(info));
- sb = journal->j_superblock;
-
- /*
- * The journal superblock's s_start field (the current log head)
- * is always zero if, and only if, the journal was cleanly
- * unmounted.
- */
-
- if (!sb->s_start) {
- journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
- return 0;
- }
-
- err = do_one_pass(journal, &info, PASS_SCAN);
- if (!err)
- err = do_one_pass(journal, &info, PASS_REVOKE);
- if (!err)
- err = do_one_pass(journal, &info, PASS_REPLAY);
-
- /* Restart the log at the next transaction ID, thus invalidating
- * any existing commit records in the log. */
- journal->j_transaction_sequence = ++info.end_transaction;
-
- journal_clear_revoke(journal);
- sync_blockdev(journal->j_fs_dev);
- return err;
-}
-
-static int do_one_pass(journal_t *journal,
- struct recovery_info *info, enum passtype pass)
-{
- unsigned int first_commit_ID, next_commit_ID;
- unsigned long next_log_block;
- int err, success = 0;
- journal_superblock_t * sb;
- journal_header_t * tmp;
- struct buffer_head * bh;
- unsigned int sequence;
- int blocktype;
-
- /* Precompute the maximum metadata descriptors in a descriptor block */
- int MAX_BLOCKS_PER_DESC;
- MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
- / sizeof(journal_block_tag_t));
-
- /*
- * First thing is to establish what we expect to find in the log
- * (in terms of transaction IDs), and where (in terms of log
- * block offsets): query the superblock.
- */
-
- sb = journal->j_superblock;
- next_commit_ID = ntohl(sb->s_sequence);
- next_log_block = ntohl(sb->s_start);
-
- first_commit_ID = next_commit_ID;
- if (pass == PASS_SCAN)
- info->start_transaction = first_commit_ID;
-
- /*
- * Now we walk through the log, transaction by transaction,
- * making sure that each transaction has a commit block in the
- * expected place. Each complete transaction gets replayed back
- * into the main filesystem.
- */
-
- while (1) {
- int flags;
- char * tagp;
- journal_block_tag_t * tag;
- struct buffer_head * obh;
- struct buffer_head * nbh;
-
- /* If we already know where to stop the log traversal,
- * check right now that we haven't gone past the end of
- * the log. */
-
- if (pass != PASS_SCAN)
- if (tid_geq(next_commit_ID, info->end_transaction))
- break;
-
- /* Skip over each chunk of the transaction looking
- * either the next descriptor block or the final commit
- * record. */
-
- err = jread(&bh, journal, next_log_block);
- if (err)
- goto failed;
-
- next_log_block++;
- wrap(journal, next_log_block);
-
- /* What kind of buffer is it?
- *
- * If it is a descriptor block, check that it has the
- * expected sequence number. Otherwise, we're all done
- * here. */
-
- tmp = (journal_header_t *)bh->b_data;
-
- if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
- brelse(bh);
- break;
- }
-
- blocktype = ntohl(tmp->h_blocktype);
- sequence = ntohl(tmp->h_sequence);
-
- if (sequence != next_commit_ID) {
- brelse(bh);
- break;
- }
-
- /* OK, we have a valid descriptor block which matches
- * all of the sequence number checks. What are we going
- * to do with it? That depends on the pass... */
-
- switch (blocktype) {
- case JFS_DESCRIPTOR_BLOCK:
- /* If it is a valid descriptor block, replay it
- * in pass REPLAY; otherwise, just skip over the
- * blocks it describes. */
- if (pass != PASS_REPLAY) {
- next_log_block +=
- count_tags(bh, journal->j_blocksize);
- wrap(journal, next_log_block);
- brelse(bh);
- continue;
- }
-
- /* A descriptor block: we can now write all of
- * the data blocks. Yay, useful work is finally
- * getting done here! */
-
- tagp = &bh->b_data[sizeof(journal_header_t)];
- while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
- <= journal->j_blocksize) {
- unsigned long io_block;
-
- tag = (journal_block_tag_t *) tagp;
- flags = ntohl(tag->t_flags);
-
- io_block = next_log_block++;
- wrap(journal, next_log_block);
- err = jread(&obh, journal, io_block);
- if (err) {
- /* Recover what we can, but
- * report failure at the end. */
- success = err;
- printf("JBD: IO error %d recovering "
- "block %ld in log\n",
- err, io_block);
- } else {
- unsigned long blocknr;
-
- blocknr = ntohl(tag->t_blocknr);
-
- /* If the block has been
- * revoked, then we're all done
- * here. */
- if (journal_test_revoke
- (journal, blocknr,
- next_commit_ID)) {
- brelse(obh);
- ++info->nr_revoke_hits;
- goto skip_write;
- }
-
- /* Find a buffer for the new
- * data being restored */
- nbh = getblk(journal->j_fs_dev,
- blocknr,
- journal->j_blocksize);
- if (nbh == NULL) {
- printf("JBD: Out of memory "
- "during recovery.\n");
- err = -ENOMEM;
- brelse(bh);
- brelse(obh);
- goto failed;
- }
-
- lock_buffer(nbh);
- memcpy(nbh->b_data, obh->b_data,
- journal->j_blocksize);
- if (flags & JFS_FLAG_ESCAPE) {
- *((unsigned int *)bh->b_data) =
- htonl(JFS_MAGIC_NUMBER);
- }
-
- mark_buffer_uptodate(nbh, 1);
- mark_buffer_dirty(nbh);
- ++info->nr_replays;
- /* ll_rw_block(WRITE, 1, &nbh); */
- unlock_buffer(nbh);
- brelse(obh);
- brelse(nbh);
- }
-
- skip_write:
- tagp += sizeof(journal_block_tag_t);
- if (!(flags & JFS_FLAG_SAME_UUID))
- tagp += 16;
-
- if (flags & JFS_FLAG_LAST_TAG)
- break;
- }
-
- brelse(bh);
- continue;
-
- case JFS_COMMIT_BLOCK:
- /* Found an expected commit block: not much to
- * do other than move on to the next sequence
- * number. */
- brelse(bh);
- next_commit_ID++;
- continue;
-
- case JFS_REVOKE_BLOCK:
- /* If we aren't in the REVOKE pass, then we can
- * just skip over this block. */
- if (pass != PASS_REVOKE) {
- brelse(bh);
- continue;
- }
-
- err = scan_revoke_records(journal, bh,
- next_commit_ID, info);
- brelse(bh);
- if (err)
- goto failed;
- continue;
-
- default:
- goto done;
- }
- }
-
- done:
- /*
- * We broke out of the log scan loop: either we came to the
- * known end of the log or we found an unexpected block in the
- * log. If the latter happened, then we know that the "current"
- * transaction marks the end of the valid log.
- */
-
- if (pass == PASS_SCAN)
- info->end_transaction = next_commit_ID;
- else {
- /* It's really bad news if different passes end up at
- * different places (but possible due to IO errors). */
- if (info->end_transaction != next_commit_ID) {
- printf("JBD: recovery pass %d ended at "
- "transaction %u, expected %u\n",
- pass, next_commit_ID, info->end_transaction);
- if (!success)
- success = -EIO;
- }
- }
-
- return success;
-
- failed:
- return err;
-}
-
-
-/* Scan a revoke record, marking all blocks mentioned as revoked. */
-
-static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
- tid_t sequence, struct recovery_info *info)
-{
- journal_revoke_header_t *header;
- int offset, max;
-
- header = (journal_revoke_header_t *) bh->b_data;
- offset = sizeof(journal_revoke_header_t);
- max = ntohl(header->r_count);
-
- while (offset < max) {
- unsigned long blocknr;
- int err;
-
- blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
- offset += 4;
- err = journal_set_revoke(journal, blocknr, sequence);
- if (err)
- return err;
- ++info->nr_revokes;
- }
- return 0;
-}
-
-
-/*
- * rehash.c --- rebuild hash tree directories
- *
- * This algorithm is designed for simplicity of implementation and to
- * pack the directory as much as possible. It however requires twice
- * as much memory as the size of the directory. The maximum size
- * directory supported using a 4k blocksize is roughly a gigabyte, and
- * so there may very well be problems with machines that don't have
- * virtual memory, and obscenely large directories.
- *
- * An alternate algorithm which is much more disk intensive could be
- * written, and probably will need to be written in the future. The
- * design goals of such an algorithm are: (a) use (roughly) constant
- * amounts of memory, no matter how large the directory, (b) the
- * directory must be safe at all times, even if e2fsck is interrupted
- * in the middle, (c) we must use minimal amounts of extra disk
- * blocks. This pretty much requires an incremental approach, where
- * we are reading from one part of the directory, and inserting into
- * the front half. So the algorithm will have to keep track of a
- * moving block boundary between the new tree and the old tree, and
- * files will need to be moved from the old directory and inserted
- * into the new tree. If the new directory requires space which isn't
- * yet available, blocks from the beginning part of the old directory
- * may need to be moved to the end of the directory to make room for
- * the new tree:
- *
- * --------------------------------------------------------
- * | new tree | | old tree |
- * --------------------------------------------------------
- * ^ ptr ^ptr
- * tail new head old
- *
- * This is going to be a pain in the tuckus to implement, and will
- * require a lot more disk accesses. So I'm going to skip it for now;
- * it's only really going to be an issue for really, really big
- * filesystems (when we reach the level of tens of millions of files
- * in a single directory). It will probably be easier to simply
- * require that e2fsck use VM first.
- */
-
-struct fill_dir_struct {
- char *buf;
- struct ext2_inode *inode;
- int err;
- e2fsck_t ctx;
- struct hash_entry *harray;
- int max_array, num_array;
- int dir_size;
- int compress;
- ino_t parent;
-};
-
-struct hash_entry {
- ext2_dirhash_t hash;
- ext2_dirhash_t minor_hash;
- struct ext2_dir_entry *dir;
-};
-
-struct out_dir {
- int num;
- int max;
- char *buf;
- ext2_dirhash_t *hashes;
-};
-
-static int fill_dir_block(ext2_filsys fs,
- blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block FSCK_ATTR((unused)),
- int ref_offset FSCK_ATTR((unused)),
- void *priv_data)
-{
- struct fill_dir_struct *fd = (struct fill_dir_struct *) priv_data;
- struct hash_entry *new_array, *ent;
- struct ext2_dir_entry *dirent;
- char *dir;
- unsigned int offset, dir_offset;
-
- if (blockcnt < 0)
- return 0;
-
- offset = blockcnt * fs->blocksize;
- if (offset + fs->blocksize > fd->inode->i_size) {
- fd->err = EXT2_ET_DIR_CORRUPTED;
- return BLOCK_ABORT;
- }
- dir = (fd->buf+offset);
- if (HOLE_BLKADDR(*block_nr)) {
- memset(dir, 0, fs->blocksize);
- dirent = (struct ext2_dir_entry *) dir;
- dirent->rec_len = fs->blocksize;
- } else {
- fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
- if (fd->err)
- return BLOCK_ABORT;
- }
- /* While the directory block is "hot", index it. */
- dir_offset = 0;
- while (dir_offset < fs->blocksize) {
- dirent = (struct ext2_dir_entry *) (dir + dir_offset);
- if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
- (dirent->rec_len < 8) ||
- ((dirent->rec_len % 4) != 0) ||
- (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
- fd->err = EXT2_ET_DIR_CORRUPTED;
- return BLOCK_ABORT;
- }
- dir_offset += dirent->rec_len;
- if (dirent->inode == 0)
- continue;
- if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
- (dirent->name[0] == '.'))
- continue;
- if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
- (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
- fd->parent = dirent->inode;
- continue;
- }
- if (fd->num_array >= fd->max_array) {
- new_array = xrealloc(fd->harray,
- sizeof(struct hash_entry) * (fd->max_array+500));
- fd->harray = new_array;
- fd->max_array += 500;
- }
- ent = fd->harray + fd->num_array++;
- ent->dir = dirent;
- fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
- if (fd->compress)
- ent->hash = ent->minor_hash = 0;
- else {
- fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
- dirent->name,
- dirent->name_len & 0xFF,
- fs->super->s_hash_seed,
- &ent->hash, &ent->minor_hash);
- if (fd->err)
- return BLOCK_ABORT;
- }
- }
-
- return 0;
-}
-
-/* Used for sorting the hash entry */
-static int name_cmp(const void *a, const void *b)
-{
- const struct hash_entry *he_a = (const struct hash_entry *) a;
- const struct hash_entry *he_b = (const struct hash_entry *) b;
- int ret;
- int min_len;
-
- min_len = he_a->dir->name_len;
- if (min_len > he_b->dir->name_len)
- min_len = he_b->dir->name_len;
-
- ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
- if (ret == 0) {
- if (he_a->dir->name_len > he_b->dir->name_len)
- ret = 1;
- else if (he_a->dir->name_len < he_b->dir->name_len)
- ret = -1;
- else
- ret = he_b->dir->inode - he_a->dir->inode;
- }
- return ret;
-}
-
-/* Used for sorting the hash entry */
-static int hash_cmp(const void *a, const void *b)
-{
- const struct hash_entry *he_a = (const struct hash_entry *) a;
- const struct hash_entry *he_b = (const struct hash_entry *) b;
- int ret;
-
- if (he_a->hash > he_b->hash)
- ret = 1;
- else if (he_a->hash < he_b->hash)
- ret = -1;
- else {
- if (he_a->minor_hash > he_b->minor_hash)
- ret = 1;
- else if (he_a->minor_hash < he_b->minor_hash)
- ret = -1;
- else
- ret = name_cmp(a, b);
- }
- return ret;
-}
-
-static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
- int blocks)
-{
- void *new_mem;
-
- if (outdir->max) {
- new_mem = xrealloc(outdir->buf, blocks * fs->blocksize);
- outdir->buf = new_mem;
- new_mem = xrealloc(outdir->hashes,
- blocks * sizeof(ext2_dirhash_t));
- outdir->hashes = new_mem;
- } else {
- outdir->buf = xmalloc(blocks * fs->blocksize);
- outdir->hashes = xmalloc(blocks * sizeof(ext2_dirhash_t));
- outdir->num = 0;
- }
- outdir->max = blocks;
- return 0;
-}
-
-static void free_out_dir(struct out_dir *outdir)
-{
- free(outdir->buf);
- free(outdir->hashes);
- outdir->max = 0;
- outdir->num =0;
-}
-
-static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
- char ** ret)
-{
- errcode_t retval;
-
- if (outdir->num >= outdir->max) {
- retval = alloc_size_dir(fs, outdir, outdir->max + 50);
- if (retval)
- return retval;
- }
- *ret = outdir->buf + (outdir->num++ * fs->blocksize);
- memset(*ret, 0, fs->blocksize);
- return 0;
-}
-
-/*
- * This function is used to make a unique filename. We do this by
- * appending ~0, and then incrementing the number. However, we cannot
- * expand the length of the filename beyond the padding available in
- * the directory entry.
- */
-static void mutate_name(char *str, __u16 *len)
-{
- int i;
- __u16 l = *len & 0xFF, h = *len & 0xff00;
-
- /*
- * First check to see if it looks the name has been mutated
- * already
- */
- for (i = l-1; i > 0; i--) {
- if (!isdigit(str[i]))
- break;
- }
- if ((i == l-1) || (str[i] != '~')) {
- if (((l-1) & 3) < 2)
- l += 2;
- else
- l = (l+3) & ~3;
- str[l-2] = '~';
- str[l-1] = '0';
- *len = l | h;
- return;
- }
- for (i = l-1; i >= 0; i--) {
- if (isdigit(str[i])) {
- if (str[i] == '9')
- str[i] = '0';
- else {
- str[i]++;
- return;
- }
- continue;
- }
- if (i == 1) {
- if (str[0] == 'z')
- str[0] = 'A';
- else if (str[0] == 'Z') {
- str[0] = '~';
- str[1] = '0';
- } else
- str[0]++;
- } else if (i > 0) {
- str[i] = '1';
- str[i-1] = '~';
- } else {
- if (str[0] == '~')
- str[0] = 'a';
- else
- str[0]++;
- }
- break;
- }
-}
-
-static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
- ext2_ino_t ino,
- struct fill_dir_struct *fd)
-{
- struct problem_context pctx;
- struct hash_entry *ent, *prev;
- int i, j;
- int fixed = 0;
- char new_name[256];
- __u16 new_len;
-
- clear_problem_context(&pctx);
- pctx.ino = ino;
-
- for (i=1; i < fd->num_array; i++) {
- ent = fd->harray + i;
- prev = ent - 1;
- if (!ent->dir->inode ||
- ((ent->dir->name_len & 0xFF) !=
- (prev->dir->name_len & 0xFF)) ||
- (strncmp(ent->dir->name, prev->dir->name,
- ent->dir->name_len & 0xFF)))
- continue;
- pctx.dirent = ent->dir;
- if ((ent->dir->inode == prev->dir->inode) &&
- fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
- e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
- ent->dir->inode = 0;
- fixed++;
- continue;
- }
- memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
- new_len = ent->dir->name_len;
- mutate_name(new_name, &new_len);
- for (j=0; j < fd->num_array; j++) {
- if ((i==j) ||
- ((ent->dir->name_len & 0xFF) !=
- (fd->harray[j].dir->name_len & 0xFF)) ||
- (strncmp(new_name, fd->harray[j].dir->name,
- new_len & 0xFF)))
- continue;
- mutate_name(new_name, &new_len);
-
- j = -1;
- }
- new_name[new_len & 0xFF] = 0;
- pctx.str = new_name;
- if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
- memcpy(ent->dir->name, new_name, new_len & 0xFF);
- ent->dir->name_len = new_len;
- ext2fs_dirhash(fs->super->s_def_hash_version,
- ent->dir->name,
- ent->dir->name_len & 0xFF,
- fs->super->s_hash_seed,
- &ent->hash, &ent->minor_hash);
- fixed++;
- }
- }
- return fixed;
-}
-
-
-static errcode_t copy_dir_entries(ext2_filsys fs,
- struct fill_dir_struct *fd,
- struct out_dir *outdir)
-{
- errcode_t retval;
- char *block_start;
- struct hash_entry *ent;
- struct ext2_dir_entry *dirent;
- int i, rec_len, left;
- ext2_dirhash_t prev_hash;
- int offset;
-
- outdir->max = 0;
- retval = alloc_size_dir(fs, outdir,
- (fd->dir_size / fs->blocksize) + 2);
- if (retval)
- return retval;
- outdir->num = fd->compress ? 0 : 1;
- offset = 0;
- outdir->hashes[0] = 0;
- prev_hash = 1;
- if ((retval = get_next_block(fs, outdir, &block_start)))
- return retval;
- dirent = (struct ext2_dir_entry *) block_start;
- left = fs->blocksize;
- for (i=0; i < fd->num_array; i++) {
- ent = fd->harray + i;
- if (ent->dir->inode == 0)
- continue;
- rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
- if (rec_len > left) {
- if (left)
- dirent->rec_len += left;
- if ((retval = get_next_block(fs, outdir,
- &block_start)))
- return retval;
- offset = 0;
- }
- left = fs->blocksize - offset;
- dirent = (struct ext2_dir_entry *) (block_start + offset);
- if (offset == 0) {
- if (ent->hash == prev_hash)
- outdir->hashes[outdir->num-1] = ent->hash | 1;
- else
- outdir->hashes[outdir->num-1] = ent->hash;
- }
- dirent->inode = ent->dir->inode;
- dirent->name_len = ent->dir->name_len;
- dirent->rec_len = rec_len;
- memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
- offset += rec_len;
- left -= rec_len;
- if (left < 12) {
- dirent->rec_len += left;
- offset += left;
- left = 0;
- }
- prev_hash = ent->hash;
- }
- if (left)
- dirent->rec_len += left;
-
- return 0;
-}
-
-
-static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
- ext2_ino_t ino, ext2_ino_t parent)
-{
- struct ext2_dir_entry *dir;
- struct ext2_dx_root_info *root;
- struct ext2_dx_countlimit *limits;
- int filetype = 0;
-
- if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
- filetype = EXT2_FT_DIR << 8;
-
- memset(buf, 0, fs->blocksize);
- dir = (struct ext2_dir_entry *) buf;
- dir->inode = ino;
- dir->name[0] = '.';
- dir->name_len = 1 | filetype;
- dir->rec_len = 12;
- dir = (struct ext2_dir_entry *) (buf + 12);
- dir->inode = parent;
- dir->name[0] = '.';
- dir->name[1] = '.';
- dir->name_len = 2 | filetype;
- dir->rec_len = fs->blocksize - 12;
-
- root = (struct ext2_dx_root_info *) (buf+24);
- root->reserved_zero = 0;
- root->hash_version = fs->super->s_def_hash_version;
- root->info_length = 8;
- root->indirect_levels = 0;
- root->unused_flags = 0;
-
- limits = (struct ext2_dx_countlimit *) (buf+32);
- limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
- limits->count = 0;
-
- return root;
-}
-
-
-static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
-{
- struct ext2_dir_entry *dir;
- struct ext2_dx_countlimit *limits;
-
- memset(buf, 0, fs->blocksize);
- dir = (struct ext2_dir_entry *) buf;
- dir->inode = 0;
- dir->rec_len = fs->blocksize;
-
- limits = (struct ext2_dx_countlimit *) (buf+8);
- limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
- limits->count = 0;
-
- return (struct ext2_dx_entry *) limits;
-}
-
-/*
- * This function takes the leaf nodes which have been written in
- * outdir, and populates the root node and any necessary interior nodes.
- */
-static errcode_t calculate_tree(ext2_filsys fs,
- struct out_dir *outdir,
- ext2_ino_t ino,
- ext2_ino_t parent)
-{
- struct ext2_dx_root_info *root_info;
- struct ext2_dx_entry *root, *dx_ent = NULL;
- struct ext2_dx_countlimit *root_limit, *limit;
- errcode_t retval;
- char * block_start;
- int i, c1, c2, nblks;
- int limit_offset, root_offset;
-
- root_info = set_root_node(fs, outdir->buf, ino, parent);
- root_offset = limit_offset = ((char *) root_info - outdir->buf) +
- root_info->info_length;
- root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
- c1 = root_limit->limit;
- nblks = outdir->num;
-
- /* Write out the pointer blocks */
- if (nblks-1 <= c1) {
- /* Just write out the root block, and we're done */
- root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
- for (i=1; i < nblks; i++) {
- root->block = ext2fs_cpu_to_le32(i);
- if (i != 1)
- root->hash =
- ext2fs_cpu_to_le32(outdir->hashes[i]);
- root++;
- c1--;
- }
- } else {
- c2 = 0;
- limit = 0;
- root_info->indirect_levels = 1;
- for (i=1; i < nblks; i++) {
- if (c1 == 0)
- return ENOSPC;
- if (c2 == 0) {
- if (limit)
- limit->limit = limit->count =
- ext2fs_cpu_to_le16(limit->limit);
- root = (struct ext2_dx_entry *)
- (outdir->buf + root_offset);
- root->block = ext2fs_cpu_to_le32(outdir->num);
- if (i != 1)
- root->hash =
- ext2fs_cpu_to_le32(outdir->hashes[i]);
- if ((retval = get_next_block(fs, outdir,
- &block_start)))
- return retval;
- dx_ent = set_int_node(fs, block_start);
- limit = (struct ext2_dx_countlimit *) dx_ent;
- c2 = limit->limit;
- root_offset += sizeof(struct ext2_dx_entry);
- c1--;
- }
- dx_ent->block = ext2fs_cpu_to_le32(i);
- if (c2 != limit->limit)
- dx_ent->hash =
- ext2fs_cpu_to_le32(outdir->hashes[i]);
- dx_ent++;
- c2--;
- }
- limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
- limit->limit = ext2fs_cpu_to_le16(limit->limit);
- }
- root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
- root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
- root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
-
- return 0;
-}
-
-struct write_dir_struct {
- struct out_dir *outdir;
- errcode_t err;
- e2fsck_t ctx;
- int cleared;
-};
-
-/*
- * Helper function which writes out a directory block.
- */
-static int write_dir_block(ext2_filsys fs,
- blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block FSCK_ATTR((unused)),
- int ref_offset FSCK_ATTR((unused)),
- void *priv_data)
-{
- struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
- blk_t blk;
- char *dir;
-
- if (*block_nr == 0)
- return 0;
- if (blockcnt >= wd->outdir->num) {
- e2fsck_read_bitmaps(wd->ctx);
- blk = *block_nr;
- ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
- ext2fs_block_alloc_stats(fs, blk, -1);
- *block_nr = 0;
- wd->cleared++;
- return BLOCK_CHANGED;
- }
- if (blockcnt < 0)
- return 0;
-
- dir = wd->outdir->buf + (blockcnt * fs->blocksize);
- wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
- if (wd->err)
- return BLOCK_ABORT;
- return 0;
-}
-
-static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
- struct out_dir *outdir,
- ext2_ino_t ino, int compress)
-{
- struct write_dir_struct wd;
- errcode_t retval;
- struct ext2_inode inode;
-
- retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
- if (retval)
- return retval;
-
- wd.outdir = outdir;
- wd.err = 0;
- wd.ctx = ctx;
- wd.cleared = 0;
-
- retval = ext2fs_block_iterate2(fs, ino, 0, 0,
- write_dir_block, &wd);
- if (retval)
- return retval;
- if (wd.err)
- return wd.err;
-
- e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
- if (compress)
- inode.i_flags &= ~EXT2_INDEX_FL;
- else
- inode.i_flags |= EXT2_INDEX_FL;
- inode.i_size = outdir->num * fs->blocksize;
- inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
- e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
-
- return 0;
-}
-
-static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
-{
- ext2_filsys fs = ctx->fs;
- errcode_t retval;
- struct ext2_inode inode;
- char *dir_buf = NULL;
- struct fill_dir_struct fd;
- struct out_dir outdir;
-
- outdir.max = outdir.num = 0;
- outdir.buf = 0;
- outdir.hashes = 0;
- e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
-
- retval = ENOMEM;
- fd.harray = 0;
- dir_buf = xmalloc(inode.i_size);
-
- fd.max_array = inode.i_size / 32;
- fd.num_array = 0;
- fd.harray = xmalloc(fd.max_array * sizeof(struct hash_entry));
-
- fd.ctx = ctx;
- fd.buf = dir_buf;
- fd.inode = &inode;
- fd.err = 0;
- fd.dir_size = 0;
- fd.compress = 0;
- if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
- (inode.i_size / fs->blocksize) < 2)
- fd.compress = 1;
- fd.parent = 0;
-
- /* Read in the entire directory into memory */
- retval = ext2fs_block_iterate2(fs, ino, 0, 0,
- fill_dir_block, &fd);
- if (fd.err) {
- retval = fd.err;
- goto errout;
- }
-
- /* Sort the list */
-resort:
- if (fd.compress)
- qsort(fd.harray+2, fd.num_array-2,
- sizeof(struct hash_entry), name_cmp);
- else
- qsort(fd.harray, fd.num_array,
- sizeof(struct hash_entry), hash_cmp);
-
- /*
- * Look for duplicates
- */
- if (duplicate_search_and_fix(ctx, fs, ino, &fd))
- goto resort;
-
- if (ctx->options & E2F_OPT_NO) {
- retval = 0;
- goto errout;
- }
-
- /*
- * Copy the directory entries. In a htree directory these
- * will become the leaf nodes.
- */
- retval = copy_dir_entries(fs, &fd, &outdir);
- if (retval)
- goto errout;
-
- free(dir_buf); dir_buf = 0;
-
- if (!fd.compress) {
- /* Calculate the interior nodes */
- retval = calculate_tree(fs, &outdir, ino, fd.parent);
- if (retval)
- goto errout;
- }
-
- retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
-
-errout:
- free(dir_buf);
- free(fd.harray);
-
- free_out_dir(&outdir);
- return retval;
-}
-
-void e2fsck_rehash_directories(e2fsck_t ctx)
-{
- struct problem_context pctx;
- struct dir_info *dir;
- ext2_u32_iterate iter;
- ext2_ino_t ino;
- errcode_t retval;
- int i, cur, max, all_dirs, dir_index, first = 1;
-
- all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
-
- if (!ctx->dirs_to_hash && !all_dirs)
- return;
-
- e2fsck_get_lost_and_found(ctx, 0);
-
- clear_problem_context(&pctx);
-
- dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
- cur = 0;
- if (all_dirs) {
- i = 0;
- max = e2fsck_get_num_dirinfo(ctx);
- } else {
- retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
- &iter);
- if (retval) {
- pctx.errcode = retval;
- fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
- return;
- }
- max = ext2fs_u32_list_count(ctx->dirs_to_hash);
- }
- while (1) {
- if (all_dirs) {
- if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
- break;
- ino = dir->ino;
- } else {
- if (!ext2fs_u32_list_iterate(iter, &ino))
- break;
- }
- if (ino == ctx->lost_and_found)
- continue;
- pctx.dir = ino;
- if (first) {
- fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
- first = 0;
- }
- pctx.errcode = e2fsck_rehash_dir(ctx, ino);
- if (pctx.errcode) {
- end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
- fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
- }
- if (ctx->progress && !ctx->progress_fd)
- e2fsck_simple_progress(ctx, "Rebuilding directory",
- 100.0 * (float) (++cur) / (float) max, ino);
- }
- end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
- if (!all_dirs)
- ext2fs_u32_list_iterate_end(iter);
-
- ext2fs_u32_list_free(ctx->dirs_to_hash);
- ctx->dirs_to_hash = 0;
-}
-
-/*
- * linux/fs/revoke.c
- *
- * Journal revoke routines for the generic filesystem journaling code;
- * part of the ext2fs journaling system.
- *
- * Revoke is the mechanism used to prevent old log records for deleted
- * metadata from being replayed on top of newer data using the same
- * blocks. The revoke mechanism is used in two separate places:
- *
- * + Commit: during commit we write the entire list of the current
- * transaction's revoked blocks to the journal
- *
- * + Recovery: during recovery we record the transaction ID of all
- * revoked blocks. If there are multiple revoke records in the log
- * for a single block, only the last one counts, and if there is a log
- * entry for a block beyond the last revoke, then that log entry still
- * gets replayed.
- *
- * We can get interactions between revokes and new log data within a
- * single transaction:
- *
- * Block is revoked and then journaled:
- * The desired end result is the journaling of the new block, so we
- * cancel the revoke before the transaction commits.
- *
- * Block is journaled and then revoked:
- * The revoke must take precedence over the write of the block, so we
- * need either to cancel the journal entry or to write the revoke
- * later in the log than the log block. In this case, we choose the
- * latter: journaling a block cancels any revoke record for that block
- * in the current transaction, so any revoke for that block in the
- * transaction must have happened after the block was journaled and so
- * the revoke must take precedence.
- *
- * Block is revoked and then written as data:
- * The data write is allowed to succeed, but the revoke is _not_
- * cancelled. We still need to prevent old log records from
- * overwriting the new data. We don't even need to clear the revoke
- * bit here.
- *
- * Revoke information on buffers is a tri-state value:
- *
- * RevokeValid clear: no cached revoke status, need to look it up
- * RevokeValid set, Revoked clear:
- * buffer has not been revoked, and cancel_revoke
- * need do nothing.
- * RevokeValid set, Revoked set:
- * buffer has been revoked.
- */
-
-static kmem_cache_t *revoke_record_cache;
-static kmem_cache_t *revoke_table_cache;
-
-/* Each revoke record represents one single revoked block. During
- journal replay, this involves recording the transaction ID of the
- last transaction to revoke this block. */
-
-struct jbd_revoke_record_s
-{
- struct list_head hash;
- tid_t sequence; /* Used for recovery only */
- unsigned long blocknr;
-};
-
-
-/* The revoke table is just a simple hash table of revoke records. */
-struct jbd_revoke_table_s
-{
- /* It is conceivable that we might want a larger hash table
- * for recovery. Must be a power of two. */
- int hash_size;
- int hash_shift;
- struct list_head *hash_table;
-};
-
-
-/* Utility functions to maintain the revoke table */
-
-/* Borrowed from buffer.c: this is a tried and tested block hash function */
-static int hash(journal_t *journal, unsigned long block)
-{
- struct jbd_revoke_table_s *table = journal->j_revoke;
- int hash_shift = table->hash_shift;
-
- return ((block << (hash_shift - 6)) ^
- (block >> 13) ^
- (block << (hash_shift - 12))) & (table->hash_size - 1);
-}
-
-static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
- tid_t seq)
-{
- struct list_head *hash_list;
- struct jbd_revoke_record_s *record;
-
- record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
- if (!record)
- goto oom;
-
- record->sequence = seq;
- record->blocknr = blocknr;
- hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
- list_add(&record->hash, hash_list);
- return 0;
-
-oom:
- return -ENOMEM;
-}
-
-/* Find a revoke record in the journal's hash table. */
-
-static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
- unsigned long blocknr)
-{
- struct list_head *hash_list;
- struct jbd_revoke_record_s *record;
-
- hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
-
- record = (struct jbd_revoke_record_s *) hash_list->next;
- while (&(record->hash) != hash_list) {
- if (record->blocknr == blocknr)
- return record;
- record = (struct jbd_revoke_record_s *) record->hash.next;
- }
- return NULL;
-}
-
-int journal_init_revoke_caches(void)
-{
- revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
- if (revoke_record_cache == 0)
- return -ENOMEM;
-
- revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
- if (revoke_table_cache == 0) {
- do_cache_destroy(revoke_record_cache);
- revoke_record_cache = NULL;
- return -ENOMEM;
- }
- return 0;
-}
-
-void journal_destroy_revoke_caches(void)
-{
- do_cache_destroy(revoke_record_cache);
- revoke_record_cache = 0;
- do_cache_destroy(revoke_table_cache);
- revoke_table_cache = 0;
-}
-
-/* Initialise the revoke table for a given journal to a given size. */
-
-int journal_init_revoke(journal_t *journal, int hash_size)
-{
- int shift, tmp;
-
- journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
- if (!journal->j_revoke)
- return -ENOMEM;
-
- /* Check that the hash_size is a power of two */
- journal->j_revoke->hash_size = hash_size;
-
- shift = 0;
- tmp = hash_size;
- while ((tmp >>= 1UL) != 0UL)
- shift++;
- journal->j_revoke->hash_shift = shift;
-
- journal->j_revoke->hash_table = xmalloc(hash_size * sizeof(struct list_head));
-
- for (tmp = 0; tmp < hash_size; tmp++)
- INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
-
- return 0;
-}
-
-/* Destoy a journal's revoke table. The table must already be empty! */
-
-void journal_destroy_revoke(journal_t *journal)
-{
- struct jbd_revoke_table_s *table;
- struct list_head *hash_list;
- int i;
-
- table = journal->j_revoke;
- if (!table)
- return;
-
- for (i=0; i<table->hash_size; i++) {
- hash_list = &table->hash_table[i];
- }
-
- free(table->hash_table);
- free(table);
- journal->j_revoke = NULL;
-}
-
-/*
- * Revoke support for recovery.
- *
- * Recovery needs to be able to:
- *
- * record all revoke records, including the tid of the latest instance
- * of each revoke in the journal
- *
- * check whether a given block in a given transaction should be replayed
- * (ie. has not been revoked by a revoke record in that or a subsequent
- * transaction)
- *
- * empty the revoke table after recovery.
- */
-
-/*
- * First, setting revoke records. We create a new revoke record for
- * every block ever revoked in the log as we scan it for recovery, and
- * we update the existing records if we find multiple revokes for a
- * single block.
- */
-
-int journal_set_revoke(journal_t *journal, unsigned long blocknr,
- tid_t sequence)
-{
- struct jbd_revoke_record_s *record;
-
- record = find_revoke_record(journal, blocknr);
- if (record) {
- /* If we have multiple occurences, only record the
- * latest sequence number in the hashed record */
- if (tid_gt(sequence, record->sequence))
- record->sequence = sequence;
- return 0;
- }
- return insert_revoke_hash(journal, blocknr, sequence);
-}
-
-/*
- * Test revoke records. For a given block referenced in the log, has
- * that block been revoked? A revoke record with a given transaction
- * sequence number revokes all blocks in that transaction and earlier
- * ones, but later transactions still need replayed.
- */
-
-int journal_test_revoke(journal_t *journal, unsigned long blocknr,
- tid_t sequence)
-{
- struct jbd_revoke_record_s *record;
-
- record = find_revoke_record(journal, blocknr);
- if (!record)
- return 0;
- if (tid_gt(sequence, record->sequence))
- return 0;
- return 1;
-}
-
-/*
- * Finally, once recovery is over, we need to clear the revoke table so
- * that it can be reused by the running filesystem.
- */
-
-void journal_clear_revoke(journal_t *journal)
-{
- int i;
- struct list_head *hash_list;
- struct jbd_revoke_record_s *record;
- struct jbd_revoke_table_s *revoke_var;
-
- revoke_var = journal->j_revoke;
-
- for (i = 0; i < revoke_var->hash_size; i++) {
- hash_list = &revoke_var->hash_table[i];
- while (!list_empty(hash_list)) {
- record = (struct jbd_revoke_record_s*) hash_list->next;
- list_del(&record->hash);
- free(record);
- }
- }
-}
-
-/*
- * e2fsck.c - superblock checks
- */
-
-#define MIN_CHECK 1
-#define MAX_CHECK 2
-
-static void check_super_value(e2fsck_t ctx, const char *descr,
- unsigned long value, int flags,
- unsigned long min_val, unsigned long max_val)
-{
- struct problem_context pctx;
-
- if (((flags & MIN_CHECK) && (value < min_val)) ||
- ((flags & MAX_CHECK) && (value > max_val))) {
- clear_problem_context(&pctx);
- pctx.num = value;
- pctx.str = descr;
- fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
- ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
- }
-}
-
-/*
- * This routine may get stubbed out in special compilations of the
- * e2fsck code..
- */
-#ifndef EXT2_SPECIAL_DEVICE_SIZE
-static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
-{
- return (ext2fs_get_device_size(ctx->filesystem_name,
- EXT2_BLOCK_SIZE(ctx->fs->super),
- &ctx->num_blocks));
-}
-#endif
-
-/*
- * helper function to release an inode
- */
-struct process_block_struct {
- e2fsck_t ctx;
- char *buf;
- struct problem_context *pctx;
- int truncating;
- int truncate_offset;
- e2_blkcnt_t truncate_block;
- int truncated_blocks;
- int abort;
- errcode_t errcode;
-};
-
-static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_blk FSCK_ATTR((unused)),
- int ref_offset FSCK_ATTR((unused)),
- void *priv_data)
-{
- struct process_block_struct *pb;
- e2fsck_t ctx;
- struct problem_context *pctx;
- blk_t blk = *block_nr;
- int retval = 0;
-
- pb = (struct process_block_struct *) priv_data;
- ctx = pb->ctx;
- pctx = pb->pctx;
-
- pctx->blk = blk;
- pctx->blkcount = blockcnt;
-
- if (HOLE_BLKADDR(blk))
- return 0;
-
- if ((blk < fs->super->s_first_data_block) ||
- (blk >= fs->super->s_blocks_count)) {
- fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
- return_abort:
- pb->abort = 1;
- return BLOCK_ABORT;
- }
-
- if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
- fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
- goto return_abort;
- }
-
- /*
- * If we are deleting an orphan, then we leave the fields alone.
- * If we are truncating an orphan, then update the inode fields
- * and clean up any partial block data.
- */
- if (pb->truncating) {
- /*
- * We only remove indirect blocks if they are
- * completely empty.
- */
- if (blockcnt < 0) {
- int i, limit;
- blk_t *bp;
-
- pb->errcode = io_channel_read_blk(fs->io, blk, 1,
- pb->buf);
- if (pb->errcode)
- goto return_abort;
-
- limit = fs->blocksize >> 2;
- for (i = 0, bp = (blk_t *) pb->buf;
- i < limit; i++, bp++)
- if (*bp)
- return 0;
- }
- /*
- * We don't remove direct blocks until we've reached
- * the truncation block.
- */
- if (blockcnt >= 0 && blockcnt < pb->truncate_block)
- return 0;
- /*
- * If part of the last block needs truncating, we do
- * it here.
- */
- if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
- pb->errcode = io_channel_read_blk(fs->io, blk, 1,
- pb->buf);
- if (pb->errcode)
- goto return_abort;
- memset(pb->buf + pb->truncate_offset, 0,
- fs->blocksize - pb->truncate_offset);
- pb->errcode = io_channel_write_blk(fs->io, blk, 1,
- pb->buf);
- if (pb->errcode)
- goto return_abort;
- }
- pb->truncated_blocks++;
- *block_nr = 0;
- retval |= BLOCK_CHANGED;
- }
-
- ext2fs_block_alloc_stats(fs, blk, -1);
- return retval;
-}
-
-/*
- * This function releases an inode. Returns 1 if an inconsistency was
- * found. If the inode has a link count, then it is being truncated and
- * not deleted.
- */
-static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
- struct ext2_inode *inode, char *block_buf,
- struct problem_context *pctx)
-{
- struct process_block_struct pb;
- ext2_filsys fs = ctx->fs;
- errcode_t retval;
- __u32 count;
-
- if (!ext2fs_inode_has_valid_blocks(inode))
- return 0;
-
- pb.buf = block_buf + 3 * ctx->fs->blocksize;
- pb.ctx = ctx;
- pb.abort = 0;
- pb.errcode = 0;
- pb.pctx = pctx;
- if (inode->i_links_count) {
- pb.truncating = 1;
- pb.truncate_block = (e2_blkcnt_t)
- ((((long long)inode->i_size_high << 32) +
- inode->i_size + fs->blocksize - 1) /
- fs->blocksize);
- pb.truncate_offset = inode->i_size % fs->blocksize;
- } else {
- pb.truncating = 0;
- pb.truncate_block = 0;
- pb.truncate_offset = 0;
- }
- pb.truncated_blocks = 0;
- retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
- block_buf, release_inode_block, &pb);
- if (retval) {
- bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"),
- ino);
- return 1;
- }
- if (pb.abort)
- return 1;
-
- /* Refresh the inode since ext2fs_block_iterate may have changed it */
- e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
-
- if (pb.truncated_blocks)
- inode->i_blocks -= pb.truncated_blocks *
- (fs->blocksize / 512);
-
- if (inode->i_file_acl) {
- retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
- block_buf, -1, &count);
- if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
- retval = 0;
- count = 1;
- }
- if (retval) {
- bb_error_msg(_("while calling ext2fs_adjust_ea_refocunt for inode %d"),
- ino);
- return 1;
- }
- if (count == 0)
- ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
- inode->i_file_acl = 0;
- }
- return 0;
-}
-
-/*
- * This function releases all of the orphan inodes. It returns 1 if
- * it hit some error, and 0 on success.
- */
-static int release_orphan_inodes(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- ext2_ino_t ino, next_ino;
- struct ext2_inode inode;
- struct problem_context pctx;
- char *block_buf;
-
- if ((ino = fs->super->s_last_orphan) == 0)
- return 0;
-
- /*
- * Win or lose, we won't be using the head of the orphan inode
- * list again.
- */
- fs->super->s_last_orphan = 0;
- ext2fs_mark_super_dirty(fs);
-
- /*
- * If the filesystem contains errors, don't run the orphan
- * list, since the orphan list can't be trusted; and we're
- * going to be running a full e2fsck run anyway...
- */
- if (fs->super->s_state & EXT2_ERROR_FS)
- return 0;
-
- if ((ino < EXT2_FIRST_INODE(fs->super)) ||
- (ino > fs->super->s_inodes_count)) {
- clear_problem_context(&pctx);
- pctx.ino = ino;
- fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
- return 1;
- }
-
- block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
- "block iterate buffer");
- e2fsck_read_bitmaps(ctx);
-
- while (ino) {
- e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
- clear_problem_context(&pctx);
- pctx.ino = ino;
- pctx.inode = &inode;
- pctx.str = inode.i_links_count ? _("Truncating") :
- _("Clearing");
-
- fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
-
- next_ino = inode.i_dtime;
- if (next_ino &&
- ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
- (next_ino > fs->super->s_inodes_count))) {
- pctx.ino = next_ino;
- fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
- goto return_abort;
- }
-
- if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
- goto return_abort;
-
- if (!inode.i_links_count) {
- ext2fs_inode_alloc_stats2(fs, ino, -1,
- LINUX_S_ISDIR(inode.i_mode));
- inode.i_dtime = time(NULL);
- } else {
- inode.i_dtime = 0;
- }
- e2fsck_write_inode(ctx, ino, &inode, "delete_file");
- ino = next_ino;
- }
- ext2fs_free_mem(&block_buf);
- return 0;
- return_abort:
- ext2fs_free_mem(&block_buf);
- return 1;
-}
-
-/*
- * Check the resize inode to make sure it is sane. We check both for
- * the case where on-line resizing is not enabled (in which case the
- * resize inode should be cleared) as well as the case where on-line
- * resizing is enabled.
- */
-static void check_resize_inode(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- struct ext2_inode inode;
- struct problem_context pctx;
- int i, j, gdt_off, ind_off;
- blk_t blk, pblk, expect;
- __u32 *dind_buf = NULL, *ind_buf;
- errcode_t retval;
-
- clear_problem_context(&pctx);
-
- /*
- * If the resize inode feature isn't set, then
- * s_reserved_gdt_blocks must be zero.
- */
- if (!(fs->super->s_feature_compat &
- EXT2_FEATURE_COMPAT_RESIZE_INO)) {
- if (fs->super->s_reserved_gdt_blocks) {
- pctx.num = fs->super->s_reserved_gdt_blocks;
- if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
- &pctx)) {
- fs->super->s_reserved_gdt_blocks = 0;
- ext2fs_mark_super_dirty(fs);
- }
- }
- }
-
- /* Read the resize inode */
- pctx.ino = EXT2_RESIZE_INO;
- retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
- if (retval) {
- if (fs->super->s_feature_compat &
- EXT2_FEATURE_COMPAT_RESIZE_INO)
- ctx->flags |= E2F_FLAG_RESIZE_INODE;
- return;
- }
-
- /*
- * If the resize inode feature isn't set, check to make sure
- * the resize inode is cleared; then we're done.
- */
- if (!(fs->super->s_feature_compat &
- EXT2_FEATURE_COMPAT_RESIZE_INO)) {
- for (i=0; i < EXT2_N_BLOCKS; i++) {
- if (inode.i_block[i])
- break;
- }
- if ((i < EXT2_N_BLOCKS) &&
- fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
- memset(&inode, 0, sizeof(inode));
- e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
- "clear_resize");
- }
- return;
- }
-
- /*
- * The resize inode feature is enabled; check to make sure the
- * only block in use is the double indirect block
- */
- blk = inode.i_block[EXT2_DIND_BLOCK];
- for (i=0; i < EXT2_N_BLOCKS; i++) {
- if (i != EXT2_DIND_BLOCK && inode.i_block[i])
- break;
- }
- if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
- !(inode.i_mode & LINUX_S_IFREG) ||
- (blk < fs->super->s_first_data_block ||
- blk >= fs->super->s_blocks_count)) {
- resize_inode_invalid:
- if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
- memset(&inode, 0, sizeof(inode));
- e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
- "clear_resize");
- ctx->flags |= E2F_FLAG_RESIZE_INODE;
- }
- if (!(ctx->options & E2F_OPT_READONLY)) {
- fs->super->s_state &= ~EXT2_VALID_FS;
- ext2fs_mark_super_dirty(fs);
- }
- goto cleanup;
- }
- dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
- "resize dind buffer");
- ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
-
- retval = ext2fs_read_ind_block(fs, blk, dind_buf);
- if (retval)
- goto resize_inode_invalid;
-
- gdt_off = fs->desc_blocks;
- pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
- for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
- i++, gdt_off++, pblk++) {
- gdt_off %= fs->blocksize/4;
- if (dind_buf[gdt_off] != pblk)
- goto resize_inode_invalid;
- retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
- if (retval)
- goto resize_inode_invalid;
- ind_off = 0;
- for (j = 1; j < fs->group_desc_count; j++) {
- if (!ext2fs_bg_has_super(fs, j))
- continue;
- expect = pblk + (j * fs->super->s_blocks_per_group);
- if (ind_buf[ind_off] != expect)
- goto resize_inode_invalid;
- ind_off++;
- }
- }
-
- cleanup:
- ext2fs_free_mem(&dind_buf);
-}
-
-static void check_super_block(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- blk_t first_block, last_block;
- struct ext2_super_block *sb = fs->super;
- struct ext2_group_desc *gd;
- blk_t blocks_per_group = fs->super->s_blocks_per_group;
- blk_t bpg_max;
- int inodes_per_block;
- int ipg_max;
- int inode_size;
- dgrp_t i;
- blk_t should_be;
- struct problem_context pctx;
- __u32 free_blocks = 0, free_inodes = 0;
-
- inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
- ipg_max = inodes_per_block * (blocks_per_group - 4);
- if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
- ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
- bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
- if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
- bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
-
- ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
- sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
- ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
- sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
- ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
- sizeof(int) * fs->group_desc_count, "invalid_inode_table");
-
- clear_problem_context(&pctx);
-
- /*
- * Verify the super block constants...
- */
- check_super_value(ctx, "inodes_count", sb->s_inodes_count,
- MIN_CHECK, 1, 0);
- check_super_value(ctx, "blocks_count", sb->s_blocks_count,
- MIN_CHECK, 1, 0);
- check_super_value(ctx, "first_data_block", sb->s_first_data_block,
- MAX_CHECK, 0, sb->s_blocks_count);
- check_super_value(ctx, "log_block_size", sb->s_log_block_size,
- MIN_CHECK | MAX_CHECK, 0,
- EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
- check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
- MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
- check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
- MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
- bpg_max);
- check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
- MIN_CHECK | MAX_CHECK, 8, bpg_max);
- check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
- MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
- check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
- MAX_CHECK, 0, sb->s_blocks_count / 2);
- check_super_value(ctx, "reserved_gdt_blocks",
- sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
- fs->blocksize/4);
- inode_size = EXT2_INODE_SIZE(sb);
- check_super_value(ctx, "inode_size",
- inode_size, MIN_CHECK | MAX_CHECK,
- EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
- if (inode_size & (inode_size - 1)) {
- pctx.num = inode_size;
- pctx.str = "inode_size";
- fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
- ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
- return;
- }
-
- if (!ctx->num_blocks) {
- pctx.errcode = e2fsck_get_device_size(ctx);
- if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
- fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
- (ctx->num_blocks < sb->s_blocks_count)) {
- pctx.blk = sb->s_blocks_count;
- pctx.blk2 = ctx->num_blocks;
- if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- }
- }
-
- if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
- pctx.blk = EXT2_BLOCK_SIZE(sb);
- pctx.blk2 = EXT2_FRAG_SIZE(sb);
- fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-
- should_be = sb->s_frags_per_group >>
- (sb->s_log_block_size - sb->s_log_frag_size);
- if (sb->s_blocks_per_group != should_be) {
- pctx.blk = sb->s_blocks_per_group;
- pctx.blk2 = should_be;
- fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-
- should_be = (sb->s_log_block_size == 0) ? 1 : 0;
- if (sb->s_first_data_block != should_be) {
- pctx.blk = sb->s_first_data_block;
- pctx.blk2 = should_be;
- fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-
- should_be = sb->s_inodes_per_group * fs->group_desc_count;
- if (sb->s_inodes_count != should_be) {
- pctx.ino = sb->s_inodes_count;
- pctx.ino2 = should_be;
- if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
- sb->s_inodes_count = should_be;
- ext2fs_mark_super_dirty(fs);
- }
- }
-
- /*
- * Verify the group descriptors....
- */
- first_block = sb->s_first_data_block;
- last_block = first_block + blocks_per_group;
-
- for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
- pctx.group = i;
-
- if (i == fs->group_desc_count - 1)
- last_block = sb->s_blocks_count;
- if ((gd->bg_block_bitmap < first_block) ||
- (gd->bg_block_bitmap >= last_block)) {
- pctx.blk = gd->bg_block_bitmap;
- if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
- gd->bg_block_bitmap = 0;
- }
- if (gd->bg_block_bitmap == 0) {
- ctx->invalid_block_bitmap_flag[i]++;
- ctx->invalid_bitmaps++;
- }
- if ((gd->bg_inode_bitmap < first_block) ||
- (gd->bg_inode_bitmap >= last_block)) {
- pctx.blk = gd->bg_inode_bitmap;
- if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
- gd->bg_inode_bitmap = 0;
- }
- if (gd->bg_inode_bitmap == 0) {
- ctx->invalid_inode_bitmap_flag[i]++;
- ctx->invalid_bitmaps++;
- }
- if ((gd->bg_inode_table < first_block) ||
- ((gd->bg_inode_table +
- fs->inode_blocks_per_group - 1) >= last_block)) {
- pctx.blk = gd->bg_inode_table;
- if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
- gd->bg_inode_table = 0;
- }
- if (gd->bg_inode_table == 0) {
- ctx->invalid_inode_table_flag[i]++;
- ctx->invalid_bitmaps++;
- }
- free_blocks += gd->bg_free_blocks_count;
- free_inodes += gd->bg_free_inodes_count;
- first_block += sb->s_blocks_per_group;
- last_block += sb->s_blocks_per_group;
-
- if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
- (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
- (gd->bg_used_dirs_count > sb->s_inodes_per_group))
- ext2fs_unmark_valid(fs);
- }
-
- /*
- * Update the global counts from the block group counts. This
- * is needed for an experimental patch which eliminates
- * locking the entire filesystem when allocating blocks or
- * inodes; if the filesystem is not unmounted cleanly, the
- * global counts may not be accurate.
- */
- if ((free_blocks != sb->s_free_blocks_count) ||
- (free_inodes != sb->s_free_inodes_count)) {
- if (ctx->options & E2F_OPT_READONLY)
- ext2fs_unmark_valid(fs);
- else {
- sb->s_free_blocks_count = free_blocks;
- sb->s_free_inodes_count = free_inodes;
- ext2fs_mark_super_dirty(fs);
- }
- }
-
- if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
- (sb->s_free_inodes_count > sb->s_inodes_count))
- ext2fs_unmark_valid(fs);
-
-
- /*
- * If we have invalid bitmaps, set the error state of the
- * filesystem.
- */
- if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
- sb->s_state &= ~EXT2_VALID_FS;
- ext2fs_mark_super_dirty(fs);
- }
-
- clear_problem_context(&pctx);
-
- /*
- * If the UUID field isn't assigned, assign it.
- */
- if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
- if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
- generate_uuid(sb->s_uuid);
- ext2fs_mark_super_dirty(fs);
- fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
- }
- }
-
- /* FIXME - HURD support?
- * For the Hurd, check to see if the filetype option is set,
- * since it doesn't support it.
- */
- if (!(ctx->options & E2F_OPT_READONLY) &&
- fs->super->s_creator_os == EXT2_OS_HURD &&
- (fs->super->s_feature_incompat &
- EXT2_FEATURE_INCOMPAT_FILETYPE)) {
- if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
- fs->super->s_feature_incompat &=
- ~EXT2_FEATURE_INCOMPAT_FILETYPE;
- ext2fs_mark_super_dirty(fs);
- }
- }
-
- /*
- * If we have any of the compatibility flags set, we need to have a
- * revision 1 filesystem. Most kernels will not check the flags on
- * a rev 0 filesystem and we may have corruption issues because of
- * the incompatible changes to the filesystem.
- */
- if (!(ctx->options & E2F_OPT_READONLY) &&
- fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
- (fs->super->s_feature_compat ||
- fs->super->s_feature_ro_compat ||
- fs->super->s_feature_incompat) &&
- fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
- ext2fs_update_dynamic_rev(fs);
- ext2fs_mark_super_dirty(fs);
- }
-
- check_resize_inode(ctx);
-
- /*
- * Clean up any orphan inodes, if present.
- */
- if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
- fs->super->s_state &= ~EXT2_VALID_FS;
- ext2fs_mark_super_dirty(fs);
- }
-
- /*
- * Move the ext3 journal file, if necessary.
- */
- e2fsck_move_ext3_journal(ctx);
-}
-
-/*
- * swapfs.c --- byte-swap an ext2 filesystem
- */
-
-#ifdef ENABLE_SWAPFS
-
-struct swap_block_struct {
- ext2_ino_t ino;
- int isdir;
- errcode_t errcode;
- char *dir_buf;
- struct ext2_inode *inode;
-};
-
-/*
- * This is a helper function for block_iterate. We mark all of the
- * indirect and direct blocks as changed, so that block_iterate will
- * write them out.
- */
-static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
- void *priv_data)
-{
- errcode_t retval;
-
- struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
-
- if (sb->isdir && (blockcnt >= 0) && *block_nr) {
- retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
- if (retval) {
- sb->errcode = retval;
- return BLOCK_ABORT;
- }
- retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
- if (retval) {
- sb->errcode = retval;
- return BLOCK_ABORT;
- }
- }
- if (blockcnt >= 0) {
- if (blockcnt < EXT2_NDIR_BLOCKS)
- return 0;
- return BLOCK_CHANGED;
- }
- if (blockcnt == BLOCK_COUNT_IND) {
- if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
- return 0;
- return BLOCK_CHANGED;
- }
- if (blockcnt == BLOCK_COUNT_DIND) {
- if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
- return 0;
- return BLOCK_CHANGED;
- }
- if (blockcnt == BLOCK_COUNT_TIND) {
- if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
- return 0;
- return BLOCK_CHANGED;
- }
- return BLOCK_CHANGED;
-}
-
-/*
- * This function is responsible for byte-swapping all of the indirect,
- * block pointers. It is also responsible for byte-swapping directories.
- */
-static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
- struct ext2_inode *inode)
-{
- errcode_t retval;
- struct swap_block_struct sb;
-
- sb.ino = ino;
- sb.inode = inode;
- sb.dir_buf = block_buf + ctx->fs->blocksize*3;
- sb.errcode = 0;
- sb.isdir = 0;
- if (LINUX_S_ISDIR(inode->i_mode))
- sb.isdir = 1;
-
- retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
- swap_block, &sb);
- if (retval) {
- bb_error_msg(_("while calling ext2fs_block_iterate"));
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- if (sb.errcode) {
- bb_error_msg(_("while calling iterator function"));
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-}
-
-static void swap_inodes(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- dgrp_t group;
- unsigned int i;
- ext2_ino_t ino = 1;
- char *buf, *block_buf;
- errcode_t retval;
- struct ext2_inode * inode;
-
- e2fsck_use_inode_shortcuts(ctx, 1);
-
- retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
- &buf);
- if (retval) {
- bb_error_msg(_("while allocating inode buffer"));
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
- "block interate buffer");
- for (group = 0; group < fs->group_desc_count; group++) {
- retval = io_channel_read_blk(fs->io,
- fs->group_desc[group].bg_inode_table,
- fs->inode_blocks_per_group, buf);
- if (retval) {
- bb_error_msg(_("while reading inode table (group %d)"),
- group);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- inode = (struct ext2_inode *) buf;
- for (i=0; i < fs->super->s_inodes_per_group;
- i++, ino++, inode++) {
- ctx->stashed_ino = ino;
- ctx->stashed_inode = inode;
-
- if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
- ext2fs_swap_inode(fs, inode, inode, 0);
-
- /*
- * Skip deleted files.
- */
- if (inode->i_links_count == 0)
- continue;
-
- if (LINUX_S_ISDIR(inode->i_mode) ||
- ((inode->i_block[EXT2_IND_BLOCK] ||
- inode->i_block[EXT2_DIND_BLOCK] ||
- inode->i_block[EXT2_TIND_BLOCK]) &&
- ext2fs_inode_has_valid_blocks(inode)))
- swap_inode_blocks(ctx, ino, block_buf, inode);
-
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
-
- if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
- ext2fs_swap_inode(fs, inode, inode, 1);
- }
- retval = io_channel_write_blk(fs->io,
- fs->group_desc[group].bg_inode_table,
- fs->inode_blocks_per_group, buf);
- if (retval) {
- bb_error_msg(_("while writing inode table (group %d)"),
- group);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- }
- ext2fs_free_mem(&buf);
- ext2fs_free_mem(&block_buf);
- e2fsck_use_inode_shortcuts(ctx, 0);
- ext2fs_flush_icache(fs);
-}
-
-#if defined(__powerpc__) && BB_BIG_ENDIAN
-/*
- * On the PowerPC, the big-endian variant of the ext2 filesystem
- * has its bitmaps stored as 32-bit words with bit 0 as the LSB
- * of each word. Thus a bitmap with only bit 0 set would be, as
- * a string of bytes, 00 00 00 01 00 ...
- * To cope with this, we byte-reverse each word of a bitmap if
- * we have a big-endian filesystem, that is, if we are *not*
- * byte-swapping other word-sized numbers.
- */
-#define EXT2_BIG_ENDIAN_BITMAPS
-#endif
-
-#ifdef EXT2_BIG_ENDIAN_BITMAPS
-static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
-{
- __u32 *p = (__u32 *) bmap->bitmap;
- int n, nbytes = (bmap->end - bmap->start + 7) / 8;
-
- for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
- *p = ext2fs_swab32(*p);
-}
-#endif
-
-
-#ifdef ENABLE_SWAPFS
-static void swap_filesys(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- if (!(ctx->options & E2F_OPT_PREEN))
- printf(_("Pass 0: Doing byte-swap of filesystem\n"));
-
- /* Byte swap */
-
- if (fs->super->s_mnt_count) {
- fprintf(stderr, _("%s: the filesystem must be freshly "
- "checked using fsck\n"
- "and not mounted before trying to "
- "byte-swap it.\n"), ctx->device_name);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
- fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
- EXT2_FLAG_SWAP_BYTES_WRITE);
- fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
- } else {
- fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
- fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
- }
- swap_inodes(ctx);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
- if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
- fs->flags |= EXT2_FLAG_SWAP_BYTES;
- fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
- EXT2_FLAG_SWAP_BYTES_WRITE);
-
-#ifdef EXT2_BIG_ENDIAN_BITMAPS
- e2fsck_read_bitmaps(ctx);
- ext2fs_swap_bitmap(fs->inode_map);
- ext2fs_swap_bitmap(fs->block_map);
- fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
-#endif
- fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
- ext2fs_flush(fs);
- fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
-}
-#endif /* ENABLE_SWAPFS */
-
-#endif
-
-/*
- * util.c --- miscellaneous utilities
- */
-
-
-void *e2fsck_allocate_memory(e2fsck_t ctx EXT2FS_ATTR((unused)), unsigned int size,
- const char *description EXT2FS_ATTR((unused)))
-{
- void *ret;
-
- ret = xzalloc(size);
- return ret;
-}
-
-static char *string_copy(const char *str, int len)
-{
- char *ret;
-
- if (!str)
- return NULL;
- if (!len)
- len = strlen(str);
- ret = xmalloc(len+1);
- strncpy(ret, str, len);
- ret[len] = 0;
- return ret;
-}
-
-#ifndef HAVE_CONIO_H
-static int read_a_char(void)
-{
- char c;
- int r;
- int fail = 0;
-
- while (1) {
- if (e2fsck_global_ctx &&
- (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
- return 3;
- }
- r = read(0, &c, 1);
- if (r == 1)
- return c;
- if (fail++ > 100)
- break;
- }
- return EOF;
-}
-#endif
-
-static int ask_yn(const char * string, int def)
-{
- int c;
- const char *defstr;
- static const char short_yes[] = "yY";
- static const char short_no[] = "nN";
-
-#ifdef HAVE_TERMIOS_H
- struct termios termios, tmp;
-
- tcgetattr (0, &termios);
- tmp = termios;
- tmp.c_lflag &= ~(ICANON | ECHO);
- tmp.c_cc[VMIN] = 1;
- tmp.c_cc[VTIME] = 0;
- tcsetattr_stdin_TCSANOW(&tmp);
-#endif
-
- if (def == 1)
- defstr = "<y>";
- else if (def == 0)
- defstr = "<n>";
- else
- defstr = " (y/n)";
- printf("%s%s? ", string, defstr);
- while (1) {
- fflush (stdout);
- if ((c = read_a_char()) == EOF)
- break;
- if (c == 3) {
-#ifdef HAVE_TERMIOS_H
- tcsetattr_stdin_TCSANOW(&termios);
-#endif
- if (e2fsck_global_ctx &&
- e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
- puts("\n");
- longjmp(e2fsck_global_ctx->abort_loc, 1);
- }
- puts(_("cancelled!\n"));
- return 0;
- }
- if (strchr(short_yes, (char) c)) {
- def = 1;
- break;
- }
- else if (strchr(short_no, (char) c)) {
- def = 0;
- break;
- }
- else if ((c == ' ' || c == '\n') && (def != -1))
- break;
- }
- if (def)
- puts("yes\n");
- else
- puts ("no\n");
-#ifdef HAVE_TERMIOS_H
- tcsetattr_stdin_TCSANOW(&termios);
-#endif
- return def;
-}
-
-int ask (e2fsck_t ctx, const char * string, int def)
-{
- if (ctx->options & E2F_OPT_NO) {
- printf(_("%s? no\n\n"), string);
- return 0;
- }
- if (ctx->options & E2F_OPT_YES) {
- printf(_("%s? yes\n\n"), string);
- return 1;
- }
- if (ctx->options & E2F_OPT_PREEN) {
- printf("%s? %s\n\n", string, def ? _("yes") : _("no"));
- return def;
- }
- return ask_yn(string, def);
-}
-
-void e2fsck_read_bitmaps(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- errcode_t retval;
-
- if (ctx->invalid_bitmaps) {
- bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
- ctx->device_name);
- bb_error_msg_and_die(0);
- }
-
- ehandler_operation(_("reading inode and block bitmaps"));
- retval = ext2fs_read_bitmaps(fs);
- ehandler_operation(0);
- if (retval) {
- bb_error_msg(_("while retrying to read bitmaps for %s"),
- ctx->device_name);
- bb_error_msg_and_die(0);
- }
-}
-
-static void e2fsck_write_bitmaps(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- errcode_t retval;
-
- if (ext2fs_test_bb_dirty(fs)) {
- ehandler_operation(_("writing block bitmaps"));
- retval = ext2fs_write_block_bitmap(fs);
- ehandler_operation(0);
- if (retval) {
- bb_error_msg(_("while retrying to write block bitmaps for %s"),
- ctx->device_name);
- bb_error_msg_and_die(0);
- }
- }
-
- if (ext2fs_test_ib_dirty(fs)) {
- ehandler_operation(_("writing inode bitmaps"));
- retval = ext2fs_write_inode_bitmap(fs);
- ehandler_operation(0);
- if (retval) {
- bb_error_msg(_("while retrying to write inode bitmaps for %s"),
- ctx->device_name);
- bb_error_msg_and_die(0);
- }
- }
-}
-
-void preenhalt(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
-
- if (!(ctx->options & E2F_OPT_PREEN))
- return;
- fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
- "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
- ctx->device_name);
- if (fs != NULL) {
- fs->super->s_state |= EXT2_ERROR_FS;
- ext2fs_mark_super_dirty(fs);
- ext2fs_close(fs);
- }
- exit(EXIT_UNCORRECTED);
-}
-
-void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
- struct ext2_inode * inode, const char *proc)
-{
- int retval;
-
- retval = ext2fs_read_inode(ctx->fs, ino, inode);
- if (retval) {
- bb_error_msg(_("while reading inode %ld in %s"), ino, proc);
- bb_error_msg_and_die(0);
- }
-}
-
-extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
- struct ext2_inode * inode, int bufsize,
- const char *proc)
-{
- int retval;
-
- retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
- if (retval) {
- bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
- bb_error_msg_and_die(0);
- }
-}
-
-extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
- struct ext2_inode * inode, const char *proc)
-{
- int retval;
-
- retval = ext2fs_write_inode(ctx->fs, ino, inode);
- if (retval) {
- bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
- bb_error_msg_and_die(0);
- }
-}
-
-blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
- io_manager manager)
-{
- struct ext2_super_block *sb;
- io_channel io = NULL;
- void *buf = NULL;
- int blocksize;
- blk_t superblock, ret_sb = 8193;
-
- if (fs && fs->super) {
- ret_sb = (fs->super->s_blocks_per_group +
- fs->super->s_first_data_block);
- if (ctx) {
- ctx->superblock = ret_sb;
- ctx->blocksize = fs->blocksize;
- }
- return ret_sb;
- }
-
- if (ctx) {
- if (ctx->blocksize) {
- ret_sb = ctx->blocksize * 8;
- if (ctx->blocksize == 1024)
- ret_sb++;
- ctx->superblock = ret_sb;
- return ret_sb;
- }
- ctx->superblock = ret_sb;
- ctx->blocksize = 1024;
- }
-
- if (!name || !manager)
- goto cleanup;
-
- if (manager->open(name, 0, &io) != 0)
- goto cleanup;
-
- if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
- goto cleanup;
- sb = (struct ext2_super_block *) buf;
-
- for (blocksize = EXT2_MIN_BLOCK_SIZE;
- blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
- superblock = blocksize*8;
- if (blocksize == 1024)
- superblock++;
- io_channel_set_blksize(io, blocksize);
- if (io_channel_read_blk(io, superblock,
- -SUPERBLOCK_SIZE, buf))
- continue;
-#if BB_BIG_ENDIAN
- if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
- ext2fs_swap_super(sb);
-#endif
- if (sb->s_magic == EXT2_SUPER_MAGIC) {
- ret_sb = superblock;
- if (ctx) {
- ctx->superblock = superblock;
- ctx->blocksize = blocksize;
- }
- break;
- }
- }
-
-cleanup:
- if (io)
- io_channel_close(io);
- ext2fs_free_mem(&buf);
- return ret_sb;
-}
-
-
-/*
- * This function runs through the e2fsck passes and calls them all,
- * returning restart, abort, or cancel as necessary...
- */
-typedef void (*pass_t)(e2fsck_t ctx);
-
-static const pass_t e2fsck_passes[] = {
- e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
- e2fsck_pass5, 0 };
-
-#define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
-
-static int e2fsck_run(e2fsck_t ctx)
-{
- int i;
- pass_t e2fsck_pass;
-
- if (setjmp(ctx->abort_loc)) {
- ctx->flags &= ~E2F_FLAG_SETJMP_OK;
- return (ctx->flags & E2F_FLAG_RUN_RETURN);
- }
- ctx->flags |= E2F_FLAG_SETJMP_OK;
-
- for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
- if (ctx->flags & E2F_FLAG_RUN_RETURN)
- break;
- e2fsck_pass(ctx);
- if (ctx->progress)
- (void) (ctx->progress)(ctx, 0, 0, 0);
- }
- ctx->flags &= ~E2F_FLAG_SETJMP_OK;
-
- if (ctx->flags & E2F_FLAG_RUN_RETURN)
- return (ctx->flags & E2F_FLAG_RUN_RETURN);
- return 0;
-}
-
-
-/*
- * unix.c - The unix-specific code for e2fsck
- */
-
-
-/* Command line options */
-static int swapfs;
-#ifdef ENABLE_SWAPFS
-static int normalize_swapfs;
-#endif
-static int cflag; /* check disk */
-static int show_version_only;
-static int verbose;
-
-#define P_E2(singular, plural, n) n, ((n) == 1 ? singular : plural)
-
-static void show_stats(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- int inodes, inodes_used, blocks, blocks_used;
- int dir_links;
- int num_files, num_links;
- int frag_percent;
-
- dir_links = 2 * ctx->fs_directory_count - 1;
- num_files = ctx->fs_total_count - dir_links;
- num_links = ctx->fs_links_count - dir_links;
- inodes = fs->super->s_inodes_count;
- inodes_used = (fs->super->s_inodes_count -
- fs->super->s_free_inodes_count);
- blocks = fs->super->s_blocks_count;
- blocks_used = (fs->super->s_blocks_count -
- fs->super->s_free_blocks_count);
-
- frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
- frag_percent = (frag_percent + 5) / 10;
-
- if (!verbose) {
- printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
- ctx->device_name, inodes_used, inodes,
- frag_percent / 10, frag_percent % 10,
- blocks_used, blocks);
- return;
- }
- printf("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
- 100 * inodes_used / inodes);
- printf("%8d non-contiguous inode%s (%0d.%d%%)\n",
- P_E2("", "s", ctx->fs_fragmented),
- frag_percent / 10, frag_percent % 10);
- printf(_(" # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
- ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
- printf("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
- (int) ((long long) 100 * blocks_used / blocks));
- printf("%8d large file%s\n", P_E2("", "s", ctx->large_files));
- printf("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
- printf("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
- printf("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
- printf("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
- printf("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
- printf("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
- printf("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
- printf(" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
- printf("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
- printf("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
-}
-
-static void check_mount(e2fsck_t ctx)
-{
- errcode_t retval;
- int cont;
-
- retval = ext2fs_check_if_mounted(ctx->filesystem_name,
- &ctx->mount_flags);
- if (retval) {
- bb_error_msg(_("while determining whether %s is mounted"),
- ctx->filesystem_name);
- return;
- }
-
- /*
- * If the filesystem isn't mounted, or it's the root filesystem
- * and it's mounted read-only, then everything's fine.
- */
- if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
- ((ctx->mount_flags & EXT2_MF_ISROOT) &&
- (ctx->mount_flags & EXT2_MF_READONLY)))
- return;
-
- if (ctx->options & E2F_OPT_READONLY) {
- printf(_("Warning! %s is mounted.\n"), ctx->filesystem_name);
- return;
- }
-
- printf(_("%s is mounted. "), ctx->filesystem_name);
- if (!ctx->interactive)
- bb_error_msg_and_die(_("can't continue, aborting"));
- printf(_("\n\n\007\007\007\007WARNING!!! "
- "Running e2fsck on a mounted filesystem may cause\n"
- "SEVERE filesystem damage.\007\007\007\n\n"));
- cont = ask_yn(_("Do you really want to continue"), -1);
- if (!cont) {
- printf(_("check aborted.\n"));
- exit(0);
- }
-}
-
-static int is_on_batt(void)
-{
- FILE *f;
- DIR *d;
- char tmp[80], tmp2[80], fname[80];
- unsigned int acflag;
- struct dirent* de;
-
- f = fopen_for_read("/proc/apm");
- if (f) {
- if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
- acflag = 1;
- fclose(f);
- return (acflag != 1);
- }
- d = opendir("/proc/acpi/ac_adapter");
- if (d) {
- while ((de=readdir(d)) != NULL) {
- if (!strncmp(".", de->d_name, 1))
- continue;
- snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
- de->d_name);
- f = fopen_for_read(fname);
- if (!f)
- continue;
- if (fscanf(f, "%s %s", tmp2, tmp) != 2)
- tmp[0] = 0;
- fclose(f);
- if (strncmp(tmp, "off-line", 8) == 0) {
- closedir(d);
- return 1;
- }
- }
- closedir(d);
- }
- return 0;
-}
-
-/*
- * This routine checks to see if a filesystem can be skipped; if so,
- * it will exit with EXIT_OK. Under some conditions it will print a
- * message explaining why a check is being forced.
- */
-static void check_if_skip(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- const char *reason = NULL;
- unsigned int reason_arg = 0;
- long next_check;
- int batt = is_on_batt();
- time_t now = time(NULL);
-
- if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
- return;
-
- if ((fs->super->s_state & EXT2_ERROR_FS) ||
- !ext2fs_test_valid(fs))
- reason = _(" contains a file system with errors");
- else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
- reason = _(" was not cleanly unmounted");
- else if ((fs->super->s_max_mnt_count > 0) &&
- (fs->super->s_mnt_count >=
- (unsigned) fs->super->s_max_mnt_count)) {
- reason = _(" has been mounted %u times without being checked");
- reason_arg = fs->super->s_mnt_count;
- if (batt && (fs->super->s_mnt_count <
- (unsigned) fs->super->s_max_mnt_count*2))
- reason = 0;
- } else if (!(ctx->options & E2F_OPT_PREEN) &&
- fs->super->s_checkinterval &&
- ((now - fs->super->s_lastcheck) >=
- fs->super->s_checkinterval)) {
- reason = _(" has gone %u days without being checked");
- reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
- if (batt && ((now - fs->super->s_lastcheck) <
- fs->super->s_checkinterval*2))
- reason = 0;
- }
- if (reason) {
- fputs(ctx->device_name, stdout);
- printf(reason, reason_arg);
- fputs(_(", check forced.\n"), stdout);
- return;
- }
- printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
- fs->super->s_inodes_count - fs->super->s_free_inodes_count,
- fs->super->s_inodes_count,
- fs->super->s_blocks_count - fs->super->s_free_blocks_count,
- fs->super->s_blocks_count);
- next_check = 100000;
- if (fs->super->s_max_mnt_count > 0) {
- next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
- if (next_check <= 0)
- next_check = 1;
- }
- if (fs->super->s_checkinterval &&
- ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
- next_check = 1;
- if (next_check <= 5) {
- if (next_check == 1)
- fputs(_(" (check after next mount)"), stdout);
- else
- printf(_(" (check in %ld mounts)"), next_check);
- }
- bb_putchar('\n');
- ext2fs_close(fs);
- ctx->fs = NULL;
- e2fsck_free_context(ctx);
- exit(EXIT_OK);
-}
-
-/*
- * For completion notice
- */
-struct percent_tbl {
- int max_pass;
- int table[32];
-};
-static const struct percent_tbl e2fsck_tbl = {
- 5, { 0, 70, 90, 92, 95, 100 }
-};
-
-static char bar[128], spaces[128];
-
-static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
- int max)
-{
- float percent;
-
- if (pass <= 0)
- return 0.0;
- if (pass > tbl->max_pass || max == 0)
- return 100.0;
- percent = ((float) curr) / ((float) max);
- return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
- + tbl->table[pass-1]);
-}
-
-void e2fsck_clear_progbar(e2fsck_t ctx)
-{
- if (!(ctx->flags & E2F_FLAG_PROG_BAR))
- return;
-
- printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
- ctx->stop_meta);
- fflush(stdout);
- ctx->flags &= ~E2F_FLAG_PROG_BAR;
-}
-
-int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
- unsigned int dpynum)
-{
- static const char spinner[] = "\\|/-";
- int i;
- unsigned int tick;
- struct timeval tv;
- int dpywidth;
- int fixed_percent;
-
- if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
- return 0;
-
- /*
- * Calculate the new progress position. If the
- * percentage hasn't changed, then we skip out right
- * away.
- */
- fixed_percent = (int) ((10 * percent) + 0.5);
- if (ctx->progress_last_percent == fixed_percent)
- return 0;
- ctx->progress_last_percent = fixed_percent;
-
- /*
- * If we've already updated the spinner once within
- * the last 1/8th of a second, no point doing it
- * again.
- */
- gettimeofday(&tv, NULL);
- tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
- if ((tick == ctx->progress_last_time) &&
- (fixed_percent != 0) && (fixed_percent != 1000))
- return 0;
- ctx->progress_last_time = tick;
-
- /*
- * Advance the spinner, and note that the progress bar
- * will be on the screen
- */
- ctx->progress_pos = (ctx->progress_pos+1) & 3;
- ctx->flags |= E2F_FLAG_PROG_BAR;
-
- dpywidth = 66 - strlen(label);
- dpywidth = 8 * (dpywidth / 8);
- if (dpynum)
- dpywidth -= 8;
-
- i = ((percent * dpywidth) + 50) / 100;
- printf("%s%s: |%s%s", ctx->start_meta, label,
- bar + (sizeof(bar) - (i+1)),
- spaces + (sizeof(spaces) - (dpywidth - i + 1)));
- if (fixed_percent == 1000)
- bb_putchar('|');
- else
- bb_putchar(spinner[ctx->progress_pos & 3]);
- printf(" %4.1f%% ", percent);
- if (dpynum)
- printf("%u\r", dpynum);
- else
- fputs(" \r", stdout);
- fputs(ctx->stop_meta, stdout);
-
- if (fixed_percent == 1000)
- e2fsck_clear_progbar(ctx);
- fflush(stdout);
-
- return 0;
-}
-
-static int e2fsck_update_progress(e2fsck_t ctx, int pass,
- unsigned long cur, unsigned long max)
-{
- char buf[80];
- float percent;
-
- if (pass == 0)
- return 0;
-
- if (ctx->progress_fd) {
- sprintf(buf, "%d %lu %lu\n", pass, cur, max);
- xwrite_str(ctx->progress_fd, buf);
- } else {
- percent = calc_percent(&e2fsck_tbl, pass, cur, max);
- e2fsck_simple_progress(ctx, ctx->device_name,
- percent, 0);
- }
- return 0;
-}
-
-static void reserve_stdio_fds(void)
-{
- int fd;
-
- while (1) {
- fd = open(bb_dev_null, O_RDWR);
- if (fd > 2)
- break;
- if (fd < 0) {
- fprintf(stderr, _("ERROR: Cannot open "
- "/dev/null (%s)\n"),
- strerror(errno));
- break;
- }
- }
- close(fd);
-}
-
-static void signal_progress_on(int sig FSCK_ATTR((unused)))
-{
- e2fsck_t ctx = e2fsck_global_ctx;
-
- if (!ctx)
- return;
-
- ctx->progress = e2fsck_update_progress;
- ctx->progress_fd = 0;
-}
-
-static void signal_progress_off(int sig FSCK_ATTR((unused)))
-{
- e2fsck_t ctx = e2fsck_global_ctx;
-
- if (!ctx)
- return;
-
- e2fsck_clear_progbar(ctx);
- ctx->progress = 0;
-}
-
-static void signal_cancel(int sig FSCK_ATTR((unused)))
-{
- e2fsck_t ctx = e2fsck_global_ctx;
-
- if (!ctx)
- exit(FSCK_CANCELED);
-
- ctx->flags |= E2F_FLAG_CANCEL;
-}
-
-static void parse_extended_opts(e2fsck_t ctx, const char *opts)
-{
- char *buf, *token, *next, *p, *arg;
- int ea_ver;
- int extended_usage = 0;
-
- buf = string_copy(opts, 0);
- for (token = buf; token && *token; token = next) {
- p = strchr(token, ',');
- next = 0;
- if (p) {
- *p = 0;
- next = p+1;
- }
- arg = strchr(token, '=');
- if (arg) {
- *arg = 0;
- arg++;
- }
- if (strcmp(token, "ea_ver") == 0) {
- if (!arg) {
- extended_usage++;
- continue;
- }
- ea_ver = strtoul(arg, &p, 0);
- if (*p ||
- ((ea_ver != 1) && (ea_ver != 2))) {
- fprintf(stderr,
- _("Invalid EA version.\n"));
- extended_usage++;
- continue;
- }
- ctx->ext_attr_ver = ea_ver;
- } else {
- fprintf(stderr, _("Unknown extended option: %s\n"),
- token);
- extended_usage++;
- }
- }
- if (extended_usage) {
- bb_error_msg_and_die(
- "Extended options are separated by commas, "
- "and may take an argument which\n"
- "is set off by an equals ('=') sign. "
- "Valid extended options are:\n"
- "\tea_ver=<ea_version (1 or 2)>\n\n");
- }
-}
-
-
-static errcode_t PRS(int argc, char **argv, e2fsck_t *ret_ctx)
-{
- int flush = 0;
- int c, fd;
- e2fsck_t ctx;
- errcode_t retval;
- struct sigaction sa;
- char *extended_opts = NULL;
-
- retval = e2fsck_allocate_context(&ctx);
- if (retval)
- return retval;
-
- *ret_ctx = ctx;
-
- setvbuf(stdout, NULL, _IONBF, BUFSIZ);
- setvbuf(stderr, NULL, _IONBF, BUFSIZ);
- if (isatty(0) && isatty(1)) {
- ctx->interactive = 1;
- } else {
- ctx->start_meta[0] = '\001';
- ctx->stop_meta[0] = '\002';
- }
- memset(bar, '=', sizeof(bar)-1);
- memset(spaces, ' ', sizeof(spaces)-1);
-
- if (argc && *argv)
- ctx->program_name = *argv;
- else
- ctx->program_name = "e2fsck";
- while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
- switch (c) {
- case 'C':
- ctx->progress = e2fsck_update_progress;
- ctx->progress_fd = atoi(optarg);
- if (!ctx->progress_fd)
- break;
- /* Validate the file descriptor to avoid disasters */
- fd = dup(ctx->progress_fd);
- if (fd < 0) {
- fprintf(stderr,
- _("Error validating file descriptor %d: %s\n"),
- ctx->progress_fd,
- error_message(errno));
- bb_error_msg_and_die(_("Invalid completion information file descriptor"));
- } else
- close(fd);
- break;
- case 'D':
- ctx->options |= E2F_OPT_COMPRESS_DIRS;
- break;
- case 'E':
- extended_opts = optarg;
- break;
- case 'p':
- case 'a':
- if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
- conflict_opt:
- bb_error_msg_and_die(_("only one the options -p/-a, -n or -y may be specified"));
- }
- ctx->options |= E2F_OPT_PREEN;
- break;
- case 'n':
- if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
- goto conflict_opt;
- ctx->options |= E2F_OPT_NO;
- break;
- case 'y':
- if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
- goto conflict_opt;
- ctx->options |= E2F_OPT_YES;
- break;
- case 't':
- /* FIXME - This needs to go away in a future path - will change binary */
- fprintf(stderr, _("The -t option is not "
- "supported on this version of e2fsck.\n"));
- break;
- case 'c':
- if (cflag++)
- ctx->options |= E2F_OPT_WRITECHECK;
- ctx->options |= E2F_OPT_CHECKBLOCKS;
- break;
- case 'r':
- /* What we do by default, anyway! */
- break;
- case 'b':
- ctx->use_superblock = atoi(optarg);
- ctx->flags |= E2F_FLAG_SB_SPECIFIED;
- break;
- case 'B':
- ctx->blocksize = atoi(optarg);
- break;
- case 'I':
- ctx->inode_buffer_blocks = atoi(optarg);
- break;
- case 'j':
- ctx->journal_name = string_copy(optarg, 0);
- break;
- case 'P':
- ctx->process_inode_size = atoi(optarg);
- break;
- case 'd':
- ctx->options |= E2F_OPT_DEBUG;
- break;
- case 'f':
- ctx->options |= E2F_OPT_FORCE;
- break;
- case 'F':
- flush = 1;
- break;
- case 'v':
- verbose = 1;
- break;
- case 'V':
- show_version_only = 1;
- break;
- case 'N':
- ctx->device_name = optarg;
- break;
-#ifdef ENABLE_SWAPFS
- case 's':
- normalize_swapfs = 1;
- case 'S':
- swapfs = 1;
- break;
-#else
- case 's':
- case 'S':
- fprintf(stderr, _("Byte-swapping filesystems "
- "not compiled in this version "
- "of e2fsck\n"));
- exit(1);
-#endif
- default:
- bb_show_usage();
- }
- if (show_version_only)
- return 0;
- if (optind != argc - 1)
- bb_show_usage();
- if ((ctx->options & E2F_OPT_NO) &&
- !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
- ctx->options |= E2F_OPT_READONLY;
- ctx->io_options = strchr(argv[optind], '?');
- if (ctx->io_options)
- *ctx->io_options++ = 0;
- ctx->filesystem_name = argv[optind];
- if (resolve_mount_spec(&ctx->filesystem_name) < 0 ||
- !ctx->filesystem_name) {
- bb_error_msg(_("Unable to resolve '%s'"), argv[optind]);
- bb_error_msg_and_die(0);
- }
- if (extended_opts)
- parse_extended_opts(ctx, extended_opts);
-
- if (flush) {
- fd = open(ctx->filesystem_name, O_RDONLY, 0);
- if (fd < 0) {
- bb_error_msg(_("while opening %s for flushing"),
- ctx->filesystem_name);
- bb_error_msg_and_die(0);
- }
- if ((retval = ext2fs_sync_device(fd, 1))) {
- bb_error_msg(_("while trying to flush %s"),
- ctx->filesystem_name);
- bb_error_msg_and_die(0);
- }
- close(fd);
- }
-#ifdef ENABLE_SWAPFS
- if (swapfs && cflag) {
- fprintf(stderr, _("Incompatible options not "
- "allowed when byte-swapping.\n"));
- exit(EXIT_USAGE);
- }
-#endif
- /*
- * Set up signal action
- */
- memset(&sa, 0, sizeof(struct sigaction));
- sa.sa_handler = signal_cancel;
- sigaction(SIGINT, &sa, 0);
- sigaction(SIGTERM, &sa, 0);
-#ifdef SA_RESTART
- sa.sa_flags = SA_RESTART;
-#endif
- e2fsck_global_ctx = ctx;
- sa.sa_handler = signal_progress_on;
- sigaction(SIGUSR1, &sa, 0);
- sa.sa_handler = signal_progress_off;
- sigaction(SIGUSR2, &sa, 0);
-
- /* Update our PATH to include /sbin if we need to run badblocks */
- if (cflag)
- e2fs_set_sbin_path();
- return 0;
-}
-
-static const char my_ver_string[] = E2FSPROGS_VERSION;
-static const char my_ver_date[] = E2FSPROGS_DATE;
-
-int e2fsck_main (int argc, char **argv);
-int e2fsck_main (int argc, char **argv)
-{
- errcode_t retval;
- int exit_value = EXIT_OK;
- ext2_filsys fs = 0;
- io_manager io_ptr;
- struct ext2_super_block *sb;
- const char *lib_ver_date;
- int my_ver, lib_ver;
- e2fsck_t ctx;
- struct problem_context pctx;
- int flags, run_result;
-
- clear_problem_context(&pctx);
-
- my_ver = ext2fs_parse_version_string(my_ver_string);
- lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
- if (my_ver > lib_ver) {
- fprintf( stderr, _("Error: ext2fs library version "
- "out of date!\n"));
- show_version_only++;
- }
-
- retval = PRS(argc, argv, &ctx);
- if (retval) {
- bb_error_msg(_("while trying to initialize program"));
- exit(EXIT_ERROR);
- }
- reserve_stdio_fds();
-
- if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
- fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
- my_ver_date);
-
- if (show_version_only) {
- fprintf(stderr, _("\tUsing %s, %s\n"),
- error_message(EXT2_ET_BASE), lib_ver_date);
- exit(EXIT_OK);
- }
-
- check_mount(ctx);
-
- if (!(ctx->options & E2F_OPT_PREEN) &&
- !(ctx->options & E2F_OPT_NO) &&
- !(ctx->options & E2F_OPT_YES)) {
- if (!ctx->interactive)
- bb_error_msg_and_die(_("need terminal for interactive repairs"));
- }
- ctx->superblock = ctx->use_superblock;
-restart:
-#ifdef CONFIG_TESTIO_DEBUG
- io_ptr = test_io_manager;
- test_io_backing_manager = unix_io_manager;
-#else
- io_ptr = unix_io_manager;
-#endif
- flags = 0;
- if ((ctx->options & E2F_OPT_READONLY) == 0)
- flags |= EXT2_FLAG_RW;
-
- if (ctx->superblock && ctx->blocksize) {
- retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
- flags, ctx->superblock, ctx->blocksize,
- io_ptr, &fs);
- } else if (ctx->superblock) {
- int blocksize;
- for (blocksize = EXT2_MIN_BLOCK_SIZE;
- blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
- retval = ext2fs_open2(ctx->filesystem_name,
- ctx->io_options, flags,
- ctx->superblock, blocksize,
- io_ptr, &fs);
- if (!retval)
- break;
- }
- } else
- retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
- flags, 0, 0, io_ptr, &fs);
- if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
- !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
- ((retval == EXT2_ET_BAD_MAGIC) ||
- ((retval == 0) && ext2fs_check_desc(fs)))) {
- if (!fs || (fs->group_desc_count > 1)) {
- printf(_("%s trying backup blocks...\n"),
- retval ? _("Couldn't find ext2 superblock,") :
- _("Group descriptors look bad..."));
- get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
- if (fs)
- ext2fs_close(fs);
- goto restart;
- }
- }
- if (retval) {
- bb_error_msg(_("while trying to open %s"),
- ctx->filesystem_name);
- if (retval == EXT2_ET_REV_TOO_HIGH) {
- printf(_("The filesystem revision is apparently "
- "too high for this version of e2fsck.\n"
- "(Or the filesystem superblock "
- "is corrupt)\n\n"));
- fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
- } else if (retval == EXT2_ET_SHORT_READ)
- printf(_("Could this be a zero-length partition?\n"));
- else if ((retval == EPERM) || (retval == EACCES))
- printf(_("You must have %s access to the "
- "filesystem or be root\n"),
- (ctx->options & E2F_OPT_READONLY) ?
- "r/o" : "r/w");
- else if (retval == ENXIO)
- printf(_("Possibly non-existent or swap device?\n"));
-#ifdef EROFS
- else if (retval == EROFS)
- printf(_("Disk write-protected; use the -n option "
- "to do a read-only\n"
- "check of the device.\n"));
-#endif
- else
- fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
- bb_error_msg_and_die(0);
- }
- ctx->fs = fs;
- fs->priv_data = ctx;
- sb = fs->super;
- if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
- bb_error_msg(_("while trying to open %s"),
- ctx->filesystem_name);
- get_newer:
- bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
- }
-
- /*
- * Set the device name, which is used whenever we print error
- * or informational messages to the user.
- */
- if (ctx->device_name == 0 &&
- (sb->s_volume_name[0] != 0)) {
- ctx->device_name = string_copy(sb->s_volume_name,
- sizeof(sb->s_volume_name));
- }
- if (ctx->device_name == 0)
- ctx->device_name = ctx->filesystem_name;
-
- /*
- * Make sure the ext3 superblock fields are consistent.
- */
- retval = e2fsck_check_ext3_journal(ctx);
- if (retval) {
- bb_error_msg(_("while checking ext3 journal for %s"),
- ctx->device_name);
- bb_error_msg_and_die(0);
- }
-
- /*
- * Check to see if we need to do ext3-style recovery. If so,
- * do it, and then restart the fsck.
- */
- if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
- if (ctx->options & E2F_OPT_READONLY) {
- printf(_("Warning: skipping journal recovery "
- "because doing a read-only filesystem "
- "check.\n"));
- io_channel_flush(ctx->fs->io);
- } else {
- if (ctx->flags & E2F_FLAG_RESTARTED) {
- /*
- * Whoops, we attempted to run the
- * journal twice. This should never
- * happen, unless the hardware or
- * device driver is being bogus.
- */
- bb_error_msg(_("can't set superblock flags on %s"), ctx->device_name);
- bb_error_msg_and_die(0);
- }
- retval = e2fsck_run_ext3_journal(ctx);
- if (retval) {
- bb_error_msg(_("while recovering ext3 journal of %s"),
- ctx->device_name);
- bb_error_msg_and_die(0);
- }
- ext2fs_close(ctx->fs);
- ctx->fs = 0;
- ctx->flags |= E2F_FLAG_RESTARTED;
- goto restart;
- }
- }
-
- /*
- * Check for compatibility with the feature sets. We need to
- * be more stringent than ext2fs_open().
- */
- if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
- (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
- bb_error_msg("(%s)", ctx->device_name);
- goto get_newer;
- }
- if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
- bb_error_msg("(%s)", ctx->device_name);
- goto get_newer;
- }
-#ifdef ENABLE_COMPRESSION
- /* FIXME - do we support this at all? */
- if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
- bb_error_msg(_("warning: compression support is experimental"));
-#endif
-#ifndef ENABLE_HTREE
- if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
- bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
- "but filesystem %s has HTREE directories."),
- ctx->device_name);
- goto get_newer;
- }
-#endif
-
- /*
- * If the user specified a specific superblock, presumably the
- * master superblock has been trashed. So we mark the
- * superblock as dirty, so it can be written out.
- */
- if (ctx->superblock &&
- !(ctx->options & E2F_OPT_READONLY))
- ext2fs_mark_super_dirty(fs);
-
- /*
- * We only update the master superblock because (a) paranoia;
- * we don't want to corrupt the backup superblocks, and (b) we
- * don't need to update the mount count and last checked
- * fields in the backup superblock (the kernel doesn't
- * update the backup superblocks anyway).
- */
- fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
-
- ehandler_init(fs->io);
-
- if (ctx->superblock)
- set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
- ext2fs_mark_valid(fs);
- check_super_block(ctx);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- bb_error_msg_and_die(0);
- check_if_skip(ctx);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- bb_error_msg_and_die(0);
-#ifdef ENABLE_SWAPFS
-
-#ifdef WORDS_BIGENDIAN
-#define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
-#else
-#define NATIVE_FLAG 0
-#endif
-
-
- if (normalize_swapfs) {
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
- fprintf(stderr, _("%s: Filesystem byte order "
- "already normalized.\n"), ctx->device_name);
- bb_error_msg_and_die(0);
- }
- }
- if (swapfs) {
- swap_filesys(ctx);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- bb_error_msg_and_die(0);
- }
-#endif
-
- /*
- * Mark the system as valid, 'til proven otherwise
- */
- ext2fs_mark_valid(fs);
-
- retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
- if (retval) {
- bb_error_msg(_("while reading bad blocks inode"));
- preenhalt(ctx);
- printf(_("This doesn't bode well,"
- " but we'll try to go on...\n"));
- }
-
- run_result = e2fsck_run(ctx);
- e2fsck_clear_progbar(ctx);
- if (run_result == E2F_FLAG_RESTART) {
- printf(_("Restarting e2fsck from the beginning...\n"));
- retval = e2fsck_reset_context(ctx);
- if (retval) {
- bb_error_msg(_("while resetting context"));
- bb_error_msg_and_die(0);
- }
- ext2fs_close(fs);
- goto restart;
- }
- if (run_result & E2F_FLAG_CANCEL) {
- printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
- ctx->device_name : ctx->filesystem_name);
- exit_value |= FSCK_CANCELED;
- }
- if (run_result & E2F_FLAG_ABORT)
- bb_error_msg_and_die(_("aborted"));
-
- /* Cleanup */
- if (ext2fs_test_changed(fs)) {
- exit_value |= EXIT_NONDESTRUCT;
- if (!(ctx->options & E2F_OPT_PREEN))
- printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
- ctx->device_name);
- if (ctx->mount_flags & EXT2_MF_ISROOT) {
- printf(_("%s: ***** REBOOT LINUX *****\n"),
- ctx->device_name);
- exit_value |= EXIT_DESTRUCT;
- }
- }
- if (!ext2fs_test_valid(fs)) {
- printf(_("\n%s: ********** WARNING: Filesystem still has "
- "errors **********\n\n"), ctx->device_name);
- exit_value |= EXIT_UNCORRECTED;
- exit_value &= ~EXIT_NONDESTRUCT;
- }
- if (exit_value & FSCK_CANCELED)
- exit_value &= ~EXIT_NONDESTRUCT;
- else {
- show_stats(ctx);
- if (!(ctx->options & E2F_OPT_READONLY)) {
- if (ext2fs_test_valid(fs)) {
- if (!(sb->s_state & EXT2_VALID_FS))
- exit_value |= EXIT_NONDESTRUCT;
- sb->s_state = EXT2_VALID_FS;
- } else
- sb->s_state &= ~EXT2_VALID_FS;
- sb->s_mnt_count = 0;
- sb->s_lastcheck = time(NULL);
- ext2fs_mark_super_dirty(fs);
- }
- }
-
- e2fsck_write_bitmaps(ctx);
-
- ext2fs_close(fs);
- ctx->fs = NULL;
- free(ctx->filesystem_name);
- free(ctx->journal_name);
- e2fsck_free_context(ctx);
-
- return exit_value;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2fsck.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2fsck.h
deleted file mode 100644
index 754d6f1097..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2fsck.h
+++ /dev/null
@@ -1,637 +0,0 @@
-/* vi: set sw=4 ts=4: */
-#include <sys/types.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <time.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <setjmp.h>
-#include <errno.h>
-#include <getopt.h>
-#include <limits.h>
-#include <stddef.h>
-#include <assert.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <sys/resource.h>
-#include <sys/param.h>
-#include <sys/mount.h>
-#include <sys/ioctl.h>
-#include <termios.h>
-#include <mntent.h>
-#include <dirent.h>
-#include "ext2fs/kernel-list.h"
-#include <sys/types.h>
-#include <linux/types.h>
-
-/*
- * Now pull in the real linux/jfs.h definitions.
- */
-#include "ext2fs/kernel-jbd.h"
-
-
-
-#include "fsck.h"
-
-#include "ext2fs/ext2_fs.h"
-#include "volume_id.h"
-#include "ext2fs/ext2_ext_attr.h"
-#include "e2fs_lib.h"
-#include "libbb.h"
-
-#ifdef HAVE_CONIO_H
-#undef HAVE_TERMIOS_H
-#include <conio.h>
-#define read_a_char() getch()
-#else
-#ifdef HAVE_TERMIOS_H
-#include <termios.h>
-#endif
-#endif
-
-
-/*
- * The last ext2fs revision level that this version of e2fsck is able to
- * support
- */
-#define E2FSCK_CURRENT_REV 1
-
-/* Used by the region allocation code */
-typedef __u32 region_addr_t;
-typedef struct region_struct *region_t;
-
-struct dx_dirblock_info {
- int type;
- blk_t phys;
- int flags;
- blk_t parent;
- ext2_dirhash_t min_hash;
- ext2_dirhash_t max_hash;
- ext2_dirhash_t node_min_hash;
- ext2_dirhash_t node_max_hash;
-};
-
-/*
-These defines are used in the type field of dx_dirblock_info
-*/
-
-#define DX_DIRBLOCK_ROOT 1
-#define DX_DIRBLOCK_LEAF 2
-#define DX_DIRBLOCK_NODE 3
-
-
-/*
-The following defines are used in the 'flags' field of a dx_dirblock_info
-*/
-#define DX_FLAG_REFERENCED 1
-#define DX_FLAG_DUP_REF 2
-#define DX_FLAG_FIRST 4
-#define DX_FLAG_LAST 8
-
-/*
- * E2fsck options
- */
-#define E2F_OPT_READONLY 0x0001
-#define E2F_OPT_PREEN 0x0002
-#define E2F_OPT_YES 0x0004
-#define E2F_OPT_NO 0x0008
-#define E2F_OPT_TIME 0x0010
-#define E2F_OPT_CHECKBLOCKS 0x0040
-#define E2F_OPT_DEBUG 0x0080
-#define E2F_OPT_FORCE 0x0100
-#define E2F_OPT_WRITECHECK 0x0200
-#define E2F_OPT_COMPRESS_DIRS 0x0400
-
-/*
- * E2fsck flags
- */
-#define E2F_FLAG_ABORT 0x0001 /* Abort signaled */
-#define E2F_FLAG_CANCEL 0x0002 /* Cancel signaled */
-#define E2F_FLAG_SIGNAL_MASK 0x0003
-#define E2F_FLAG_RESTART 0x0004 /* Restart signaled */
-
-#define E2F_FLAG_SETJMP_OK 0x0010 /* Setjmp valid for abort */
-
-#define E2F_FLAG_PROG_BAR 0x0020 /* Progress bar on screen */
-#define E2F_FLAG_PROG_SUPPRESS 0x0040 /* Progress suspended */
-#define E2F_FLAG_JOURNAL_INODE 0x0080 /* Create a new ext3 journal inode */
-#define E2F_FLAG_SB_SPECIFIED 0x0100 /* The superblock was explicitly
- * specified by the user */
-#define E2F_FLAG_RESTARTED 0x0200 /* E2fsck has been restarted */
-#define E2F_FLAG_RESIZE_INODE 0x0400 /* Request to recreate resize inode */
-
-
-/*Don't know where these come from*/
-#define READ 0
-#define WRITE 1
-#define cpu_to_be32(n) htonl(n)
-#define be32_to_cpu(n) ntohl(n)
-
-/*
- * We define a set of "latch groups"; these are problems which are
- * handled as a set. The user answers once for a particular latch
- * group.
- */
-#define PR_LATCH_MASK 0x0ff0 /* Latch mask */
-#define PR_LATCH_BLOCK 0x0010 /* Latch for illegal blocks (pass 1) */
-#define PR_LATCH_BBLOCK 0x0020 /* Latch for bad block inode blocks (pass 1) */
-#define PR_LATCH_IBITMAP 0x0030 /* Latch for pass 5 inode bitmap proc. */
-#define PR_LATCH_BBITMAP 0x0040 /* Latch for pass 5 inode bitmap proc. */
-#define PR_LATCH_RELOC 0x0050 /* Latch for superblock relocate hint */
-#define PR_LATCH_DBLOCK 0x0060 /* Latch for pass 1b dup block headers */
-#define PR_LATCH_LOW_DTIME 0x0070 /* Latch for pass1 orphaned list refugees */
-#define PR_LATCH_TOOBIG 0x0080 /* Latch for file to big errors */
-#define PR_LATCH_OPTIMIZE_DIR 0x0090 /* Latch for optimize directories */
-
-#define PR_LATCH(x) ((((x) & PR_LATCH_MASK) >> 4) - 1)
-
-/*
- * Latch group descriptor flags
- */
-#define PRL_YES 0x0001 /* Answer yes */
-#define PRL_NO 0x0002 /* Answer no */
-#define PRL_LATCHED 0x0004 /* The latch group is latched */
-#define PRL_SUPPRESS 0x0008 /* Suppress all latch group questions */
-
-#define PRL_VARIABLE 0x000f /* All the flags that need to be reset */
-
-/*
- * Pre-Pass 1 errors
- */
-
-#define PR_0_BB_NOT_GROUP 0x000001 /* Block bitmap not in group */
-#define PR_0_IB_NOT_GROUP 0x000002 /* Inode bitmap not in group */
-#define PR_0_ITABLE_NOT_GROUP 0x000003 /* Inode table not in group */
-#define PR_0_SB_CORRUPT 0x000004 /* Superblock corrupt */
-#define PR_0_FS_SIZE_WRONG 0x000005 /* Filesystem size is wrong */
-#define PR_0_NO_FRAGMENTS 0x000006 /* Fragments not supported */
-#define PR_0_BLOCKS_PER_GROUP 0x000007 /* Bad blocks_per_group */
-#define PR_0_FIRST_DATA_BLOCK 0x000008 /* Bad first_data_block */
-#define PR_0_ADD_UUID 0x000009 /* Adding UUID to filesystem */
-#define PR_0_RELOCATE_HINT 0x00000A /* Relocate hint */
-#define PR_0_MISC_CORRUPT_SUPER 0x00000B /* Miscellaneous superblock corruption */
-#define PR_0_GETSIZE_ERROR 0x00000C /* Error determing physical device size of filesystem */
-#define PR_0_INODE_COUNT_WRONG 0x00000D /* Inode count in the superblock incorrect */
-#define PR_0_HURD_CLEAR_FILETYPE 0x00000E /* The Hurd does not support the filetype feature */
-#define PR_0_JOURNAL_BAD_INODE 0x00000F /* The Hurd does not support the filetype feature */
-#define PR_0_JOURNAL_UNSUPP_MULTIFS 0x000010 /* The external journal has multiple filesystems (which we can't handle yet) */
-#define PR_0_CANT_FIND_JOURNAL 0x000011 /* Can't find external journal */
-#define PR_0_EXT_JOURNAL_BAD_SUPER 0x000012/* External journal has bad superblock */
-#define PR_0_JOURNAL_BAD_UUID 0x000013 /* Superblock has a bad journal UUID */
-#define PR_0_JOURNAL_UNSUPP_SUPER 0x000014 /* Journal has an unknown superblock type */
-#define PR_0_JOURNAL_BAD_SUPER 0x000015 /* Journal superblock is corrupt */
-#define PR_0_JOURNAL_HAS_JOURNAL 0x000016 /* Journal superblock is corrupt */
-#define PR_0_JOURNAL_RECOVER_SET 0x000017 /* Superblock has recovery flag set but no journal */
-#define PR_0_JOURNAL_RECOVERY_CLEAR 0x000018 /* Journal has data, but recovery flag is clear */
-#define PR_0_JOURNAL_RESET_JOURNAL 0x000019 /* Ask if we should clear the journal */
-#define PR_0_FS_REV_LEVEL 0x00001A /* Filesystem revision is 0, but feature flags are set */
-#define PR_0_ORPHAN_CLEAR_INODE 0x000020 /* Clearing orphan inode */
-#define PR_0_ORPHAN_ILLEGAL_BLOCK_NUM 0x000021 /* Illegal block found in orphaned inode */
-#define PR_0_ORPHAN_ALREADY_CLEARED_BLOCK 0x000022 /* Already cleared block found in orphaned inode */
-#define PR_0_ORPHAN_ILLEGAL_HEAD_INODE 0x000023 /* Illegal orphan inode in superblock */
-#define PR_0_ORPHAN_ILLEGAL_INODE 0x000024 /* Illegal inode in orphaned inode list */
-#define PR_0_JOURNAL_UNSUPP_ROCOMPAT 0x000025 /* Journal has unsupported read-only feature - abort */
-#define PR_0_JOURNAL_UNSUPP_INCOMPAT 0x000026 /* Journal has unsupported incompatible feature - abort */
-#define PR_0_JOURNAL_UNSUPP_VERSION 0x000027 /* Journal has unsupported version number */
-#define PR_0_MOVE_JOURNAL 0x000028 /* Moving journal to hidden file */
-#define PR_0_ERR_MOVE_JOURNAL 0x000029 /* Error moving journal */
-#define PR_0_CLEAR_V2_JOURNAL 0x00002A /* Clearing V2 journal superblock */
-#define PR_0_JOURNAL_RUN 0x00002B /* Run journal anyway */
-#define PR_0_JOURNAL_RUN_DEFAULT 0x00002C /* Run journal anyway by default */
-#define PR_0_BACKUP_JNL 0x00002D /* Backup journal inode blocks */
-#define PR_0_NONZERO_RESERVED_GDT_BLOCKS 0x00002E /* Reserved blocks w/o resize_inode */
-#define PR_0_CLEAR_RESIZE_INODE 0x00002F /* Resize_inode not enabled, but resize inode is non-zero */
-#define PR_0_RESIZE_INODE_INVALID 0x000030 /* Resize inode invalid */
-
-/*
- * Pass 1 errors
- */
-
-#define PR_1_PASS_HEADER 0x010000 /* Pass 1: Checking inodes, blocks, and sizes */
-#define PR_1_ROOT_NO_DIR 0x010001 /* Root directory is not an inode */
-#define PR_1_ROOT_DTIME 0x010002 /* Root directory has dtime set */
-#define PR_1_RESERVED_BAD_MODE 0x010003 /* Reserved inode has bad mode */
-#define PR_1_ZERO_DTIME 0x010004 /* Deleted inode has zero dtime */
-#define PR_1_SET_DTIME 0x010005 /* Inode in use, but dtime set */
-#define PR_1_ZERO_LENGTH_DIR 0x010006 /* Zero-length directory */
-#define PR_1_BB_CONFLICT 0x010007 /* Block bitmap conflicts with some other fs block */
-#define PR_1_IB_CONFLICT 0x010008 /* Inode bitmap conflicts with some other fs block */
-#define PR_1_ITABLE_CONFLICT 0x010009 /* Inode table conflicts with some other fs block */
-#define PR_1_BB_BAD_BLOCK 0x01000A /* Block bitmap is on a bad block */
-#define PR_1_IB_BAD_BLOCK 0x01000B /* Inode bitmap is on a bad block */
-#define PR_1_BAD_I_SIZE 0x01000C /* Inode has incorrect i_size */
-#define PR_1_BAD_I_BLOCKS 0x01000D /* Inode has incorrect i_blocks */
-#define PR_1_ILLEGAL_BLOCK_NUM 0x01000E /* Illegal block number in inode */
-#define PR_1_BLOCK_OVERLAPS_METADATA 0x01000F /* Block number overlaps fs metadata */
-#define PR_1_INODE_BLOCK_LATCH 0x010010 /* Inode has illegal blocks (latch question) */
-#define PR_1_TOO_MANY_BAD_BLOCKS 0x010011 /* Too many bad blocks in inode */
-#define PR_1_BB_ILLEGAL_BLOCK_NUM 0x010012 /* Illegal block number in bad block inode */
-#define PR_1_INODE_BBLOCK_LATCH 0x010013 /* Bad block inode has illegal blocks (latch question) */
-#define PR_1_DUP_BLOCKS_PREENSTOP 0x010014 /* Duplicate or bad blocks in use! */
-#define PR_1_BBINODE_BAD_METABLOCK 0x010015 /* Bad block used as bad block indirect block */
-#define PR_1_BBINODE_BAD_METABLOCK_PROMPT 0x010016 /* Inconsistency can't be fixed prompt */
-#define PR_1_BAD_PRIMARY_BLOCK 0x010017 /* Bad primary block */
-#define PR_1_BAD_PRIMARY_BLOCK_PROMPT 0x010018 /* Bad primary block prompt */
-#define PR_1_BAD_PRIMARY_SUPERBLOCK 0x010019 /* Bad primary superblock */
-#define PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR 0x01001A /* Bad primary block group descriptors */
-#define PR_1_BAD_SUPERBLOCK 0x01001B /* Bad superblock in group */
-#define PR_1_BAD_GROUP_DESCRIPTORS 0x01001C /* Bad block group descriptors in group */
-#define PR_1_PROGERR_CLAIMED_BLOCK 0x01001D /* Block claimed for no reason */
-#define PR_1_RELOC_BLOCK_ALLOCATE 0x01001E /* Error allocating blocks for relocating metadata */
-#define PR_1_RELOC_MEMORY_ALLOCATE 0x01001F /* Error allocating block buffer during relocation process */
-#define PR_1_RELOC_FROM_TO 0x010020 /* Relocating metadata group information from X to Y */
-#define PR_1_RELOC_TO 0x010021 /* Relocating metatdata group information to X */
-#define PR_1_RELOC_READ_ERR 0x010022 /* Block read error during relocation process */
-#define PR_1_RELOC_WRITE_ERR 0x010023 /* Block write error during relocation process */
-#define PR_1_ALLOCATE_IBITMAP_ERROR 0x010024 /* Error allocating inode bitmap */
-#define PR_1_ALLOCATE_BBITMAP_ERROR 0x010025 /* Error allocating block bitmap */
-#define PR_1_ALLOCATE_ICOUNT 0x010026 /* Error allocating icount structure */
-#define PR_1_ALLOCATE_DBCOUNT 0x010027 /* Error allocating dbcount */
-#define PR_1_ISCAN_ERROR 0x010028 /* Error while scanning inodes */
-#define PR_1_BLOCK_ITERATE 0x010029 /* Error while iterating over blocks */
-#define PR_1_ICOUNT_STORE 0x01002A /* Error while storing inode count information */
-#define PR_1_ADD_DBLOCK 0x01002B /* Error while storing directory block information */
-#define PR_1_READ_INODE 0x01002C /* Error while reading inode (for clearing) */
-#define PR_1_SUPPRESS_MESSAGES 0x01002D /* Suppress messages prompt */
-#define PR_1_SET_IMAGIC 0x01002F /* Imagic flag set on an inode when filesystem doesn't support it */
-#define PR_1_SET_IMMUTABLE 0x010030 /* Immutable flag set on a device or socket inode */
-#define PR_1_COMPR_SET 0x010031 /* Compression flag set on a non-compressed filesystem */
-#define PR_1_SET_NONZSIZE 0x010032 /* Non-zero size on device, fifo or socket inode */
-#define PR_1_FS_REV_LEVEL 0x010033 /* Filesystem revision is 0, but feature flags are set */
-#define PR_1_JOURNAL_INODE_NOT_CLEAR 0x010034 /* Journal inode not in use, needs clearing */
-#define PR_1_JOURNAL_BAD_MODE 0x010035 /* Journal inode has wrong mode */
-#define PR_1_LOW_DTIME 0x010036 /* Inode that was part of orphan linked list */
-#define PR_1_ORPHAN_LIST_REFUGEES 0x010037 /* Latch question which asks how to deal with low dtime inodes */
-#define PR_1_ALLOCATE_REFCOUNT 0x010038 /* Error allocating refcount structure */
-#define PR_1_READ_EA_BLOCK 0x010039 /* Error reading Extended Attribute block */
-#define PR_1_BAD_EA_BLOCK 0x01003A /* Invalid Extended Attribute block */
-#define PR_1_EXTATTR_READ_ABORT 0x01003B /* Error reading Extended Attribute block while fixing refcount -- abort */
-#define PR_1_EXTATTR_REFCOUNT 0x01003C /* Extended attribute reference count incorrect */
-#define PR_1_EXTATTR_WRITE 0x01003D /* Error writing Extended Attribute block while fixing refcount */
-#define PR_1_EA_MULTI_BLOCK 0x01003E /* Multiple EA blocks not supported */
-#define PR_1_EA_ALLOC_REGION 0x01003F /* Error allocating EA region allocation structure */
-#define PR_1_EA_ALLOC_COLLISION 0x010040 /* Error EA allocation collision */
-#define PR_1_EA_BAD_NAME 0x010041 /* Bad extended attribute name */
-#define PR_1_EA_BAD_VALUE 0x010042 /* Bad extended attribute value */
-#define PR_1_INODE_TOOBIG 0x010043 /* Inode too big (latch question) */
-#define PR_1_TOOBIG_DIR 0x010044 /* Directory too big */
-#define PR_1_TOOBIG_REG 0x010045 /* Regular file too big */
-#define PR_1_TOOBIG_SYMLINK 0x010046 /* Symlink too big */
-#define PR_1_HTREE_SET 0x010047 /* INDEX_FL flag set on a non-HTREE filesystem */
-#define PR_1_HTREE_NODIR 0x010048 /* INDEX_FL flag set on a non-directory */
-#define PR_1_HTREE_BADROOT 0x010049 /* Invalid root node in HTREE directory */
-#define PR_1_HTREE_HASHV 0x01004A /* Unsupported hash version in HTREE directory */
-#define PR_1_HTREE_INCOMPAT 0x01004B /* Incompatible flag in HTREE root node */
-#define PR_1_HTREE_DEPTH 0x01004C /* HTREE too deep */
-#define PR_1_BB_FS_BLOCK 0x01004D /* Bad block has indirect block that conflicts with filesystem block */
-#define PR_1_RESIZE_INODE_CREATE 0x01004E /* Resize inode failed */
-#define PR_1_EXTRA_ISIZE 0x01004F /* inode->i_size is too long */
-#define PR_1_ATTR_NAME_LEN 0x010050 /* attribute name is too long */
-#define PR_1_ATTR_VALUE_OFFSET 0x010051 /* wrong EA value offset */
-#define PR_1_ATTR_VALUE_BLOCK 0x010052 /* wrong EA blocknumber */
-#define PR_1_ATTR_VALUE_SIZE 0x010053 /* wrong EA value size */
-#define PR_1_ATTR_HASH 0x010054 /* wrong EA hash value */
-
-/*
- * Pass 1b errors
- */
-
-#define PR_1B_PASS_HEADER 0x011000 /* Pass 1B: Rescan for duplicate/bad blocks */
-#define PR_1B_DUP_BLOCK_HEADER 0x011001 /* Duplicate/bad block(s) header */
-#define PR_1B_DUP_BLOCK 0x011002 /* Duplicate/bad block(s) in inode */
-#define PR_1B_DUP_BLOCK_END 0x011003 /* Duplicate/bad block(s) end */
-#define PR_1B_ISCAN_ERROR 0x011004 /* Error while scanning inodes */
-#define PR_1B_ALLOCATE_IBITMAP_ERROR 0x011005 /* Error allocating inode bitmap */
-#define PR_1B_BLOCK_ITERATE 0x0110006 /* Error while iterating over blocks */
-#define PR_1B_ADJ_EA_REFCOUNT 0x0110007 /* Error adjusting EA refcount */
-#define PR_1C_PASS_HEADER 0x012000 /* Pass 1C: Scan directories for inodes with dup blocks. */
-#define PR_1D_PASS_HEADER 0x013000 /* Pass 1D: Reconciling duplicate blocks */
-#define PR_1D_DUP_FILE 0x013001 /* File has duplicate blocks */
-#define PR_1D_DUP_FILE_LIST 0x013002 /* List of files sharing duplicate blocks */
-#define PR_1D_SHARE_METADATA 0x013003 /* File sharing blocks with filesystem metadata */
-#define PR_1D_NUM_DUP_INODES 0x013004 /* Report of how many duplicate/bad inodes */
-#define PR_1D_DUP_BLOCKS_DEALT 0x013005 /* Duplicated blocks already reassigned or cloned. */
-#define PR_1D_CLONE_QUESTION 0x013006 /* Clone duplicate/bad blocks? */
-#define PR_1D_DELETE_QUESTION 0x013007 /* Delete file? */
-#define PR_1D_CLONE_ERROR 0x013008 /* Couldn't clone file (error) */
-
-/*
- * Pass 2 errors
- */
-
-#define PR_2_PASS_HEADER 0x020000 /* Pass 2: Checking directory structure */
-#define PR_2_BAD_INODE_DOT 0x020001 /* Bad inode number for '.' */
-#define PR_2_BAD_INO 0x020002 /* Directory entry has bad inode number */
-#define PR_2_UNUSED_INODE 0x020003 /* Directory entry has deleted or unused inode */
-#define PR_2_LINK_DOT 0x020004 /* Directry entry is link to '.' */
-#define PR_2_BB_INODE 0x020005 /* Directory entry points to inode now located in a bad block */
-#define PR_2_LINK_DIR 0x020006 /* Directory entry contains a link to a directory */
-#define PR_2_LINK_ROOT 0x020007 /* Directory entry contains a link to the root directry */
-#define PR_2_BAD_NAME 0x020008 /* Directory entry has illegal characters in its name */
-#define PR_2_MISSING_DOT 0x020009 /* Missing '.' in directory inode */
-#define PR_2_MISSING_DOT_DOT 0x02000A /* Missing '..' in directory inode */
-#define PR_2_1ST_NOT_DOT 0x02000B /* First entry in directory inode doesn't contain '.' */
-#define PR_2_2ND_NOT_DOT_DOT 0x02000C /* Second entry in directory inode doesn't contain '..' */
-#define PR_2_FADDR_ZERO 0x02000D /* i_faddr should be zero */
-#define PR_2_FILE_ACL_ZERO 0x02000E /* i_file_acl should be zero */
-#define PR_2_DIR_ACL_ZERO 0x02000F /* i_dir_acl should be zero */
-#define PR_2_FRAG_ZERO 0x020010 /* i_frag should be zero */
-#define PR_2_FSIZE_ZERO 0x020011 /* i_fsize should be zero */
-#define PR_2_BAD_MODE 0x020012 /* inode has bad mode */
-#define PR_2_DIR_CORRUPTED 0x020013 /* directory corrupted */
-#define PR_2_FILENAME_LONG 0x020014 /* filename too long */
-#define PR_2_DIRECTORY_HOLE 0x020015 /* Directory inode has a missing block (hole) */
-#define PR_2_DOT_NULL_TERM 0x020016 /* '.' is not NULL terminated */
-#define PR_2_DOT_DOT_NULL_TERM 0x020017 /* '..' is not NULL terminated */
-#define PR_2_BAD_CHAR_DEV 0x020018 /* Illegal character device in inode */
-#define PR_2_BAD_BLOCK_DEV 0x020019 /* Illegal block device in inode */
-#define PR_2_DUP_DOT 0x02001A /* Duplicate '.' entry */
-#define PR_2_DUP_DOT_DOT 0x02001B /* Duplicate '..' entry */
-#define PR_2_NO_DIRINFO 0x02001C /* Internal error: couldn't find dir_info */
-#define PR_2_FINAL_RECLEN 0x02001D /* Final rec_len is wrong */
-#define PR_2_ALLOCATE_ICOUNT 0x02001E /* Error allocating icount structure */
-#define PR_2_DBLIST_ITERATE 0x02001F /* Error iterating over directory blocks */
-#define PR_2_READ_DIRBLOCK 0x020020 /* Error reading directory block */
-#define PR_2_WRITE_DIRBLOCK 0x020021 /* Error writing directory block */
-#define PR_2_ALLOC_DIRBOCK 0x020022 /* Error allocating new directory block */
-#define PR_2_DEALLOC_INODE 0x020023 /* Error deallocating inode */
-#define PR_2_SPLIT_DOT 0x020024 /* Directory entry for '.' is big. Split? */
-#define PR_2_BAD_FIFO 0x020025 /* Illegal FIFO */
-#define PR_2_BAD_SOCKET 0x020026 /* Illegal socket */
-#define PR_2_SET_FILETYPE 0x020027 /* Directory filetype not set */
-#define PR_2_BAD_FILETYPE 0x020028 /* Directory filetype incorrect */
-#define PR_2_CLEAR_FILETYPE 0x020029 /* Directory filetype set when it shouldn't be */
-#define PR_2_NULL_NAME 0x020030 /* Directory filename can't be zero-length */
-#define PR_2_INVALID_SYMLINK 0x020031 /* Invalid symlink */
-#define PR_2_FILE_ACL_BAD 0x020032 /* i_file_acl (extended attribute) is bad */
-#define PR_2_FEATURE_LARGE_FILES 0x020033 /* Filesystem contains large files, but has no such flag in sb */
-#define PR_2_HTREE_NOTREF 0x020034 /* Node in HTREE directory not referenced */
-#define PR_2_HTREE_DUPREF 0x020035 /* Node in HTREE directory referenced twice */
-#define PR_2_HTREE_MIN_HASH 0x020036 /* Node in HTREE directory has bad min hash */
-#define PR_2_HTREE_MAX_HASH 0x020037 /* Node in HTREE directory has bad max hash */
-#define PR_2_HTREE_CLEAR 0x020038 /* Clear invalid HTREE directory */
-#define PR_2_HTREE_BADBLK 0x02003A /* Bad block in htree interior node */
-#define PR_2_ADJ_EA_REFCOUNT 0x02003B /* Error adjusting EA refcount */
-#define PR_2_HTREE_BAD_ROOT 0x02003C /* Invalid HTREE root node */
-#define PR_2_HTREE_BAD_LIMIT 0x02003D /* Invalid HTREE limit */
-#define PR_2_HTREE_BAD_COUNT 0x02003E /* Invalid HTREE count */
-#define PR_2_HTREE_HASH_ORDER 0x02003F /* HTREE interior node has out-of-order hashes in table */
-#define PR_2_HTREE_BAD_DEPTH 0x020040 /* Node in HTREE directory has bad depth */
-#define PR_2_DUPLICATE_DIRENT 0x020041 /* Duplicate directory entry found */
-#define PR_2_NON_UNIQUE_FILE 0x020042 /* Non-unique filename found */
-#define PR_2_REPORT_DUP_DIRENT 0x020043 /* Duplicate directory entry found */
-
-/*
- * Pass 3 errors
- */
-
-#define PR_3_PASS_HEADER 0x030000 /* Pass 3: Checking directory connectivity */
-#define PR_3_NO_ROOT_INODE 0x030001 /* Root inode not allocated */
-#define PR_3_EXPAND_LF_DIR 0x030002 /* No room in lost+found */
-#define PR_3_UNCONNECTED_DIR 0x030003 /* Unconnected directory inode */
-#define PR_3_NO_LF_DIR 0x030004 /* /lost+found not found */
-#define PR_3_BAD_DOT_DOT 0x030005 /* .. entry is incorrect */
-#define PR_3_NO_LPF 0x030006 /* Bad or non-existent /lost+found. Cannot reconnect */
-#define PR_3_CANT_EXPAND_LPF 0x030007 /* Could not expand /lost+found */
-#define PR_3_CANT_RECONNECT 0x030008 /* Could not reconnect inode */
-#define PR_3_ERR_FIND_LPF 0x030009 /* Error while trying to find /lost+found */
-#define PR_3_ERR_LPF_NEW_BLOCK 0x03000A /* Error in ext2fs_new_block while creating /lost+found */
-#define PR_3_ERR_LPF_NEW_INODE 0x03000B /* Error in ext2fs_new_inode while creating /lost+found */
-#define PR_3_ERR_LPF_NEW_DIR_BLOCK 0x03000C /* Error in ext2fs_new_dir_block while creating /lost+found */
-#define PR_3_ERR_LPF_WRITE_BLOCK 0x03000D /* Error while writing directory block for /lost+found */
-#define PR_3_ADJUST_INODE 0x03000E /* Error while adjusting inode count */
-#define PR_3_FIX_PARENT_ERR 0x03000F /* Couldn't fix parent directory -- error */
-#define PR_3_FIX_PARENT_NOFIND 0x030010 /* Couldn't fix parent directory -- couldn't find it */
-#define PR_3_ALLOCATE_IBITMAP_ERROR 0x030011 /* Error allocating inode bitmap */
-#define PR_3_CREATE_ROOT_ERROR 0x030012 /* Error creating root directory */
-#define PR_3_CREATE_LPF_ERROR 0x030013 /* Error creating lost and found directory */
-#define PR_3_ROOT_NOT_DIR_ABORT 0x030014 /* Root inode is not directory; aborting */
-#define PR_3_NO_ROOT_INODE_ABORT 0x030015 /* Cannot proceed without a root inode. */
-#define PR_3_NO_DIRINFO 0x030016 /* Internal error: couldn't find dir_info */
-#define PR_3_LPF_NOTDIR 0x030017 /* Lost+found is not a directory */
-
-/*
- * Pass 3a --- rehashing diretories
- */
-#define PR_3A_PASS_HEADER 0x031000 /* Pass 3a: Reindexing directories */
-#define PR_3A_OPTIMIZE_ITER 0x031001 /* Error iterating over directories */
-#define PR_3A_OPTIMIZE_DIR_ERR 0x031002 /* Error rehash directory */
-#define PR_3A_OPTIMIZE_DIR_HEADER 0x031003 /* Rehashing dir header */
-#define PR_3A_OPTIMIZE_DIR 0x031004 /* Rehashing directory %d */
-#define PR_3A_OPTIMIZE_DIR_END 0x031005 /* Rehashing dir end */
-
-/*
- * Pass 4 errors
- */
-
-#define PR_4_PASS_HEADER 0x040000 /* Pass 4: Checking reference counts */
-#define PR_4_ZERO_LEN_INODE 0x040001 /* Unattached zero-length inode */
-#define PR_4_UNATTACHED_INODE 0x040002 /* Unattached inode */
-#define PR_4_BAD_REF_COUNT 0x040003 /* Inode ref count wrong */
-#define PR_4_INCONSISTENT_COUNT 0x040004 /* Inconsistent inode count information cached */
-
-/*
- * Pass 5 errors
- */
-
-#define PR_5_PASS_HEADER 0x050000 /* Pass 5: Checking group summary information */
-#define PR_5_INODE_BMAP_PADDING 0x050001 /* Padding at end of inode bitmap is not set. */
-#define PR_5_BLOCK_BMAP_PADDING 0x050002 /* Padding at end of block bitmap is not set. */
-#define PR_5_BLOCK_BITMAP_HEADER 0x050003 /* Block bitmap differences header */
-#define PR_5_BLOCK_UNUSED 0x050004 /* Block not used, but marked in bitmap */
-#define PR_5_BLOCK_USED 0x050005 /* Block used, but not marked used in bitmap */
-#define PR_5_BLOCK_BITMAP_END 0x050006 /* Block bitmap differences end */
-#define PR_5_INODE_BITMAP_HEADER 0x050007 /* Inode bitmap differences header */
-#define PR_5_INODE_UNUSED 0x050008 /* Inode not used, but marked in bitmap */
-#define PR_5_INODE_USED 0x050009 /* Inode used, but not marked used in bitmap */
-#define PR_5_INODE_BITMAP_END 0x05000A /* Inode bitmap differences end */
-#define PR_5_FREE_INODE_COUNT_GROUP 0x05000B /* Free inodes count for group wrong */
-#define PR_5_FREE_DIR_COUNT_GROUP 0x05000C /* Directories count for group wrong */
-#define PR_5_FREE_INODE_COUNT 0x05000D /* Free inodes count wrong */
-#define PR_5_FREE_BLOCK_COUNT_GROUP 0x05000E /* Free blocks count for group wrong */
-#define PR_5_FREE_BLOCK_COUNT 0x05000F /* Free blocks count wrong */
-#define PR_5_BMAP_ENDPOINTS 0x050010 /* Programming error: bitmap endpoints don't match */
-#define PR_5_FUDGE_BITMAP_ERROR 0x050011 /* Internal error: fudging end of bitmap */
-#define PR_5_COPY_IBITMAP_ERROR 0x050012 /* Error copying in replacement inode bitmap */
-#define PR_5_COPY_BBITMAP_ERROR 0x050013 /* Error copying in replacement block bitmap */
-#define PR_5_BLOCK_RANGE_UNUSED 0x050014 /* Block range not used, but marked in bitmap */
-#define PR_5_BLOCK_RANGE_USED 0x050015 /* Block range used, but not marked used in bitmap */
-#define PR_5_INODE_RANGE_UNUSED 0x050016 /* Inode range not used, but marked in bitmap */
-#define PR_5_INODE_RANGE_USED 0x050017 /* Inode rangeused, but not marked used in bitmap */
-
-
-/*
- * The directory information structure; stores directory information
- * collected in earlier passes, to avoid disk i/o in fetching the
- * directory information.
- */
-struct dir_info {
- ext2_ino_t ino; /* Inode number */
- ext2_ino_t dotdot; /* Parent according to '..' */
- ext2_ino_t parent; /* Parent according to treewalk */
-};
-
-
-
-/*
- * The indexed directory information structure; stores information for
- * directories which contain a hash tree index.
- */
-struct dx_dir_info {
- ext2_ino_t ino; /* Inode number */
- int numblocks; /* number of blocks */
- int hashversion;
- short depth; /* depth of tree */
- struct dx_dirblock_info *dx_block; /* Array of size numblocks */
-};
-
-/*
- * Define the extended attribute refcount structure
- */
-typedef struct ea_refcount *ext2_refcount_t;
-
-struct e2fsck_struct {
- ext2_filsys fs;
- const char *program_name;
- char *filesystem_name;
- char *device_name;
- char *io_options;
- int flags; /* E2fsck internal flags */
- int options;
- blk_t use_superblock; /* sb requested by user */
- blk_t superblock; /* sb used to open fs */
- int blocksize; /* blocksize */
- blk_t num_blocks; /* Total number of blocks */
- int mount_flags;
-
- jmp_buf abort_loc;
-
- unsigned long abort_code;
-
- int (*progress)(e2fsck_t ctx, int pass, unsigned long cur,
- unsigned long max);
-
- ext2fs_inode_bitmap inode_used_map; /* Inodes which are in use */
- ext2fs_inode_bitmap inode_bad_map; /* Inodes which are bad somehow */
- ext2fs_inode_bitmap inode_dir_map; /* Inodes which are directories */
- ext2fs_inode_bitmap inode_imagic_map; /* AFS inodes */
- ext2fs_inode_bitmap inode_reg_map; /* Inodes which are regular files*/
-
- ext2fs_block_bitmap block_found_map; /* Blocks which are in use */
- ext2fs_block_bitmap block_dup_map; /* Blks referenced more than once */
- ext2fs_block_bitmap block_ea_map; /* Blocks which are used by EA's */
-
- /*
- * Inode count arrays
- */
- ext2_icount_t inode_count;
- ext2_icount_t inode_link_info;
-
- ext2_refcount_t refcount;
- ext2_refcount_t refcount_extra;
-
- /*
- * Array of flags indicating whether an inode bitmap, block
- * bitmap, or inode table is invalid
- */
- int *invalid_inode_bitmap_flag;
- int *invalid_block_bitmap_flag;
- int *invalid_inode_table_flag;
- int invalid_bitmaps; /* There are invalid bitmaps/itable */
-
- /*
- * Block buffer
- */
- char *block_buf;
-
- /*
- * For pass1_check_directory and pass1_get_blocks
- */
- ext2_ino_t stashed_ino;
- struct ext2_inode *stashed_inode;
-
- /*
- * Location of the lost and found directory
- */
- ext2_ino_t lost_and_found;
- int bad_lost_and_found;
-
- /*
- * Directory information
- */
- int dir_info_count;
- int dir_info_size;
- struct dir_info *dir_info;
-
- /*
- * Indexed directory information
- */
- int dx_dir_info_count;
- int dx_dir_info_size;
- struct dx_dir_info *dx_dir_info;
-
- /*
- * Directories to hash
- */
- ext2_u32_list dirs_to_hash;
-
- /*
- * Tuning parameters
- */
- int process_inode_size;
- int inode_buffer_blocks;
-
- /*
- * ext3 journal support
- */
- io_channel journal_io;
- char *journal_name;
-
- /*
- * How we display the progress update (for unix)
- */
- int progress_fd;
- int progress_pos;
- int progress_last_percent;
- unsigned int progress_last_time;
- int interactive; /* Are we connected directly to a tty? */
- char start_meta[2], stop_meta[2];
-
- /* File counts */
- int fs_directory_count;
- int fs_regular_count;
- int fs_blockdev_count;
- int fs_chardev_count;
- int fs_links_count;
- int fs_symlinks_count;
- int fs_fast_symlinks_count;
- int fs_fifo_count;
- int fs_total_count;
- int fs_sockets_count;
- int fs_ind_count;
- int fs_dind_count;
- int fs_tind_count;
- int fs_fragmented;
- int large_files;
- int fs_ext_attr_inodes;
- int fs_ext_attr_blocks;
-
- int ext_attr_ver;
-
- /*
- * For the use of callers of the e2fsck functions; not used by
- * e2fsck functions themselves.
- */
- void *priv_data;
-};
-
-
-#define tid_gt(x, y) ((x - y) > 0)
-
-static inline int tid_geq(tid_t x, tid_t y)
-{
- int difference = (x - y);
- return (difference >= 0);
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/Kbuild.src b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/Kbuild.src
deleted file mode 100644
index 01ac720b94..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/Kbuild.src
+++ /dev/null
@@ -1,18 +0,0 @@
-# Makefile for busybox
-#
-# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
-#
-# Licensed under GPLv2, see file LICENSE in this source tree.
-
-NEEDED-$(CONFIG_CHATTR) = y
-NEEDED-$(CONFIG_LSATTR) = y
-NEEDED-$(CONFIG_MKE2FS) = y
-NEEDED-$(CONFIG_TUNE2FS) = y
-
-lib-y:=
-
-INSERT
-
-lib-$(NEEDED-y) += mntopts.o \
- feature.o ls.o pe.o ostype.o ps.o hashstr.o \
- parse_num.o
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/e2p.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/e2p.h
deleted file mode 100644
index 2abb92c8f3..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/e2p.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* vi: set sw=4 ts=4: */
-#include "libbb.h"
-#include <sys/types.h> /* Needed by dirent.h on netbsd */
-#include <stdio.h>
-#include <dirent.h>
-
-#include "../ext2fs/ext2_fs.h"
-
-#define E2P_FEATURE_COMPAT 0
-#define E2P_FEATURE_INCOMPAT 1
-#define E2P_FEATURE_RO_INCOMPAT 2
-#ifndef EXT3_FEATURE_INCOMPAT_EXTENTS
-#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040
-#endif
-
-/* `options' for print_e2flags() */
-
-#define PFOPT_LONG 1 /* Must be 1 for compatibility with `int long_format'. */
-
-
-/*void list_super(struct ext2_super_block * s);*/
-void list_super2(struct ext2_super_block * s, FILE *f);
-#define list_super(s) list_super2(s, stdout)
-void print_fs_errors (FILE *f, unsigned short errors);
-void print_fs_state (FILE *f, unsigned short state);
-
-const char *e2p_feature2string(int compat, unsigned int mask);
-int e2p_string2feature(char *string, int *compat, unsigned int *mask);
-int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array);
-
-const char *e2p_hash2string(int num);
-int e2p_string2hash(char *string);
-
-const char *e2p_mntopt2string(unsigned int mask);
-int e2p_string2mntopt(char *string, unsigned int *mask);
-int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok);
-
-unsigned long parse_num_blocks(const char *arg, int log_block_size);
-
-char *e2p_os2string(int os_type);
-int e2p_string2os(char *str);
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/feature.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/feature.c
deleted file mode 100644
index 2102ed8e76..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/feature.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * feature.c --- convert between features and strings
- *
- * Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu>
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-
-#include "e2p.h"
-
-struct feature {
- int compat;
- unsigned int mask;
- const char *string;
-};
-
-static const struct feature feature_list[] = {
- { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_PREALLOC,
- "dir_prealloc" },
- { E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL,
- "has_journal" },
- { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_IMAGIC_INODES,
- "imagic_inodes" },
- { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_EXT_ATTR,
- "ext_attr" },
- { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX,
- "dir_index" },
- { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_RESIZE_INO,
- "resize_inode" },
- { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER,
- "sparse_super" },
- { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_LARGE_FILE,
- "large_file" },
- { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_COMPRESSION,
- "compression" },
- { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_FILETYPE,
- "filetype" },
- { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_RECOVER,
- "needs_recovery" },
- { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV,
- "journal_dev" },
- { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS,
- "extents" },
- { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_META_BG,
- "meta_bg" },
- { 0, 0, 0 },
-};
-
-const char *e2p_feature2string(int compat, unsigned int mask)
-{
- const struct feature *f;
- static char buf[20];
- char fchar;
- int fnum;
-
- for (f = feature_list; f->string; f++) {
- if ((compat == f->compat) &&
- (mask == f->mask))
- return f->string;
- }
- switch (compat) {
- case E2P_FEATURE_COMPAT:
- fchar = 'C';
- break;
- case E2P_FEATURE_INCOMPAT:
- fchar = 'I';
- break;
- case E2P_FEATURE_RO_INCOMPAT:
- fchar = 'R';
- break;
- default:
- fchar = '?';
- break;
- }
- for (fnum = 0; mask >>= 1; fnum++);
- sprintf(buf, "FEATURE_%c%d", fchar, fnum);
- return buf;
-}
-
-int e2p_string2feature(char *string, int *compat_type, unsigned int *mask)
-{
- const struct feature *f;
- char *eptr;
- int num;
-
- for (f = feature_list; f->string; f++) {
- if (!strcasecmp(string, f->string)) {
- *compat_type = f->compat;
- *mask = f->mask;
- return 0;
- }
- }
- if (strncasecmp(string, "FEATURE_", 8))
- return 1;
-
- switch (string[8]) {
- case 'c':
- case 'C':
- *compat_type = E2P_FEATURE_COMPAT;
- break;
- case 'i':
- case 'I':
- *compat_type = E2P_FEATURE_INCOMPAT;
- break;
- case 'r':
- case 'R':
- *compat_type = E2P_FEATURE_RO_INCOMPAT;
- break;
- default:
- return 1;
- }
- if (string[9] == 0)
- return 1;
- num = strtol(string+9, &eptr, 10);
- if (num > 32 || num < 0)
- return 1;
- if (*eptr)
- return 1;
- *mask = 1 << num;
- return 0;
-}
-
-static inline char *skip_over_blanks(char *cp)
-{
- while (*cp && isspace(*cp))
- cp++;
- return cp;
-}
-
-static inline char *skip_over_word(char *cp)
-{
- while (*cp && !isspace(*cp) && *cp != ',')
- cp++;
- return cp;
-}
-
-/*
- * Edit a feature set array as requested by the user. The ok_array,
- * if set, allows the application to limit what features the user is
- * allowed to set or clear using this function.
- */
-int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array)
-{
- char *cp, *buf, *next;
- int neg;
- unsigned int mask;
- int compat_type;
-
- buf = xstrdup(str);
- cp = buf;
- while (cp && *cp) {
- neg = 0;
- cp = skip_over_blanks(cp);
- next = skip_over_word(cp);
- if (*next == 0)
- next = 0;
- else
- *next = 0;
- switch (*cp) {
- case '-':
- case '^':
- neg++;
- case '+':
- cp++;
- break;
- }
- if (e2p_string2feature(cp, &compat_type, &mask))
- return 1;
- if (ok_array && !(ok_array[compat_type] & mask))
- return 1;
- if (neg)
- compat_array[compat_type] &= ~mask;
- else
- compat_array[compat_type] |= mask;
- cp = next ? next+1 : 0;
- }
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/fgetsetflags.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/fgetsetflags.c
deleted file mode 100644
index 008b798504..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/fgetsetflags.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * fgetflags.c - Get a file flags on an ext2 file system
- * fsetflags.c - Set a file flags on an ext2 file system
- *
- * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
- * Laboratoire MASI, Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- */
-
-/*
- * History:
- * 93/10/30 - Creation
- */
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef HAVE_EXT2_IOCTLS
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#endif
-
-#include "e2p.h"
-
-#ifdef O_LARGEFILE
-#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
-#else
-#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
-#endif
-
-int fgetsetflags (const char * name, unsigned long * get_flags, unsigned long set_flags)
-{
-#ifdef HAVE_EXT2_IOCTLS
- struct stat buf;
- int fd, r, f, save_errno = 0;
-
- if (!stat(name, &buf) &&
- !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) {
- goto notsupp;
- }
- fd = open (name, OPEN_FLAGS);
- if (fd == -1)
- return -1;
- if (!get_flags) {
- f = (int) set_flags;
- r = ioctl (fd, EXT2_IOC_SETFLAGS, &f);
- } else {
- r = ioctl (fd, EXT2_IOC_GETFLAGS, &f);
- *get_flags = f;
- }
- if (r == -1)
- save_errno = errno;
- close (fd);
- if (save_errno)
- errno = save_errno;
- return r;
-notsupp:
-#endif /* HAVE_EXT2_IOCTLS */
- errno = EOPNOTSUPP;
- return -1;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/fgetsetversion.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/fgetsetversion.c
deleted file mode 100644
index 8d79054d6a..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/fgetsetversion.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * fgetversion.c - Get a file version on an ext2 file system
- * fsetversion.c - Set a file version on an ext2 file system
- *
- *
- * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
- * Laboratoire MASI, Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- */
-
-/*
- * History:
- * 93/10/30 - Creation
- */
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <sys/ioctl.h>
-
-#include "e2p.h"
-
-#ifdef O_LARGEFILE
-#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
-#else
-#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
-#endif
-
-/*
- To do fsetversion: unsigned long *ptr_version must be set to NULL.
- and unsigned long version must be set to a value
- To do fgetversion: unsigned long *ptr_version must NOT be set to NULL
- and unsigned long version is ignored.
- TITO.
-*/
-
-int fgetsetversion (const char * name, unsigned long * get_version, unsigned long set_version)
-{
-#ifdef HAVE_EXT2_IOCTLS
- int fd, r, ver, save_errno = 0;
-
- fd = open (name, OPEN_FLAGS);
- if (fd == -1)
- return -1;
- if (!get_version) {
- ver = (int) set_version;
- r = ioctl (fd, EXT2_IOC_SETVERSION, &ver);
- } else {
- r = ioctl (fd, EXT2_IOC_GETVERSION, &ver);
- *get_version = ver;
- }
- if (r == -1)
- save_errno = errno;
- close (fd);
- if (save_errno)
- errno = save_errno;
- return r;
-#else /* ! HAVE_EXT2_IOCTLS */
- errno = EOPNOTSUPP;
- return -1;
-#endif /* ! HAVE_EXT2_IOCTLS */
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/hashstr.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/hashstr.c
deleted file mode 100644
index 697ffadc37..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/hashstr.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * feature.c --- convert between features and strings
- *
- * Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu>
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-
-#include "e2p.h"
-
-struct hash {
- int num;
- const char *string;
-};
-
-static const struct hash hash_list[] = {
- { EXT2_HASH_LEGACY, "legacy" },
- { EXT2_HASH_HALF_MD4, "half_md4" },
- { EXT2_HASH_TEA, "tea" },
- { 0, 0 },
-};
-
-const char *e2p_hash2string(int num)
-{
- const struct hash *p;
- static char buf[20];
-
- for (p = hash_list; p->string; p++) {
- if (num == p->num)
- return p->string;
- }
- sprintf(buf, "HASHALG_%d", num);
- return buf;
-}
-
-/*
- * Returns the hash algorithm, or -1 on error
- */
-int e2p_string2hash(char *string)
-{
- const struct hash *p;
- char *eptr;
- int num;
-
- for (p = hash_list; p->string; p++) {
- if (!strcasecmp(string, p->string)) {
- return p->num;
- }
- }
- if (strncasecmp(string, "HASHALG_", 8))
- return -1;
-
- if (string[8] == 0)
- return -1;
- num = strtol(string+8, &eptr, 10);
- if (num > 255 || num < 0)
- return -1;
- if (*eptr)
- return -1;
- return num;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/iod.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/iod.c
deleted file mode 100644
index 23ab8d5b54..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/iod.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * iod.c - Iterate a function on each entry of a directory
- *
- * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
- * Laboratoire MASI, Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- */
-
-/*
- * History:
- * 93/10/30 - Creation
- */
-
-#include "e2p.h"
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-
-int iterate_on_dir (const char * dir_name,
- int (*func) (const char *, struct dirent *, void *),
- void * private)
-{
- DIR * dir;
- struct dirent *de, *dep;
- int max_len, len;
-
- max_len = PATH_MAX + sizeof(struct dirent);
- de = xmalloc(max_len+1);
- memset(de, 0, max_len+1);
-
- dir = opendir (dir_name);
- if (dir == NULL) {
- free(de);
- return -1;
- }
- while ((dep = readdir (dir))) {
- len = sizeof(struct dirent);
- if (len < dep->d_reclen)
- len = dep->d_reclen;
- if (len > max_len)
- len = max_len;
- memcpy(de, dep, len);
- (*func) (dir_name, de, private);
- }
- free(de);
- closedir(dir);
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/ls.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/ls.c
deleted file mode 100644
index 4a2ed5ff8d..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/ls.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * ls.c - List the contents of an ext2fs superblock
- *
- * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr>
- * Laboratoire MASI, Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * Copyright (C) 1995, 1996, 1997 Theodore Ts'o <tytso@mit.edu>
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <string.h>
-#include <grp.h>
-#include <pwd.h>
-#include <time.h>
-
-#include "e2p.h"
-#include "../e2fs_lib.h"
-
-static void print_user(unsigned short uid, FILE *f)
-{
- struct passwd *pw = getpwuid(uid);
- fprintf(f, "%u (user %s)\n", uid,
- (pw == NULL ? "unknown" : pw->pw_name));
-}
-
-static void print_group(unsigned short gid, FILE *f)
-{
- struct group *gr = getgrgid(gid);
- fprintf(f, "%u (group %s)\n", gid,
- (gr == NULL ? "unknown" : gr->gr_name));
-}
-
-#define MONTH_INT (86400 * 30)
-#define WEEK_INT (86400 * 7)
-#define DAY_INT (86400)
-#define HOUR_INT (60 * 60)
-#define MINUTE_INT (60)
-
-static const char *interval_string(unsigned int secs)
-{
- static char buf[256], tmp[80];
- int hr, min, num;
-
- buf[0] = 0;
-
- if (secs == 0)
- return "<none>";
-
- if (secs >= MONTH_INT) {
- num = secs / MONTH_INT;
- secs -= num*MONTH_INT;
- sprintf(buf, "%d month%s", num, (num>1) ? "s" : "");
- }
- if (secs >= WEEK_INT) {
- num = secs / WEEK_INT;
- secs -= num*WEEK_INT;
- sprintf(tmp, "%s%d week%s", buf[0] ? ", " : "",
- num, (num>1) ? "s" : "");
- strcat(buf, tmp);
- }
- if (secs >= DAY_INT) {
- num = secs / DAY_INT;
- secs -= num*DAY_INT;
- sprintf(tmp, "%s%d day%s", buf[0] ? ", " : "",
- num, (num>1) ? "s" : "");
- strcat(buf, tmp);
- }
- if (secs > 0) {
- hr = secs / HOUR_INT;
- secs -= hr*HOUR_INT;
- min = secs / MINUTE_INT;
- secs -= min*MINUTE_INT;
- sprintf(tmp, "%s%d:%02d:%02d", buf[0] ? ", " : "",
- hr, min, secs);
- strcat(buf, tmp);
- }
- return buf;
-}
-
-static void print_features(struct ext2_super_block * s, FILE *f)
-{
-#ifdef EXT2_DYNAMIC_REV
- int i, j, printed=0;
- __u32 *mask = &s->s_feature_compat, m;
-
- fprintf(f, "Filesystem features: ");
- for (i=0; i <3; i++,mask++) {
- for (j=0,m=1; j < 32; j++, m<<=1) {
- if (*mask & m) {
- fprintf(f, " %s", e2p_feature2string(i, m));
- printed++;
- }
- }
- }
- if (printed == 0)
- fprintf(f, " (none)");
- fprintf(f, "\n");
-#endif
-}
-
-static void print_mntopts(struct ext2_super_block * s, FILE *f)
-{
-#ifdef EXT2_DYNAMIC_REV
- int i, printed=0;
- __u32 mask = s->s_default_mount_opts, m;
-
- fprintf(f, "Default mount options: ");
- if (mask & EXT3_DEFM_JMODE) {
- fprintf(f, " %s", e2p_mntopt2string(mask & EXT3_DEFM_JMODE));
- printed++;
- }
- for (i=0,m=1; i < 32; i++, m<<=1) {
- if (m & EXT3_DEFM_JMODE)
- continue;
- if (mask & m) {
- fprintf(f, " %s", e2p_mntopt2string(m));
- printed++;
- }
- }
- if (printed == 0)
- fprintf(f, " (none)");
- fprintf(f, "\n");
-#endif
-}
-
-
-#ifndef EXT2_INODE_SIZE
-#define EXT2_INODE_SIZE(s) sizeof(struct ext2_inode)
-#endif
-
-#ifndef EXT2_GOOD_OLD_REV
-#define EXT2_GOOD_OLD_REV 0
-#endif
-
-void list_super2(struct ext2_super_block * sb, FILE *f)
-{
- int inode_blocks_per_group;
- char buf[80], uuid_buf[37], *str;
- time_t tm;
-
- inode_blocks_per_group = (((sb->s_inodes_per_group *
- EXT2_INODE_SIZE(sb)) +
- EXT2_BLOCK_SIZE(sb) - 1) /
- EXT2_BLOCK_SIZE(sb));
- if (sb->s_volume_name[0]) {
- memset(buf, 0, sizeof(buf));
- strncpy(buf, sb->s_volume_name, sizeof(sb->s_volume_name));
- } else
- strcpy(buf, "<none>");
- fprintf(f, "Filesystem volume name: %s\n", buf);
- if (sb->s_last_mounted[0]) {
- memset(buf, 0, sizeof(buf));
- strncpy(buf, sb->s_last_mounted, sizeof(sb->s_last_mounted));
- } else
- strcpy(buf, "<not available>");
- fprintf(f,
- "Last mounted on: %s\n"
- "Filesystem UUID: %s\n"
- "Filesystem magic number: 0x%04X\n"
- "Filesystem revision #: %d",
- buf, unparse_uuid(sb->s_uuid, uuid_buf), sb->s_magic, sb->s_rev_level);
- if (sb->s_rev_level == EXT2_GOOD_OLD_REV) {
- fprintf(f, " (original)\n");
-#ifdef EXT2_DYNAMIC_REV
- } else if (sb->s_rev_level == EXT2_DYNAMIC_REV) {
- fprintf(f, " (dynamic)\n");
-#endif
- } else
- fprintf(f, " (unknown)\n");
- print_features(sb, f);
- print_mntopts(sb, f);
- fprintf(f, "Filesystem state: ");
- print_fs_state (f, sb->s_state);
- fprintf(f, "\nErrors behavior: ");
- print_fs_errors(f, sb->s_errors);
- str = e2p_os2string(sb->s_creator_os);
- fprintf(f,
- "\n"
- "Filesystem OS type: %s\n"
- "Inode count: %u\n"
- "Block count: %u\n"
- "Reserved block count: %u\n"
- "Free blocks: %u\n"
- "Free inodes: %u\n"
- "First block: %u\n"
- "Block size: %u\n"
- "Fragment size: %u\n",
- str, sb->s_inodes_count, sb->s_blocks_count, sb->s_r_blocks_count,
- sb->s_free_blocks_count, sb->s_free_inodes_count,
- sb->s_first_data_block, EXT2_BLOCK_SIZE(sb), EXT2_FRAG_SIZE(sb));
- free(str);
- if (sb->s_reserved_gdt_blocks)
- fprintf(f, "Reserved GDT blocks: %u\n",
- sb->s_reserved_gdt_blocks);
- fprintf(f,
- "Blocks per group: %u\n"
- "Fragments per group: %u\n"
- "Inodes per group: %u\n"
- "Inode blocks per group: %u\n",
- sb->s_blocks_per_group, sb->s_frags_per_group,
- sb->s_inodes_per_group, inode_blocks_per_group);
- if (sb->s_first_meta_bg)
- fprintf(f, "First meta block group: %u\n",
- sb->s_first_meta_bg);
- if (sb->s_mkfs_time) {
- tm = sb->s_mkfs_time;
- fprintf(f, "Filesystem created: %s", ctime(&tm));
- }
- tm = sb->s_mtime;
- fprintf(f, "Last mount time: %s",
- sb->s_mtime ? ctime(&tm) : "n/a\n");
- tm = sb->s_wtime;
- fprintf(f,
- "Last write time: %s"
- "Mount count: %u\n"
- "Maximum mount count: %d\n",
- ctime(&tm), sb->s_mnt_count, sb->s_max_mnt_count);
- tm = sb->s_lastcheck;
- fprintf(f,
- "Last checked: %s"
- "Check interval: %u (%s)\n",
- ctime(&tm),
- sb->s_checkinterval, interval_string(sb->s_checkinterval));
- if (sb->s_checkinterval)
- {
- time_t next;
-
- next = sb->s_lastcheck + sb->s_checkinterval;
- fprintf(f, "Next check after: %s", ctime(&next));
- }
- fprintf(f, "Reserved blocks uid: ");
- print_user(sb->s_def_resuid, f);
- fprintf(f, "Reserved blocks gid: ");
- print_group(sb->s_def_resgid, f);
- if (sb->s_rev_level >= EXT2_DYNAMIC_REV) {
- fprintf(f,
- "First inode: %d\n"
- "Inode size: %d\n",
- sb->s_first_ino, sb->s_inode_size);
- }
- if (!uuid_is_null(sb->s_journal_uuid))
- fprintf(f, "Journal UUID: %s\n",
- unparse_uuid(sb->s_journal_uuid, uuid_buf));
- if (sb->s_journal_inum)
- fprintf(f, "Journal inode: %u\n",
- sb->s_journal_inum);
- if (sb->s_journal_dev)
- fprintf(f, "Journal device: 0x%04x\n",
- sb->s_journal_dev);
- if (sb->s_last_orphan)
- fprintf(f, "First orphan inode: %u\n",
- sb->s_last_orphan);
- if ((sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
- sb->s_def_hash_version)
- fprintf(f, "Default directory hash: %s\n",
- e2p_hash2string(sb->s_def_hash_version));
- if (!uuid_is_null(sb->s_hash_seed))
- fprintf(f, "Directory Hash Seed: %s\n",
- unparse_uuid((unsigned char *)sb->s_hash_seed, uuid_buf));
- if (sb->s_jnl_backup_type) {
- fprintf(f, "Journal backup: ");
- if (sb->s_jnl_backup_type == 1)
- fprintf(f, "inode blocks\n");
- else
- fprintf(f, "type %u\n", sb->s_jnl_backup_type);
- }
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/mntopts.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/mntopts.c
deleted file mode 100644
index 17c26c480b..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/mntopts.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * mountopts.c --- convert between default mount options and strings
- *
- * Copyright (C) 2002 Theodore Ts'o <tytso@mit.edu>
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-
-#include "e2p.h"
-
-struct mntopt {
- unsigned int mask;
- const char *string;
-};
-
-static const struct mntopt mntopt_list[] = {
- { EXT2_DEFM_DEBUG, "debug" },
- { EXT2_DEFM_BSDGROUPS, "bsdgroups" },
- { EXT2_DEFM_XATTR_USER, "user_xattr" },
- { EXT2_DEFM_ACL, "acl" },
- { EXT2_DEFM_UID16, "uid16" },
- { EXT3_DEFM_JMODE_DATA, "journal_data" },
- { EXT3_DEFM_JMODE_ORDERED, "journal_data_ordered" },
- { EXT3_DEFM_JMODE_WBACK, "journal_data_writeback" },
- { 0, 0 },
-};
-
-const char *e2p_mntopt2string(unsigned int mask)
-{
- const struct mntopt *f;
- static char buf[20];
- int fnum;
-
- for (f = mntopt_list; f->string; f++) {
- if (mask == f->mask)
- return f->string;
- }
- for (fnum = 0; mask >>= 1; fnum++);
- sprintf(buf, "MNTOPT_%d", fnum);
- return buf;
-}
-
-int e2p_string2mntopt(char *string, unsigned int *mask)
-{
- const struct mntopt *f;
- char *eptr;
- int num;
-
- for (f = mntopt_list; f->string; f++) {
- if (!strcasecmp(string, f->string)) {
- *mask = f->mask;
- return 0;
- }
- }
- if (strncasecmp(string, "MNTOPT_", 8))
- return 1;
-
- if (string[8] == 0)
- return 1;
- num = strtol(string+8, &eptr, 10);
- if (num > 32 || num < 0)
- return 1;
- if (*eptr)
- return 1;
- *mask = 1 << num;
- return 0;
-}
-
-static char *skip_over_blanks(char *cp)
-{
- while (*cp && isspace(*cp))
- cp++;
- return cp;
-}
-
-static char *skip_over_word(char *cp)
-{
- while (*cp && !isspace(*cp) && *cp != ',')
- cp++;
- return cp;
-}
-
-/*
- * Edit a mntopt set array as requested by the user. The ok
- * parameter, if non-zero, allows the application to limit what
- * mntopts the user is allowed to set or clear using this function.
- */
-int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok)
-{
- char *cp, *buf, *next;
- int neg;
- unsigned int mask;
-
- buf = xstrdup(str);
- cp = buf;
- while (cp && *cp) {
- neg = 0;
- cp = skip_over_blanks(cp);
- next = skip_over_word(cp);
- if (*next == 0)
- next = 0;
- else
- *next = 0;
- switch (*cp) {
- case '-':
- case '^':
- neg++;
- case '+':
- cp++;
- break;
- }
- if (e2p_string2mntopt(cp, &mask))
- return 1;
- if (ok && !(ok & mask))
- return 1;
- if (mask & EXT3_DEFM_JMODE)
- *mntopts &= ~EXT3_DEFM_JMODE;
- if (neg)
- *mntopts &= ~mask;
- else
- *mntopts |= mask;
- cp = next ? next+1 : 0;
- }
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/ostype.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/ostype.c
deleted file mode 100644
index 6a2f178f33..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/ostype.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * getostype.c - Get the Filesystem OS type
- *
- * Copyright (C) 2004,2005 Theodore Ts'o <tytso@mit.edu>
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- */
-
-#include "e2p.h"
-#include <string.h>
-#include <stdlib.h>
-
-static const char *const os_tab[] =
- { "Linux",
- "Hurd",
- "Masix",
- "FreeBSD",
- "Lites",
- 0 };
-
-/*
- * Convert an os_type to a string
- */
-char *e2p_os2string(int os_type)
-{
- const char *os;
- char *ret;
-
- if (os_type <= EXT2_OS_LITES)
- os = os_tab[os_type];
- else
- os = "(unknown os)";
-
- ret = xstrdup(os);
- return ret;
-}
-
-/*
- * Convert an os_type to a string
- */
-int e2p_string2os(char *str)
-{
- const char *const *cpp;
- int i = 0;
-
- for (cpp = os_tab; *cpp; cpp++, i++) {
- if (!strcasecmp(str, *cpp))
- return i;
- }
- return -1;
-}
-
-#ifdef TEST_PROGRAM
-int main(int argc, char **argv)
-{
- char *s;
- int i, os;
-
- for (i=0; i <= EXT2_OS_LITES; i++) {
- s = e2p_os2string(i);
- os = e2p_string2os(s);
- printf("%d: %s (%d)\n", i, s, os);
- if (i != os) {
- fprintf(stderr, "Failure!\n");
- exit(1);
- }
- }
- exit(0);
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/parse_num.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/parse_num.c
deleted file mode 100644
index 6db076f9cd..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/parse_num.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * parse_num.c - Parse the number of blocks
- *
- * Copyright (C) 2004,2005 Theodore Ts'o <tytso@mit.edu>
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- */
-
-#include "e2p.h"
-
-#include <stdlib.h>
-
-unsigned long parse_num_blocks(const char *arg, int log_block_size)
-{
- char *p;
- unsigned long long num;
-
- num = strtoull(arg, &p, 0);
-
- if (p[0] && p[1])
- return 0;
-
- switch (*p) { /* Using fall-through logic */
- case 'T': case 't':
- num <<= 10;
- case 'G': case 'g':
- num <<= 10;
- case 'M': case 'm':
- num <<= 10;
- case 'K': case 'k':
- num >>= log_block_size;
- break;
- case 's':
- num >>= 1;
- break;
- case '\0':
- break;
- default:
- return 0;
- }
- return num;
-}
-
-#ifdef DEBUG
-#include <unistd.h>
-#include <stdio.h>
-
-main(int argc, char **argv)
-{
- unsigned long num;
- int log_block_size = 0;
-
- if (argc != 2) {
- fprintf(stderr, "Usage: %s arg\n", argv[0]);
- exit(1);
- }
-
- num = parse_num_blocks(argv[1], log_block_size);
-
- printf("Parsed number: %lu\n", num);
- exit(0);
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/pe.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/pe.c
deleted file mode 100644
index fd96dbeea4..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/pe.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * pe.c - Print a second extended filesystem errors behavior
- *
- * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr>
- * Laboratoire MASI, Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- */
-
-/*
- * History:
- * 94/01/09 - Creation
- */
-
-#include <stdio.h>
-
-#include "e2p.h"
-
-void print_fs_errors(FILE *f, unsigned short errors)
-{
- const char *disp = NULL;
- switch (errors) {
- case EXT2_ERRORS_CONTINUE: disp = "Continue"; break;
- case EXT2_ERRORS_RO: disp = "Remount read-only"; break;
- case EXT2_ERRORS_PANIC: disp = "Panic"; break;
- default: disp = "Unknown (continue)";
- }
- fprintf(f, disp);
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/pf.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/pf.c
deleted file mode 100644
index 02cbec7e0f..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/pf.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * pf.c - Print file attributes on an ext2 file system
- *
- * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
- * Laboratoire MASI, Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- */
-
-/*
- * History:
- * 93/10/30 - Creation
- */
-
-#include <stdio.h>
-
-#include "e2p.h"
-
-struct flags_name {
- unsigned long flag;
- const char *short_name;
- const char *long_name;
-};
-
-static const struct flags_name flags_array[] = {
- { EXT2_SECRM_FL, "s", "Secure_Deletion" },
- { EXT2_UNRM_FL, "u" , "Undelete" },
- { EXT2_SYNC_FL, "S", "Synchronous_Updates" },
- { EXT2_DIRSYNC_FL, "D", "Synchronous_Directory_Updates" },
- { EXT2_IMMUTABLE_FL, "i", "Immutable" },
- { EXT2_APPEND_FL, "a", "Append_Only" },
- { EXT2_NODUMP_FL, "d", "No_Dump" },
- { EXT2_NOATIME_FL, "A", "No_Atime" },
- { EXT2_COMPR_FL, "c", "Compression_Requested" },
-#ifdef ENABLE_COMPRESSION
- { EXT2_COMPRBLK_FL, "B", "Compressed_File" },
- { EXT2_DIRTY_FL, "Z", "Compressed_Dirty_File" },
- { EXT2_NOCOMPR_FL, "X", "Compression_Raw_Access" },
- { EXT2_ECOMPR_FL, "E", "Compression_Error" },
-#endif
- { EXT3_JOURNAL_DATA_FL, "j", "Journaled_Data" },
- { EXT2_INDEX_FL, "I", "Indexed_direcctory" },
- { EXT2_NOTAIL_FL, "t", "No_Tailmerging" },
- { EXT2_TOPDIR_FL, "T", "Top_of_Directory_Hierarchies" },
- { 0, NULL, NULL }
-};
-
-void print_flags (FILE *f, unsigned long flags, unsigned options)
-{
- int long_opt = (options & PFOPT_LONG);
- const struct flags_name *fp;
- int first = 1;
-
- for (fp = flags_array; fp->flag != 0; fp++) {
- if (flags & fp->flag) {
- if (long_opt) {
- if (first)
- first = 0;
- else
- fputs(", ", f);
- fputs(fp->long_name, f);
- } else
- fputs(fp->short_name, f);
- } else {
- if (!long_opt)
- fputs("-", f);
- }
- }
- if (long_opt && first)
- fputs("---", f);
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/ps.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/ps.c
deleted file mode 100644
index a6b4099db5..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/ps.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * ps.c - Print filesystem state
- *
- * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
- * Laboratoire MASI, Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
- */
-
-/*
- * History:
- * 93/12/22 - Creation
- */
-
-#include <stdio.h>
-
-#include "e2p.h"
-
-void print_fs_state(FILE *f, unsigned short state)
-{
- fprintf(f, (state & EXT2_VALID_FS ? " clean" : " not clean"));
- if (state & EXT2_ERROR_FS)
- fprintf(f, " with errors");
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/uuid.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/uuid.c
deleted file mode 100644
index 474d64a5a4..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2p/uuid.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * uuid.c -- utility routines for manipulating UUID's.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include "../ext2fs/ext2_types.h"
-
-#include "e2p.h"
-
-struct uuid {
- __u32 time_low;
- __u16 time_mid;
- __u16 time_hi_and_version;
- __u16 clock_seq;
- __u8 node[6];
-};
-
-/* Returns 1 if the uuid is the NULL uuid */
-int e2p_is_null_uuid(void *uu)
-{
- __u8 *cp;
- int i;
-
- for (i=0, cp = uu; i < 16; i++)
- if (*cp)
- return 0;
- return 1;
-}
-
-static void e2p_unpack_uuid(void *in, struct uuid *uu)
-{
- __u8 *ptr = in;
- __u32 tmp;
-
- tmp = *ptr++;
- tmp = (tmp << 8) | *ptr++;
- tmp = (tmp << 8) | *ptr++;
- tmp = (tmp << 8) | *ptr++;
- uu->time_low = tmp;
-
- tmp = *ptr++;
- tmp = (tmp << 8) | *ptr++;
- uu->time_mid = tmp;
-
- tmp = *ptr++;
- tmp = (tmp << 8) | *ptr++;
- uu->time_hi_and_version = tmp;
-
- tmp = *ptr++;
- tmp = (tmp << 8) | *ptr++;
- uu->clock_seq = tmp;
-
- memcpy(uu->node, ptr, 6);
-}
-
-void e2p_uuid_to_str(void *uu, char *out)
-{
- struct uuid uuid;
-
- e2p_unpack_uuid(uu, &uuid);
- sprintf(out,
- "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
- uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
- uuid.node[0], uuid.node[1], uuid.node[2],
- uuid.node[3], uuid.node[4], uuid.node[5]);
-}
-
-const char *e2p_uuid2str(void *uu)
-{
- static char buf[80];
- if (e2p_is_null_uuid(uu))
- return "<none>";
- e2p_uuid_to_str(uu, buf);
- return buf;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/Kbuild.src b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/Kbuild.src
deleted file mode 100644
index 12adc6e469..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/Kbuild.src
+++ /dev/null
@@ -1,26 +0,0 @@
-# Makefile for busybox
-#
-# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
-#
-# Licensed under GPLv2, see file LICENSE in this source tree.
-
-NEEDED-$(CONFIG_E2FSCK) = y
-NEEDED-$(CONFIG_FSCK) = y
-NEEDED-$(CONFIG_MKE2FS) = y
-NEEDED-$(CONFIG_TUNE2FS) = y
-
-lib-y:=
-
-INSERT
-
-lib-$(NEEDED-y) += gen_bitmap.o bitops.o ismounted.o mkjournal.o unix_io.o \
- rw_bitmaps.o initialize.o bitmaps.o block.o \
- ind_block.o inode.o freefs.o alloc_stats.o closefs.o \
- openfs.o io_manager.o finddev.o read_bb.o alloc.o badblocks.o \
- getsize.o getsectsize.o alloc_tables.o read_bb_file.o mkdir.o \
- bb_inode.o newdir.o alloc_sb.o lookup.o dirblock.o expanddir.o \
- dir_iterate.o link.o res_gdt.o icount.o get_pathname.o dblist.o \
- dirhash.o version.o flushb.o unlink.o check_desc.o valid_blk.o \
- ext_attr.o bmap.o dblist_dir.o ext2fs_inline.o swapfs.o
-
-CFLAGS += -include $(srctree)/e2fsprogs/e2fsbb.h
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/alloc.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/alloc.c
deleted file mode 100644
index cbb63e15a5..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/alloc.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * alloc.c --- allocate new inodes, blocks for ext2fs
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- *
- */
-
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <time.h>
-#include <string.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * Right now, just search forward from the parent directory's block
- * group to find the next free inode.
- *
- * Should have a special policy for directories.
- */
-errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir,
- int mode EXT2FS_ATTR((unused)),
- ext2fs_inode_bitmap map, ext2_ino_t *ret)
-{
- ext2_ino_t dir_group = 0;
- ext2_ino_t i;
- ext2_ino_t start_inode;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!map)
- map = fs->inode_map;
- if (!map)
- return EXT2_ET_NO_INODE_BITMAP;
-
- if (dir > 0)
- dir_group = (dir - 1) / EXT2_INODES_PER_GROUP(fs->super);
-
- start_inode = (dir_group * EXT2_INODES_PER_GROUP(fs->super)) + 1;
- if (start_inode < EXT2_FIRST_INODE(fs->super))
- start_inode = EXT2_FIRST_INODE(fs->super);
- i = start_inode;
-
- do {
- if (!ext2fs_fast_test_inode_bitmap(map, i))
- break;
- i++;
- if (i > fs->super->s_inodes_count)
- i = EXT2_FIRST_INODE(fs->super);
- } while (i != start_inode);
-
- if (ext2fs_test_inode_bitmap(map, i))
- return EXT2_ET_INODE_ALLOC_FAIL;
- *ret = i;
- return 0;
-}
-
-/*
- * Stupid algorithm --- we now just search forward starting from the
- * goal. Should put in a smarter one someday....
- */
-errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
- ext2fs_block_bitmap map, blk_t *ret)
-{
- blk_t i;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!map)
- map = fs->block_map;
- if (!map)
- return EXT2_ET_NO_BLOCK_BITMAP;
- if (!goal || (goal >= fs->super->s_blocks_count))
- goal = fs->super->s_first_data_block;
- i = goal;
- do {
- if (!ext2fs_fast_test_block_bitmap(map, i)) {
- *ret = i;
- return 0;
- }
- i++;
- if (i >= fs->super->s_blocks_count)
- i = fs->super->s_first_data_block;
- } while (i != goal);
- return EXT2_ET_BLOCK_ALLOC_FAIL;
-}
-
-/*
- * This function zeros out the allocated block, and updates all of the
- * appropriate filesystem records.
- */
-errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
- char *block_buf, blk_t *ret)
-{
- errcode_t retval;
- blk_t block;
- char *buf = NULL;
-
- if (!block_buf) {
- retval = ext2fs_get_mem(fs->blocksize, &buf);
- if (retval)
- return retval;
- block_buf = buf;
- }
- memset(block_buf, 0, fs->blocksize);
-
- if (!fs->block_map) {
- retval = ext2fs_read_block_bitmap(fs);
- if (retval)
- goto fail;
- }
-
- retval = ext2fs_new_block(fs, goal, 0, &block);
- if (retval)
- goto fail;
-
- retval = io_channel_write_blk(fs->io, block, 1, block_buf);
- if (retval)
- goto fail;
-
- ext2fs_block_alloc_stats(fs, block, +1);
- *ret = block;
- return 0;
-
-fail:
- if (buf)
- ext2fs_free_mem(&buf);
- return retval;
-}
-
-errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish,
- int num, ext2fs_block_bitmap map, blk_t *ret)
-{
- blk_t b = start;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!map)
- map = fs->block_map;
- if (!map)
- return EXT2_ET_NO_BLOCK_BITMAP;
- if (!b)
- b = fs->super->s_first_data_block;
- if (!finish)
- finish = start;
- if (!num)
- num = 1;
- do {
- if (b+num-1 > fs->super->s_blocks_count)
- b = fs->super->s_first_data_block;
- if (ext2fs_fast_test_block_bitmap_range(map, b, num)) {
- *ret = b;
- return 0;
- }
- b++;
- } while (b != finish);
- return EXT2_ET_BLOCK_ALLOC_FAIL;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/alloc_sb.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/alloc_sb.c
deleted file mode 100644
index a7437c96f5..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/alloc_sb.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * alloc_sb.c --- Allocate the superblock and block group descriptors for a
- * newly initialized filesystem. Used by mke2fs when initializing a filesystem
- *
- * Copyright (C) 1994, 1995, 1996, 2003 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-int ext2fs_reserve_super_and_bgd(ext2_filsys fs,
- dgrp_t group,
- ext2fs_block_bitmap bmap)
-{
- blk_t super_blk, old_desc_blk, new_desc_blk;
- int j, old_desc_blocks, num_blocks;
-
- num_blocks = ext2fs_super_and_bgd_loc(fs, group, &super_blk,
- &old_desc_blk, &new_desc_blk, 0);
-
- if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
- old_desc_blocks = fs->super->s_first_meta_bg;
- else
- old_desc_blocks =
- fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
-
- if (super_blk || (group == 0))
- ext2fs_mark_block_bitmap(bmap, super_blk);
-
- if (old_desc_blk) {
- for (j=0; j < old_desc_blocks; j++)
- ext2fs_mark_block_bitmap(bmap, old_desc_blk + j);
- }
- if (new_desc_blk)
- ext2fs_mark_block_bitmap(bmap, new_desc_blk);
-
- return num_blocks;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/alloc_stats.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/alloc_stats.c
deleted file mode 100644
index f3ab06a237..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/alloc_stats.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * alloc_stats.c --- Update allocation statistics for ext2fs
- *
- * Copyright (C) 2001 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- *
- */
-
-#include <stdio.h>
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino,
- int inuse, int isdir)
-{
- int group = ext2fs_group_of_ino(fs, ino);
-
- if (inuse > 0)
- ext2fs_mark_inode_bitmap(fs->inode_map, ino);
- else
- ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
- fs->group_desc[group].bg_free_inodes_count -= inuse;
- if (isdir)
- fs->group_desc[group].bg_used_dirs_count += inuse;
- fs->super->s_free_inodes_count -= inuse;
- ext2fs_mark_super_dirty(fs);
- ext2fs_mark_ib_dirty(fs);
-}
-
-void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse)
-{
- ext2fs_inode_alloc_stats2(fs, ino, inuse, 0);
-}
-
-void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse)
-{
- int group = ext2fs_group_of_blk(fs, blk);
-
- if (inuse > 0)
- ext2fs_mark_block_bitmap(fs->block_map, blk);
- else
- ext2fs_unmark_block_bitmap(fs->block_map, blk);
- fs->group_desc[group].bg_free_blocks_count -= inuse;
- fs->super->s_free_blocks_count -= inuse;
- ext2fs_mark_super_dirty(fs);
- ext2fs_mark_bb_dirty(fs);
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/alloc_tables.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/alloc_tables.c
deleted file mode 100644
index 7c60e2bf5f..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/alloc_tables.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * alloc_tables.c --- Allocate tables for a newly initialized
- * filesystem. Used by mke2fs when initializing a filesystem
- *
- * Copyright (C) 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
- ext2fs_block_bitmap bmap)
-{
- errcode_t retval;
- blk_t group_blk, start_blk, last_blk, new_blk, blk;
- int j;
-
- group_blk = fs->super->s_first_data_block +
- (group * fs->super->s_blocks_per_group);
-
- last_blk = group_blk + fs->super->s_blocks_per_group;
- if (last_blk >= fs->super->s_blocks_count)
- last_blk = fs->super->s_blocks_count - 1;
-
- if (!bmap)
- bmap = fs->block_map;
-
- /*
- * Allocate the block and inode bitmaps, if necessary
- */
- if (fs->stride) {
- start_blk = group_blk + fs->inode_blocks_per_group;
- start_blk += ((fs->stride * group) %
- (last_blk - start_blk));
- if (start_blk > last_blk)
- start_blk = group_blk;
- } else
- start_blk = group_blk;
-
- if (!fs->group_desc[group].bg_block_bitmap) {
- retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
- 1, bmap, &new_blk);
- if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
- retval = ext2fs_get_free_blocks(fs, group_blk,
- last_blk, 1, bmap, &new_blk);
- if (retval)
- return retval;
- ext2fs_mark_block_bitmap(bmap, new_blk);
- fs->group_desc[group].bg_block_bitmap = new_blk;
- }
-
- if (!fs->group_desc[group].bg_inode_bitmap) {
- retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
- 1, bmap, &new_blk);
- if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
- retval = ext2fs_get_free_blocks(fs, group_blk,
- last_blk, 1, bmap, &new_blk);
- if (retval)
- return retval;
- ext2fs_mark_block_bitmap(bmap, new_blk);
- fs->group_desc[group].bg_inode_bitmap = new_blk;
- }
-
- /*
- * Allocate the inode table
- */
- if (!fs->group_desc[group].bg_inode_table) {
- retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
- fs->inode_blocks_per_group,
- bmap, &new_blk);
- if (retval)
- return retval;
- for (j=0, blk = new_blk;
- j < fs->inode_blocks_per_group;
- j++, blk++)
- ext2fs_mark_block_bitmap(bmap, blk);
- fs->group_desc[group].bg_inode_table = new_blk;
- }
-
- return 0;
-}
-
-errcode_t ext2fs_allocate_tables(ext2_filsys fs)
-{
- errcode_t retval;
- dgrp_t i;
-
- for (i = 0; i < fs->group_desc_count; i++) {
- retval = ext2fs_allocate_group_table(fs, i, fs->block_map);
- if (retval)
- return retval;
- }
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/badblocks.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/badblocks.c
deleted file mode 100644
index 6e5cc10b82..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/badblocks.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * badblocks.c --- routines to manipulate the bad block structure
- *
- * Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fsP.h"
-
-/*
- * Helper function for making a badblocks list
- */
-static errcode_t make_u32_list(int size, int num, __u32 *list,
- ext2_u32_list *ret)
-{
- ext2_u32_list bb;
- errcode_t retval;
-
- retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_list), &bb);
- if (retval)
- return retval;
- memset(bb, 0, sizeof(struct ext2_struct_u32_list));
- bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST;
- bb->size = size ? size : 10;
- bb->num = num;
- retval = ext2fs_get_mem(bb->size * sizeof(blk_t), &bb->list);
- if (!bb->list) {
- ext2fs_free_mem(&bb);
- return retval;
- }
- if (list)
- memcpy(bb->list, list, bb->size * sizeof(blk_t));
- else
- memset(bb->list, 0, bb->size * sizeof(blk_t));
- *ret = bb;
- return 0;
-}
-
-
-/*
- * This procedure creates an empty u32 list.
- */
-errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size)
-{
- return make_u32_list(size, 0, 0, ret);
-}
-
-/*
- * This procedure creates an empty badblocks list.
- */
-errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size)
-{
- return make_u32_list(size, 0, 0, (ext2_badblocks_list *) ret);
-}
-
-
-/*
- * This procedure copies a badblocks list
- */
-errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest)
-{
- errcode_t retval;
-
- retval = make_u32_list(src->size, src->num, src->list, dest);
- if (retval)
- return retval;
- (*dest)->badblocks_flags = src->badblocks_flags;
- return 0;
-}
-
-errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
- ext2_badblocks_list *dest)
-{
- return ext2fs_u32_copy((ext2_u32_list) src,
- (ext2_u32_list *) dest);
-}
-
-/*
- * This procedure frees a badblocks list.
- *
- * (note: moved to closefs.c)
- */
-
-
-/*
- * This procedure adds a block to a badblocks list.
- */
-errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk)
-{
- errcode_t retval;
- int i, j;
- unsigned long old_size;
-
- EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
-
- if (bb->num >= bb->size) {
- old_size = bb->size * sizeof(__u32);
- bb->size += 100;
- retval = ext2fs_resize_mem(old_size, bb->size * sizeof(__u32),
- &bb->list);
- if (retval) {
- bb->size -= 100;
- return retval;
- }
- }
-
- /*
- * Add special case code for appending to the end of the list
- */
- i = bb->num-1;
- if ((bb->num != 0) && (bb->list[i] == blk))
- return 0;
- if ((bb->num == 0) || (bb->list[i] < blk)) {
- bb->list[bb->num++] = blk;
- return 0;
- }
-
- j = bb->num;
- for (i=0; i < bb->num; i++) {
- if (bb->list[i] == blk)
- return 0;
- if (bb->list[i] > blk) {
- j = i;
- break;
- }
- }
- for (i=bb->num; i > j; i--)
- bb->list[i] = bb->list[i-1];
- bb->list[j] = blk;
- bb->num++;
- return 0;
-}
-
-errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk)
-{
- return ext2fs_u32_list_add((ext2_u32_list) bb, (__u32) blk);
-}
-
-/*
- * This procedure finds a particular block is on a badblocks
- * list.
- */
-int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk)
-{
- int low, high, mid;
-
- if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
- return -1;
-
- if (bb->num == 0)
- return -1;
-
- low = 0;
- high = bb->num-1;
- if (blk == bb->list[low])
- return low;
- if (blk == bb->list[high])
- return high;
-
- while (low < high) {
- mid = (low+high)/2;
- if (mid == low || mid == high)
- break;
- if (blk == bb->list[mid])
- return mid;
- if (blk < bb->list[mid])
- high = mid;
- else
- low = mid;
- }
- return -1;
-}
-
-/*
- * This procedure tests to see if a particular block is on a badblocks
- * list.
- */
-int ext2fs_u32_list_test(ext2_u32_list bb, __u32 blk)
-{
- if (ext2fs_u32_list_find(bb, blk) < 0)
- return 0;
- else
- return 1;
-}
-
-int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk)
-{
- return ext2fs_u32_list_test((ext2_u32_list) bb, (__u32) blk);
-}
-
-
-/*
- * Remove a block from the badblock list
- */
-int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk)
-{
- int remloc, i;
-
- if (bb->num == 0)
- return -1;
-
- remloc = ext2fs_u32_list_find(bb, blk);
- if (remloc < 0)
- return -1;
-
- for (i = remloc; i < bb->num - 1; i++)
- bb->list[i] = bb->list[i+1];
- bb->num--;
- return 0;
-}
-
-void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk)
-{
- ext2fs_u32_list_del(bb, blk);
-}
-
-errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb,
- ext2_u32_iterate *ret)
-{
- ext2_u32_iterate iter;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
-
- retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_iterate), &iter);
- if (retval)
- return retval;
-
- iter->magic = EXT2_ET_MAGIC_BADBLOCKS_ITERATE;
- iter->bb = bb;
- iter->ptr = 0;
- *ret = iter;
- return 0;
-}
-
-errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
- ext2_badblocks_iterate *ret)
-{
- return ext2fs_u32_list_iterate_begin((ext2_u32_list) bb,
- (ext2_u32_iterate *) ret);
-}
-
-
-int ext2fs_u32_list_iterate(ext2_u32_iterate iter, __u32 *blk)
-{
- ext2_u32_list bb;
-
- if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)
- return 0;
-
- bb = iter->bb;
-
- if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
- return 0;
-
- if (iter->ptr < bb->num) {
- *blk = bb->list[iter->ptr++];
- return 1;
- }
- *blk = 0;
- return 0;
-}
-
-int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk)
-{
- return ext2fs_u32_list_iterate((ext2_u32_iterate) iter,
- (__u32 *) blk);
-}
-
-
-void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter)
-{
- if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE))
- return;
-
- iter->bb = 0;
- ext2fs_free_mem(&iter);
-}
-
-void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter)
-{
- ext2fs_u32_list_iterate_end((ext2_u32_iterate) iter);
-}
-
-
-int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2)
-{
- EXT2_CHECK_MAGIC(bb1, EXT2_ET_MAGIC_BADBLOCKS_LIST);
- EXT2_CHECK_MAGIC(bb2, EXT2_ET_MAGIC_BADBLOCKS_LIST);
-
- if (bb1->num != bb2->num)
- return 0;
-
- if (memcmp(bb1->list, bb2->list, bb1->num * sizeof(blk_t)) != 0)
- return 0;
- return 1;
-}
-
-int ext2fs_badblocks_equal(ext2_badblocks_list bb1, ext2_badblocks_list bb2)
-{
- return ext2fs_u32_list_equal((ext2_u32_list) bb1,
- (ext2_u32_list) bb2);
-}
-
-int ext2fs_u32_list_count(ext2_u32_list bb)
-{
- return bb->num;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bb_compat.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bb_compat.c
deleted file mode 100644
index 419ac77859..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bb_compat.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * bb_compat.c --- compatibility badblocks routines
- *
- * Copyright (C) 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fsP.h"
-
-errcode_t badblocks_list_create(badblocks_list *ret, int size)
-{
- return ext2fs_badblocks_list_create(ret, size);
-}
-
-void badblocks_list_free(badblocks_list bb)
-{
- ext2fs_badblocks_list_free(bb);
-}
-
-errcode_t badblocks_list_add(badblocks_list bb, blk_t blk)
-{
- return ext2fs_badblocks_list_add(bb, blk);
-}
-
-int badblocks_list_test(badblocks_list bb, blk_t blk)
-{
- return ext2fs_badblocks_list_test(bb, blk);
-}
-
-errcode_t badblocks_list_iterate_begin(badblocks_list bb,
- badblocks_iterate *ret)
-{
- return ext2fs_badblocks_list_iterate_begin(bb, ret);
-}
-
-int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk)
-{
- return ext2fs_badblocks_list_iterate(iter, blk);
-}
-
-void badblocks_list_iterate_end(badblocks_iterate iter)
-{
- ext2fs_badblocks_list_iterate_end(iter);
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bb_inode.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bb_inode.c
deleted file mode 100644
index a967896181..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bb_inode.c
+++ /dev/null
@@ -1,262 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * bb_inode.c --- routines to update the bad block inode.
- *
- * WARNING: This routine modifies a lot of state in the filesystem; if
- * this routine returns an error, the bad block inode may be in an
- * inconsistent state.
- *
- * Copyright (C) 1994, 1995 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-struct set_badblock_record {
- ext2_badblocks_iterate bb_iter;
- int bad_block_count;
- blk_t *ind_blocks;
- int max_ind_blocks;
- int ind_blocks_size;
- int ind_blocks_ptr;
- char *block_buf;
- errcode_t err;
-};
-
-static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block, int ref_offset,
- void *priv_data);
-static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block, int ref_offset,
- void *priv_data);
-
-/*
- * Given a bad blocks bitmap, update the bad blocks inode to reflect
- * the map.
- */
-errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list)
-{
- errcode_t retval;
- struct set_badblock_record rec;
- struct ext2_inode inode;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!fs->block_map)
- return EXT2_ET_NO_BLOCK_BITMAP;
-
- rec.bad_block_count = 0;
- rec.ind_blocks_size = rec.ind_blocks_ptr = 0;
- rec.max_ind_blocks = 10;
- retval = ext2fs_get_mem(rec.max_ind_blocks * sizeof(blk_t),
- &rec.ind_blocks);
- if (retval)
- return retval;
- memset(rec.ind_blocks, 0, rec.max_ind_blocks * sizeof(blk_t));
- retval = ext2fs_get_mem(fs->blocksize, &rec.block_buf);
- if (retval)
- goto cleanup;
- memset(rec.block_buf, 0, fs->blocksize);
- rec.err = 0;
-
- /*
- * First clear the old bad blocks (while saving the indirect blocks)
- */
- retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
- BLOCK_FLAG_DEPTH_TRAVERSE, 0,
- clear_bad_block_proc, &rec);
- if (retval)
- goto cleanup;
- if (rec.err) {
- retval = rec.err;
- goto cleanup;
- }
-
- /*
- * Now set the bad blocks!
- *
- * First, mark the bad blocks as used. This prevents a bad
- * block from being used as an indirecto block for the bad
- * block inode (!).
- */
- if (bb_list) {
- retval = ext2fs_badblocks_list_iterate_begin(bb_list,
- &rec.bb_iter);
- if (retval)
- goto cleanup;
- retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
- BLOCK_FLAG_APPEND, 0,
- set_bad_block_proc, &rec);
- ext2fs_badblocks_list_iterate_end(rec.bb_iter);
- if (retval)
- goto cleanup;
- if (rec.err) {
- retval = rec.err;
- goto cleanup;
- }
- }
-
- /*
- * Update the bad block inode's mod time and block count
- * field.
- */
- retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode);
- if (retval)
- goto cleanup;
-
- inode.i_atime = inode.i_mtime = time(NULL);
- if (!inode.i_ctime)
- inode.i_ctime = time(NULL);
- inode.i_blocks = rec.bad_block_count * (fs->blocksize / 512);
- inode.i_size = rec.bad_block_count * fs->blocksize;
-
- retval = ext2fs_write_inode(fs, EXT2_BAD_INO, &inode);
- if (retval)
- goto cleanup;
-
-cleanup:
- ext2fs_free_mem(&rec.ind_blocks);
- ext2fs_free_mem(&rec.block_buf);
- return retval;
-}
-
-/*
- * Helper function for update_bb_inode()
- *
- * Clear the bad blocks in the bad block inode, while saving the
- * indirect blocks.
- */
-#ifdef __TURBOC__
-# pragma argsused
-#endif
-static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block EXT2FS_ATTR((unused)),
- int ref_offset EXT2FS_ATTR((unused)),
- void *priv_data)
-{
- struct set_badblock_record *rec = (struct set_badblock_record *)
- priv_data;
- errcode_t retval;
- unsigned long old_size;
-
- if (!*block_nr)
- return 0;
-
- /*
- * If the block number is outrageous, clear it and ignore it.
- */
- if (*block_nr >= fs->super->s_blocks_count ||
- *block_nr < fs->super->s_first_data_block) {
- *block_nr = 0;
- return BLOCK_CHANGED;
- }
-
- if (blockcnt < 0) {
- if (rec->ind_blocks_size >= rec->max_ind_blocks) {
- old_size = rec->max_ind_blocks * sizeof(blk_t);
- rec->max_ind_blocks += 10;
- retval = ext2fs_resize_mem(old_size,
- rec->max_ind_blocks * sizeof(blk_t),
- &rec->ind_blocks);
- if (retval) {
- rec->max_ind_blocks -= 10;
- rec->err = retval;
- return BLOCK_ABORT;
- }
- }
- rec->ind_blocks[rec->ind_blocks_size++] = *block_nr;
- }
-
- /*
- * Mark the block as unused, and update accounting information
- */
- ext2fs_block_alloc_stats(fs, *block_nr, -1);
-
- *block_nr = 0;
- return BLOCK_CHANGED;
-}
-
-
-/*
- * Helper function for update_bb_inode()
- *
- * Set the block list in the bad block inode, using the supplied bitmap.
- */
-#ifdef __TURBOC__
- #pragma argsused
-#endif
-static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block EXT2FS_ATTR((unused)),
- int ref_offset EXT2FS_ATTR((unused)),
- void *priv_data)
-{
- struct set_badblock_record *rec = (struct set_badblock_record *)
- priv_data;
- errcode_t retval;
- blk_t blk;
-
- if (blockcnt >= 0) {
- /*
- * Get the next bad block.
- */
- if (!ext2fs_badblocks_list_iterate(rec->bb_iter, &blk))
- return BLOCK_ABORT;
- rec->bad_block_count++;
- } else {
- /*
- * An indirect block; fetch a block from the
- * previously used indirect block list. The block
- * most be not marked as used; if so, get another one.
- * If we run out of reserved indirect blocks, allocate
- * a new one.
- */
- retry:
- if (rec->ind_blocks_ptr < rec->ind_blocks_size) {
- blk = rec->ind_blocks[rec->ind_blocks_ptr++];
- if (ext2fs_test_block_bitmap(fs->block_map, blk))
- goto retry;
- } else {
- retval = ext2fs_new_block(fs, 0, 0, &blk);
- if (retval) {
- rec->err = retval;
- return BLOCK_ABORT;
- }
- }
- retval = io_channel_write_blk(fs->io, blk, 1, rec->block_buf);
- if (retval) {
- rec->err = retval;
- return BLOCK_ABORT;
- }
- }
-
- /*
- * Update block counts
- */
- ext2fs_block_alloc_stats(fs, blk, +1);
-
- *block_nr = blk;
- return BLOCK_CHANGED;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bitmaps.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bitmaps.c
deleted file mode 100644
index 637ed27af9..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bitmaps.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * bitmaps.c --- routines to read, write, and manipulate the inode and
- * block bitmaps.
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-static errcode_t make_bitmap(__u32 start, __u32 end, __u32 real_end,
- const char *descr, char *init_map,
- ext2fs_generic_bitmap *ret)
-{
- ext2fs_generic_bitmap bitmap;
- errcode_t retval;
- size_t size;
-
- retval = ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap),
- &bitmap);
- if (retval)
- return retval;
-
- bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
- bitmap->fs = NULL;
- bitmap->start = start;
- bitmap->end = end;
- bitmap->real_end = real_end;
- bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK;
- if (descr) {
- retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description);
- if (retval) {
- ext2fs_free_mem(&bitmap);
- return retval;
- }
- strcpy(bitmap->description, descr);
- } else
- bitmap->description = 0;
-
- size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1);
- retval = ext2fs_get_mem(size, &bitmap->bitmap);
- if (retval) {
- ext2fs_free_mem(&bitmap->description);
- ext2fs_free_mem(&bitmap);
- return retval;
- }
-
- if (init_map)
- memcpy(bitmap->bitmap, init_map, size);
- else
- memset(bitmap->bitmap, 0, size);
- *ret = bitmap;
- return 0;
-}
-
-errcode_t ext2fs_allocate_generic_bitmap(__u32 start,
- __u32 end,
- __u32 real_end,
- const char *descr,
- ext2fs_generic_bitmap *ret)
-{
- return make_bitmap(start, end, real_end, descr, 0, ret);
-}
-
-errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
- ext2fs_generic_bitmap *dest)
-{
- errcode_t retval;
- ext2fs_generic_bitmap new_map;
-
- retval = make_bitmap(src->start, src->end, src->real_end,
- src->description, src->bitmap, &new_map);
- if (retval)
- return retval;
- new_map->magic = src->magic;
- new_map->fs = src->fs;
- new_map->base_error_code = src->base_error_code;
- *dest = new_map;
- return 0;
-}
-
-void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map)
-{
- __u32 i, j;
-
- for (i=map->end+1, j = i - map->start; i <= map->real_end; i++, j++)
- ext2fs_set_bit(j, map->bitmap);
-}
-
-errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs,
- const char *descr,
- ext2fs_inode_bitmap *ret)
-{
- ext2fs_inode_bitmap bitmap;
- errcode_t retval;
- __u32 start, end, real_end;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- fs->write_bitmaps = ext2fs_write_bitmaps;
-
- start = 1;
- end = fs->super->s_inodes_count;
- real_end = (EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count);
-
- retval = ext2fs_allocate_generic_bitmap(start, end, real_end,
- descr, &bitmap);
- if (retval)
- return retval;
-
- bitmap->magic = EXT2_ET_MAGIC_INODE_BITMAP;
- bitmap->fs = fs;
- bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK;
-
- *ret = bitmap;
- return 0;
-}
-
-errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
- const char *descr,
- ext2fs_block_bitmap *ret)
-{
- ext2fs_block_bitmap bitmap;
- errcode_t retval;
- __u32 start, end, real_end;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- fs->write_bitmaps = ext2fs_write_bitmaps;
-
- start = fs->super->s_first_data_block;
- end = fs->super->s_blocks_count-1;
- real_end = (EXT2_BLOCKS_PER_GROUP(fs->super)
- * fs->group_desc_count)-1 + start;
-
- retval = ext2fs_allocate_generic_bitmap(start, end, real_end,
- descr, &bitmap);
- if (retval)
- return retval;
-
- bitmap->magic = EXT2_ET_MAGIC_BLOCK_BITMAP;
- bitmap->fs = fs;
- bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK;
-
- *ret = bitmap;
- return 0;
-}
-
-errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap,
- ext2_ino_t end, ext2_ino_t *oend)
-{
- EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_INODE_BITMAP);
-
- if (end > bitmap->real_end)
- return EXT2_ET_FUDGE_INODE_BITMAP_END;
- if (oend)
- *oend = bitmap->end;
- bitmap->end = end;
- return 0;
-}
-
-errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap,
- blk_t end, blk_t *oend)
-{
- EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_BLOCK_BITMAP);
-
- if (end > bitmap->real_end)
- return EXT2_ET_FUDGE_BLOCK_BITMAP_END;
- if (oend)
- *oend = bitmap->end;
- bitmap->end = end;
- return 0;
-}
-
-void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap)
-{
- if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_INODE_BITMAP))
- return;
-
- memset(bitmap->bitmap, 0,
- (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
-}
-
-void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap)
-{
- if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_BLOCK_BITMAP))
- return;
-
- memset(bitmap->bitmap, 0,
- (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bitops.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bitops.c
deleted file mode 100644
index b4ec51ed7c..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bitops.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * bitops.c --- Bitmap frobbing code. See bitops.h for the inlined
- * routines.
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-#ifndef _EXT2_HAVE_ASM_BITOPS_
-
-/*
- * For the benefit of those who are trying to port Linux to another
- * architecture, here are some C-language equivalents. You should
- * recode these in the native assmebly language, if at all possible.
- *
- * C language equivalents written by Theodore Ts'o, 9/26/92.
- * Modified by Pete A. Zaitcev 7/14/95 to be portable to big endian
- * systems, as well as non-32 bit systems.
- */
-
-int ext2fs_set_bit(unsigned int nr,void * addr)
-{
- int mask, retval;
- unsigned char *ADDR = (unsigned char *) addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- retval = mask & *ADDR;
- *ADDR |= mask;
- return retval;
-}
-
-int ext2fs_clear_bit(unsigned int nr, void * addr)
-{
- int mask, retval;
- unsigned char *ADDR = (unsigned char *) addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- retval = mask & *ADDR;
- *ADDR &= ~mask;
- return retval;
-}
-
-int ext2fs_test_bit(unsigned int nr, const void * addr)
-{
- int mask;
- const unsigned char *ADDR = (const unsigned char *) addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- return (mask & *ADDR);
-}
-
-#endif /* !_EXT2_HAVE_ASM_BITOPS_ */
-
-void ext2fs_warn_bitmap(errcode_t errcode EXT2FS_ATTR((unused)),
- unsigned long arg,
- const char *description)
-{
-#ifndef OMIT_COM_ERR
- if (description)
- bb_error_msg("#%lu for %s", arg, description);
- else
- bb_error_msg("#%lu", arg);
-#endif
-}
-
-void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
- int code EXT2FS_ATTR((unused)), unsigned long arg)
-{
-#ifndef OMIT_COM_ERR
- if (bitmap->description)
- bb_error_msg("#%lu for %s", arg, bitmap->description);
- else
- bb_error_msg("#%lu", arg);
-#endif
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bitops.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bitops.h
deleted file mode 100644
index 7271a497bf..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bitops.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * bitops.h --- Bitmap frobbing code. The byte swapping routines are
- * also included here.
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- *
- * i386 bitops operations taken from <asm/bitops.h>, Copyright 1992,
- * Linus Torvalds.
- */
-#include <string.h>
-
-extern int ext2fs_set_bit(unsigned int nr,void * addr);
-extern int ext2fs_clear_bit(unsigned int nr, void * addr);
-extern int ext2fs_test_bit(unsigned int nr, const void * addr);
-extern __u16 ext2fs_swab16(__u16 val);
-extern __u32 ext2fs_swab32(__u32 val);
-
-#ifdef WORDS_BIGENDIAN
-#define ext2fs_cpu_to_le32(x) ext2fs_swab32((x))
-#define ext2fs_le32_to_cpu(x) ext2fs_swab32((x))
-#define ext2fs_cpu_to_le16(x) ext2fs_swab16((x))
-#define ext2fs_le16_to_cpu(x) ext2fs_swab16((x))
-#define ext2fs_cpu_to_be32(x) ((__u32)(x))
-#define ext2fs_be32_to_cpu(x) ((__u32)(x))
-#define ext2fs_cpu_to_be16(x) ((__u16)(x))
-#define ext2fs_be16_to_cpu(x) ((__u16)(x))
-#else
-#define ext2fs_cpu_to_le32(x) ((__u32)(x))
-#define ext2fs_le32_to_cpu(x) ((__u32)(x))
-#define ext2fs_cpu_to_le16(x) ((__u16)(x))
-#define ext2fs_le16_to_cpu(x) ((__u16)(x))
-#define ext2fs_cpu_to_be32(x) ext2fs_swab32((x))
-#define ext2fs_be32_to_cpu(x) ext2fs_swab32((x))
-#define ext2fs_cpu_to_be16(x) ext2fs_swab16((x))
-#define ext2fs_be16_to_cpu(x) ext2fs_swab16((x))
-#endif
-
-/*
- * EXT2FS bitmap manipulation routines.
- */
-
-/* Support for sending warning messages from the inline subroutines */
-extern const char *ext2fs_block_string;
-extern const char *ext2fs_inode_string;
-extern const char *ext2fs_mark_string;
-extern const char *ext2fs_unmark_string;
-extern const char *ext2fs_test_string;
-extern void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
- const char *description);
-extern void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
- int code, unsigned long arg);
-
-extern int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
-extern int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
- blk_t block);
-extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
-
-extern int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
-extern int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
- ext2_ino_t inode);
-extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
-
-extern void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
- blk_t block);
-extern void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
- blk_t block);
-extern int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
- blk_t block);
-
-extern void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
- ext2_ino_t inode);
-extern void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
- ext2_ino_t inode);
-extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
- ext2_ino_t inode);
-extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap);
-extern ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap);
-extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap);
-extern ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap);
-
-extern void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num);
-extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num);
-extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num);
-extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num);
-extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num);
-extern int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num);
-extern void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map);
-
-/* These two routines moved to gen_bitmap.c */
-extern int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
- __u32 bitno);
-extern int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
- blk_t bitno);
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/block.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/block.c
deleted file mode 100644
index dbd04f8469..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/block.c
+++ /dev/null
@@ -1,437 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * block.c --- iterate over all blocks in an inode
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-struct block_context {
- ext2_filsys fs;
- int (*func)(ext2_filsys fs,
- blk_t *blocknr,
- e2_blkcnt_t bcount,
- blk_t ref_blk,
- int ref_offset,
- void *priv_data);
- e2_blkcnt_t bcount;
- int bsize;
- int flags;
- errcode_t errcode;
- char *ind_buf;
- char *dind_buf;
- char *tind_buf;
- void *priv_data;
-};
-
-static int block_iterate_ind(blk_t *ind_block, blk_t ref_block,
- int ref_offset, struct block_context *ctx)
-{
- int ret = 0, changed = 0;
- int i, flags, limit, offset;
- blk_t *block_nr;
-
- limit = ctx->fs->blocksize >> 2;
- if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
- !(ctx->flags & BLOCK_FLAG_DATA_ONLY))
- ret = (*ctx->func)(ctx->fs, ind_block,
- BLOCK_COUNT_IND, ref_block,
- ref_offset, ctx->priv_data);
- if (!*ind_block || (ret & BLOCK_ABORT)) {
- ctx->bcount += limit;
- return ret;
- }
- if (*ind_block >= ctx->fs->super->s_blocks_count ||
- *ind_block < ctx->fs->super->s_first_data_block) {
- ctx->errcode = EXT2_ET_BAD_IND_BLOCK;
- ret |= BLOCK_ERROR;
- return ret;
- }
- ctx->errcode = ext2fs_read_ind_block(ctx->fs, *ind_block,
- ctx->ind_buf);
- if (ctx->errcode) {
- ret |= BLOCK_ERROR;
- return ret;
- }
-
- block_nr = (blk_t *) ctx->ind_buf;
- offset = 0;
- if (ctx->flags & BLOCK_FLAG_APPEND) {
- for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
- flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
- *ind_block, offset,
- ctx->priv_data);
- changed |= flags;
- if (flags & BLOCK_ABORT) {
- ret |= BLOCK_ABORT;
- break;
- }
- offset += sizeof(blk_t);
- }
- } else {
- for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
- if (*block_nr == 0)
- continue;
- flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
- *ind_block, offset,
- ctx->priv_data);
- changed |= flags;
- if (flags & BLOCK_ABORT) {
- ret |= BLOCK_ABORT;
- break;
- }
- offset += sizeof(blk_t);
- }
- }
- if (changed & BLOCK_CHANGED) {
- ctx->errcode = ext2fs_write_ind_block(ctx->fs, *ind_block,
- ctx->ind_buf);
- if (ctx->errcode)
- ret |= BLOCK_ERROR | BLOCK_ABORT;
- }
- if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
- !(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
- !(ret & BLOCK_ABORT))
- ret |= (*ctx->func)(ctx->fs, ind_block,
- BLOCK_COUNT_IND, ref_block,
- ref_offset, ctx->priv_data);
- return ret;
-}
-
-static int block_iterate_dind(blk_t *dind_block, blk_t ref_block,
- int ref_offset, struct block_context *ctx)
-{
- int ret = 0, changed = 0;
- int i, flags, limit, offset;
- blk_t *block_nr;
-
- limit = ctx->fs->blocksize >> 2;
- if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE |
- BLOCK_FLAG_DATA_ONLY)))
- ret = (*ctx->func)(ctx->fs, dind_block,
- BLOCK_COUNT_DIND, ref_block,
- ref_offset, ctx->priv_data);
- if (!*dind_block || (ret & BLOCK_ABORT)) {
- ctx->bcount += limit*limit;
- return ret;
- }
- if (*dind_block >= ctx->fs->super->s_blocks_count ||
- *dind_block < ctx->fs->super->s_first_data_block) {
- ctx->errcode = EXT2_ET_BAD_DIND_BLOCK;
- ret |= BLOCK_ERROR;
- return ret;
- }
- ctx->errcode = ext2fs_read_ind_block(ctx->fs, *dind_block,
- ctx->dind_buf);
- if (ctx->errcode) {
- ret |= BLOCK_ERROR;
- return ret;
- }
-
- block_nr = (blk_t *) ctx->dind_buf;
- offset = 0;
- if (ctx->flags & BLOCK_FLAG_APPEND) {
- for (i = 0; i < limit; i++, block_nr++) {
- flags = block_iterate_ind(block_nr,
- *dind_block, offset,
- ctx);
- changed |= flags;
- if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
- ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
- break;
- }
- offset += sizeof(blk_t);
- }
- } else {
- for (i = 0; i < limit; i++, block_nr++) {
- if (*block_nr == 0) {
- ctx->bcount += limit;
- continue;
- }
- flags = block_iterate_ind(block_nr,
- *dind_block, offset,
- ctx);
- changed |= flags;
- if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
- ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
- break;
- }
- offset += sizeof(blk_t);
- }
- }
- if (changed & BLOCK_CHANGED) {
- ctx->errcode = ext2fs_write_ind_block(ctx->fs, *dind_block,
- ctx->dind_buf);
- if (ctx->errcode)
- ret |= BLOCK_ERROR | BLOCK_ABORT;
- }
- if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
- !(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
- !(ret & BLOCK_ABORT))
- ret |= (*ctx->func)(ctx->fs, dind_block,
- BLOCK_COUNT_DIND, ref_block,
- ref_offset, ctx->priv_data);
- return ret;
-}
-
-static int block_iterate_tind(blk_t *tind_block, blk_t ref_block,
- int ref_offset, struct block_context *ctx)
-{
- int ret = 0, changed = 0;
- int i, flags, limit, offset;
- blk_t *block_nr;
-
- limit = ctx->fs->blocksize >> 2;
- if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE |
- BLOCK_FLAG_DATA_ONLY)))
- ret = (*ctx->func)(ctx->fs, tind_block,
- BLOCK_COUNT_TIND, ref_block,
- ref_offset, ctx->priv_data);
- if (!*tind_block || (ret & BLOCK_ABORT)) {
- ctx->bcount += limit*limit*limit;
- return ret;
- }
- if (*tind_block >= ctx->fs->super->s_blocks_count ||
- *tind_block < ctx->fs->super->s_first_data_block) {
- ctx->errcode = EXT2_ET_BAD_TIND_BLOCK;
- ret |= BLOCK_ERROR;
- return ret;
- }
- ctx->errcode = ext2fs_read_ind_block(ctx->fs, *tind_block,
- ctx->tind_buf);
- if (ctx->errcode) {
- ret |= BLOCK_ERROR;
- return ret;
- }
-
- block_nr = (blk_t *) ctx->tind_buf;
- offset = 0;
- if (ctx->flags & BLOCK_FLAG_APPEND) {
- for (i = 0; i < limit; i++, block_nr++) {
- flags = block_iterate_dind(block_nr,
- *tind_block,
- offset, ctx);
- changed |= flags;
- if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
- ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
- break;
- }
- offset += sizeof(blk_t);
- }
- } else {
- for (i = 0; i < limit; i++, block_nr++) {
- if (*block_nr == 0) {
- ctx->bcount += limit*limit;
- continue;
- }
- flags = block_iterate_dind(block_nr,
- *tind_block,
- offset, ctx);
- changed |= flags;
- if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
- ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
- break;
- }
- offset += sizeof(blk_t);
- }
- }
- if (changed & BLOCK_CHANGED) {
- ctx->errcode = ext2fs_write_ind_block(ctx->fs, *tind_block,
- ctx->tind_buf);
- if (ctx->errcode)
- ret |= BLOCK_ERROR | BLOCK_ABORT;
- }
- if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
- !(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
- !(ret & BLOCK_ABORT))
- ret |= (*ctx->func)(ctx->fs, tind_block,
- BLOCK_COUNT_TIND, ref_block,
- ref_offset, ctx->priv_data);
-
- return ret;
-}
-
-errcode_t ext2fs_block_iterate2(ext2_filsys fs,
- ext2_ino_t ino,
- int flags,
- char *block_buf,
- int (*func)(ext2_filsys fs,
- blk_t *blocknr,
- e2_blkcnt_t blockcnt,
- blk_t ref_blk,
- int ref_offset,
- void *priv_data),
- void *priv_data)
-{
- int i;
- int got_inode = 0;
- int ret = 0;
- blk_t blocks[EXT2_N_BLOCKS]; /* directory data blocks */
- struct ext2_inode inode;
- errcode_t retval;
- struct block_context ctx;
- int limit;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- /*
- * Check to see if we need to limit large files
- */
- if (flags & BLOCK_FLAG_NO_LARGE) {
- ctx.errcode = ext2fs_read_inode(fs, ino, &inode);
- if (ctx.errcode)
- return ctx.errcode;
- got_inode = 1;
- if (!LINUX_S_ISDIR(inode.i_mode) &&
- (inode.i_size_high != 0))
- return EXT2_ET_FILE_TOO_BIG;
- }
-
- retval = ext2fs_get_blocks(fs, ino, blocks);
- if (retval)
- return retval;
-
- limit = fs->blocksize >> 2;
-
- ctx.fs = fs;
- ctx.func = func;
- ctx.priv_data = priv_data;
- ctx.flags = flags;
- ctx.bcount = 0;
- if (block_buf) {
- ctx.ind_buf = block_buf;
- } else {
- retval = ext2fs_get_mem(fs->blocksize * 3, &ctx.ind_buf);
- if (retval)
- return retval;
- }
- ctx.dind_buf = ctx.ind_buf + fs->blocksize;
- ctx.tind_buf = ctx.dind_buf + fs->blocksize;
-
- /*
- * Iterate over the HURD translator block (if present)
- */
- if ((fs->super->s_creator_os == EXT2_OS_HURD) &&
- !(flags & BLOCK_FLAG_DATA_ONLY)) {
- ctx.errcode = ext2fs_read_inode(fs, ino, &inode);
- if (ctx.errcode)
- goto abort_exit;
- got_inode = 1;
- if (inode.osd1.hurd1.h_i_translator) {
- ret |= (*ctx.func)(fs,
- &inode.osd1.hurd1.h_i_translator,
- BLOCK_COUNT_TRANSLATOR,
- 0, 0, priv_data);
- if (ret & BLOCK_ABORT)
- goto abort_exit;
- }
- }
-
- /*
- * Iterate over normal data blocks
- */
- for (i = 0; i < EXT2_NDIR_BLOCKS; i++, ctx.bcount++) {
- if (blocks[i] || (flags & BLOCK_FLAG_APPEND)) {
- ret |= (*ctx.func)(fs, &blocks[i],
- ctx.bcount, 0, i, priv_data);
- if (ret & BLOCK_ABORT)
- goto abort_exit;
- }
- }
- if (*(blocks + EXT2_IND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
- ret |= block_iterate_ind(blocks + EXT2_IND_BLOCK,
- 0, EXT2_IND_BLOCK, &ctx);
- if (ret & BLOCK_ABORT)
- goto abort_exit;
- } else
- ctx.bcount += limit;
- if (*(blocks + EXT2_DIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
- ret |= block_iterate_dind(blocks + EXT2_DIND_BLOCK,
- 0, EXT2_DIND_BLOCK, &ctx);
- if (ret & BLOCK_ABORT)
- goto abort_exit;
- } else
- ctx.bcount += limit * limit;
- if (*(blocks + EXT2_TIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
- ret |= block_iterate_tind(blocks + EXT2_TIND_BLOCK,
- 0, EXT2_TIND_BLOCK, &ctx);
- if (ret & BLOCK_ABORT)
- goto abort_exit;
- }
-
-abort_exit:
- if (ret & BLOCK_CHANGED) {
- if (!got_inode) {
- retval = ext2fs_read_inode(fs, ino, &inode);
- if (retval)
- return retval;
- }
- for (i=0; i < EXT2_N_BLOCKS; i++)
- inode.i_block[i] = blocks[i];
- retval = ext2fs_write_inode(fs, ino, &inode);
- if (retval)
- return retval;
- }
-
- if (!block_buf)
- ext2fs_free_mem(&ctx.ind_buf);
-
- return (ret & BLOCK_ERROR) ? ctx.errcode : 0;
-}
-
-/*
- * Emulate the old ext2fs_block_iterate function!
- */
-
-struct xlate {
- int (*func)(ext2_filsys fs,
- blk_t *blocknr,
- int bcount,
- void *priv_data);
- void *real_private;
-};
-
-#ifdef __TURBOC__
-# pragma argsused
-#endif
-static int xlate_func(ext2_filsys fs, blk_t *blocknr, e2_blkcnt_t blockcnt,
- blk_t ref_block EXT2FS_ATTR((unused)),
- int ref_offset EXT2FS_ATTR((unused)),
- void *priv_data)
-{
- struct xlate *xl = (struct xlate *) priv_data;
-
- return (*xl->func)(fs, blocknr, (int) blockcnt, xl->real_private);
-}
-
-errcode_t ext2fs_block_iterate(ext2_filsys fs,
- ext2_ino_t ino,
- int flags,
- char *block_buf,
- int (*func)(ext2_filsys fs,
- blk_t *blocknr,
- int blockcnt,
- void *priv_data),
- void *priv_data)
-{
- struct xlate xl;
-
- xl.real_private = priv_data;
- xl.func = func;
-
- return ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_NO_LARGE | flags,
- block_buf, xlate_func, &xl);
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bmap.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bmap.c
deleted file mode 100644
index 796b0e4f51..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bmap.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * bmap.c --- logical to physical block mapping
- *
- * Copyright (C) 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode,
- char *block_buf, int bmap_flags,
- blk_t block, blk_t *phys_blk);
-
-#define inode_bmap(inode, nr) ((inode)->i_block[(nr)])
-
-static errcode_t block_ind_bmap(ext2_filsys fs, int flags,
- blk_t ind, char *block_buf,
- int *blocks_alloc,
- blk_t nr, blk_t *ret_blk)
-{
- errcode_t retval;
- blk_t b;
-
- if (!ind) {
- if (flags & BMAP_SET)
- return EXT2_ET_SET_BMAP_NO_IND;
- *ret_blk = 0;
- return 0;
- }
- retval = io_channel_read_blk(fs->io, ind, 1, block_buf);
- if (retval)
- return retval;
-
- if (flags & BMAP_SET) {
- b = *ret_blk;
-#if BB_BIG_ENDIAN
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
- b = ext2fs_swab32(b);
-#endif
- ((blk_t *) block_buf)[nr] = b;
- return io_channel_write_blk(fs->io, ind, 1, block_buf);
- }
-
- b = ((blk_t *) block_buf)[nr];
-
-#if BB_BIG_ENDIAN
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
- b = ext2fs_swab32(b);
-#endif
-
- if (!b && (flags & BMAP_ALLOC)) {
- b = nr ? ((blk_t *) block_buf)[nr-1] : 0;
- retval = ext2fs_alloc_block(fs, b,
- block_buf + fs->blocksize, &b);
- if (retval)
- return retval;
-
-#if BB_BIG_ENDIAN
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
- ((blk_t *) block_buf)[nr] = ext2fs_swab32(b);
- else
-#endif
- ((blk_t *) block_buf)[nr] = b;
-
- retval = io_channel_write_blk(fs->io, ind, 1, block_buf);
- if (retval)
- return retval;
-
- (*blocks_alloc)++;
- }
-
- *ret_blk = b;
- return 0;
-}
-
-static errcode_t block_dind_bmap(ext2_filsys fs, int flags,
- blk_t dind, char *block_buf,
- int *blocks_alloc,
- blk_t nr, blk_t *ret_blk)
-{
- blk_t b;
- errcode_t retval;
- blk_t addr_per_block;
-
- addr_per_block = (blk_t) fs->blocksize >> 2;
-
- retval = block_ind_bmap(fs, flags & ~BMAP_SET, dind, block_buf,
- blocks_alloc, nr / addr_per_block, &b);
- if (retval)
- return retval;
- retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc,
- nr % addr_per_block, ret_blk);
- return retval;
-}
-
-static errcode_t block_tind_bmap(ext2_filsys fs, int flags,
- blk_t tind, char *block_buf,
- int *blocks_alloc,
- blk_t nr, blk_t *ret_blk)
-{
- blk_t b;
- errcode_t retval;
- blk_t addr_per_block;
-
- addr_per_block = (blk_t) fs->blocksize >> 2;
-
- retval = block_dind_bmap(fs, flags & ~BMAP_SET, tind, block_buf,
- blocks_alloc, nr / addr_per_block, &b);
- if (retval)
- return retval;
- retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc,
- nr % addr_per_block, ret_blk);
- return retval;
-}
-
-errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode,
- char *block_buf, int bmap_flags, blk_t block,
- blk_t *phys_blk)
-{
- struct ext2_inode inode_buf;
- blk_t addr_per_block;
- blk_t b;
- char *buf = NULL;
- errcode_t retval = 0;
- int blocks_alloc = 0, inode_dirty = 0;
-
- if (!(bmap_flags & BMAP_SET))
- *phys_blk = 0;
-
- /* Read inode structure if necessary */
- if (!inode) {
- retval = ext2fs_read_inode(fs, ino, &inode_buf);
- if (retval)
- return retval;
- inode = &inode_buf;
- }
- addr_per_block = (blk_t) fs->blocksize >> 2;
-
- if (!block_buf) {
- retval = ext2fs_get_mem(fs->blocksize * 2, &buf);
- if (retval)
- return retval;
- block_buf = buf;
- }
-
- if (block < EXT2_NDIR_BLOCKS) {
- if (bmap_flags & BMAP_SET) {
- b = *phys_blk;
-#if BB_BIG_ENDIAN
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
- b = ext2fs_swab32(b);
-#endif
- inode_bmap(inode, block) = b;
- inode_dirty++;
- goto done;
- }
-
- *phys_blk = inode_bmap(inode, block);
- b = block ? inode_bmap(inode, block-1) : 0;
-
- if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) {
- retval = ext2fs_alloc_block(fs, b, block_buf, &b);
- if (retval)
- goto done;
- inode_bmap(inode, block) = b;
- blocks_alloc++;
- *phys_blk = b;
- }
- goto done;
- }
-
- /* Indirect block */
- block -= EXT2_NDIR_BLOCKS;
- if (block < addr_per_block) {
- b = inode_bmap(inode, EXT2_IND_BLOCK);
- if (!b) {
- if (!(bmap_flags & BMAP_ALLOC)) {
- if (bmap_flags & BMAP_SET)
- retval = EXT2_ET_SET_BMAP_NO_IND;
- goto done;
- }
-
- b = inode_bmap(inode, EXT2_IND_BLOCK-1);
- retval = ext2fs_alloc_block(fs, b, block_buf, &b);
- if (retval)
- goto done;
- inode_bmap(inode, EXT2_IND_BLOCK) = b;
- blocks_alloc++;
- }
- retval = block_ind_bmap(fs, bmap_flags, b, block_buf,
- &blocks_alloc, block, phys_blk);
- goto done;
- }
-
- /* Doubly indirect block */
- block -= addr_per_block;
- if (block < addr_per_block * addr_per_block) {
- b = inode_bmap(inode, EXT2_DIND_BLOCK);
- if (!b) {
- if (!(bmap_flags & BMAP_ALLOC)) {
- if (bmap_flags & BMAP_SET)
- retval = EXT2_ET_SET_BMAP_NO_IND;
- goto done;
- }
-
- b = inode_bmap(inode, EXT2_IND_BLOCK);
- retval = ext2fs_alloc_block(fs, b, block_buf, &b);
- if (retval)
- goto done;
- inode_bmap(inode, EXT2_DIND_BLOCK) = b;
- blocks_alloc++;
- }
- retval = block_dind_bmap(fs, bmap_flags, b, block_buf,
- &blocks_alloc, block, phys_blk);
- goto done;
- }
-
- /* Triply indirect block */
- block -= addr_per_block * addr_per_block;
- b = inode_bmap(inode, EXT2_TIND_BLOCK);
- if (!b) {
- if (!(bmap_flags & BMAP_ALLOC)) {
- if (bmap_flags & BMAP_SET)
- retval = EXT2_ET_SET_BMAP_NO_IND;
- goto done;
- }
-
- b = inode_bmap(inode, EXT2_DIND_BLOCK);
- retval = ext2fs_alloc_block(fs, b, block_buf, &b);
- if (retval)
- goto done;
- inode_bmap(inode, EXT2_TIND_BLOCK) = b;
- blocks_alloc++;
- }
- retval = block_tind_bmap(fs, bmap_flags, b, block_buf,
- &blocks_alloc, block, phys_blk);
-done:
- ext2fs_free_mem(&buf);
- if ((retval == 0) && (blocks_alloc || inode_dirty)) {
- inode->i_blocks += (blocks_alloc * fs->blocksize) / 512;
- retval = ext2fs_write_inode(fs, ino, inode);
- }
- return retval;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bmove.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bmove.c
deleted file mode 100644
index ec9244d0bc..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bmove.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * bmove.c --- Move blocks around to make way for a particular
- * filesystem structure.
- *
- * Copyright (C) 1997 Theodore Ts'o. This file may be redistributed
- * under the terms of the GNU Public License.
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fsP.h"
-
-struct process_block_struct {
- ext2_ino_t ino;
- struct ext2_inode * inode;
- ext2fs_block_bitmap reserve;
- ext2fs_block_bitmap alloc_map;
- errcode_t error;
- char *buf;
- int add_dir;
- int flags;
-};
-
-static int process_block(ext2_filsys fs, blk_t *block_nr,
- e2_blkcnt_t blockcnt, blk_t ref_block,
- int ref_offset, void *priv_data)
-{
- struct process_block_struct *pb;
- errcode_t retval;
- int ret;
- blk_t block, orig;
-
- pb = (struct process_block_struct *) priv_data;
- block = orig = *block_nr;
- ret = 0;
-
- /*
- * Let's see if this is one which we need to relocate
- */
- if (ext2fs_test_block_bitmap(pb->reserve, block)) {
- do {
- if (++block >= fs->super->s_blocks_count)
- block = fs->super->s_first_data_block;
- if (block == orig) {
- pb->error = EXT2_ET_BLOCK_ALLOC_FAIL;
- return BLOCK_ABORT;
- }
- } while (ext2fs_test_block_bitmap(pb->reserve, block) ||
- ext2fs_test_block_bitmap(pb->alloc_map, block));
-
- retval = io_channel_read_blk(fs->io, orig, 1, pb->buf);
- if (retval) {
- pb->error = retval;
- return BLOCK_ABORT;
- }
- retval = io_channel_write_blk(fs->io, block, 1, pb->buf);
- if (retval) {
- pb->error = retval;
- return BLOCK_ABORT;
- }
- *block_nr = block;
- ext2fs_mark_block_bitmap(pb->alloc_map, block);
- ret = BLOCK_CHANGED;
- if (pb->flags & EXT2_BMOVE_DEBUG)
- printf("ino=%ld, blockcnt=%lld, %d->%d\n", pb->ino,
- blockcnt, orig, block);
- }
- if (pb->add_dir) {
- retval = ext2fs_add_dir_block(fs->dblist, pb->ino,
- block, (int) blockcnt);
- if (retval) {
- pb->error = retval;
- ret |= BLOCK_ABORT;
- }
- }
- return ret;
-}
-
-errcode_t ext2fs_move_blocks(ext2_filsys fs,
- ext2fs_block_bitmap reserve,
- ext2fs_block_bitmap alloc_map,
- int flags)
-{
- ext2_ino_t ino;
- struct ext2_inode inode;
- errcode_t retval;
- struct process_block_struct pb;
- ext2_inode_scan scan;
- char *block_buf;
-
- retval = ext2fs_open_inode_scan(fs, 0, &scan);
- if (retval)
- return retval;
-
- pb.reserve = reserve;
- pb.error = 0;
- pb.alloc_map = alloc_map ? alloc_map : fs->block_map;
- pb.flags = flags;
-
- retval = ext2fs_get_mem(fs->blocksize * 4, &block_buf);
- if (retval)
- return retval;
- pb.buf = block_buf + fs->blocksize * 3;
-
- /*
- * If GET_DBLIST is set in the flags field, then we should
- * gather directory block information while we're doing the
- * block move.
- */
- if (flags & EXT2_BMOVE_GET_DBLIST) {
- ext2fs_free_dblist(fs->dblist);
- fs->dblist = NULL;
- retval = ext2fs_init_dblist(fs, 0);
- if (retval)
- return retval;
- }
-
- retval = ext2fs_get_next_inode(scan, &ino, &inode);
- if (retval)
- return retval;
-
- while (ino) {
- if ((inode.i_links_count == 0) ||
- !ext2fs_inode_has_valid_blocks(&inode))
- goto next;
-
- pb.ino = ino;
- pb.inode = &inode;
-
- pb.add_dir = (LINUX_S_ISDIR(inode.i_mode) &&
- flags & EXT2_BMOVE_GET_DBLIST);
-
- retval = ext2fs_block_iterate2(fs, ino, 0, block_buf,
- process_block, &pb);
- if (retval)
- return retval;
- if (pb.error)
- return pb.error;
-
- next:
- retval = ext2fs_get_next_inode(scan, &ino, &inode);
- if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
- goto next;
- }
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/brel.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/brel.h
deleted file mode 100644
index 87bf72be45..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/brel.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * brel.h
- *
- * Copyright (C) 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-struct ext2_block_relocate_entry {
- blk_t new;
- __s16 offset;
- __u16 flags;
- union {
- blk_t block_ref;
- ext2_ino_t inode_ref;
- } owner;
-};
-
-#define RELOCATE_TYPE_REF 0x0007
-#define RELOCATE_BLOCK_REF 0x0001
-#define RELOCATE_INODE_REF 0x0002
-
-typedef struct ext2_block_relocation_table *ext2_brel;
-
-struct ext2_block_relocation_table {
- __u32 magic;
- char *name;
- blk_t current;
- void *priv_data;
-
- /*
- * Add a block relocation entry.
- */
- errcode_t (*put)(ext2_brel brel, blk_t old,
- struct ext2_block_relocate_entry *ent);
-
- /*
- * Get a block relocation entry.
- */
- errcode_t (*get)(ext2_brel brel, blk_t old,
- struct ext2_block_relocate_entry *ent);
-
- /*
- * Initialize for iterating over the block relocation entries.
- */
- errcode_t (*start_iter)(ext2_brel brel);
-
- /*
- * The iterator function for the inode relocation entries.
- * Returns an inode number of 0 when out of entries.
- */
- errcode_t (*next)(ext2_brel brel, blk_t *old,
- struct ext2_block_relocate_entry *ent);
-
- /*
- * Move the inode relocation table from one block number to
- * another.
- */
- errcode_t (*move)(ext2_brel brel, blk_t old, blk_t new);
-
- /*
- * Remove a block relocation entry.
- */
- errcode_t (*delete)(ext2_brel brel, blk_t old);
-
-
- /*
- * Free the block relocation table.
- */
- errcode_t (*free)(ext2_brel brel);
-};
-
-errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block,
- ext2_brel *brel);
-
-#define ext2fs_brel_put(brel, old, ent) ((brel)->put((brel), old, ent))
-#define ext2fs_brel_get(brel, old, ent) ((brel)->get((brel), old, ent))
-#define ext2fs_brel_start_iter(brel) ((brel)->start_iter((brel)))
-#define ext2fs_brel_next(brel, old, ent) ((brel)->next((brel), old, ent))
-#define ext2fs_brel_move(brel, old, new) ((brel)->move((brel), old, new))
-#define ext2fs_brel_delete(brel, old) ((brel)->delete((brel), old))
-#define ext2fs_brel_free(brel) ((brel)->free((brel)))
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/brel_ma.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/brel_ma.c
deleted file mode 100644
index 652a3509cb..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/brel_ma.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * brel_ma.c
- *
- * Copyright (C) 1996, 1997 Theodore Ts'o.
- *
- * TODO: rewrite to not use a direct array!!! (Fortunately this
- * module isn't really used yet.)
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-#include "brel.h"
-
-static errcode_t bma_put(ext2_brel brel, blk_t old,
- struct ext2_block_relocate_entry *ent);
-static errcode_t bma_get(ext2_brel brel, blk_t old,
- struct ext2_block_relocate_entry *ent);
-static errcode_t bma_start_iter(ext2_brel brel);
-static errcode_t bma_next(ext2_brel brel, blk_t *old,
- struct ext2_block_relocate_entry *ent);
-static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new);
-static errcode_t bma_delete(ext2_brel brel, blk_t old);
-static errcode_t bma_free(ext2_brel brel);
-
-struct brel_ma {
- __u32 magic;
- blk_t max_block;
- struct ext2_block_relocate_entry *entries;
-};
-
-errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block,
- ext2_brel *new_brel)
-{
- ext2_brel brel = 0;
- errcode_t retval;
- struct brel_ma *ma = 0;
- size_t size;
-
- *new_brel = 0;
-
- /*
- * Allocate memory structures
- */
- retval = ext2fs_get_mem(sizeof(struct ext2_block_relocation_table),
- &brel);
- if (retval)
- goto errout;
- memset(brel, 0, sizeof(struct ext2_block_relocation_table));
-
- retval = ext2fs_get_mem(strlen(name)+1, &brel->name);
- if (retval)
- goto errout;
- strcpy(brel->name, name);
-
- retval = ext2fs_get_mem(sizeof(struct brel_ma), &ma);
- if (retval)
- goto errout;
- memset(ma, 0, sizeof(struct brel_ma));
- brel->priv_data = ma;
-
- size = (size_t) (sizeof(struct ext2_block_relocate_entry) *
- (max_block+1));
- retval = ext2fs_get_mem(size, &ma->entries);
- if (retval)
- goto errout;
- memset(ma->entries, 0, size);
- ma->max_block = max_block;
-
- /*
- * Fill in the brel data structure
- */
- brel->put = bma_put;
- brel->get = bma_get;
- brel->start_iter = bma_start_iter;
- brel->next = bma_next;
- brel->move = bma_move;
- brel->delete = bma_delete;
- brel->free = bma_free;
-
- *new_brel = brel;
- return 0;
-
-errout:
- bma_free(brel);
- return retval;
-}
-
-static errcode_t bma_put(ext2_brel brel, blk_t old,
- struct ext2_block_relocate_entry *ent)
-{
- struct brel_ma *ma;
-
- ma = brel->priv_data;
- if (old > ma->max_block)
- return EXT2_ET_INVALID_ARGUMENT;
- ma->entries[(unsigned)old] = *ent;
- return 0;
-}
-
-static errcode_t bma_get(ext2_brel brel, blk_t old,
- struct ext2_block_relocate_entry *ent)
-{
- struct brel_ma *ma;
-
- ma = brel->priv_data;
- if (old > ma->max_block)
- return EXT2_ET_INVALID_ARGUMENT;
- if (ma->entries[(unsigned)old].new == 0)
- return ENOENT;
- *ent = ma->entries[old];
- return 0;
-}
-
-static errcode_t bma_start_iter(ext2_brel brel)
-{
- brel->current = 0;
- return 0;
-}
-
-static errcode_t bma_next(ext2_brel brel, blk_t *old,
- struct ext2_block_relocate_entry *ent)
-{
- struct brel_ma *ma;
-
- ma = brel->priv_data;
- while (++brel->current < ma->max_block) {
- if (ma->entries[(unsigned)brel->current].new == 0)
- continue;
- *old = brel->current;
- *ent = ma->entries[(unsigned)brel->current];
- return 0;
- }
- *old = 0;
- return 0;
-}
-
-static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new)
-{
- struct brel_ma *ma;
-
- ma = brel->priv_data;
- if ((old > ma->max_block) || (new > ma->max_block))
- return EXT2_ET_INVALID_ARGUMENT;
- if (ma->entries[(unsigned)old].new == 0)
- return ENOENT;
- ma->entries[(unsigned)new] = ma->entries[old];
- ma->entries[(unsigned)old].new = 0;
- return 0;
-}
-
-static errcode_t bma_delete(ext2_brel brel, blk_t old)
-{
- struct brel_ma *ma;
-
- ma = brel->priv_data;
- if (old > ma->max_block)
- return EXT2_ET_INVALID_ARGUMENT;
- if (ma->entries[(unsigned)old].new == 0)
- return ENOENT;
- ma->entries[(unsigned)old].new = 0;
- return 0;
-}
-
-static errcode_t bma_free(ext2_brel brel)
-{
- struct brel_ma *ma;
-
- if (!brel)
- return 0;
-
- ma = brel->priv_data;
-
- if (ma) {
- ext2fs_free_mem(&ma->entries);
- ext2fs_free_mem(&ma);
- }
- ext2fs_free_mem(&brel->name);
- ext2fs_free_mem(&brel);
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/check_desc.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/check_desc.c
deleted file mode 100644
index dd4b0e9cf5..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/check_desc.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * check_desc.c --- Check the group descriptors of an ext2 filesystem
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * This routine sanity checks the group descriptors
- */
-errcode_t ext2fs_check_desc(ext2_filsys fs)
-{
- dgrp_t i;
- blk_t block = fs->super->s_first_data_block;
- blk_t next;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- for (i = 0; i < fs->group_desc_count; i++) {
- next = block + fs->super->s_blocks_per_group;
- /*
- * Check to make sure block bitmap for group is
- * located within the group.
- */
- if (fs->group_desc[i].bg_block_bitmap < block ||
- fs->group_desc[i].bg_block_bitmap >= next)
- return EXT2_ET_GDESC_BAD_BLOCK_MAP;
- /*
- * Check to make sure inode bitmap for group is
- * located within the group
- */
- if (fs->group_desc[i].bg_inode_bitmap < block ||
- fs->group_desc[i].bg_inode_bitmap >= next)
- return EXT2_ET_GDESC_BAD_INODE_MAP;
- /*
- * Check to make sure inode table for group is located
- * within the group
- */
- if (fs->group_desc[i].bg_inode_table < block ||
- ((fs->group_desc[i].bg_inode_table +
- fs->inode_blocks_per_group) >= next))
- return EXT2_ET_GDESC_BAD_INODE_TABLE;
-
- block = next;
- }
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/closefs.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/closefs.c
deleted file mode 100644
index bfa15e22a8..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/closefs.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * closefs.c --- close an ext2 filesystem
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <time.h>
-#include <string.h>
-
-#include "ext2_fs.h"
-#include "ext2fsP.h"
-
-static int test_root(int a, int b)
-{
- if (a == 0)
- return 1;
- while (1) {
- if (a == 1)
- return 1;
- if (a % b)
- return 0;
- a = a / b;
- }
-}
-
-int ext2fs_bg_has_super(ext2_filsys fs, int group_block)
-{
- if (!(fs->super->s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
- return 1;
-
- if (test_root(group_block, 3) || (test_root(group_block, 5)) ||
- test_root(group_block, 7))
- return 1;
-
- return 0;
-}
-
-int ext2fs_super_and_bgd_loc(ext2_filsys fs,
- dgrp_t group,
- blk_t *ret_super_blk,
- blk_t *ret_old_desc_blk,
- blk_t *ret_new_desc_blk,
- int *ret_meta_bg)
-{
- blk_t group_block, super_blk = 0, old_desc_blk = 0, new_desc_blk = 0;
- unsigned int meta_bg, meta_bg_size;
- int numblocks, has_super;
- int old_desc_blocks;
-
- group_block = fs->super->s_first_data_block +
- (group * fs->super->s_blocks_per_group);
-
- if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
- old_desc_blocks = fs->super->s_first_meta_bg;
- else
- old_desc_blocks =
- fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
-
- if (group == fs->group_desc_count-1) {
- numblocks = (fs->super->s_blocks_count -
- fs->super->s_first_data_block) %
- fs->super->s_blocks_per_group;
- if (!numblocks)
- numblocks = fs->super->s_blocks_per_group;
- } else
- numblocks = fs->super->s_blocks_per_group;
-
- has_super = ext2fs_bg_has_super(fs, group);
-
- if (has_super) {
- super_blk = group_block;
- numblocks--;
- }
- meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc));
- meta_bg = group / meta_bg_size;
-
- if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
- (meta_bg < fs->super->s_first_meta_bg)) {
- if (has_super) {
- old_desc_blk = group_block + 1;
- numblocks -= old_desc_blocks;
- }
- } else {
- if (((group % meta_bg_size) == 0) ||
- ((group % meta_bg_size) == 1) ||
- ((group % meta_bg_size) == (meta_bg_size-1))) {
- if (has_super)
- has_super = 1;
- new_desc_blk = group_block + has_super;
- numblocks--;
- }
- }
-
- numblocks -= 2 + fs->inode_blocks_per_group;
-
- if (ret_super_blk)
- *ret_super_blk = super_blk;
- if (ret_old_desc_blk)
- *ret_old_desc_blk = old_desc_blk;
- if (ret_new_desc_blk)
- *ret_new_desc_blk = new_desc_blk;
- if (ret_meta_bg)
- *ret_meta_bg = meta_bg;
- return numblocks;
-}
-
-
-/*
- * This function forces out the primary superblock. We need to only
- * write out those fields which we have changed, since if the
- * filesystem is mounted, it may have changed some of the other
- * fields.
- *
- * It takes as input a superblock which has already been byte swapped
- * (if necessary).
- *
- */
-static errcode_t write_primary_superblock(ext2_filsys fs,
- struct ext2_super_block *super)
-{
- __u16 *old_super, *new_super;
- int check_idx, write_idx, size;
- errcode_t retval;
-
- if (!fs->io->manager->write_byte || !fs->orig_super) {
- io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET);
- retval = io_channel_write_blk(fs->io, 1, -SUPERBLOCK_SIZE,
- super);
- io_channel_set_blksize(fs->io, fs->blocksize);
- return retval;
- }
-
- old_super = (__u16 *) fs->orig_super;
- new_super = (__u16 *) super;
-
- for (check_idx = 0; check_idx < SUPERBLOCK_SIZE/2; check_idx++) {
- if (old_super[check_idx] == new_super[check_idx])
- continue;
- write_idx = check_idx;
- for (check_idx++; check_idx < SUPERBLOCK_SIZE/2; check_idx++)
- if (old_super[check_idx] == new_super[check_idx])
- break;
- size = 2 * (check_idx - write_idx);
- retval = io_channel_write_byte(fs->io,
- SUPERBLOCK_OFFSET + (2 * write_idx), size,
- new_super + write_idx);
- if (retval)
- return retval;
- }
- memcpy(fs->orig_super, super, SUPERBLOCK_SIZE);
- return 0;
-}
-
-
-/*
- * Updates the revision to EXT2_DYNAMIC_REV
- */
-void ext2fs_update_dynamic_rev(ext2_filsys fs)
-{
- struct ext2_super_block *sb = fs->super;
-
- if (sb->s_rev_level > EXT2_GOOD_OLD_REV)
- return;
-
- sb->s_rev_level = EXT2_DYNAMIC_REV;
- sb->s_first_ino = EXT2_GOOD_OLD_FIRST_INO;
- sb->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
- /* s_uuid is handled by e2fsck already */
- /* other fields should be left alone */
-}
-
-static errcode_t write_backup_super(ext2_filsys fs, dgrp_t group,
- blk_t group_block,
- struct ext2_super_block *super_shadow)
-{
- dgrp_t sgrp = group;
-
- if (sgrp > ((1 << 16) - 1))
- sgrp = (1 << 16) - 1;
-#if BB_BIG_ENDIAN
- if (fs->flags & EXT2_FLAG_SWAP_BYTES)
- super_shadow->s_block_group_nr = ext2fs_swab16(sgrp);
- else
-#endif
- fs->super->s_block_group_nr = sgrp;
-
- return io_channel_write_blk(fs->io, group_block, -SUPERBLOCK_SIZE,
- super_shadow);
-}
-
-
-errcode_t ext2fs_flush(ext2_filsys fs)
-{
- dgrp_t i;
- blk_t group_block;
- errcode_t retval;
- unsigned long fs_state;
- struct ext2_super_block *super_shadow = NULL;
- struct ext2_group_desc *group_shadow = NULL;
- char *group_ptr;
- int old_desc_blocks;
-#if BB_BIG_ENDIAN
- dgrp_t j;
- struct ext2_group_desc *s, *t;
-#endif
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- fs_state = fs->super->s_state;
-
- fs->super->s_wtime = time(NULL);
- fs->super->s_block_group_nr = 0;
-#if BB_BIG_ENDIAN
- if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
- retval = EXT2_ET_NO_MEMORY;
- retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow);
- if (retval)
- goto errout;
- retval = ext2fs_get_mem((size_t)(fs->blocksize *
- fs->desc_blocks),
- &group_shadow);
- if (retval)
- goto errout;
- memset(group_shadow, 0, (size_t) fs->blocksize *
- fs->desc_blocks);
-
- /* swap the group descriptors */
- for (j=0, s=fs->group_desc, t=group_shadow;
- j < fs->group_desc_count; j++, t++, s++) {
- *t = *s;
- ext2fs_swap_group_desc(t);
- }
- } else {
- super_shadow = fs->super;
- group_shadow = fs->group_desc;
- }
-#else
- super_shadow = fs->super;
- group_shadow = fs->group_desc;
-#endif
-
- /*
- * If this is an external journal device, don't write out the
- * block group descriptors or any of the backup superblocks
- */
- if (fs->super->s_feature_incompat &
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
- goto write_primary_superblock_only;
-
- /*
- * Set the state of the FS to be non-valid. (The state has
- * already been backed up earlier, and will be restored after
- * we write out the backup superblocks.)
- */
- fs->super->s_state &= ~EXT2_VALID_FS;
-#if BB_BIG_ENDIAN
- if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
- *super_shadow = *fs->super;
- ext2fs_swap_super(super_shadow);
- }
-#endif
-
- /*
- * Write out the master group descriptors, and the backup
- * superblocks and group descriptors.
- */
- group_block = fs->super->s_first_data_block;
- group_ptr = (char *) group_shadow;
- if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
- old_desc_blocks = fs->super->s_first_meta_bg;
- else
- old_desc_blocks = fs->desc_blocks;
-
- for (i = 0; i < fs->group_desc_count; i++) {
- blk_t super_blk, old_desc_blk, new_desc_blk;
- int meta_bg;
-
- ext2fs_super_and_bgd_loc(fs, i, &super_blk, &old_desc_blk,
- &new_desc_blk, &meta_bg);
-
- if (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) &&i && super_blk) {
- retval = write_backup_super(fs, i, super_blk,
- super_shadow);
- if (retval)
- goto errout;
- }
- if (fs->flags & EXT2_FLAG_SUPER_ONLY)
- continue;
- if ((old_desc_blk) &&
- (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) || (i == 0))) {
- retval = io_channel_write_blk(fs->io,
- old_desc_blk, old_desc_blocks, group_ptr);
- if (retval)
- goto errout;
- }
- if (new_desc_blk) {
- retval = io_channel_write_blk(fs->io, new_desc_blk,
- 1, group_ptr + (meta_bg*fs->blocksize));
- if (retval)
- goto errout;
- }
- }
- fs->super->s_block_group_nr = 0;
- fs->super->s_state = fs_state;
-#if BB_BIG_ENDIAN
- if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
- *super_shadow = *fs->super;
- ext2fs_swap_super(super_shadow);
- }
-#endif
-
- /*
- * If the write_bitmaps() function is present, call it to
- * flush the bitmaps. This is done this way so that a simple
- * program that doesn't mess with the bitmaps doesn't need to
- * drag in the bitmaps.c code.
- */
- if (fs->write_bitmaps) {
- retval = fs->write_bitmaps(fs);
- if (retval)
- goto errout;
- }
-
-write_primary_superblock_only:
- /*
- * Write out master superblock. This has to be done
- * separately, since it is located at a fixed location
- * (SUPERBLOCK_OFFSET). We flush all other pending changes
- * out to disk first, just to avoid a race condition with an
- * insy-tinsy window....
- */
- retval = io_channel_flush(fs->io);
- retval = write_primary_superblock(fs, super_shadow);
- if (retval)
- goto errout;
-
- fs->flags &= ~EXT2_FLAG_DIRTY;
-
- retval = io_channel_flush(fs->io);
-errout:
- fs->super->s_state = fs_state;
- if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
- if (super_shadow)
- ext2fs_free_mem(&super_shadow);
- if (group_shadow)
- ext2fs_free_mem(&group_shadow);
- }
- return retval;
-}
-
-errcode_t ext2fs_close(ext2_filsys fs)
-{
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (fs->flags & EXT2_FLAG_DIRTY) {
- retval = ext2fs_flush(fs);
- if (retval)
- return retval;
- }
- if (fs->write_bitmaps) {
- retval = fs->write_bitmaps(fs);
- if (retval)
- return retval;
- }
- ext2fs_free(fs);
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/cmp_bitmaps.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/cmp_bitmaps.c
deleted file mode 100644
index 7f78ff8042..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/cmp_bitmaps.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * cmp_bitmaps.c --- routines to compare inode and block bitmaps.
- *
- * Copyright (C) 1995 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
- ext2fs_block_bitmap bm2)
-{
- blk_t i;
-
- EXT2_CHECK_MAGIC(bm1, EXT2_ET_MAGIC_BLOCK_BITMAP);
- EXT2_CHECK_MAGIC(bm2, EXT2_ET_MAGIC_BLOCK_BITMAP);
-
- if ((bm1->start != bm2->start) ||
- (bm1->end != bm2->end) ||
- (memcmp(bm1->bitmap, bm2->bitmap,
- (size_t) (bm1->end - bm1->start)/8)))
- return EXT2_ET_NEQ_BLOCK_BITMAP;
-
- for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
- if (ext2fs_fast_test_block_bitmap(bm1, i) !=
- ext2fs_fast_test_block_bitmap(bm2, i))
- return EXT2_ET_NEQ_BLOCK_BITMAP;
-
- return 0;
-}
-
-errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
- ext2fs_inode_bitmap bm2)
-{
- ext2_ino_t i;
-
- EXT2_CHECK_MAGIC(bm1, EXT2_ET_MAGIC_INODE_BITMAP);
- EXT2_CHECK_MAGIC(bm2, EXT2_ET_MAGIC_INODE_BITMAP);
-
- if ((bm1->start != bm2->start) ||
- (bm1->end != bm2->end) ||
- (memcmp(bm1->bitmap, bm2->bitmap,
- (size_t) (bm1->end - bm1->start)/8)))
- return EXT2_ET_NEQ_INODE_BITMAP;
-
- for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
- if (ext2fs_fast_test_inode_bitmap(bm1, i) !=
- ext2fs_fast_test_inode_bitmap(bm2, i))
- return EXT2_ET_NEQ_INODE_BITMAP;
-
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dblist.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dblist.c
deleted file mode 100644
index 06ff6d8079..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dblist.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * dblist.c -- directory block list functions
- *
- * Copyright 1997 by Theodore Ts'o
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- *
- */
-
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <string.h>
-#include <time.h>
-
-#include "ext2_fs.h"
-#include "ext2fsP.h"
-
-static int dir_block_cmp(const void *a, const void *b);
-
-/*
- * Returns the number of directories in the filesystem as reported by
- * the group descriptors. Of course, the group descriptors could be
- * wrong!
- */
-errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs)
-{
- dgrp_t i;
- ext2_ino_t num_dirs, max_dirs;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- num_dirs = 0;
- max_dirs = fs->super->s_inodes_per_group;
- for (i = 0; i < fs->group_desc_count; i++) {
- if (fs->group_desc[i].bg_used_dirs_count > max_dirs)
- num_dirs += max_dirs / 8;
- else
- num_dirs += fs->group_desc[i].bg_used_dirs_count;
- }
- if (num_dirs > fs->super->s_inodes_count)
- num_dirs = fs->super->s_inodes_count;
-
- *ret_num_dirs = num_dirs;
-
- return 0;
-}
-
-/*
- * helper function for making a new directory block list (for
- * initialize and copy).
- */
-static errcode_t make_dblist(ext2_filsys fs, ext2_ino_t size, ext2_ino_t count,
- struct ext2_db_entry *list,
- ext2_dblist *ret_dblist)
-{
- ext2_dblist dblist;
- errcode_t retval;
- size_t len;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if ((ret_dblist == 0) && fs->dblist &&
- (fs->dblist->magic == EXT2_ET_MAGIC_DBLIST))
- return 0;
-
- retval = ext2fs_get_mem(sizeof(struct ext2_struct_dblist), &dblist);
- if (retval)
- return retval;
- memset(dblist, 0, sizeof(struct ext2_struct_dblist));
-
- dblist->magic = EXT2_ET_MAGIC_DBLIST;
- dblist->fs = fs;
- if (size)
- dblist->size = size;
- else {
- retval = ext2fs_get_num_dirs(fs, &dblist->size);
- if (retval)
- goto cleanup;
- dblist->size = (dblist->size * 2) + 12;
- }
- len = (size_t) sizeof(struct ext2_db_entry) * dblist->size;
- dblist->count = count;
- retval = ext2fs_get_mem(len, &dblist->list);
- if (retval)
- goto cleanup;
-
- if (list)
- memcpy(dblist->list, list, len);
- else
- memset(dblist->list, 0, len);
- if (ret_dblist)
- *ret_dblist = dblist;
- else
- fs->dblist = dblist;
- return 0;
-cleanup:
- ext2fs_free_mem(&dblist);
- return retval;
-}
-
-/*
- * Initialize a directory block list
- */
-errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist)
-{
- ext2_dblist dblist;
- errcode_t retval;
-
- retval = make_dblist(fs, 0, 0, 0, &dblist);
- if (retval)
- return retval;
-
- dblist->sorted = 1;
- if (ret_dblist)
- *ret_dblist = dblist;
- else
- fs->dblist = dblist;
-
- return 0;
-}
-
-/*
- * Copy a directory block list
- */
-errcode_t ext2fs_copy_dblist(ext2_dblist src, ext2_dblist *dest)
-{
- ext2_dblist dblist;
- errcode_t retval;
-
- retval = make_dblist(src->fs, src->size, src->count, src->list,
- &dblist);
- if (retval)
- return retval;
- dblist->sorted = src->sorted;
- *dest = dblist;
- return 0;
-}
-
-/*
- * Close a directory block list
- *
- * (moved to closefs.c)
- */
-
-
-/*
- * Add a directory block to the directory block list
- */
-errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk,
- int blockcnt)
-{
- struct ext2_db_entry *new_entry;
- errcode_t retval;
- unsigned long old_size;
-
- EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
-
- if (dblist->count >= dblist->size) {
- old_size = dblist->size * sizeof(struct ext2_db_entry);
- dblist->size += 100;
- retval = ext2fs_resize_mem(old_size, (size_t) dblist->size *
- sizeof(struct ext2_db_entry),
- &dblist->list);
- if (retval) {
- dblist->size -= 100;
- return retval;
- }
- }
- new_entry = dblist->list + ( (int) dblist->count++);
- new_entry->blk = blk;
- new_entry->ino = ino;
- new_entry->blockcnt = blockcnt;
-
- dblist->sorted = 0;
-
- return 0;
-}
-
-/*
- * Change the directory block to the directory block list
- */
-errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk,
- int blockcnt)
-{
- dgrp_t i;
-
- EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
-
- for (i=0; i < dblist->count; i++) {
- if ((dblist->list[i].ino != ino) ||
- (dblist->list[i].blockcnt != blockcnt))
- continue;
- dblist->list[i].blk = blk;
- dblist->sorted = 0;
- return 0;
- }
- return EXT2_ET_DB_NOT_FOUND;
-}
-
-void ext2fs_dblist_sort(ext2_dblist dblist,
- int (*sortfunc)(const void *,
- const void *))
-{
- if (!sortfunc)
- sortfunc = dir_block_cmp;
- qsort(dblist->list, (size_t) dblist->count,
- sizeof(struct ext2_db_entry), sortfunc);
- dblist->sorted = 1;
-}
-
-/*
- * This function iterates over the directory block list
- */
-errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
- int (*func)(ext2_filsys fs,
- struct ext2_db_entry *db_info,
- void *priv_data),
- void *priv_data)
-{
- ext2_ino_t i;
- int ret;
-
- EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
-
- if (!dblist->sorted)
- ext2fs_dblist_sort(dblist, 0);
- for (i=0; i < dblist->count; i++) {
- ret = (*func)(dblist->fs, &dblist->list[(int)i], priv_data);
- if (ret & DBLIST_ABORT)
- return 0;
- }
- return 0;
-}
-
-static int dir_block_cmp(const void *a, const void *b)
-{
- const struct ext2_db_entry *db_a =
- (const struct ext2_db_entry *) a;
- const struct ext2_db_entry *db_b =
- (const struct ext2_db_entry *) b;
-
- if (db_a->blk != db_b->blk)
- return (int) (db_a->blk - db_b->blk);
-
- if (db_a->ino != db_b->ino)
- return (int) (db_a->ino - db_b->ino);
-
- return (int) (db_a->blockcnt - db_b->blockcnt);
-}
-
-int ext2fs_dblist_count(ext2_dblist dblist)
-{
- return (int) dblist->count;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dblist_dir.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dblist_dir.c
deleted file mode 100644
index b239204664..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dblist_dir.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * dblist_dir.c --- iterate by directory entry
- *
- * Copyright 1997 by Theodore Ts'o
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- *
- */
-
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <string.h>
-#include <time.h>
-
-#include "ext2_fs.h"
-#include "ext2fsP.h"
-
-static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info,
- void *priv_data);
-
-errcode_t ext2fs_dblist_dir_iterate(ext2_dblist dblist,
- int flags,
- char *block_buf,
- int (*func)(ext2_ino_t dir,
- int entry,
- struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *priv_data),
- void *priv_data)
-{
- errcode_t retval;
- struct dir_context ctx;
-
- EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
-
- ctx.dir = 0;
- ctx.flags = flags;
- if (block_buf)
- ctx.buf = block_buf;
- else {
- retval = ext2fs_get_mem(dblist->fs->blocksize, &ctx.buf);
- if (retval)
- return retval;
- }
- ctx.func = func;
- ctx.priv_data = priv_data;
- ctx.errcode = 0;
-
- retval = ext2fs_dblist_iterate(dblist, db_dir_proc, &ctx);
-
- if (!block_buf)
- ext2fs_free_mem(&ctx.buf);
- if (retval)
- return retval;
- return ctx.errcode;
-}
-
-static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info,
- void *priv_data)
-{
- struct dir_context *ctx;
-
- ctx = (struct dir_context *) priv_data;
- ctx->dir = db_info->ino;
-
- return ext2fs_process_dir_block(fs, &db_info->blk,
- db_info->blockcnt, 0, 0, priv_data);
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dir_iterate.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dir_iterate.c
deleted file mode 100644
index eb5dae0a64..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dir_iterate.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * dir_iterate.c --- ext2fs directory iteration operations
- *
- * Copyright (C) 1993, 1994, 1994, 1995, 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fsP.h"
-
-/*
- * This function checks to see whether or not a potential deleted
- * directory entry looks valid. What we do is check the deleted entry
- * and each successive entry to make sure that they all look valid and
- * that the last deleted entry ends at the beginning of the next
- * undeleted entry. Returns 1 if the deleted entry looks valid, zero
- * if not valid.
- */
-static int ext2fs_validate_entry(char *buf, int offset, int final_offset)
-{
- struct ext2_dir_entry *dirent;
-
- while (offset < final_offset) {
- dirent = (struct ext2_dir_entry *)(buf + offset);
- offset += dirent->rec_len;
- if ((dirent->rec_len < 8) ||
- ((dirent->rec_len % 4) != 0) ||
- (((dirent->name_len & 0xFF)+8) > dirent->rec_len))
- return 0;
- }
- return (offset == final_offset);
-}
-
-errcode_t ext2fs_dir_iterate2(ext2_filsys fs,
- ext2_ino_t dir,
- int flags,
- char *block_buf,
- int (*func)(ext2_ino_t dir,
- int entry,
- struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *priv_data),
- void *priv_data)
-{
- struct dir_context ctx;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- retval = ext2fs_check_directory(fs, dir);
- if (retval)
- return retval;
-
- ctx.dir = dir;
- ctx.flags = flags;
- if (block_buf)
- ctx.buf = block_buf;
- else {
- retval = ext2fs_get_mem(fs->blocksize, &ctx.buf);
- if (retval)
- return retval;
- }
- ctx.func = func;
- ctx.priv_data = priv_data;
- ctx.errcode = 0;
- retval = ext2fs_block_iterate2(fs, dir, 0, 0,
- ext2fs_process_dir_block, &ctx);
- if (!block_buf)
- ext2fs_free_mem(&ctx.buf);
- if (retval)
- return retval;
- return ctx.errcode;
-}
-
-struct xlate {
- int (*func)(struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *priv_data);
- void *real_private;
-};
-
-static int xlate_func(ext2_ino_t dir EXT2FS_ATTR((unused)),
- int entry EXT2FS_ATTR((unused)),
- struct ext2_dir_entry *dirent, int offset,
- int blocksize, char *buf, void *priv_data)
-{
- struct xlate *xl = (struct xlate *) priv_data;
-
- return (*xl->func)(dirent, offset, blocksize, buf, xl->real_private);
-}
-
-extern errcode_t ext2fs_dir_iterate(ext2_filsys fs,
- ext2_ino_t dir,
- int flags,
- char *block_buf,
- int (*func)(struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *priv_data),
- void *priv_data)
-{
- struct xlate xl;
-
- xl.real_private = priv_data;
- xl.func = func;
-
- return ext2fs_dir_iterate2(fs, dir, flags, block_buf,
- xlate_func, &xl);
-}
-
-
-/*
- * Helper function which is private to this module. Used by
- * ext2fs_dir_iterate() and ext2fs_dblist_dir_iterate()
- */
-int ext2fs_process_dir_block(ext2_filsys fs,
- blk_t *blocknr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block EXT2FS_ATTR((unused)),
- int ref_offset EXT2FS_ATTR((unused)),
- void *priv_data)
-{
- struct dir_context *ctx = (struct dir_context *) priv_data;
- unsigned int offset = 0;
- unsigned int next_real_entry = 0;
- int ret = 0;
- int changed = 0;
- int do_abort = 0;
- int entry, size;
- struct ext2_dir_entry *dirent;
-
- if (blockcnt < 0)
- return 0;
-
- entry = blockcnt ? DIRENT_OTHER_FILE : DIRENT_DOT_FILE;
-
- ctx->errcode = ext2fs_read_dir_block(fs, *blocknr, ctx->buf);
- if (ctx->errcode)
- return BLOCK_ABORT;
-
- while (offset < fs->blocksize) {
- dirent = (struct ext2_dir_entry *) (ctx->buf + offset);
- if (((offset + dirent->rec_len) > fs->blocksize) ||
- (dirent->rec_len < 8) ||
- ((dirent->rec_len % 4) != 0) ||
- (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
- ctx->errcode = EXT2_ET_DIR_CORRUPTED;
- return BLOCK_ABORT;
- }
- if (!dirent->inode &&
- !(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY))
- goto next;
-
- ret = (ctx->func)(ctx->dir,
- (next_real_entry > offset) ?
- DIRENT_DELETED_FILE : entry,
- dirent, offset,
- fs->blocksize, ctx->buf,
- ctx->priv_data);
- if (entry < DIRENT_OTHER_FILE)
- entry++;
-
- if (ret & DIRENT_CHANGED)
- changed++;
- if (ret & DIRENT_ABORT) {
- do_abort++;
- break;
- }
-next:
- if (next_real_entry == offset)
- next_real_entry += dirent->rec_len;
-
- if (ctx->flags & DIRENT_FLAG_INCLUDE_REMOVED) {
- size = ((dirent->name_len & 0xFF) + 11) & ~3;
-
- if (dirent->rec_len != size) {
- unsigned int final_offset;
-
- final_offset = offset + dirent->rec_len;
- offset += size;
- while (offset < final_offset &&
- !ext2fs_validate_entry(ctx->buf,
- offset,
- final_offset))
- offset += 4;
- continue;
- }
- }
- offset += dirent->rec_len;
- }
-
- if (changed) {
- ctx->errcode = ext2fs_write_dir_block(fs, *blocknr, ctx->buf);
- if (ctx->errcode)
- return BLOCK_ABORT;
- }
- if (do_abort)
- return BLOCK_ABORT;
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dirblock.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dirblock.c
deleted file mode 100644
index f9c5a104b0..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dirblock.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * dirblock.c --- directory block routines.
- *
- * Copyright (C) 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <string.h>
-#include <time.h>
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
- void *buf, int flags EXT2FS_ATTR((unused)))
-{
- errcode_t retval;
- char *p, *end;
- struct ext2_dir_entry *dirent;
- unsigned int name_len, rec_len;
-#if BB_BIG_ENDIAN
- unsigned int do_swap;
-#endif
-
- retval = io_channel_read_blk(fs->io, block, 1, buf);
- if (retval)
- return retval;
-#if BB_BIG_ENDIAN
- do_swap = (fs->flags & (EXT2_FLAG_SWAP_BYTES|
- EXT2_FLAG_SWAP_BYTES_READ)) != 0;
-#endif
- p = (char *) buf;
- end = (char *) buf + fs->blocksize;
- while (p < end-8) {
- dirent = (struct ext2_dir_entry *) p;
-#if BB_BIG_ENDIAN
- if (do_swap) {
- dirent->inode = ext2fs_swab32(dirent->inode);
- dirent->rec_len = ext2fs_swab16(dirent->rec_len);
- dirent->name_len = ext2fs_swab16(dirent->name_len);
- }
-#endif
- name_len = dirent->name_len;
-#ifdef WORDS_BIGENDIAN
- if (flags & EXT2_DIRBLOCK_V2_STRUCT)
- dirent->name_len = ext2fs_swab16(dirent->name_len);
-#endif
- rec_len = dirent->rec_len;
- if ((rec_len < 8) || (rec_len % 4)) {
- rec_len = 8;
- retval = EXT2_ET_DIR_CORRUPTED;
- }
- if (((name_len & 0xFF) + 8) > dirent->rec_len)
- retval = EXT2_ET_DIR_CORRUPTED;
- p += rec_len;
- }
- return retval;
-}
-
-errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
- void *buf)
-{
- return ext2fs_read_dir_block2(fs, block, buf, 0);
-}
-
-
-errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
- void *inbuf, int flags EXT2FS_ATTR((unused)))
-{
-#if BB_BIG_ENDIAN
- int do_swap = 0;
- errcode_t retval;
- char *p, *end;
- char *buf = NULL;
- struct ext2_dir_entry *dirent;
-
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
- do_swap = 1;
-
-#ifndef WORDS_BIGENDIAN
- if (!do_swap)
- return io_channel_write_blk(fs->io, block, 1, (char *) inbuf);
-#endif
-
- retval = ext2fs_get_mem(fs->blocksize, &buf);
- if (retval)
- return retval;
- memcpy(buf, inbuf, fs->blocksize);
- p = buf;
- end = buf + fs->blocksize;
- while (p < end) {
- dirent = (struct ext2_dir_entry *) p;
- if ((dirent->rec_len < 8) ||
- (dirent->rec_len % 4)) {
- ext2fs_free_mem(&buf);
- return EXT2_ET_DIR_CORRUPTED;
- }
- p += dirent->rec_len;
- if (do_swap) {
- dirent->inode = ext2fs_swab32(dirent->inode);
- dirent->rec_len = ext2fs_swab16(dirent->rec_len);
- dirent->name_len = ext2fs_swab16(dirent->name_len);
- }
-#ifdef WORDS_BIGENDIAN
- if (flags & EXT2_DIRBLOCK_V2_STRUCT)
- dirent->name_len = ext2fs_swab16(dirent->name_len);
-#endif
- }
- retval = io_channel_write_blk(fs->io, block, 1, buf);
- ext2fs_free_mem(&buf);
- return retval;
-#else
- return io_channel_write_blk(fs->io, block, 1, (char *) inbuf);
-#endif
-}
-
-
-errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
- void *inbuf)
-{
- return ext2fs_write_dir_block2(fs, block, inbuf, 0);
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dirhash.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dirhash.c
deleted file mode 100644
index 09e34be3b6..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dirhash.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * dirhash.c -- Calculate the hash of a directory entry
- *
- * Copyright (c) 2001 Daniel Phillips
- *
- * Copyright (c) 2002 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * Keyed 32-bit hash function using TEA in a Davis-Meyer function
- * H0 = Key
- * Hi = E Mi(Hi-1) + Hi-1
- *
- * (see Applied Cryptography, 2nd edition, p448).
- *
- * Jeremy Fitzhardinge <jeremy@zip.com.au> 1998
- *
- * This code is made available under the terms of the GPL
- */
-#define DELTA 0x9E3779B9
-
-static void TEA_transform(__u32 buf[4], __u32 const in[])
-{
- __u32 sum = 0;
- __u32 b0 = buf[0], b1 = buf[1];
- __u32 a = in[0], b = in[1], c = in[2], d = in[3];
- int n = 16;
-
- do {
- sum += DELTA;
- b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
- b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
- } while (--n);
-
- buf[0] += b0;
- buf[1] += b1;
-}
-
-/* F, G and H are basic MD4 functions: selection, majority, parity */
-#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
-#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-
-/*
- * The generic round function. The application is so specific that
- * we don't bother protecting all the arguments with parens, as is generally
- * good macro practice, in favor of extra legibility.
- * Rotation is separate from addition to prevent recomputation
- */
-#define ROUND(f, a, b, c, d, x, s) \
- (a += f(b, c, d) + x, a = (a << s) | (a >> (32-s)))
-#define K1 0
-#define K2 013240474631UL
-#define K3 015666365641UL
-
-/*
- * Basic cut-down MD4 transform. Returns only 32 bits of result.
- */
-static void halfMD4Transform (__u32 buf[4], __u32 const in[])
-{
- __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
-
- /* Round 1 */
- ROUND(F, a, b, c, d, in[0] + K1, 3);
- ROUND(F, d, a, b, c, in[1] + K1, 7);
- ROUND(F, c, d, a, b, in[2] + K1, 11);
- ROUND(F, b, c, d, a, in[3] + K1, 19);
- ROUND(F, a, b, c, d, in[4] + K1, 3);
- ROUND(F, d, a, b, c, in[5] + K1, 7);
- ROUND(F, c, d, a, b, in[6] + K1, 11);
- ROUND(F, b, c, d, a, in[7] + K1, 19);
-
- /* Round 2 */
- ROUND(G, a, b, c, d, in[1] + K2, 3);
- ROUND(G, d, a, b, c, in[3] + K2, 5);
- ROUND(G, c, d, a, b, in[5] + K2, 9);
- ROUND(G, b, c, d, a, in[7] + K2, 13);
- ROUND(G, a, b, c, d, in[0] + K2, 3);
- ROUND(G, d, a, b, c, in[2] + K2, 5);
- ROUND(G, c, d, a, b, in[4] + K2, 9);
- ROUND(G, b, c, d, a, in[6] + K2, 13);
-
- /* Round 3 */
- ROUND(H, a, b, c, d, in[3] + K3, 3);
- ROUND(H, d, a, b, c, in[7] + K3, 9);
- ROUND(H, c, d, a, b, in[2] + K3, 11);
- ROUND(H, b, c, d, a, in[6] + K3, 15);
- ROUND(H, a, b, c, d, in[1] + K3, 3);
- ROUND(H, d, a, b, c, in[5] + K3, 9);
- ROUND(H, c, d, a, b, in[0] + K3, 11);
- ROUND(H, b, c, d, a, in[4] + K3, 15);
-
- buf[0] += a;
- buf[1] += b;
- buf[2] += c;
- buf[3] += d;
-}
-
-#undef ROUND
-#undef F
-#undef G
-#undef H
-#undef K1
-#undef K2
-#undef K3
-
-/* The old legacy hash */
-static ext2_dirhash_t dx_hack_hash (const char *name, int len)
-{
- __u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
- while (len--) {
- __u32 hash = hash1 + (hash0 ^ (*name++ * 7152373));
-
- if (hash & 0x80000000) hash -= 0x7fffffff;
- hash1 = hash0;
- hash0 = hash;
- }
- return (hash0 << 1);
-}
-
-static void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
-{
- __u32 pad, val;
- int i;
-
- pad = (__u32)len | ((__u32)len << 8);
- pad |= pad << 16;
-
- val = pad;
- if (len > num*4)
- len = num * 4;
- for (i=0; i < len; i++) {
- if ((i % 4) == 0)
- val = pad;
- val = msg[i] + (val << 8);
- if ((i % 4) == 3) {
- *buf++ = val;
- val = pad;
- num--;
- }
- }
- if (--num >= 0)
- *buf++ = val;
- while (--num >= 0)
- *buf++ = pad;
-}
-
-/*
- * Returns the hash of a filename. If len is 0 and name is NULL, then
- * this function can be used to test whether or not a hash version is
- * supported.
- *
- * The seed is an 4 longword (32 bits) "secret" which can be used to
- * uniquify a hash. If the seed is all zero's, then some default seed
- * may be used.
- *
- * A particular hash version specifies whether or not the seed is
- * represented, and whether or not the returned hash is 32 bits or 64
- * bits. 32 bit hashes will return 0 for the minor hash.
- */
-errcode_t ext2fs_dirhash(int version, const char *name, int len,
- const __u32 *seed,
- ext2_dirhash_t *ret_hash,
- ext2_dirhash_t *ret_minor_hash)
-{
- __u32 hash;
- __u32 minor_hash = 0;
- const char *p;
- int i;
- __u32 in[8], buf[4];
-
- /* Initialize the default seed for the hash checksum functions */
- buf[0] = 0x67452301;
- buf[1] = 0xefcdab89;
- buf[2] = 0x98badcfe;
- buf[3] = 0x10325476;
-
- /* Check to see if the seed is all zero's */
- if (seed) {
- for (i=0; i < 4; i++) {
- if (seed[i])
- break;
- }
- if (i < 4)
- memcpy(buf, seed, sizeof(buf));
- }
-
- switch (version) {
- case EXT2_HASH_LEGACY:
- hash = dx_hack_hash(name, len);
- break;
- case EXT2_HASH_HALF_MD4:
- p = name;
- while (len > 0) {
- str2hashbuf(p, len, in, 8);
- halfMD4Transform(buf, in);
- len -= 32;
- p += 32;
- }
- minor_hash = buf[2];
- hash = buf[1];
- break;
- case EXT2_HASH_TEA:
- p = name;
- while (len > 0) {
- str2hashbuf(p, len, in, 4);
- TEA_transform(buf, in);
- len -= 16;
- p += 16;
- }
- hash = buf[0];
- minor_hash = buf[1];
- break;
- default:
- *ret_hash = 0;
- return EXT2_ET_DIRHASH_UNSUPP;
- }
- *ret_hash = hash & ~1;
- if (ret_minor_hash)
- *ret_minor_hash = minor_hash;
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dupfs.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dupfs.c
deleted file mode 100644
index d1879377a0..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dupfs.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * dupfs.c --- duplicate a ext2 filesystem handle
- *
- * Copyright (C) 1997, 1998, 2001, 2003, 2005 by Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <time.h>
-#include <string.h>
-
-#include "ext2_fs.h"
-#include "ext2fsP.h"
-
-errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest)
-{
- ext2_filsys fs;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(src, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
- if (retval)
- return retval;
-
- *fs = *src;
- fs->device_name = 0;
- fs->super = 0;
- fs->orig_super = 0;
- fs->group_desc = 0;
- fs->inode_map = 0;
- fs->block_map = 0;
- fs->badblocks = 0;
- fs->dblist = 0;
-
- io_channel_bumpcount(fs->io);
- if (fs->icache)
- fs->icache->refcount++;
-
- retval = ext2fs_get_mem(strlen(src->device_name)+1, &fs->device_name);
- if (retval)
- goto errout;
- strcpy(fs->device_name, src->device_name);
-
- retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->super);
- if (retval)
- goto errout;
- memcpy(fs->super, src->super, SUPERBLOCK_SIZE);
-
- retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super);
- if (retval)
- goto errout;
- memcpy(fs->orig_super, src->orig_super, SUPERBLOCK_SIZE);
-
- retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize,
- &fs->group_desc);
- if (retval)
- goto errout;
- memcpy(fs->group_desc, src->group_desc,
- (size_t) fs->desc_blocks * fs->blocksize);
-
- if (src->inode_map) {
- retval = ext2fs_copy_bitmap(src->inode_map, &fs->inode_map);
- if (retval)
- goto errout;
- }
- if (src->block_map) {
- retval = ext2fs_copy_bitmap(src->block_map, &fs->block_map);
- if (retval)
- goto errout;
- }
- if (src->badblocks) {
- retval = ext2fs_badblocks_copy(src->badblocks, &fs->badblocks);
- if (retval)
- goto errout;
- }
- if (src->dblist) {
- retval = ext2fs_copy_dblist(src->dblist, &fs->dblist);
- if (retval)
- goto errout;
- }
- *dest = fs;
- return 0;
-errout:
- ext2fs_free(fs);
- return retval;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/e2image.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/e2image.h
deleted file mode 100644
index a598d01117..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/e2image.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * e2image.h --- header file describing the ext2 image format
- *
- * Copyright (C) 2000 Theodore Ts'o.
- *
- * Note: this uses the POSIX IO interfaces, unlike most of the other
- * functions in this library. So sue me.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-
-struct ext2_image_hdr {
- __u32 magic_number; /* This must be EXT2_ET_MAGIC_E2IMAGE */
- char magic_descriptor[16]; /* "Ext2 Image 1.0", w/ null padding */
- char fs_hostname[64];/* Hostname of machine of image */
- char fs_netaddr[32]; /* Network address */
- __u32 fs_netaddr_type;/* 0 = IPV4, 1 = IPV6, etc. */
- __u32 fs_device; /* Device number of image */
- char fs_device_name[64]; /* Device name */
- char fs_uuid[16]; /* UUID of filesystem */
- __u32 fs_blocksize; /* Block size of the filesystem */
- __u32 fs_reserved[8];
-
- __u32 image_device; /* Device number of image file */
- __u32 image_inode; /* Inode number of image file */
- __u32 image_time; /* Time of image creation */
- __u32 image_reserved[8];
-
- __u32 offset_super; /* Byte offset of the sb and descriptors */
- __u32 offset_inode; /* Byte offset of the inode table */
- __u32 offset_inodemap; /* Byte offset of the inode bitmaps */
- __u32 offset_blockmap; /* Byte offset of the inode bitmaps */
- __u32 offset_reserved[8];
-};
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/expanddir.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/expanddir.c
deleted file mode 100644
index 8a29ae5849..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/expanddir.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * expand.c --- expand an ext2fs directory
- *
- * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-struct expand_dir_struct {
- int done;
- int newblocks;
- errcode_t err;
-};
-
-static int expand_dir_proc(ext2_filsys fs,
- blk_t *blocknr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block EXT2FS_ATTR((unused)),
- int ref_offset EXT2FS_ATTR((unused)),
- void *priv_data)
-{
- struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
- blk_t new_blk;
- static blk_t last_blk = 0;
- char *block;
- errcode_t retval;
-
- if (*blocknr) {
- last_blk = *blocknr;
- return 0;
- }
- retval = ext2fs_new_block(fs, last_blk, 0, &new_blk);
- if (retval) {
- es->err = retval;
- return BLOCK_ABORT;
- }
- if (blockcnt > 0) {
- retval = ext2fs_new_dir_block(fs, 0, 0, &block);
- if (retval) {
- es->err = retval;
- return BLOCK_ABORT;
- }
- es->done = 1;
- retval = ext2fs_write_dir_block(fs, new_blk, block);
- } else {
- retval = ext2fs_get_mem(fs->blocksize, &block);
- if (retval) {
- es->err = retval;
- return BLOCK_ABORT;
- }
- memset(block, 0, fs->blocksize);
- retval = io_channel_write_blk(fs->io, new_blk, 1, block);
- }
- if (retval) {
- es->err = retval;
- return BLOCK_ABORT;
- }
- ext2fs_free_mem(&block);
- *blocknr = new_blk;
- ext2fs_block_alloc_stats(fs, new_blk, +1);
- es->newblocks++;
-
- if (es->done)
- return (BLOCK_CHANGED | BLOCK_ABORT);
- else
- return BLOCK_CHANGED;
-}
-
-errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir)
-{
- errcode_t retval;
- struct expand_dir_struct es;
- struct ext2_inode inode;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!(fs->flags & EXT2_FLAG_RW))
- return EXT2_ET_RO_FILSYS;
-
- if (!fs->block_map)
- return EXT2_ET_NO_BLOCK_BITMAP;
-
- retval = ext2fs_check_directory(fs, dir);
- if (retval)
- return retval;
-
- es.done = 0;
- es.err = 0;
- es.newblocks = 0;
-
- retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
- 0, expand_dir_proc, &es);
-
- if (es.err)
- return es.err;
- if (!es.done)
- return EXT2_ET_EXPAND_DIR_ERR;
-
- /*
- * Update the size and block count fields in the inode.
- */
- retval = ext2fs_read_inode(fs, dir, &inode);
- if (retval)
- return retval;
-
- inode.i_size += fs->blocksize;
- inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
-
- retval = ext2fs_write_inode(fs, dir, &inode);
- if (retval)
- return retval;
-
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_err.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_err.h
deleted file mode 100644
index ead352810a..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_err.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * ext2_err.h:
- * This file is automatically generated; please do not edit it.
- */
-
-#define EXT2_ET_BASE (2133571328L)
-#define EXT2_ET_MAGIC_EXT2FS_FILSYS (2133571329L)
-#define EXT2_ET_MAGIC_BADBLOCKS_LIST (2133571330L)
-#define EXT2_ET_MAGIC_BADBLOCKS_ITERATE (2133571331L)
-#define EXT2_ET_MAGIC_INODE_SCAN (2133571332L)
-#define EXT2_ET_MAGIC_IO_CHANNEL (2133571333L)
-#define EXT2_ET_MAGIC_UNIX_IO_CHANNEL (2133571334L)
-#define EXT2_ET_MAGIC_IO_MANAGER (2133571335L)
-#define EXT2_ET_MAGIC_BLOCK_BITMAP (2133571336L)
-#define EXT2_ET_MAGIC_INODE_BITMAP (2133571337L)
-#define EXT2_ET_MAGIC_GENERIC_BITMAP (2133571338L)
-#define EXT2_ET_MAGIC_TEST_IO_CHANNEL (2133571339L)
-#define EXT2_ET_MAGIC_DBLIST (2133571340L)
-#define EXT2_ET_MAGIC_ICOUNT (2133571341L)
-#define EXT2_ET_MAGIC_PQ_IO_CHANNEL (2133571342L)
-#define EXT2_ET_MAGIC_EXT2_FILE (2133571343L)
-#define EXT2_ET_MAGIC_E2IMAGE (2133571344L)
-#define EXT2_ET_MAGIC_INODE_IO_CHANNEL (2133571345L)
-#define EXT2_ET_MAGIC_RESERVED_9 (2133571346L)
-#define EXT2_ET_BAD_MAGIC (2133571347L)
-#define EXT2_ET_REV_TOO_HIGH (2133571348L)
-#define EXT2_ET_RO_FILSYS (2133571349L)
-#define EXT2_ET_GDESC_READ (2133571350L)
-#define EXT2_ET_GDESC_WRITE (2133571351L)
-#define EXT2_ET_GDESC_BAD_BLOCK_MAP (2133571352L)
-#define EXT2_ET_GDESC_BAD_INODE_MAP (2133571353L)
-#define EXT2_ET_GDESC_BAD_INODE_TABLE (2133571354L)
-#define EXT2_ET_INODE_BITMAP_WRITE (2133571355L)
-#define EXT2_ET_INODE_BITMAP_READ (2133571356L)
-#define EXT2_ET_BLOCK_BITMAP_WRITE (2133571357L)
-#define EXT2_ET_BLOCK_BITMAP_READ (2133571358L)
-#define EXT2_ET_INODE_TABLE_WRITE (2133571359L)
-#define EXT2_ET_INODE_TABLE_READ (2133571360L)
-#define EXT2_ET_NEXT_INODE_READ (2133571361L)
-#define EXT2_ET_UNEXPECTED_BLOCK_SIZE (2133571362L)
-#define EXT2_ET_DIR_CORRUPTED (2133571363L)
-#define EXT2_ET_SHORT_READ (2133571364L)
-#define EXT2_ET_SHORT_WRITE (2133571365L)
-#define EXT2_ET_DIR_NO_SPACE (2133571366L)
-#define EXT2_ET_NO_INODE_BITMAP (2133571367L)
-#define EXT2_ET_NO_BLOCK_BITMAP (2133571368L)
-#define EXT2_ET_BAD_INODE_NUM (2133571369L)
-#define EXT2_ET_BAD_BLOCK_NUM (2133571370L)
-#define EXT2_ET_EXPAND_DIR_ERR (2133571371L)
-#define EXT2_ET_TOOSMALL (2133571372L)
-#define EXT2_ET_BAD_BLOCK_MARK (2133571373L)
-#define EXT2_ET_BAD_BLOCK_UNMARK (2133571374L)
-#define EXT2_ET_BAD_BLOCK_TEST (2133571375L)
-#define EXT2_ET_BAD_INODE_MARK (2133571376L)
-#define EXT2_ET_BAD_INODE_UNMARK (2133571377L)
-#define EXT2_ET_BAD_INODE_TEST (2133571378L)
-#define EXT2_ET_FUDGE_BLOCK_BITMAP_END (2133571379L)
-#define EXT2_ET_FUDGE_INODE_BITMAP_END (2133571380L)
-#define EXT2_ET_BAD_IND_BLOCK (2133571381L)
-#define EXT2_ET_BAD_DIND_BLOCK (2133571382L)
-#define EXT2_ET_BAD_TIND_BLOCK (2133571383L)
-#define EXT2_ET_NEQ_BLOCK_BITMAP (2133571384L)
-#define EXT2_ET_NEQ_INODE_BITMAP (2133571385L)
-#define EXT2_ET_BAD_DEVICE_NAME (2133571386L)
-#define EXT2_ET_MISSING_INODE_TABLE (2133571387L)
-#define EXT2_ET_CORRUPT_SUPERBLOCK (2133571388L)
-#define EXT2_ET_BAD_GENERIC_MARK (2133571389L)
-#define EXT2_ET_BAD_GENERIC_UNMARK (2133571390L)
-#define EXT2_ET_BAD_GENERIC_TEST (2133571391L)
-#define EXT2_ET_SYMLINK_LOOP (2133571392L)
-#define EXT2_ET_CALLBACK_NOTHANDLED (2133571393L)
-#define EXT2_ET_BAD_BLOCK_IN_INODE_TABLE (2133571394L)
-#define EXT2_ET_UNSUPP_FEATURE (2133571395L)
-#define EXT2_ET_RO_UNSUPP_FEATURE (2133571396L)
-#define EXT2_ET_LLSEEK_FAILED (2133571397L)
-#define EXT2_ET_NO_MEMORY (2133571398L)
-#define EXT2_ET_INVALID_ARGUMENT (2133571399L)
-#define EXT2_ET_BLOCK_ALLOC_FAIL (2133571400L)
-#define EXT2_ET_INODE_ALLOC_FAIL (2133571401L)
-#define EXT2_ET_NO_DIRECTORY (2133571402L)
-#define EXT2_ET_TOO_MANY_REFS (2133571403L)
-#define EXT2_ET_FILE_NOT_FOUND (2133571404L)
-#define EXT2_ET_FILE_RO (2133571405L)
-#define EXT2_ET_DB_NOT_FOUND (2133571406L)
-#define EXT2_ET_DIR_EXISTS (2133571407L)
-#define EXT2_ET_UNIMPLEMENTED (2133571408L)
-#define EXT2_ET_CANCEL_REQUESTED (2133571409L)
-#define EXT2_ET_FILE_TOO_BIG (2133571410L)
-#define EXT2_ET_JOURNAL_NOT_BLOCK (2133571411L)
-#define EXT2_ET_NO_JOURNAL_SB (2133571412L)
-#define EXT2_ET_JOURNAL_TOO_SMALL (2133571413L)
-#define EXT2_ET_JOURNAL_UNSUPP_VERSION (2133571414L)
-#define EXT2_ET_LOAD_EXT_JOURNAL (2133571415L)
-#define EXT2_ET_NO_JOURNAL (2133571416L)
-#define EXT2_ET_DIRHASH_UNSUPP (2133571417L)
-#define EXT2_ET_BAD_EA_BLOCK_NUM (2133571418L)
-#define EXT2_ET_TOO_MANY_INODES (2133571419L)
-#define EXT2_ET_NOT_IMAGE_FILE (2133571420L)
-#define EXT2_ET_RES_GDT_BLOCKS (2133571421L)
-#define EXT2_ET_RESIZE_INODE_CORRUPT (2133571422L)
-#define EXT2_ET_SET_BMAP_NO_IND (2133571423L)
-
-#if 0
-extern const struct error_table et_ext2_error_table;
-extern void initialize_ext2_error_table(void);
-
-/* For compatibility with Heimdal */
-extern void initialize_ext2_error_table_r(struct et_list **list);
-
-#define ERROR_TABLE_BASE_ext2 (2133571328L)
-
-/* for compatibility with older versions... */
-#define init_ext2_err_tbl initialize_ext2_error_table
-#define ext2_err_base ERROR_TABLE_BASE_ext2
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_ext_attr.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_ext_attr.h
deleted file mode 100644
index ca309c0d03..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_ext_attr.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- File: linux/ext2_ext_attr.h
-
- On-disk format of extended attributes for the ext2 filesystem.
-
- (C) 2000 Andreas Gruenbacher, <a.gruenbacher@computer.org>
-*/
-
-/* Magic value in attribute blocks */
-#define EXT2_EXT_ATTR_MAGIC_v1 0xEA010000
-#define EXT2_EXT_ATTR_MAGIC 0xEA020000
-
-/* Maximum number of references to one attribute block */
-#define EXT2_EXT_ATTR_REFCOUNT_MAX 1024
-
-struct ext2_ext_attr_header {
- __u32 h_magic; /* magic number for identification */
- __u32 h_refcount; /* reference count */
- __u32 h_blocks; /* number of disk blocks used */
- __u32 h_hash; /* hash value of all attributes */
- __u32 h_reserved[4]; /* zero right now */
-};
-
-struct ext2_ext_attr_entry {
- __u8 e_name_len; /* length of name */
- __u8 e_name_index; /* attribute name index */
- __u16 e_value_offs; /* offset in disk block of value */
- __u32 e_value_block; /* disk block attribute is stored on (n/i) */
- __u32 e_value_size; /* size of attribute value */
- __u32 e_hash; /* hash value of name and value */
-};
-
-#define EXT2_EXT_ATTR_PAD_BITS 2
-#define EXT2_EXT_ATTR_PAD (1<<EXT2_EXT_ATTR_PAD_BITS)
-#define EXT2_EXT_ATTR_ROUND (EXT2_EXT_ATTR_PAD-1)
-#define EXT2_EXT_ATTR_LEN(name_len) \
- (((name_len) + EXT2_EXT_ATTR_ROUND + \
- sizeof(struct ext2_ext_attr_entry)) & ~EXT2_EXT_ATTR_ROUND)
-#define EXT2_EXT_ATTR_NEXT(entry) \
- ( (struct ext2_ext_attr_entry *)( \
- (char *)(entry) + EXT2_EXT_ATTR_LEN((entry)->e_name_len)) )
-#define EXT2_EXT_ATTR_SIZE(size) \
- (((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND)
-#define EXT2_EXT_IS_LAST_ENTRY(entry) (*((__u32 *)(entry)) == 0UL)
-#define EXT2_EXT_ATTR_NAME(entry) \
- (((char *) (entry)) + sizeof(struct ext2_ext_attr_entry))
-#define EXT2_XATTR_LEN(name_len) \
- (((name_len) + EXT2_EXT_ATTR_ROUND + \
- sizeof(struct ext2_xattr_entry)) & ~EXT2_EXT_ATTR_ROUND)
-#define EXT2_XATTR_SIZE(size) \
- (((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND)
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_fs.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_fs.h
deleted file mode 100644
index 80ea2cbddd..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_fs.h
+++ /dev/null
@@ -1,569 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * linux/include/linux/ext2_fs.h
- *
- * Copyright (C) 1992, 1993, 1994, 1995
- * Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * from
- *
- * linux/include/linux/minix_fs.h
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- */
-#ifndef LINUX_EXT2_FS_H
-#define LINUX_EXT2_FS_H 1
-
-#include "ext2_types.h" /* Changed from linux/types.h */
-
-/*
- * Special inode numbers
- */
-#define EXT2_BAD_INO 1 /* Bad blocks inode */
-#define EXT2_ROOT_INO 2 /* Root inode */
-#define EXT2_ACL_IDX_INO 3 /* ACL inode */
-#define EXT2_ACL_DATA_INO 4 /* ACL inode */
-#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
-#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
-#define EXT2_RESIZE_INO 7 /* Reserved group descriptors inode */
-#define EXT2_JOURNAL_INO 8 /* Journal inode */
-
-/* First non-reserved inode for old ext2 filesystems */
-#define EXT2_GOOD_OLD_FIRST_INO 11
-
-/*
- * The second extended file system magic number
- */
-#define EXT2_SUPER_MAGIC 0xEF53
-
-/* Assume that user mode programs are passing in an ext2fs superblock, not
- * a kernel struct super_block. This will allow us to call the feature-test
- * macros from user land. */
-#define EXT2_SB(sb) (sb)
-
-/*
- * Maximal count of links to a file
- */
-#define EXT2_LINK_MAX 32000
-
-/*
- * Macro-instructions used to manage several block sizes
- */
-#define EXT2_MIN_BLOCK_LOG_SIZE 10 /* 1024 */
-#define EXT2_MAX_BLOCK_LOG_SIZE 16 /* 65536 */
-#define EXT2_MIN_BLOCK_SIZE (1 << EXT2_MIN_BLOCK_LOG_SIZE)
-#define EXT2_MAX_BLOCK_SIZE (1 << EXT2_MAX_BLOCK_LOG_SIZE)
-#define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
-#define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
-#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
- EXT2_GOOD_OLD_INODE_SIZE : (s)->s_inode_size)
-#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
- EXT2_GOOD_OLD_FIRST_INO : (s)->s_first_ino)
-#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof(__u32))
-
-/*
- * Macro-instructions used to manage fragments
- */
-#define EXT2_MIN_FRAG_SIZE EXT2_MIN_BLOCK_SIZE
-#define EXT2_MAX_FRAG_SIZE EXT2_MAX_BLOCK_SIZE
-#define EXT2_MIN_FRAG_LOG_SIZE EXT2_MIN_BLOCK_LOG_SIZE
-# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size)
-# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
-
-/*
- * ACL structures
- */
-struct ext2_acl_header /* Header of Access Control Lists */
-{
- __u32 aclh_size;
- __u32 aclh_file_count;
- __u32 aclh_acle_count;
- __u32 aclh_first_acle;
-};
-
-struct ext2_acl_entry /* Access Control List Entry */
-{
- __u32 acle_size;
- __u16 acle_perms; /* Access permissions */
- __u16 acle_type; /* Type of entry */
- __u16 acle_tag; /* User or group identity */
- __u16 acle_pad1;
- __u32 acle_next; /* Pointer on next entry for the */
- /* same inode or on next free entry */
-};
-
-/*
- * Structure of a blocks group descriptor
- */
-struct ext2_group_desc
-{
- __u32 bg_block_bitmap; /* Blocks bitmap block */
- __u32 bg_inode_bitmap; /* Inodes bitmap block */
- __u32 bg_inode_table; /* Inodes table block */
- __u16 bg_free_blocks_count; /* Free blocks count */
- __u16 bg_free_inodes_count; /* Free inodes count */
- __u16 bg_used_dirs_count; /* Directories count */
- __u16 bg_pad;
- __u32 bg_reserved[3];
-};
-
-/*
- * Data structures used by the directory indexing feature
- *
- * Note: all of the multibyte integer fields are little endian.
- */
-
-/*
- * Note: dx_root_info is laid out so that if it should somehow get
- * overlaid by a dirent the two low bits of the hash version will be
- * zero. Therefore, the hash version mod 4 should never be 0.
- * Sincerely, the paranoia department.
- */
-struct ext2_dx_root_info {
- __u32 reserved_zero;
- __u8 hash_version; /* 0 now, 1 at release */
- __u8 info_length; /* 8 */
- __u8 indirect_levels;
- __u8 unused_flags;
-};
-
-#define EXT2_HASH_LEGACY 0
-#define EXT2_HASH_HALF_MD4 1
-#define EXT2_HASH_TEA 2
-
-#define EXT2_HASH_FLAG_INCOMPAT 0x1
-
-struct ext2_dx_entry {
- __u32 hash;
- __u32 block;
-};
-
-struct ext2_dx_countlimit {
- __u16 limit;
- __u16 count;
-};
-
-
-/*
- * Macro-instructions used to manage group descriptors
- */
-#define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->s_blocks_per_group)
-#define EXT2_INODES_PER_GROUP(s) (EXT2_SB(s)->s_inodes_per_group)
-#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s))
-/* limits imposed by 16-bit value gd_free_{blocks,inode}_count */
-#define EXT2_MAX_BLOCKS_PER_GROUP(s) ((1 << 16) - 8)
-#define EXT2_MAX_INODES_PER_GROUP(s) ((1 << 16) - EXT2_INODES_PER_BLOCK(s))
-#define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
-
-/*
- * Constants relative to the data blocks
- */
-#define EXT2_NDIR_BLOCKS 12
-#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
-#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
-#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
-#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
-
-/*
- * Inode flags
- */
-#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */
-#define EXT2_UNRM_FL 0x00000002 /* Undelete */
-#define EXT2_COMPR_FL 0x00000004 /* Compress file */
-#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */
-#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */
-#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */
-#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */
-#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */
-/* Reserved for compression usage... */
-#define EXT2_DIRTY_FL 0x00000100
-#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
-#define EXT2_NOCOMPR_FL 0x00000400 /* Access raw compressed data */
-#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */
-/* End compression flags --- maybe not all used */
-#define EXT2_BTREE_FL 0x00001000 /* btree format dir */
-#define EXT2_INDEX_FL 0x00001000 /* hash-indexed directory */
-#define EXT2_IMAGIC_FL 0x00002000
-#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */
-#define EXT2_NOTAIL_FL 0x00008000 /* file tail should not be merged */
-#define EXT2_DIRSYNC_FL 0x00010000 /* Synchronous directory modifications */
-#define EXT2_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
-#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */
-#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
-
-#define EXT2_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */
-#define EXT2_FL_USER_MODIFIABLE 0x000080FF /* User modifiable flags */
-
-/*
- * ioctl commands
- */
-#define EXT2_IOC_GETFLAGS _IOR('f', 1, long)
-#define EXT2_IOC_SETFLAGS _IOW('f', 2, long)
-#define EXT2_IOC_GETVERSION _IOR('v', 1, long)
-#define EXT2_IOC_SETVERSION _IOW('v', 2, long)
-
-/*
- * Structure of an inode on the disk
- */
-struct ext2_inode {
- __u16 i_mode; /* File mode */
- __u16 i_uid; /* Low 16 bits of Owner Uid */
- __u32 i_size; /* Size in bytes */
- __u32 i_atime; /* Access time */
- __u32 i_ctime; /* Creation time */
- __u32 i_mtime; /* Modification time */
- __u32 i_dtime; /* Deletion Time */
- __u16 i_gid; /* Low 16 bits of Group Id */
- __u16 i_links_count; /* Links count */
- __u32 i_blocks; /* Blocks count */
- __u32 i_flags; /* File flags */
- union {
- struct {
- __u32 l_i_reserved1;
- } linux1;
- struct {
- __u32 h_i_translator;
- } hurd1;
- struct {
- __u32 m_i_reserved1;
- } masix1;
- } osd1; /* OS dependent 1 */
- __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
- __u32 i_generation; /* File version (for NFS) */
- __u32 i_file_acl; /* File ACL */
- __u32 i_dir_acl; /* Directory ACL */
- __u32 i_faddr; /* Fragment address */
- union {
- struct {
- __u8 l_i_frag; /* Fragment number */
- __u8 l_i_fsize; /* Fragment size */
- __u16 i_pad1;
- __u16 l_i_uid_high; /* these 2 fields */
- __u16 l_i_gid_high; /* were reserved2[0] */
- __u32 l_i_reserved2;
- } linux2;
- struct {
- __u8 h_i_frag; /* Fragment number */
- __u8 h_i_fsize; /* Fragment size */
- __u16 h_i_mode_high;
- __u16 h_i_uid_high;
- __u16 h_i_gid_high;
- __u32 h_i_author;
- } hurd2;
- struct {
- __u8 m_i_frag; /* Fragment number */
- __u8 m_i_fsize; /* Fragment size */
- __u16 m_pad1;
- __u32 m_i_reserved2[2];
- } masix2;
- } osd2; /* OS dependent 2 */
-};
-
-/*
- * Permanent part of an large inode on the disk
- */
-struct ext2_inode_large {
- __u16 i_mode; /* File mode */
- __u16 i_uid; /* Low 16 bits of Owner Uid */
- __u32 i_size; /* Size in bytes */
- __u32 i_atime; /* Access time */
- __u32 i_ctime; /* Creation time */
- __u32 i_mtime; /* Modification time */
- __u32 i_dtime; /* Deletion Time */
- __u16 i_gid; /* Low 16 bits of Group Id */
- __u16 i_links_count; /* Links count */
- __u32 i_blocks; /* Blocks count */
- __u32 i_flags; /* File flags */
- union {
- struct {
- __u32 l_i_reserved1;
- } linux1;
- struct {
- __u32 h_i_translator;
- } hurd1;
- struct {
- __u32 m_i_reserved1;
- } masix1;
- } osd1; /* OS dependent 1 */
- __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
- __u32 i_generation; /* File version (for NFS) */
- __u32 i_file_acl; /* File ACL */
- __u32 i_dir_acl; /* Directory ACL */
- __u32 i_faddr; /* Fragment address */
- union {
- struct {
- __u8 l_i_frag; /* Fragment number */
- __u8 l_i_fsize; /* Fragment size */
- __u16 i_pad1;
- __u16 l_i_uid_high; /* these 2 fields */
- __u16 l_i_gid_high; /* were reserved2[0] */
- __u32 l_i_reserved2;
- } linux2;
- struct {
- __u8 h_i_frag; /* Fragment number */
- __u8 h_i_fsize; /* Fragment size */
- __u16 h_i_mode_high;
- __u16 h_i_uid_high;
- __u16 h_i_gid_high;
- __u32 h_i_author;
- } hurd2;
- struct {
- __u8 m_i_frag; /* Fragment number */
- __u8 m_i_fsize; /* Fragment size */
- __u16 m_pad1;
- __u32 m_i_reserved2[2];
- } masix2;
- } osd2; /* OS dependent 2 */
- __u16 i_extra_isize;
- __u16 i_pad1;
-};
-
-#define i_size_high i_dir_acl
-
-/*
- * File system states
- */
-#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */
-#define EXT2_ERROR_FS 0x0002 /* Errors detected */
-
-/*
- * Mount flags
- */
-#define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */
-#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */
-#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */
-#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */
-#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */
-#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
-#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
-#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
-
-#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
-#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
-#define test_opt(sb, opt) (EXT2_SB(sb)->s_mount_opt & \
- EXT2_MOUNT_##opt)
-/*
- * Maximal mount counts between two filesystem checks
- */
-#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */
-#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */
-
-/*
- * Behaviour when detecting errors
- */
-#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */
-#define EXT2_ERRORS_RO 2 /* Remount fs read-only */
-#define EXT2_ERRORS_PANIC 3 /* Panic */
-#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE
-
-/*
- * Structure of the super block
- */
-struct ext2_super_block {
- __u32 s_inodes_count; /* Inodes count */
- __u32 s_blocks_count; /* Blocks count */
- __u32 s_r_blocks_count; /* Reserved blocks count */
- __u32 s_free_blocks_count; /* Free blocks count */
- __u32 s_free_inodes_count; /* Free inodes count */
- __u32 s_first_data_block; /* First Data Block */
- __u32 s_log_block_size; /* Block size */
- __s32 s_log_frag_size; /* Fragment size */
- __u32 s_blocks_per_group; /* # Blocks per group */
- __u32 s_frags_per_group; /* # Fragments per group */
- __u32 s_inodes_per_group; /* # Inodes per group */
- __u32 s_mtime; /* Mount time */
- __u32 s_wtime; /* Write time */
- __u16 s_mnt_count; /* Mount count */
- __s16 s_max_mnt_count; /* Maximal mount count */
- __u16 s_magic; /* Magic signature */
- __u16 s_state; /* File system state */
- __u16 s_errors; /* Behaviour when detecting errors */
- __u16 s_minor_rev_level; /* minor revision level */
- __u32 s_lastcheck; /* time of last check */
- __u32 s_checkinterval; /* max. time between checks */
- __u32 s_creator_os; /* OS */
- __u32 s_rev_level; /* Revision level */
- __u16 s_def_resuid; /* Default uid for reserved blocks */
- __u16 s_def_resgid; /* Default gid for reserved blocks */
- /*
- * These fields are for EXT2_DYNAMIC_REV superblocks only.
- *
- * Note: the difference between the compatible feature set and
- * the incompatible feature set is that if there is a bit set
- * in the incompatible feature set that the kernel doesn't
- * know about, it should refuse to mount the filesystem.
- *
- * e2fsck's requirements are more strict; if it doesn't know
- * about a feature in either the compatible or incompatible
- * feature set, it must abort and not try to meddle with
- * things it doesn't understand...
- */
- __u32 s_first_ino; /* First non-reserved inode */
- __u16 s_inode_size; /* size of inode structure */
- __u16 s_block_group_nr; /* block group # of this superblock */
- __u32 s_feature_compat; /* compatible feature set */
- __u32 s_feature_incompat; /* incompatible feature set */
- __u32 s_feature_ro_compat; /* readonly-compatible feature set */
- __u8 s_uuid[16]; /* 128-bit uuid for volume */
- char s_volume_name[16]; /* volume name */
- char s_last_mounted[64]; /* directory where last mounted */
- __u32 s_algorithm_usage_bitmap; /* For compression */
- /*
- * Performance hints. Directory preallocation should only
- * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
- */
- __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
- __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
- __u16 s_reserved_gdt_blocks; /* Per group table for online growth */
- /*
- * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
- */
- __u8 s_journal_uuid[16]; /* uuid of journal superblock */
- __u32 s_journal_inum; /* inode number of journal file */
- __u32 s_journal_dev; /* device number of journal file */
- __u32 s_last_orphan; /* start of list of inodes to delete */
- __u32 s_hash_seed[4]; /* HTREE hash seed */
- __u8 s_def_hash_version; /* Default hash version to use */
- __u8 s_jnl_backup_type; /* Default type of journal backup */
- __u16 s_reserved_word_pad;
- __u32 s_default_mount_opts;
- __u32 s_first_meta_bg; /* First metablock group */
- __u32 s_mkfs_time; /* When the filesystem was created */
- __u32 s_jnl_blocks[17]; /* Backup of the journal inode */
- __u32 s_reserved[172]; /* Padding to the end of the block */
-};
-
-/*
- * Codes for operating systems
- */
-#define EXT2_OS_LINUX 0
-#define EXT2_OS_HURD 1
-#define EXT2_OS_MASIX 2
-#define EXT2_OS_FREEBSD 3
-#define EXT2_OS_LITES 4
-
-/*
- * Revision levels
- */
-#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
-#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
-
-#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV
-#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV
-
-#define EXT2_GOOD_OLD_INODE_SIZE 128
-
-/*
- * Journal inode backup types
- */
-#define EXT3_JNL_BACKUP_BLOCKS 1
-
-/*
- * Feature set definitions
- */
-
-#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \
- ( EXT2_SB(sb)->s_feature_compat & (mask) )
-#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \
- ( EXT2_SB(sb)->s_feature_ro_compat & (mask) )
-#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \
- ( EXT2_SB(sb)->s_feature_incompat & (mask) )
-
-#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001
-#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002
-#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
-#define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008
-#define EXT2_FEATURE_COMPAT_RESIZE_INO 0x0010
-#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020
-
-#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
-#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
-/* #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 not used */
-
-#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
-#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
-#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
-#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
-#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010
-#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040
-
-
-#define EXT2_FEATURE_COMPAT_SUPP 0
-#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE)
-#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
- EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
-
-/*
- * Default values for user and/or group using reserved blocks
- */
-#define EXT2_DEF_RESUID 0
-#define EXT2_DEF_RESGID 0
-
-/*
- * Default mount options
- */
-#define EXT2_DEFM_DEBUG 0x0001
-#define EXT2_DEFM_BSDGROUPS 0x0002
-#define EXT2_DEFM_XATTR_USER 0x0004
-#define EXT2_DEFM_ACL 0x0008
-#define EXT2_DEFM_UID16 0x0010
-#define EXT3_DEFM_JMODE 0x0060
-#define EXT3_DEFM_JMODE_DATA 0x0020
-#define EXT3_DEFM_JMODE_ORDERED 0x0040
-#define EXT3_DEFM_JMODE_WBACK 0x0060
-
-/*
- * Structure of a directory entry
- */
-#define EXT2_NAME_LEN 255
-
-struct ext2_dir_entry {
- __u32 inode; /* Inode number */
- __u16 rec_len; /* Directory entry length */
- __u16 name_len; /* Name length */
- char name[EXT2_NAME_LEN]; /* File name */
-};
-
-/*
- * The new version of the directory entry. Since EXT2 structures are
- * stored in intel byte order, and the name_len field could never be
- * bigger than 255 chars, it's safe to reclaim the extra byte for the
- * file_type field.
- */
-struct ext2_dir_entry_2 {
- __u32 inode; /* Inode number */
- __u16 rec_len; /* Directory entry length */
- __u8 name_len; /* Name length */
- __u8 file_type;
- char name[EXT2_NAME_LEN]; /* File name */
-};
-
-/*
- * Ext2 directory file types. Only the low 3 bits are used. The
- * other bits are reserved for now.
- */
-#define EXT2_FT_UNKNOWN 0
-#define EXT2_FT_REG_FILE 1
-#define EXT2_FT_DIR 2
-#define EXT2_FT_CHRDEV 3
-#define EXT2_FT_BLKDEV 4
-#define EXT2_FT_FIFO 5
-#define EXT2_FT_SOCK 6
-#define EXT2_FT_SYMLINK 7
-
-#define EXT2_FT_MAX 8
-
-/*
- * EXT2_DIR_PAD defines the directory entries boundaries
- *
- * NOTE: It must be a multiple of 4
- */
-#define EXT2_DIR_PAD 4
-#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
-#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
- ~EXT2_DIR_ROUND)
-
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_io.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_io.h
deleted file mode 100644
index 1900a76392..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_io.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * io.h --- the I/O manager abstraction
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-#ifndef EXT2FS_EXT2_IO_H
-#define EXT2FS_EXT2_IO_H 1
-
-/*
- * ext2_loff_t is defined here since unix_io.c needs it.
- */
-#if defined(__GNUC__) || defined(HAS_LONG_LONG)
-typedef long long ext2_loff_t;
-#else
-typedef long ext2_loff_t;
-#endif
-
-/* llseek.c */
-/* ext2_loff_t ext2fs_llseek (int, ext2_loff_t, int); */
-#ifdef CONFIG_LFS
-# define ext2fs_llseek lseek64
-#else
-# define ext2fs_llseek lseek
-#endif
-
-typedef struct struct_io_manager *io_manager;
-typedef struct struct_io_channel *io_channel;
-
-#define CHANNEL_FLAGS_WRITETHROUGH 0x01
-
-struct struct_io_channel {
- errcode_t magic;
- io_manager manager;
- char *name;
- int block_size;
- errcode_t (*read_error)(io_channel channel,
- unsigned long block,
- int count,
- void *data,
- size_t size,
- int actual_bytes_read,
- errcode_t error);
- errcode_t (*write_error)(io_channel channel,
- unsigned long block,
- int count,
- const void *data,
- size_t size,
- int actual_bytes_written,
- errcode_t error);
- int refcount;
- int flags;
- int reserved[14];
- void *private_data;
- void *app_data;
-};
-
-struct struct_io_manager {
- errcode_t magic;
- const char *name;
- errcode_t (*open)(const char *name, int flags, io_channel *channel);
- errcode_t (*close)(io_channel channel);
- errcode_t (*set_blksize)(io_channel channel, int blksize);
- errcode_t (*read_blk)(io_channel channel, unsigned long block,
- int count, void *data);
- errcode_t (*write_blk)(io_channel channel, unsigned long block,
- int count, const void *data);
- errcode_t (*flush)(io_channel channel);
- errcode_t (*write_byte)(io_channel channel, unsigned long offset,
- int count, const void *data);
- errcode_t (*set_option)(io_channel channel, const char *option,
- const char *arg);
- int reserved[14];
-};
-
-#define IO_FLAG_RW 1
-
-/*
- * Convenience functions....
- */
-#define io_channel_close(c) ((c)->manager->close((c)))
-#define io_channel_set_blksize(c,s) ((c)->manager->set_blksize((c),s))
-#define io_channel_read_blk(c,b,n,d) ((c)->manager->read_blk((c),b,n,d))
-#define io_channel_write_blk(c,b,n,d) ((c)->manager->write_blk((c),b,n,d))
-#define io_channel_flush(c) ((c)->manager->flush((c)))
-#define io_channel_bumpcount(c) ((c)->refcount++)
-
-/* io_manager.c */
-extern errcode_t io_channel_set_options(io_channel channel,
- const char *options);
-extern errcode_t io_channel_write_byte(io_channel channel,
- unsigned long offset,
- int count, const void *data);
-
-/* unix_io.c */
-extern io_manager unix_io_manager;
-
-/* test_io.c */
-extern io_manager test_io_manager, test_io_backing_manager;
-extern void (*test_io_cb_read_blk)
- (unsigned long block, int count, errcode_t err);
-extern void (*test_io_cb_write_blk)
- (unsigned long block, int count, errcode_t err);
-extern void (*test_io_cb_set_blksize)
- (int blksize, errcode_t err);
-
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_types.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_types.h
deleted file mode 100644
index 2c1196b8b7..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_types.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* vi: set sw=4 ts=4: */
-#include <linux/types.h>
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs.h
deleted file mode 100644
index ffd096f416..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs.h
+++ /dev/null
@@ -1,926 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * ext2fs.h --- ext2fs
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-#ifndef EXT2FS_EXT2FS_H
-#define EXT2FS_EXT2FS_H 1
-
-
-#ifdef __GNUC__
-# define EXT2FS_ATTR(x) __attribute__(x)
-#else
-# define EXT2FS_ATTR(x)
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Where the master copy of the superblock is located, and how big
- * superblocks are supposed to be. We define SUPERBLOCK_SIZE because
- * the size of the superblock structure is not necessarily trustworthy
- * (some versions have the padding set up so that the superblock is
- * 1032 bytes long).
- */
-#define SUPERBLOCK_OFFSET 1024
-#define SUPERBLOCK_SIZE 1024
-
-/*
- * The last ext2fs revision level that this version of the library is
- * able to support.
- */
-#define EXT2_LIB_CURRENT_REV EXT2_DYNAMIC_REV
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "ext2_types.h"
-#include "ext2_fs.h"
-
-typedef __u32 ext2_ino_t;
-typedef __u32 blk_t;
-typedef __u32 dgrp_t;
-typedef __u32 ext2_off_t;
-typedef __s64 e2_blkcnt_t;
-typedef __u32 ext2_dirhash_t;
-
-#include "ext2_io.h"
-#include "ext2_err.h"
-
-typedef struct struct_ext2_filsys *ext2_filsys;
-
-struct ext2fs_struct_generic_bitmap {
- errcode_t magic;
- ext2_filsys fs;
- __u32 start, end;
- __u32 real_end;
- char * description;
- char * bitmap;
- errcode_t base_error_code;
- __u32 reserved[7];
-};
-
-#define EXT2FS_MARK_ERROR 0
-#define EXT2FS_UNMARK_ERROR 1
-#define EXT2FS_TEST_ERROR 2
-
-typedef struct ext2fs_struct_generic_bitmap *ext2fs_generic_bitmap;
-typedef struct ext2fs_struct_generic_bitmap *ext2fs_inode_bitmap;
-typedef struct ext2fs_struct_generic_bitmap *ext2fs_block_bitmap;
-
-#define EXT2_FIRST_INODE(s) EXT2_FIRST_INO(s)
-
-/*
- * badblocks list definitions
- */
-
-typedef struct ext2_struct_u32_list *ext2_badblocks_list;
-typedef struct ext2_struct_u32_iterate *ext2_badblocks_iterate;
-
-typedef struct ext2_struct_u32_list *ext2_u32_list;
-typedef struct ext2_struct_u32_iterate *ext2_u32_iterate;
-
-/* old */
-typedef struct ext2_struct_u32_list *badblocks_list;
-typedef struct ext2_struct_u32_iterate *badblocks_iterate;
-
-#define BADBLOCKS_FLAG_DIRTY 1
-
-/*
- * ext2_dblist structure and abstractions (see dblist.c)
- */
-struct ext2_db_entry {
- ext2_ino_t ino;
- blk_t blk;
- int blockcnt;
-};
-
-typedef struct ext2_struct_dblist *ext2_dblist;
-
-#define DBLIST_ABORT 1
-
-/*
- * ext2_fileio definitions
- */
-
-#define EXT2_FILE_WRITE 0x0001
-#define EXT2_FILE_CREATE 0x0002
-
-#define EXT2_FILE_MASK 0x00FF
-
-#define EXT2_FILE_BUF_DIRTY 0x4000
-#define EXT2_FILE_BUF_VALID 0x2000
-
-typedef struct ext2_file *ext2_file_t;
-
-#define EXT2_SEEK_SET 0
-#define EXT2_SEEK_CUR 1
-#define EXT2_SEEK_END 2
-
-/*
- * Flags for the ext2_filsys structure and for ext2fs_open()
- */
-#define EXT2_FLAG_RW 0x01
-#define EXT2_FLAG_CHANGED 0x02
-#define EXT2_FLAG_DIRTY 0x04
-#define EXT2_FLAG_VALID 0x08
-#define EXT2_FLAG_IB_DIRTY 0x10
-#define EXT2_FLAG_BB_DIRTY 0x20
-#define EXT2_FLAG_SWAP_BYTES 0x40
-#define EXT2_FLAG_SWAP_BYTES_READ 0x80
-#define EXT2_FLAG_SWAP_BYTES_WRITE 0x100
-#define EXT2_FLAG_MASTER_SB_ONLY 0x200
-#define EXT2_FLAG_FORCE 0x400
-#define EXT2_FLAG_SUPER_ONLY 0x800
-#define EXT2_FLAG_JOURNAL_DEV_OK 0x1000
-#define EXT2_FLAG_IMAGE_FILE 0x2000
-
-/*
- * Special flag in the ext2 inode i_flag field that means that this is
- * a new inode. (So that ext2_write_inode() can clear extra fields.)
- */
-#define EXT2_NEW_INODE_FL 0x80000000
-
-/*
- * Flags for mkjournal
- *
- * EXT2_MKJOURNAL_V1_SUPER Make a (deprecated) V1 journal superblock
- */
-#define EXT2_MKJOURNAL_V1_SUPER 0x0000001
-
-struct struct_ext2_filsys {
- errcode_t magic;
- io_channel io;
- int flags;
- char * device_name;
- struct ext2_super_block * super;
- unsigned int blocksize;
- int fragsize;
- dgrp_t group_desc_count;
- unsigned long desc_blocks;
- struct ext2_group_desc * group_desc;
- int inode_blocks_per_group;
- ext2fs_inode_bitmap inode_map;
- ext2fs_block_bitmap block_map;
- errcode_t (*get_blocks)(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks);
- errcode_t (*check_directory)(ext2_filsys fs, ext2_ino_t ino);
- errcode_t (*write_bitmaps)(ext2_filsys fs);
- errcode_t (*read_inode)(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode);
- errcode_t (*write_inode)(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode);
- ext2_badblocks_list badblocks;
- ext2_dblist dblist;
- __u32 stride; /* for mke2fs */
- struct ext2_super_block * orig_super;
- struct ext2_image_hdr * image_header;
- __u32 umask;
- /*
- * Reserved for future expansion
- */
- __u32 reserved[8];
-
- /*
- * Reserved for the use of the calling application.
- */
- void * priv_data;
-
- /*
- * Inode cache
- */
- struct ext2_inode_cache *icache;
- io_channel image_io;
-};
-
-#include "bitops.h"
-
-/*
- * Return flags for the block iterator functions
- */
-#define BLOCK_CHANGED 1
-#define BLOCK_ABORT 2
-#define BLOCK_ERROR 4
-
-/*
- * Block interate flags
- *
- * BLOCK_FLAG_APPEND, or BLOCK_FLAG_HOLE, indicates that the interator
- * function should be called on blocks where the block number is zero.
- * This is used by ext2fs_expand_dir() to be able to add a new block
- * to an inode. It can also be used for programs that want to be able
- * to deal with files that contain "holes".
- *
- * BLOCK_FLAG_TRAVERSE indicates that the iterator function for the
- * indirect, doubly indirect, etc. blocks should be called after all
- * of the blocks containined in the indirect blocks are processed.
- * This is useful if you are going to be deallocating blocks from an
- * inode.
- *
- * BLOCK_FLAG_DATA_ONLY indicates that the iterator function should be
- * called for data blocks only.
- *
- * BLOCK_FLAG_NO_LARGE is for internal use only. It informs
- * ext2fs_block_iterate2 that large files won't be accepted.
- */
-#define BLOCK_FLAG_APPEND 1
-#define BLOCK_FLAG_HOLE 1
-#define BLOCK_FLAG_DEPTH_TRAVERSE 2
-#define BLOCK_FLAG_DATA_ONLY 4
-
-#define BLOCK_FLAG_NO_LARGE 0x1000
-
-/*
- * Magic "block count" return values for the block iterator function.
- */
-#define BLOCK_COUNT_IND (-1)
-#define BLOCK_COUNT_DIND (-2)
-#define BLOCK_COUNT_TIND (-3)
-#define BLOCK_COUNT_TRANSLATOR (-4)
-
-#if 0
-/*
- * Flags for ext2fs_move_blocks
- */
-#define EXT2_BMOVE_GET_DBLIST 0x0001
-#define EXT2_BMOVE_DEBUG 0x0002
-#endif
-
-/*
- * Flags for directory block reading and writing functions
- */
-#define EXT2_DIRBLOCK_V2_STRUCT 0x0001
-
-/*
- * Return flags for the directory iterator functions
- */
-#define DIRENT_CHANGED 1
-#define DIRENT_ABORT 2
-#define DIRENT_ERROR 3
-
-/*
- * Directory iterator flags
- */
-
-#define DIRENT_FLAG_INCLUDE_EMPTY 1
-#define DIRENT_FLAG_INCLUDE_REMOVED 2
-
-#define DIRENT_DOT_FILE 1
-#define DIRENT_DOT_DOT_FILE 2
-#define DIRENT_OTHER_FILE 3
-#define DIRENT_DELETED_FILE 4
-
-/*
- * Inode scan definitions
- */
-typedef struct ext2_struct_inode_scan *ext2_inode_scan;
-
-/*
- * ext2fs_scan flags
- */
-#define EXT2_SF_CHK_BADBLOCKS 0x0001
-#define EXT2_SF_BAD_INODE_BLK 0x0002
-#define EXT2_SF_BAD_EXTRA_BYTES 0x0004
-#define EXT2_SF_SKIP_MISSING_ITABLE 0x0008
-
-/*
- * ext2fs_check_if_mounted flags
- */
-#define EXT2_MF_MOUNTED 1
-#define EXT2_MF_ISROOT 2
-#define EXT2_MF_READONLY 4
-#define EXT2_MF_SWAP 8
-#define EXT2_MF_BUSY 16
-
-/*
- * Ext2/linux mode flags. We define them here so that we don't need
- * to depend on the OS's sys/stat.h, since we may be compiling on a
- * non-Linux system.
- */
-#define LINUX_S_IFMT 00170000
-#define LINUX_S_IFSOCK 0140000
-#define LINUX_S_IFLNK 0120000
-#define LINUX_S_IFREG 0100000
-#define LINUX_S_IFBLK 0060000
-#define LINUX_S_IFDIR 0040000
-#define LINUX_S_IFCHR 0020000
-#define LINUX_S_IFIFO 0010000
-#define LINUX_S_ISUID 0004000
-#define LINUX_S_ISGID 0002000
-#define LINUX_S_ISVTX 0001000
-
-#define LINUX_S_IRWXU 00700
-#define LINUX_S_IRUSR 00400
-#define LINUX_S_IWUSR 00200
-#define LINUX_S_IXUSR 00100
-
-#define LINUX_S_IRWXG 00070
-#define LINUX_S_IRGRP 00040
-#define LINUX_S_IWGRP 00020
-#define LINUX_S_IXGRP 00010
-
-#define LINUX_S_IRWXO 00007
-#define LINUX_S_IROTH 00004
-#define LINUX_S_IWOTH 00002
-#define LINUX_S_IXOTH 00001
-
-#define LINUX_S_ISLNK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFLNK)
-#define LINUX_S_ISREG(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFREG)
-#define LINUX_S_ISDIR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFDIR)
-#define LINUX_S_ISCHR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFCHR)
-#define LINUX_S_ISBLK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFBLK)
-#define LINUX_S_ISFIFO(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFIFO)
-#define LINUX_S_ISSOCK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFSOCK)
-
-/*
- * ext2 size of an inode
- */
-#define EXT2_I_SIZE(i) ((i)->i_size | ((__u64) (i)->i_size_high << 32))
-
-/*
- * ext2_icount_t abstraction
- */
-#define EXT2_ICOUNT_OPT_INCREMENT 0x01
-
-typedef struct ext2_icount *ext2_icount_t;
-
-/*
- * Flags for ext2fs_bmap
- */
-#define BMAP_ALLOC 0x0001
-#define BMAP_SET 0x0002
-
-/*
- * Flags for imager.c functions
- */
-#define IMAGER_FLAG_INODEMAP 1
-#define IMAGER_FLAG_SPARSEWRITE 2
-
-/*
- * For checking structure magic numbers...
- */
-
-#define EXT2_CHECK_MAGIC(struct, code) \
- if ((struct)->magic != (code)) return (code)
-
-
-/*
- * For ext2 compression support
- */
-#define EXT2FS_COMPRESSED_BLKADDR ((blk_t) 0xffffffff)
-#define HOLE_BLKADDR(_b) ((_b) == 0 || (_b) == EXT2FS_COMPRESSED_BLKADDR)
-
-/*
- * Features supported by this version of the library
- */
-#define EXT2_LIB_FEATURE_COMPAT_SUPP (EXT2_FEATURE_COMPAT_DIR_PREALLOC|\
- EXT2_FEATURE_COMPAT_IMAGIC_INODES|\
- EXT3_FEATURE_COMPAT_HAS_JOURNAL|\
- EXT2_FEATURE_COMPAT_RESIZE_INO|\
- EXT2_FEATURE_COMPAT_DIR_INDEX|\
- EXT2_FEATURE_COMPAT_EXT_ATTR)
-
-/* This #ifdef is temporary until compression is fully supported */
-#ifdef ENABLE_COMPRESSION
-#ifndef I_KNOW_THAT_COMPRESSION_IS_EXPERIMENTAL
-/* If the below warning bugs you, then have
- `CPPFLAGS=-DI_KNOW_THAT_COMPRESSION_IS_EXPERIMENTAL' in your
- environment at configure time. */
- #warning "Compression support is experimental"
-#endif
-#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\
- EXT2_FEATURE_INCOMPAT_COMPRESSION|\
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
- EXT2_FEATURE_INCOMPAT_META_BG|\
- EXT3_FEATURE_INCOMPAT_RECOVER)
-#else
-#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
- EXT2_FEATURE_INCOMPAT_META_BG|\
- EXT3_FEATURE_INCOMPAT_RECOVER)
-#endif
-#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE)
-/*
- * function prototypes
- */
-
-/* alloc.c */
-extern errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir, int mode,
- ext2fs_inode_bitmap map, ext2_ino_t *ret);
-extern errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
- ext2fs_block_bitmap map, blk_t *ret);
-extern errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start,
- blk_t finish, int num,
- ext2fs_block_bitmap map,
- blk_t *ret);
-extern errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
- char *block_buf, blk_t *ret);
-
-/* alloc_sb.c */
-extern int ext2fs_reserve_super_and_bgd(ext2_filsys fs,
- dgrp_t group,
- ext2fs_block_bitmap bmap);
-
-/* alloc_stats.c */
-void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse);
-void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino,
- int inuse, int isdir);
-void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse);
-
-/* alloc_tables.c */
-extern errcode_t ext2fs_allocate_tables(ext2_filsys fs);
-extern errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
- ext2fs_block_bitmap bmap);
-
-/* badblocks.c */
-extern errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size);
-extern errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk);
-extern int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk);
-extern int ext2fs_u32_list_test(ext2_u32_list bb, blk_t blk);
-extern errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb,
- ext2_u32_iterate *ret);
-extern int ext2fs_u32_list_iterate(ext2_u32_iterate iter, blk_t *blk);
-extern void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter);
-extern errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest);
-extern int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2);
-
-extern errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret,
- int size);
-extern errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb,
- blk_t blk);
-extern int ext2fs_badblocks_list_test(ext2_badblocks_list bb,
- blk_t blk);
-extern int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk);
-extern void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk);
-extern errcode_t
- ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
- ext2_badblocks_iterate *ret);
-extern int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter,
- blk_t *blk);
-extern void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter);
-extern errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
- ext2_badblocks_list *dest);
-extern int ext2fs_badblocks_equal(ext2_badblocks_list bb1,
- ext2_badblocks_list bb2);
-extern int ext2fs_u32_list_count(ext2_u32_list bb);
-
-/* bb_compat */
-extern errcode_t badblocks_list_create(badblocks_list *ret, int size);
-extern errcode_t badblocks_list_add(badblocks_list bb, blk_t blk);
-extern int badblocks_list_test(badblocks_list bb, blk_t blk);
-extern errcode_t badblocks_list_iterate_begin(badblocks_list bb,
- badblocks_iterate *ret);
-extern int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk);
-extern void badblocks_list_iterate_end(badblocks_iterate iter);
-extern void badblocks_list_free(badblocks_list bb);
-
-/* bb_inode.c */
-extern errcode_t ext2fs_update_bb_inode(ext2_filsys fs,
- ext2_badblocks_list bb_list);
-
-/* bitmaps.c */
-extern errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs);
-extern errcode_t ext2fs_write_block_bitmap (ext2_filsys fs);
-extern errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs);
-extern errcode_t ext2fs_read_block_bitmap(ext2_filsys fs);
-extern errcode_t ext2fs_allocate_generic_bitmap(__u32 start,
- __u32 end,
- __u32 real_end,
- const char *descr,
- ext2fs_generic_bitmap *ret);
-extern errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
- const char *descr,
- ext2fs_block_bitmap *ret);
-extern errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs,
- const char *descr,
- ext2fs_inode_bitmap *ret);
-extern errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap,
- ext2_ino_t end, ext2_ino_t *oend);
-extern errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap,
- blk_t end, blk_t *oend);
-extern void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap);
-extern void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap);
-extern errcode_t ext2fs_read_bitmaps(ext2_filsys fs);
-extern errcode_t ext2fs_write_bitmaps(ext2_filsys fs);
-
-/* block.c */
-extern errcode_t ext2fs_block_iterate(ext2_filsys fs,
- ext2_ino_t ino,
- int flags,
- char *block_buf,
- int (*func)(ext2_filsys fs,
- blk_t *blocknr,
- int blockcnt,
- void *priv_data),
- void *priv_data);
-errcode_t ext2fs_block_iterate2(ext2_filsys fs,
- ext2_ino_t ino,
- int flags,
- char *block_buf,
- int (*func)(ext2_filsys fs,
- blk_t *blocknr,
- e2_blkcnt_t blockcnt,
- blk_t ref_blk,
- int ref_offset,
- void *priv_data),
- void *priv_data);
-
-/* bmap.c */
-extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode,
- char *block_buf, int bmap_flags,
- blk_t block, blk_t *phys_blk);
-
-
-#if 0
-/* bmove.c */
-extern errcode_t ext2fs_move_blocks(ext2_filsys fs,
- ext2fs_block_bitmap reserve,
- ext2fs_block_bitmap alloc_map,
- int flags);
-#endif
-
-/* check_desc.c */
-extern errcode_t ext2fs_check_desc(ext2_filsys fs);
-
-/* closefs.c */
-extern errcode_t ext2fs_close(ext2_filsys fs);
-extern errcode_t ext2fs_flush(ext2_filsys fs);
-extern int ext2fs_bg_has_super(ext2_filsys fs, int group_block);
-extern int ext2fs_super_and_bgd_loc(ext2_filsys fs,
- dgrp_t group,
- blk_t *ret_super_blk,
- blk_t *ret_old_desc_blk,
- blk_t *ret_new_desc_blk,
- int *ret_meta_bg);
-extern void ext2fs_update_dynamic_rev(ext2_filsys fs);
-
-/* cmp_bitmaps.c */
-extern errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
- ext2fs_block_bitmap bm2);
-extern errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
- ext2fs_inode_bitmap bm2);
-
-/* dblist.c */
-
-extern errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs);
-extern errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist);
-extern errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino,
- blk_t blk, int blockcnt);
-extern void ext2fs_dblist_sort(ext2_dblist dblist,
- int (*sortfunc)(const void *,
- const void *));
-extern errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
- int (*func)(ext2_filsys fs, struct ext2_db_entry *db_info,
- void *priv_data),
- void *priv_data);
-extern errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino,
- blk_t blk, int blockcnt);
-extern errcode_t ext2fs_copy_dblist(ext2_dblist src,
- ext2_dblist *dest);
-extern int ext2fs_dblist_count(ext2_dblist dblist);
-
-/* dblist_dir.c */
-extern errcode_t
- ext2fs_dblist_dir_iterate(ext2_dblist dblist,
- int flags,
- char *block_buf,
- int (*func)(ext2_ino_t dir,
- int entry,
- struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *priv_data),
- void *priv_data);
-
-/* dirblock.c */
-extern errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
- void *buf);
-extern errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
- void *buf, int flags);
-extern errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
- void *buf);
-extern errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
- void *buf, int flags);
-
-/* dirhash.c */
-extern errcode_t ext2fs_dirhash(int version, const char *name, int len,
- const __u32 *seed,
- ext2_dirhash_t *ret_hash,
- ext2_dirhash_t *ret_minor_hash);
-
-
-/* dir_iterate.c */
-extern errcode_t ext2fs_dir_iterate(ext2_filsys fs,
- ext2_ino_t dir,
- int flags,
- char *block_buf,
- int (*func)(struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *priv_data),
- void *priv_data);
-extern errcode_t ext2fs_dir_iterate2(ext2_filsys fs,
- ext2_ino_t dir,
- int flags,
- char *block_buf,
- int (*func)(ext2_ino_t dir,
- int entry,
- struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *priv_data),
- void *priv_data);
-
-/* dupfs.c */
-extern errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest);
-
-/* expanddir.c */
-extern errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir);
-
-/* ext_attr.c */
-extern errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf);
-extern errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block,
- void *buf);
-extern errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk,
- char *block_buf,
- int adjust, __u32 *newcount);
-
-/* fileio.c */
-extern errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode,
- int flags, ext2_file_t *ret);
-extern errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino,
- int flags, ext2_file_t *ret);
-extern ext2_filsys ext2fs_file_get_fs(ext2_file_t file);
-extern errcode_t ext2fs_file_close(ext2_file_t file);
-extern errcode_t ext2fs_file_flush(ext2_file_t file);
-extern errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
- unsigned int wanted, unsigned int *got);
-extern errcode_t ext2fs_file_write(ext2_file_t file, const void *buf,
- unsigned int nbytes, unsigned int *written);
-extern errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset,
- int whence, __u64 *ret_pos);
-extern errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
- int whence, ext2_off_t *ret_pos);
-errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size);
-extern ext2_off_t ext2fs_file_get_size(ext2_file_t file);
-extern errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size);
-
-/* finddev.c */
-extern char *ext2fs_find_block_device(dev_t device);
-
-/* flushb.c */
-extern errcode_t ext2fs_sync_device(int fd, int flushb);
-
-/* freefs.c */
-extern void ext2fs_free(ext2_filsys fs);
-extern void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap);
-extern void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap);
-extern void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap);
-extern void ext2fs_free_dblist(ext2_dblist dblist);
-extern void ext2fs_badblocks_list_free(ext2_badblocks_list bb);
-extern void ext2fs_u32_list_free(ext2_u32_list bb);
-
-/* getsize.c */
-extern errcode_t ext2fs_get_device_size(const char *file, int blocksize,
- blk_t *retblocks);
-
-/* getsectsize.c */
-errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize);
-
-/* imager.c */
-extern errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags);
-extern errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd, int flags);
-extern errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, int flags);
-extern errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd, int flags);
-extern errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags);
-extern errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags);
-
-/* ind_block.c */
-errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf);
-errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf);
-
-/* initialize.c */
-extern errcode_t ext2fs_initialize(const char *name, int flags,
- struct ext2_super_block *param,
- io_manager manager, ext2_filsys *ret_fs);
-
-/* icount.c */
-extern void ext2fs_free_icount(ext2_icount_t icount);
-extern errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags,
- unsigned int size,
- ext2_icount_t hint, ext2_icount_t *ret);
-extern errcode_t ext2fs_create_icount(ext2_filsys fs, int flags,
- unsigned int size,
- ext2_icount_t *ret);
-extern errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino,
- __u16 *ret);
-extern errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino,
- __u16 *ret);
-extern errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
- __u16 *ret);
-extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
- __u16 count);
-extern ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount);
-errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *);
-
-/* inode.c */
-extern errcode_t ext2fs_flush_icache(ext2_filsys fs);
-extern errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan,
- ext2_ino_t *ino,
- struct ext2_inode *inode,
- int bufsize);
-extern errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
- ext2_inode_scan *ret_scan);
-extern void ext2fs_close_inode_scan(ext2_inode_scan scan);
-extern errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino,
- struct ext2_inode *inode);
-extern errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,
- int group);
-extern void ext2fs_set_inode_callback
- (ext2_inode_scan scan,
- errcode_t (*done_group)(ext2_filsys fs,
- dgrp_t group,
- void * priv_data),
- void *done_group_data);
-extern int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags,
- int clear_flags);
-extern errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode * inode,
- int bufsize);
-extern errcode_t ext2fs_read_inode (ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode * inode);
-extern errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode * inode,
- int bufsize);
-extern errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode * inode);
-extern errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode * inode);
-extern errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks);
-extern errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino);
-
-/* inode_io.c */
-extern io_manager inode_io_manager;
-extern errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino,
- char **name);
-extern errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode,
- char **name);
-
-/* ismounted.c */
-extern errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags);
-extern errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags,
- char *mtpt, int mtlen);
-
-/* namei.c */
-extern errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name,
- int namelen, char *buf, ext2_ino_t *inode);
-extern errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
- const char *name, ext2_ino_t *inode);
-errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
- const char *name, ext2_ino_t *inode);
-extern errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
- ext2_ino_t inode, ext2_ino_t *res_inode);
-
-/* native.c */
-int ext2fs_native_flag(void);
-
-/* newdir.c */
-extern errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino,
- ext2_ino_t parent_ino, char **block);
-
-/* mkdir.c */
-extern errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
- const char *name);
-
-/* mkjournal.c */
-extern errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
- __u32 size, int flags,
- char **ret_jsb);
-extern errcode_t ext2fs_add_journal_device(ext2_filsys fs,
- ext2_filsys journal_dev);
-extern errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size,
- int flags);
-
-/* openfs.c */
-extern errcode_t ext2fs_open(const char *name, int flags, int superblock,
- unsigned int block_size, io_manager manager,
- ext2_filsys *ret_fs);
-extern errcode_t ext2fs_open2(const char *name, const char *io_options,
- int flags, int superblock,
- unsigned int block_size, io_manager manager,
- ext2_filsys *ret_fs);
-extern blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block,
- dgrp_t i);
-errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io);
-errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io);
-errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io);
-
-/* get_pathname.c */
-extern errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino,
- char **name);
-
-/* link.c */
-errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name,
- ext2_ino_t ino, int flags);
-errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir, const char *name,
- ext2_ino_t ino, int flags);
-
-/* read_bb.c */
-extern errcode_t ext2fs_read_bb_inode(ext2_filsys fs,
- ext2_badblocks_list *bb_list);
-
-/* read_bb_file.c */
-extern errcode_t ext2fs_read_bb_FILE2(ext2_filsys fs, FILE *f,
- ext2_badblocks_list *bb_list,
- void *priv_data,
- void (*invalid)(ext2_filsys fs,
- blk_t blk,
- char *badstr,
- void *priv_data));
-extern errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f,
- ext2_badblocks_list *bb_list,
- void (*invalid)(ext2_filsys fs,
- blk_t blk));
-
-/* res_gdt.c */
-extern errcode_t ext2fs_create_resize_inode(ext2_filsys fs);
-
-/* rs_bitmap.c */
-extern errcode_t ext2fs_resize_generic_bitmap(__u32 new_end,
- __u32 new_real_end,
- ext2fs_generic_bitmap bmap);
-extern errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
- ext2fs_inode_bitmap bmap);
-extern errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
- ext2fs_block_bitmap bmap);
-extern errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
- ext2fs_generic_bitmap *dest);
-
-/* swapfs.c */
-extern void ext2fs_swap_ext_attr(char *to, char *from, int bufsize,
- int has_header);
-extern void ext2fs_swap_super(struct ext2_super_block * super);
-extern void ext2fs_swap_group_desc(struct ext2_group_desc *gdp);
-extern void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t,
- struct ext2_inode_large *f, int hostorder,
- int bufsize);
-extern void ext2fs_swap_inode(ext2_filsys fs,struct ext2_inode *t,
- struct ext2_inode *f, int hostorder);
-
-/* valid_blk.c */
-extern int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode);
-
-/* version.c */
-extern int ext2fs_parse_version_string(const char *ver_string);
-extern int ext2fs_get_library_version(const char **ver_string,
- const char **date_string);
-
-/* write_bb_file.c */
-extern errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list,
- unsigned int flags,
- FILE *f);
-
-
-/* inline functions */
-extern errcode_t ext2fs_get_mem(unsigned long size, void *ptr);
-extern errcode_t ext2fs_free_mem(void *ptr);
-extern errcode_t ext2fs_resize_mem(unsigned long old_size,
- unsigned long size, void *ptr);
-extern void ext2fs_mark_super_dirty(ext2_filsys fs);
-extern void ext2fs_mark_changed(ext2_filsys fs);
-extern int ext2fs_test_changed(ext2_filsys fs);
-extern void ext2fs_mark_valid(ext2_filsys fs);
-extern void ext2fs_unmark_valid(ext2_filsys fs);
-extern int ext2fs_test_valid(ext2_filsys fs);
-extern void ext2fs_mark_ib_dirty(ext2_filsys fs);
-extern void ext2fs_mark_bb_dirty(ext2_filsys fs);
-extern int ext2fs_test_ib_dirty(ext2_filsys fs);
-extern int ext2fs_test_bb_dirty(ext2_filsys fs);
-extern int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk);
-extern int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino);
-extern blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
- struct ext2_inode *inode);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2fsP.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2fsP.h
deleted file mode 100644
index 7a02e9a8e3..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2fsP.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * ext2fsP.h --- private header file for ext2 library
- *
- * Copyright (C) 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include "ext2fs.h"
-
-/*
- * Badblocks list
- */
-struct ext2_struct_u32_list {
- int magic;
- int num;
- int size;
- __u32 *list;
- int badblocks_flags;
-};
-
-struct ext2_struct_u32_iterate {
- int magic;
- ext2_u32_list bb;
- int ptr;
-};
-
-
-/*
- * Directory block iterator definition
- */
-struct ext2_struct_dblist {
- int magic;
- ext2_filsys fs;
- ext2_ino_t size;
- ext2_ino_t count;
- int sorted;
- struct ext2_db_entry * list;
-};
-
-/*
- * For directory iterators
- */
-struct dir_context {
- ext2_ino_t dir;
- int flags;
- char *buf;
- int (*func)(ext2_ino_t dir,
- int entry,
- struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *priv_data);
- void *priv_data;
- errcode_t errcode;
-};
-
-/*
- * Inode cache structure
- */
-struct ext2_inode_cache {
- void * buffer;
- blk_t buffer_blk;
- int cache_last;
- int cache_size;
- int refcount;
- struct ext2_inode_cache_ent *cache;
-};
-
-struct ext2_inode_cache_ent {
- ext2_ino_t ino;
- struct ext2_inode inode;
-};
-
-/* Function prototypes */
-
-extern int ext2fs_process_dir_block(ext2_filsys fs,
- blk_t *blocknr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block,
- int ref_offset,
- void *priv_data);
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs_inline.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs_inline.c
deleted file mode 100644
index 7d37d232d8..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs_inline.c
+++ /dev/null
@@ -1,365 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * ext2fs.h --- ext2fs
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include "ext2fs.h"
-#include "bitops.h"
-#include <string.h>
-
-/*
- * Allocate memory
- */
-errcode_t ext2fs_get_mem(unsigned long size, void *ptr)
-{
- void **pp = (void **)ptr;
-
- *pp = malloc(size);
- if (!*pp)
- return EXT2_ET_NO_MEMORY;
- return 0;
-}
-
-/*
- * Free memory
- */
-errcode_t ext2fs_free_mem(void *ptr)
-{
- void **pp = (void **)ptr;
-
- free(*pp);
- *pp = 0;
- return 0;
-}
-
-/*
- * Resize memory
- */
-errcode_t ext2fs_resize_mem(unsigned long EXT2FS_ATTR((unused)) old_size,
- unsigned long size, void *ptr)
-{
- void *p;
-
- /* Use "memcpy" for pointer assignments here to avoid problems
- * with C99 strict type aliasing rules. */
- memcpy(&p, ptr, sizeof (p));
- p = xrealloc(p, size);
- memcpy(ptr, &p, sizeof (p));
- return 0;
-}
-
-/*
- * Mark a filesystem superblock as dirty
- */
-void ext2fs_mark_super_dirty(ext2_filsys fs)
-{
- fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_CHANGED;
-}
-
-/*
- * Mark a filesystem as changed
- */
-void ext2fs_mark_changed(ext2_filsys fs)
-{
- fs->flags |= EXT2_FLAG_CHANGED;
-}
-
-/*
- * Check to see if a filesystem has changed
- */
-int ext2fs_test_changed(ext2_filsys fs)
-{
- return (fs->flags & EXT2_FLAG_CHANGED);
-}
-
-/*
- * Mark a filesystem as valid
- */
-void ext2fs_mark_valid(ext2_filsys fs)
-{
- fs->flags |= EXT2_FLAG_VALID;
-}
-
-/*
- * Mark a filesystem as NOT valid
- */
-void ext2fs_unmark_valid(ext2_filsys fs)
-{
- fs->flags &= ~EXT2_FLAG_VALID;
-}
-
-/*
- * Check to see if a filesystem is valid
- */
-int ext2fs_test_valid(ext2_filsys fs)
-{
- return (fs->flags & EXT2_FLAG_VALID);
-}
-
-/*
- * Mark the inode bitmap as dirty
- */
-void ext2fs_mark_ib_dirty(ext2_filsys fs)
-{
- fs->flags |= EXT2_FLAG_IB_DIRTY | EXT2_FLAG_CHANGED;
-}
-
-/*
- * Mark the block bitmap as dirty
- */
-void ext2fs_mark_bb_dirty(ext2_filsys fs)
-{
- fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_CHANGED;
-}
-
-/*
- * Check to see if a filesystem's inode bitmap is dirty
- */
-int ext2fs_test_ib_dirty(ext2_filsys fs)
-{
- return (fs->flags & EXT2_FLAG_IB_DIRTY);
-}
-
-/*
- * Check to see if a filesystem's block bitmap is dirty
- */
-int ext2fs_test_bb_dirty(ext2_filsys fs)
-{
- return (fs->flags & EXT2_FLAG_BB_DIRTY);
-}
-
-/*
- * Return the group # of a block
- */
-int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk)
-{
- return (blk - fs->super->s_first_data_block) /
- fs->super->s_blocks_per_group;
-}
-
-/*
- * Return the group # of an inode number
- */
-int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino)
-{
- return (ino - 1) / fs->super->s_inodes_per_group;
-}
-
-blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
- struct ext2_inode *inode)
-{
- return inode->i_blocks -
- (inode->i_file_acl ? fs->blocksize >> 9 : 0);
-}
-
-
-
-
-
-
-
-
-
-__u16 ext2fs_swab16(__u16 val)
-{
- return (val >> 8) | (val << 8);
-}
-
-__u32 ext2fs_swab32(__u32 val)
-{
- return ((val>>24) | ((val>>8)&0xFF00) |
- ((val<<8)&0xFF0000) | (val<<24));
-}
-
-int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
- blk_t bitno);
-
-int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
- blk_t bitno)
-{
- if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
- ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, bitno);
- return 0;
- }
- return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap);
-}
-
-int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap,
- blk_t block)
-{
- return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap)
- bitmap,
- block);
-}
-
-int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
- blk_t block)
-{
- return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
- block);
-}
-
-int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap,
- blk_t block)
-{
- return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
- block);
-}
-
-int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
- ext2_ino_t inode)
-{
- return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
- inode);
-}
-
-int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
- ext2_ino_t inode)
-{
- return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
- inode);
-}
-
-int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
- ext2_ino_t inode)
-{
- return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
- inode);
-}
-
-void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
- blk_t block)
-{
- ext2fs_set_bit(block - bitmap->start, bitmap->bitmap);
-}
-
-void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
- blk_t block)
-{
- ext2fs_clear_bit(block - bitmap->start, bitmap->bitmap);
-}
-
-int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
- blk_t block)
-{
- return ext2fs_test_bit(block - bitmap->start, bitmap->bitmap);
-}
-
-void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
- ext2_ino_t inode)
-{
- ext2fs_set_bit(inode - bitmap->start, bitmap->bitmap);
-}
-
-void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
- ext2_ino_t inode)
-{
- ext2fs_clear_bit(inode - bitmap->start, bitmap->bitmap);
-}
-
-int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
- ext2_ino_t inode)
-{
- return ext2fs_test_bit(inode - bitmap->start, bitmap->bitmap);
-}
-
-blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap)
-{
- return bitmap->start;
-}
-
-ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
-{
- return bitmap->start;
-}
-
-blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap)
-{
- return bitmap->end;
-}
-
-ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
-{
- return bitmap->end;
-}
-
-int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num)
-{
- int i;
-
- if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
- ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
- block, bitmap->description);
- return 0;
- }
- for (i=0; i < num; i++) {
- if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
- return 0;
- }
- return 1;
-}
-
-int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num)
-{
- int i;
-
- for (i=0; i < num; i++) {
- if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
- return 0;
- }
- return 1;
-}
-
-void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num)
-{
- int i;
-
- if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
- ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
- bitmap->description);
- return;
- }
- for (i=0; i < num; i++)
- ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
-}
-
-void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num)
-{
- int i;
-
- for (i=0; i < num; i++)
- ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
-}
-
-void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num)
-{
- int i;
-
- if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
- ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
- bitmap->description);
- return;
- }
- for (i=0; i < num; i++)
- ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);
-}
-
-void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num)
-{
- int i;
- for (i=0; i < num; i++)
- ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext_attr.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext_attr.c
deleted file mode 100644
index a2ba12d45c..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext_attr.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * ext_attr.c --- extended attribute blocks
- *
- * Copyright (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
- *
- * Copyright (C) 2002 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <time.h>
-
-#include "ext2_fs.h"
-#include "ext2_ext_attr.h"
-#include "ext2fs.h"
-
-errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf)
-{
- errcode_t retval;
-
- retval = io_channel_read_blk(fs->io, block, 1, buf);
- if (retval)
- return retval;
-#if BB_BIG_ENDIAN
- if ((fs->flags & (EXT2_FLAG_SWAP_BYTES|
- EXT2_FLAG_SWAP_BYTES_READ)) != 0)
- ext2fs_swap_ext_attr(buf, buf, fs->blocksize, 1);
-#endif
- return 0;
-}
-
-errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *inbuf)
-{
- errcode_t retval;
- char *write_buf;
- char *buf = NULL;
-
- if (BB_BIG_ENDIAN && ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))) {
- retval = ext2fs_get_mem(fs->blocksize, &buf);
- if (retval)
- return retval;
- write_buf = buf;
- ext2fs_swap_ext_attr(buf, inbuf, fs->blocksize, 1);
- } else
- write_buf = (char *) inbuf;
- retval = io_channel_write_blk(fs->io, block, 1, write_buf);
- if (buf)
- ext2fs_free_mem(&buf);
- if (!retval)
- ext2fs_mark_changed(fs);
- return retval;
-}
-
-/*
- * This function adjusts the reference count of the EA block.
- */
-errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk,
- char *block_buf, int adjust,
- __u32 *newcount)
-{
- errcode_t retval;
- struct ext2_ext_attr_header *header;
- char *buf = NULL;
-
- if ((blk >= fs->super->s_blocks_count) ||
- (blk < fs->super->s_first_data_block))
- return EXT2_ET_BAD_EA_BLOCK_NUM;
-
- if (!block_buf) {
- retval = ext2fs_get_mem(fs->blocksize, &buf);
- if (retval)
- return retval;
- block_buf = buf;
- }
-
- retval = ext2fs_read_ext_attr(fs, blk, block_buf);
- if (retval)
- goto errout;
-
- header = (struct ext2_ext_attr_header *) block_buf;
- header->h_refcount += adjust;
- if (newcount)
- *newcount = header->h_refcount;
-
- retval = ext2fs_write_ext_attr(fs, blk, block_buf);
- if (retval)
- goto errout;
-
-errout:
- if (buf)
- ext2fs_free_mem(&buf);
- return retval;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/fileio.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/fileio.c
deleted file mode 100644
index 5a5ad3ef89..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/fileio.c
+++ /dev/null
@@ -1,377 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * fileio.c --- Simple file I/O routines
- *
- * Copyright (C) 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-struct ext2_file {
- errcode_t magic;
- ext2_filsys fs;
- ext2_ino_t ino;
- struct ext2_inode inode;
- int flags;
- __u64 pos;
- blk_t blockno;
- blk_t physblock;
- char *buf;
-};
-
-#define BMAP_BUFFER (file->buf + fs->blocksize)
-
-errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode,
- int flags, ext2_file_t *ret)
-{
- ext2_file_t file;
- errcode_t retval;
-
- /*
- * Don't let caller create or open a file for writing if the
- * filesystem is read-only.
- */
- if ((flags & (EXT2_FILE_WRITE | EXT2_FILE_CREATE)) &&
- !(fs->flags & EXT2_FLAG_RW))
- return EXT2_ET_RO_FILSYS;
-
- retval = ext2fs_get_mem(sizeof(struct ext2_file), &file);
- if (retval)
- return retval;
-
- memset(file, 0, sizeof(struct ext2_file));
- file->magic = EXT2_ET_MAGIC_EXT2_FILE;
- file->fs = fs;
- file->ino = ino;
- file->flags = flags & EXT2_FILE_MASK;
-
- if (inode) {
- memcpy(&file->inode, inode, sizeof(struct ext2_inode));
- } else {
- retval = ext2fs_read_inode(fs, ino, &file->inode);
- if (retval)
- goto fail;
- }
-
- retval = ext2fs_get_mem(fs->blocksize * 3, &file->buf);
- if (retval)
- goto fail;
-
- *ret = file;
- return 0;
-
-fail:
- ext2fs_free_mem(&file->buf);
- ext2fs_free_mem(&file);
- return retval;
-}
-
-errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino,
- int flags, ext2_file_t *ret)
-{
- return ext2fs_file_open2(fs, ino, NULL, flags, ret);
-}
-
-/*
- * This function returns the filesystem handle of a file from the structure
- */
-ext2_filsys ext2fs_file_get_fs(ext2_file_t file)
-{
- if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
- return 0;
- return file->fs;
-}
-
-/*
- * This function flushes the dirty block buffer out to disk if
- * necessary.
- */
-errcode_t ext2fs_file_flush(ext2_file_t file)
-{
- errcode_t retval;
- ext2_filsys fs;
-
- EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
- fs = file->fs;
-
- if (!(file->flags & EXT2_FILE_BUF_VALID) ||
- !(file->flags & EXT2_FILE_BUF_DIRTY))
- return 0;
-
- /*
- * OK, the physical block hasn't been allocated yet.
- * Allocate it.
- */
- if (!file->physblock) {
- retval = ext2fs_bmap(fs, file->ino, &file->inode,
- BMAP_BUFFER, file->ino ? BMAP_ALLOC : 0,
- file->blockno, &file->physblock);
- if (retval)
- return retval;
- }
-
- retval = io_channel_write_blk(fs->io, file->physblock,
- 1, file->buf);
- if (retval)
- return retval;
-
- file->flags &= ~EXT2_FILE_BUF_DIRTY;
-
- return retval;
-}
-
-/*
- * This function synchronizes the file's block buffer and the current
- * file position, possibly invalidating block buffer if necessary
- */
-static errcode_t sync_buffer_position(ext2_file_t file)
-{
- blk_t b;
- errcode_t retval;
-
- b = file->pos / file->fs->blocksize;
- if (b != file->blockno) {
- retval = ext2fs_file_flush(file);
- if (retval)
- return retval;
- file->flags &= ~EXT2_FILE_BUF_VALID;
- }
- file->blockno = b;
- return 0;
-}
-
-/*
- * This function loads the file's block buffer with valid data from
- * the disk as necessary.
- *
- * If dontfill is true, then skip initializing the buffer since we're
- * going to be replacing its entire contents anyway. If set, then the
- * function basically only sets file->physblock and EXT2_FILE_BUF_VALID
- */
-#define DONTFILL 1
-static errcode_t load_buffer(ext2_file_t file, int dontfill)
-{
- ext2_filsys fs = file->fs;
- errcode_t retval;
-
- if (!(file->flags & EXT2_FILE_BUF_VALID)) {
- retval = ext2fs_bmap(fs, file->ino, &file->inode,
- BMAP_BUFFER, 0, file->blockno,
- &file->physblock);
- if (retval)
- return retval;
- if (!dontfill) {
- if (file->physblock) {
- retval = io_channel_read_blk(fs->io,
- file->physblock,
- 1, file->buf);
- if (retval)
- return retval;
- } else
- memset(file->buf, 0, fs->blocksize);
- }
- file->flags |= EXT2_FILE_BUF_VALID;
- }
- return 0;
-}
-
-
-errcode_t ext2fs_file_close(ext2_file_t file)
-{
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
-
- retval = ext2fs_file_flush(file);
-
- ext2fs_free_mem(&file->buf);
- ext2fs_free_mem(&file);
-
- return retval;
-}
-
-
-errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
- unsigned int wanted, unsigned int *got)
-{
- ext2_filsys fs;
- errcode_t retval = 0;
- unsigned int start, c, count = 0;
- __u64 left;
- char *ptr = (char *) buf;
-
- EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
- fs = file->fs;
-
- while ((file->pos < EXT2_I_SIZE(&file->inode)) && (wanted > 0)) {
- retval = sync_buffer_position(file);
- if (retval)
- goto fail;
- retval = load_buffer(file, 0);
- if (retval)
- goto fail;
-
- start = file->pos % fs->blocksize;
- c = fs->blocksize - start;
- if (c > wanted)
- c = wanted;
- left = EXT2_I_SIZE(&file->inode) - file->pos;
- if (c > left)
- c = left;
-
- memcpy(ptr, file->buf+start, c);
- file->pos += c;
- ptr += c;
- count += c;
- wanted -= c;
- }
-
-fail:
- if (got)
- *got = count;
- return retval;
-}
-
-
-errcode_t ext2fs_file_write(ext2_file_t file, const void *buf,
- unsigned int nbytes, unsigned int *written)
-{
- ext2_filsys fs;
- errcode_t retval = 0;
- unsigned int start, c, count = 0;
- const char *ptr = (const char *) buf;
-
- EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
- fs = file->fs;
-
- if (!(file->flags & EXT2_FILE_WRITE))
- return EXT2_ET_FILE_RO;
-
- while (nbytes > 0) {
- retval = sync_buffer_position(file);
- if (retval)
- goto fail;
-
- start = file->pos % fs->blocksize;
- c = fs->blocksize - start;
- if (c > nbytes)
- c = nbytes;
-
- /*
- * We only need to do a read-modify-update cycle if
- * we're doing a partial write.
- */
- retval = load_buffer(file, (c == fs->blocksize));
- if (retval)
- goto fail;
-
- file->flags |= EXT2_FILE_BUF_DIRTY;
- memcpy(file->buf+start, ptr, c);
- file->pos += c;
- ptr += c;
- count += c;
- nbytes -= c;
- }
-
-fail:
- if (written)
- *written = count;
- return retval;
-}
-
-errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset,
- int whence, __u64 *ret_pos)
-{
- EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
-
- if (whence == EXT2_SEEK_SET)
- file->pos = offset;
- else if (whence == EXT2_SEEK_CUR)
- file->pos += offset;
- else if (whence == EXT2_SEEK_END)
- file->pos = EXT2_I_SIZE(&file->inode) + offset;
- else
- return EXT2_ET_INVALID_ARGUMENT;
-
- if (ret_pos)
- *ret_pos = file->pos;
-
- return 0;
-}
-
-errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
- int whence, ext2_off_t *ret_pos)
-{
- __u64 loffset, ret_loffset;
- errcode_t retval;
-
- loffset = offset;
- retval = ext2fs_file_llseek(file, loffset, whence, &ret_loffset);
- if (ret_pos)
- *ret_pos = (ext2_off_t) ret_loffset;
- return retval;
-}
-
-
-/*
- * This function returns the size of the file, according to the inode
- */
-errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size)
-{
- if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
- return EXT2_ET_MAGIC_EXT2_FILE;
- *ret_size = EXT2_I_SIZE(&file->inode);
- return 0;
-}
-
-/*
- * This function returns the size of the file, according to the inode
- */
-ext2_off_t ext2fs_file_get_size(ext2_file_t file)
-{
- __u64 size;
-
- if (ext2fs_file_get_lsize(file, &size))
- return 0;
- if ((size >> 32) != 0)
- return 0;
- return size;
-}
-
-/*
- * This function sets the size of the file, truncating it if necessary
- *
- * XXX still need to call truncate
- */
-errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size)
-{
- errcode_t retval;
- EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
-
- file->inode.i_size = size;
- file->inode.i_size_high = 0;
- if (file->ino) {
- retval = ext2fs_write_inode(file->fs, file->ino, &file->inode);
- if (retval)
- return retval;
- }
-
- /*
- * XXX truncate inode if necessary
- */
-
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/finddev.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/finddev.c
deleted file mode 100644
index e9e83fd7ad..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/finddev.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * finddev.c -- this routine attempts to find a particular device in
- * /dev
- *
- * Copyright (C) 2000 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#include <dirent.h>
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_SYS_MKDEV_H
-#include <sys/mkdev.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-struct dir_list {
- char *name;
- struct dir_list *next;
-};
-
-/*
- * This function adds an entry to the directory list
- */
-static void add_to_dirlist(const char *name, struct dir_list **list)
-{
- struct dir_list *dp;
-
- dp = xmalloc(sizeof(struct dir_list));
- dp->name = xmalloc(strlen(name)+1);
- strcpy(dp->name, name);
- dp->next = *list;
- *list = dp;
-}
-
-/*
- * This function frees a directory list
- */
-static void free_dirlist(struct dir_list **list)
-{
- struct dir_list *dp, *next;
-
- for (dp = *list; dp; dp = next) {
- next = dp->next;
- free(dp->name);
- free(dp);
- }
- *list = 0;
-}
-
-static int scan_dir(char *dir_name, dev_t device, struct dir_list **list,
- char **ret_path)
-{
- DIR *dir;
- struct dirent *dp;
- char path[1024], *cp;
- int dirlen;
- struct stat st;
-
- dirlen = strlen(dir_name);
- if ((dir = opendir(dir_name)) == NULL)
- return errno;
- dp = readdir(dir);
- while (dp) {
- if (dirlen + strlen(dp->d_name) + 2 >= sizeof(path))
- goto skip_to_next;
- if (dp->d_name[0] == '.' &&
- ((dp->d_name[1] == 0) ||
- ((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
- goto skip_to_next;
- sprintf(path, "%s/%s", dir_name, dp->d_name);
- if (stat(path, &st) < 0)
- goto skip_to_next;
- if (S_ISDIR(st.st_mode))
- add_to_dirlist(path, list);
- if (S_ISBLK(st.st_mode) && st.st_rdev == device) {
- cp = xmalloc(strlen(path)+1);
- strcpy(cp, path);
- *ret_path = cp;
- goto success;
- }
- skip_to_next:
- dp = readdir(dir);
- }
-success:
- closedir(dir);
- return 0;
-}
-
-/*
- * This function finds the pathname to a block device with a given
- * device number. It returns a pointer to allocated memory to the
- * pathname on success, and NULL on failure.
- */
-char *ext2fs_find_block_device(dev_t device)
-{
- struct dir_list *list = NULL, *new_list = NULL;
- struct dir_list *current;
- char *ret_path = NULL;
-
- /*
- * Add the starting directories to search...
- */
- add_to_dirlist("/devices", &list);
- add_to_dirlist("/devfs", &list);
- add_to_dirlist("/dev", &list);
-
- while (list) {
- current = list;
- list = list->next;
-#ifdef DEBUG
- printf("Scanning directory %s\n", current->name);
-#endif
- scan_dir(current->name, device, &new_list, &ret_path);
- free(current->name);
- free(current);
- if (ret_path)
- break;
- /*
- * If we're done checking at this level, descend to
- * the next level of subdirectories. (breadth-first)
- */
- if (list == 0) {
- list = new_list;
- new_list = 0;
- }
- }
- free_dirlist(&list);
- free_dirlist(&new_list);
- return ret_path;
-}
-
-
-#ifdef DEBUG
-int main(int argc, char** argv)
-{
- char *devname, *tmp;
- int major, minor;
- dev_t device;
- const char *errmsg = "Cannot parse %s: %s\n";
-
- if ((argc != 2) && (argc != 3)) {
- fprintf(stderr, "Usage: %s device_number\n", argv[0]);
- fprintf(stderr, "\t: %s major minor\n", argv[0]);
- exit(1);
- }
- if (argc == 2) {
- device = strtoul(argv[1], &tmp, 0);
- if (*tmp) {
- fprintf(stderr, errmsg, "device number", argv[1]);
- exit(1);
- }
- } else {
- major = strtoul(argv[1], &tmp, 0);
- if (*tmp) {
- fprintf(stderr, errmsg, "major number", argv[1]);
- exit(1);
- }
- minor = strtoul(argv[2], &tmp, 0);
- if (*tmp) {
- fprintf(stderr, errmsg, "minor number", argv[2]);
- exit(1);
- }
- device = makedev(major, minor);
- printf("Looking for device 0x%04x (%d:%d)\n", device,
- major, minor);
- }
- devname = ext2fs_find_block_device(device);
- if (devname) {
- printf("Found device! %s\n", devname);
- free(devname);
- } else {
- printf("Cannot find device.\n");
- }
- return 0;
-}
-
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/flushb.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/flushb.c
deleted file mode 100644
index 45ed76512d..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/flushb.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * flushb.c --- Hides system-dependent information for both syncing a
- * device to disk and to flush any buffers from disk cache.
- *
- * Copyright (C) 2000 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#if HAVE_SYS_MOUNT_H
-#include <sys/param.h>
-#include <sys/mount.h> /* This may define BLKFLSBUF */
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * For Linux, define BLKFLSBUF and FDFLUSH if necessary, since
- * not all portable header file does so for us. This really should be
- * fixed in the glibc header files. (Recent glibcs appear to define
- * BLKFLSBUF in sys/mount.h, but FDFLUSH still doesn't seem to be
- * defined anywhere portable.) Until then....
- */
-#ifdef __linux__
-#ifndef BLKFLSBUF
-#define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
-#endif
-#ifndef FDFLUSH
-#define FDFLUSH _IO(2,0x4b) /* flush floppy disk */
-#endif
-#endif
-
-/*
- * This function will sync a device/file, and optionally attempt to
- * flush the buffer cache. The latter is basically only useful for
- * system benchmarks and for torturing systems in burn-in tests. :)
- */
-errcode_t ext2fs_sync_device(int fd, int flushb)
-{
- /*
- * We always sync the device in case we're running on old
- * kernels for which we can lose data if we don't. (There
- * still is a race condition for those kernels, but this
- * reduces it greatly.)
- */
- if (fsync (fd) == -1)
- return errno;
-
- if (flushb) {
-
-#ifdef BLKFLSBUF
- if (ioctl (fd, BLKFLSBUF, 0) == 0)
- return 0;
-#else
-#ifdef __GNUC__
-# warning BLKFLSBUF not defined
-#endif /* __GNUC__ */
-#endif
-#ifdef FDFLUSH
- ioctl (fd, FDFLUSH, 0); /* In case this is a floppy */
-#else
-#ifdef __GNUC__
-# warning FDFLUSH not defined
-#endif /* __GNUC__ */
-#endif
- }
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/freefs.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/freefs.c
deleted file mode 100644
index 0c5d48b113..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/freefs.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * freefs.c --- free an ext2 filesystem
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fsP.h"
-
-static void ext2fs_free_inode_cache(struct ext2_inode_cache *icache);
-
-void ext2fs_free(ext2_filsys fs)
-{
- if (!fs || (fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS))
- return;
- if (fs->image_io != fs->io) {
- if (fs->image_io)
- io_channel_close(fs->image_io);
- }
- if (fs->io) {
- io_channel_close(fs->io);
- }
- ext2fs_free_mem(&fs->device_name);
- ext2fs_free_mem(&fs->super);
- ext2fs_free_mem(&fs->orig_super);
- ext2fs_free_mem(&fs->group_desc);
- ext2fs_free_block_bitmap(fs->block_map);
- ext2fs_free_inode_bitmap(fs->inode_map);
-
- ext2fs_badblocks_list_free(fs->badblocks);
- fs->badblocks = 0;
-
- ext2fs_free_dblist(fs->dblist);
-
- if (fs->icache)
- ext2fs_free_inode_cache(fs->icache);
-
- fs->magic = 0;
-
- ext2fs_free_mem(&fs);
-}
-
-void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap)
-{
- if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_GENERIC_BITMAP))
- return;
-
- bitmap->magic = 0;
- ext2fs_free_mem(&bitmap->description);
- ext2fs_free_mem(&bitmap->bitmap);
- ext2fs_free_mem(&bitmap);
-}
-
-void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap)
-{
- if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_INODE_BITMAP))
- return;
-
- bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
- ext2fs_free_generic_bitmap(bitmap);
-}
-
-void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap)
-{
- if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_BLOCK_BITMAP))
- return;
-
- bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
- ext2fs_free_generic_bitmap(bitmap);
-}
-
-/*
- * Free the inode cache structure
- */
-static void ext2fs_free_inode_cache(struct ext2_inode_cache *icache)
-{
- if (--icache->refcount)
- return;
- ext2fs_free_mem(&icache->buffer);
- ext2fs_free_mem(&icache->cache);
- icache->buffer_blk = 0;
- ext2fs_free_mem(&icache);
-}
-
-/*
- * This procedure frees a badblocks list.
- */
-void ext2fs_u32_list_free(ext2_u32_list bb)
-{
- if (!bb || bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
- return;
-
- ext2fs_free_mem(&bb->list);
- ext2fs_free_mem(&bb);
-}
-
-void ext2fs_badblocks_list_free(ext2_badblocks_list bb)
-{
- ext2fs_u32_list_free((ext2_u32_list) bb);
-}
-
-
-/*
- * Free a directory block list
- */
-void ext2fs_free_dblist(ext2_dblist dblist)
-{
- if (!dblist || (dblist->magic != EXT2_ET_MAGIC_DBLIST))
- return;
-
- ext2fs_free_mem(&dblist->list);
- if (dblist->fs && dblist->fs->dblist == dblist)
- dblist->fs->dblist = 0;
- dblist->magic = 0;
- ext2fs_free_mem(&dblist);
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/gen_bitmap.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/gen_bitmap.c
deleted file mode 100644
index d0869c9191..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/gen_bitmap.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * gen_bitmap.c --- Generic bitmap routines that used to be inlined.
- *
- * Copyright (C) 2001 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
- __u32 bitno)
-{
- if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
- ext2fs_warn_bitmap2(bitmap, EXT2FS_MARK_ERROR, bitno);
- return 0;
- }
- return ext2fs_set_bit(bitno - bitmap->start, bitmap->bitmap);
-}
-
-int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
- blk_t bitno)
-{
- if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
- ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno);
- return 0;
- }
- return ext2fs_clear_bit(bitno - bitmap->start, bitmap->bitmap);
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/get_pathname.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/get_pathname.c
deleted file mode 100644
index 2bb1cc25ec..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/get_pathname.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * get_pathname.c --- do directry/inode -> name translation
- *
- * Copyright (C) 1993, 1994, 1995 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- *
- * ext2fs_get_pathname(fs, dir, ino, name)
- *
- * This function translates takes two inode numbers into a
- * string, placing the result in <name>. <dir> is the containing
- * directory inode, and <ino> is the inode number itself. If
- * <ino> is zero, then ext2fs_get_pathname will return pathname
- * of the directory <dir>.
- *
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-struct get_pathname_struct {
- ext2_ino_t search_ino;
- ext2_ino_t parent;
- char *name;
- errcode_t errcode;
-};
-
-#ifdef __TURBOC__
-# pragma argsused
-#endif
-static int get_pathname_proc(struct ext2_dir_entry *dirent,
- int offset EXT2FS_ATTR((unused)),
- int blocksize EXT2FS_ATTR((unused)),
- char *buf EXT2FS_ATTR((unused)),
- void *priv_data)
-{
- struct get_pathname_struct *gp;
- errcode_t retval;
-
- gp = (struct get_pathname_struct *) priv_data;
-
- if (((dirent->name_len & 0xFF) == 2) &&
- !strncmp(dirent->name, "..", 2))
- gp->parent = dirent->inode;
- if (dirent->inode == gp->search_ino) {
- retval = ext2fs_get_mem((dirent->name_len & 0xFF) + 1,
- &gp->name);
- if (retval) {
- gp->errcode = retval;
- return DIRENT_ABORT;
- }
- strncpy(gp->name, dirent->name, (dirent->name_len & 0xFF));
- gp->name[dirent->name_len & 0xFF] = '\0';
- return DIRENT_ABORT;
- }
- return 0;
-}
-
-static errcode_t ext2fs_get_pathname_int(ext2_filsys fs, ext2_ino_t dir,
- ext2_ino_t ino, int maxdepth,
- char *buf, char **name)
-{
- struct get_pathname_struct gp;
- char *parent_name, *ret;
- errcode_t retval;
-
- if (dir == ino) {
- retval = ext2fs_get_mem(2, name);
- if (retval)
- return retval;
- strcpy(*name, (dir == EXT2_ROOT_INO) ? "/" : ".");
- return 0;
- }
-
- if (!dir || (maxdepth < 0)) {
- retval = ext2fs_get_mem(4, name);
- if (retval)
- return retval;
- strcpy(*name, "...");
- return 0;
- }
-
- gp.search_ino = ino;
- gp.parent = 0;
- gp.name = 0;
- gp.errcode = 0;
-
- retval = ext2fs_dir_iterate(fs, dir, 0, buf, get_pathname_proc, &gp);
- if (retval)
- goto cleanup;
- if (gp.errcode) {
- retval = gp.errcode;
- goto cleanup;
- }
-
- retval = ext2fs_get_pathname_int(fs, gp.parent, dir, maxdepth-1,
- buf, &parent_name);
- if (retval)
- goto cleanup;
- if (!ino) {
- *name = parent_name;
- return 0;
- }
-
- if (gp.name)
- retval = ext2fs_get_mem(strlen(parent_name)+strlen(gp.name)+2,
- &ret);
- else
- retval = ext2fs_get_mem(strlen(parent_name)+5, &ret);
- if (retval)
- goto cleanup;
-
- ret[0] = 0;
- if (parent_name[1])
- strcat(ret, parent_name);
- strcat(ret, "/");
- if (gp.name)
- strcat(ret, gp.name);
- else
- strcat(ret, "???");
- *name = ret;
- ext2fs_free_mem(&parent_name);
- retval = 0;
-
-cleanup:
- ext2fs_free_mem(&gp.name);
- return retval;
-}
-
-errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino,
- char **name)
-{
- char *buf;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- retval = ext2fs_get_mem(fs->blocksize, &buf);
- if (retval)
- return retval;
- if (dir == ino)
- ino = 0;
- retval = ext2fs_get_pathname_int(fs, dir, ino, 32, buf, name);
- ext2fs_free_mem(&buf);
- return retval;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/getsectsize.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/getsectsize.c
deleted file mode 100644
index 163ec65e5b..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/getsectsize.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * getsectsize.c --- get the sector size of a device.
- *
- * Copyright (C) 1995, 1995 Theodore Ts'o.
- * Copyright (C) 2003 VMware, Inc.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <fcntl.h>
-#ifdef HAVE_LINUX_FD_H
-#include <sys/ioctl.h>
-#include <linux/fd.h>
-#endif
-
-#if defined(__linux__) && defined(_IO) && !defined(BLKSSZGET)
-#define BLKSSZGET _IO(0x12,104)/* get block device sector size */
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * Returns the number of blocks in a partition
- */
-errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize)
-{
- int fd;
-
-#ifdef CONFIG_LFS
- fd = open64(file, O_RDONLY);
-#else
- fd = open(file, O_RDONLY);
-#endif
- if (fd < 0)
- return errno;
-
-#ifdef BLKSSZGET
- if (ioctl(fd, BLKSSZGET, sectsize) >= 0) {
- close(fd);
- return 0;
- }
-#endif
- *sectsize = 0;
- close(fd);
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/getsize.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/getsize.c
deleted file mode 100644
index 923334facc..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/getsize.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * getsize.c --- get the size of a partition.
- *
- * Copyright (C) 1995, 1995 Theodore Ts'o.
- * Copyright (C) 2003 VMware, Inc.
- *
- * Windows version of ext2fs_get_device_size by Chris Li, VMware.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <fcntl.h>
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#ifdef HAVE_LINUX_FD_H
-#include <linux/fd.h>
-#endif
-#ifdef HAVE_SYS_DISKLABEL_H
-#include <sys/disklabel.h>
-#endif
-#ifdef HAVE_SYS_DISK_H
-#ifdef HAVE_SYS_QUEUE_H
-#include <sys/queue.h> /* for LIST_HEAD */
-#endif
-#include <sys/disk.h>
-#endif
-#ifdef __linux__
-#include <sys/utsname.h>
-#endif
-
-#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
-#define BLKGETSIZE _IO(0x12,96) /* return device size */
-#endif
-
-#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
-#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
-#endif
-
-#ifdef APPLE_DARWIN
-#define BLKGETSIZE DKIOCGETBLOCKCOUNT32
-#endif /* APPLE_DARWIN */
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-#if defined(__CYGWIN__) || defined(WIN32)
-#include <windows.h>
-#include <winioctl.h>
-
-#if (_WIN32_WINNT >= 0x0500)
-#define HAVE_GET_FILE_SIZE_EX 1
-#endif
-
-errcode_t ext2fs_get_device_size(const char *file, int blocksize,
- blk_t *retblocks)
-{
- HANDLE dev;
- PARTITION_INFORMATION pi;
- DISK_GEOMETRY gi;
- DWORD retbytes;
-#ifdef HAVE_GET_FILE_SIZE_EX
- LARGE_INTEGER filesize;
-#else
- DWORD filesize;
-#endif /* HAVE_GET_FILE_SIZE_EX */
-
- dev = CreateFile(file, GENERIC_READ,
- FILE_SHARE_READ | FILE_SHARE_WRITE ,
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-
- if (dev == INVALID_HANDLE_VALUE)
- return EBADF;
- if (DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO,
- &pi, sizeof(PARTITION_INFORMATION),
- &pi, sizeof(PARTITION_INFORMATION),
- &retbytes, NULL)) {
-
- *retblocks = pi.PartitionLength.QuadPart / blocksize;
-
- } else if (DeviceIoControl(dev, IOCTL_DISK_GET_DRIVE_GEOMETRY,
- &gi, sizeof(DISK_GEOMETRY),
- &gi, sizeof(DISK_GEOMETRY),
- &retbytes, NULL)) {
-
- *retblocks = gi.BytesPerSector *
- gi.SectorsPerTrack *
- gi.TracksPerCylinder *
- gi.Cylinders.QuadPart / blocksize;
-
-#ifdef HAVE_GET_FILE_SIZE_EX
- } else if (GetFileSizeEx(dev, &filesize)) {
- *retblocks = filesize.QuadPart / blocksize;
- }
-#else
- } else {
- filesize = GetFileSize(dev, NULL);
- if (INVALID_FILE_SIZE != filesize) {
- *retblocks = filesize / blocksize;
- }
- }
-#endif /* HAVE_GET_FILE_SIZE_EX */
-
- CloseHandle(dev);
- return 0;
-}
-
-#else
-
-static int valid_offset (int fd, ext2_loff_t offset)
-{
- char ch;
-
- if (ext2fs_llseek (fd, offset, 0) < 0)
- return 0;
- if (read (fd, &ch, 1) < 1)
- return 0;
- return 1;
-}
-
-/*
- * Returns the number of blocks in a partition
- */
-errcode_t ext2fs_get_device_size(const char *file, int blocksize,
- blk_t *retblocks)
-{
- int fd;
- int valid_blkgetsize64 = 1;
-#ifdef __linux__
- struct utsname ut;
-#endif
- unsigned long long size64;
- unsigned long size;
- ext2_loff_t high, low;
-#ifdef FDGETPRM
- struct floppy_struct this_floppy;
-#endif
-#ifdef HAVE_SYS_DISKLABEL_H
- int part;
- struct disklabel lab;
- struct partition *pp;
- char ch;
-#endif /* HAVE_SYS_DISKLABEL_H */
-
-#ifdef CONFIG_LFS
- fd = open64(file, O_RDONLY);
-#else
- fd = open(file, O_RDONLY);
-#endif
- if (fd < 0)
- return errno;
-
-#ifdef DKIOCGETBLOCKCOUNT /* For Apple Darwin */
- if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) {
- if ((sizeof(*retblocks) < sizeof(unsigned long long))
- && ((size64 / (blocksize / 512)) > 0xFFFFFFFF))
- return EFBIG;
- close(fd);
- *retblocks = size64 / (blocksize / 512);
- return 0;
- }
-#endif
-
-#ifdef BLKGETSIZE64
-#ifdef __linux__
- uname(&ut);
- if ((ut.release[0] == '2') && (ut.release[1] == '.') &&
- (ut.release[2] < '6') && (ut.release[3] == '.'))
- valid_blkgetsize64 = 0;
-#endif
- if (valid_blkgetsize64 &&
- ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
- if ((sizeof(*retblocks) < sizeof(unsigned long long))
- && ((size64 / blocksize) > 0xFFFFFFFF))
- return EFBIG;
- close(fd);
- *retblocks = size64 / blocksize;
- return 0;
- }
-#endif
-
-#ifdef BLKGETSIZE
- if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
- close(fd);
- *retblocks = size / (blocksize / 512);
- return 0;
- }
-#endif
-
-#ifdef FDGETPRM
- if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) {
- close(fd);
- *retblocks = this_floppy.size / (blocksize / 512);
- return 0;
- }
-#endif
-
-#ifdef HAVE_SYS_DISKLABEL_H
-#if defined(DIOCGMEDIASIZE)
- {
- off_t ms;
- u_int bs;
- if (ioctl(fd, DIOCGMEDIASIZE, &ms) >= 0) {
- close(fd);
- *retblocks = ms / blocksize;
- return 0;
- }
- }
-#elif defined(DIOCGDINFO)
- /* old disklabel interface */
- part = strlen(file) - 1;
- if (part >= 0) {
- ch = file[part];
- if (isdigit(ch))
- part = 0;
- else if (ch >= 'a' && ch <= 'h')
- part = ch - 'a';
- else
- part = -1;
- }
- if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
- pp = &lab.d_partitions[part];
- if (pp->p_size) {
- close(fd);
- *retblocks = pp->p_size / (blocksize / 512);
- return 0;
- }
- }
-#endif /* defined(DIOCG*) */
-#endif /* HAVE_SYS_DISKLABEL_H */
-
- /*
- * OK, we couldn't figure it out by using a specialized ioctl,
- * which is generally the best way. So do binary search to
- * find the size of the partition.
- */
- low = 0;
- for (high = 1024; valid_offset (fd, high); high *= 2)
- low = high;
- while (low < high - 1)
- {
- const ext2_loff_t mid = (low + high) / 2;
-
- if (valid_offset (fd, mid))
- low = mid;
- else
- high = mid;
- }
- valid_offset (fd, 0);
- close(fd);
- size64 = low + 1;
- if ((sizeof(*retblocks) < sizeof(unsigned long long))
- && ((size64 / blocksize) > 0xFFFFFFFF))
- return EFBIG;
- *retblocks = size64 / blocksize;
- return 0;
-}
-
-#endif /* WIN32 */
-
-#ifdef DEBUG
-int main(int argc, char **argv)
-{
- blk_t blocks;
- int retval;
-
- if (argc < 2) {
- fprintf(stderr, "Usage: %s device\n", argv[0]);
- exit(1);
- }
-
- retval = ext2fs_get_device_size(argv[1], 1024, &blocks);
- if (retval) {
- com_err(argv[0], retval,
- "while calling ext2fs_get_device_size");
- exit(1);
- }
- printf("Device %s has %d 1k blocks.\n", argv[1], blocks);
- exit(0);
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/icount.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/icount.c
deleted file mode 100644
index 7ab5f51f48..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/icount.c
+++ /dev/null
@@ -1,467 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * icount.c --- an efficient inode count abstraction
- *
- * Copyright (C) 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <string.h>
-#include <stdio.h>
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * The data storage strategy used by icount relies on the observation
- * that most inode counts are either zero (for non-allocated inodes),
- * one (for most files), and only a few that are two or more
- * (directories and files that are linked to more than one directory).
- *
- * Also, e2fsck tends to load the icount data sequentially.
- *
- * So, we use an inode bitmap to indicate which inodes have a count of
- * one, and then use a sorted list to store the counts for inodes
- * which are greater than one.
- *
- * We also use an optional bitmap to indicate which inodes are already
- * in the sorted list, to speed up the use of this abstraction by
- * e2fsck's pass 2. Pass 2 increments inode counts as it finds them,
- * so this extra bitmap avoids searching the sorted list to see if a
- * particular inode is on the sorted list already.
- */
-
-struct ext2_icount_el {
- ext2_ino_t ino;
- __u16 count;
-};
-
-struct ext2_icount {
- errcode_t magic;
- ext2fs_inode_bitmap single;
- ext2fs_inode_bitmap multiple;
- ext2_ino_t count;
- ext2_ino_t size;
- ext2_ino_t num_inodes;
- ext2_ino_t cursor;
- struct ext2_icount_el *list;
-};
-
-void ext2fs_free_icount(ext2_icount_t icount)
-{
- if (!icount)
- return;
-
- icount->magic = 0;
- ext2fs_free_mem(&icount->list);
- ext2fs_free_inode_bitmap(icount->single);
- ext2fs_free_inode_bitmap(icount->multiple);
- ext2fs_free_mem(&icount);
-}
-
-errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, unsigned int size,
- ext2_icount_t hint, ext2_icount_t *ret)
-{
- ext2_icount_t icount;
- errcode_t retval;
- size_t bytes;
- ext2_ino_t i;
-
- if (hint) {
- EXT2_CHECK_MAGIC(hint, EXT2_ET_MAGIC_ICOUNT);
- if (hint->size > size)
- size = (size_t) hint->size;
- }
-
- retval = ext2fs_get_mem(sizeof(struct ext2_icount), &icount);
- if (retval)
- return retval;
- memset(icount, 0, sizeof(struct ext2_icount));
-
- retval = ext2fs_allocate_inode_bitmap(fs, 0,
- &icount->single);
- if (retval)
- goto errout;
-
- if (flags & EXT2_ICOUNT_OPT_INCREMENT) {
- retval = ext2fs_allocate_inode_bitmap(fs, 0,
- &icount->multiple);
- if (retval)
- goto errout;
- } else
- icount->multiple = 0;
-
- if (size) {
- icount->size = size;
- } else {
- /*
- * Figure out how many special case inode counts we will
- * have. We know we will need one for each directory;
- * we also need to reserve some extra room for file links
- */
- retval = ext2fs_get_num_dirs(fs, &icount->size);
- if (retval)
- goto errout;
- icount->size += fs->super->s_inodes_count / 50;
- }
-
- bytes = (size_t) (icount->size * sizeof(struct ext2_icount_el));
- retval = ext2fs_get_mem(bytes, &icount->list);
- if (retval)
- goto errout;
- memset(icount->list, 0, bytes);
-
- icount->magic = EXT2_ET_MAGIC_ICOUNT;
- icount->count = 0;
- icount->cursor = 0;
- icount->num_inodes = fs->super->s_inodes_count;
-
- /*
- * Populate the sorted list with those entries which were
- * found in the hint icount (since those are ones which will
- * likely need to be in the sorted list this time around).
- */
- if (hint) {
- for (i=0; i < hint->count; i++)
- icount->list[i].ino = hint->list[i].ino;
- icount->count = hint->count;
- }
-
- *ret = icount;
- return 0;
-
-errout:
- ext2fs_free_icount(icount);
- return retval;
-}
-
-errcode_t ext2fs_create_icount(ext2_filsys fs, int flags,
- unsigned int size,
- ext2_icount_t *ret)
-{
- return ext2fs_create_icount2(fs, flags, size, 0, ret);
-}
-
-/*
- * insert_icount_el() --- Insert a new entry into the sorted list at a
- * specified position.
- */
-static struct ext2_icount_el *insert_icount_el(ext2_icount_t icount,
- ext2_ino_t ino, int pos)
-{
- struct ext2_icount_el *el;
- errcode_t retval;
- ext2_ino_t new_size = 0;
- int num;
-
- if (icount->count >= icount->size) {
- if (icount->count) {
- new_size = icount->list[(unsigned)icount->count-1].ino;
- new_size = (ext2_ino_t) (icount->count *
- ((float) icount->num_inodes / new_size));
- }
- if (new_size < (icount->size + 100))
- new_size = icount->size + 100;
- retval = ext2fs_resize_mem((size_t) icount->size *
- sizeof(struct ext2_icount_el),
- (size_t) new_size *
- sizeof(struct ext2_icount_el),
- &icount->list);
- if (retval)
- return 0;
- icount->size = new_size;
- }
- num = (int) icount->count - pos;
- if (num < 0)
- return 0; /* should never happen */
- if (num) {
- memmove(&icount->list[pos+1], &icount->list[pos],
- sizeof(struct ext2_icount_el) * num);
- }
- icount->count++;
- el = &icount->list[pos];
- el->count = 0;
- el->ino = ino;
- return el;
-}
-
-/*
- * get_icount_el() --- given an inode number, try to find icount
- * information in the sorted list. If the create flag is set,
- * and we can't find an entry, create one in the sorted list.
- */
-static struct ext2_icount_el *get_icount_el(ext2_icount_t icount,
- ext2_ino_t ino, int create)
-{
- float range;
- int low, high, mid;
- ext2_ino_t lowval, highval;
-
- if (!icount || !icount->list)
- return 0;
-
- if (create && ((icount->count == 0) ||
- (ino > icount->list[(unsigned)icount->count-1].ino))) {
- return insert_icount_el(icount, ino, (unsigned) icount->count);
- }
- if (icount->count == 0)
- return 0;
-
- if (icount->cursor >= icount->count)
- icount->cursor = 0;
- if (ino == icount->list[icount->cursor].ino)
- return &icount->list[icount->cursor++];
- low = 0;
- high = (int) icount->count-1;
- while (low <= high) {
- if (low == high)
- mid = low;
- else {
- /* Interpolate for efficiency */
- lowval = icount->list[low].ino;
- highval = icount->list[high].ino;
-
- if (ino < lowval)
- range = 0;
- else if (ino > highval)
- range = 1;
- else
- range = ((float) (ino - lowval)) /
- (highval - lowval);
- mid = low + ((int) (range * (high-low)));
- }
- if (ino == icount->list[mid].ino) {
- icount->cursor = mid+1;
- return &icount->list[mid];
- }
- if (ino < icount->list[mid].ino)
- high = mid-1;
- else
- low = mid+1;
- }
- /*
- * If we need to create a new entry, it should be right at
- * low (where high will be left at low-1).
- */
- if (create)
- return insert_icount_el(icount, ino, low);
- return 0;
-}
-
-errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *out)
-{
- errcode_t ret = 0;
- unsigned int i;
- const char *bad = "bad icount";
-
- EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
-
- if (icount->count > icount->size) {
- fprintf(out, "%s: count > size\n", bad);
- return EXT2_ET_INVALID_ARGUMENT;
- }
- for (i=1; i < icount->count; i++) {
- if (icount->list[i-1].ino >= icount->list[i].ino) {
- fprintf(out, "%s: list[%d].ino=%u, list[%d].ino=%u\n",
- bad, i-1, icount->list[i-1].ino,
- i, icount->list[i].ino);
- ret = EXT2_ET_INVALID_ARGUMENT;
- }
- }
- return ret;
-}
-
-errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, __u16 *ret)
-{
- struct ext2_icount_el *el;
-
- EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
-
- if (!ino || (ino > icount->num_inodes))
- return EXT2_ET_INVALID_ARGUMENT;
-
- if (ext2fs_test_inode_bitmap(icount->single, ino)) {
- *ret = 1;
- return 0;
- }
- if (icount->multiple &&
- !ext2fs_test_inode_bitmap(icount->multiple, ino)) {
- *ret = 0;
- return 0;
- }
- el = get_icount_el(icount, ino, 0);
- if (!el) {
- *ret = 0;
- return 0;
- }
- *ret = el->count;
- return 0;
-}
-
-errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino,
- __u16 *ret)
-{
- struct ext2_icount_el *el;
-
- EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
-
- if (!ino || (ino > icount->num_inodes))
- return EXT2_ET_INVALID_ARGUMENT;
-
- if (ext2fs_test_inode_bitmap(icount->single, ino)) {
- /*
- * If the existing count is 1, then we know there is
- * no entry in the list.
- */
- el = get_icount_el(icount, ino, 1);
- if (!el)
- return EXT2_ET_NO_MEMORY;
- ext2fs_unmark_inode_bitmap(icount->single, ino);
- el->count = 2;
- } else if (icount->multiple) {
- /*
- * The count is either zero or greater than 1; if the
- * inode is set in icount->multiple, then there should
- * be an entry in the list, so find it using
- * get_icount_el().
- */
- if (ext2fs_test_inode_bitmap(icount->multiple, ino)) {
- el = get_icount_el(icount, ino, 1);
- if (!el)
- return EXT2_ET_NO_MEMORY;
- el->count++;
- } else {
- /*
- * The count was zero; mark the single bitmap
- * and return.
- */
- zero_count:
- ext2fs_mark_inode_bitmap(icount->single, ino);
- if (ret)
- *ret = 1;
- return 0;
- }
- } else {
- /*
- * The count is either zero or greater than 1; try to
- * find an entry in the list to determine which.
- */
- el = get_icount_el(icount, ino, 0);
- if (!el) {
- /* No entry means the count was zero */
- goto zero_count;
- }
- el = get_icount_el(icount, ino, 1);
- if (!el)
- return EXT2_ET_NO_MEMORY;
- el->count++;
- }
- if (icount->multiple)
- ext2fs_mark_inode_bitmap(icount->multiple, ino);
- if (ret)
- *ret = el->count;
- return 0;
-}
-
-errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
- __u16 *ret)
-{
- struct ext2_icount_el *el;
-
- if (!ino || (ino > icount->num_inodes))
- return EXT2_ET_INVALID_ARGUMENT;
-
- EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
-
- if (ext2fs_test_inode_bitmap(icount->single, ino)) {
- ext2fs_unmark_inode_bitmap(icount->single, ino);
- if (icount->multiple)
- ext2fs_unmark_inode_bitmap(icount->multiple, ino);
- else {
- el = get_icount_el(icount, ino, 0);
- if (el)
- el->count = 0;
- }
- if (ret)
- *ret = 0;
- return 0;
- }
-
- if (icount->multiple &&
- !ext2fs_test_inode_bitmap(icount->multiple, ino))
- return EXT2_ET_INVALID_ARGUMENT;
-
- el = get_icount_el(icount, ino, 0);
- if (!el || el->count == 0)
- return EXT2_ET_INVALID_ARGUMENT;
-
- el->count--;
- if (el->count == 1)
- ext2fs_mark_inode_bitmap(icount->single, ino);
- if ((el->count == 0) && icount->multiple)
- ext2fs_unmark_inode_bitmap(icount->multiple, ino);
-
- if (ret)
- *ret = el->count;
- return 0;
-}
-
-errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
- __u16 count)
-{
- struct ext2_icount_el *el;
-
- if (!ino || (ino > icount->num_inodes))
- return EXT2_ET_INVALID_ARGUMENT;
-
- EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
-
- if (count == 1) {
- ext2fs_mark_inode_bitmap(icount->single, ino);
- if (icount->multiple)
- ext2fs_unmark_inode_bitmap(icount->multiple, ino);
- return 0;
- }
- if (count == 0) {
- ext2fs_unmark_inode_bitmap(icount->single, ino);
- if (icount->multiple) {
- /*
- * If the icount->multiple bitmap is enabled,
- * we can just clear both bitmaps and we're done
- */
- ext2fs_unmark_inode_bitmap(icount->multiple, ino);
- } else {
- el = get_icount_el(icount, ino, 0);
- if (el)
- el->count = 0;
- }
- return 0;
- }
-
- /*
- * Get the icount element
- */
- el = get_icount_el(icount, ino, 1);
- if (!el)
- return EXT2_ET_NO_MEMORY;
- el->count = count;
- ext2fs_unmark_inode_bitmap(icount->single, ino);
- if (icount->multiple)
- ext2fs_mark_inode_bitmap(icount->multiple, ino);
- return 0;
-}
-
-ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount)
-{
- if (!icount || icount->magic != EXT2_ET_MAGIC_ICOUNT)
- return 0;
-
- return icount->size;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/imager.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/imager.c
deleted file mode 100644
index 0f9cfcfafb..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/imager.c
+++ /dev/null
@@ -1,377 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * image.c --- writes out the critical parts of the filesystem as a
- * flat file.
- *
- * Copyright (C) 2000 Theodore Ts'o.
- *
- * Note: this uses the POSIX IO interfaces, unlike most of the other
- * functions in this library. So sue me.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-#ifndef HAVE_TYPE_SSIZE_T
-typedef int ssize_t;
-#endif
-
-/*
- * This function returns 1 if the specified block is all zeros
- */
-static int check_zero_block(char *buf, int blocksize)
-{
- char *cp = buf;
- int left = blocksize;
-
- while (left > 0) {
- if (*cp++)
- return 0;
- left--;
- }
- return 1;
-}
-
-/*
- * Write the inode table out as a single block.
- */
-#define BUF_BLOCKS 32
-
-errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags)
-{
- unsigned int group, left, c, d;
- char *buf, *cp;
- blk_t blk;
- ssize_t actual;
- errcode_t retval;
-
- buf = xmalloc(fs->blocksize * BUF_BLOCKS);
-
- for (group = 0; group < fs->group_desc_count; group++) {
- blk = fs->group_desc[(unsigned)group].bg_inode_table;
- if (!blk)
- return EXT2_ET_MISSING_INODE_TABLE;
- left = fs->inode_blocks_per_group;
- while (left) {
- c = BUF_BLOCKS;
- if (c > left)
- c = left;
- retval = io_channel_read_blk(fs->io, blk, c, buf);
- if (retval)
- goto errout;
- cp = buf;
- while (c) {
- if (!(flags & IMAGER_FLAG_SPARSEWRITE)) {
- d = c;
- goto skip_sparse;
- }
- /* Skip zero blocks */
- if (check_zero_block(cp, fs->blocksize)) {
- c--;
- blk++;
- left--;
- cp += fs->blocksize;
- lseek(fd, fs->blocksize, SEEK_CUR);
- continue;
- }
- /* Find non-zero blocks */
- for (d=1; d < c; d++) {
- if (check_zero_block(cp + d*fs->blocksize, fs->blocksize))
- break;
- }
- skip_sparse:
- actual = write(fd, cp, fs->blocksize * d);
- if (actual == -1) {
- retval = errno;
- goto errout;
- }
- if (actual != (ssize_t) (fs->blocksize * d)) {
- retval = EXT2_ET_SHORT_WRITE;
- goto errout;
- }
- blk += d;
- left -= d;
- cp += fs->blocksize * d;
- c -= d;
- }
- }
- }
- retval = 0;
-
-errout:
- free(buf);
- return retval;
-}
-
-/*
- * Read in the inode table and stuff it into place
- */
-errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd,
- int flags EXT2FS_ATTR((unused)))
-{
- unsigned int group, c, left;
- char *buf;
- blk_t blk;
- ssize_t actual;
- errcode_t retval;
-
- buf = xmalloc(fs->blocksize * BUF_BLOCKS);
-
- for (group = 0; group < fs->group_desc_count; group++) {
- blk = fs->group_desc[(unsigned)group].bg_inode_table;
- if (!blk) {
- retval = EXT2_ET_MISSING_INODE_TABLE;
- goto errout;
- }
- left = fs->inode_blocks_per_group;
- while (left) {
- c = BUF_BLOCKS;
- if (c > left)
- c = left;
- actual = read(fd, buf, fs->blocksize * c);
- if (actual == -1) {
- retval = errno;
- goto errout;
- }
- if (actual != (ssize_t) (fs->blocksize * c)) {
- retval = EXT2_ET_SHORT_READ;
- goto errout;
- }
- retval = io_channel_write_blk(fs->io, blk, c, buf);
- if (retval)
- goto errout;
-
- blk += c;
- left -= c;
- }
- }
- retval = ext2fs_flush_icache(fs);
-
-errout:
- free(buf);
- return retval;
-}
-
-/*
- * Write out superblock and group descriptors
- */
-errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd,
- int flags EXT2FS_ATTR((unused)))
-{
- char *buf, *cp;
- ssize_t actual;
- errcode_t retval;
-
- buf = xmalloc(fs->blocksize);
-
- /*
- * Write out the superblock
- */
- memset(buf, 0, fs->blocksize);
- memcpy(buf, fs->super, SUPERBLOCK_SIZE);
- actual = write(fd, buf, fs->blocksize);
- if (actual == -1) {
- retval = errno;
- goto errout;
- }
- if (actual != (ssize_t) fs->blocksize) {
- retval = EXT2_ET_SHORT_WRITE;
- goto errout;
- }
-
- /*
- * Now write out the block group descriptors
- */
- cp = (char *) fs->group_desc;
- actual = write(fd, cp, fs->blocksize * fs->desc_blocks);
- if (actual == -1) {
- retval = errno;
- goto errout;
- }
- if (actual != (ssize_t) (fs->blocksize * fs->desc_blocks)) {
- retval = EXT2_ET_SHORT_WRITE;
- goto errout;
- }
-
- retval = 0;
-
-errout:
- free(buf);
- return retval;
-}
-
-/*
- * Read the superblock and group descriptors and overwrite them.
- */
-errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd,
- int flags EXT2FS_ATTR((unused)))
-{
- char *buf;
- ssize_t actual, size;
- errcode_t retval;
-
- size = fs->blocksize * (fs->group_desc_count + 1);
- buf = xmalloc(size);
-
- /*
- * Read it all in.
- */
- actual = read(fd, buf, size);
- if (actual == -1) {
- retval = errno;
- goto errout;
- }
- if (actual != size) {
- retval = EXT2_ET_SHORT_READ;
- goto errout;
- }
-
- /*
- * Now copy in the superblock and group descriptors
- */
- memcpy(fs->super, buf, SUPERBLOCK_SIZE);
-
- memcpy(fs->group_desc, buf + fs->blocksize,
- fs->blocksize * fs->group_desc_count);
-
- retval = 0;
-
-errout:
- free(buf);
- return retval;
-}
-
-/*
- * Write the block/inode bitmaps.
- */
-errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
-{
- char *ptr;
- int c, size;
- char zero_buf[1024];
- ssize_t actual;
- errcode_t retval;
-
- if (flags & IMAGER_FLAG_INODEMAP) {
- if (!fs->inode_map) {
- retval = ext2fs_read_inode_bitmap(fs);
- if (retval)
- return retval;
- }
- ptr = fs->inode_map->bitmap;
- size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
- } else {
- if (!fs->block_map) {
- retval = ext2fs_read_block_bitmap(fs);
- if (retval)
- return retval;
- }
- ptr = fs->block_map->bitmap;
- size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
- }
- size = size * fs->group_desc_count;
-
- actual = write(fd, ptr, size);
- if (actual == -1) {
- retval = errno;
- goto errout;
- }
- if (actual != size) {
- retval = EXT2_ET_SHORT_WRITE;
- goto errout;
- }
- size = size % fs->blocksize;
- memset(zero_buf, 0, sizeof(zero_buf));
- if (size) {
- size = fs->blocksize - size;
- while (size) {
- c = size;
- if (c > (int) sizeof(zero_buf))
- c = sizeof(zero_buf);
- actual = write(fd, zero_buf, c);
- if (actual == -1) {
- retval = errno;
- goto errout;
- }
- if (actual != c) {
- retval = EXT2_ET_SHORT_WRITE;
- goto errout;
- }
- size -= c;
- }
- }
- retval = 0;
-errout:
- return retval;
-}
-
-
-/*
- * Read the block/inode bitmaps.
- */
-errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
-{
- char *ptr, *buf = NULL;
- int size;
- ssize_t actual;
- errcode_t retval;
-
- if (flags & IMAGER_FLAG_INODEMAP) {
- if (!fs->inode_map) {
- retval = ext2fs_read_inode_bitmap(fs);
- if (retval)
- return retval;
- }
- ptr = fs->inode_map->bitmap;
- size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
- } else {
- if (!fs->block_map) {
- retval = ext2fs_read_block_bitmap(fs);
- if (retval)
- return retval;
- }
- ptr = fs->block_map->bitmap;
- size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
- }
- size = size * fs->group_desc_count;
-
- buf = xmalloc(size);
-
- actual = read(fd, buf, size);
- if (actual == -1) {
- retval = errno;
- goto errout;
- }
- if (actual != size) {
- retval = EXT2_ET_SHORT_WRITE;
- goto errout;
- }
- memcpy(ptr, buf, size);
-
- retval = 0;
-errout:
- free(buf);
- return retval;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ind_block.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ind_block.c
deleted file mode 100644
index a1038300b3..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ind_block.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * ind_block.c --- indirect block I/O routines
- *
- * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- * 2001, 2002, 2003, 2004, 2005 by Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf)
-{
- errcode_t retval;
-#if BB_BIG_ENDIAN
- blk_t *block_nr;
- int i;
- int limit = fs->blocksize >> 2;
-#endif
-
- if ((fs->flags & EXT2_FLAG_IMAGE_FILE) &&
- (fs->io != fs->image_io))
- memset(buf, 0, fs->blocksize);
- else {
- retval = io_channel_read_blk(fs->io, blk, 1, buf);
- if (retval)
- return retval;
- }
-#if BB_BIG_ENDIAN
- if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_READ)) {
- block_nr = (blk_t *) buf;
- for (i = 0; i < limit; i++, block_nr++)
- *block_nr = ext2fs_swab32(*block_nr);
- }
-#endif
- return 0;
-}
-
-errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf)
-{
-#if BB_BIG_ENDIAN
- blk_t *block_nr;
- int i;
- int limit = fs->blocksize >> 2;
-#endif
-
- if (fs->flags & EXT2_FLAG_IMAGE_FILE)
- return 0;
-
-#if BB_BIG_ENDIAN
- if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_WRITE)) {
- block_nr = (blk_t *) buf;
- for (i = 0; i < limit; i++, block_nr++)
- *block_nr = ext2fs_swab32(*block_nr);
- }
-#endif
- return io_channel_write_blk(fs->io, blk, 1, buf);
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/initialize.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/initialize.c
deleted file mode 100644
index da2d151375..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/initialize.c
+++ /dev/null
@@ -1,388 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * initialize.c --- initialize a filesystem handle given superblock
- * parameters. Used by mke2fs when initializing a filesystem.
- *
- * Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-#if defined(__linux__) && defined(EXT2_OS_LINUX)
-#define CREATOR_OS EXT2_OS_LINUX
-#else
-#if defined(__GNU__) && defined(EXT2_OS_HURD)
-#define CREATOR_OS EXT2_OS_HURD
-#else
-#if defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD)
-#define CREATOR_OS EXT2_OS_FREEBSD
-#else
-#if defined(LITES) && defined(EXT2_OS_LITES)
-#define CREATOR_OS EXT2_OS_LITES
-#else
-#define CREATOR_OS EXT2_OS_LINUX /* by default */
-#endif /* defined(LITES) && defined(EXT2_OS_LITES) */
-#endif /* defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD) */
-#endif /* defined(__GNU__) && defined(EXT2_OS_HURD) */
-#endif /* defined(__linux__) && defined(EXT2_OS_LINUX) */
-
-/*
- * Note we override the kernel include file's idea of what the default
- * check interval (never) should be. It's a good idea to check at
- * least *occasionally*, specially since servers will never rarely get
- * to reboot, since Linux is so robust these days. :-)
- *
- * 180 days (six months) seems like a good value.
- */
-#ifdef EXT2_DFL_CHECKINTERVAL
-#undef EXT2_DFL_CHECKINTERVAL
-#endif
-#define EXT2_DFL_CHECKINTERVAL (86400L * 180L)
-
-/*
- * Calculate the number of GDT blocks to reserve for online filesystem growth.
- * The absolute maximum number of GDT blocks we can reserve is determined by
- * the number of block pointers that can fit into a single block.
- */
-static int calc_reserved_gdt_blocks(ext2_filsys fs)
-{
- struct ext2_super_block *sb = fs->super;
- unsigned long bpg = sb->s_blocks_per_group;
- unsigned int gdpb = fs->blocksize / sizeof(struct ext2_group_desc);
- unsigned long max_blocks = 0xffffffff;
- unsigned long rsv_groups;
- int rsv_gdb;
-
- /* We set it at 1024x the current filesystem size, or
- * the upper block count limit (2^32), whichever is lower.
- */
- if (sb->s_blocks_count < max_blocks / 1024)
- max_blocks = sb->s_blocks_count * 1024;
- rsv_groups = (max_blocks - sb->s_first_data_block + bpg - 1) / bpg;
- rsv_gdb = (rsv_groups + gdpb - 1) / gdpb - fs->desc_blocks;
- if (rsv_gdb > EXT2_ADDR_PER_BLOCK(sb))
- rsv_gdb = EXT2_ADDR_PER_BLOCK(sb);
-#ifdef RES_GDT_DEBUG
- printf("max_blocks %lu, rsv_groups = %lu, rsv_gdb = %lu\n",
- max_blocks, rsv_groups, rsv_gdb);
-#endif
-
- return rsv_gdb;
-}
-
-errcode_t ext2fs_initialize(const char *name, int flags,
- struct ext2_super_block *param,
- io_manager manager, ext2_filsys *ret_fs)
-{
- ext2_filsys fs;
- errcode_t retval;
- struct ext2_super_block *super;
- int frags_per_block;
- unsigned int rem;
- unsigned int overhead = 0;
- blk_t group_block;
- unsigned int ipg;
- dgrp_t i;
- blk_t numblocks;
- int rsv_gdt;
- char *buf;
-
- if (!param || !param->s_blocks_count)
- return EXT2_ET_INVALID_ARGUMENT;
-
- retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
- if (retval)
- return retval;
-
- memset(fs, 0, sizeof(struct struct_ext2_filsys));
- fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS;
- fs->flags = flags | EXT2_FLAG_RW;
- fs->umask = 022;
-#ifdef WORDS_BIGENDIAN
- fs->flags |= EXT2_FLAG_SWAP_BYTES;
-#endif
- retval = manager->open(name, IO_FLAG_RW, &fs->io);
- if (retval)
- goto cleanup;
- fs->image_io = fs->io;
- fs->io->app_data = fs;
- retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name);
- if (retval)
- goto cleanup;
-
- strcpy(fs->device_name, name);
- retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super);
- if (retval)
- goto cleanup;
- fs->super = super;
-
- memset(super, 0, SUPERBLOCK_SIZE);
-
-#define set_field(field, default) (super->field = param->field ? \
- param->field : (default))
-
- super->s_magic = EXT2_SUPER_MAGIC;
- super->s_state = EXT2_VALID_FS;
-
- set_field(s_log_block_size, 0); /* default blocksize: 1024 bytes */
- set_field(s_log_frag_size, 0); /* default fragsize: 1024 bytes */
- set_field(s_first_data_block, super->s_log_block_size ? 0 : 1);
- set_field(s_max_mnt_count, EXT2_DFL_MAX_MNT_COUNT);
- set_field(s_errors, EXT2_ERRORS_DEFAULT);
- set_field(s_feature_compat, 0);
- set_field(s_feature_incompat, 0);
- set_field(s_feature_ro_compat, 0);
- set_field(s_first_meta_bg, 0);
- if (super->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) {
- retval = EXT2_ET_UNSUPP_FEATURE;
- goto cleanup;
- }
- if (super->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
- retval = EXT2_ET_RO_UNSUPP_FEATURE;
- goto cleanup;
- }
-
- set_field(s_rev_level, EXT2_GOOD_OLD_REV);
- if (super->s_rev_level >= EXT2_DYNAMIC_REV) {
- set_field(s_first_ino, EXT2_GOOD_OLD_FIRST_INO);
- set_field(s_inode_size, EXT2_GOOD_OLD_INODE_SIZE);
- }
-
- set_field(s_checkinterval, EXT2_DFL_CHECKINTERVAL);
- super->s_mkfs_time = super->s_lastcheck = time(NULL);
-
- super->s_creator_os = CREATOR_OS;
-
- fs->blocksize = EXT2_BLOCK_SIZE(super);
- fs->fragsize = EXT2_FRAG_SIZE(super);
- frags_per_block = fs->blocksize / fs->fragsize;
-
- /* default: (fs->blocksize*8) blocks/group, up to 2^16 (GDT limit) */
- set_field(s_blocks_per_group, fs->blocksize * 8);
- if (super->s_blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(super))
- super->s_blocks_per_group = EXT2_MAX_BLOCKS_PER_GROUP(super);
- super->s_frags_per_group = super->s_blocks_per_group * frags_per_block;
-
- super->s_blocks_count = param->s_blocks_count;
- super->s_r_blocks_count = param->s_r_blocks_count;
- if (super->s_r_blocks_count >= param->s_blocks_count) {
- retval = EXT2_ET_INVALID_ARGUMENT;
- goto cleanup;
- }
-
- /*
- * If we're creating an external journal device, we don't need
- * to bother with the rest.
- */
- if (super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
- fs->group_desc_count = 0;
- ext2fs_mark_super_dirty(fs);
- *ret_fs = fs;
- return 0;
- }
-
-retry:
- fs->group_desc_count = (super->s_blocks_count -
- super->s_first_data_block +
- EXT2_BLOCKS_PER_GROUP(super) - 1)
- / EXT2_BLOCKS_PER_GROUP(super);
- if (fs->group_desc_count == 0) {
- retval = EXT2_ET_TOOSMALL;
- goto cleanup;
- }
- fs->desc_blocks = (fs->group_desc_count +
- EXT2_DESC_PER_BLOCK(super) - 1)
- / EXT2_DESC_PER_BLOCK(super);
-
- i = fs->blocksize >= 4096 ? 1 : 4096 / fs->blocksize;
- set_field(s_inodes_count, super->s_blocks_count / i);
-
- /*
- * Make sure we have at least EXT2_FIRST_INO + 1 inodes, so
- * that we have enough inodes for the filesystem(!)
- */
- if (super->s_inodes_count < EXT2_FIRST_INODE(super)+1)
- super->s_inodes_count = EXT2_FIRST_INODE(super)+1;
-
- /*
- * There should be at least as many inodes as the user
- * requested. Figure out how many inodes per group that
- * should be. But make sure that we don't allocate more than
- * one bitmap's worth of inodes each group.
- */
- ipg = (super->s_inodes_count + fs->group_desc_count - 1) /
- fs->group_desc_count;
- if (ipg > fs->blocksize * 8) {
- if (super->s_blocks_per_group >= 256) {
- /* Try again with slightly different parameters */
- super->s_blocks_per_group -= 8;
- super->s_blocks_count = param->s_blocks_count;
- super->s_frags_per_group = super->s_blocks_per_group *
- frags_per_block;
- goto retry;
- } else
- return EXT2_ET_TOO_MANY_INODES;
- }
-
- if (ipg > (unsigned) EXT2_MAX_INODES_PER_GROUP(super))
- ipg = EXT2_MAX_INODES_PER_GROUP(super);
-
- super->s_inodes_per_group = ipg;
- if (super->s_inodes_count > ipg * fs->group_desc_count)
- super->s_inodes_count = ipg * fs->group_desc_count;
-
- /*
- * Make sure the number of inodes per group completely fills
- * the inode table blocks in the descriptor. If not, add some
- * additional inodes/group. Waste not, want not...
- */
- fs->inode_blocks_per_group = (((super->s_inodes_per_group *
- EXT2_INODE_SIZE(super)) +
- EXT2_BLOCK_SIZE(super) - 1) /
- EXT2_BLOCK_SIZE(super));
- super->s_inodes_per_group = ((fs->inode_blocks_per_group *
- EXT2_BLOCK_SIZE(super)) /
- EXT2_INODE_SIZE(super));
- /*
- * Finally, make sure the number of inodes per group is a
- * multiple of 8. This is needed to simplify the bitmap
- * splicing code.
- */
- super->s_inodes_per_group &= ~7;
- fs->inode_blocks_per_group = (((super->s_inodes_per_group *
- EXT2_INODE_SIZE(super)) +
- EXT2_BLOCK_SIZE(super) - 1) /
- EXT2_BLOCK_SIZE(super));
-
- /*
- * adjust inode count to reflect the adjusted inodes_per_group
- */
- super->s_inodes_count = super->s_inodes_per_group *
- fs->group_desc_count;
- super->s_free_inodes_count = super->s_inodes_count;
-
- /*
- * check the number of reserved group descriptor table blocks
- */
- if (super->s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INO)
- rsv_gdt = calc_reserved_gdt_blocks(fs);
- else
- rsv_gdt = 0;
- set_field(s_reserved_gdt_blocks, rsv_gdt);
- if (super->s_reserved_gdt_blocks > EXT2_ADDR_PER_BLOCK(super)) {
- retval = EXT2_ET_RES_GDT_BLOCKS;
- goto cleanup;
- }
-
- /*
- * Overhead is the number of bookkeeping blocks per group. It
- * includes the superblock backup, the group descriptor
- * backups, the inode bitmap, the block bitmap, and the inode
- * table.
- */
-
- overhead = (int) (2 + fs->inode_blocks_per_group);
-
- if (ext2fs_bg_has_super(fs, fs->group_desc_count - 1))
- overhead += 1 + fs->desc_blocks + super->s_reserved_gdt_blocks;
-
- /* This can only happen if the user requested too many inodes */
- if (overhead > super->s_blocks_per_group)
- return EXT2_ET_TOO_MANY_INODES;
-
- /*
- * See if the last group is big enough to support the
- * necessary data structures. If not, we need to get rid of
- * it.
- */
- rem = ((super->s_blocks_count - super->s_first_data_block) %
- super->s_blocks_per_group);
- if ((fs->group_desc_count == 1) && rem && (rem < overhead))
- return EXT2_ET_TOOSMALL;
- if (rem && (rem < overhead+50)) {
- super->s_blocks_count -= rem;
- goto retry;
- }
-
- /*
- * At this point we know how big the filesystem will be. So
- * we can do any and all allocations that depend on the block
- * count.
- */
-
- retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
- if (retval)
- goto cleanup;
-
- sprintf(buf, "block bitmap for %s", fs->device_name);
- retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
- if (retval)
- goto cleanup;
-
- sprintf(buf, "inode bitmap for %s", fs->device_name);
- retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
- if (retval)
- goto cleanup;
-
- ext2fs_free_mem(&buf);
-
- retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize,
- &fs->group_desc);
- if (retval)
- goto cleanup;
-
- memset(fs->group_desc, 0, (size_t) fs->desc_blocks * fs->blocksize);
-
- /*
- * Reserve the superblock and group descriptors for each
- * group, and fill in the correct group statistics for group.
- * Note that although the block bitmap, inode bitmap, and
- * inode table have not been allocated (and in fact won't be
- * by this routine), they are accounted for nevertheless.
- */
- group_block = super->s_first_data_block;
- super->s_free_blocks_count = 0;
- for (i = 0; i < fs->group_desc_count; i++) {
- numblocks = ext2fs_reserve_super_and_bgd(fs, i, fs->block_map);
-
- super->s_free_blocks_count += numblocks;
- fs->group_desc[i].bg_free_blocks_count = numblocks;
- fs->group_desc[i].bg_free_inodes_count =
- fs->super->s_inodes_per_group;
- fs->group_desc[i].bg_used_dirs_count = 0;
-
- group_block += super->s_blocks_per_group;
- }
-
- ext2fs_mark_super_dirty(fs);
- ext2fs_mark_bb_dirty(fs);
- ext2fs_mark_ib_dirty(fs);
-
- io_channel_set_blksize(fs->io, fs->blocksize);
-
- *ret_fs = fs;
- return 0;
-cleanup:
- ext2fs_free(fs);
- return retval;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/inline.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/inline.c
deleted file mode 100644
index 7457b93962..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/inline.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * inline.c --- Includes the inlined functions defined in the header
- * files as standalone functions, in case the application program
- * is compiled with inlining turned off.
- *
- * Copyright (C) 1993, 1994 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#define INCLUDE_INLINE_FUNCS
-#include "ext2fs.h"
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/inode.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/inode.c
deleted file mode 100644
index 7a1d5c94bb..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/inode.c
+++ /dev/null
@@ -1,766 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * inode.c --- utility routines to read and write inodes
- *
- * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fsP.h"
-#include "e2image.h"
-
-struct ext2_struct_inode_scan {
- errcode_t magic;
- ext2_filsys fs;
- ext2_ino_t current_inode;
- blk_t current_block;
- dgrp_t current_group;
- ext2_ino_t inodes_left;
- blk_t blocks_left;
- dgrp_t groups_left;
- blk_t inode_buffer_blocks;
- char * inode_buffer;
- int inode_size;
- char * ptr;
- int bytes_left;
- char *temp_buffer;
- errcode_t (*done_group)(ext2_filsys fs,
- dgrp_t group,
- void * priv_data);
- void * done_group_data;
- int bad_block_ptr;
- int scan_flags;
- int reserved[6];
-};
-
-/*
- * This routine flushes the icache, if it exists.
- */
-errcode_t ext2fs_flush_icache(ext2_filsys fs)
-{
- int i;
-
- if (!fs->icache)
- return 0;
-
- for (i=0; i < fs->icache->cache_size; i++)
- fs->icache->cache[i].ino = 0;
-
- fs->icache->buffer_blk = 0;
- return 0;
-}
-
-static errcode_t create_icache(ext2_filsys fs)
-{
- errcode_t retval;
-
- if (fs->icache)
- return 0;
- retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache), &fs->icache);
- if (retval)
- return retval;
-
- memset(fs->icache, 0, sizeof(struct ext2_inode_cache));
- retval = ext2fs_get_mem(fs->blocksize, &fs->icache->buffer);
- if (retval) {
- ext2fs_free_mem(&fs->icache);
- return retval;
- }
- fs->icache->buffer_blk = 0;
- fs->icache->cache_last = -1;
- fs->icache->cache_size = 4;
- fs->icache->refcount = 1;
- retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache_ent)
- * fs->icache->cache_size,
- &fs->icache->cache);
- if (retval) {
- ext2fs_free_mem(&fs->icache->buffer);
- ext2fs_free_mem(&fs->icache);
- return retval;
- }
- ext2fs_flush_icache(fs);
- return 0;
-}
-
-errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
- ext2_inode_scan *ret_scan)
-{
- ext2_inode_scan scan;
- errcode_t retval;
- errcode_t (*save_get_blocks)(ext2_filsys f, ext2_ino_t ino, blk_t *blocks);
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- /*
- * If fs->badblocks isn't set, then set it --- since the inode
- * scanning functions require it.
- */
- if (fs->badblocks == 0) {
- /*
- * Temporarly save fs->get_blocks and set it to zero,
- * for compatibility with old e2fsck's.
- */
- save_get_blocks = fs->get_blocks;
- fs->get_blocks = 0;
- retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
- if (retval) {
- ext2fs_badblocks_list_free(fs->badblocks);
- fs->badblocks = 0;
- }
- fs->get_blocks = save_get_blocks;
- }
-
- retval = ext2fs_get_mem(sizeof(struct ext2_struct_inode_scan), &scan);
- if (retval)
- return retval;
- memset(scan, 0, sizeof(struct ext2_struct_inode_scan));
-
- scan->magic = EXT2_ET_MAGIC_INODE_SCAN;
- scan->fs = fs;
- scan->inode_size = EXT2_INODE_SIZE(fs->super);
- scan->bytes_left = 0;
- scan->current_group = 0;
- scan->groups_left = fs->group_desc_count - 1;
- scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : 8;
- scan->current_block = scan->fs->
- group_desc[scan->current_group].bg_inode_table;
- scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
- scan->blocks_left = scan->fs->inode_blocks_per_group;
- retval = ext2fs_get_mem((size_t) (scan->inode_buffer_blocks *
- fs->blocksize),
- &scan->inode_buffer);
- scan->done_group = 0;
- scan->done_group_data = 0;
- scan->bad_block_ptr = 0;
- if (retval) {
- ext2fs_free_mem(&scan);
- return retval;
- }
- retval = ext2fs_get_mem(scan->inode_size, &scan->temp_buffer);
- if (retval) {
- ext2fs_free_mem(&scan->inode_buffer);
- ext2fs_free_mem(&scan);
- return retval;
- }
- if (scan->fs->badblocks && scan->fs->badblocks->num)
- scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS;
- *ret_scan = scan;
- return 0;
-}
-
-void ext2fs_close_inode_scan(ext2_inode_scan scan)
-{
- if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
- return;
-
- ext2fs_free_mem(&scan->inode_buffer);
- scan->inode_buffer = NULL;
- ext2fs_free_mem(&scan->temp_buffer);
- scan->temp_buffer = NULL;
- ext2fs_free_mem(&scan);
-}
-
-void ext2fs_set_inode_callback(ext2_inode_scan scan,
- errcode_t (*done_group)(ext2_filsys fs,
- dgrp_t group,
- void * priv_data),
- void *done_group_data)
-{
- if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
- return;
-
- scan->done_group = done_group;
- scan->done_group_data = done_group_data;
-}
-
-int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags,
- int clear_flags)
-{
- int old_flags;
-
- if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
- return 0;
-
- old_flags = scan->scan_flags;
- scan->scan_flags &= ~clear_flags;
- scan->scan_flags |= set_flags;
- return old_flags;
-}
-
-/*
- * This function is called by ext2fs_get_next_inode when it needs to
- * get ready to read in a new blockgroup.
- */
-static errcode_t get_next_blockgroup(ext2_inode_scan scan)
-{
- scan->current_group++;
- scan->groups_left--;
-
- scan->current_block = scan->fs->
- group_desc[scan->current_group].bg_inode_table;
-
- scan->current_inode = scan->current_group *
- EXT2_INODES_PER_GROUP(scan->fs->super);
-
- scan->bytes_left = 0;
- scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
- scan->blocks_left = scan->fs->inode_blocks_per_group;
- return 0;
-}
-
-errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,
- int group)
-{
- scan->current_group = group - 1;
- scan->groups_left = scan->fs->group_desc_count - group;
- return get_next_blockgroup(scan);
-}
-
-/*
- * This function is called by get_next_blocks() to check for bad
- * blocks in the inode table.
- *
- * This function assumes that badblocks_list->list is sorted in
- * increasing order.
- */
-static errcode_t check_for_inode_bad_blocks(ext2_inode_scan scan,
- blk_t *num_blocks)
-{
- blk_t blk = scan->current_block;
- badblocks_list bb = scan->fs->badblocks;
-
- /*
- * If the inode table is missing, then obviously there are no
- * bad blocks. :-)
- */
- if (blk == 0)
- return 0;
-
- /*
- * If the current block is greater than the bad block listed
- * in the bad block list, then advance the pointer until this
- * is no longer the case. If we run out of bad blocks, then
- * we don't need to do any more checking!
- */
- while (blk > bb->list[scan->bad_block_ptr]) {
- if (++scan->bad_block_ptr >= bb->num) {
- scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
- return 0;
- }
- }
-
- /*
- * If the current block is equal to the bad block listed in
- * the bad block list, then handle that one block specially.
- * (We could try to handle runs of bad blocks, but that
- * only increases CPU efficiency by a small amount, at the
- * expense of a huge expense of code complexity, and for an
- * uncommon case at that.)
- */
- if (blk == bb->list[scan->bad_block_ptr]) {
- scan->scan_flags |= EXT2_SF_BAD_INODE_BLK;
- *num_blocks = 1;
- if (++scan->bad_block_ptr >= bb->num)
- scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
- return 0;
- }
-
- /*
- * If there is a bad block in the range that we're about to
- * read in, adjust the number of blocks to read so that we we
- * don't read in the bad block. (Then the next block to read
- * will be the bad block, which is handled in the above case.)
- */
- if ((blk + *num_blocks) > bb->list[scan->bad_block_ptr])
- *num_blocks = (int) (bb->list[scan->bad_block_ptr] - blk);
-
- return 0;
-}
-
-/*
- * This function is called by ext2fs_get_next_inode when it needs to
- * read in more blocks from the current blockgroup's inode table.
- */
-static errcode_t get_next_blocks(ext2_inode_scan scan)
-{
- blk_t num_blocks;
- errcode_t retval;
-
- /*
- * Figure out how many blocks to read; we read at most
- * inode_buffer_blocks, and perhaps less if there aren't that
- * many blocks left to read.
- */
- num_blocks = scan->inode_buffer_blocks;
- if (num_blocks > scan->blocks_left)
- num_blocks = scan->blocks_left;
-
- /*
- * If the past block "read" was a bad block, then mark the
- * left-over extra bytes as also being bad.
- */
- if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) {
- if (scan->bytes_left)
- scan->scan_flags |= EXT2_SF_BAD_EXTRA_BYTES;
- scan->scan_flags &= ~EXT2_SF_BAD_INODE_BLK;
- }
-
- /*
- * Do inode bad block processing, if necessary.
- */
- if (scan->scan_flags & EXT2_SF_CHK_BADBLOCKS) {
- retval = check_for_inode_bad_blocks(scan, &num_blocks);
- if (retval)
- return retval;
- }
-
- if ((scan->scan_flags & EXT2_SF_BAD_INODE_BLK) ||
- (scan->current_block == 0)) {
- memset(scan->inode_buffer, 0,
- (size_t) num_blocks * scan->fs->blocksize);
- } else {
- retval = io_channel_read_blk(scan->fs->io,
- scan->current_block,
- (int) num_blocks,
- scan->inode_buffer);
- if (retval)
- return EXT2_ET_NEXT_INODE_READ;
- }
- scan->ptr = scan->inode_buffer;
- scan->bytes_left = num_blocks * scan->fs->blocksize;
-
- scan->blocks_left -= num_blocks;
- if (scan->current_block)
- scan->current_block += num_blocks;
- return 0;
-}
-
-errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, ext2_ino_t *ino,
- struct ext2_inode *inode, int bufsize)
-{
- errcode_t retval;
- int extra_bytes = 0;
-
- EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN);
-
- /*
- * Do we need to start reading a new block group?
- */
- if (scan->inodes_left <= 0) {
- force_new_group:
- if (scan->done_group) {
- retval = (scan->done_group)
- (scan->fs, scan->current_group,
- scan->done_group_data);
- if (retval)
- return retval;
- }
- if (scan->groups_left <= 0) {
- *ino = 0;
- return 0;
- }
- retval = get_next_blockgroup(scan);
- if (retval)
- return retval;
- }
- /*
- * This is done outside the above if statement so that the
- * check can be done for block group #0.
- */
- if (scan->current_block == 0) {
- if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) {
- goto force_new_group;
- } else
- return EXT2_ET_MISSING_INODE_TABLE;
- }
-
-
- /*
- * Have we run out of space in the inode buffer? If so, we
- * need to read in more blocks.
- */
- if (scan->bytes_left < scan->inode_size) {
- memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left);
- extra_bytes = scan->bytes_left;
-
- retval = get_next_blocks(scan);
- if (retval)
- return retval;
-#if 0
- /*
- * XXX test Need check for used inode somehow.
- * (Note: this is hard.)
- */
- if (is_empty_scan(scan))
- goto force_new_group;
-#endif
- }
-
- retval = 0;
- if (extra_bytes) {
- memcpy(scan->temp_buffer+extra_bytes, scan->ptr,
- scan->inode_size - extra_bytes);
- scan->ptr += scan->inode_size - extra_bytes;
- scan->bytes_left -= scan->inode_size - extra_bytes;
-
-#if BB_BIG_ENDIAN
- if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
- ext2fs_swap_inode_full(scan->fs,
- (struct ext2_inode_large *) inode,
- (struct ext2_inode_large *) scan->temp_buffer,
- 0, bufsize);
- else
-#endif
- *inode = *((struct ext2_inode *) scan->temp_buffer);
- if (scan->scan_flags & EXT2_SF_BAD_EXTRA_BYTES)
- retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
- scan->scan_flags &= ~EXT2_SF_BAD_EXTRA_BYTES;
- } else {
-#if BB_BIG_ENDIAN
- if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
- ext2fs_swap_inode_full(scan->fs,
- (struct ext2_inode_large *) inode,
- (struct ext2_inode_large *) scan->ptr,
- 0, bufsize);
- else
-#endif
- memcpy(inode, scan->ptr, bufsize);
- scan->ptr += scan->inode_size;
- scan->bytes_left -= scan->inode_size;
- if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK)
- retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
- }
-
- scan->inodes_left--;
- scan->current_inode++;
- *ino = scan->current_inode;
- return retval;
-}
-
-errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino,
- struct ext2_inode *inode)
-{
- return ext2fs_get_next_inode_full(scan, ino, inode,
- sizeof(struct ext2_inode));
-}
-
-/*
- * Functions to read and write a single inode.
- */
-errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode * inode, int bufsize)
-{
- unsigned long group, block, block_nr, offset;
- char *ptr;
- errcode_t retval;
- int clen, i, inodes_per_block, length;
- io_channel io;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- /* Check to see if user has an override function */
- if (fs->read_inode) {
- retval = (fs->read_inode)(fs, ino, inode);
- if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
- return retval;
- }
- /* Create inode cache if not present */
- if (!fs->icache) {
- retval = create_icache(fs);
- if (retval)
- return retval;
- }
- /* Check to see if it's in the inode cache */
- if (bufsize == sizeof(struct ext2_inode)) {
- /* only old good inode can be retrieve from the cache */
- for (i=0; i < fs->icache->cache_size; i++) {
- if (fs->icache->cache[i].ino == ino) {
- *inode = fs->icache->cache[i].inode;
- return 0;
- }
- }
- }
- if ((ino == 0) || (ino > fs->super->s_inodes_count))
- return EXT2_ET_BAD_INODE_NUM;
- if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
- inodes_per_block = fs->blocksize / EXT2_INODE_SIZE(fs->super);
- block_nr = fs->image_header->offset_inode / fs->blocksize;
- block_nr += (ino - 1) / inodes_per_block;
- offset = ((ino - 1) % inodes_per_block) *
- EXT2_INODE_SIZE(fs->super);
- io = fs->image_io;
- } else {
- group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
- offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
- EXT2_INODE_SIZE(fs->super);
- block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
- if (!fs->group_desc[(unsigned)group].bg_inode_table)
- return EXT2_ET_MISSING_INODE_TABLE;
- block_nr = fs->group_desc[(unsigned)group].bg_inode_table +
- block;
- io = fs->io;
- }
- offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
-
- length = EXT2_INODE_SIZE(fs->super);
- if (bufsize < length)
- length = bufsize;
-
- ptr = (char *) inode;
- while (length) {
- clen = length;
- if ((offset + length) > fs->blocksize)
- clen = fs->blocksize - offset;
-
- if (block_nr != fs->icache->buffer_blk) {
- retval = io_channel_read_blk(io, block_nr, 1,
- fs->icache->buffer);
- if (retval)
- return retval;
- fs->icache->buffer_blk = block_nr;
- }
-
- memcpy(ptr, ((char *) fs->icache->buffer) + (unsigned) offset,
- clen);
-
- offset = 0;
- length -= clen;
- ptr += clen;
- block_nr++;
- }
-
-#if BB_BIG_ENDIAN
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
- ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) inode,
- (struct ext2_inode_large *) inode,
- 0, length);
-#endif
-
- /* Update the inode cache */
- fs->icache->cache_last = (fs->icache->cache_last + 1) %
- fs->icache->cache_size;
- fs->icache->cache[fs->icache->cache_last].ino = ino;
- fs->icache->cache[fs->icache->cache_last].inode = *inode;
-
- return 0;
-}
-
-errcode_t ext2fs_read_inode(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode * inode)
-{
- return ext2fs_read_inode_full(fs, ino, inode,
- sizeof(struct ext2_inode));
-}
-
-errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode * inode, int bufsize)
-{
- unsigned long group, block, block_nr, offset;
- errcode_t retval = 0;
- struct ext2_inode_large temp_inode, *w_inode;
- char *ptr;
- int clen, i, length;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- /* Check to see if user provided an override function */
- if (fs->write_inode) {
- retval = (fs->write_inode)(fs, ino, inode);
- if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
- return retval;
- }
-
- /* Check to see if the inode cache needs to be updated */
- if (fs->icache) {
- for (i=0; i < fs->icache->cache_size; i++) {
- if (fs->icache->cache[i].ino == ino) {
- fs->icache->cache[i].inode = *inode;
- break;
- }
- }
- } else {
- retval = create_icache(fs);
- if (retval)
- return retval;
- }
-
- if (!(fs->flags & EXT2_FLAG_RW))
- return EXT2_ET_RO_FILSYS;
-
- if ((ino == 0) || (ino > fs->super->s_inodes_count))
- return EXT2_ET_BAD_INODE_NUM;
-
- length = bufsize;
- if (length < EXT2_INODE_SIZE(fs->super))
- length = EXT2_INODE_SIZE(fs->super);
-
- if (length > (int) sizeof(struct ext2_inode_large)) {
- w_inode = xmalloc(length);
- } else
- w_inode = &temp_inode;
- memset(w_inode, 0, length);
-
-#if BB_BIG_ENDIAN
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
- ext2fs_swap_inode_full(fs, w_inode,
- (struct ext2_inode_large *) inode,
- 1, bufsize);
- else
-#endif
- memcpy(w_inode, inode, bufsize);
-
- group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
- offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
- EXT2_INODE_SIZE(fs->super);
- block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
- if (!fs->group_desc[(unsigned) group].bg_inode_table)
- return EXT2_ET_MISSING_INODE_TABLE;
- block_nr = fs->group_desc[(unsigned) group].bg_inode_table + block;
-
- offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
-
- length = EXT2_INODE_SIZE(fs->super);
- if (length > bufsize)
- length = bufsize;
-
- ptr = (char *) w_inode;
-
- while (length) {
- clen = length;
- if ((offset + length) > fs->blocksize)
- clen = fs->blocksize - offset;
-
- if (fs->icache->buffer_blk != block_nr) {
- retval = io_channel_read_blk(fs->io, block_nr, 1,
- fs->icache->buffer);
- if (retval)
- goto errout;
- fs->icache->buffer_blk = block_nr;
- }
-
-
- memcpy((char *) fs->icache->buffer + (unsigned) offset,
- ptr, clen);
-
- retval = io_channel_write_blk(fs->io, block_nr, 1,
- fs->icache->buffer);
- if (retval)
- goto errout;
-
- offset = 0;
- ptr += clen;
- length -= clen;
- block_nr++;
- }
-
- fs->flags |= EXT2_FLAG_CHANGED;
-errout:
- if (w_inode && w_inode != &temp_inode)
- free(w_inode);
- return retval;
-}
-
-errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode)
-{
- return ext2fs_write_inode_full(fs, ino, inode,
- sizeof(struct ext2_inode));
-}
-
-/*
- * This function should be called when writing a new inode. It makes
- * sure that extra part of large inodes is initialized properly.
- */
-errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode)
-{
- struct ext2_inode *buf;
- int size = EXT2_INODE_SIZE(fs->super);
- struct ext2_inode_large *large_inode;
-
- if (size == sizeof(struct ext2_inode))
- return ext2fs_write_inode_full(fs, ino, inode,
- sizeof(struct ext2_inode));
-
- buf = xmalloc(size);
-
- memset(buf, 0, size);
- *buf = *inode;
-
- large_inode = (struct ext2_inode_large *) buf;
- large_inode->i_extra_isize = sizeof(struct ext2_inode_large) -
- EXT2_GOOD_OLD_INODE_SIZE;
-
- return ext2fs_write_inode_full(fs, ino, buf, size);
-}
-
-
-errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks)
-{
- struct ext2_inode inode;
- int i;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (ino > fs->super->s_inodes_count)
- return EXT2_ET_BAD_INODE_NUM;
-
- if (fs->get_blocks) {
- if (!(*fs->get_blocks)(fs, ino, blocks))
- return 0;
- }
- retval = ext2fs_read_inode(fs, ino, &inode);
- if (retval)
- return retval;
- for (i=0; i < EXT2_N_BLOCKS; i++)
- blocks[i] = inode.i_block[i];
- return 0;
-}
-
-errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino)
-{
- struct ext2_inode inode;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (ino > fs->super->s_inodes_count)
- return EXT2_ET_BAD_INODE_NUM;
-
- if (fs->check_directory) {
- retval = (fs->check_directory)(fs, ino);
- if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
- return retval;
- }
- retval = ext2fs_read_inode(fs, ino, &inode);
- if (retval)
- return retval;
- if (!LINUX_S_ISDIR(inode.i_mode))
- return EXT2_ET_NO_DIRECTORY;
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/inode_io.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/inode_io.c
deleted file mode 100644
index b861d5ff69..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/inode_io.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * inode_io.c --- This is allows an inode in an ext2 filesystem image
- * to be accessed via the I/O manager interface.
- *
- * Copyright (C) 2002 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <time.h>
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * For checking structure magic numbers...
- */
-
-#define EXT2_CHECK_MAGIC(struct, code) \
- if ((struct)->magic != (code)) return (code)
-
-struct inode_private_data {
- int magic;
- char name[32];
- ext2_file_t file;
- ext2_filsys fs;
- ext2_ino_t ino;
- struct ext2_inode inode;
- int flags;
- struct inode_private_data *next;
-};
-
-#define CHANNEL_HAS_INODE 0x8000
-
-static struct inode_private_data *top_intern;
-static int ino_unique = 0;
-
-static errcode_t inode_open(const char *name, int flags, io_channel *channel);
-static errcode_t inode_close(io_channel channel);
-static errcode_t inode_set_blksize(io_channel channel, int blksize);
-static errcode_t inode_read_blk(io_channel channel, unsigned long block,
- int count, void *data);
-static errcode_t inode_write_blk(io_channel channel, unsigned long block,
- int count, const void *data);
-static errcode_t inode_flush(io_channel channel);
-static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
- int size, const void *data);
-
-static struct struct_io_manager struct_inode_manager = {
- EXT2_ET_MAGIC_IO_MANAGER,
- "Inode I/O Manager",
- inode_open,
- inode_close,
- inode_set_blksize,
- inode_read_blk,
- inode_write_blk,
- inode_flush,
- inode_write_byte
-};
-
-io_manager inode_io_manager = &struct_inode_manager;
-
-errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode *inode,
- char **name)
-{
- struct inode_private_data *data;
- errcode_t retval;
-
- if ((retval = ext2fs_get_mem(sizeof(struct inode_private_data),
- &data)))
- return retval;
- data->magic = EXT2_ET_MAGIC_INODE_IO_CHANNEL;
- sprintf(data->name, "%u:%d", ino, ino_unique++);
- data->file = 0;
- data->fs = fs;
- data->ino = ino;
- data->flags = 0;
- if (inode) {
- memcpy(&data->inode, inode, sizeof(struct ext2_inode));
- data->flags |= CHANNEL_HAS_INODE;
- }
- data->next = top_intern;
- top_intern = data;
- *name = data->name;
- return 0;
-}
-
-errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino,
- char **name)
-{
- return ext2fs_inode_io_intern2(fs, ino, NULL, name);
-}
-
-
-static errcode_t inode_open(const char *name, int flags, io_channel *channel)
-{
- io_channel io = NULL;
- struct inode_private_data *prev, *data = NULL;
- errcode_t retval;
- int open_flags;
-
- if (name == 0)
- return EXT2_ET_BAD_DEVICE_NAME;
-
- for (data = top_intern, prev = NULL; data;
- prev = data, data = data->next)
- if (strcmp(name, data->name) == 0)
- break;
- if (!data)
- return ENOENT;
- if (prev)
- prev->next = data->next;
- else
- top_intern = data->next;
-
- retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
- if (retval)
- goto cleanup;
- memset(io, 0, sizeof(struct struct_io_channel));
-
- io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
- io->manager = inode_io_manager;
- retval = ext2fs_get_mem(strlen(name)+1, &io->name);
- if (retval)
- goto cleanup;
-
- strcpy(io->name, name);
- io->private_data = data;
- io->block_size = 1024;
- io->read_error = 0;
- io->write_error = 0;
- io->refcount = 1;
-
- open_flags = (flags & IO_FLAG_RW) ? EXT2_FILE_WRITE : 0;
- retval = ext2fs_file_open2(data->fs, data->ino,
- (data->flags & CHANNEL_HAS_INODE) ?
- &data->inode : 0, open_flags,
- &data->file);
- if (retval)
- goto cleanup;
-
- *channel = io;
- return 0;
-
-cleanup:
- if (data) {
- ext2fs_free_mem(&data);
- }
- if (io)
- ext2fs_free_mem(&io);
- return retval;
-}
-
-static errcode_t inode_close(io_channel channel)
-{
- struct inode_private_data *data;
- errcode_t retval = 0;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct inode_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
-
- if (--channel->refcount > 0)
- return 0;
-
- retval = ext2fs_file_close(data->file);
-
- ext2fs_free_mem(&channel->private_data);
- if (channel->name)
- ext2fs_free_mem(&channel->name);
- ext2fs_free_mem(&channel);
- return retval;
-}
-
-static errcode_t inode_set_blksize(io_channel channel, int blksize)
-{
- struct inode_private_data *data;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct inode_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
-
- channel->block_size = blksize;
- return 0;
-}
-
-
-static errcode_t inode_read_blk(io_channel channel, unsigned long block,
- int count, void *buf)
-{
- struct inode_private_data *data;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct inode_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
-
- if ((retval = ext2fs_file_lseek(data->file,
- block * channel->block_size,
- EXT2_SEEK_SET, 0)))
- return retval;
-
- count = (count < 0) ? -count : (count * channel->block_size);
-
- return ext2fs_file_read(data->file, buf, count, 0);
-}
-
-static errcode_t inode_write_blk(io_channel channel, unsigned long block,
- int count, const void *buf)
-{
- struct inode_private_data *data;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct inode_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
-
- if ((retval = ext2fs_file_lseek(data->file,
- block * channel->block_size,
- EXT2_SEEK_SET, 0)))
- return retval;
-
- count = (count < 0) ? -count : (count * channel->block_size);
-
- return ext2fs_file_write(data->file, buf, count, 0);
-}
-
-static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
- int size, const void *buf)
-{
- struct inode_private_data *data;
- errcode_t retval = 0;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct inode_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
-
- if ((retval = ext2fs_file_lseek(data->file, offset,
- EXT2_SEEK_SET, 0)))
- return retval;
-
- return ext2fs_file_write(data->file, buf, size, 0);
-}
-
-/*
- * Flush data buffers to disk.
- */
-static errcode_t inode_flush(io_channel channel)
-{
- struct inode_private_data *data;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct inode_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
-
- return ext2fs_file_flush(data->file);
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/io_manager.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/io_manager.c
deleted file mode 100644
index b47038602a..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/io_manager.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * io_manager.c --- the I/O manager abstraction
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-errcode_t io_channel_set_options(io_channel channel, const char *opts)
-{
- errcode_t retval = 0;
- char *next, *ptr, *options, *arg;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
-
- if (!opts)
- return 0;
-
- if (!channel->manager->set_option)
- return EXT2_ET_INVALID_ARGUMENT;
-
- options = malloc(strlen(opts)+1);
- if (!options)
- return EXT2_ET_NO_MEMORY;
- strcpy(options, opts);
- ptr = options;
-
- while (ptr && *ptr) {
- next = strchr(ptr, '&');
- if (next)
- *next++ = 0;
-
- arg = strchr(ptr, '=');
- if (arg)
- *arg++ = 0;
-
- retval = (channel->manager->set_option)(channel, ptr, arg);
- if (retval)
- break;
- ptr = next;
- }
- free(options);
- return retval;
-}
-
-errcode_t io_channel_write_byte(io_channel channel, unsigned long offset,
- int count, const void *data)
-{
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
-
- if (channel->manager->write_byte)
- return channel->manager->write_byte(channel, offset,
- count, data);
-
- return EXT2_ET_UNIMPLEMENTED;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/irel.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/irel.h
deleted file mode 100644
index 91d1d89d5f..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/irel.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * irel.h
- *
- * Copyright (C) 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-struct ext2_inode_reference {
- blk_t block;
- __u16 offset;
-};
-
-struct ext2_inode_relocate_entry {
- ext2_ino_t new;
- ext2_ino_t orig;
- __u16 flags;
- __u16 max_refs;
-};
-
-typedef struct ext2_inode_relocation_table *ext2_irel;
-
-struct ext2_inode_relocation_table {
- __u32 magic;
- char *name;
- ext2_ino_t current;
- void *priv_data;
-
- /*
- * Add an inode relocation entry.
- */
- errcode_t (*put)(ext2_irel irel, ext2_ino_t old,
- struct ext2_inode_relocate_entry *ent);
- /*
- * Get an inode relocation entry.
- */
- errcode_t (*get)(ext2_irel irel, ext2_ino_t old,
- struct ext2_inode_relocate_entry *ent);
-
- /*
- * Get an inode relocation entry by its original inode number
- */
- errcode_t (*get_by_orig)(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old,
- struct ext2_inode_relocate_entry *ent);
-
- /*
- * Initialize for iterating over the inode relocation entries.
- */
- errcode_t (*start_iter)(ext2_irel irel);
-
- /*
- * The iterator function for the inode relocation entries.
- * Returns an inode number of 0 when out of entries.
- */
- errcode_t (*next)(ext2_irel irel, ext2_ino_t *old,
- struct ext2_inode_relocate_entry *ent);
-
- /*
- * Add an inode reference (i.e., note the fact that a
- * particular block/offset contains a reference to an inode)
- */
- errcode_t (*add_ref)(ext2_irel irel, ext2_ino_t ino,
- struct ext2_inode_reference *ref);
-
- /*
- * Initialize for iterating over the inode references for a
- * particular inode.
- */
- errcode_t (*start_iter_ref)(ext2_irel irel, ext2_ino_t ino);
-
- /*
- * The iterator function for the inode references for an
- * inode. The references for only one inode can be interator
- * over at a time, as the iterator state is stored in ext2_irel.
- */
- errcode_t (*next_ref)(ext2_irel irel,
- struct ext2_inode_reference *ref);
-
- /*
- * Move the inode relocation table from one inode number to
- * another. Note that the inode references also must move.
- */
- errcode_t (*move)(ext2_irel irel, ext2_ino_t old, ext2_ino_t new);
-
- /*
- * Remove an inode relocation entry, along with all of the
- * inode references.
- */
- errcode_t (*delete)(ext2_irel irel, ext2_ino_t old);
-
- /*
- * Free the inode relocation table.
- */
- errcode_t (*free)(ext2_irel irel);
-};
-
-errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode,
- ext2_irel *irel);
-
-#define ext2fs_irel_put(irel, old, ent) ((irel)->put((irel), old, ent))
-#define ext2fs_irel_get(irel, old, ent) ((irel)->get((irel), old, ent))
-#define ext2fs_irel_get_by_orig(irel, orig, old, ent) \
- ((irel)->get_by_orig((irel), orig, old, ent))
-#define ext2fs_irel_start_iter(irel) ((irel)->start_iter((irel)))
-#define ext2fs_irel_next(irel, old, ent) ((irel)->next((irel), old, ent))
-#define ext2fs_irel_add_ref(irel, ino, ref) ((irel)->add_ref((irel), ino, ref))
-#define ext2fs_irel_start_iter_ref(irel, ino) ((irel)->start_iter_ref((irel), ino))
-#define ext2fs_irel_next_ref(irel, ref) ((irel)->next_ref((irel), ref))
-#define ext2fs_irel_move(irel, old, new) ((irel)->move((irel), old, new))
-#define ext2fs_irel_delete(irel, old) ((irel)->delete((irel), old))
-#define ext2fs_irel_free(irel) ((irel)->free((irel)))
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/irel_ma.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/irel_ma.c
deleted file mode 100644
index c871b18919..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/irel_ma.c
+++ /dev/null
@@ -1,367 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * irel_ma.c
- *
- * Copyright (C) 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-#include "irel.h"
-
-static errcode_t ima_put(ext2_irel irel, ext2_ino_t old,
- struct ext2_inode_relocate_entry *ent);
-static errcode_t ima_get(ext2_irel irel, ext2_ino_t old,
- struct ext2_inode_relocate_entry *ent);
-static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old,
- struct ext2_inode_relocate_entry *ent);
-static errcode_t ima_start_iter(ext2_irel irel);
-static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old,
- struct ext2_inode_relocate_entry *ent);
-static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino,
- struct ext2_inode_reference *ref);
-static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino);
-static errcode_t ima_next_ref(ext2_irel irel, struct ext2_inode_reference *ref);
-static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new);
-static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old);
-static errcode_t ima_free(ext2_irel irel);
-
-/*
- * This data structure stores the array of inode references; there is
- * a structure for each inode.
- */
-struct inode_reference_entry {
- __u16 num;
- struct ext2_inode_reference *refs;
-};
-
-struct irel_ma {
- __u32 magic;
- ext2_ino_t max_inode;
- ext2_ino_t ref_current;
- int ref_iter;
- ext2_ino_t *orig_map;
- struct ext2_inode_relocate_entry *entries;
- struct inode_reference_entry *ref_entries;
-};
-
-errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode,
- ext2_irel *new_irel)
-{
- ext2_irel irel = 0;
- errcode_t retval;
- struct irel_ma *ma = 0;
- size_t size;
-
- *new_irel = 0;
-
- /*
- * Allocate memory structures
- */
- retval = ext2fs_get_mem(sizeof(struct ext2_inode_relocation_table),
- &irel);
- if (retval)
- goto errout;
- memset(irel, 0, sizeof(struct ext2_inode_relocation_table));
-
- retval = ext2fs_get_mem(strlen(name)+1, &irel->name);
- if (retval)
- goto errout;
- strcpy(irel->name, name);
-
- retval = ext2fs_get_mem(sizeof(struct irel_ma), &ma);
- if (retval)
- goto errout;
- memset(ma, 0, sizeof(struct irel_ma));
- irel->priv_data = ma;
-
- size = (size_t) (sizeof(ext2_ino_t) * (max_inode+1));
- retval = ext2fs_get_mem(size, &ma->orig_map);
- if (retval)
- goto errout;
- memset(ma->orig_map, 0, size);
-
- size = (size_t) (sizeof(struct ext2_inode_relocate_entry) *
- (max_inode+1));
- retval = ext2fs_get_mem(size, &ma->entries);
- if (retval)
- goto errout;
- memset(ma->entries, 0, size);
-
- size = (size_t) (sizeof(struct inode_reference_entry) *
- (max_inode+1));
- retval = ext2fs_get_mem(size, &ma->ref_entries);
- if (retval)
- goto errout;
- memset(ma->ref_entries, 0, size);
- ma->max_inode = max_inode;
-
- /*
- * Fill in the irel data structure
- */
- irel->put = ima_put;
- irel->get = ima_get;
- irel->get_by_orig = ima_get_by_orig;
- irel->start_iter = ima_start_iter;
- irel->next = ima_next;
- irel->add_ref = ima_add_ref;
- irel->start_iter_ref = ima_start_iter_ref;
- irel->next_ref = ima_next_ref;
- irel->move = ima_move;
- irel->delete = ima_delete;
- irel->free = ima_free;
-
- *new_irel = irel;
- return 0;
-
-errout:
- ima_free(irel);
- return retval;
-}
-
-static errcode_t ima_put(ext2_irel irel, ext2_ino_t old,
- struct ext2_inode_relocate_entry *ent)
-{
- struct inode_reference_entry *ref_ent;
- struct irel_ma *ma;
- errcode_t retval;
- size_t size, old_size;
-
- ma = irel->priv_data;
- if (old > ma->max_inode)
- return EXT2_ET_INVALID_ARGUMENT;
-
- /*
- * Force the orig field to the correct value; the application
- * program shouldn't be messing with this field.
- */
- if (ma->entries[(unsigned) old].new == 0)
- ent->orig = old;
- else
- ent->orig = ma->entries[(unsigned) old].orig;
-
- /*
- * If max_refs has changed, reallocate the refs array
- */
- ref_ent = ma->ref_entries + (unsigned) old;
- if (ref_ent->refs && ent->max_refs !=
- ma->entries[(unsigned) old].max_refs) {
- size = (sizeof(struct ext2_inode_reference) * ent->max_refs);
- old_size = (sizeof(struct ext2_inode_reference) *
- ma->entries[(unsigned) old].max_refs);
- retval = ext2fs_resize_mem(old_size, size, &ref_ent->refs);
- if (retval)
- return retval;
- }
-
- ma->entries[(unsigned) old] = *ent;
- ma->orig_map[(unsigned) ent->orig] = old;
- return 0;
-}
-
-static errcode_t ima_get(ext2_irel irel, ext2_ino_t old,
- struct ext2_inode_relocate_entry *ent)
-{
- struct irel_ma *ma;
-
- ma = irel->priv_data;
- if (old > ma->max_inode)
- return EXT2_ET_INVALID_ARGUMENT;
- if (ma->entries[(unsigned) old].new == 0)
- return ENOENT;
- *ent = ma->entries[(unsigned) old];
- return 0;
-}
-
-static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old,
- struct ext2_inode_relocate_entry *ent)
-{
- struct irel_ma *ma;
- ext2_ino_t ino;
-
- ma = irel->priv_data;
- if (orig > ma->max_inode)
- return EXT2_ET_INVALID_ARGUMENT;
- ino = ma->orig_map[(unsigned) orig];
- if (ino == 0)
- return ENOENT;
- *old = ino;
- *ent = ma->entries[(unsigned) ino];
- return 0;
-}
-
-static errcode_t ima_start_iter(ext2_irel irel)
-{
- irel->current = 0;
- return 0;
-}
-
-static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old,
- struct ext2_inode_relocate_entry *ent)
-{
- struct irel_ma *ma;
-
- ma = irel->priv_data;
- while (++irel->current < ma->max_inode) {
- if (ma->entries[(unsigned) irel->current].new == 0)
- continue;
- *old = irel->current;
- *ent = ma->entries[(unsigned) irel->current];
- return 0;
- }
- *old = 0;
- return 0;
-}
-
-static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino,
- struct ext2_inode_reference *ref)
-{
- struct irel_ma *ma;
- size_t size;
- struct inode_reference_entry *ref_ent;
- struct ext2_inode_relocate_entry *ent;
- errcode_t retval;
-
- ma = irel->priv_data;
- if (ino > ma->max_inode)
- return EXT2_ET_INVALID_ARGUMENT;
-
- ref_ent = ma->ref_entries + (unsigned) ino;
- ent = ma->entries + (unsigned) ino;
-
- /*
- * If the inode reference array doesn't exist, create it.
- */
- if (ref_ent->refs == 0) {
- size = (size_t) ((sizeof(struct ext2_inode_reference) *
- ent->max_refs));
- retval = ext2fs_get_mem(size, &ref_ent->refs);
- if (retval)
- return retval;
- memset(ref_ent->refs, 0, size);
- ref_ent->num = 0;
- }
-
- if (ref_ent->num >= ent->max_refs)
- return EXT2_ET_TOO_MANY_REFS;
-
- ref_ent->refs[(unsigned) ref_ent->num++] = *ref;
- return 0;
-}
-
-static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino)
-{
- struct irel_ma *ma;
-
- ma = irel->priv_data;
- if (ino > ma->max_inode)
- return EXT2_ET_INVALID_ARGUMENT;
- if (ma->entries[(unsigned) ino].new == 0)
- return ENOENT;
- ma->ref_current = ino;
- ma->ref_iter = 0;
- return 0;
-}
-
-static errcode_t ima_next_ref(ext2_irel irel,
- struct ext2_inode_reference *ref)
-{
- struct irel_ma *ma;
- struct inode_reference_entry *ref_ent;
-
- ma = irel->priv_data;
-
- ref_ent = ma->ref_entries + ma->ref_current;
-
- if ((ref_ent->refs == NULL) ||
- (ma->ref_iter >= ref_ent->num)) {
- ref->block = 0;
- ref->offset = 0;
- return 0;
- }
- *ref = ref_ent->refs[ma->ref_iter++];
- return 0;
-}
-
-
-static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new)
-{
- struct irel_ma *ma;
-
- ma = irel->priv_data;
- if ((old > ma->max_inode) || (new > ma->max_inode))
- return EXT2_ET_INVALID_ARGUMENT;
- if (ma->entries[(unsigned) old].new == 0)
- return ENOENT;
-
- ma->entries[(unsigned) new] = ma->entries[(unsigned) old];
- ext2fs_free_mem(&ma->ref_entries[(unsigned) new].refs);
- ma->ref_entries[(unsigned) new] = ma->ref_entries[(unsigned) old];
-
- ma->entries[(unsigned) old].new = 0;
- ma->ref_entries[(unsigned) old].num = 0;
- ma->ref_entries[(unsigned) old].refs = 0;
-
- ma->orig_map[ma->entries[new].orig] = new;
- return 0;
-}
-
-static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old)
-{
- struct irel_ma *ma;
-
- ma = irel->priv_data;
- if (old > ma->max_inode)
- return EXT2_ET_INVALID_ARGUMENT;
- if (ma->entries[(unsigned) old].new == 0)
- return ENOENT;
-
- ma->entries[old].new = 0;
- ext2fs_free_mem(&ma->ref_entries[(unsigned) old].refs);
- ma->orig_map[ma->entries[(unsigned) old].orig] = 0;
-
- ma->ref_entries[(unsigned) old].num = 0;
- ma->ref_entries[(unsigned) old].refs = 0;
- return 0;
-}
-
-static errcode_t ima_free(ext2_irel irel)
-{
- struct irel_ma *ma;
- ext2_ino_t ino;
-
- if (!irel)
- return 0;
-
- ma = irel->priv_data;
-
- if (ma) {
- ext2fs_free_mem(&ma->orig_map);
- ext2fs_free_mem(&ma->entries);
- if (ma->ref_entries) {
- for (ino = 0; ino <= ma->max_inode; ino++) {
- ext2fs_free_mem(&ma->ref_entries[(unsigned) ino].refs);
- }
- ext2fs_free_mem(&ma->ref_entries);
- }
- ext2fs_free_mem(&ma);
- }
- ext2fs_free_mem(&irel->name);
- ext2fs_free_mem(&irel);
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ismounted.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ismounted.c
deleted file mode 100644
index 58dab79b1d..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ismounted.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * ismounted.c --- Check to see if the filesystem was mounted
- *
- * Copyright (C) 1995,1996,1997,1998,1999,2000 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <fcntl.h>
-#ifdef HAVE_LINUX_FD_H
-#include <linux/fd.h>
-#endif
-#ifdef HAVE_MNTENT_H
-#include <mntent.h>
-#endif
-#ifdef HAVE_GETMNTINFO
-#include <paths.h>
-#include <sys/param.h>
-#include <sys/mount.h>
-#endif /* HAVE_GETMNTINFO */
-#include <string.h>
-#include <sys/stat.h>
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-#ifdef HAVE_MNTENT_H
-/*
- * Helper function which checks a file in /etc/mtab format to see if a
- * filesystem is mounted. Returns an error if the file doesn't exist
- * or can't be opened.
- */
-static errcode_t check_mntent_file(const char *mtab_file, const char *file,
- int *mount_flags, char *mtpt, int mtlen)
-{
- struct mntent *mnt;
- struct stat st_buf;
- errcode_t retval = 0;
- dev_t file_dev=0, file_rdev=0;
- ino_t file_ino=0;
- FILE *f;
- int fd;
-
- *mount_flags = 0;
- if ((f = setmntent (mtab_file, "r")) == NULL)
- return errno;
- if (stat(file, &st_buf) == 0) {
- if (S_ISBLK(st_buf.st_mode)) {
-#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
- file_rdev = st_buf.st_rdev;
-#endif /* __GNU__ */
- } else {
- file_dev = st_buf.st_dev;
- file_ino = st_buf.st_ino;
- }
- }
- while ((mnt = getmntent (f)) != NULL) {
- if (strcmp(file, mnt->mnt_fsname) == 0)
- break;
- if (stat(mnt->mnt_fsname, &st_buf) == 0) {
- if (S_ISBLK(st_buf.st_mode)) {
-#ifndef __GNU__
- if (file_rdev && (file_rdev == st_buf.st_rdev))
- break;
-#endif /* __GNU__ */
- } else {
- if (file_dev && ((file_dev == st_buf.st_dev) &&
- (file_ino == st_buf.st_ino)))
- break;
- }
- }
- }
-
- if (mnt == 0) {
-#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
- /*
- * Do an extra check to see if this is the root device. We
- * can't trust /etc/mtab, and /proc/mounts will only list
- * /dev/root for the root filesystem. Argh. Instead we
- * check if the given device has the same major/minor number
- * as the device that the root directory is on.
- */
- if (file_rdev && stat("/", &st_buf) == 0) {
- if (st_buf.st_dev == file_rdev) {
- *mount_flags = EXT2_MF_MOUNTED;
- if (mtpt)
- strncpy(mtpt, "/", mtlen);
- goto is_root;
- }
- }
-#endif /* __GNU__ */
- goto errout;
- }
-#ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */
- /* Validate the entry in case /etc/mtab is out of date */
- /*
- * We need to be paranoid, because some broken distributions
- * (read: Slackware) don't initialize /etc/mtab before checking
- * all of the non-root filesystems on the disk.
- */
- if (stat(mnt->mnt_dir, &st_buf) < 0) {
- retval = errno;
- if (retval == ENOENT) {
-#ifdef DEBUG
- printf("Bogus entry in %s! (%s does not exist)\n",
- mtab_file, mnt->mnt_dir);
-#endif /* DEBUG */
- retval = 0;
- }
- goto errout;
- }
- if (file_rdev && (st_buf.st_dev != file_rdev)) {
-#ifdef DEBUG
- printf("Bogus entry in %s! (%s not mounted on %s)\n",
- mtab_file, file, mnt->mnt_dir);
-#endif /* DEBUG */
- goto errout;
- }
-#endif /* __GNU__ */
- *mount_flags = EXT2_MF_MOUNTED;
-
-#ifdef MNTOPT_RO
- /* Check to see if the ro option is set */
- if (hasmntopt(mnt, MNTOPT_RO))
- *mount_flags |= EXT2_MF_READONLY;
-#endif
-
- if (mtpt)
- strncpy(mtpt, mnt->mnt_dir, mtlen);
- /*
- * Check to see if we're referring to the root filesystem.
- * If so, do a manual check to see if we can open /etc/mtab
- * read/write, since if the root is mounted read/only, the
- * contents of /etc/mtab may not be accurate.
- */
- if (LONE_CHAR(mnt->mnt_dir, '/')) {
-is_root:
-#define TEST_FILE "/.ismount-test-file"
- *mount_flags |= EXT2_MF_ISROOT;
- fd = open(TEST_FILE, O_RDWR|O_CREAT);
- if (fd < 0) {
- if (errno == EROFS)
- *mount_flags |= EXT2_MF_READONLY;
- } else
- close(fd);
- (void) unlink(TEST_FILE);
- }
- retval = 0;
-errout:
- endmntent (f);
- return retval;
-}
-
-static errcode_t check_mntent(const char *file, int *mount_flags,
- char *mtpt, int mtlen)
-{
- errcode_t retval;
-
-#ifdef DEBUG
- retval = check_mntent_file("/tmp/mtab", file, mount_flags,
- mtpt, mtlen);
- if (retval == 0)
- return 0;
-#endif /* DEBUG */
-#ifdef __linux__
- retval = check_mntent_file("/proc/mounts", file, mount_flags,
- mtpt, mtlen);
- return retval;
-#endif /* __linux__ */
-#if defined(MOUNTED) || defined(_PATH_MOUNTED)
-#ifndef MOUNTED
-#define MOUNTED _PATH_MOUNTED
-#endif /* MOUNTED */
- retval = check_mntent_file(MOUNTED, file, mount_flags, mtpt, mtlen);
- return retval;
-#else
- *mount_flags = 0;
- return 0;
-#endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */
-}
-
-#else
-#if defined(HAVE_GETMNTINFO)
-
-static errcode_t check_getmntinfo(const char *file, int *mount_flags,
- char *mtpt, int mtlen)
-{
- struct statfs *mp;
- int len, n;
- const char *s1;
- char *s2;
-
- n = getmntinfo(&mp, MNT_NOWAIT);
- if (n == 0)
- return errno;
-
- len = sizeof(_PATH_DEV) - 1;
- s1 = file;
- if (strncmp(_PATH_DEV, s1, len) == 0)
- s1 += len;
-
- *mount_flags = 0;
- while (--n >= 0) {
- s2 = mp->f_mntfromname;
- if (strncmp(_PATH_DEV, s2, len) == 0) {
- s2 += len - 1;
- *s2 = 'r';
- }
- if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) {
- *mount_flags = EXT2_MF_MOUNTED;
- break;
- }
- ++mp;
- }
- if (mtpt)
- strncpy(mtpt, mp->f_mntonname, mtlen);
- return 0;
-}
-#endif /* HAVE_GETMNTINFO */
-#endif /* HAVE_MNTENT_H */
-
-/*
- * Check to see if we're dealing with the swap device.
- */
-static int is_swap_device(const char *file)
-{
- FILE *f;
- char buf[1024], *cp;
- dev_t file_dev;
- struct stat st_buf;
- int ret = 0;
-
- file_dev = 0;
-#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
- if ((stat(file, &st_buf) == 0) &&
- S_ISBLK(st_buf.st_mode))
- file_dev = st_buf.st_rdev;
-#endif /* __GNU__ */
-
- if (!(f = fopen_for_read("/proc/swaps")))
- return 0;
- /* Skip the first line */
- fgets(buf, sizeof(buf), f);
- while (!feof(f)) {
- if (!fgets(buf, sizeof(buf), f))
- break;
- if ((cp = strchr(buf, ' ')) != NULL)
- *cp = 0;
- if ((cp = strchr(buf, '\t')) != NULL)
- *cp = 0;
- if (strcmp(buf, file) == 0) {
- ret++;
- break;
- }
-#ifndef __GNU__
- if (file_dev && (stat(buf, &st_buf) == 0) &&
- S_ISBLK(st_buf.st_mode) &&
- file_dev == st_buf.st_rdev) {
- ret++;
- break;
- }
-#endif /* __GNU__ */
- }
- fclose(f);
- return ret;
-}
-
-
-/*
- * ext2fs_check_mount_point() returns 1 if the device is mounted, 0
- * otherwise. If mtpt is non-NULL, the directory where the device is
- * mounted is copied to where mtpt is pointing, up to mtlen
- * characters.
- */
-#ifdef __TURBOC__
-# pragma argsused
-#endif
-errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags,
- char *mtpt, int mtlen)
-{
- if (is_swap_device(device)) {
- *mount_flags = EXT2_MF_MOUNTED | EXT2_MF_SWAP;
- strncpy(mtpt, "<swap>", mtlen);
- return 0;
- }
-#ifdef HAVE_MNTENT_H
- return check_mntent(device, mount_flags, mtpt, mtlen);
-#else
-#ifdef HAVE_GETMNTINFO
- return check_getmntinfo(device, mount_flags, mtpt, mtlen);
-#else
-#ifdef __GNUC__
- #warning "Can't use getmntent or getmntinfo to check for mounted filesystems!"
-#endif
- *mount_flags = 0;
- return 0;
-#endif /* HAVE_GETMNTINFO */
-#endif /* HAVE_MNTENT_H */
-}
-
-/*
- * ext2fs_check_if_mounted() sets the mount_flags EXT2_MF_MOUNTED,
- * EXT2_MF_READONLY, and EXT2_MF_ROOT
- *
- */
-errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags)
-{
- return ext2fs_check_mount_point(file, mount_flags, NULL, 0);
-}
-
-#ifdef DEBUG
-int main(int argc, char **argv)
-{
- int retval, mount_flags;
- char mntpt[80];
-
- if (argc < 2) {
- fprintf(stderr, "Usage: %s device\n", argv[0]);
- exit(1);
- }
-
- mntpt[0] = 0;
- retval = ext2fs_check_mount_point(argv[1], &mount_flags,
- mntpt, sizeof(mntpt));
- if (retval) {
- com_err(argv[0], retval,
- "while calling ext2fs_check_if_mounted");
- exit(1);
- }
- printf("Device %s reports flags %02x\n", argv[1], mount_flags);
- if (mount_flags & EXT2_MF_BUSY)
- printf("\t%s is apparently in use.\n", argv[1]);
- if (mount_flags & EXT2_MF_MOUNTED)
- printf("\t%s is mounted.\n", argv[1]);
- if (mount_flags & EXT2_MF_SWAP)
- printf("\t%s is a swap device.\n", argv[1]);
- if (mount_flags & EXT2_MF_READONLY)
- printf("\t%s is read-only.\n", argv[1]);
- if (mount_flags & EXT2_MF_ISROOT)
- printf("\t%s is the root filesystem.\n", argv[1]);
- if (mntpt[0])
- printf("\t%s is mounted on %s.\n", argv[1], mntpt);
- exit(0);
-}
-#endif /* DEBUG */
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/jfs_dat.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/jfs_dat.h
deleted file mode 100644
index 17c586a29b..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/jfs_dat.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * jfs_dat.h --- stripped down header file which only contains the JFS
- * on-disk data structures
- */
-
-#define JFS_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */
-
-/*
- * On-disk structures
- */
-
-/*
- * Descriptor block types:
- */
-
-#define JFS_DESCRIPTOR_BLOCK 1
-#define JFS_COMMIT_BLOCK 2
-#define JFS_SUPERBLOCK 3
-
-/*
- * Standard header for all descriptor blocks:
- */
-typedef struct journal_header_s
-{
- __u32 h_magic;
- __u32 h_blocktype;
- __u32 h_sequence;
-} journal_header_t;
-
-
-/*
- * The block tag: used to describe a single buffer in the journal
- */
-typedef struct journal_block_tag_s
-{
- __u32 t_blocknr; /* The on-disk block number */
- __u32 t_flags; /* See below */
-} journal_block_tag_t;
-
-/* Definitions for the journal tag flags word: */
-#define JFS_FLAG_ESCAPE 1 /* on-disk block is escaped */
-#define JFS_FLAG_SAME_UUID 2 /* block has same uuid as previous */
-#define JFS_FLAG_DELETED 4 /* block deleted by this transaction */
-#define JFS_FLAG_LAST_TAG 8 /* last tag in this descriptor block */
-
-
-/*
- * The journal superblock
- */
-typedef struct journal_superblock_s
-{
- journal_header_t s_header;
-
- /* Static information describing the journal */
- __u32 s_blocksize; /* journal device blocksize */
- __u32 s_maxlen; /* total blocks in journal file */
- __u32 s_first; /* first block of log information */
-
- /* Dynamic information describing the current state of the log */
- __u32 s_sequence; /* first commit ID expected in log */
- __u32 s_start; /* blocknr of start of log */
-} journal_superblock_t;
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/kernel-jbd.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/kernel-jbd.h
deleted file mode 100644
index 853d97ac7f..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/kernel-jbd.h
+++ /dev/null
@@ -1,235 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * linux/include/linux/jbd.h
- *
- * Written by Stephen C. Tweedie <sct@redhat.com>
- *
- * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved
- *
- * This file is part of the Linux kernel and is made available under
- * the terms of the GNU General Public License, version 2, or at your
- * option, any later version, incorporated herein by reference.
- *
- * Definitions for transaction data structures for the buffer cache
- * filesystem journaling support.
- */
-#ifndef LINUX_JBD_H
-#define LINUX_JBD_H 1
-
-#include <sys/types.h>
-#include <linux/types.h>
-#include "ext2fs.h"
-
-/*
- * Standard header for all descriptor blocks:
- */
-
-typedef struct journal_header_s
-{
- __u32 h_magic;
- __u32 h_blocktype;
- __u32 h_sequence;
-} journal_header_t;
-
-/*
- * This is the global e2fsck structure.
- */
-typedef struct e2fsck_struct *e2fsck_t;
-
-
-struct inode {
- e2fsck_t i_ctx;
- ext2_ino_t i_ino;
- struct ext2_inode i_ext2;
-};
-
-
-/*
- * The journal superblock. All fields are in big-endian byte order.
- */
-typedef struct journal_superblock_s
-{
-/* 0x0000 */
- journal_header_t s_header;
-
-/* 0x000C */
- /* Static information describing the journal */
- __u32 s_blocksize; /* journal device blocksize */
- __u32 s_maxlen; /* total blocks in journal file */
- __u32 s_first; /* first block of log information */
-
-/* 0x0018 */
- /* Dynamic information describing the current state of the log */
- __u32 s_sequence; /* first commit ID expected in log */
- __u32 s_start; /* blocknr of start of log */
-
-/* 0x0020 */
- /* Error value, as set by journal_abort(). */
- __s32 s_errno;
-
-/* 0x0024 */
- /* Remaining fields are only valid in a version-2 superblock */
- __u32 s_feature_compat; /* compatible feature set */
- __u32 s_feature_incompat; /* incompatible feature set */
- __u32 s_feature_ro_compat; /* readonly-compatible feature set */
-/* 0x0030 */
- __u8 s_uuid[16]; /* 128-bit uuid for journal */
-
-/* 0x0040 */
- __u32 s_nr_users; /* Nr of filesystems sharing log */
-
- __u32 s_dynsuper; /* Blocknr of dynamic superblock copy*/
-
-/* 0x0048 */
- __u32 s_max_transaction; /* Limit of journal blocks per trans.*/
- __u32 s_max_trans_data; /* Limit of data blocks per trans. */
-
-/* 0x0050 */
- __u32 s_padding[44];
-
-/* 0x0100 */
- __u8 s_users[16*48]; /* ids of all fs'es sharing the log */
-/* 0x0400 */
-} journal_superblock_t;
-
-
-extern int journal_blocks_per_page(struct inode *inode);
-extern int jbd_blocks_per_page(struct inode *inode);
-
-#define JFS_MIN_JOURNAL_BLOCKS 1024
-
-
-/*
- * Internal structures used by the logging mechanism:
- */
-
-#define JFS_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */
-
-/*
- * Descriptor block types:
- */
-
-#define JFS_DESCRIPTOR_BLOCK 1
-#define JFS_COMMIT_BLOCK 2
-#define JFS_SUPERBLOCK_V1 3
-#define JFS_SUPERBLOCK_V2 4
-#define JFS_REVOKE_BLOCK 5
-
-/*
- * The block tag: used to describe a single buffer in the journal
- */
-typedef struct journal_block_tag_s
-{
- __u32 t_blocknr; /* The on-disk block number */
- __u32 t_flags; /* See below */
-} journal_block_tag_t;
-
-/*
- * The revoke descriptor: used on disk to describe a series of blocks to
- * be revoked from the log
- */
-typedef struct journal_revoke_header_s
-{
- journal_header_t r_header;
- int r_count; /* Count of bytes used in the block */
-} journal_revoke_header_t;
-
-
-/* Definitions for the journal tag flags word: */
-#define JFS_FLAG_ESCAPE 1 /* on-disk block is escaped */
-#define JFS_FLAG_SAME_UUID 2 /* block has same uuid as previous */
-#define JFS_FLAG_DELETED 4 /* block deleted by this transaction */
-#define JFS_FLAG_LAST_TAG 8 /* last tag in this descriptor block */
-
-
-
-
-#define JFS_HAS_COMPAT_FEATURE(j,mask) \
- ((j)->j_format_version >= 2 && \
- ((j)->j_superblock->s_feature_compat & cpu_to_be32((mask))))
-#define JFS_HAS_RO_COMPAT_FEATURE(j,mask) \
- ((j)->j_format_version >= 2 && \
- ((j)->j_superblock->s_feature_ro_compat & cpu_to_be32((mask))))
-#define JFS_HAS_INCOMPAT_FEATURE(j,mask) \
- ((j)->j_format_version >= 2 && \
- ((j)->j_superblock->s_feature_incompat & cpu_to_be32((mask))))
-
-#define JFS_FEATURE_INCOMPAT_REVOKE 0x00000001
-
-/* Features known to this kernel version: */
-#define JFS_KNOWN_COMPAT_FEATURES 0
-#define JFS_KNOWN_ROCOMPAT_FEATURES 0
-#define JFS_KNOWN_INCOMPAT_FEATURES JFS_FEATURE_INCOMPAT_REVOKE
-
-/* Comparison functions for transaction IDs: perform comparisons using
- * modulo arithmetic so that they work over sequence number wraps. */
-
-
-/*
- * Definitions which augment the buffer_head layer
- */
-
-/* journaling buffer types */
-#define BJ_None 0 /* Not journaled */
-#define BJ_SyncData 1 /* Normal data: flush before commit */
-#define BJ_AsyncData 2 /* writepage data: wait on it before commit */
-#define BJ_Metadata 3 /* Normal journaled metadata */
-#define BJ_Forget 4 /* Buffer superceded by this transaction */
-#define BJ_IO 5 /* Buffer is for temporary IO use */
-#define BJ_Shadow 6 /* Buffer contents being shadowed to the log */
-#define BJ_LogCtl 7 /* Buffer contains log descriptors */
-#define BJ_Reserved 8 /* Buffer is reserved for access by journal */
-#define BJ_Types 9
-
-
-struct kdev_s {
- e2fsck_t k_ctx;
- int k_dev;
-};
-
-typedef struct kdev_s *kdev_t;
-typedef unsigned int tid_t;
-
-struct journal_s
-{
- unsigned long j_flags;
- int j_errno;
- struct buffer_head * j_sb_buffer;
- struct journal_superblock_s *j_superblock;
- int j_format_version;
- unsigned long j_head;
- unsigned long j_tail;
- unsigned long j_free;
- unsigned long j_first, j_last;
- kdev_t j_dev;
- kdev_t j_fs_dev;
- int j_blocksize;
- unsigned int j_blk_offset;
- unsigned int j_maxlen;
- struct inode * j_inode;
- tid_t j_tail_sequence;
- tid_t j_transaction_sequence;
- __u8 j_uuid[16];
- struct jbd_revoke_table_s *j_revoke;
-};
-
-typedef struct journal_s journal_t;
-
-extern int journal_recover (journal_t *journal);
-extern int journal_skip_recovery (journal_t *);
-
-/* Primary revoke support */
-extern int journal_init_revoke(journal_t *, int);
-extern void journal_destroy_revoke_caches(void);
-extern int journal_init_revoke_caches(void);
-
-/* Recovery revoke support */
-extern int journal_set_revoke(journal_t *, unsigned long, tid_t);
-extern int journal_test_revoke(journal_t *, unsigned long, tid_t);
-extern void journal_clear_revoke(journal_t *);
-extern void journal_brelse_array(struct buffer_head *b[], int n);
-
-extern void journal_destroy_revoke(journal_t *);
-
-
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/kernel-list.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/kernel-list.h
deleted file mode 100644
index d80716a454..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/kernel-list.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/* vi: set sw=4 ts=4: */
-#ifndef LINUX_LIST_H
-#define LINUX_LIST_H 1
-
-/*
- * Simple doubly linked list implementation.
- *
- * Some of the internal functions ("__xxx") are useful when
- * manipulating whole lists rather than single entries, as
- * sometimes we already know the next/prev entries and we can
- * generate better code by using them directly rather than
- * using the generic single-entry routines.
- */
-
-struct list_head {
- struct list_head *next, *prev;
-};
-
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define LIST_HEAD(name) \
- struct list_head name = { &name, &name }
-
-#define INIT_LIST_HEAD(ptr) do { \
- (ptr)->next = (ptr); (ptr)->prev = (ptr); \
-} while (0)
-
-#if (!defined(__GNUC__) && !defined(__WATCOMC__))
-#define __inline__
-#endif
-
-/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static __inline__ void __list_add(struct list_head * new,
- struct list_head * prev,
- struct list_head * next)
-{
- next->prev = new;
- new->next = next;
- new->prev = prev;
- prev->next = new;
-}
-
-/*
- * Insert a new entry after the specified head..
- */
-static __inline__ void list_add(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head, head->next);
-}
-
-/*
- * Insert a new entry at the tail
- */
-static __inline__ void list_add_tail(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head->prev, head);
-}
-
-/*
- * Delete a list entry by making the prev/next entries
- * point to each other.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static __inline__ void __list_del(struct list_head * prev,
- struct list_head * next)
-{
- next->prev = prev;
- prev->next = next;
-}
-
-static __inline__ void list_del(struct list_head *entry)
-{
- __list_del(entry->prev, entry->next);
-}
-
-static __inline__ int list_empty(struct list_head *head)
-{
- return head->next == head;
-}
-
-/*
- * Splice in "list" into "head"
- */
-static __inline__ void list_splice(struct list_head *list, struct list_head *head)
-{
- struct list_head *first = list->next;
-
- if (first != list) {
- struct list_head *last = list->prev;
- struct list_head *at = head->next;
-
- first->prev = head;
- head->next = first;
-
- last->next = at;
- at->prev = last;
- }
-}
-
-#define list_entry(ptr, type, member) \
- ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
-
-#define list_for_each(pos, head) \
- for (pos = (head)->next; pos != (head); pos = pos->next)
-
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/link.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/link.c
deleted file mode 100644
index 08b2e96738..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/link.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * link.c --- create links in a ext2fs directory
- *
- * Copyright (C) 1993, 1994 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-struct link_struct {
- const char *name;
- int namelen;
- ext2_ino_t inode;
- int flags;
- int done;
- struct ext2_super_block *sb;
-};
-
-static int link_proc(struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *priv_data)
-{
- struct link_struct *ls = (struct link_struct *) priv_data;
- struct ext2_dir_entry *next;
- int rec_len, min_rec_len;
- int ret = 0;
-
- rec_len = EXT2_DIR_REC_LEN(ls->namelen);
-
- /*
- * See if the following directory entry (if any) is unused;
- * if so, absorb it into this one.
- */
- next = (struct ext2_dir_entry *) (buf + offset + dirent->rec_len);
- if ((offset + dirent->rec_len < blocksize - 8) &&
- (next->inode == 0) &&
- (offset + dirent->rec_len + next->rec_len <= blocksize)) {
- dirent->rec_len += next->rec_len;
- ret = DIRENT_CHANGED;
- }
-
- /*
- * If the directory entry is used, see if we can split the
- * directory entry to make room for the new name. If so,
- * truncate it and return.
- */
- if (dirent->inode) {
- min_rec_len = EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
- if (dirent->rec_len < (min_rec_len + rec_len))
- return ret;
- rec_len = dirent->rec_len - min_rec_len;
- dirent->rec_len = min_rec_len;
- next = (struct ext2_dir_entry *) (buf + offset +
- dirent->rec_len);
- next->inode = 0;
- next->name_len = 0;
- next->rec_len = rec_len;
- return DIRENT_CHANGED;
- }
-
- /*
- * If we get this far, then the directory entry is not used.
- * See if we can fit the request entry in. If so, do it.
- */
- if (dirent->rec_len < rec_len)
- return ret;
- dirent->inode = ls->inode;
- dirent->name_len = ls->namelen;
- strncpy(dirent->name, ls->name, ls->namelen);
- if (ls->sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
- dirent->name_len |= (ls->flags & 0x7) << 8;
-
- ls->done++;
- return DIRENT_ABORT|DIRENT_CHANGED;
-}
-
-/*
- * Note: the low 3 bits of the flags field are used as the directory
- * entry filetype.
- */
-#ifdef __TURBOC__
-# pragma argsused
-#endif
-errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name,
- ext2_ino_t ino, int flags)
-{
- errcode_t retval;
- struct link_struct ls;
- struct ext2_inode inode;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!(fs->flags & EXT2_FLAG_RW))
- return EXT2_ET_RO_FILSYS;
-
- ls.name = name;
- ls.namelen = name ? strlen(name) : 0;
- ls.inode = ino;
- ls.flags = flags;
- ls.done = 0;
- ls.sb = fs->super;
-
- retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY,
- 0, link_proc, &ls);
- if (retval)
- return retval;
-
- if (!ls.done)
- return EXT2_ET_DIR_NO_SPACE;
-
- if ((retval = ext2fs_read_inode(fs, dir, &inode)) != 0)
- return retval;
-
- if (inode.i_flags & EXT2_INDEX_FL) {
- inode.i_flags &= ~EXT2_INDEX_FL;
- if ((retval = ext2fs_write_inode(fs, dir, &inode)) != 0)
- return retval;
- }
-
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/lookup.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/lookup.c
deleted file mode 100644
index b2e8de8ec5..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/lookup.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * lookup.c --- ext2fs directory lookup operations
- *
- * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-struct lookup_struct {
- const char *name;
- int len;
- ext2_ino_t *inode;
- int found;
-};
-
-#ifdef __TURBOC__
-# pragma argsused
-#endif
-static int lookup_proc(struct ext2_dir_entry *dirent,
- int offset EXT2FS_ATTR((unused)),
- int blocksize EXT2FS_ATTR((unused)),
- char *buf EXT2FS_ATTR((unused)),
- void *priv_data)
-{
- struct lookup_struct *ls = (struct lookup_struct *) priv_data;
-
- if (ls->len != (dirent->name_len & 0xFF))
- return 0;
- if (strncmp(ls->name, dirent->name, (dirent->name_len & 0xFF)))
- return 0;
- *ls->inode = dirent->inode;
- ls->found++;
- return DIRENT_ABORT;
-}
-
-
-errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name,
- int namelen, char *buf, ext2_ino_t *inode)
-{
- errcode_t retval;
- struct lookup_struct ls;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- ls.name = name;
- ls.len = namelen;
- ls.inode = inode;
- ls.found = 0;
-
- retval = ext2fs_dir_iterate(fs, dir, 0, buf, lookup_proc, &ls);
- if (retval)
- return retval;
-
- return (ls.found) ? 0 : EXT2_ET_FILE_NOT_FOUND;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/mkdir.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/mkdir.c
deleted file mode 100644
index a86ac8e938..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/mkdir.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * mkdir.c --- make a directory in the filesystem
- *
- * Copyright (C) 1994, 1995 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-#ifndef EXT2_FT_DIR
-#define EXT2_FT_DIR 2
-#endif
-
-errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
- const char *name)
-{
- errcode_t retval;
- struct ext2_inode parent_inode, inode;
- ext2_ino_t ino = inum;
- ext2_ino_t scratch_ino;
- blk_t blk;
- char *block = NULL;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- /*
- * Allocate an inode, if necessary
- */
- if (!ino) {
- retval = ext2fs_new_inode(fs, parent, LINUX_S_IFDIR | 0755,
- 0, &ino);
- if (retval)
- goto cleanup;
- }
-
- /*
- * Allocate a data block for the directory
- */
- retval = ext2fs_new_block(fs, 0, 0, &blk);
- if (retval)
- goto cleanup;
-
- /*
- * Create a scratch template for the directory
- */
- retval = ext2fs_new_dir_block(fs, ino, parent, &block);
- if (retval)
- goto cleanup;
-
- /*
- * Get the parent's inode, if necessary
- */
- if (parent != ino) {
- retval = ext2fs_read_inode(fs, parent, &parent_inode);
- if (retval)
- goto cleanup;
- } else
- memset(&parent_inode, 0, sizeof(parent_inode));
-
- /*
- * Create the inode structure....
- */
- memset(&inode, 0, sizeof(struct ext2_inode));
- inode.i_mode = LINUX_S_IFDIR | (0777 & ~fs->umask);
- inode.i_uid = inode.i_gid = 0;
- inode.i_blocks = fs->blocksize / 512;
- inode.i_block[0] = blk;
- inode.i_links_count = 2;
- inode.i_ctime = inode.i_atime = inode.i_mtime = time(NULL);
- inode.i_size = fs->blocksize;
-
- /*
- * Write out the inode and inode data block
- */
- retval = ext2fs_write_dir_block(fs, blk, block);
- if (retval)
- goto cleanup;
- retval = ext2fs_write_new_inode(fs, ino, &inode);
- if (retval)
- goto cleanup;
-
- /*
- * Link the directory into the filesystem hierarchy
- */
- if (name) {
- retval = ext2fs_lookup(fs, parent, name, strlen(name), 0,
- &scratch_ino);
- if (!retval) {
- retval = EXT2_ET_DIR_EXISTS;
- name = 0;
- goto cleanup;
- }
- if (retval != EXT2_ET_FILE_NOT_FOUND)
- goto cleanup;
- retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_DIR);
- if (retval)
- goto cleanup;
- }
-
- /*
- * Update parent inode's counts
- */
- if (parent != ino) {
- parent_inode.i_links_count++;
- retval = ext2fs_write_inode(fs, parent, &parent_inode);
- if (retval)
- goto cleanup;
- }
-
- /*
- * Update accounting....
- */
- ext2fs_block_alloc_stats(fs, blk, +1);
- ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
-
-cleanup:
- ext2fs_free_mem(&block);
- return retval;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/mkjournal.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/mkjournal.c
deleted file mode 100644
index 748d9abc70..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/mkjournal.c
+++ /dev/null
@@ -1,426 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * mkjournal.c --- make a journal for a filesystem
- *
- * Copyright (C) 2000 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#if HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#if HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-
-#include "ext2_fs.h"
-#include "../e2p/e2p.h"
-#include "../e2fsck.h"
-#include "ext2fs.h"
-#include "kernel-jbd.h"
-
-/*
- * This function automatically sets up the journal superblock and
- * returns it as an allocated block.
- */
-errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
- __u32 size, int flags,
- char **ret_jsb)
-{
- errcode_t retval;
- journal_superblock_t *jsb;
-
- if (size < 1024)
- return EXT2_ET_JOURNAL_TOO_SMALL;
-
- if ((retval = ext2fs_get_mem(fs->blocksize, &jsb)))
- return retval;
-
- memset (jsb, 0, fs->blocksize);
-
- jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
- if (flags & EXT2_MKJOURNAL_V1_SUPER)
- jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V1);
- else
- jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
- jsb->s_blocksize = htonl(fs->blocksize);
- jsb->s_maxlen = htonl(size);
- jsb->s_nr_users = htonl(1);
- jsb->s_first = htonl(1);
- jsb->s_sequence = htonl(1);
- memcpy(jsb->s_uuid, fs->super->s_uuid, sizeof(fs->super->s_uuid));
- /*
- * If we're creating an external journal device, we need to
- * adjust these fields.
- */
- if (fs->super->s_feature_incompat &
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
- jsb->s_nr_users = 0;
- if (fs->blocksize == 1024)
- jsb->s_first = htonl(3);
- else
- jsb->s_first = htonl(2);
- }
-
- *ret_jsb = (char *) jsb;
- return 0;
-}
-
-/*
- * This function writes a journal using POSIX routines. It is used
- * for creating external journals and creating journals on live
- * filesystems.
- */
-static errcode_t write_journal_file(ext2_filsys fs, char *filename,
- blk_t size, int flags)
-{
- errcode_t retval;
- char *buf = NULL;
- int fd, ret_size;
- blk_t i;
-
- if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf)))
- return retval;
-
- /* Open the device or journal file */
- if ((fd = open(filename, O_WRONLY)) < 0) {
- retval = errno;
- goto errout;
- }
-
- /* Write the superblock out */
- retval = EXT2_ET_SHORT_WRITE;
- ret_size = write(fd, buf, fs->blocksize);
- if (ret_size < 0) {
- retval = errno;
- goto errout;
- }
- if (ret_size != (int) fs->blocksize)
- goto errout;
- memset(buf, 0, fs->blocksize);
-
- for (i = 1; i < size; i++) {
- ret_size = write(fd, buf, fs->blocksize);
- if (ret_size < 0) {
- retval = errno;
- goto errout;
- }
- if (ret_size != (int) fs->blocksize)
- goto errout;
- }
- close(fd);
-
- retval = 0;
-errout:
- ext2fs_free_mem(&buf);
- return retval;
-}
-
-/*
- * Helper function for creating the journal using direct I/O routines
- */
-struct mkjournal_struct {
- int num_blocks;
- int newblocks;
- char *buf;
- errcode_t err;
-};
-
-static int mkjournal_proc(ext2_filsys fs,
- blk_t *blocknr,
- e2_blkcnt_t blockcnt,
- blk_t ref_block EXT2FS_ATTR((unused)),
- int ref_offset EXT2FS_ATTR((unused)),
- void *priv_data)
-{
- struct mkjournal_struct *es = (struct mkjournal_struct *) priv_data;
- blk_t new_blk;
- static blk_t last_blk = 0;
- errcode_t retval;
-
- if (*blocknr) {
- last_blk = *blocknr;
- return 0;
- }
- retval = ext2fs_new_block(fs, last_blk, 0, &new_blk);
- if (retval) {
- es->err = retval;
- return BLOCK_ABORT;
- }
- if (blockcnt > 0)
- es->num_blocks--;
-
- es->newblocks++;
- retval = io_channel_write_blk(fs->io, new_blk, 1, es->buf);
-
- if (blockcnt == 0)
- memset(es->buf, 0, fs->blocksize);
-
- if (retval) {
- es->err = retval;
- return BLOCK_ABORT;
- }
- *blocknr = new_blk;
- last_blk = new_blk;
- ext2fs_block_alloc_stats(fs, new_blk, +1);
-
- if (es->num_blocks == 0)
- return (BLOCK_CHANGED | BLOCK_ABORT);
- else
- return BLOCK_CHANGED;
-}
-
-/*
- * This function creates a journal using direct I/O routines.
- */
-static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
- blk_t size, int flags)
-{
- char *buf;
- errcode_t retval;
- struct ext2_inode inode;
- struct mkjournal_struct es;
-
- if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf)))
- return retval;
-
- if ((retval = ext2fs_read_bitmaps(fs)))
- return retval;
-
- if ((retval = ext2fs_read_inode(fs, journal_ino, &inode)))
- return retval;
-
- if (inode.i_blocks > 0)
- return EEXIST;
-
- es.num_blocks = size;
- es.newblocks = 0;
- es.buf = buf;
- es.err = 0;
-
- retval = ext2fs_block_iterate2(fs, journal_ino, BLOCK_FLAG_APPEND,
- 0, mkjournal_proc, &es);
- if (es.err) {
- retval = es.err;
- goto errout;
- }
-
- if ((retval = ext2fs_read_inode(fs, journal_ino, &inode)))
- goto errout;
-
- inode.i_size += fs->blocksize * size;
- inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
- inode.i_mtime = inode.i_ctime = time(NULL);
- inode.i_links_count = 1;
- inode.i_mode = LINUX_S_IFREG | 0600;
-
- if ((retval = ext2fs_write_inode(fs, journal_ino, &inode)))
- goto errout;
- retval = 0;
-
- memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4);
- fs->super->s_jnl_blocks[16] = inode.i_size;
- fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
- ext2fs_mark_super_dirty(fs);
-
-errout:
- ext2fs_free_mem(&buf);
- return retval;
-}
-
-/*
- * This function adds a journal device to a filesystem
- */
-errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev)
-{
- struct stat st;
- errcode_t retval;
- char buf[1024];
- journal_superblock_t *jsb;
- int start;
- __u32 i, nr_users;
-
- /* Make sure the device exists and is a block device */
- if (stat(journal_dev->device_name, &st) < 0)
- return errno;
-
- if (!S_ISBLK(st.st_mode))
- return EXT2_ET_JOURNAL_NOT_BLOCK; /* Must be a block device */
-
- /* Get the journal superblock */
- start = 1;
- if (journal_dev->blocksize == 1024)
- start++;
- if ((retval = io_channel_read_blk(journal_dev->io, start, -1024, buf)))
- return retval;
-
- jsb = (journal_superblock_t *) buf;
- if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) ||
- (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2)))
- return EXT2_ET_NO_JOURNAL_SB;
-
- if (ntohl(jsb->s_blocksize) != (unsigned long) fs->blocksize)
- return EXT2_ET_UNEXPECTED_BLOCK_SIZE;
-
- /* Check and see if this filesystem has already been added */
- nr_users = ntohl(jsb->s_nr_users);
- for (i=0; i < nr_users; i++) {
- if (memcmp(fs->super->s_uuid,
- &jsb->s_users[i*16], 16) == 0)
- break;
- }
- if (i >= nr_users) {
- memcpy(&jsb->s_users[nr_users*16],
- fs->super->s_uuid, 16);
- jsb->s_nr_users = htonl(nr_users+1);
- }
-
- /* Writeback the journal superblock */
- if ((retval = io_channel_write_blk(journal_dev->io, start, -1024, buf)))
- return retval;
-
- fs->super->s_journal_inum = 0;
- fs->super->s_journal_dev = st.st_rdev;
- memcpy(fs->super->s_journal_uuid, jsb->s_uuid,
- sizeof(fs->super->s_journal_uuid));
- fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
- ext2fs_mark_super_dirty(fs);
- return 0;
-}
-
-/*
- * This function adds a journal inode to a filesystem, using either
- * POSIX routines if the filesystem is mounted, or using direct I/O
- * functions if it is not.
- */
-errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size, int flags)
-{
- errcode_t retval;
- ext2_ino_t journal_ino;
- struct stat st;
- char jfile[1024];
- int fd, mount_flags, f;
-
- retval = ext2fs_check_mount_point(fs->device_name, &mount_flags,
- jfile, sizeof(jfile)-10);
- if (retval)
- return retval;
-
- if (mount_flags & EXT2_MF_MOUNTED) {
- strcat(jfile, "/.journal");
-
- /*
- * If .../.journal already exists, make sure any
- * immutable or append-only flags are cleared.
- */
-#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP)
- (void) chflags (jfile, 0);
-#else
-#if HAVE_EXT2_IOCTLS
- fd = open(jfile, O_RDONLY);
- if (fd >= 0) {
- f = 0;
- ioctl(fd, EXT2_IOC_SETFLAGS, &f);
- close(fd);
- }
-#endif
-#endif
-
- /* Create the journal file */
- if ((fd = open(jfile, O_CREAT|O_WRONLY, 0600)) < 0)
- return errno;
-
- if ((retval = write_journal_file(fs, jfile, size, flags)))
- goto errout;
-
- /* Get inode number of the journal file */
- if (fstat(fd, &st) < 0)
- goto errout;
-
-#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP)
- retval = fchflags (fd, UF_NODUMP|UF_IMMUTABLE);
-#else
-#if HAVE_EXT2_IOCTLS
- f = EXT2_NODUMP_FL | EXT2_IMMUTABLE_FL;
- retval = ioctl(fd, EXT2_IOC_SETFLAGS, &f);
-#endif
-#endif
- if (retval)
- goto errout;
-
- close(fd);
- journal_ino = st.st_ino;
- } else {
- journal_ino = EXT2_JOURNAL_INO;
- if ((retval = write_journal_inode(fs, journal_ino,
- size, flags)))
- return retval;
- }
-
- fs->super->s_journal_inum = journal_ino;
- fs->super->s_journal_dev = 0;
- memset(fs->super->s_journal_uuid, 0,
- sizeof(fs->super->s_journal_uuid));
- fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
-
- ext2fs_mark_super_dirty(fs);
- return 0;
-errout:
- close(fd);
- return retval;
-}
-
-#ifdef DEBUG
-main(int argc, char **argv)
-{
- errcode_t retval;
- char *device_name;
- ext2_filsys fs;
-
- if (argc < 2) {
- fprintf(stderr, "Usage: %s filesystem\n", argv[0]);
- exit(1);
- }
- device_name = argv[1];
-
- retval = ext2fs_open (device_name, EXT2_FLAG_RW, 0, 0,
- unix_io_manager, &fs);
- if (retval) {
- com_err(argv[0], retval, "while opening %s", device_name);
- exit(1);
- }
-
- retval = ext2fs_add_journal_inode(fs, 1024);
- if (retval) {
- com_err(argv[0], retval, "while adding journal to %s",
- device_name);
- exit(1);
- }
- retval = ext2fs_flush(fs);
- if (retval) {
- printf("Warning, had trouble writing out superblocks.\n");
- }
- ext2fs_close(fs);
- exit(0);
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/namei.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/namei.c
deleted file mode 100644
index 18244613c6..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/namei.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * namei.c --- ext2fs directory lookup operations
- *
- * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-/* #define NAMEI_DEBUG */
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base,
- const char *pathname, size_t pathlen, int follow,
- int link_count, char *buf, ext2_ino_t *res_inode);
-
-static errcode_t follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir,
- ext2_ino_t inode, int link_count,
- char *buf, ext2_ino_t *res_inode)
-{
- char *pathname;
- char *buffer = NULL;
- errcode_t retval;
- struct ext2_inode ei;
-
-#ifdef NAMEI_DEBUG
- printf("follow_link: root=%lu, dir=%lu, inode=%lu, lc=%d\n",
- root, dir, inode, link_count);
-
-#endif
- retval = ext2fs_read_inode (fs, inode, &ei);
- if (retval) return retval;
- if (!LINUX_S_ISLNK (ei.i_mode)) {
- *res_inode = inode;
- return 0;
- }
- if (link_count++ > 5) {
- return EXT2_ET_SYMLINK_LOOP;
- }
- if (ext2fs_inode_data_blocks(fs, &ei)) {
- retval = ext2fs_get_mem(fs->blocksize, &buffer);
- if (retval)
- return retval;
- retval = io_channel_read_blk(fs->io, ei.i_block[0], 1, buffer);
- if (retval) {
- ext2fs_free_mem(&buffer);
- return retval;
- }
- pathname = buffer;
- } else
- pathname = (char *)&(ei.i_block[0]);
- retval = open_namei(fs, root, dir, pathname, ei.i_size, 1,
- link_count, buf, res_inode);
- ext2fs_free_mem(&buffer);
- return retval;
-}
-
-/*
- * This routine interprets a pathname in the context of the current
- * directory and the root directory, and returns the inode of the
- * containing directory, and a pointer to the filename of the file
- * (pointing into the pathname) and the length of the filename.
- */
-static errcode_t dir_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir,
- const char *pathname, int pathlen,
- int link_count, char *buf,
- const char **name, int *namelen,
- ext2_ino_t *res_inode)
-{
- char c;
- const char *thisname;
- int len;
- ext2_ino_t inode;
- errcode_t retval;
-
- if ((c = *pathname) == '/') {
- dir = root;
- pathname++;
- pathlen--;
- }
- while (1) {
- thisname = pathname;
- for (len=0; --pathlen >= 0;len++) {
- c = *(pathname++);
- if (c == '/')
- break;
- }
- if (pathlen < 0)
- break;
- retval = ext2fs_lookup (fs, dir, thisname, len, buf, &inode);
- if (retval) return retval;
- retval = follow_link (fs, root, dir, inode,
- link_count, buf, &dir);
- if (retval) return retval;
- }
- *name = thisname;
- *namelen = len;
- *res_inode = dir;
- return 0;
-}
-
-static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base,
- const char *pathname, size_t pathlen, int follow,
- int link_count, char *buf, ext2_ino_t *res_inode)
-{
- const char *basename;
- int namelen;
- ext2_ino_t dir, inode;
- errcode_t retval;
-
-#ifdef NAMEI_DEBUG
- printf("open_namei: root=%lu, dir=%lu, path=%*s, lc=%d\n",
- root, base, pathlen, pathname, link_count);
-#endif
- retval = dir_namei(fs, root, base, pathname, pathlen,
- link_count, buf, &basename, &namelen, &dir);
- if (retval) return retval;
- if (!namelen) { /* special case: '/usr/' etc */
- *res_inode=dir;
- return 0;
- }
- retval = ext2fs_lookup (fs, dir, basename, namelen, buf, &inode);
- if (retval)
- return retval;
- if (follow) {
- retval = follow_link(fs, root, dir, inode, link_count,
- buf, &inode);
- if (retval)
- return retval;
- }
-#ifdef NAMEI_DEBUG
- printf("open_namei: (link_count=%d) returns %lu\n",
- link_count, inode);
-#endif
- *res_inode = inode;
- return 0;
-}
-
-errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
- const char *name, ext2_ino_t *inode)
-{
- char *buf;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- retval = ext2fs_get_mem(fs->blocksize, &buf);
- if (retval)
- return retval;
-
- retval = open_namei(fs, root, cwd, name, strlen(name), 0, 0,
- buf, inode);
-
- ext2fs_free_mem(&buf);
- return retval;
-}
-
-errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
- const char *name, ext2_ino_t *inode)
-{
- char *buf;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- retval = ext2fs_get_mem(fs->blocksize, &buf);
- if (retval)
- return retval;
-
- retval = open_namei(fs, root, cwd, name, strlen(name), 1, 0,
- buf, inode);
-
- ext2fs_free_mem(&buf);
- return retval;
-}
-
-errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
- ext2_ino_t inode, ext2_ino_t *res_inode)
-{
- char *buf;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- retval = ext2fs_get_mem(fs->blocksize, &buf);
- if (retval)
- return retval;
-
- retval = follow_link(fs, root, cwd, inode, 0, buf, res_inode);
-
- ext2fs_free_mem(&buf);
- return retval;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/newdir.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/newdir.c
deleted file mode 100644
index 9f156626d8..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/newdir.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * newdir.c --- create a new directory block
- *
- * Copyright (C) 1994, 1995 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-#ifndef EXT2_FT_DIR
-#define EXT2_FT_DIR 2
-#endif
-
-/*
- * Create new directory block
- */
-errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino,
- ext2_ino_t parent_ino, char **block)
-{
- struct ext2_dir_entry *dir = NULL;
- errcode_t retval;
- char *buf;
- int rec_len;
- int filetype = 0;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- retval = ext2fs_get_mem(fs->blocksize, &buf);
- if (retval)
- return retval;
- memset(buf, 0, fs->blocksize);
- dir = (struct ext2_dir_entry *) buf;
- dir->rec_len = fs->blocksize;
-
- if (dir_ino) {
- if (fs->super->s_feature_incompat &
- EXT2_FEATURE_INCOMPAT_FILETYPE)
- filetype = EXT2_FT_DIR << 8;
- /*
- * Set up entry for '.'
- */
- dir->inode = dir_ino;
- dir->name_len = 1 | filetype;
- dir->name[0] = '.';
- rec_len = dir->rec_len - EXT2_DIR_REC_LEN(1);
- dir->rec_len = EXT2_DIR_REC_LEN(1);
-
- /*
- * Set up entry for '..'
- */
- dir = (struct ext2_dir_entry *) (buf + dir->rec_len);
- dir->rec_len = rec_len;
- dir->inode = parent_ino;
- dir->name_len = 2 | filetype;
- dir->name[0] = '.';
- dir->name[1] = '.';
- }
- *block = buf;
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/openfs.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/openfs.c
deleted file mode 100644
index 1b271196b1..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/openfs.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * openfs.c --- open an ext2 filesystem
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-
-
-#include "ext2fs.h"
-#include "e2image.h"
-
-blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, dgrp_t i)
-{
- int bg;
- int has_super = 0;
- int ret_blk;
-
- if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
- (i < fs->super->s_first_meta_bg))
- return (group_block + i + 1);
-
- bg = (fs->blocksize / sizeof (struct ext2_group_desc)) * i;
- if (ext2fs_bg_has_super(fs, bg))
- has_super = 1;
- ret_blk = (fs->super->s_first_data_block + has_super +
- (bg * fs->super->s_blocks_per_group));
- /*
- * If group_block is not the normal value, we're trying to use
- * the backup group descriptors and superblock --- so use the
- * alternate location of the second block group in the
- * metablock group. Ideally we should be testing each bg
- * descriptor block individually for correctness, but we don't
- * have the infrastructure in place to do that.
- */
- if (group_block != fs->super->s_first_data_block &&
- ((ret_blk + fs->super->s_blocks_per_group) <
- fs->super->s_blocks_count))
- ret_blk += fs->super->s_blocks_per_group;
- return ret_blk;
-}
-
-errcode_t ext2fs_open(const char *name, int flags, int superblock,
- unsigned int block_size, io_manager manager,
- ext2_filsys *ret_fs)
-{
- return ext2fs_open2(name, 0, flags, superblock, block_size,
- manager, ret_fs);
-}
-
-/*
- * Note: if superblock is non-zero, block-size must also be non-zero.
- * Superblock and block_size can be zero to use the default size.
- *
- * Valid flags for ext2fs_open()
- *
- * EXT2_FLAG_RW - Open the filesystem for read/write.
- * EXT2_FLAG_FORCE - Open the filesystem even if some of the
- * features aren't supported.
- * EXT2_FLAG_JOURNAL_DEV_OK - Open an ext3 journal device
- */
-errcode_t ext2fs_open2(const char *name, const char *io_options,
- int flags, int superblock,
- unsigned int block_size, io_manager manager,
- ext2_filsys *ret_fs)
-{
- ext2_filsys fs;
- errcode_t retval;
- unsigned long i;
- int groups_per_block, blocks_per_group;
- blk_t group_block, blk;
- char *dest, *cp;
-#if BB_BIG_ENDIAN
- int j;
- struct ext2_group_desc *gdp;
-#endif
-
- EXT2_CHECK_MAGIC(manager, EXT2_ET_MAGIC_IO_MANAGER);
-
- retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
- if (retval)
- return retval;
-
- memset(fs, 0, sizeof(struct struct_ext2_filsys));
- fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS;
- fs->flags = flags;
- fs->umask = 022;
- retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name);
- if (retval)
- goto cleanup;
- strcpy(fs->device_name, name);
- cp = strchr(fs->device_name, '?');
- if (!io_options && cp) {
- *cp++ = 0;
- io_options = cp;
- }
-
- retval = manager->open(fs->device_name,
- (flags & EXT2_FLAG_RW) ? IO_FLAG_RW : 0,
- &fs->io);
- if (retval)
- goto cleanup;
- if (io_options &&
- (retval = io_channel_set_options(fs->io, io_options)))
- goto cleanup;
- fs->image_io = fs->io;
- fs->io->app_data = fs;
- retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->super);
- if (retval)
- goto cleanup;
- if (flags & EXT2_FLAG_IMAGE_FILE) {
- retval = ext2fs_get_mem(sizeof(struct ext2_image_hdr),
- &fs->image_header);
- if (retval)
- goto cleanup;
- retval = io_channel_read_blk(fs->io, 0,
- -(int)sizeof(struct ext2_image_hdr),
- fs->image_header);
- if (retval)
- goto cleanup;
- if (fs->image_header->magic_number != EXT2_ET_MAGIC_E2IMAGE)
- return EXT2_ET_MAGIC_E2IMAGE;
- superblock = 1;
- block_size = fs->image_header->fs_blocksize;
- }
-
- /*
- * If the user specifies a specific block # for the
- * superblock, then he/she must also specify the block size!
- * Otherwise, read the master superblock located at offset
- * SUPERBLOCK_OFFSET from the start of the partition.
- *
- * Note: we only save a backup copy of the superblock if we
- * are reading the superblock from the primary superblock location.
- */
- if (superblock) {
- if (!block_size) {
- retval = EXT2_ET_INVALID_ARGUMENT;
- goto cleanup;
- }
- io_channel_set_blksize(fs->io, block_size);
- group_block = superblock;
- fs->orig_super = 0;
- } else {
- io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET);
- superblock = 1;
- group_block = 0;
- retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super);
- if (retval)
- goto cleanup;
- }
- retval = io_channel_read_blk(fs->io, superblock, -SUPERBLOCK_SIZE,
- fs->super);
- if (retval)
- goto cleanup;
- if (fs->orig_super)
- memcpy(fs->orig_super, fs->super, SUPERBLOCK_SIZE);
-
-#if BB_BIG_ENDIAN
- if ((fs->super->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC)) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES)) {
- fs->flags |= EXT2_FLAG_SWAP_BYTES;
-
- ext2fs_swap_super(fs->super);
- }
-#endif
-
- if (fs->super->s_magic != EXT2_SUPER_MAGIC) {
- retval = EXT2_ET_BAD_MAGIC;
- goto cleanup;
- }
- if (fs->super->s_rev_level > EXT2_LIB_CURRENT_REV) {
- retval = EXT2_ET_REV_TOO_HIGH;
- goto cleanup;
- }
-
- /*
- * Check for feature set incompatibility
- */
- if (!(flags & EXT2_FLAG_FORCE)) {
- if (fs->super->s_feature_incompat &
- ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) {
- retval = EXT2_ET_UNSUPP_FEATURE;
- goto cleanup;
- }
- if ((flags & EXT2_FLAG_RW) &&
- (fs->super->s_feature_ro_compat &
- ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP)) {
- retval = EXT2_ET_RO_UNSUPP_FEATURE;
- goto cleanup;
- }
- if (!(flags & EXT2_FLAG_JOURNAL_DEV_OK) &&
- (fs->super->s_feature_incompat &
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
- retval = EXT2_ET_UNSUPP_FEATURE;
- goto cleanup;
- }
- }
-
- fs->blocksize = EXT2_BLOCK_SIZE(fs->super);
- if (fs->blocksize == 0) {
- retval = EXT2_ET_CORRUPT_SUPERBLOCK;
- goto cleanup;
- }
- fs->fragsize = EXT2_FRAG_SIZE(fs->super);
- fs->inode_blocks_per_group = ((fs->super->s_inodes_per_group *
- EXT2_INODE_SIZE(fs->super) +
- EXT2_BLOCK_SIZE(fs->super) - 1) /
- EXT2_BLOCK_SIZE(fs->super));
- if (block_size) {
- if (block_size != fs->blocksize) {
- retval = EXT2_ET_UNEXPECTED_BLOCK_SIZE;
- goto cleanup;
- }
- }
- /*
- * Set the blocksize to the filesystem's blocksize.
- */
- io_channel_set_blksize(fs->io, fs->blocksize);
-
- /*
- * If this is an external journal device, don't try to read
- * the group descriptors, because they're not there.
- */
- if (fs->super->s_feature_incompat &
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
- fs->group_desc_count = 0;
- *ret_fs = fs;
- return 0;
- }
-
- /*
- * Read group descriptors
- */
- blocks_per_group = EXT2_BLOCKS_PER_GROUP(fs->super);
- if (blocks_per_group == 0 ||
- blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(fs->super) ||
- fs->inode_blocks_per_group > EXT2_MAX_INODES_PER_GROUP(fs->super)) {
- retval = EXT2_ET_CORRUPT_SUPERBLOCK;
- goto cleanup;
- }
- fs->group_desc_count = (fs->super->s_blocks_count -
- fs->super->s_first_data_block +
- blocks_per_group - 1) / blocks_per_group;
- fs->desc_blocks = (fs->group_desc_count +
- EXT2_DESC_PER_BLOCK(fs->super) - 1)
- / EXT2_DESC_PER_BLOCK(fs->super);
- retval = ext2fs_get_mem(fs->desc_blocks * fs->blocksize,
- &fs->group_desc);
- if (retval)
- goto cleanup;
- if (!group_block)
- group_block = fs->super->s_first_data_block;
- dest = (char *) fs->group_desc;
- groups_per_block = fs->blocksize / sizeof(struct ext2_group_desc);
- for (i = 0; i < fs->desc_blocks; i++) {
- blk = ext2fs_descriptor_block_loc(fs, group_block, i);
- retval = io_channel_read_blk(fs->io, blk, 1, dest);
- if (retval)
- goto cleanup;
-#if BB_BIG_ENDIAN
- if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
- gdp = (struct ext2_group_desc *) dest;
- for (j=0; j < groups_per_block; j++)
- ext2fs_swap_group_desc(gdp++);
- }
-#endif
- dest += fs->blocksize;
- }
-
- *ret_fs = fs;
- return 0;
-cleanup:
- ext2fs_free(fs);
- return retval;
-}
-
-/*
- * Set/get the filesystem data I/O channel.
- *
- * These functions are only valid if EXT2_FLAG_IMAGE_FILE is true.
- */
-errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io)
-{
- if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0)
- return EXT2_ET_NOT_IMAGE_FILE;
- if (old_io) {
- *old_io = (fs->image_io == fs->io) ? 0 : fs->io;
- }
- return 0;
-}
-
-errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io)
-{
- if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0)
- return EXT2_ET_NOT_IMAGE_FILE;
- fs->io = new_io ? new_io : fs->image_io;
- return 0;
-}
-
-errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io)
-{
- if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0)
- return EXT2_ET_NOT_IMAGE_FILE;
- fs->io = fs->image_io = new_io;
- fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_RW |
- EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
- fs->flags &= ~EXT2_FLAG_IMAGE_FILE;
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/read_bb.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/read_bb.c
deleted file mode 100644
index ce77bc9f6b..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/read_bb.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * read_bb --- read the bad blocks inode
- *
- * Copyright (C) 1994 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-struct read_bb_record {
- ext2_badblocks_list bb_list;
- errcode_t err;
-};
-
-/*
- * Helper function for ext2fs_read_bb_inode()
- */
-#ifdef __TURBOC__
-# pragma argsused
-#endif
-static int mark_bad_block(ext2_filsys fs, blk_t *block_nr,
- e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
- blk_t ref_block EXT2FS_ATTR((unused)),
- int ref_offset EXT2FS_ATTR((unused)),
- void *priv_data)
-{
- struct read_bb_record *rb = (struct read_bb_record *) priv_data;
-
- if (blockcnt < 0)
- return 0;
-
- if ((*block_nr < fs->super->s_first_data_block) ||
- (*block_nr >= fs->super->s_blocks_count))
- return 0; /* Ignore illegal blocks */
-
- rb->err = ext2fs_badblocks_list_add(rb->bb_list, *block_nr);
- if (rb->err)
- return BLOCK_ABORT;
- return 0;
-}
-
-/*
- * Reads the current bad blocks from the bad blocks inode.
- */
-errcode_t ext2fs_read_bb_inode(ext2_filsys fs, ext2_badblocks_list *bb_list)
-{
- errcode_t retval;
- struct read_bb_record rb;
- struct ext2_inode inode;
- blk_t numblocks;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!*bb_list) {
- retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode);
- if (retval)
- return retval;
- if (inode.i_blocks < 500)
- numblocks = (inode.i_blocks /
- (fs->blocksize / 512)) + 20;
- else
- numblocks = 500;
- retval = ext2fs_badblocks_list_create(bb_list, numblocks);
- if (retval)
- return retval;
- }
-
- rb.bb_list = *bb_list;
- rb.err = 0;
- retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, 0, 0,
- mark_bad_block, &rb);
- if (retval)
- return retval;
-
- return rb.err;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/read_bb_file.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/read_bb_file.c
deleted file mode 100644
index bf1fc328be..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/read_bb_file.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * read_bb_file.c --- read a list of bad blocks from a FILE *
- *
- * Copyright (C) 1994, 1995, 2000 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * Reads a list of bad blocks from a FILE *
- */
-errcode_t ext2fs_read_bb_FILE2(ext2_filsys fs, FILE *f,
- ext2_badblocks_list *bb_list,
- void *priv_data,
- void (*invalid)(ext2_filsys fs,
- blk_t blk,
- char *badstr,
- void *priv_data))
-{
- errcode_t retval;
- blk_t blockno;
- int count;
- char buf[128];
-
- if (fs)
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!*bb_list) {
- retval = ext2fs_badblocks_list_create(bb_list, 10);
- if (retval)
- return retval;
- }
-
- while (!feof (f)) {
- if (fgets(buf, sizeof(buf), f) == NULL)
- break;
- count = sscanf(buf, "%u", &blockno);
- if (count <= 0)
- continue;
- if (fs &&
- ((blockno < fs->super->s_first_data_block) ||
- (blockno >= fs->super->s_blocks_count))) {
- if (invalid)
- (invalid)(fs, blockno, buf, priv_data);
- continue;
- }
- retval = ext2fs_badblocks_list_add(*bb_list, blockno);
- if (retval)
- return retval;
- }
- return 0;
-}
-
-static void call_compat_invalid(ext2_filsys fs, blk_t blk,
- char *badstr EXT2FS_ATTR((unused)),
- void *priv_data)
-{
- void (*invalid)(ext2_filsys, blk_t);
-
- invalid = (void (*)(ext2_filsys, blk_t)) priv_data;
- if (invalid)
- invalid(fs, blk);
-}
-
-
-/*
- * Reads a list of bad blocks from a FILE *
- */
-errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f,
- ext2_badblocks_list *bb_list,
- void (*invalid)(ext2_filsys fs, blk_t blk))
-{
- return ext2fs_read_bb_FILE2(fs, f, bb_list, (void *) invalid,
- call_compat_invalid);
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/res_gdt.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/res_gdt.c
deleted file mode 100644
index 403463a90f..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/res_gdt.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * res_gdt.c --- reserve blocks for growing the group descriptor table
- * during online resizing.
- *
- * Copyright (C) 2002 Andreas Dilger
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * Iterate through the groups which hold BACKUP superblock/GDT copies in an
- * ext3 filesystem. The counters should be initialized to 1, 5, and 7 before
- * calling this for the first time. In a sparse filesystem it will be the
- * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ...
- * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ...
- */
-static unsigned int list_backups(ext2_filsys fs, unsigned int *three,
- unsigned int *five, unsigned int *seven)
-{
- unsigned int *min = three;
- int mult = 3;
- unsigned int ret;
-
- if (!(fs->super->s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
- ret = *min;
- *min += 1;
- return ret;
- }
-
- if (*five < *min) {
- min = five;
- mult = 5;
- }
- if (*seven < *min) {
- min = seven;
- mult = 7;
- }
-
- ret = *min;
- *min *= mult;
-
- return ret;
-}
-
-/*
- * This code assumes that the reserved blocks have already been marked in-use
- * during ext2fs_initialize(), so that they are not allocated for other
- * uses before we can add them to the resize inode (which has to come
- * after the creation of the inode table).
- */
-errcode_t ext2fs_create_resize_inode(ext2_filsys fs)
-{
- errcode_t retval, retval2;
- struct ext2_super_block *sb;
- struct ext2_inode inode;
- __u32 *dindir_buf, *gdt_buf;
- int rsv_add;
- unsigned long long apb, inode_size;
- blk_t dindir_blk, rsv_off, gdt_off, gdt_blk;
- int dindir_dirty = 0, inode_dirty = 0;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- sb = fs->super;
-
- retval = ext2fs_get_mem(2 * fs->blocksize, (void *)&dindir_buf);
- if (retval)
- goto out_free;
- gdt_buf = (__u32 *)((char *)dindir_buf + fs->blocksize);
-
- retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
- if (retval)
- goto out_free;
-
- /* Maximum possible file size (we donly use the dindirect blocks) */
- apb = EXT2_ADDR_PER_BLOCK(sb);
- rsv_add = fs->blocksize / 512;
- if ((dindir_blk = inode.i_block[EXT2_DIND_BLOCK])) {
-#ifdef RES_GDT_DEBUG
- printf("reading GDT dindir %u\n", dindir_blk);
-#endif
- retval = ext2fs_read_ind_block(fs, dindir_blk, dindir_buf);
- if (retval)
- goto out_inode;
- } else {
- blk_t goal = 3 + sb->s_reserved_gdt_blocks +
- fs->desc_blocks + fs->inode_blocks_per_group;
-
- retval = ext2fs_alloc_block(fs, goal, 0, &dindir_blk);
- if (retval)
- goto out_free;
- inode.i_mode = LINUX_S_IFREG | 0600;
- inode.i_links_count = 1;
- inode.i_block[EXT2_DIND_BLOCK] = dindir_blk;
- inode.i_blocks = rsv_add;
- memset(dindir_buf, 0, fs->blocksize);
-#ifdef RES_GDT_DEBUG
- printf("allocated GDT dindir %u\n", dindir_blk);
-#endif
- dindir_dirty = inode_dirty = 1;
- inode_size = apb*apb + apb + EXT2_NDIR_BLOCKS;
- inode_size *= fs->blocksize;
- inode.i_size = inode_size & 0xFFFFFFFF;
- inode.i_size_high = (inode_size >> 32) & 0xFFFFFFFF;
- if (inode.i_size_high) {
- sb->s_feature_ro_compat |=
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
- }
- inode.i_ctime = time(NULL);
- }
-
- for (rsv_off = 0, gdt_off = fs->desc_blocks,
- gdt_blk = sb->s_first_data_block + 1 + fs->desc_blocks;
- rsv_off < sb->s_reserved_gdt_blocks;
- rsv_off++, gdt_off++, gdt_blk++) {
- unsigned int three = 1, five = 5, seven = 7;
- unsigned int grp, last = 0;
- int gdt_dirty = 0;
-
- gdt_off %= apb;
- if (!dindir_buf[gdt_off]) {
- /* FIXME XXX XXX
- blk_t new_blk;
-
- retval = ext2fs_new_block(fs, gdt_blk, 0, &new_blk);
- if (retval)
- goto out_free;
- if (new_blk != gdt_blk) {
- // XXX free block
- retval = -1; // XXX
- }
- */
- gdt_dirty = dindir_dirty = inode_dirty = 1;
- memset(gdt_buf, 0, fs->blocksize);
- dindir_buf[gdt_off] = gdt_blk;
- inode.i_blocks += rsv_add;
-#ifdef RES_GDT_DEBUG
- printf("added primary GDT block %u at %u[%u]\n",
- gdt_blk, dindir_blk, gdt_off);
-#endif
- } else if (dindir_buf[gdt_off] == gdt_blk) {
-#ifdef RES_GDT_DEBUG
- printf("reading primary GDT block %u\n", gdt_blk);
-#endif
- retval = ext2fs_read_ind_block(fs, gdt_blk, gdt_buf);
- if (retval)
- goto out_dindir;
- } else {
-#ifdef RES_GDT_DEBUG
- printf("bad primary GDT %u != %u at %u[%u]\n",
- dindir_buf[gdt_off], gdt_blk,dindir_blk,gdt_off);
-#endif
- retval = EXT2_ET_RESIZE_INODE_CORRUPT;
- goto out_dindir;
- }
-
- while ((grp = list_backups(fs, &three, &five, &seven)) <
- fs->group_desc_count) {
- blk_t expect = gdt_blk + grp * sb->s_blocks_per_group;
-
- if (!gdt_buf[last]) {
-#ifdef RES_GDT_DEBUG
- printf("added backup GDT %u grp %u@%u[%u]\n",
- expect, grp, gdt_blk, last);
-#endif
- gdt_buf[last] = expect;
- inode.i_blocks += rsv_add;
- gdt_dirty = inode_dirty = 1;
- } else if (gdt_buf[last] != expect) {
-#ifdef RES_GDT_DEBUG
- printf("bad backup GDT %u != %u at %u[%u]\n",
- gdt_buf[last], expect, gdt_blk, last);
-#endif
- retval = EXT2_ET_RESIZE_INODE_CORRUPT;
- goto out_dindir;
- }
- last++;
- }
- if (gdt_dirty) {
-#ifdef RES_GDT_DEBUG
- printf("writing primary GDT block %u\n", gdt_blk);
-#endif
- retval = ext2fs_write_ind_block(fs, gdt_blk, gdt_buf);
- if (retval)
- goto out_dindir;
- }
- }
-
-out_dindir:
- if (dindir_dirty) {
- retval2 = ext2fs_write_ind_block(fs, dindir_blk, dindir_buf);
- if (!retval)
- retval = retval2;
- }
-out_inode:
-#ifdef RES_GDT_DEBUG
- printf("inode.i_blocks = %u, i_size = %u\n", inode.i_blocks,
- inode.i_size);
-#endif
- if (inode_dirty) {
- inode.i_atime = inode.i_mtime = time(NULL);
- retval2 = ext2fs_write_inode(fs, EXT2_RESIZE_INO, &inode);
- if (!retval)
- retval = retval2;
- }
-out_free:
- ext2fs_free_mem((void *)&dindir_buf);
- return retval;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/rs_bitmap.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/rs_bitmap.c
deleted file mode 100644
index 32e87b77a9..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/rs_bitmap.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * rs_bitmap.c --- routine for changing the size of a bitmap
- *
- * Copyright (C) 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-errcode_t ext2fs_resize_generic_bitmap(__u32 new_end, __u32 new_real_end,
- ext2fs_generic_bitmap bmap)
-{
- errcode_t retval;
- size_t size, new_size;
- __u32 bitno;
-
- if (!bmap)
- return EXT2_ET_INVALID_ARGUMENT;
-
- EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_GENERIC_BITMAP);
-
- /*
- * If we're expanding the bitmap, make sure all of the new
- * parts of the bitmap are zero.
- */
- if (new_end > bmap->end) {
- bitno = bmap->real_end;
- if (bitno > new_end)
- bitno = new_end;
- for (; bitno > bmap->end; bitno--)
- ext2fs_clear_bit(bitno - bmap->start, bmap->bitmap);
- }
- if (new_real_end == bmap->real_end) {
- bmap->end = new_end;
- return 0;
- }
-
- size = ((bmap->real_end - bmap->start) / 8) + 1;
- new_size = ((new_real_end - bmap->start) / 8) + 1;
-
- if (size != new_size) {
- retval = ext2fs_resize_mem(size, new_size, &bmap->bitmap);
- if (retval)
- return retval;
- }
- if (new_size > size)
- memset(bmap->bitmap + size, 0, new_size - size);
-
- bmap->end = new_end;
- bmap->real_end = new_real_end;
- return 0;
-}
-
-errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
- ext2fs_inode_bitmap bmap)
-{
- errcode_t retval;
-
- if (!bmap)
- return EXT2_ET_INVALID_ARGUMENT;
-
- EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_INODE_BITMAP);
-
- bmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
- retval = ext2fs_resize_generic_bitmap(new_end, new_real_end,
- bmap);
- bmap->magic = EXT2_ET_MAGIC_INODE_BITMAP;
- return retval;
-}
-
-errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
- ext2fs_block_bitmap bmap)
-{
- errcode_t retval;
-
- if (!bmap)
- return EXT2_ET_INVALID_ARGUMENT;
-
- EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_BLOCK_BITMAP);
-
- bmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
- retval = ext2fs_resize_generic_bitmap(new_end, new_real_end,
- bmap);
- bmap->magic = EXT2_ET_MAGIC_BLOCK_BITMAP;
- return retval;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/rw_bitmaps.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/rw_bitmaps.c
deleted file mode 100644
index bba4326796..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/rw_bitmaps.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * rw_bitmaps.c --- routines to read and write the inode and block bitmaps.
- *
- * Copyright (C) 1993, 1994, 1994, 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-#include "e2image.h"
-
-#if defined(__powerpc__) && BB_BIG_ENDIAN
-/*
- * On the PowerPC, the big-endian variant of the ext2 filesystem
- * has its bitmaps stored as 32-bit words with bit 0 as the LSB
- * of each word. Thus a bitmap with only bit 0 set would be, as
- * a string of bytes, 00 00 00 01 00 ...
- * To cope with this, we byte-reverse each word of a bitmap if
- * we have a big-endian filesystem, that is, if we are *not*
- * byte-swapping other word-sized numbers.
- */
-#define EXT2_BIG_ENDIAN_BITMAPS
-#endif
-
-#ifdef EXT2_BIG_ENDIAN_BITMAPS
-static void ext2fs_swap_bitmap(ext2_filsys fs, char *bitmap, int nbytes)
-{
- __u32 *p = (__u32 *) bitmap;
- int n;
-
- for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
- *p = ext2fs_swab32(*p);
-}
-#endif
-
-errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs)
-{
- dgrp_t i;
- size_t nbytes;
- errcode_t retval;
- char * inode_bitmap = fs->inode_map->bitmap;
- char * bitmap_block = NULL;
- blk_t blk;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!(fs->flags & EXT2_FLAG_RW))
- return EXT2_ET_RO_FILSYS;
- if (!inode_bitmap)
- return 0;
- nbytes = (size_t) ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8);
-
- retval = ext2fs_get_mem(fs->blocksize, &bitmap_block);
- if (retval)
- return retval;
- memset(bitmap_block, 0xff, fs->blocksize);
- for (i = 0; i < fs->group_desc_count; i++) {
- memcpy(bitmap_block, inode_bitmap, nbytes);
- blk = fs->group_desc[i].bg_inode_bitmap;
- if (blk) {
-#ifdef EXT2_BIG_ENDIAN_BITMAPS
- if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
- ext2fs_swap_bitmap(fs, bitmap_block, nbytes);
-#endif
- retval = io_channel_write_blk(fs->io, blk, 1,
- bitmap_block);
- if (retval)
- return EXT2_ET_INODE_BITMAP_WRITE;
- }
- inode_bitmap += nbytes;
- }
- fs->flags &= ~EXT2_FLAG_IB_DIRTY;
- ext2fs_free_mem(&bitmap_block);
- return 0;
-}
-
-errcode_t ext2fs_write_block_bitmap (ext2_filsys fs)
-{
- dgrp_t i;
- unsigned int j;
- int nbytes;
- unsigned int nbits;
- errcode_t retval;
- char * block_bitmap = fs->block_map->bitmap;
- char * bitmap_block = NULL;
- blk_t blk;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!(fs->flags & EXT2_FLAG_RW))
- return EXT2_ET_RO_FILSYS;
- if (!block_bitmap)
- return 0;
- nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
- retval = ext2fs_get_mem(fs->blocksize, &bitmap_block);
- if (retval)
- return retval;
- memset(bitmap_block, 0xff, fs->blocksize);
- for (i = 0; i < fs->group_desc_count; i++) {
- memcpy(bitmap_block, block_bitmap, nbytes);
- if (i == fs->group_desc_count - 1) {
- /* Force bitmap padding for the last group */
- nbits = ((fs->super->s_blocks_count
- - fs->super->s_first_data_block)
- % EXT2_BLOCKS_PER_GROUP(fs->super));
- if (nbits)
- for (j = nbits; j < fs->blocksize * 8; j++)
- ext2fs_set_bit(j, bitmap_block);
- }
- blk = fs->group_desc[i].bg_block_bitmap;
- if (blk) {
-#ifdef EXT2_BIG_ENDIAN_BITMAPS
- if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
- ext2fs_swap_bitmap(fs, bitmap_block, nbytes);
-#endif
- retval = io_channel_write_blk(fs->io, blk, 1,
- bitmap_block);
- if (retval)
- return EXT2_ET_BLOCK_BITMAP_WRITE;
- }
- block_bitmap += nbytes;
- }
- fs->flags &= ~EXT2_FLAG_BB_DIRTY;
- ext2fs_free_mem(&bitmap_block);
- return 0;
-}
-
-static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
-{
- dgrp_t i;
- char *block_bitmap = NULL, *inode_bitmap = NULL;
- char *buf;
- errcode_t retval;
- int block_nbytes = (int) EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
- int inode_nbytes = (int) EXT2_INODES_PER_GROUP(fs->super) / 8;
- blk_t blk;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- fs->write_bitmaps = ext2fs_write_bitmaps;
-
- retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
- if (retval)
- return retval;
- if (do_block) {
- ext2fs_free_block_bitmap(fs->block_map);
- sprintf(buf, "block bitmap for %s", fs->device_name);
- retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
- if (retval)
- goto cleanup;
- block_bitmap = fs->block_map->bitmap;
- }
- if (do_inode) {
- ext2fs_free_inode_bitmap(fs->inode_map);
- sprintf(buf, "inode bitmap for %s", fs->device_name);
- retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
- if (retval)
- goto cleanup;
- inode_bitmap = fs->inode_map->bitmap;
- }
- ext2fs_free_mem(&buf);
-
- if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
- if (inode_bitmap) {
- blk = (fs->image_header->offset_inodemap /
- fs->blocksize);
- retval = io_channel_read_blk(fs->image_io, blk,
- -(inode_nbytes * fs->group_desc_count),
- inode_bitmap);
- if (retval)
- goto cleanup;
- }
- if (block_bitmap) {
- blk = (fs->image_header->offset_blockmap /
- fs->blocksize);
- retval = io_channel_read_blk(fs->image_io, blk,
- -(block_nbytes * fs->group_desc_count),
- block_bitmap);
- if (retval)
- goto cleanup;
- }
- return 0;
- }
-
- for (i = 0; i < fs->group_desc_count; i++) {
- if (block_bitmap) {
- blk = fs->group_desc[i].bg_block_bitmap;
- if (blk) {
- retval = io_channel_read_blk(fs->io, blk,
- -block_nbytes, block_bitmap);
- if (retval) {
- retval = EXT2_ET_BLOCK_BITMAP_READ;
- goto cleanup;
- }
-#ifdef EXT2_BIG_ENDIAN_BITMAPS
- if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)))
- ext2fs_swap_bitmap(fs, block_bitmap, block_nbytes);
-#endif
- } else
- memset(block_bitmap, 0, block_nbytes);
- block_bitmap += block_nbytes;
- }
- if (inode_bitmap) {
- blk = fs->group_desc[i].bg_inode_bitmap;
- if (blk) {
- retval = io_channel_read_blk(fs->io, blk,
- -inode_nbytes, inode_bitmap);
- if (retval) {
- retval = EXT2_ET_INODE_BITMAP_READ;
- goto cleanup;
- }
-#ifdef EXT2_BIG_ENDIAN_BITMAPS
- if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)))
- ext2fs_swap_bitmap(fs, inode_bitmap, inode_nbytes);
-#endif
- } else
- memset(inode_bitmap, 0, inode_nbytes);
- inode_bitmap += inode_nbytes;
- }
- }
- return 0;
-
-cleanup:
- if (do_block) {
- ext2fs_free_mem(&fs->block_map);
- }
- if (do_inode) {
- ext2fs_free_mem(&fs->inode_map);
- }
- ext2fs_free_mem(&buf);
- return retval;
-}
-
-errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs)
-{
- return read_bitmaps(fs, 1, 0);
-}
-
-errcode_t ext2fs_read_block_bitmap(ext2_filsys fs)
-{
- return read_bitmaps(fs, 0, 1);
-}
-
-errcode_t ext2fs_read_bitmaps(ext2_filsys fs)
-{
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (fs->inode_map && fs->block_map)
- return 0;
-
- return read_bitmaps(fs, !fs->inode_map, !fs->block_map);
-}
-
-errcode_t ext2fs_write_bitmaps(ext2_filsys fs)
-{
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (fs->block_map && ext2fs_test_bb_dirty(fs)) {
- retval = ext2fs_write_block_bitmap(fs);
- if (retval)
- return retval;
- }
- if (fs->inode_map && ext2fs_test_ib_dirty(fs)) {
- retval = ext2fs_write_inode_bitmap(fs);
- if (retval)
- return retval;
- }
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/sparse.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/sparse.c
deleted file mode 100644
index b3d3071e98..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/sparse.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * sparse.c --- find the groups in an ext2 filesystem with metadata backups
- *
- * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
- * Copyright (C) 2002 Andreas Dilger.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-
-#include "ext2_fs.h"
-#include "ext2fsP.h"
-
-static int test_root(int a, int b)
-{
- if (a == 0)
- return 1;
- while (1) {
- if (a == 1)
- return 1;
- if (a % b)
- return 0;
- a = a / b;
- }
-}
-
-int ext2fs_bg_has_super(ext2_filsys fs, int group_block)
-{
- if (!(fs->super->s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
- return 1;
-
- if (test_root(group_block, 3) || (test_root(group_block, 5)) ||
- test_root(group_block, 7))
- return 1;
-
- return 0;
-}
-
-/*
- * Iterate through the groups which hold BACKUP superblock/GDT copies in an
- * ext3 filesystem. The counters should be initialized to 1, 5, and 7 before
- * calling this for the first time. In a sparse filesystem it will be the
- * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ...
- * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ...
- */
-unsigned int ext2fs_list_backups(ext2_filsys fs, unsigned int *three,
- unsigned int *five, unsigned int *seven)
-{
- unsigned int *min = three;
- int mult = 3;
- unsigned int ret;
-
- if (!(fs->super->s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
- ret = *min;
- *min += 1;
- return ret;
- }
-
- if (*five < *min) {
- min = five;
- mult = 5;
- }
- if (*seven < *min) {
- min = seven;
- mult = 7;
- }
-
- ret = *min;
- *min *= mult;
-
- return ret;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/swapfs.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/swapfs.c
deleted file mode 100644
index 07b757abd2..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/swapfs.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * swapfs.c --- swap ext2 filesystem data structures
- *
- * Copyright (C) 1995, 1996, 2002 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <time.h>
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-#include "ext2_ext_attr.h"
-
-#if BB_BIG_ENDIAN
-void ext2fs_swap_super(struct ext2_super_block * sb)
-{
- int i;
- sb->s_inodes_count = ext2fs_swab32(sb->s_inodes_count);
- sb->s_blocks_count = ext2fs_swab32(sb->s_blocks_count);
- sb->s_r_blocks_count = ext2fs_swab32(sb->s_r_blocks_count);
- sb->s_free_blocks_count = ext2fs_swab32(sb->s_free_blocks_count);
- sb->s_free_inodes_count = ext2fs_swab32(sb->s_free_inodes_count);
- sb->s_first_data_block = ext2fs_swab32(sb->s_first_data_block);
- sb->s_log_block_size = ext2fs_swab32(sb->s_log_block_size);
- sb->s_log_frag_size = ext2fs_swab32(sb->s_log_frag_size);
- sb->s_blocks_per_group = ext2fs_swab32(sb->s_blocks_per_group);
- sb->s_frags_per_group = ext2fs_swab32(sb->s_frags_per_group);
- sb->s_inodes_per_group = ext2fs_swab32(sb->s_inodes_per_group);
- sb->s_mtime = ext2fs_swab32(sb->s_mtime);
- sb->s_wtime = ext2fs_swab32(sb->s_wtime);
- sb->s_mnt_count = ext2fs_swab16(sb->s_mnt_count);
- sb->s_max_mnt_count = ext2fs_swab16(sb->s_max_mnt_count);
- sb->s_magic = ext2fs_swab16(sb->s_magic);
- sb->s_state = ext2fs_swab16(sb->s_state);
- sb->s_errors = ext2fs_swab16(sb->s_errors);
- sb->s_minor_rev_level = ext2fs_swab16(sb->s_minor_rev_level);
- sb->s_lastcheck = ext2fs_swab32(sb->s_lastcheck);
- sb->s_checkinterval = ext2fs_swab32(sb->s_checkinterval);
- sb->s_creator_os = ext2fs_swab32(sb->s_creator_os);
- sb->s_rev_level = ext2fs_swab32(sb->s_rev_level);
- sb->s_def_resuid = ext2fs_swab16(sb->s_def_resuid);
- sb->s_def_resgid = ext2fs_swab16(sb->s_def_resgid);
- sb->s_first_ino = ext2fs_swab32(sb->s_first_ino);
- sb->s_inode_size = ext2fs_swab16(sb->s_inode_size);
- sb->s_block_group_nr = ext2fs_swab16(sb->s_block_group_nr);
- sb->s_feature_compat = ext2fs_swab32(sb->s_feature_compat);
- sb->s_feature_incompat = ext2fs_swab32(sb->s_feature_incompat);
- sb->s_feature_ro_compat = ext2fs_swab32(sb->s_feature_ro_compat);
- sb->s_algorithm_usage_bitmap = ext2fs_swab32(sb->s_algorithm_usage_bitmap);
- sb->s_reserved_gdt_blocks = ext2fs_swab16(sb->s_reserved_gdt_blocks);
- sb->s_journal_inum = ext2fs_swab32(sb->s_journal_inum);
- sb->s_journal_dev = ext2fs_swab32(sb->s_journal_dev);
- sb->s_last_orphan = ext2fs_swab32(sb->s_last_orphan);
- sb->s_default_mount_opts = ext2fs_swab32(sb->s_default_mount_opts);
- sb->s_first_meta_bg = ext2fs_swab32(sb->s_first_meta_bg);
- sb->s_mkfs_time = ext2fs_swab32(sb->s_mkfs_time);
- for (i=0; i < 4; i++)
- sb->s_hash_seed[i] = ext2fs_swab32(sb->s_hash_seed[i]);
- for (i=0; i < 17; i++)
- sb->s_jnl_blocks[i] = ext2fs_swab32(sb->s_jnl_blocks[i]);
-}
-
-void ext2fs_swap_group_desc(struct ext2_group_desc *gdp)
-{
- gdp->bg_block_bitmap = ext2fs_swab32(gdp->bg_block_bitmap);
- gdp->bg_inode_bitmap = ext2fs_swab32(gdp->bg_inode_bitmap);
- gdp->bg_inode_table = ext2fs_swab32(gdp->bg_inode_table);
- gdp->bg_free_blocks_count = ext2fs_swab16(gdp->bg_free_blocks_count);
- gdp->bg_free_inodes_count = ext2fs_swab16(gdp->bg_free_inodes_count);
- gdp->bg_used_dirs_count = ext2fs_swab16(gdp->bg_used_dirs_count);
-}
-
-void ext2fs_swap_ext_attr(char *to, char *from, int bufsize, int has_header)
-{
- struct ext2_ext_attr_header *from_header =
- (struct ext2_ext_attr_header *)from;
- struct ext2_ext_attr_header *to_header =
- (struct ext2_ext_attr_header *)to;
- struct ext2_ext_attr_entry *from_entry, *to_entry;
- char *from_end = (char *)from_header + bufsize;
- int n;
-
- if (to_header != from_header)
- memcpy(to_header, from_header, bufsize);
-
- from_entry = (struct ext2_ext_attr_entry *)from_header;
- to_entry = (struct ext2_ext_attr_entry *)to_header;
-
- if (has_header) {
- to_header->h_magic = ext2fs_swab32(from_header->h_magic);
- to_header->h_blocks = ext2fs_swab32(from_header->h_blocks);
- to_header->h_refcount = ext2fs_swab32(from_header->h_refcount);
- for (n=0; n<4; n++)
- to_header->h_reserved[n] =
- ext2fs_swab32(from_header->h_reserved[n]);
- from_entry = (struct ext2_ext_attr_entry *)(from_header+1);
- to_entry = (struct ext2_ext_attr_entry *)(to_header+1);
- }
-
- while ((char *)from_entry < from_end && *(__u32 *)from_entry) {
- to_entry->e_value_offs =
- ext2fs_swab16(from_entry->e_value_offs);
- to_entry->e_value_block =
- ext2fs_swab32(from_entry->e_value_block);
- to_entry->e_value_size =
- ext2fs_swab32(from_entry->e_value_size);
- from_entry = EXT2_EXT_ATTR_NEXT(from_entry);
- to_entry = EXT2_EXT_ATTR_NEXT(to_entry);
- }
-}
-
-void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t,
- struct ext2_inode_large *f, int hostorder,
- int bufsize)
-{
- unsigned i;
- int islnk = 0;
- __u32 *eaf, *eat;
-
- if (hostorder && LINUX_S_ISLNK(f->i_mode))
- islnk = 1;
- t->i_mode = ext2fs_swab16(f->i_mode);
- if (!hostorder && LINUX_S_ISLNK(t->i_mode))
- islnk = 1;
- t->i_uid = ext2fs_swab16(f->i_uid);
- t->i_size = ext2fs_swab32(f->i_size);
- t->i_atime = ext2fs_swab32(f->i_atime);
- t->i_ctime = ext2fs_swab32(f->i_ctime);
- t->i_mtime = ext2fs_swab32(f->i_mtime);
- t->i_dtime = ext2fs_swab32(f->i_dtime);
- t->i_gid = ext2fs_swab16(f->i_gid);
- t->i_links_count = ext2fs_swab16(f->i_links_count);
- t->i_blocks = ext2fs_swab32(f->i_blocks);
- t->i_flags = ext2fs_swab32(f->i_flags);
- t->i_file_acl = ext2fs_swab32(f->i_file_acl);
- t->i_dir_acl = ext2fs_swab32(f->i_dir_acl);
- if (!islnk || ext2fs_inode_data_blocks(fs, (struct ext2_inode *)t)) {
- for (i = 0; i < EXT2_N_BLOCKS; i++)
- t->i_block[i] = ext2fs_swab32(f->i_block[i]);
- } else if (t != f) {
- for (i = 0; i < EXT2_N_BLOCKS; i++)
- t->i_block[i] = f->i_block[i];
- }
- t->i_generation = ext2fs_swab32(f->i_generation);
- t->i_faddr = ext2fs_swab32(f->i_faddr);
-
- switch (fs->super->s_creator_os) {
- case EXT2_OS_LINUX:
- t->osd1.linux1.l_i_reserved1 =
- ext2fs_swab32(f->osd1.linux1.l_i_reserved1);
- t->osd2.linux2.l_i_frag = f->osd2.linux2.l_i_frag;
- t->osd2.linux2.l_i_fsize = f->osd2.linux2.l_i_fsize;
- t->osd2.linux2.i_pad1 = ext2fs_swab16(f->osd2.linux2.i_pad1);
- t->osd2.linux2.l_i_uid_high =
- ext2fs_swab16 (f->osd2.linux2.l_i_uid_high);
- t->osd2.linux2.l_i_gid_high =
- ext2fs_swab16 (f->osd2.linux2.l_i_gid_high);
- t->osd2.linux2.l_i_reserved2 =
- ext2fs_swab32(f->osd2.linux2.l_i_reserved2);
- break;
- case EXT2_OS_HURD:
- t->osd1.hurd1.h_i_translator =
- ext2fs_swab32 (f->osd1.hurd1.h_i_translator);
- t->osd2.hurd2.h_i_frag = f->osd2.hurd2.h_i_frag;
- t->osd2.hurd2.h_i_fsize = f->osd2.hurd2.h_i_fsize;
- t->osd2.hurd2.h_i_mode_high =
- ext2fs_swab16 (f->osd2.hurd2.h_i_mode_high);
- t->osd2.hurd2.h_i_uid_high =
- ext2fs_swab16 (f->osd2.hurd2.h_i_uid_high);
- t->osd2.hurd2.h_i_gid_high =
- ext2fs_swab16 (f->osd2.hurd2.h_i_gid_high);
- t->osd2.hurd2.h_i_author =
- ext2fs_swab32 (f->osd2.hurd2.h_i_author);
- break;
- case EXT2_OS_MASIX:
- t->osd1.masix1.m_i_reserved1 =
- ext2fs_swab32(f->osd1.masix1.m_i_reserved1);
- t->osd2.masix2.m_i_frag = f->osd2.masix2.m_i_frag;
- t->osd2.masix2.m_i_fsize = f->osd2.masix2.m_i_fsize;
- t->osd2.masix2.m_pad1 = ext2fs_swab16(f->osd2.masix2.m_pad1);
- t->osd2.masix2.m_i_reserved2[0] =
- ext2fs_swab32(f->osd2.masix2.m_i_reserved2[0]);
- t->osd2.masix2.m_i_reserved2[1] =
- ext2fs_swab32(f->osd2.masix2.m_i_reserved2[1]);
- break;
- }
-
- if (bufsize < (int) (sizeof(struct ext2_inode) + sizeof(__u16)))
- return; /* no i_extra_isize field */
-
- t->i_extra_isize = ext2fs_swab16(f->i_extra_isize);
- if (t->i_extra_isize > EXT2_INODE_SIZE(fs->super) -
- sizeof(struct ext2_inode)) {
- /* this is error case: i_extra_size is too large */
- return;
- }
-
- i = sizeof(struct ext2_inode) + t->i_extra_isize + sizeof(__u32);
- if (bufsize < (int) i)
- return; /* no space for EA magic */
-
- eaf = (__u32 *) (((char *) f) + sizeof(struct ext2_inode) +
- f->i_extra_isize);
-
- if (ext2fs_swab32(*eaf) != EXT2_EXT_ATTR_MAGIC)
- return; /* it seems no magic here */
-
- eat = (__u32 *) (((char *) t) + sizeof(struct ext2_inode) +
- f->i_extra_isize);
- *eat = ext2fs_swab32(*eaf);
-
- /* convert EA(s) */
- ext2fs_swap_ext_attr((char *) (eat + 1), (char *) (eaf + 1),
- bufsize - sizeof(struct ext2_inode) -
- t->i_extra_isize - sizeof(__u32), 0);
-}
-
-void ext2fs_swap_inode(ext2_filsys fs, struct ext2_inode *t,
- struct ext2_inode *f, int hostorder)
-{
- ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) t,
- (struct ext2_inode_large *) f, hostorder,
- sizeof(struct ext2_inode));
-}
-
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/test_io.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/test_io.c
deleted file mode 100644
index 3d40d9a97f..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/test_io.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * test_io.c --- This is the Test I/O interface.
- *
- * Copyright (C) 1996 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * For checking structure magic numbers...
- */
-
-#define EXT2_CHECK_MAGIC(struct, code) \
- if ((struct)->magic != (code)) return (code)
-
-struct test_private_data {
- int magic;
- io_channel real;
- int flags;
- FILE *outfile;
- unsigned long block;
- int read_abort_count, write_abort_count;
- void (*read_blk)(unsigned long block, int count, errcode_t err);
- void (*write_blk)(unsigned long block, int count, errcode_t err);
- void (*set_blksize)(int blksize, errcode_t err);
- void (*write_byte)(unsigned long block, int count, errcode_t err);
-};
-
-static errcode_t test_open(const char *name, int flags, io_channel *channel);
-static errcode_t test_close(io_channel channel);
-static errcode_t test_set_blksize(io_channel channel, int blksize);
-static errcode_t test_read_blk(io_channel channel, unsigned long block,
- int count, void *data);
-static errcode_t test_write_blk(io_channel channel, unsigned long block,
- int count, const void *data);
-static errcode_t test_flush(io_channel channel);
-static errcode_t test_write_byte(io_channel channel, unsigned long offset,
- int count, const void *buf);
-static errcode_t test_set_option(io_channel channel, const char *option,
- const char *arg);
-
-static struct struct_io_manager struct_test_manager = {
- EXT2_ET_MAGIC_IO_MANAGER,
- "Test I/O Manager",
- test_open,
- test_close,
- test_set_blksize,
- test_read_blk,
- test_write_blk,
- test_flush,
- test_write_byte,
- test_set_option
-};
-
-io_manager test_io_manager = &struct_test_manager;
-
-/*
- * These global variable can be set by the test program as
- * necessary *before* calling test_open
- */
-io_manager test_io_backing_manager = 0;
-void (*test_io_cb_read_blk)
- (unsigned long block, int count, errcode_t err) = 0;
-void (*test_io_cb_write_blk)
- (unsigned long block, int count, errcode_t err) = 0;
-void (*test_io_cb_set_blksize)
- (int blksize, errcode_t err) = 0;
-void (*test_io_cb_write_byte)
- (unsigned long block, int count, errcode_t err) = 0;
-
-/*
- * Test flags
- */
-#define TEST_FLAG_READ 0x01
-#define TEST_FLAG_WRITE 0x02
-#define TEST_FLAG_SET_BLKSIZE 0x04
-#define TEST_FLAG_FLUSH 0x08
-#define TEST_FLAG_DUMP 0x10
-#define TEST_FLAG_SET_OPTION 0x20
-
-static void test_dump_block(io_channel channel,
- struct test_private_data *data,
- unsigned long block, const void *buf)
-{
- const unsigned char *cp;
- FILE *f = data->outfile;
- int i;
- unsigned long cksum = 0;
-
- for (i=0, cp = buf; i < channel->block_size; i++, cp++) {
- cksum += *cp;
- }
- fprintf(f, "Contents of block %lu, checksum %08lu:\n", block, cksum);
- for (i=0, cp = buf; i < channel->block_size; i++, cp++) {
- if ((i % 16) == 0)
- fprintf(f, "%04x: ", i);
- fprintf(f, "%02x%c", *cp, ((i % 16) == 15) ? '\n' : ' ');
- }
-}
-
-static void test_abort(io_channel channel, unsigned long block)
-{
- struct test_private_data *data;
- FILE *f;
-
- data = (struct test_private_data *) channel->private_data;
- f = data->outfile;
- test_flush(channel);
-
- fprintf(f, "Aborting due to I/O to block %lu\n", block);
- fflush(f);
- abort();
-}
-
-static errcode_t test_open(const char *name, int flags, io_channel *channel)
-{
- io_channel io = NULL;
- struct test_private_data *data = NULL;
- errcode_t retval;
- char *value;
-
- if (name == 0)
- return EXT2_ET_BAD_DEVICE_NAME;
- retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
- if (retval)
- return retval;
- memset(io, 0, sizeof(struct struct_io_channel));
- io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
- retval = ext2fs_get_mem(sizeof(struct test_private_data), &data);
- if (retval) {
- retval = EXT2_ET_NO_MEMORY;
- goto cleanup;
- }
- io->manager = test_io_manager;
- retval = ext2fs_get_mem(strlen(name)+1, &io->name);
- if (retval)
- goto cleanup;
-
- strcpy(io->name, name);
- io->private_data = data;
- io->block_size = 1024;
- io->read_error = 0;
- io->write_error = 0;
- io->refcount = 1;
-
- memset(data, 0, sizeof(struct test_private_data));
- data->magic = EXT2_ET_MAGIC_TEST_IO_CHANNEL;
- if (test_io_backing_manager) {
- retval = test_io_backing_manager->open(name, flags,
- &data->real);
- if (retval)
- goto cleanup;
- } else
- data->real = 0;
- data->read_blk = test_io_cb_read_blk;
- data->write_blk = test_io_cb_write_blk;
- data->set_blksize = test_io_cb_set_blksize;
- data->write_byte = test_io_cb_write_byte;
-
- data->outfile = NULL;
- if ((value = getenv("TEST_IO_LOGFILE")) != NULL)
- data->outfile = fopen_for_write(value);
- if (!data->outfile)
- data->outfile = stderr;
-
- data->flags = 0;
- if ((value = getenv("TEST_IO_FLAGS")) != NULL)
- data->flags = strtoul(value, NULL, 0);
-
- data->block = 0;
- if ((value = getenv("TEST_IO_BLOCK")) != NULL)
- data->block = strtoul(value, NULL, 0);
-
- data->read_abort_count = 0;
- if ((value = getenv("TEST_IO_READ_ABORT")) != NULL)
- data->read_abort_count = strtoul(value, NULL, 0);
-
- data->write_abort_count = 0;
- if ((value = getenv("TEST_IO_WRITE_ABORT")) != NULL)
- data->write_abort_count = strtoul(value, NULL, 0);
-
- *channel = io;
- return 0;
-
-cleanup:
- ext2fs_free_mem(&io);
- ext2fs_free_mem(&data);
- return retval;
-}
-
-static errcode_t test_close(io_channel channel)
-{
- struct test_private_data *data;
- errcode_t retval = 0;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct test_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
-
- if (--channel->refcount > 0)
- return 0;
-
- if (data->real)
- retval = io_channel_close(data->real);
-
- if (data->outfile && data->outfile != stderr)
- fclose(data->outfile);
-
- ext2fs_free_mem(&channel->private_data);
- ext2fs_free_mem(&channel->name);
- ext2fs_free_mem(&channel);
- return retval;
-}
-
-static errcode_t test_set_blksize(io_channel channel, int blksize)
-{
- struct test_private_data *data;
- errcode_t retval = 0;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct test_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
-
- if (data->real)
- retval = io_channel_set_blksize(data->real, blksize);
- if (data->set_blksize)
- data->set_blksize(blksize, retval);
- if (data->flags & TEST_FLAG_SET_BLKSIZE)
- fprintf(data->outfile,
- "Test_io: set_blksize(%d) returned %s\n",
- blksize, retval ? error_message(retval) : "OK");
- channel->block_size = blksize;
- return retval;
-}
-
-
-static errcode_t test_read_blk(io_channel channel, unsigned long block,
- int count, void *buf)
-{
- struct test_private_data *data;
- errcode_t retval = 0;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct test_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
-
- if (data->real)
- retval = io_channel_read_blk(data->real, block, count, buf);
- if (data->read_blk)
- data->read_blk(block, count, retval);
- if (data->flags & TEST_FLAG_READ)
- fprintf(data->outfile,
- "Test_io: read_blk(%lu, %d) returned %s\n",
- block, count, retval ? error_message(retval) : "OK");
- if (data->block && data->block == block) {
- if (data->flags & TEST_FLAG_DUMP)
- test_dump_block(channel, data, block, buf);
- if (--data->read_abort_count == 0)
- test_abort(channel, block);
- }
- return retval;
-}
-
-static errcode_t test_write_blk(io_channel channel, unsigned long block,
- int count, const void *buf)
-{
- struct test_private_data *data;
- errcode_t retval = 0;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct test_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
-
- if (data->real)
- retval = io_channel_write_blk(data->real, block, count, buf);
- if (data->write_blk)
- data->write_blk(block, count, retval);
- if (data->flags & TEST_FLAG_WRITE)
- fprintf(data->outfile,
- "Test_io: write_blk(%lu, %d) returned %s\n",
- block, count, retval ? error_message(retval) : "OK");
- if (data->block && data->block == block) {
- if (data->flags & TEST_FLAG_DUMP)
- test_dump_block(channel, data, block, buf);
- if (--data->write_abort_count == 0)
- test_abort(channel, block);
- }
- return retval;
-}
-
-static errcode_t test_write_byte(io_channel channel, unsigned long offset,
- int count, const void *buf)
-{
- struct test_private_data *data;
- errcode_t retval = 0;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct test_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
-
- if (data->real && data->real->manager->write_byte)
- retval = io_channel_write_byte(data->real, offset, count, buf);
- if (data->write_byte)
- data->write_byte(offset, count, retval);
- if (data->flags & TEST_FLAG_WRITE)
- fprintf(data->outfile,
- "Test_io: write_byte(%lu, %d) returned %s\n",
- offset, count, retval ? error_message(retval) : "OK");
- return retval;
-}
-
-/*
- * Flush data buffers to disk.
- */
-static errcode_t test_flush(io_channel channel)
-{
- struct test_private_data *data;
- errcode_t retval = 0;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct test_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
-
- if (data->real)
- retval = io_channel_flush(data->real);
-
- if (data->flags & TEST_FLAG_FLUSH)
- fprintf(data->outfile, "Test_io: flush() returned %s\n",
- retval ? error_message(retval) : "OK");
-
- return retval;
-}
-
-static errcode_t test_set_option(io_channel channel, const char *option,
- const char *arg)
-{
- struct test_private_data *data;
- errcode_t retval = 0;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct test_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
-
-
- if (data->flags & TEST_FLAG_SET_OPTION)
- fprintf(data->outfile, "Test_io: set_option(%s, %s) ",
- option, arg);
- if (data->real && data->real->manager->set_option) {
- retval = (data->real->manager->set_option)(data->real,
- option, arg);
- if (data->flags & TEST_FLAG_SET_OPTION)
- fprintf(data->outfile, "returned %s\n",
- retval ? error_message(retval) : "OK");
- } else {
- if (data->flags & TEST_FLAG_SET_OPTION)
- fprintf(data->outfile, "not implemented\n");
- }
- return retval;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/unix_io.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/unix_io.c
deleted file mode 100644
index 8dde4c7322..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/unix_io.c
+++ /dev/null
@@ -1,703 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * unix_io.c --- This is the Unix (well, really POSIX) implementation
- * of the I/O manager.
- *
- * Implements a one-block write-through cache.
- *
- * Includes support for Windows NT support under Cygwin.
- *
- * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- * 2002 by Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#ifdef __linux__
-#include <sys/utsname.h>
-#endif
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#include <sys/resource.h>
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * For checking structure magic numbers...
- */
-
-#define EXT2_CHECK_MAGIC(struct, code) \
- if ((struct)->magic != (code)) return (code)
-
-struct unix_cache {
- char *buf;
- unsigned long block;
- int access_time;
- unsigned dirty:1;
- unsigned in_use:1;
-};
-
-#define CACHE_SIZE 8
-#define WRITE_DIRECT_SIZE 4 /* Must be smaller than CACHE_SIZE */
-#define READ_DIRECT_SIZE 4 /* Should be smaller than CACHE_SIZE */
-
-struct unix_private_data {
- int magic;
- int dev;
- int flags;
- int access_time;
- ext2_loff_t offset;
- struct unix_cache cache[CACHE_SIZE];
-};
-
-static errcode_t unix_open(const char *name, int flags, io_channel *channel);
-static errcode_t unix_close(io_channel channel);
-static errcode_t unix_set_blksize(io_channel channel, int blksize);
-static errcode_t unix_read_blk(io_channel channel, unsigned long block,
- int count, void *data);
-static errcode_t unix_write_blk(io_channel channel, unsigned long block,
- int count, const void *data);
-static errcode_t unix_flush(io_channel channel);
-static errcode_t unix_write_byte(io_channel channel, unsigned long offset,
- int size, const void *data);
-static errcode_t unix_set_option(io_channel channel, const char *option,
- const char *arg);
-
-static void reuse_cache(io_channel channel, struct unix_private_data *data,
- struct unix_cache *cache, unsigned long block);
-
-/* __FreeBSD_kernel__ is defined by GNU/kFreeBSD - the FreeBSD kernel
- * does not know buffered block devices - everything is raw. */
-#if defined(__CYGWIN__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-#define NEED_BOUNCE_BUFFER
-#else
-#undef NEED_BOUNCE_BUFFER
-#endif
-
-static struct struct_io_manager struct_unix_manager = {
- EXT2_ET_MAGIC_IO_MANAGER,
- "Unix I/O Manager",
- unix_open,
- unix_close,
- unix_set_blksize,
- unix_read_blk,
- unix_write_blk,
- unix_flush,
-#ifdef NEED_BOUNCE_BUFFER
- 0,
-#else
- unix_write_byte,
-#endif
- unix_set_option
-};
-
-io_manager unix_io_manager = &struct_unix_manager;
-
-/*
- * Here are the raw I/O functions
- */
-#ifndef NEED_BOUNCE_BUFFER
-static errcode_t raw_read_blk(io_channel channel,
- struct unix_private_data *data,
- unsigned long block,
- int count, void *buf)
-{
- errcode_t retval;
- ssize_t size;
- ext2_loff_t location;
- int actual = 0;
-
- size = (count < 0) ? -count : count * channel->block_size;
- location = ((ext2_loff_t) block * channel->block_size) + data->offset;
- if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
- retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
- goto error_out;
- }
- actual = read(data->dev, buf, size);
- if (actual != size) {
- if (actual < 0)
- actual = 0;
- retval = EXT2_ET_SHORT_READ;
- goto error_out;
- }
- return 0;
-
-error_out:
- memset((char *) buf+actual, 0, size-actual);
- if (channel->read_error)
- retval = (channel->read_error)(channel, block, count, buf,
- size, actual, retval);
- return retval;
-}
-#else /* NEED_BOUNCE_BUFFER */
-/*
- * Windows and FreeBSD block devices only allow sector alignment IO in offset and size
- */
-static errcode_t raw_read_blk(io_channel channel,
- struct unix_private_data *data,
- unsigned long block,
- int count, void *buf)
-{
- errcode_t retval;
- size_t size, alignsize, fragment;
- ext2_loff_t location;
- int total = 0, actual;
-#define BLOCKALIGN 512
- char sector[BLOCKALIGN];
-
- size = (count < 0) ? -count : count * channel->block_size;
- location = ((ext2_loff_t) block * channel->block_size) + data->offset;
-#ifdef DEBUG
- printf("count=%d, size=%d, block=%d, blk_size=%d, location=%lx\n",
- count, size, block, channel->block_size, location);
-#endif
- if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
- retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
- goto error_out;
- }
- fragment = size % BLOCKALIGN;
- alignsize = size - fragment;
- if (alignsize) {
- actual = read(data->dev, buf, alignsize);
- if (actual != alignsize)
- goto short_read;
- }
- if (fragment) {
- actual = read(data->dev, sector, BLOCKALIGN);
- if (actual != BLOCKALIGN)
- goto short_read;
- memcpy(buf+alignsize, sector, fragment);
- }
- return 0;
-
-short_read:
- if (actual>0)
- total += actual;
- retval = EXT2_ET_SHORT_READ;
-
-error_out:
- memset((char *) buf+total, 0, size-actual);
- if (channel->read_error)
- retval = (channel->read_error)(channel, block, count, buf,
- size, actual, retval);
- return retval;
-}
-#endif
-
-static errcode_t raw_write_blk(io_channel channel,
- struct unix_private_data *data,
- unsigned long block,
- int count, const void *buf)
-{
- ssize_t size;
- ext2_loff_t location;
- int actual = 0;
- errcode_t retval;
-
- if (count == 1)
- size = channel->block_size;
- else {
- if (count < 0)
- size = -count;
- else
- size = count * channel->block_size;
- }
-
- location = ((ext2_loff_t) block * channel->block_size) + data->offset;
- if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
- retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
- goto error_out;
- }
-
- actual = write(data->dev, buf, size);
- if (actual != size) {
- retval = EXT2_ET_SHORT_WRITE;
- goto error_out;
- }
- return 0;
-
-error_out:
- if (channel->write_error)
- retval = (channel->write_error)(channel, block, count, buf,
- size, actual, retval);
- return retval;
-}
-
-
-/*
- * Here we implement the cache functions
- */
-
-/* Allocate the cache buffers */
-static errcode_t alloc_cache(io_channel channel,
- struct unix_private_data *data)
-{
- errcode_t retval;
- struct unix_cache *cache;
- int i;
-
- data->access_time = 0;
- for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
- cache->block = 0;
- cache->access_time = 0;
- cache->dirty = 0;
- cache->in_use = 0;
- if ((retval = ext2fs_get_mem(channel->block_size,
- &cache->buf)))
- return retval;
- }
- return 0;
-}
-
-/* Free the cache buffers */
-static void free_cache(struct unix_private_data *data)
-{
- struct unix_cache *cache;
- int i;
-
- data->access_time = 0;
- for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
- cache->block = 0;
- cache->access_time = 0;
- cache->dirty = 0;
- cache->in_use = 0;
- ext2fs_free_mem(&cache->buf);
- cache->buf = 0;
- }
-}
-
-#ifndef NO_IO_CACHE
-/*
- * Try to find a block in the cache. If the block is not found, and
- * eldest is a non-zero pointer, then fill in eldest with the cache
- * entry to that should be reused.
- */
-static struct unix_cache *find_cached_block(struct unix_private_data *data,
- unsigned long block,
- struct unix_cache **eldest)
-{
- struct unix_cache *cache, *unused_cache, *oldest_cache;
- int i;
-
- unused_cache = oldest_cache = 0;
- for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
- if (!cache->in_use) {
- if (!unused_cache)
- unused_cache = cache;
- continue;
- }
- if (cache->block == block) {
- cache->access_time = ++data->access_time;
- return cache;
- }
- if (!oldest_cache ||
- (cache->access_time < oldest_cache->access_time))
- oldest_cache = cache;
- }
- if (eldest)
- *eldest = (unused_cache) ? unused_cache : oldest_cache;
- return 0;
-}
-
-/*
- * Reuse a particular cache entry for another block.
- */
-static void reuse_cache(io_channel channel, struct unix_private_data *data,
- struct unix_cache *cache, unsigned long block)
-{
- if (cache->dirty && cache->in_use)
- raw_write_blk(channel, data, cache->block, 1, cache->buf);
-
- cache->in_use = 1;
- cache->dirty = 0;
- cache->block = block;
- cache->access_time = ++data->access_time;
-}
-
-/*
- * Flush all of the blocks in the cache
- */
-static errcode_t flush_cached_blocks(io_channel channel,
- struct unix_private_data *data,
- int invalidate)
-
-{
- struct unix_cache *cache;
- errcode_t retval, retval2;
- int i;
-
- retval2 = 0;
- for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
- if (!cache->in_use)
- continue;
-
- if (invalidate)
- cache->in_use = 0;
-
- if (!cache->dirty)
- continue;
-
- retval = raw_write_blk(channel, data,
- cache->block, 1, cache->buf);
- if (retval)
- retval2 = retval;
- else
- cache->dirty = 0;
- }
- return retval2;
-}
-#endif /* NO_IO_CACHE */
-
-static errcode_t unix_open(const char *name, int flags, io_channel *channel)
-{
- io_channel io = NULL;
- struct unix_private_data *data = NULL;
- errcode_t retval;
- int open_flags;
- struct stat st;
-#ifdef __linux__
- struct utsname ut;
-#endif
-
- if (name == 0)
- return EXT2_ET_BAD_DEVICE_NAME;
- retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
- if (retval)
- return retval;
- memset(io, 0, sizeof(struct struct_io_channel));
- io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
- retval = ext2fs_get_mem(sizeof(struct unix_private_data), &data);
- if (retval)
- goto cleanup;
-
- io->manager = unix_io_manager;
- retval = ext2fs_get_mem(strlen(name)+1, &io->name);
- if (retval)
- goto cleanup;
-
- strcpy(io->name, name);
- io->private_data = data;
- io->block_size = 1024;
- io->read_error = 0;
- io->write_error = 0;
- io->refcount = 1;
-
- memset(data, 0, sizeof(struct unix_private_data));
- data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL;
-
- if ((retval = alloc_cache(io, data)))
- goto cleanup;
-
- open_flags = (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY;
-#ifdef CONFIG_LFS
- data->dev = open64(io->name, open_flags);
-#else
- data->dev = open(io->name, open_flags);
-#endif
- if (data->dev < 0) {
- retval = errno;
- goto cleanup;
- }
-
-#ifdef __linux__
-#undef RLIM_INFINITY
-#if (defined(__alpha__) || (defined(__sparc__) && (__WORDSIZE == 32)) || (defined(__mips__) && (_MIPS_SZLONG == 32)))
-#define RLIM_INFINITY ((unsigned long)(~0UL>>1))
-#else
-#define RLIM_INFINITY (~0UL)
-#endif
- /*
- * Work around a bug in 2.4.10-2.4.18 kernels where writes to
- * block devices are wrongly getting hit by the filesize
- * limit. This workaround isn't perfect, since it won't work
- * if glibc wasn't built against 2.2 header files. (Sigh.)
- *
- */
- if ((flags & IO_FLAG_RW) &&
- (uname(&ut) == 0) &&
- ((ut.release[0] == '2') && (ut.release[1] == '.') &&
- (ut.release[2] == '4') && (ut.release[3] == '.') &&
- (ut.release[4] == '1') && (ut.release[5] >= '0') &&
- (ut.release[5] < '8')) &&
- (fstat(data->dev, &st) == 0) &&
- (S_ISBLK(st.st_mode))) {
- struct rlimit rlim;
-
- rlim.rlim_cur = rlim.rlim_max = (unsigned long) RLIM_INFINITY;
- setrlimit(RLIMIT_FSIZE, &rlim);
- getrlimit(RLIMIT_FSIZE, &rlim);
- if (((unsigned long) rlim.rlim_cur) <
- ((unsigned long) rlim.rlim_max)) {
- rlim.rlim_cur = rlim.rlim_max;
- setrlimit(RLIMIT_FSIZE, &rlim);
- }
- }
-#endif
- *channel = io;
- return 0;
-
-cleanup:
- if (data) {
- free_cache(data);
- ext2fs_free_mem(&data);
- }
- ext2fs_free_mem(&io);
- return retval;
-}
-
-static errcode_t unix_close(io_channel channel)
-{
- struct unix_private_data *data;
- errcode_t retval = 0;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct unix_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
-
- if (--channel->refcount > 0)
- return 0;
-
-#ifndef NO_IO_CACHE
- retval = flush_cached_blocks(channel, data, 0);
-#endif
-
- if (close(data->dev) < 0)
- retval = errno;
- free_cache(data);
-
- ext2fs_free_mem(&channel->private_data);
- ext2fs_free_mem(&channel->name);
- ext2fs_free_mem(&channel);
- return retval;
-}
-
-static errcode_t unix_set_blksize(io_channel channel, int blksize)
-{
- struct unix_private_data *data;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct unix_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
-
- if (channel->block_size != blksize) {
-#ifndef NO_IO_CACHE
- if ((retval = flush_cached_blocks(channel, data, 0)))
- return retval;
-#endif
-
- channel->block_size = blksize;
- free_cache(data);
- if ((retval = alloc_cache(channel, data)))
- return retval;
- }
- return 0;
-}
-
-
-static errcode_t unix_read_blk(io_channel channel, unsigned long block,
- int count, void *buf)
-{
- struct unix_private_data *data;
- struct unix_cache *cache, *reuse[READ_DIRECT_SIZE];
- errcode_t retval;
- char *cp;
- int i, j;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct unix_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
-
-#ifdef NO_IO_CACHE
- return raw_read_blk(channel, data, block, count, buf);
-#else
- /*
- * If we're doing an odd-sized read or a very large read,
- * flush out the cache and then do a direct read.
- */
- if (count < 0 || count > WRITE_DIRECT_SIZE) {
- if ((retval = flush_cached_blocks(channel, data, 0)))
- return retval;
- return raw_read_blk(channel, data, block, count, buf);
- }
-
- cp = buf;
- while (count > 0) {
- /* If it's in the cache, use it! */
- if ((cache = find_cached_block(data, block, &reuse[0]))) {
-#ifdef DEBUG
- printf("Using cached block %d\n", block);
-#endif
- memcpy(cp, cache->buf, channel->block_size);
- count--;
- block++;
- cp += channel->block_size;
- continue;
- }
- /*
- * Find the number of uncached blocks so we can do a
- * single read request
- */
- for (i=1; i < count; i++)
- if (find_cached_block(data, block+i, &reuse[i]))
- break;
-#ifdef DEBUG
- printf("Reading %d blocks starting at %d\n", i, block);
-#endif
- if ((retval = raw_read_blk(channel, data, block, i, cp)))
- return retval;
-
- /* Save the results in the cache */
- for (j=0; j < i; j++) {
- count--;
- cache = reuse[j];
- reuse_cache(channel, data, cache, block++);
- memcpy(cache->buf, cp, channel->block_size);
- cp += channel->block_size;
- }
- }
- return 0;
-#endif /* NO_IO_CACHE */
-}
-
-static errcode_t unix_write_blk(io_channel channel, unsigned long block,
- int count, const void *buf)
-{
- struct unix_private_data *data;
- struct unix_cache *cache, *reuse;
- errcode_t retval = 0;
- const char *cp;
- int writethrough;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct unix_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
-
-#ifdef NO_IO_CACHE
- return raw_write_blk(channel, data, block, count, buf);
-#else
- /*
- * If we're doing an odd-sized write or a very large write,
- * flush out the cache completely and then do a direct write.
- */
- if (count < 0 || count > WRITE_DIRECT_SIZE) {
- if ((retval = flush_cached_blocks(channel, data, 1)))
- return retval;
- return raw_write_blk(channel, data, block, count, buf);
- }
-
- /*
- * For a moderate-sized multi-block write, first force a write
- * if we're in write-through cache mode, and then fill the
- * cache with the blocks.
- */
- writethrough = channel->flags & CHANNEL_FLAGS_WRITETHROUGH;
- if (writethrough)
- retval = raw_write_blk(channel, data, block, count, buf);
-
- cp = buf;
- while (count > 0) {
- cache = find_cached_block(data, block, &reuse);
- if (!cache) {
- cache = reuse;
- reuse_cache(channel, data, cache, block);
- }
- memcpy(cache->buf, cp, channel->block_size);
- cache->dirty = !writethrough;
- count--;
- block++;
- cp += channel->block_size;
- }
- return retval;
-#endif /* NO_IO_CACHE */
-}
-
-static errcode_t unix_write_byte(io_channel channel, unsigned long offset,
- int size, const void *buf)
-{
- struct unix_private_data *data;
- errcode_t retval = 0;
- ssize_t actual;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct unix_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
-
-#ifndef NO_IO_CACHE
- /*
- * Flush out the cache completely
- */
- if ((retval = flush_cached_blocks(channel, data, 1)))
- return retval;
-#endif
-
- if (lseek(data->dev, offset + data->offset, SEEK_SET) < 0)
- return errno;
-
- actual = write(data->dev, buf, size);
- if (actual != size)
- return EXT2_ET_SHORT_WRITE;
-
- return 0;
-}
-
-/*
- * Flush data buffers to disk.
- */
-static errcode_t unix_flush(io_channel channel)
-{
- struct unix_private_data *data;
- errcode_t retval = 0;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct unix_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
-
-#ifndef NO_IO_CACHE
- retval = flush_cached_blocks(channel, data, 0);
-#endif
- fsync(data->dev);
- return retval;
-}
-
-static errcode_t unix_set_option(io_channel channel, const char *option,
- const char *arg)
-{
- struct unix_private_data *data;
- unsigned long tmp;
- char *end;
-
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- data = (struct unix_private_data *) channel->private_data;
- EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
-
- if (!strcmp(option, "offset")) {
- if (!arg)
- return EXT2_ET_INVALID_ARGUMENT;
-
- tmp = strtoul(arg, &end, 0);
- if (*end)
- return EXT2_ET_INVALID_ARGUMENT;
- data->offset = tmp;
- return 0;
- }
- return EXT2_ET_INVALID_ARGUMENT;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/unlink.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/unlink.c
deleted file mode 100644
index 71a9ffcb9b..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/unlink.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * unlink.c --- delete links in a ext2fs directory
- *
- * Copyright (C) 1993, 1994, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-struct link_struct {
- const char *name;
- int namelen;
- ext2_ino_t inode;
- int flags;
- struct ext2_dir_entry *prev;
- int done;
-};
-
-#ifdef __TURBOC__
-# pragma argsused
-#endif
-static int unlink_proc(struct ext2_dir_entry *dirent,
- int offset EXT2FS_ATTR((unused)),
- int blocksize EXT2FS_ATTR((unused)),
- char *buf EXT2FS_ATTR((unused)),
- void *priv_data)
-{
- struct link_struct *ls = (struct link_struct *) priv_data;
- struct ext2_dir_entry *prev;
-
- prev = ls->prev;
- ls->prev = dirent;
-
- if (ls->name) {
- if ((dirent->name_len & 0xFF) != ls->namelen)
- return 0;
- if (strncmp(ls->name, dirent->name, dirent->name_len & 0xFF))
- return 0;
- }
- if (ls->inode) {
- if (dirent->inode != ls->inode)
- return 0;
- } else {
- if (!dirent->inode)
- return 0;
- }
-
- if (prev)
- prev->rec_len += dirent->rec_len;
- else
- dirent->inode = 0;
- ls->done++;
- return DIRENT_ABORT|DIRENT_CHANGED;
-}
-
-#ifdef __TURBOC__
- #pragma argsused
-#endif
-errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir,
- const char *name, ext2_ino_t ino,
- int flags EXT2FS_ATTR((unused)))
-{
- errcode_t retval;
- struct link_struct ls;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!name && !ino)
- return EXT2_ET_INVALID_ARGUMENT;
-
- if (!(fs->flags & EXT2_FLAG_RW))
- return EXT2_ET_RO_FILSYS;
-
- ls.name = name;
- ls.namelen = name ? strlen(name) : 0;
- ls.inode = ino;
- ls.flags = 0;
- ls.done = 0;
- ls.prev = 0;
-
- retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY,
- 0, unlink_proc, &ls);
- if (retval)
- return retval;
-
- return (ls.done) ? 0 : EXT2_ET_DIR_NO_SPACE;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/valid_blk.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/valid_blk.c
deleted file mode 100644
index 8ed77ae2ac..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/valid_blk.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * valid_blk.c --- does the inode have valid blocks?
- *
- * Copyright 1997 by Theodore Ts'o
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- *
- */
-
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <string.h>
-#include <time.h>
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-/*
- * This function returns 1 if the inode's block entries actually
- * contain block entries.
- */
-int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode)
-{
- /*
- * Only directories, regular files, and some symbolic links
- * have valid block entries.
- */
- if (!LINUX_S_ISDIR(inode->i_mode) && !LINUX_S_ISREG(inode->i_mode) &&
- !LINUX_S_ISLNK(inode->i_mode))
- return 0;
-
- /*
- * If the symbolic link is a "fast symlink", then the symlink
- * target is stored in the block entries.
- */
- if (LINUX_S_ISLNK (inode->i_mode)) {
- if (inode->i_file_acl == 0) {
- /* With no EA block, we can rely on i_blocks */
- if (inode->i_blocks == 0)
- return 0;
- } else {
- /* With an EA block, life gets more tricky */
- if (inode->i_size >= EXT2_N_BLOCKS*4)
- return 1; /* definitely using i_block[] */
- if (inode->i_size > 4 && inode->i_block[1] == 0)
- return 1; /* definitely using i_block[] */
- return 0; /* Probably a fast symlink */
- }
- }
- return 1;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/version.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/version.c
deleted file mode 100644
index d2981e867e..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/version.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * version.c --- Return the version of the ext2 library
- *
- * Copyright (C) 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-static const char *lib_version = E2FSPROGS_VERSION;
-static const char *lib_date = E2FSPROGS_DATE;
-
-int ext2fs_parse_version_string(const char *ver_string)
-{
- const char *cp;
- int version = 0;
-
- for (cp = ver_string; *cp; cp++) {
- if (*cp == '.')
- continue;
- if (!isdigit(*cp))
- break;
- version = (version * 10) + (*cp - '0');
- }
- return version;
-}
-
-
-int ext2fs_get_library_version(const char **ver_string,
- const char **date_string)
-{
- if (ver_string)
- *ver_string = lib_version;
- if (date_string)
- *date_string = lib_date;
-
- return ext2fs_parse_version_string(lib_version);
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/write_bb_file.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/write_bb_file.c
deleted file mode 100644
index 5b19eefa09..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/write_bb_file.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * write_bb_file.c --- write a list of bad blocks to a FILE *
- *
- * Copyright (C) 1994, 1995 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list,
- unsigned int flags EXT2FS_ATTR((unused)),
- FILE *f)
-{
- badblocks_iterate bb_iter;
- blk_t blk;
- errcode_t retval;
-
- retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter);
- if (retval)
- return retval;
-
- while (ext2fs_badblocks_list_iterate(bb_iter, &blk)) {
- fprintf(f, "%d\n", blk);
- }
- ext2fs_badblocks_list_iterate_end(bb_iter);
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/fsck.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/fsck.c
deleted file mode 100644
index 3a0743bb12..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/fsck.c
+++ /dev/null
@@ -1,1376 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * pfsck --- A generic, parallelizing front-end for the fsck program.
- * It will automatically try to run fsck programs in parallel if the
- * devices are on separate spindles. It is based on the same ideas as
- * the generic front end for fsck by David Engel and Fred van Kempen,
- * but it has been completely rewritten from scratch to support
- * parallel execution.
- *
- * Written by Theodore Ts'o, <tytso@mit.edu>
- *
- * Miquel van Smoorenburg (miquels@drinkel.ow.org) 20-Oct-1994:
- * o Changed -t fstype to behave like with mount when -A (all file
- * systems) or -M (like mount) is specified.
- * o fsck looks if it can find the fsck.type program to decide
- * if it should ignore the fs type. This way more fsck programs
- * can be added without changing this front-end.
- * o -R flag skip root file system.
- *
- * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- * 2001, 2002, 2003, 2004, 2005 by Theodore Ts'o.
- *
- * Licensed under GPLv2, see file LICENSE in this source tree.
- */
-
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <limits.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#include <time.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <paths.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-
-#include "fsck.h"
-#include "blkid/blkid.h"
-
-#include "e2fsbb.h"
-
-#include "libbb.h"
-
-#ifndef _PATH_MNTTAB
-#define _PATH_MNTTAB "/etc/fstab"
-#endif
-
-/*
- * fsck.h
- */
-
-#ifndef DEFAULT_FSTYPE
-#define DEFAULT_FSTYPE "ext2"
-#endif
-
-#define MAX_DEVICES 32
-#define MAX_ARGS 32
-
-/*
- * Internal structure for mount tabel entries.
- */
-
-struct fs_info {
- char *device;
- char *mountpt;
- char *type;
- char *opts;
- int freq;
- int passno;
- int flags;
- struct fs_info *next;
-};
-
-#define FLAG_DONE 1
-#define FLAG_PROGRESS 2
-
-/*
- * Structure to allow exit codes to be stored
- */
-struct fsck_instance {
- int pid;
- int flags;
- int exit_status;
- time_t start_time;
- char * prog;
- char * type;
- char * device;
- char * base_device;
- struct fsck_instance *next;
-};
-
-/*
- * base_device.c
- *
- * Return the "base device" given a particular device; this is used to
- * assure that we only fsck one partition on a particular drive at any
- * one time. Otherwise, the disk heads will be seeking all over the
- * place. If the base device cannot be determined, return NULL.
- *
- * The base_device() function returns an allocated string which must
- * be freed.
- *
- */
-
-
-#ifdef CONFIG_FEATURE_DEVFS
-/*
- * Required for the uber-silly devfs /dev/ide/host1/bus2/target3/lun3
- * pathames.
- */
-static const char *const devfs_hier[] = {
- "host", "bus", "target", "lun", 0
-};
-#endif
-
-static char *base_device(const char *device)
-{
- char *str, *cp;
-#ifdef CONFIG_FEATURE_DEVFS
- const char *const *hier;
- const char *disk;
- int len;
-#endif
-
- cp = str = xstrdup(device);
-
- /* Skip over /dev/; if it's not present, give up. */
- if (strncmp(cp, "/dev/", 5) != 0)
- goto errout;
- cp += 5;
-
- /*
- * For md devices, we treat them all as if they were all
- * on one disk, since we don't know how to parallelize them.
- */
- if (cp[0] == 'm' && cp[1] == 'd') {
- *(cp+2) = 0;
- return str;
- }
-
- /* Handle DAC 960 devices */
- if (strncmp(cp, "rd/", 3) == 0) {
- cp += 3;
- if (cp[0] != 'c' || cp[2] != 'd' ||
- !isdigit(cp[1]) || !isdigit(cp[3]))
- goto errout;
- *(cp+4) = 0;
- return str;
- }
-
- /* Now let's handle /dev/hd* and /dev/sd* devices.... */
- if ((cp[0] == 'h' || cp[0] == 's') && (cp[1] == 'd')) {
- cp += 2;
- /* If there's a single number after /dev/hd, skip it */
- if (isdigit(*cp))
- cp++;
- /* What follows must be an alpha char, or give up */
- if (!isalpha(*cp))
- goto errout;
- *(cp + 1) = 0;
- return str;
- }
-
-#ifdef CONFIG_FEATURE_DEVFS
- /* Now let's handle devfs (ugh) names */
- len = 0;
- if (strncmp(cp, "ide/", 4) == 0)
- len = 4;
- if (strncmp(cp, "scsi/", 5) == 0)
- len = 5;
- if (len) {
- cp += len;
- /*
- * Now we proceed down the expected devfs hierarchy.
- * i.e., .../host1/bus2/target3/lun4/...
- * If we don't find the expected token, followed by
- * some number of digits at each level, abort.
- */
- for (hier = devfs_hier; *hier; hier++) {
- len = strlen(*hier);
- if (strncmp(cp, *hier, len) != 0)
- goto errout;
- cp += len;
- while (*cp != '/' && *cp != 0) {
- if (!isdigit(*cp))
- goto errout;
- cp++;
- }
- cp++;
- }
- *(cp - 1) = 0;
- return str;
- }
-
- /* Now handle devfs /dev/disc or /dev/disk names */
- disk = 0;
- if (strncmp(cp, "discs/", 6) == 0)
- disk = "disc";
- else if (strncmp(cp, "disks/", 6) == 0)
- disk = "disk";
- if (disk) {
- cp += 6;
- if (strncmp(cp, disk, 4) != 0)
- goto errout;
- cp += 4;
- while (*cp != '/' && *cp != 0) {
- if (!isdigit(*cp))
- goto errout;
- cp++;
- }
- *cp = 0;
- return str;
- }
-#endif
-
-errout:
- free(str);
- return NULL;
-}
-
-
-static const char *const ignored_types[] = {
- "ignore",
- "iso9660",
- "nfs",
- "proc",
- "sw",
- "swap",
- "tmpfs",
- "devpts",
- NULL
-};
-
-static const char *const really_wanted[] = {
- "minix",
- "ext2",
- "ext3",
- "jfs",
- "reiserfs",
- "xiafs",
- "xfs",
- NULL
-};
-
-#define BASE_MD "/dev/md"
-
-/*
- * Global variables for options
- */
-static char *devices[MAX_DEVICES];
-static char *args[MAX_ARGS];
-static int num_devices, num_args;
-
-static int verbose;
-static int doall;
-static int noexecute;
-static int serialize;
-static int skip_root;
-static int like_mount;
-static int notitle;
-static int parallel_root;
-static int progress;
-static int progress_fd;
-static int force_all_parallel;
-static int num_running;
-static int max_running;
-static volatile int cancel_requested;
-static int kill_sent;
-static char *fstype;
-static struct fs_info *filesys_info, *filesys_last;
-static struct fsck_instance *instance_list;
-static char *fsck_path;
-static blkid_cache cache;
-
-static char *string_copy(const char *s)
-{
- char *ret;
-
- if (!s)
- return 0;
- ret = xstrdup(s);
- return ret;
-}
-
-static int string_to_int(const char *s)
-{
- long l;
- char *p;
-
- l = strtol(s, &p, 0);
- if (*p || l == LONG_MIN || l == LONG_MAX || l < 0 || l > INT_MAX)
- return -1;
- else
- return (int) l;
-}
-
-static char *skip_over_blank(char *cp)
-{
- while (*cp && isspace(*cp))
- cp++;
- return cp;
-}
-
-static char *skip_over_word(char *cp)
-{
- while (*cp && !isspace(*cp))
- cp++;
- return cp;
-}
-
-static void strip_line(char *line)
-{
- char *p;
-
- while (*line) {
- p = line + strlen(line) - 1;
- if ((*p == '\n') || (*p == '\r'))
- *p = 0;
- else
- break;
- }
-}
-
-static char *parse_word(char **buf)
-{
- char *word, *next;
-
- word = *buf;
- if (*word == 0)
- return 0;
-
- word = skip_over_blank(word);
- next = skip_over_word(word);
- if (*next)
- *next++ = 0;
- *buf = next;
- return word;
-}
-
-static void parse_escape(char *word)
-{
- char *q, c;
- const char *p;
-
- if (!word)
- return;
-
- strcpy_and_process_escape_sequences(word, word);
-}
-
-static void free_instance(struct fsck_instance *i)
-{
- if (i->prog)
- free(i->prog);
- if (i->device)
- free(i->device);
- if (i->base_device)
- free(i->base_device);
- free(i);
-}
-
-static struct fs_info *create_fs_device(const char *device, const char *mntpnt,
- const char *type, const char *opts,
- int freq, int passno)
-{
- struct fs_info *fs;
-
- fs = xmalloc(sizeof(struct fs_info));
-
- fs->device = string_copy(device);
- fs->mountpt = string_copy(mntpnt);
- fs->type = string_copy(type);
- fs->opts = string_copy(opts ? opts : "");
- fs->freq = freq;
- fs->passno = passno;
- fs->flags = 0;
- fs->next = NULL;
-
- if (!filesys_info)
- filesys_info = fs;
- else
- filesys_last->next = fs;
- filesys_last = fs;
-
- return fs;
-}
-
-
-
-static int parse_fstab_line(char *line, struct fs_info **ret_fs)
-{
- char *dev, *device, *mntpnt, *type, *opts, *freq, *passno, *cp;
- struct fs_info *fs;
-
- *ret_fs = 0;
- strip_line(line);
- if ((cp = strchr(line, '#')))
- *cp = 0; /* Ignore everything after the comment char */
- cp = line;
-
- device = parse_word(&cp);
- mntpnt = parse_word(&cp);
- type = parse_word(&cp);
- opts = parse_word(&cp);
- freq = parse_word(&cp);
- passno = parse_word(&cp);
-
- if (!device)
- return 0; /* Allow blank lines */
-
- if (!mntpnt || !type)
- return -1;
-
- parse_escape(device);
- parse_escape(mntpnt);
- parse_escape(type);
- parse_escape(opts);
- parse_escape(freq);
- parse_escape(passno);
-
- dev = blkid_get_devname(cache, device, NULL);
- if (dev)
- device = dev;
-
- if (strchr(type, ','))
- type = 0;
-
- fs = create_fs_device(device, mntpnt, type ? type : "auto", opts,
- freq ? atoi(freq) : -1,
- passno ? atoi(passno) : -1);
- if (dev)
- free(dev);
-
- if (!fs)
- return -1;
- *ret_fs = fs;
- return 0;
-}
-
-static void interpret_type(struct fs_info *fs)
-{
- char *t;
-
- if (strcmp(fs->type, "auto") != 0)
- return;
- t = blkid_get_tag_value(cache, "TYPE", fs->device);
- if (t) {
- free(fs->type);
- fs->type = t;
- }
-}
-
-/*
- * Load the filesystem database from /etc/fstab
- */
-static void load_fs_info(const char *filename)
-{
- FILE *f;
- char buf[1024];
- int lineno = 0;
- int old_fstab = 1;
- struct fs_info *fs;
-
- if ((f = fopen_or_warn(filename, "r")) == NULL) {
- return;
- }
- while (!feof(f)) {
- lineno++;
- if (!fgets(buf, sizeof(buf), f))
- break;
- buf[sizeof(buf)-1] = 0;
- if (parse_fstab_line(buf, &fs) < 0) {
- bb_error_msg("WARNING: bad format "
- "on line %d of %s\n", lineno, filename);
- continue;
- }
- if (!fs)
- continue;
- if (fs->passno < 0)
- fs->passno = 0;
- else
- old_fstab = 0;
- }
-
- fclose(f);
-
- if (old_fstab) {
- fputs("\007\007\007"
- "WARNING: Your /etc/fstab does not contain the fsck passno\n"
- " field. I will kludge around things for you, but you\n"
- " should fix your /etc/fstab file as soon as you can.\n\n", stderr);
-
- for (fs = filesys_info; fs; fs = fs->next) {
- fs->passno = 1;
- }
- }
-}
-
-/* Lookup filesys in /etc/fstab and return the corresponding entry. */
-static struct fs_info *lookup(char *filesys)
-{
- struct fs_info *fs;
-
- /* No filesys name given. */
- if (filesys == NULL)
- return NULL;
-
- for (fs = filesys_info; fs; fs = fs->next) {
- if (!strcmp(filesys, fs->device) ||
- (fs->mountpt && !strcmp(filesys, fs->mountpt)))
- break;
- }
-
- return fs;
-}
-
-/* Find fsck program for a given fs type. */
-static char *find_fsck(char *type)
-{
- char *s;
- const char *tpl;
- char *p = string_copy(fsck_path);
- struct stat st;
-
- /* Are we looking for a program or just a type? */
- tpl = (strncmp(type, "fsck.", 5) ? "%s/fsck.%s" : "%s/%s");
-
- for (s = strtok(p, ":"); s; s = strtok(NULL, ":")) {
- s = xasprintf(tpl, s, type);
- if (stat(s, &st) == 0) break;
- free(s);
- }
- free(p);
- return s;
-}
-
-static int progress_active(void)
-{
- struct fsck_instance *inst;
-
- for (inst = instance_list; inst; inst = inst->next) {
- if (inst->flags & FLAG_DONE)
- continue;
- if (inst->flags & FLAG_PROGRESS)
- return 1;
- }
- return 0;
-}
-
-/*
- * Execute a particular fsck program, and link it into the list of
- * child processes we are waiting for.
- */
-static int execute(const char *type, const char *device, const char *mntpt,
- int interactive)
-{
- char *s, *argv[80];
- char *prog;
- int argc, i;
- struct fsck_instance *inst, *p;
- pid_t pid;
-
- inst = xzalloc(sizeof(struct fsck_instance));
-
- prog = xasprintf("fsck.%s", type);
- argv[0] = prog;
- argc = 1;
-
- for (i=0; i <num_args; i++)
- argv[argc++] = string_copy(args[i]);
-
- if (progress && !progress_active()) {
- if ((strcmp(type, "ext2") == 0) ||
- (strcmp(type, "ext3") == 0)) {
- char tmp[80];
- snprintf(tmp, 80, "-C%d", progress_fd);
- argv[argc++] = string_copy(tmp);
- inst->flags |= FLAG_PROGRESS;
- }
- }
-
- argv[argc++] = string_copy(device);
- argv[argc] = 0;
-
- s = find_fsck(prog);
- if (s == NULL) {
- bb_error_msg("%s: not found", prog);
- return ENOENT;
- }
-
- if (verbose || noexecute) {
- printf("[%s (%d) -- %s] ", s, num_running,
- mntpt ? mntpt : device);
- for (i=0; i < argc; i++)
- printf("%s ", argv[i]);
- bb_putchar('\n');
- }
-
- /* Fork and execute the correct program. */
- if (noexecute)
- pid = -1;
- else if ((pid = fork()) < 0) {
- perror("vfork"+1);
- return errno;
- } else if (pid == 0) {
- if (!interactive)
- close(0);
- (void) execv(s, argv);
- bb_simple_perror_msg_and_die(argv[0]);
- }
-
- for (i = 1; i < argc; i++)
- free(argv[i]);
-
- free(s);
- inst->pid = pid;
- inst->prog = prog;
- inst->type = string_copy(type);
- inst->device = string_copy(device);
- inst->base_device = base_device(device);
- inst->start_time = time(0);
- inst->next = NULL;
-
- /*
- * Find the end of the list, so we add the instance on at the end.
- */
- for (p = instance_list; p && p->next; p = p->next);
-
- if (p)
- p->next = inst;
- else
- instance_list = inst;
-
- return 0;
-}
-
-/*
- * Send a signal to all outstanding fsck child processes
- */
-static int kill_all(int signum)
-{
- struct fsck_instance *inst;
- int n = 0;
-
- for (inst = instance_list; inst; inst = inst->next) {
- if (inst->flags & FLAG_DONE)
- continue;
- kill(inst->pid, signum);
- n++;
- }
- return n;
-}
-
-/*
- * Wait for one child process to exit; when it does, unlink it from
- * the list of executing child processes, and return it.
- */
-static struct fsck_instance *wait_one(int flags)
-{
- int status;
- int sig;
- struct fsck_instance *inst, *inst2, *prev;
- pid_t pid;
-
- if (!instance_list)
- return NULL;
-
- if (noexecute) {
- inst = instance_list;
- prev = 0;
-#ifdef RANDOM_DEBUG
- while (inst->next && (random() & 1)) {
- prev = inst;
- inst = inst->next;
- }
-#endif
- inst->exit_status = 0;
- goto ret_inst;
- }
-
- /*
- * gcc -Wall fails saving throw against stupidity
- * (inst and prev are thought to be uninitialized variables)
- */
- inst = prev = NULL;
-
- do {
- pid = waitpid(-1, &status, flags);
- if (cancel_requested && !kill_sent) {
- kill_all(SIGTERM);
- kill_sent++;
- }
- if ((pid == 0) && (flags & WNOHANG))
- return NULL;
- if (pid < 0) {
- if ((errno == EINTR) || (errno == EAGAIN))
- continue;
- if (errno == ECHILD) {
- bb_error_msg("wait: no more child process?!?");
- return NULL;
- }
- perror("wait");
- continue;
- }
- for (prev = 0, inst = instance_list;
- inst;
- prev = inst, inst = inst->next) {
- if (inst->pid == pid)
- break;
- }
- } while (!inst);
-
- if (WIFEXITED(status))
- status = WEXITSTATUS(status);
- else if (WIFSIGNALED(status)) {
- sig = WTERMSIG(status);
- if (sig == SIGINT) {
- status = EXIT_UNCORRECTED;
- } else {
- printf("Warning... %s for device %s exited "
- "with signal %d.\n",
- inst->prog, inst->device, sig);
- status = EXIT_ERROR;
- }
- } else {
- printf("%s %s: status is %x, should never happen.\n",
- inst->prog, inst->device, status);
- status = EXIT_ERROR;
- }
- inst->exit_status = status;
- if (progress && (inst->flags & FLAG_PROGRESS) &&
- !progress_active()) {
- for (inst2 = instance_list; inst2; inst2 = inst2->next) {
- if (inst2->flags & FLAG_DONE)
- continue;
- if (strcmp(inst2->type, "ext2") &&
- strcmp(inst2->type, "ext3"))
- continue;
- /*
- * If we've just started the fsck, wait a tiny
- * bit before sending the kill, to give it
- * time to set up the signal handler
- */
- if (inst2->start_time < time(0)+2) {
- if (fork() == 0) {
- sleep(1);
- kill(inst2->pid, SIGUSR1);
- exit(0);
- }
- } else
- kill(inst2->pid, SIGUSR1);
- inst2->flags |= FLAG_PROGRESS;
- break;
- }
- }
-ret_inst:
- if (prev)
- prev->next = inst->next;
- else
- instance_list = inst->next;
- if (verbose > 1)
- printf("Finished with %s (exit status %d)\n",
- inst->device, inst->exit_status);
- num_running--;
- return inst;
-}
-
-#define FLAG_WAIT_ALL 0
-#define FLAG_WAIT_ATLEAST_ONE 1
-/*
- * Wait until all executing child processes have exited; return the
- * logical OR of all of their exit code values.
- */
-static int wait_many(int flags)
-{
- struct fsck_instance *inst;
- int global_status = 0;
- int wait_flags = 0;
-
- while ((inst = wait_one(wait_flags))) {
- global_status |= inst->exit_status;
- free_instance(inst);
-#ifdef RANDOM_DEBUG
- if (noexecute && (flags & WNOHANG) && !(random() % 3))
- break;
-#endif
- if (flags & FLAG_WAIT_ATLEAST_ONE)
- wait_flags = WNOHANG;
- }
- return global_status;
-}
-
-/*
- * Run the fsck program on a particular device
- *
- * If the type is specified using -t, and it isn't prefixed with "no"
- * (as in "noext2") and only one filesystem type is specified, then
- * use that type regardless of what is specified in /etc/fstab.
- *
- * If the type isn't specified by the user, then use either the type
- * specified in /etc/fstab, or DEFAULT_FSTYPE.
- */
-static void fsck_device(struct fs_info *fs, int interactive)
-{
- const char *type;
- int retval;
-
- interpret_type(fs);
-
- if (strcmp(fs->type, "auto") != 0)
- type = fs->type;
- else if (fstype && strncmp(fstype, "no", 2) &&
- strncmp(fstype, "opts=", 5) && strncmp(fstype, "loop", 4) &&
- !strchr(fstype, ','))
- type = fstype;
- else
- type = DEFAULT_FSTYPE;
-
- num_running++;
- retval = execute(type, fs->device, fs->mountpt, interactive);
- if (retval) {
- bb_error_msg("error %d while executing fsck.%s for %s",
- retval, type, fs->device);
- num_running--;
- }
-}
-
-
-/*
- * Deal with the fsck -t argument.
- */
-struct fs_type_compile {
- char **list;
- int *type;
- int negate;
-} fs_type_compiled;
-
-#define FS_TYPE_NORMAL 0
-#define FS_TYPE_OPT 1
-#define FS_TYPE_NEGOPT 2
-
-static const char fs_type_syntax_error[] =
-"Either all or none of the filesystem types passed to -t must be prefixed\n"
- "with 'no' or '!'.";
-
-static void compile_fs_type(char *fs_type, struct fs_type_compile *cmp)
-{
- char *cp, *list, *s;
- int num = 2;
- int negate, first_negate = 1;
-
- if (fs_type) {
- for (cp=fs_type; *cp; cp++) {
- if (*cp == ',')
- num++;
- }
- }
-
- cmp->list = xzalloc(num * sizeof(char *));
- cmp->type = xzalloc(num * sizeof(int));
- cmp->negate = 0;
-
- if (!fs_type)
- return;
-
- list = string_copy(fs_type);
- num = 0;
- s = strtok(list, ",");
- while (s) {
- negate = 0;
- if (strncmp(s, "no", 2) == 0) {
- s += 2;
- negate = 1;
- } else if (*s == '!') {
- s++;
- negate = 1;
- }
- if (strcmp(s, "loop") == 0)
- /* loop is really short-hand for opts=loop */
- goto loop_special_case;
- else if (strncmp(s, "opts=", 5) == 0) {
- s += 5;
- loop_special_case:
- cmp->type[num] = negate ? FS_TYPE_NEGOPT : FS_TYPE_OPT;
- } else {
- if (first_negate) {
- cmp->negate = negate;
- first_negate = 0;
- }
- if ((negate && !cmp->negate) ||
- (!negate && cmp->negate)) {
- bb_error_msg_and_die("%s", fs_type_syntax_error);
- }
- }
- cmp->list[num++] = string_copy(s);
- s = strtok(NULL, ",");
- }
- free(list);
-}
-
-/*
- * This function returns true if a particular option appears in a
- * comma-delimited options list
- */
-static int opt_in_list(char *opt, char *optlist)
-{
- char *list, *s;
-
- if (!optlist)
- return 0;
- list = string_copy(optlist);
-
- s = strtok(list, ",");
- while (s) {
- if (strcmp(s, opt) == 0) {
- free(list);
- return 1;
- }
- s = strtok(NULL, ",");
- }
- free(list);
- return 0;
-}
-
-/* See if the filesystem matches the criteria given by the -t option */
-static int fs_match(struct fs_info *fs, struct fs_type_compile *cmp)
-{
- int n, ret = 0, checked_type = 0;
- char *cp;
-
- if (cmp->list == 0 || cmp->list[0] == 0)
- return 1;
-
- for (n=0; (cp = cmp->list[n]); n++) {
- switch (cmp->type[n]) {
- case FS_TYPE_NORMAL:
- checked_type++;
- if (strcmp(cp, fs->type) == 0) {
- ret = 1;
- }
- break;
- case FS_TYPE_NEGOPT:
- if (opt_in_list(cp, fs->opts))
- return 0;
- break;
- case FS_TYPE_OPT:
- if (!opt_in_list(cp, fs->opts))
- return 0;
- break;
- }
- }
- if (checked_type == 0)
- return 1;
- return (cmp->negate ? !ret : ret);
-}
-
-/* Check if we should ignore this filesystem. */
-static int ignore(struct fs_info *fs)
-{
- int wanted;
- char *s;
-
- /*
- * If the pass number is 0, ignore it.
- */
- if (fs->passno == 0)
- return 1;
-
- interpret_type(fs);
-
- /*
- * If a specific fstype is specified, and it doesn't match,
- * ignore it.
- */
- if (!fs_match(fs, &fs_type_compiled)) return 1;
-
- /* Are we ignoring this type? */
- if (index_in_str_array(ignored_types, fs->type) >= 0)
- return 1;
-
- /* Do we really really want to check this fs? */
- wanted = index_in_str_array(really_wanted, fs->type) >= 0;
-
- /* See if the <fsck.fs> program is available. */
- s = find_fsck(fs->type);
- if (s == NULL) {
- if (wanted)
- bb_error_msg("can't check %s: fsck.%s not found",
- fs->device, fs->type);
- return 1;
- }
- free(s);
-
- /* We can and want to check this file system type. */
- return 0;
-}
-
-/*
- * Returns TRUE if a partition on the same disk is already being
- * checked.
- */
-static int device_already_active(char *device)
-{
- struct fsck_instance *inst;
- char *base;
-
- if (force_all_parallel)
- return 0;
-
-#ifdef BASE_MD
- /* Don't check a soft raid disk with any other disk */
- if (instance_list &&
- (!strncmp(instance_list->device, BASE_MD, sizeof(BASE_MD)-1) ||
- !strncmp(device, BASE_MD, sizeof(BASE_MD)-1)))
- return 1;
-#endif
-
- base = base_device(device);
- /*
- * If we don't know the base device, assume that the device is
- * already active if there are any fsck instances running.
- */
- if (!base)
- return (instance_list != 0);
- for (inst = instance_list; inst; inst = inst->next) {
- if (!inst->base_device || !strcmp(base, inst->base_device)) {
- free(base);
- return 1;
- }
- }
- free(base);
- return 0;
-}
-
-/* Check all file systems, using the /etc/fstab table. */
-static int check_all(void)
-{
- struct fs_info *fs = NULL;
- int status = EXIT_OK;
- int not_done_yet = 1;
- int passno = 1;
- int pass_done;
-
- if (verbose)
- fputs("Checking all file systems.\n", stdout);
-
- /*
- * Do an initial scan over the filesystem; mark filesystems
- * which should be ignored as done, and resolve any "auto"
- * filesystem types (done as a side-effect of calling ignore()).
- */
- for (fs = filesys_info; fs; fs = fs->next) {
- if (ignore(fs))
- fs->flags |= FLAG_DONE;
- }
-
- /*
- * Find and check the root filesystem.
- */
- if (!parallel_root) {
- for (fs = filesys_info; fs; fs = fs->next) {
- if (LONE_CHAR(fs->mountpt, '/'))
- break;
- }
- if (fs) {
- if (!skip_root && !ignore(fs)) {
- fsck_device(fs, 1);
- status |= wait_many(FLAG_WAIT_ALL);
- if (status > EXIT_NONDESTRUCT)
- return status;
- }
- fs->flags |= FLAG_DONE;
- }
- }
- /*
- * This is for the bone-headed user who enters the root
- * filesystem twice. Skip root will skep all root entries.
- */
- if (skip_root)
- for (fs = filesys_info; fs; fs = fs->next)
- if (LONE_CHAR(fs->mountpt, '/'))
- fs->flags |= FLAG_DONE;
-
- while (not_done_yet) {
- not_done_yet = 0;
- pass_done = 1;
-
- for (fs = filesys_info; fs; fs = fs->next) {
- if (cancel_requested)
- break;
- if (fs->flags & FLAG_DONE)
- continue;
- /*
- * If the filesystem's pass number is higher
- * than the current pass number, then we don't
- * do it yet.
- */
- if (fs->passno > passno) {
- not_done_yet++;
- continue;
- }
- /*
- * If a filesystem on a particular device has
- * already been spawned, then we need to defer
- * this to another pass.
- */
- if (device_already_active(fs->device)) {
- pass_done = 0;
- continue;
- }
- /*
- * Spawn off the fsck process
- */
- fsck_device(fs, serialize);
- fs->flags |= FLAG_DONE;
-
- /*
- * Only do one filesystem at a time, or if we
- * have a limit on the number of fsck's extant
- * at one time, apply that limit.
- */
- if (serialize ||
- (max_running && (num_running >= max_running))) {
- pass_done = 0;
- break;
- }
- }
- if (cancel_requested)
- break;
- if (verbose > 1)
- printf("--waiting-- (pass %d)\n", passno);
- status |= wait_many(pass_done ? FLAG_WAIT_ALL :
- FLAG_WAIT_ATLEAST_ONE);
- if (pass_done) {
- if (verbose > 1)
- printf("----------------------------------\n");
- passno++;
- } else
- not_done_yet++;
- }
- if (cancel_requested && !kill_sent) {
- kill_all(SIGTERM);
- kill_sent++;
- }
- status |= wait_many(FLAG_WAIT_ATLEAST_ONE);
- return status;
-}
-
-static void signal_cancel(int sig FSCK_ATTR((unused)))
-{
- cancel_requested++;
-}
-
-static void PRS(int argc, char **argv)
-{
- int i, j;
- char *arg, *dev, *tmp = NULL;
- char options[128];
- int opt = 0;
- int opts_for_fsck = 0;
- struct sigaction sa;
-
- /*
- * Set up signal action
- */
- memset(&sa, 0, sizeof(struct sigaction));
- sa.sa_handler = signal_cancel;
- sigaction(SIGINT, &sa, 0);
- sigaction(SIGTERM, &sa, 0);
-
- num_devices = 0;
- num_args = 0;
- instance_list = 0;
-
- for (i=1; i < argc; i++) {
- arg = argv[i];
- if (!arg)
- continue;
- if ((arg[0] == '/' && !opts_for_fsck) || strchr(arg, '=')) {
- if (num_devices >= MAX_DEVICES) {
- bb_error_msg_and_die("too many devices");
- }
- dev = blkid_get_devname(cache, arg, NULL);
- if (!dev && strchr(arg, '=')) {
- /*
- * Check to see if we failed because
- * /proc/partitions isn't found.
- */
- if (access("/proc/partitions", R_OK) < 0) {
- bb_perror_msg_and_die("can't open /proc/partitions "
- "(is /proc mounted?)");
- }
- /*
- * Check to see if this is because
- * we're not running as root
- */
- if (geteuid())
- bb_error_msg_and_die(
- "must be root to scan for matching filesystems: %s\n", arg);
- else
- bb_error_msg_and_die(
- "can't find matching filesystem: %s", arg);
- }
- devices[num_devices++] = dev ? dev : string_copy(arg);
- continue;
- }
- if (arg[0] != '-' || opts_for_fsck) {
- if (num_args >= MAX_ARGS) {
- bb_error_msg_and_die("too many arguments");
- }
- args[num_args++] = string_copy(arg);
- continue;
- }
- for (j=1; arg[j]; j++) {
- if (opts_for_fsck) {
- options[++opt] = arg[j];
- continue;
- }
- switch (arg[j]) {
- case 'A':
- doall++;
- break;
- case 'C':
- progress++;
- if (arg[j+1]) {
- progress_fd = string_to_int(arg+j+1);
- if (progress_fd < 0)
- progress_fd = 0;
- else
- goto next_arg;
- } else if ((i+1) < argc
- && argv[i+1][0] != '-') {
- progress_fd = string_to_int(argv[i]);
- if (progress_fd < 0)
- progress_fd = 0;
- else {
- goto next_arg;
- i++;
- }
- }
- break;
- case 'V':
- verbose++;
- break;
- case 'N':
- noexecute++;
- break;
- case 'R':
- skip_root++;
- break;
- case 'T':
- notitle++;
- break;
- case 'M':
- like_mount++;
- break;
- case 'P':
- parallel_root++;
- break;
- case 's':
- serialize++;
- break;
- case 't':
- tmp = 0;
- if (fstype)
- bb_show_usage();
- if (arg[j+1])
- tmp = arg+j+1;
- else if ((i+1) < argc)
- tmp = argv[++i];
- else
- bb_show_usage();
- fstype = string_copy(tmp);
- compile_fs_type(fstype, &fs_type_compiled);
- goto next_arg;
- case '-':
- opts_for_fsck++;
- break;
- case '?':
- bb_show_usage();
- break;
- default:
- options[++opt] = arg[j];
- break;
- }
- }
- next_arg:
- if (opt) {
- options[0] = '-';
- options[++opt] = '\0';
- if (num_args >= MAX_ARGS) {
- bb_error_msg("too many arguments");
- }
- args[num_args++] = string_copy(options);
- opt = 0;
- }
- }
- if (getenv("FSCK_FORCE_ALL_PARALLEL"))
- force_all_parallel++;
- if ((tmp = getenv("FSCK_MAX_INST")))
- max_running = atoi(tmp);
-}
-
-int fsck_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int fsck_main(int argc, char **argv)
-{
- int i, status = 0;
- int interactive = 0;
- const char *fstab;
- struct fs_info *fs;
-
- setvbuf(stdout, NULL, _IONBF, BUFSIZ);
- setvbuf(stderr, NULL, _IONBF, BUFSIZ);
-
- blkid_get_cache(&cache, NULL);
- PRS(argc, argv);
-
- if (!notitle)
- printf("fsck %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE);
-
- fstab = getenv("FSTAB_FILE");
- if (!fstab)
- fstab = _PATH_MNTTAB;
- load_fs_info(fstab);
-
- fsck_path = e2fs_set_sbin_path();
-
- if ((num_devices == 1) || (serialize))
- interactive = 1;
-
- /* If -A was specified ("check all"), do that! */
- if (doall)
- return check_all();
-
- if (num_devices == 0) {
- serialize++;
- interactive++;
- return check_all();
- }
- for (i = 0; i < num_devices; i++) {
- if (cancel_requested) {
- if (!kill_sent) {
- kill_all(SIGTERM);
- kill_sent++;
- }
- break;
- }
- fs = lookup(devices[i]);
- if (!fs) {
- fs = create_fs_device(devices[i], 0, "auto",
- 0, -1, -1);
- if (!fs)
- continue;
- }
- fsck_device(fs, interactive);
- if (serialize ||
- (max_running && (num_running >= max_running))) {
- struct fsck_instance *inst;
-
- inst = wait_one(0);
- if (inst) {
- status |= inst->exit_status;
- free_instance(inst);
- }
- if (verbose > 1)
- printf("----------------------------------\n");
- }
- }
- status |= wait_many(FLAG_WAIT_ALL);
- blkid_put_cache(cache);
- return status;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/fsck.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/fsck.h
deleted file mode 100644
index 2ca2af7da8..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/fsck.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * fsck.h
- */
-
-#define FSCK_ATTR(x) __attribute__(x)
-
-#define EXIT_OK 0
-#define EXIT_NONDESTRUCT 1
-#define EXIT_DESTRUCT 2
-#define EXIT_UNCORRECTED 4
-#define EXIT_ERROR 8
-#define EXIT_USAGE 16
-#define FSCK_CANCELED 32 /* Aborted with a signal or ^C */
-
-extern char *e2fs_set_sbin_path(void);
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/lsattr.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/lsattr.c
deleted file mode 100644
index 9e0e4cb602..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/lsattr.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * lsattr.c - List file attributes on an ext2 file system
- *
- * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
- * Laboratoire MASI, Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * This file can be redistributed under the terms of the GNU General
- * Public License
- */
-
-/*
- * History:
- * 93/10/30 - Creation
- * 93/11/13 - Replace stat() calls by lstat() to avoid loops
- * 94/02/27 - Integrated in Ted's distribution
- * 98/12/29 - Display version info only when -V specified (G M Sipe)
- */
-
-#include <sys/types.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-
-#include "ext2fs/ext2_fs.h"
-#include "e2fsbb.h"
-#include "e2p/e2p.h"
-
-#define OPT_RECUR 1
-#define OPT_ALL 2
-#define OPT_DIRS_OPT 4
-#define OPT_PF_LONG 8
-#define OPT_GENERATION 16
-static int flags;
-
-static void list_attributes(const char *name)
-{
- unsigned long fsflags;
- unsigned long generation;
-
- if (fgetflags(name, &fsflags) == -1)
- goto read_err;
- if (flags & OPT_GENERATION) {
- if (fgetversion(name, &generation) == -1)
- goto read_err;
- printf("%5lu ", generation);
- }
-
- if (flags & OPT_PF_LONG) {
- printf("%-28s ", name);
- print_e2flags(stdout, fsflags, PFOPT_LONG);
- bb_putchar('\n');
- } else {
- print_e2flags(stdout, fsflags, 0);
- printf(" %s\n", name);
- }
-
- return;
-read_err:
- bb_perror_msg("reading %s", name);
-}
-
-static int lsattr_dir_proc(const char *, struct dirent *, void *);
-
-static void lsattr_args(const char *name)
-{
- struct stat st;
-
- if (lstat(name, &st) == -1) {
- bb_perror_msg("stating %s", name);
- } else {
- if (S_ISDIR(st.st_mode) && !(flags & OPT_DIRS_OPT))
- iterate_on_dir(name, lsattr_dir_proc, NULL);
- else
- list_attributes(name);
- }
-}
-
-static int lsattr_dir_proc(const char *dir_name, struct dirent *de,
- void *private)
-{
- struct stat st;
- char *path;
-
- path = concat_path_file(dir_name, de->d_name);
-
- if (lstat(path, &st) == -1)
- bb_perror_msg(path);
- else {
- if (de->d_name[0] != '.' || (flags & OPT_ALL)) {
- list_attributes(path);
- if (S_ISDIR(st.st_mode) && (flags & OPT_RECUR) &&
- (de->d_name[0] != '.' && (de->d_name[1] != '\0' ||
- (de->d_name[1] != '.' && de->d_name[2] != '\0')))) {
- printf("\n%s:\n", path);
- iterate_on_dir(path, lsattr_dir_proc, NULL);
- bb_putchar('\n');
- }
- }
- }
-
- free(path);
-
- return 0;
-}
-
-int lsattr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int lsattr_main(int argc, char **argv)
-{
- int i;
-
- flags = getopt32(argv, "Radlv");
-
- if (optind > argc - 1)
- lsattr_args(".");
- else
- for (i = optind; i < argc; i++)
- lsattr_args(argv[i]);
-
- return EXIT_SUCCESS;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/mke2fs.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/mke2fs.c
deleted file mode 100644
index c2c1836a2b..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/mke2fs.c
+++ /dev/null
@@ -1,1370 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * mke2fs.c - Make a ext2fs filesystem.
- *
- * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- * 2003, 2004, 2005 by Theodore Ts'o.
- *
- * Licensed under GPLv2, see file LICENSE in this source tree.
- */
-
-//usage:#define mkfs_ext2_trivial_usage
-//usage: "[-Fn] "
-//usage: "[-c|-l filename] "
-//usage: "[-b BLK_SIZE] "
-//usage: "[-f fragment-size] [-g blocks-per-group] "
-//usage: "[-i INODE_RATIO] [-I INODE_SIZE] "
-//usage: "[-j] [-J journal-options] [-N number-of-inodes] "
-//usage: "[-m RESERVED_PERCENT] "
-//usage: "[-o creator-os] [-O feature[,...]] [-q] "
-//usage: "[r fs-revision-level] [-E extended-options] [-v] [-F] "
-//usage: "[-L LABEL] "
-//usage: "[-M last-mounted-directory] [-S] [-T filesystem-type] "
-//usage: "BLOCKDEV [KBYTES]"
-//usage:#define mkfs_ext2_full_usage "\n\n"
-//usage: " -b BLK_SIZE Block size, bytes"
-//usage: "\n -c Check device for bad blocks"
-//usage: "\n -E opts Set extended options"
-//usage: "\n -f size Fragment size in bytes"
-//usage: "\n -F Force"
-//usage: "\n -g N Number of blocks in a block group"
-//usage: "\n -i RATIO Max number of files is filesystem_size / RATIO"
-//usage: "\n -I BYTES Inode size (min 128)"
-//usage: "\n -j Create a journal (ext3)"
-//usage: "\n -J opts Set journal options (size/device)"
-//usage: "\n -l file Read bad blocks list from file"
-//usage: "\n -L LBL Volume label"
-//usage: "\n -m PERCENT Percent of blocks to reserve for admin"
-//usage: "\n -M dir Set last mounted directory"
-//usage: "\n -n Dry run"
-//usage: "\n -N N Number of inodes to create"
-//usage: "\n -o os Set the 'creator os' field"
-//usage: "\n -O features Dir_index/filetype/has_journal/journal_dev/sparse_super"
-//usage: "\n -q Quiet"
-//usage: "\n -r rev Set filesystem revision"
-//usage: "\n -S Write superblock and group descriptors only"
-//usage: "\n -T fs-type Set usage type (news/largefile/largefile4)"
-//usage: "\n -v Verbose"
-
-//usage:#define mkfs_ext3_trivial_usage NOUSAGE_STR
-//usage:#define mkfs_ext3_full_usage ""
-
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <time.h>
-#include <getopt.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <mntent.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-
-#include "e2fsbb.h"
-#include "ext2fs/ext2_fs.h"
-#include "e2fs_lib.h"
-#include "e2p/e2p.h"
-#include "ext2fs/ext2fs.h"
-#include "util.h"
-
-#define STRIDE_LENGTH 8
-
-#ifndef __sparc__
-#define ZAP_BOOTBLOCK
-#endif
-
-static const char * device_name;
-
-/* Command line options */
-static int cflag;
-static int quiet;
-static int super_only;
-static int force;
-static int noaction;
-static int journal_size;
-static int journal_flags;
-static const char *bad_blocks_filename;
-static __u32 fs_stride;
-
-static struct ext2_super_block param;
-static char *creator_os;
-static char *volume_label;
-static char *mount_dir;
-static char *journal_device = NULL;
-static int sync_kludge; /* Set using the MKE2FS_SYNC env. option */
-
-static int sys_page_size = 4096;
-static int linux_version_code = 0;
-
-static int int_log2(int arg)
-{
- int l = 0;
-
- arg >>= 1;
- while (arg) {
- l++;
- arg >>= 1;
- }
- return l;
-}
-
-static int int_log10(unsigned int arg)
-{
- int l;
-
- for (l = 0; arg; l++)
- arg = arg / 10;
- return l;
-}
-
-/*
- * This function sets the default parameters for a filesystem
- *
- * The type is specified by the user. The size is the maximum size
- * (in megabytes) for which a set of parameters applies, with a size
- * of zero meaning that it is the default parameter for the type.
- * Note that order is important in the table below.
- */
-#define DEF_MAX_BLOCKSIZE -1
-static const char default_str[] = "default";
-struct mke2fs_defaults {
- const char *type;
- int size;
- int blocksize;
- int inode_ratio;
-};
-
-static const struct mke2fs_defaults settings[] = {
- { default_str, 0, 4096, 8192 },
- { default_str, 512, 1024, 4096 },
- { default_str, 3, 1024, 8192 },
- { "journal", 0, 4096, 8192 },
- { "news", 0, 4096, 4096 },
- { "largefile", 0, 4096, 1024 * 1024 },
- { "largefile4", 0, 4096, 4096 * 1024 },
- { 0, 0, 0, 0},
-};
-
-static void set_fs_defaults(const char *fs_type,
- struct ext2_super_block *super,
- int blocksize, int sector_size,
- int *inode_ratio)
-{
- int megs;
- int ratio = 0;
- const struct mke2fs_defaults *p;
- int use_bsize = 1024;
-
- megs = super->s_blocks_count * (EXT2_BLOCK_SIZE(super) / 1024) / 1024;
- if (inode_ratio)
- ratio = *inode_ratio;
- if (!fs_type)
- fs_type = default_str;
- for (p = settings; p->type; p++) {
- if ((strcmp(p->type, fs_type) != 0) &&
- (strcmp(p->type, default_str) != 0))
- continue;
- if ((p->size != 0) && (megs > p->size))
- continue;
- if (ratio == 0)
- *inode_ratio = p->inode_ratio < blocksize ?
- blocksize : p->inode_ratio;
- use_bsize = p->blocksize;
- }
- if (blocksize <= 0) {
- if (use_bsize == DEF_MAX_BLOCKSIZE) {
- use_bsize = sys_page_size;
- if ((linux_version_code < (2*65536 + 6*256)) &&
- (use_bsize > 4096))
- use_bsize = 4096;
- }
- if (sector_size && use_bsize < sector_size)
- use_bsize = sector_size;
- if ((blocksize < 0) && (use_bsize < (-blocksize)))
- use_bsize = -blocksize;
- blocksize = use_bsize;
- super->s_blocks_count /= blocksize / 1024;
- }
- super->s_log_frag_size = super->s_log_block_size =
- int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
-}
-
-
-/*
- * Helper function for read_bb_file and test_disk
- */
-static void invalid_block(ext2_filsys fs EXT2FS_ATTR((unused)), blk_t blk)
-{
- bb_error_msg("Bad block %u out of range; ignored", blk);
-}
-
-/*
- * Busybox stuff
- */
-static void mke2fs_error_msg_and_die(int retval, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
-static void mke2fs_error_msg_and_die(int retval, const char *fmt, ...)
-{
- va_list ap;
-
- if (retval) {
- va_start(ap, fmt);
- fprintf(stderr, "\nCould not ");
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
- va_end(ap);
- exit(EXIT_FAILURE);
- }
-}
-
-static void mke2fs_verbose(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
-static void mke2fs_verbose(const char *fmt, ...)
-{
- va_list ap;
-
- if (!quiet) {
- va_start(ap, fmt);
- vfprintf(stdout, fmt, ap);
- fflush(stdout);
- va_end(ap);
- }
-}
-
-static void mke2fs_verbose_done(void)
-{
- mke2fs_verbose("done\n");
-}
-
-static void mke2fs_warning_msg(int retval, const char *fmt, ... ) __attribute__ ((format (printf, 2, 3)));
-static void mke2fs_warning_msg(int retval, const char *fmt, ... )
-{
- va_list ap;
-
- if (retval) {
- va_start(ap, fmt);
- fprintf(stderr, "\nWarning: ");
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
- va_end(ap);
- }
-}
-
-/*
- * Reads the bad blocks list from a file
- */
-static void read_bb_file(ext2_filsys fs, badblocks_list *bb_list,
- const char *bad_blocks_file)
-{
- FILE *f;
- errcode_t retval;
-
- f = xfopen_for_read(bad_blocks_file);
- retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block);
- fclose (f);
- mke2fs_error_msg_and_die(retval, "read bad blocks from list");
-}
-
-/*
- * Runs the badblocks program to test the disk
- */
-static void test_disk(ext2_filsys fs, badblocks_list *bb_list)
-{
- FILE *f;
- errcode_t retval;
- char buf[1024];
-
- sprintf(buf, "badblocks -b %d %s%s%s %d", fs->blocksize,
- quiet ? "" : "-s ", (cflag > 1) ? "-w " : "",
- fs->device_name, fs->super->s_blocks_count);
- mke2fs_verbose("Running command: %s\n", buf);
- f = popen(buf, "r");
- if (!f) {
- bb_perror_msg_and_die("can't run '%s'", buf);
- }
- retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block);
- pclose(f);
- mke2fs_error_msg_and_die(retval, "read bad blocks from program");
-}
-
-static void handle_bad_blocks(ext2_filsys fs, badblocks_list bb_list)
-{
- dgrp_t i;
- blk_t j;
- unsigned must_be_good;
- blk_t blk;
- badblocks_iterate bb_iter;
- errcode_t retval;
- blk_t group_block;
- int group;
- int group_bad;
-
- if (!bb_list)
- return;
-
- /*
- * The primary superblock and group descriptors *must* be
- * good; if not, abort.
- */
- must_be_good = fs->super->s_first_data_block + 1 + fs->desc_blocks;
- for (i = fs->super->s_first_data_block; i <= must_be_good; i++) {
- if (ext2fs_badblocks_list_test(bb_list, i)) {
- bb_error_msg_and_die(
- "Block %d in primary superblock/group descriptor area bad\n"
- "Blocks %d through %d must be good in order to build a filesystem\n"
- "Aborting ...", i, fs->super->s_first_data_block, must_be_good);
- }
- }
-
- /*
- * See if any of the bad blocks are showing up in the backup
- * superblocks and/or group descriptors. If so, issue a
- * warning and adjust the block counts appropriately.
- */
- group_block = fs->super->s_first_data_block +
- fs->super->s_blocks_per_group;
-
- for (i = 1; i < fs->group_desc_count; i++) {
- group_bad = 0;
- for (j=0; j < fs->desc_blocks+1; j++) {
- if (ext2fs_badblocks_list_test(bb_list,
- group_block + j)) {
- mke2fs_warning_msg(!group_bad,
- "the backup superblock/group descriptors at block %d contain\n"
- "bad blocks\n", group_block);
- group_bad++;
- group = ext2fs_group_of_blk(fs, group_block+j);
- fs->group_desc[group].bg_free_blocks_count++;
- fs->super->s_free_blocks_count++;
- }
- }
- group_block += fs->super->s_blocks_per_group;
- }
-
- /*
- * Mark all the bad blocks as used...
- */
- retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter);
- mke2fs_error_msg_and_die(retval, "mark bad blocks as used");
-
- while (ext2fs_badblocks_list_iterate(bb_iter, &blk))
- ext2fs_mark_block_bitmap(fs->block_map, blk);
- ext2fs_badblocks_list_iterate_end(bb_iter);
-}
-
-/*
- * These functions implement a generalized progress meter.
- */
-struct progress_struct {
- char format[20];
- char backup[80];
- __u32 max;
- int skip_progress;
-};
-
-static void progress_init(struct progress_struct *progress,
- const char *label,__u32 max)
-{
- int i;
-
- memset(progress, 0, sizeof(struct progress_struct));
- if (quiet)
- return;
-
- /*
- * Figure out how many digits we need
- */
- i = int_log10(max);
- sprintf(progress->format, "%%%dd/%%%dld", i, i);
- memset(progress->backup, '\b', sizeof(progress->backup)-1);
- progress->backup[sizeof(progress->backup)-1] = 0;
- if ((2*i)+1 < (int) sizeof(progress->backup))
- progress->backup[(2*i)+1] = 0;
- progress->max = max;
-
- progress->skip_progress = 0;
- if (getenv("MKE2FS_SKIP_PROGRESS"))
- progress->skip_progress++;
-
- fputs(label, stdout);
- fflush(stdout);
-}
-
-static void progress_update(struct progress_struct *progress, __u32 val)
-{
- if ((progress->format[0] == 0) || progress->skip_progress)
- return;
- printf(progress->format, val, progress->max);
- fputs(progress->backup, stdout);
-}
-
-static void progress_close(struct progress_struct *progress)
-{
- if (progress->format[0] == 0)
- return;
- printf("%-28s\n", "done");
-}
-
-
-/*
- * Helper function which zeros out _num_ blocks starting at _blk_. In
- * case of an error, the details of the error is returned via _ret_blk_
- * and _ret_count_ if they are non-NULL pointers. Returns 0 on
- * success, and an error code on an error.
- *
- * As a special case, if the first argument is NULL, then it will
- * attempt to free the static zeroizing buffer. (This is to keep
- * programs that check for memory leaks happy.)
- */
-static errcode_t zero_blocks(ext2_filsys fs, blk_t blk, int num,
- struct progress_struct *progress,
- blk_t *ret_blk, int *ret_count)
-{
- int j, count, next_update, next_update_incr;
- static char *buf;
- errcode_t retval;
-
- /* If fs is null, clean up the static buffer and return */
- if (!fs) {
- if (buf) {
- free(buf);
- buf = 0;
- }
- return 0;
- }
- /* Allocate the zeroizing buffer if necessary */
- if (!buf) {
- buf = xzalloc(fs->blocksize * STRIDE_LENGTH);
- }
- /* OK, do the write loop */
- next_update = 0;
- next_update_incr = num / 100;
- if (next_update_incr < 1)
- next_update_incr = 1;
- for (j=0; j < num; j += STRIDE_LENGTH, blk += STRIDE_LENGTH) {
- count = num - j;
- if (count > STRIDE_LENGTH)
- count = STRIDE_LENGTH;
- retval = io_channel_write_blk(fs->io, blk, count, buf);
- if (retval) {
- if (ret_count)
- *ret_count = count;
- if (ret_blk)
- *ret_blk = blk;
- return retval;
- }
- if (progress && j > next_update) {
- next_update += num / 100;
- progress_update(progress, blk);
- }
- }
- return 0;
-}
-
-static void write_inode_tables(ext2_filsys fs)
-{
- errcode_t retval;
- blk_t blk;
- dgrp_t i;
- int num;
- struct progress_struct progress;
-
- if (quiet)
- memset(&progress, 0, sizeof(progress));
- else
- progress_init(&progress, "Writing inode tables: ",
- fs->group_desc_count);
-
- for (i = 0; i < fs->group_desc_count; i++) {
- progress_update(&progress, i);
-
- blk = fs->group_desc[i].bg_inode_table;
- num = fs->inode_blocks_per_group;
-
- retval = zero_blocks(fs, blk, num, 0, &blk, &num);
- mke2fs_error_msg_and_die(retval,
- "write %d blocks in inode table starting at %d.",
- num, blk);
- if (sync_kludge) {
- if (sync_kludge == 1)
- sync();
- else if ((i % sync_kludge) == 0)
- sync();
- }
- }
- zero_blocks(0, 0, 0, 0, 0, 0);
- progress_close(&progress);
-}
-
-static void create_root_dir(ext2_filsys fs)
-{
- errcode_t retval;
- struct ext2_inode inode;
-
- retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, 0);
- mke2fs_error_msg_and_die(retval, "create root dir");
- if (geteuid()) {
- retval = ext2fs_read_inode(fs, EXT2_ROOT_INO, &inode);
- mke2fs_error_msg_and_die(retval, "read root inode");
- inode.i_uid = getuid();
- if (inode.i_uid)
- inode.i_gid = getgid();
- retval = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
- mke2fs_error_msg_and_die(retval, "set root inode ownership");
- }
-}
-
-static void create_lost_and_found(ext2_filsys fs)
-{
- errcode_t retval;
- ext2_ino_t ino;
- const char *name = "lost+found";
- int i = 1;
- const char *msg = "create";
- int lpf_size = 0;
-
- fs->umask = 077;
- retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, 0, name);
- if (retval) {
- goto CREATE_LOST_AND_FOUND_ERROR;
- }
-
- retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name, strlen(name), 0, &ino);
- if (retval) {
- msg = "lookup";
- goto CREATE_LOST_AND_FOUND_ERROR;
- }
-
- for (; i < EXT2_NDIR_BLOCKS; i++) {
- if ((lpf_size += fs->blocksize) >= 16*1024)
- break;
- retval = ext2fs_expand_dir(fs, ino);
- msg = "expand";
-CREATE_LOST_AND_FOUND_ERROR:
- mke2fs_error_msg_and_die(retval, "%s %s", msg, name);
- }
-}
-
-static void create_bad_block_inode(ext2_filsys fs, badblocks_list bb_list)
-{
- errcode_t retval;
-
- ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_BAD_INO);
- fs->group_desc[0].bg_free_inodes_count--;
- fs->super->s_free_inodes_count--;
- retval = ext2fs_update_bb_inode(fs, bb_list);
- mke2fs_error_msg_and_die(retval, "set bad block inode");
-}
-
-static void reserve_inodes(ext2_filsys fs)
-{
- ext2_ino_t i;
- int group;
-
- for (i = EXT2_ROOT_INO + 1; i < EXT2_FIRST_INODE(fs->super); i++) {
- ext2fs_mark_inode_bitmap(fs->inode_map, i);
- group = ext2fs_group_of_ino(fs, i);
- fs->group_desc[group].bg_free_inodes_count--;
- fs->super->s_free_inodes_count--;
- }
- ext2fs_mark_ib_dirty(fs);
-}
-
-#define BSD_DISKMAGIC (0x82564557UL) /* The disk magic number */
-#define BSD_MAGICDISK (0x57455682UL) /* The disk magic number reversed */
-#define BSD_LABEL_OFFSET 64
-
-static void zap_sector(ext2_filsys fs, int sect, int nsect)
-{
- char *buf;
- const char *fmt = "could not %s %d";
- int retval;
- unsigned int *magic;
-
- buf = xmalloc(512*nsect);
-
- if (sect == 0) {
- /* Check for a BSD disklabel, and don't erase it if so */
- retval = io_channel_read_blk(fs->io, 0, -512, buf);
- if (retval)
- mke2fs_warning_msg(retval, fmt, "read block", 0);
- else {
- magic = (unsigned int *) (buf + BSD_LABEL_OFFSET);
- if ((*magic == BSD_DISKMAGIC) ||
- (*magic == BSD_MAGICDISK))
- return;
- }
- }
-
- memset(buf, 0, 512*nsect);
- io_channel_set_blksize(fs->io, 512);
- retval = io_channel_write_blk(fs->io, sect, -512*nsect, buf);
- io_channel_set_blksize(fs->io, fs->blocksize);
- free(buf);
- mke2fs_warning_msg(retval, fmt, "erase sector", sect);
-}
-
-static void create_journal_dev(ext2_filsys fs)
-{
- struct progress_struct progress;
- errcode_t retval;
- char *buf;
- const char *fmt = "%s journal superblock";
- blk_t blk;
- int count;
-
- retval = ext2fs_create_journal_superblock(fs,
- fs->super->s_blocks_count, 0, &buf);
- mke2fs_error_msg_and_die(retval, fmt, "init");
- if (quiet)
- memset(&progress, 0, sizeof(progress));
- else
- progress_init(&progress, "Zeroing journal device: ",
- fs->super->s_blocks_count);
-
- retval = zero_blocks(fs, 0, fs->super->s_blocks_count,
- &progress, &blk, &count);
- mke2fs_error_msg_and_die(retval, "zero journal device (block %u, count %d)",
- blk, count);
- zero_blocks(0, 0, 0, 0, 0, 0);
-
- retval = io_channel_write_blk(fs->io,
- fs->super->s_first_data_block+1,
- 1, buf);
- mke2fs_error_msg_and_die(retval, fmt, "write");
- progress_close(&progress);
-}
-
-static void show_stats(ext2_filsys fs)
-{
- struct ext2_super_block *s = fs->super;
- char *os;
- blk_t group_block;
- dgrp_t i;
- int need, col_left;
-
- mke2fs_warning_msg((param.s_blocks_count != s->s_blocks_count),
- "%d blocks unused\n", param.s_blocks_count - s->s_blocks_count);
- os = e2p_os2string(fs->super->s_creator_os);
- printf( "Filesystem label=%.*s\n"
- "OS type: %s\n"
- "Block size=%u (log=%u)\n"
- "Fragment size=%u (log=%u)\n"
- "%u inodes, %u blocks\n"
- "%u blocks (%2.2f%%) reserved for the super user\n"
- "First data block=%u\n",
- (int) sizeof(s->s_volume_name),
- s->s_volume_name,
- os,
- fs->blocksize, s->s_log_block_size,
- fs->fragsize, s->s_log_frag_size,
- s->s_inodes_count, s->s_blocks_count,
- s->s_r_blocks_count, 100.0 * s->s_r_blocks_count / s->s_blocks_count,
- s->s_first_data_block);
- free(os);
- if (s->s_reserved_gdt_blocks) {
- printf("Maximum filesystem blocks=%lu\n",
- (s->s_reserved_gdt_blocks + fs->desc_blocks) *
- (fs->blocksize / sizeof(struct ext2_group_desc)) *
- s->s_blocks_per_group);
- }
- printf( "%u block group%s\n"
- "%u blocks per group, %u fragments per group\n"
- "%u inodes per group\n",
- fs->group_desc_count, (fs->group_desc_count > 1) ? "s" : "",
- s->s_blocks_per_group, s->s_frags_per_group,
- s->s_inodes_per_group);
- if (fs->group_desc_count == 1) {
- bb_putchar('\n');
- return;
- }
-
- printf("Superblock backups stored on blocks: ");
- group_block = s->s_first_data_block;
- col_left = 0;
- for (i = 1; i < fs->group_desc_count; i++) {
- group_block += s->s_blocks_per_group;
- if (!ext2fs_bg_has_super(fs, i))
- continue;
- if (i != 1)
- printf(", ");
- need = int_log10(group_block) + 2;
- if (need > col_left) {
- printf("\n\t");
- col_left = 72;
- }
- col_left -= need;
- printf("%u", group_block);
- }
- puts("\n");
-}
-
-/*
- * Set the S_CREATOR_OS field. Return true if OS is known,
- * otherwise, 0.
- */
-static int set_os(struct ext2_super_block *sb, char *os)
-{
- if (isdigit (*os)) {
- sb->s_creator_os = atoi(os);
- return 1;
- }
-
- if ((sb->s_creator_os = e2p_string2os(os)) >= 0) {
- return 1;
- } else if (!strcasecmp("GNU", os)) {
- sb->s_creator_os = EXT2_OS_HURD;
- return 1;
- }
- return 0;
-}
-
-static void parse_extended_opts(struct ext2_super_block *sb_param,
- const char *opts)
-{
- char *buf, *token, *next, *p, *arg;
- int r_usage = 0;
-
- buf = xstrdup(opts);
- for (token = buf; token && *token; token = next) {
- p = strchr(token, ',');
- next = 0;
- if (p) {
- *p = 0;
- next = p+1;
- }
- arg = strchr(token, '=');
- if (arg) {
- *arg = 0;
- arg++;
- }
- if (strcmp(token, "stride") == 0) {
- if (!arg) {
- r_usage++;
- continue;
- }
- fs_stride = strtoul(arg, &p, 0);
- if (*p || (fs_stride == 0)) {
- bb_error_msg("Invalid stride parameter: %s", arg);
- r_usage++;
- continue;
- }
- } else if (!strcmp(token, "resize")) {
- unsigned long resize, bpg, rsv_groups;
- unsigned long group_desc_count, desc_blocks;
- unsigned int gdpb, blocksize;
- int rsv_gdb;
-
- if (!arg) {
- r_usage++;
- continue;
- }
-
- resize = parse_num_blocks(arg,
- sb_param->s_log_block_size);
-
- if (resize == 0) {
- bb_error_msg("Invalid resize parameter: %s", arg);
- r_usage++;
- continue;
- }
- if (resize <= sb_param->s_blocks_count) {
- bb_error_msg("The resize maximum must be greater "
- "than the filesystem size");
- r_usage++;
- continue;
- }
-
- blocksize = EXT2_BLOCK_SIZE(sb_param);
- bpg = sb_param->s_blocks_per_group;
- if (!bpg)
- bpg = blocksize * 8;
- gdpb = blocksize / sizeof(struct ext2_group_desc);
- group_desc_count = (sb_param->s_blocks_count +
- bpg - 1) / bpg;
- desc_blocks = (group_desc_count +
- gdpb - 1) / gdpb;
- rsv_groups = (resize + bpg - 1) / bpg;
- rsv_gdb = (rsv_groups + gdpb - 1) / gdpb -
- desc_blocks;
- if (rsv_gdb > EXT2_ADDR_PER_BLOCK(sb_param))
- rsv_gdb = EXT2_ADDR_PER_BLOCK(sb_param);
-
- if (rsv_gdb > 0) {
- sb_param->s_feature_compat |=
- EXT2_FEATURE_COMPAT_RESIZE_INO;
-
- sb_param->s_reserved_gdt_blocks = rsv_gdb;
- }
- } else
- r_usage++;
- }
- if (r_usage) {
- bb_error_msg_and_die(
- "\nBad options specified.\n\n"
- "Extended options are separated by commas, "
- "and may take an argument which\n"
- "\tis set off by an equals ('=') sign.\n\n"
- "Valid extended options are:\n"
- "\tstride=<stride length in blocks>\n"
- "\tresize=<resize maximum size in blocks>\n");
- }
-}
-
-static __u32 ok_features[3] = {
- EXT3_FEATURE_COMPAT_HAS_JOURNAL |
- EXT2_FEATURE_COMPAT_RESIZE_INO |
- EXT2_FEATURE_COMPAT_DIR_INDEX, /* Compat */
- EXT2_FEATURE_INCOMPAT_FILETYPE| /* Incompat */
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|
- EXT2_FEATURE_INCOMPAT_META_BG,
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER /* R/O compat */
-};
-
-static int PRS(int argc, char **argv)
-{
- int c;
- int size;
- char * tmp;
- int blocksize = 0;
- int inode_ratio = 0;
- int inode_size = 0;
- int reserved_ratio = 5;
- int sector_size = 0;
- int show_version_only = 0;
- ext2_ino_t num_inodes = 0;
- errcode_t retval;
- char * extended_opts = NULL;
- const char * fs_type = NULL;
- blk_t dev_size;
- long sysval;
-
- /* Update our PATH to include /sbin */
- e2fs_set_sbin_path();
-
- tmp = getenv("MKE2FS_SYNC");
- if (tmp)
- sync_kludge = atoi(tmp);
-
- /* Determine the system page size if possible */
-#if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE))
-#define _SC_PAGESIZE _SC_PAGE_SIZE
-#endif
-#ifdef _SC_PAGESIZE
- sysval = sysconf(_SC_PAGESIZE);
- if (sysval > 0)
- sys_page_size = sysval;
-#endif /* _SC_PAGESIZE */
-
- setbuf(stdout, NULL);
- setbuf(stderr, NULL);
- memset(&param, 0, sizeof(struct ext2_super_block));
- param.s_rev_level = 1; /* Create revision 1 filesystems now */
- param.s_feature_incompat |= EXT2_FEATURE_INCOMPAT_FILETYPE;
- param.s_feature_ro_compat |= EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
-
-#ifdef __linux__
- linux_version_code = get_linux_version_code();
- if (linux_version_code && linux_version_code < KERNEL_VERSION(2,2,0)) {
- param.s_rev_level = 0;
- param.s_feature_incompat = 0;
- param.s_feature_compat = 0;
- param.s_feature_ro_compat = 0;
- }
-#endif
-
- /* If called as mkfs.ext3, create a journal inode */
- if (last_char_is(applet_name, '3'))
- journal_size = -1;
-
- while ((c = getopt (argc, argv,
- "b:cE:f:g:i:jl:m:no:qr:R:s:tvI:J:ST:FL:M:N:O:V")) != EOF) {
- switch (c) {
- case 'b':
- blocksize = xatou_range(optarg, EXT2_MIN_BLOCK_SIZE, EXT2_MAX_BLOCK_SIZE);
- mke2fs_warning_msg((blocksize > 4096),
- "blocksize %d not usable on most systems",
- blocksize);
- param.s_log_block_size =
- int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
- break;
- case 'c': /* Check for bad blocks */
- case 't': /* deprecated */
- cflag++;
- break;
- case 'f':
- size = xatou_range(optarg, EXT2_MIN_BLOCK_SIZE, EXT2_MAX_BLOCK_SIZE);
- param.s_log_frag_size =
- int_log2(size >> EXT2_MIN_BLOCK_LOG_SIZE);
- mke2fs_warning_msg(1, "fragments not supported. Ignoring -f option");
- break;
- case 'g':
- param.s_blocks_per_group = xatou32(optarg);
- if ((param.s_blocks_per_group % 8) != 0) {
- bb_error_msg_and_die("blocks per group must be multiple of 8");
- }
- break;
- case 'i':
- /* Huh? is "* 1024" correct? */
- inode_ratio = xatou_range(optarg, EXT2_MIN_BLOCK_SIZE, EXT2_MAX_BLOCK_SIZE * 1024);
- break;
- case 'J':
- parse_journal_opts(&journal_device, &journal_flags, &journal_size, optarg);
- break;
- case 'j':
- param.s_feature_compat |=
- EXT3_FEATURE_COMPAT_HAS_JOURNAL;
- if (!journal_size)
- journal_size = -1;
- break;
- case 'l':
- bad_blocks_filename = optarg;
- break;
- case 'm':
- reserved_ratio = xatou_range(optarg, 0, 50);
- break;
- case 'n':
- noaction++;
- break;
- case 'o':
- creator_os = optarg;
- break;
- case 'r':
- param.s_rev_level = xatoi_positive(optarg);
- if (param.s_rev_level == EXT2_GOOD_OLD_REV) {
- param.s_feature_incompat = 0;
- param.s_feature_compat = 0;
- param.s_feature_ro_compat = 0;
- }
- break;
- case 's': /* deprecated */
- if (xatou(optarg))
- param.s_feature_ro_compat |=
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
- else
- param.s_feature_ro_compat &=
- ~EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
- break;
-#ifdef EXT2_DYNAMIC_REV
- case 'I':
- inode_size = xatoi_positive(optarg);
- break;
-#endif
- case 'N':
- num_inodes = xatoi_positive(optarg);
- break;
- case 'v':
- quiet = 0;
- break;
- case 'q':
- quiet = 1;
- break;
- case 'F':
- force = 1;
- break;
- case 'L':
- volume_label = optarg;
- break;
- case 'M':
- mount_dir = optarg;
- break;
- case 'O':
- if (!strcmp(optarg, "none")) {
- param.s_feature_compat = 0;
- param.s_feature_incompat = 0;
- param.s_feature_ro_compat = 0;
- break;
- }
- if (e2p_edit_feature(optarg,
- &param.s_feature_compat,
- ok_features)) {
- bb_error_msg_and_die("Invalid filesystem option set: %s", optarg);
- }
- break;
- case 'E':
- case 'R':
- extended_opts = optarg;
- break;
- case 'S':
- super_only = 1;
- break;
- case 'T':
- fs_type = optarg;
- break;
- case 'V':
- /* Print version number and exit */
- show_version_only = 1;
- quiet = 0;
- break;
- default:
- bb_show_usage();
- }
- }
- if ((optind == argc) /*&& !show_version_only*/)
- bb_show_usage();
- device_name = argv[optind++];
-
- mke2fs_verbose("mke2fs %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE);
-
- if (show_version_only) {
- return 0;
- }
-
- /*
- * If there's no blocksize specified and there is a journal
- * device, use it to figure out the blocksize
- */
- if (blocksize <= 0 && journal_device) {
- ext2_filsys jfs;
- io_manager io_ptr;
-
-#ifdef CONFIG_TESTIO_DEBUG
- io_ptr = test_io_manager;
- test_io_backing_manager = unix_io_manager;
-#else
- io_ptr = unix_io_manager;
-#endif
- retval = ext2fs_open(journal_device,
- EXT2_FLAG_JOURNAL_DEV_OK, 0,
- 0, io_ptr, &jfs);
- mke2fs_error_msg_and_die(retval, "open journal device %s", journal_device);
- if ((blocksize < 0) && (jfs->blocksize < (unsigned) (-blocksize))) {
- bb_error_msg_and_die(
- "Journal dev blocksize (%d) smaller than "
- "minimum blocksize %d\n", jfs->blocksize,
- -blocksize);
- }
- blocksize = jfs->blocksize;
- param.s_log_block_size =
- int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
- ext2fs_close(jfs);
- }
-
- if (blocksize > sys_page_size) {
- mke2fs_warning_msg(1, "%d-byte blocks too big for system (max %d)",
- blocksize, sys_page_size);
- if (!force) {
- proceed_question();
- }
- bb_error_msg("Forced to continue");
- }
- mke2fs_warning_msg(((blocksize > 4096) &&
- (param.s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)),
- "some 2.4 kernels do not support "
- "blocksizes greater than 4096 using ext3.\n"
- "Use -b 4096 if this is an issue for you\n");
-
- if (optind < argc) {
- param.s_blocks_count = parse_num_blocks(argv[optind++],
- param.s_log_block_size);
- mke2fs_error_msg_and_die(!param.s_blocks_count, "invalid blocks count - %s", argv[optind - 1]);
- }
- if (optind < argc)
- bb_show_usage();
-
- if (param.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
- if (!fs_type)
- fs_type = "journal";
- reserved_ratio = 0;
- param.s_feature_incompat = EXT3_FEATURE_INCOMPAT_JOURNAL_DEV;
- param.s_feature_compat = 0;
- param.s_feature_ro_compat = 0;
- }
- if (param.s_rev_level == EXT2_GOOD_OLD_REV &&
- (param.s_feature_compat || param.s_feature_ro_compat ||
- param.s_feature_incompat))
- param.s_rev_level = 1; /* Create a revision 1 filesystem */
-
- check_plausibility(device_name , force);
- check_mount(device_name, force, "filesystem");
-
- param.s_log_frag_size = param.s_log_block_size;
-
- if (noaction && param.s_blocks_count) {
- dev_size = param.s_blocks_count;
- retval = 0;
- } else {
- retry:
- retval = ext2fs_get_device_size(device_name,
- EXT2_BLOCK_SIZE(&param),
- &dev_size);
- if ((retval == EFBIG) &&
- (blocksize == 0) &&
- (param.s_log_block_size == 0)) {
- param.s_log_block_size = 2;
- blocksize = 4096;
- goto retry;
- }
- }
-
- mke2fs_error_msg_and_die((retval && (retval != EXT2_ET_UNIMPLEMENTED)),"determine filesystem size");
-
- if (!param.s_blocks_count) {
- if (retval == EXT2_ET_UNIMPLEMENTED) {
- mke2fs_error_msg_and_die(1,
- "determine device size; you "
- "must specify\nthe size of the "
- "filesystem");
- } else {
- if (dev_size == 0) {
- bb_error_msg_and_die(
- "Device size reported to be zero. "
- "Invalid partition specified, or\n\t"
- "partition table wasn't reread "
- "after running fdisk, due to\n\t"
- "a modified partition being busy "
- "and in use. You may need to reboot\n\t"
- "to re-read your partition table.\n"
- );
- }
- param.s_blocks_count = dev_size;
- if (sys_page_size > EXT2_BLOCK_SIZE(&param))
- param.s_blocks_count &= ~((sys_page_size /
- EXT2_BLOCK_SIZE(&param))-1);
- }
-
- } else if (!force && (param.s_blocks_count > dev_size)) {
- bb_error_msg("Filesystem larger than apparent device size");
- proceed_question();
- }
-
- /*
- * If the user asked for HAS_JOURNAL, then make sure a journal
- * gets created.
- */
- if ((param.s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
- !journal_size)
- journal_size = -1;
-
- /* Set first meta blockgroup via an environment variable */
- /* (this is mostly for debugging purposes) */
- if ((param.s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) &&
- ((tmp = getenv("MKE2FS_FIRST_META_BG"))))
- param.s_first_meta_bg = atoi(tmp);
-
- /* Get the hardware sector size, if available */
- retval = ext2fs_get_device_sectsize(device_name, &sector_size);
- mke2fs_error_msg_and_die(retval, "determine hardware sector size");
-
- if ((tmp = getenv("MKE2FS_DEVICE_SECTSIZE")) != NULL)
- sector_size = atoi(tmp);
-
- set_fs_defaults(fs_type, &param, blocksize, sector_size, &inode_ratio);
- blocksize = EXT2_BLOCK_SIZE(&param);
-
- if (extended_opts)
- parse_extended_opts(&param, extended_opts);
-
- /* Since sparse_super is the default, we would only have a problem
- * here if it was explicitly disabled.
- */
- if ((param.s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INO) &&
- !(param.s_feature_ro_compat&EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
- bb_error_msg_and_die("reserved online resize blocks not supported "
- "on non-sparse filesystem");
- }
-
- if (param.s_blocks_per_group) {
- if (param.s_blocks_per_group < 256 ||
- param.s_blocks_per_group > 8 * (unsigned) blocksize) {
- bb_error_msg_and_die("blocks per group count out of range");
- }
- }
-
- if (!force && param.s_blocks_count >= (1 << 31)) {
- bb_error_msg_and_die("Filesystem too large. No more than 2**31-1 blocks\n"
- "\t (8TB using a blocksize of 4k) are currently supported.");
- }
-
- if (inode_size) {
- if (inode_size < EXT2_GOOD_OLD_INODE_SIZE ||
- inode_size > EXT2_BLOCK_SIZE(&param) ||
- inode_size & (inode_size - 1)) {
- bb_error_msg_and_die("invalid inode size %d (min %d/max %d)",
- inode_size, EXT2_GOOD_OLD_INODE_SIZE,
- blocksize);
- }
- mke2fs_warning_msg((inode_size != EXT2_GOOD_OLD_INODE_SIZE),
- "%d-byte inodes not usable on most systems",
- inode_size);
- param.s_inode_size = inode_size;
- }
-
- /*
- * Calculate number of inodes based on the inode ratio
- */
- param.s_inodes_count = num_inodes ? num_inodes :
- ((__u64) param.s_blocks_count * blocksize)
- / inode_ratio;
-
- /*
- * Calculate number of blocks to reserve
- */
- param.s_r_blocks_count = (param.s_blocks_count * reserved_ratio) / 100;
- return 1;
-}
-
-static void mke2fs_clean_up(void)
-{
- if (ENABLE_FEATURE_CLEAN_UP && journal_device) free(journal_device);
-}
-
-int mkfs_ext2_main (int argc, char **argv);
-int mkfs_ext2_main (int argc, char **argv)
-{
- errcode_t retval;
- ext2_filsys fs;
- badblocks_list bb_list = 0;
- unsigned int i;
- int val;
- io_manager io_ptr;
-
- if (ENABLE_FEATURE_CLEAN_UP)
- atexit(mke2fs_clean_up);
- if (!PRS(argc, argv))
- return 0;
-
-#ifdef CONFIG_TESTIO_DEBUG
- io_ptr = test_io_manager;
- test_io_backing_manager = unix_io_manager;
-#else
- io_ptr = unix_io_manager;
-#endif
-
- /*
- * Initialize the superblock....
- */
- retval = ext2fs_initialize(device_name, 0, &param,
- io_ptr, &fs);
- mke2fs_error_msg_and_die(retval, "set up superblock");
-
- /*
- * Wipe out the old on-disk superblock
- */
- if (!noaction)
- zap_sector(fs, 2, 6);
-
- /*
- * Generate a UUID for it...
- */
- generate_uuid(fs->super->s_uuid);
-
- /*
- * Initialize the directory index variables
- */
- fs->super->s_def_hash_version = EXT2_HASH_TEA;
- generate_uuid((uint8_t *) fs->super->s_hash_seed);
-
- /*
- * Add "jitter" to the superblock's check interval so that we
- * don't check all the filesystems at the same time. We use a
- * kludgy hack of using the UUID to derive a random jitter value.
- */
- for (i = 0, val = 0; i < sizeof(fs->super->s_uuid); i++)
- val += fs->super->s_uuid[i];
- fs->super->s_max_mnt_count += val % EXT2_DFL_MAX_MNT_COUNT;
-
- /*
- * Override the creator OS, if applicable
- */
- if (creator_os && !set_os(fs->super, creator_os)) {
- bb_error_msg_and_die("unknown os - %s", creator_os);
- }
-
- /*
- * For the Hurd, we will turn off filetype since it doesn't
- * support it.
- */
- if (fs->super->s_creator_os == EXT2_OS_HURD)
- fs->super->s_feature_incompat &=
- ~EXT2_FEATURE_INCOMPAT_FILETYPE;
-
- /*
- * Set the volume label...
- */
- if (volume_label) {
- snprintf(fs->super->s_volume_name, sizeof(fs->super->s_volume_name), "%s", volume_label);
- }
-
- /*
- * Set the last mount directory
- */
- if (mount_dir) {
- snprintf(fs->super->s_last_mounted, sizeof(fs->super->s_last_mounted), "%s", mount_dir);
- }
-
- if (!quiet || noaction)
- show_stats(fs);
-
- if (noaction)
- return 0;
-
- if (fs->super->s_feature_incompat &
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
- create_journal_dev(fs);
- return (ext2fs_close(fs) ? 1 : 0);
- }
-
- if (bad_blocks_filename)
- read_bb_file(fs, &bb_list, bad_blocks_filename);
- if (cflag)
- test_disk(fs, &bb_list);
-
- handle_bad_blocks(fs, bb_list);
- fs->stride = fs_stride;
- retval = ext2fs_allocate_tables(fs);
- mke2fs_error_msg_and_die(retval, "allocate filesystem tables");
- if (super_only) {
- fs->super->s_state |= EXT2_ERROR_FS;
- fs->flags &= ~(EXT2_FLAG_IB_DIRTY|EXT2_FLAG_BB_DIRTY);
- } else {
- /* rsv must be a power of two (64kB is MD RAID sb alignment) */
- unsigned int rsv = 65536 / fs->blocksize;
- unsigned long blocks = fs->super->s_blocks_count;
- unsigned long start;
- blk_t ret_blk;
-
-#ifdef ZAP_BOOTBLOCK
- zap_sector(fs, 0, 2);
-#endif
-
- /*
- * Wipe out any old MD RAID (or other) metadata at the end
- * of the device. This will also verify that the device is
- * as large as we think. Be careful with very small devices.
- */
- start = (blocks & ~(rsv - 1));
- if (start > rsv)
- start -= rsv;
- if (start > 0)
- retval = zero_blocks(fs, start, blocks - start,
- NULL, &ret_blk, NULL);
-
- mke2fs_warning_msg(retval, "can't zero block %u at end of filesystem", ret_blk);
- write_inode_tables(fs);
- create_root_dir(fs);
- create_lost_and_found(fs);
- reserve_inodes(fs);
- create_bad_block_inode(fs, bb_list);
- if (fs->super->s_feature_compat &
- EXT2_FEATURE_COMPAT_RESIZE_INO) {
- retval = ext2fs_create_resize_inode(fs);
- mke2fs_error_msg_and_die(retval, "reserve blocks for online resize");
- }
- }
-
- if (journal_device) {
- make_journal_device(journal_device, fs, quiet, force);
- } else if (journal_size) {
- make_journal_blocks(fs, journal_size, journal_flags, quiet);
- }
-
- mke2fs_verbose("Writing superblocks and filesystem accounting information: ");
- retval = ext2fs_flush(fs);
- mke2fs_warning_msg(retval, "had trouble writing out superblocks");
- mke2fs_verbose_done();
- if (!quiet && !getenv("MKE2FS_SKIP_CHECK_MSG"))
- print_check_message(fs);
- val = ext2fs_close(fs);
- return (retval || val) ? 1 : 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/tune2fs.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/tune2fs.c
deleted file mode 100644
index 464f18d612..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/tune2fs.c
+++ /dev/null
@@ -1,727 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * tune2fs.c - Change the file system parameters on an ext2 file system
- *
- * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr>
- * Laboratoire MASI, Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o.
- *
- * Licensed under GPLv2, see file LICENSE in this source tree.
- */
-
-//usage:#define tune2fs_trivial_usage
-//usage: "[-c MOUNT_CNT] "
-//usage: "[-e errors-behavior] [-g group] "
-//usage: "[-i DAYS] "
-//usage: "[-j] [-J journal-options] [-l] [-s sparse-flag] "
-//usage: "[-m reserved-blocks-percent] [-o [^]mount-options[,...]] "
-//usage: "[-r reserved-blocks-count] [-u user] [-C mount-count] "
-//usage: "[-L LABEL] "
-//usage: "[-M last-mounted-dir] [-O [^]feature[,...]] "
-//usage: "[-T last-check-time] [-U UUID] "
-//usage: "BLOCKDEV"
-//usage:
-//usage:#define tune2fs_full_usage "\n\n"
-//usage: "Adjust filesystem options on ext[23] filesystems"
-
-/*
- * History:
- * 93/06/01 - Creation
- * 93/10/31 - Added the -c option to change the maximal mount counts
- * 93/12/14 - Added -l flag to list contents of superblock
- * M.J.E. Mol (marcel@duteca.et.tudelft.nl)
- * F.W. ten Wolde (franky@duteca.et.tudelft.nl)
- * 93/12/29 - Added the -e option to change errors behavior
- * 94/02/27 - Ported to use the ext2fs library
- * 94/03/06 - Added the checks interval from Uwe Ohse (uwe@tirka.gun.de)
- */
-
-#include <sys/types.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <getopt.h>
-
-#include "e2fsbb.h"
-#include "ext2fs/ext2_fs.h"
-#include "ext2fs/ext2fs.h"
-#include "e2fs_lib.h"
-#include "e2p/e2p.h"
-#include "ext2fs/kernel-jbd.h"
-#include "util.h"
-#include "volume_id.h"
-
-#include "libbb.h"
-
-static char * device_name = NULL;
-static char * new_label, *new_last_mounted, *new_UUID;
-static char * io_options;
-static int c_flag, C_flag, e_flag, f_flag, g_flag, i_flag, l_flag, L_flag;
-static int m_flag, M_flag, r_flag, s_flag = -1, u_flag, U_flag, T_flag;
-static time_t last_check_time;
-static int print_label;
-static int max_mount_count, mount_count, mount_flags;
-static unsigned long interval, reserved_blocks;
-static unsigned reserved_ratio;
-static unsigned long resgid, resuid;
-static unsigned short errors;
-static int open_flag;
-static char *features_cmd;
-static char *mntopts_cmd;
-
-static int journal_size, journal_flags;
-static char *journal_device = NULL;
-
-static const char *please_fsck = "Please run e2fsck on the filesystem\n";
-
-static __u32 ok_features[3] = {
- EXT3_FEATURE_COMPAT_HAS_JOURNAL | EXT2_FEATURE_COMPAT_DIR_INDEX,
- EXT2_FEATURE_INCOMPAT_FILETYPE,
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
-};
-
-/*
- * Remove an external journal from the filesystem
- */
-static void remove_journal_device(ext2_filsys fs)
-{
- char *journal_path;
- ext2_filsys jfs;
- char buf[1024];
- journal_superblock_t *jsb;
- int i, nr_users;
- errcode_t retval;
- int commit_remove_journal = 0;
- io_manager io_ptr;
-
- if (f_flag)
- commit_remove_journal = 1; /* force removal even if error */
-
- unparse_uuid(fs->super->s_journal_uuid, buf);
- journal_path = get_devname_from_uuid(buf);
-
- if (!journal_path) {
- journal_path =
- ext2fs_find_block_device(fs->super->s_journal_dev);
- if (!journal_path)
- return;
- }
-
- io_ptr = unix_io_manager;
- retval = ext2fs_open(journal_path, EXT2_FLAG_RW|
- EXT2_FLAG_JOURNAL_DEV_OK, 0,
- fs->blocksize, io_ptr, &jfs);
- if (retval) {
- bb_error_msg("Failed to open external journal");
- goto no_valid_journal;
- }
- if (!(jfs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
- bb_error_msg("%s is not a journal device", journal_path);
- goto no_valid_journal;
- }
-
- /* Get the journal superblock */
- if ((retval = io_channel_read_blk(jfs->io, 1, -1024, buf))) {
- bb_error_msg("Failed to read journal superblock");
- goto no_valid_journal;
- }
-
- jsb = (journal_superblock_t *) buf;
- if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) ||
- (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2))) {
- bb_error_msg("Journal superblock not found!");
- goto no_valid_journal;
- }
-
- /* Find the filesystem UUID */
- nr_users = ntohl(jsb->s_nr_users);
- for (i=0; i < nr_users; i++) {
- if (memcmp(fs->super->s_uuid,
- &jsb->s_users[i*16], 16) == 0)
- break;
- }
- if (i >= nr_users) {
- bb_error_msg("Filesystem's UUID not found on journal device");
- commit_remove_journal = 1;
- goto no_valid_journal;
- }
- nr_users--;
- for (i=0; i < nr_users; i++)
- memcpy(&jsb->s_users[i*16], &jsb->s_users[(i+1)*16], 16);
- jsb->s_nr_users = htonl(nr_users);
-
- /* Write back the journal superblock */
- if ((retval = io_channel_write_blk(jfs->io, 1, -1024, buf))) {
- bb_error_msg("Failed to write journal superblock");
- goto no_valid_journal;
- }
-
- commit_remove_journal = 1;
-
-no_valid_journal:
- if (commit_remove_journal == 0)
- bb_error_msg_and_die("Journal NOT removed");
- fs->super->s_journal_dev = 0;
- uuid_clear(fs->super->s_journal_uuid);
- ext2fs_mark_super_dirty(fs);
- puts("Journal removed");
- free(journal_path);
-}
-
-/* Helper function for remove_journal_inode */
-static int release_blocks_proc(ext2_filsys fs, blk_t *blocknr,
- int blockcnt EXT2FS_ATTR((unused)),
- void *private EXT2FS_ATTR((unused)))
-{
- blk_t block;
- int group;
-
- block = *blocknr;
- ext2fs_unmark_block_bitmap(fs->block_map,block);
- group = ext2fs_group_of_blk(fs, block);
- fs->group_desc[group].bg_free_blocks_count++;
- fs->super->s_free_blocks_count++;
- return 0;
-}
-
-/*
- * Remove the journal inode from the filesystem
- */
-static void remove_journal_inode(ext2_filsys fs)
-{
- struct ext2_inode inode;
- errcode_t retval;
- ino_t ino = fs->super->s_journal_inum;
- const char *msg = "to read";
- const char *s = "journal inode";
-
- retval = ext2fs_read_inode(fs, ino, &inode);
- if (retval)
- goto REMOVE_JOURNAL_INODE_ERROR;
- if (ino == EXT2_JOURNAL_INO) {
- retval = ext2fs_read_bitmaps(fs);
- if (retval) {
- msg = "to read bitmaps";
- s = "";
- goto REMOVE_JOURNAL_INODE_ERROR;
- }
- retval = ext2fs_block_iterate(fs, ino, 0, NULL,
- release_blocks_proc, NULL);
- if (retval) {
- msg = "clearing";
- goto REMOVE_JOURNAL_INODE_ERROR;
- }
- memset(&inode, 0, sizeof(inode));
- ext2fs_mark_bb_dirty(fs);
- fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
- } else
- inode.i_flags &= ~EXT2_IMMUTABLE_FL;
- retval = ext2fs_write_inode(fs, ino, &inode);
- if (retval) {
- msg = "writing";
-REMOVE_JOURNAL_INODE_ERROR:
- bb_error_msg_and_die("Failed %s %s", msg, s);
- }
- fs->super->s_journal_inum = 0;
- ext2fs_mark_super_dirty(fs);
-}
-
-/*
- * Update the default mount options
- */
-static void update_mntopts(ext2_filsys fs, char *mntopts)
-{
- struct ext2_super_block *sb= fs->super;
-
- if (e2p_edit_mntopts(mntopts, &sb->s_default_mount_opts, ~0))
- bb_error_msg_and_die("Invalid mount option set: %s", mntopts);
- ext2fs_mark_super_dirty(fs);
-}
-
-/*
- * Update the feature set as provided by the user.
- */
-static void update_feature_set(ext2_filsys fs, char *features)
-{
- int sparse, old_sparse, filetype, old_filetype;
- int journal, old_journal, dxdir, old_dxdir;
- struct ext2_super_block *sb= fs->super;
- __u32 old_compat, old_incompat, old_ro_compat;
-
- old_compat = sb->s_feature_compat;
- old_ro_compat = sb->s_feature_ro_compat;
- old_incompat = sb->s_feature_incompat;
-
- old_sparse = sb->s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
- old_filetype = sb->s_feature_incompat &
- EXT2_FEATURE_INCOMPAT_FILETYPE;
- old_journal = sb->s_feature_compat &
- EXT3_FEATURE_COMPAT_HAS_JOURNAL;
- old_dxdir = sb->s_feature_compat &
- EXT2_FEATURE_COMPAT_DIR_INDEX;
- if (e2p_edit_feature(features, &sb->s_feature_compat, ok_features))
- bb_error_msg_and_die("Invalid filesystem option set: %s", features);
- sparse = sb->s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
- filetype = sb->s_feature_incompat &
- EXT2_FEATURE_INCOMPAT_FILETYPE;
- journal = sb->s_feature_compat &
- EXT3_FEATURE_COMPAT_HAS_JOURNAL;
- dxdir = sb->s_feature_compat &
- EXT2_FEATURE_COMPAT_DIR_INDEX;
- if (old_journal && !journal) {
- if ((mount_flags & EXT2_MF_MOUNTED) &&
- !(mount_flags & EXT2_MF_READONLY)) {
- bb_error_msg_and_die(
- "The has_journal flag may only be "
- "cleared when the filesystem is\n"
- "unmounted or mounted "
- "read-only");
- }
- if (sb->s_feature_incompat &
- EXT3_FEATURE_INCOMPAT_RECOVER) {
- bb_error_msg_and_die(
- "The needs_recovery flag is set. "
- "%s before clearing the has_journal flag.",
- please_fsck);
- }
- if (sb->s_journal_inum) {
- remove_journal_inode(fs);
- }
- if (sb->s_journal_dev) {
- remove_journal_device(fs);
- }
- }
- if (journal && !old_journal) {
- /*
- * If adding a journal flag, let the create journal
- * code below handle creating setting the flag and
- * creating the journal. We supply a default size if
- * necessary.
- */
- if (!journal_size)
- journal_size = -1;
- sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
- }
- if (dxdir && !old_dxdir) {
- if (!sb->s_def_hash_version)
- sb->s_def_hash_version = EXT2_HASH_TEA;
- if (uuid_is_null((unsigned char *) sb->s_hash_seed))
- generate_uuid((unsigned char *) sb->s_hash_seed);
- }
-
- if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
- (sb->s_feature_compat || sb->s_feature_ro_compat ||
- sb->s_feature_incompat))
- ext2fs_update_dynamic_rev(fs);
- if ((sparse != old_sparse) ||
- (filetype != old_filetype)) {
- sb->s_state &= ~EXT2_VALID_FS;
- printf("\n%s\n", please_fsck);
- }
- if ((old_compat != sb->s_feature_compat) ||
- (old_ro_compat != sb->s_feature_ro_compat) ||
- (old_incompat != sb->s_feature_incompat))
- ext2fs_mark_super_dirty(fs);
-}
-
-/*
- * Add a journal to the filesystem.
- */
-static void add_journal(ext2_filsys fs)
-{
- if (fs->super->s_feature_compat &
- EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
- bb_error_msg_and_die("The filesystem already has a journal");
- }
- if (journal_device) {
- make_journal_device(journal_device, fs, 0, 0);
- } else if (journal_size) {
- make_journal_blocks(fs, journal_size, journal_flags, 0);
- /*
- * If the filesystem wasn't mounted, we need to force
- * the block group descriptors out.
- */
- if ((mount_flags & EXT2_MF_MOUNTED) == 0)
- fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
- }
- print_check_message(fs);
-}
-
-/*
- * Busybox stuff
- */
-static char * x_blkid_get_devname(const char *token)
-{
- char *dev_name = (char *)token;
-
- if (resolve_mount_spec(&dev_name) != 1 || !dev_name)
- bb_error_msg_and_die("Unable to resolve '%s'", token);
- return dev_name;
-}
-
-#ifdef CONFIG_E2LABEL
-static void parse_e2label_options(int argc, char ** argv)
-{
- if ((argc < 2) || (argc > 3))
- bb_show_usage();
- io_options = strchr(argv[1], '?');
- if (io_options)
- *io_options++ = 0;
- device_name = x_blkid_get_devname(argv[1]);
- if (argc == 3) {
- open_flag = EXT2_FLAG_RW | EXT2_FLAG_JOURNAL_DEV_OK;
- L_flag = 1;
- new_label = argv[2];
- } else
- print_label++;
-}
-#else
-#define parse_e2label_options(x,y)
-#endif
-
-static time_t parse_time(char *str)
-{
- struct tm ts;
-
- if (strcmp(str, "now") == 0) {
- return time(0);
- }
- memset(&ts, 0, sizeof(ts));
-#ifdef HAVE_STRPTIME
- strptime(str, "%Y%m%d%H%M%S", &ts);
-#else
- sscanf(str, "%4d%2d%2d%2d%2d%2d", &ts.tm_year, &ts.tm_mon,
- &ts.tm_mday, &ts.tm_hour, &ts.tm_min, &ts.tm_sec);
- ts.tm_year -= 1900;
- ts.tm_mon -= 1;
- if (ts.tm_year < 0 || ts.tm_mon < 0 || ts.tm_mon > 11 ||
- ts.tm_mday < 0 || ts.tm_mday > 31 || ts.tm_hour > 23 ||
- ts.tm_min > 59 || ts.tm_sec > 61)
- ts.tm_mday = 0;
-#endif
- if (ts.tm_mday == 0) {
- bb_error_msg_and_die("can't parse date/time specifier: %s", str);
- }
- return mktime(&ts);
-}
-
-static void parse_tune2fs_options(int argc, char **argv)
-{
- int c;
- char * tmp;
-
- printf("tune2fs %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE);
- while ((c = getopt(argc, argv, "c:e:fg:i:jlm:o:r:s:u:C:J:L:M:O:T:U:")) != EOF)
- switch (c)
- {
- case 'c':
- max_mount_count = xatou_range(optarg, 0, 16000);
- if (max_mount_count == 0)
- max_mount_count = -1;
- c_flag = 1;
- open_flag = EXT2_FLAG_RW;
- break;
- case 'C':
- mount_count = xatou_range(optarg, 0, 16000);
- C_flag = 1;
- open_flag = EXT2_FLAG_RW;
- break;
- case 'e':
- if (strcmp (optarg, "continue") == 0)
- errors = EXT2_ERRORS_CONTINUE;
- else if (strcmp (optarg, "remount-ro") == 0)
- errors = EXT2_ERRORS_RO;
- else if (strcmp (optarg, "panic") == 0)
- errors = EXT2_ERRORS_PANIC;
- else {
- bb_error_msg_and_die("bad error behavior - %s", optarg);
- }
- e_flag = 1;
- open_flag = EXT2_FLAG_RW;
- break;
- case 'f': /* Force */
- f_flag = 1;
- break;
- case 'g':
- resgid = bb_strtoul(optarg, NULL, 10);
- if (errno)
- resgid = xgroup2gid(optarg);
- g_flag = 1;
- open_flag = EXT2_FLAG_RW;
- break;
- case 'i':
- interval = strtoul(optarg, &tmp, 0);
- switch (*tmp) {
- case 's':
- tmp++;
- break;
- case '\0':
- case 'd':
- case 'D': /* days */
- interval *= 86400;
- if (*tmp != '\0')
- tmp++;
- break;
- case 'm':
- case 'M': /* months! */
- interval *= 86400 * 30;
- tmp++;
- break;
- case 'w':
- case 'W': /* weeks */
- interval *= 86400 * 7;
- tmp++;
- break;
- }
- if (*tmp || interval > (365 * 86400)) {
- bb_error_msg_and_die("bad interval - %s", optarg);
- }
- i_flag = 1;
- open_flag = EXT2_FLAG_RW;
- break;
- case 'j':
- if (!journal_size)
- journal_size = -1;
- open_flag = EXT2_FLAG_RW;
- break;
- case 'J':
- parse_journal_opts(&journal_device, &journal_flags, &journal_size, optarg);
- open_flag = EXT2_FLAG_RW;
- break;
- case 'l':
- l_flag = 1;
- break;
- case 'L':
- new_label = optarg;
- L_flag = 1;
- open_flag = EXT2_FLAG_RW |
- EXT2_FLAG_JOURNAL_DEV_OK;
- break;
- case 'm':
- reserved_ratio = xatou_range(optarg, 0, 50);
- m_flag = 1;
- open_flag = EXT2_FLAG_RW;
- break;
- case 'M':
- new_last_mounted = optarg;
- M_flag = 1;
- open_flag = EXT2_FLAG_RW;
- break;
- case 'o':
- if (mntopts_cmd) {
- bb_error_msg_and_die("-o may only be specified once");
- }
- mntopts_cmd = optarg;
- open_flag = EXT2_FLAG_RW;
- break;
-
- case 'O':
- if (features_cmd) {
- bb_error_msg_and_die("-O may only be specified once");
- }
- features_cmd = optarg;
- open_flag = EXT2_FLAG_RW;
- break;
- case 'r':
- reserved_blocks = xatoul(optarg);
- r_flag = 1;
- open_flag = EXT2_FLAG_RW;
- break;
- case 's':
- s_flag = atoi(optarg);
- open_flag = EXT2_FLAG_RW;
- break;
- case 'T':
- T_flag = 1;
- last_check_time = parse_time(optarg);
- open_flag = EXT2_FLAG_RW;
- break;
- case 'u':
- resuid = bb_strtoul(optarg, NULL, 10);
- if (errno)
- resuid = xuname2uid(optarg);
- u_flag = 1;
- open_flag = EXT2_FLAG_RW;
- break;
- case 'U':
- new_UUID = optarg;
- U_flag = 1;
- open_flag = EXT2_FLAG_RW |
- EXT2_FLAG_JOURNAL_DEV_OK;
- break;
- default:
- bb_show_usage();
- }
- if (optind < argc - 1 || optind == argc)
- bb_show_usage();
- if (!open_flag && !l_flag)
- bb_show_usage();
- io_options = strchr(argv[optind], '?');
- if (io_options)
- *io_options++ = 0;
- device_name = x_blkid_get_devname(argv[optind]);
-}
-
-static void tune2fs_clean_up(void)
-{
- if (ENABLE_FEATURE_CLEAN_UP && device_name) free(device_name);
- if (ENABLE_FEATURE_CLEAN_UP && journal_device) free(journal_device);
-}
-
-int tune2fs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int tune2fs_main(int argc, char **argv)
-{
- errcode_t retval;
- ext2_filsys fs;
- struct ext2_super_block *sb;
- io_manager io_ptr;
-
- if (ENABLE_FEATURE_CLEAN_UP)
- atexit(tune2fs_clean_up);
-
- if (ENABLE_E2LABEL && (applet_name[0] == 'e')) /* e2label */
- parse_e2label_options(argc, argv);
- else
- parse_tune2fs_options(argc, argv); /* tune2fs */
-
- io_ptr = unix_io_manager;
- retval = ext2fs_open2(device_name, io_options, open_flag,
- 0, 0, io_ptr, &fs);
- if (retval)
- bb_error_msg_and_die("No valid superblock on %s", device_name);
- sb = fs->super;
- if (print_label) {
- /* For e2label emulation */
- printf("%.*s\n", (int) sizeof(sb->s_volume_name),
- sb->s_volume_name);
- return 0;
- }
- retval = ext2fs_check_if_mounted(device_name, &mount_flags);
- if (retval)
- bb_error_msg_and_die("can't determine if %s is mounted", device_name);
- /* Normally we only need to write out the superblock */
- fs->flags |= EXT2_FLAG_SUPER_ONLY;
-
- if (c_flag) {
- sb->s_max_mnt_count = max_mount_count;
- ext2fs_mark_super_dirty(fs);
- printf("Setting maximal mount count to %d\n", max_mount_count);
- }
- if (C_flag) {
- sb->s_mnt_count = mount_count;
- ext2fs_mark_super_dirty(fs);
- printf("Setting current mount count to %d\n", mount_count);
- }
- if (e_flag) {
- sb->s_errors = errors;
- ext2fs_mark_super_dirty(fs);
- printf("Setting error behavior to %d\n", errors);
- }
- if (g_flag) {
- sb->s_def_resgid = resgid;
- ext2fs_mark_super_dirty(fs);
- printf("Setting reserved blocks gid to %lu\n", resgid);
- }
- if (i_flag) {
- sb->s_checkinterval = interval;
- ext2fs_mark_super_dirty(fs);
- printf("Setting interval between check %lu seconds\n", interval);
- }
- if (m_flag) {
- sb->s_r_blocks_count = (sb->s_blocks_count / 100)
- * reserved_ratio;
- ext2fs_mark_super_dirty(fs);
- printf("Setting reserved blocks percentage to %u (%u blocks)\n",
- reserved_ratio, sb->s_r_blocks_count);
- }
- if (r_flag) {
- if (reserved_blocks >= sb->s_blocks_count/2)
- bb_error_msg_and_die("reserved blocks count is too big (%lu)", reserved_blocks);
- sb->s_r_blocks_count = reserved_blocks;
- ext2fs_mark_super_dirty(fs);
- printf("Setting reserved blocks count to %lu\n", reserved_blocks);
- }
- if (s_flag == 1) {
- if (sb->s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)
- bb_error_msg("\nThe filesystem already has sparse superblocks");
- else {
- sb->s_feature_ro_compat |=
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
- sb->s_state &= ~EXT2_VALID_FS;
- ext2fs_mark_super_dirty(fs);
- printf("\nSparse superblock flag set. %s", please_fsck);
- }
- }
- if (s_flag == 0) {
- if (!(sb->s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
- bb_error_msg("\nThe filesystem already has sparse superblocks disabled");
- else {
- sb->s_feature_ro_compat &=
- ~EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
- sb->s_state &= ~EXT2_VALID_FS;
- fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
- ext2fs_mark_super_dirty(fs);
- printf("\nSparse superblock flag cleared. %s", please_fsck);
- }
- }
- if (T_flag) {
- sb->s_lastcheck = last_check_time;
- ext2fs_mark_super_dirty(fs);
- printf("Setting time filesystem last checked to %s\n",
- ctime(&last_check_time));
- }
- if (u_flag) {
- sb->s_def_resuid = resuid;
- ext2fs_mark_super_dirty(fs);
- printf("Setting reserved blocks uid to %lu\n", resuid);
- }
- if (L_flag) {
- if (strlen(new_label) > sizeof(sb->s_volume_name))
- bb_error_msg("Warning: label too long, truncating");
- memset(sb->s_volume_name, 0, sizeof(sb->s_volume_name));
- safe_strncpy(sb->s_volume_name, new_label,
- sizeof(sb->s_volume_name));
- ext2fs_mark_super_dirty(fs);
- }
- if (M_flag) {
- memset(sb->s_last_mounted, 0, sizeof(sb->s_last_mounted));
- safe_strncpy(sb->s_last_mounted, new_last_mounted,
- sizeof(sb->s_last_mounted));
- ext2fs_mark_super_dirty(fs);
- }
- if (mntopts_cmd)
- update_mntopts(fs, mntopts_cmd);
- if (features_cmd)
- update_feature_set(fs, features_cmd);
- if (journal_size || journal_device)
- add_journal(fs);
-
- if (U_flag) {
- if ((strcasecmp(new_UUID, "null") == 0) ||
- (strcasecmp(new_UUID, "clear") == 0)) {
- uuid_clear(sb->s_uuid);
-/*
- } else if (strcasecmp(new_UUID, "time") == 0) {
- uuid_generate_time(sb->s_uuid);
-*/
- } else if (strcasecmp(new_UUID, "random") == 0) {
- generate_uuid(sb->s_uuid);
- } else if (parse_uuid(new_UUID, sb->s_uuid)) {
- bb_error_msg_and_die("Invalid UUID format");
- }
- ext2fs_mark_super_dirty(fs);
- }
-
- if (l_flag)
- list_super (sb);
- return (ext2fs_close (fs) ? 1 : 0);
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/util.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/util.c
deleted file mode 100644
index ca1837bcb6..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/util.c
+++ /dev/null
@@ -1,264 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * util.c --- helper functions used by tune2fs and mke2fs
- *
- * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o.
- *
- * Licensed under GPLv2, see file LICENSE in this source tree.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <linux/major.h>
-#include <sys/stat.h>
-
-#include "e2fsbb.h"
-#include "e2p/e2p.h"
-#include "ext2fs/ext2_fs.h"
-#include "ext2fs/ext2fs.h"
-#include "volume_id.h"
-#include "util.h"
-
-void proceed_question(void)
-{
- fputs("Proceed anyway? (y,n) ", stdout);
- if (bb_ask_confirmation() == 0)
- exit(1);
-}
-
-void check_plausibility(const char *device, int force)
-{
- int val;
- struct stat s;
- val = stat(device, &s);
- if (force)
- return;
- if (val == -1)
- bb_perror_msg_and_die("can't stat '%s'", device);
- if (!S_ISBLK(s.st_mode)) {
- printf("%s is not a block special device.\n", device);
- proceed_question();
- return;
- }
-
-#ifdef HAVE_LINUX_MAJOR_H
-#ifndef MAJOR
-#define MAJOR(dev) ((dev)>>8)
-#define MINOR(dev) ((dev) & 0xff)
-#endif
-#ifndef SCSI_BLK_MAJOR
-#ifdef SCSI_DISK0_MAJOR
-#ifdef SCSI_DISK8_MAJOR
-#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
- ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR) || \
- ((M) >= SCSI_DISK8_MAJOR && (M) <= SCSI_DISK15_MAJOR))
-#else
-#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
- ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
-#endif /* defined(SCSI_DISK8_MAJOR) */
-#define SCSI_BLK_MAJOR(M) (SCSI_DISK_MAJOR((M)) || (M) == SCSI_CDROM_MAJOR)
-#else
-#define SCSI_BLK_MAJOR(M) ((M) == SCSI_DISK_MAJOR || (M) == SCSI_CDROM_MAJOR)
-#endif /* defined(SCSI_DISK0_MAJOR) */
-#endif /* defined(SCSI_BLK_MAJOR) */
- if (((MAJOR(s.st_rdev) == HD_MAJOR &&
- MINOR(s.st_rdev)%64 == 0) ||
- (SCSI_BLK_MAJOR(MAJOR(s.st_rdev)) &&
- MINOR(s.st_rdev)%16 == 0))) {
- printf("%s is entire device, not just one partition!\n", device);
- proceed_question();
- }
-#endif
-}
-
-void check_mount(const char *device, int force, const char *type UNUSED_PARAM)
-{
- errcode_t retval;
- int mount_flags;
-
- retval = ext2fs_check_if_mounted(device, &mount_flags);
- if (retval) {
- bb_error_msg("can't determine if %s is mounted", device);
- return;
- }
- if (mount_flags & EXT2_MF_MOUNTED) {
- bb_error_msg("%s is mounted !", device);
-force_check:
- if (force)
- bb_error_msg("badblocks forced anyways");
- else
- bb_error_msg_and_die("it's not safe to run badblocks!");
- }
-
- if (mount_flags & EXT2_MF_BUSY) {
- bb_error_msg("%s is apparently in use by the system", device);
- goto force_check;
- }
-}
-
-void parse_journal_opts(char **journal_device, int *journal_flags,
- int *journal_size, const char *opts)
-{
- char *buf, *token, *next, *p, *arg;
- int journal_usage = 0;
- buf = xstrdup(opts);
- for (token = buf; token && *token; token = next) {
- p = strchr(token, ',');
- next = 0;
- if (p) {
- *p = 0;
- next = p+1;
- }
- arg = strchr(token, '=');
- if (arg) {
- *arg = 0;
- arg++;
- }
- if (strcmp(token, "device") == 0) {
- *journal_device = arg;
- if (resolve_mount_spec(journal_device) < 0 ||
- !(*journal_device)) {
- journal_usage++;
- continue;
- }
- } else if (strcmp(token, "size") == 0) {
- if (!arg) {
- journal_usage++;
- continue;
- }
- (*journal_size) = strtoul(arg, &p, 0);
- if (*p)
- journal_usage++;
- } else if (strcmp(token, "v1_superblock") == 0) {
- (*journal_flags) |= EXT2_MKJOURNAL_V1_SUPER;
- continue;
- } else
- journal_usage++;
- }
- if (journal_usage)
- bb_error_msg_and_die(
- "\nBad journal options specified.\n\n"
- "Journal options are separated by commas, "
- "and may take an argument which\n"
- "\tis set off by an equals ('=') sign.\n\n"
- "Valid journal options are:\n"
- "\tsize=<journal size in megabytes>\n"
- "\tdevice=<journal device>\n\n"
- "The journal size must be between "
- "1024 and 102400 filesystem blocks.\n\n");
-}
-
-/*
- * Determine the number of journal blocks to use, either via
- * user-specified # of megabytes, or via some intelligently selected
- * defaults.
- *
- * Find a reasonable journal file size (in blocks) given the number of blocks
- * in the filesystem. For very small filesystems, it is not reasonable to
- * have a journal that fills more than half of the filesystem.
- */
-int figure_journal_size(int size, ext2_filsys fs)
-{
- blk_t j_blocks;
-
- if (fs->super->s_blocks_count < 2048) {
- bb_error_msg("Filesystem too small for a journal");
- return 0;
- }
-
- if (size >= 0) {
- j_blocks = size * 1024 / (fs->blocksize / 1024);
- if (j_blocks < 1024 || j_blocks > 102400)
- bb_error_msg_and_die("\nThe requested journal "
- "size is %d blocks;\n it must be "
- "between 1024 and 102400 blocks; Aborting",
- j_blocks);
- if (j_blocks > fs->super->s_free_blocks_count)
- bb_error_msg_and_die("Journal size too big for filesystem");
- return j_blocks;
- }
-
- if (fs->super->s_blocks_count < 32768)
- j_blocks = 1024;
- else if (fs->super->s_blocks_count < 256*1024)
- j_blocks = 4096;
- else if (fs->super->s_blocks_count < 512*1024)
- j_blocks = 8192;
- else if (fs->super->s_blocks_count < 1024*1024)
- j_blocks = 16384;
- else
- j_blocks = 32768;
-
- return j_blocks;
-}
-
-void print_check_message(ext2_filsys fs)
-{
- printf("This filesystem will be automatically "
- "checked every %d mounts or\n"
- "%g days, whichever comes first. "
- "Use tune2fs -c or -i to override.\n",
- fs->super->s_max_mnt_count,
- (double)fs->super->s_checkinterval / (3600 * 24));
-}
-
-void make_journal_device(char *journal_device, ext2_filsys fs, int quiet, int force)
-{
- errcode_t retval;
- ext2_filsys jfs;
- io_manager io_ptr;
-
- check_plausibility(journal_device, force);
- check_mount(journal_device, force, "journal");
- io_ptr = unix_io_manager;
- retval = ext2fs_open(journal_device, EXT2_FLAG_RW|
- EXT2_FLAG_JOURNAL_DEV_OK, 0,
- fs->blocksize, io_ptr, &jfs);
- if (retval)
- bb_error_msg_and_die("can't journal device %s", journal_device);
- if (!quiet)
- printf("Adding journal to device %s: ", journal_device);
- fflush(stdout);
- retval = ext2fs_add_journal_device(fs, jfs);
- if (retval)
- bb_error_msg_and_die("\nFailed to add journal to device %s", journal_device);
- if (!quiet)
- puts("done");
- ext2fs_close(jfs);
-}
-
-void make_journal_blocks(ext2_filsys fs, int journal_size, int journal_flags, int quiet)
-{
- unsigned long journal_blocks;
- errcode_t retval;
-
- journal_blocks = figure_journal_size(journal_size, fs);
- if (!journal_blocks) {
- fs->super->s_feature_compat &=
- ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
- return;
- }
- if (!quiet)
- printf("Creating journal (%ld blocks): ", journal_blocks);
- fflush(stdout);
- retval = ext2fs_add_journal_inode(fs, journal_blocks,
- journal_flags);
- if (retval)
- bb_error_msg_and_die("can't create journal");
- if (!quiet)
- puts("done");
-}
-
-char *e2fs_set_sbin_path(void)
-{
- char *oldpath = getenv("PATH");
- /* Update our PATH to include /sbin */
-#define PATH_SET "/sbin"
- if (oldpath)
- oldpath = xasprintf("%s:%s", PATH_SET, oldpath);
- else
- oldpath = (char *)PATH_SET;
- putenv(oldpath);
- return oldpath;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/util.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/util.h
deleted file mode 100644
index 80d2417185..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/util.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * util.h --- header file defining prototypes for helper functions
- * used by tune2fs and mke2fs
- *
- * Copyright 2000 by Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-extern void proceed_question(void);
-extern void check_plausibility(const char *device, int force);
-extern void parse_journal_opts(char **, int *, int *, const char *opts);
-extern void check_mount(const char *device, int force, const char *type);
-extern int figure_journal_size(int size, ext2_filsys fs);
-extern void print_check_message(ext2_filsys fs);
-extern void make_journal_device(char *journal_device, ext2_filsys fs, int quiet, int force);
-extern void make_journal_blocks(ext2_filsys fs, int journal_size, int journal_flags, int quiet);
-extern char *e2fs_set_sbin_path(void);
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/Kbuild.src b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/Kbuild.src
deleted file mode 100644
index b8c687d30c..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/Kbuild.src
+++ /dev/null
@@ -1,16 +0,0 @@
-# Makefile for busybox
-#
-# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
-#
-# Licensed under GPLv2, see file LICENSE in this source tree.
-
-NEEDED-$(CONFIG_E2FSCK) = y
-NEEDED-$(CONFIG_FSCK) = y
-NEEDED-$(CONFIG_MKE2FS) = y
-NEEDED-$(CONFIG_TUNE2FS) = y
-
-lib-y:=
-
-INSERT
-lib-$(NEEDED-y) += compare.o gen_uuid.o pack.o parse.o unpack.o unparse.o \
- uuid_time.o
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/compare.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/compare.c
deleted file mode 100644
index 348ea7c1f9..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/compare.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * compare.c --- compare whether or not two UUID's are the same
- *
- * Returns 0 if the two UUID's are different, and 1 if they are the same.
- *
- * Copyright (C) 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, and the entire permission notice in its entirety,
- * including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
- * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- * %End-Header%
- */
-
-#include "uuidP.h"
-#include <string.h>
-
-#define UUCMP(u1,u2) if (u1 != u2) return (u1 < u2) ? -1 : 1;
-
-int uuid_compare(const uuid_t uu1, const uuid_t uu2)
-{
- struct uuid uuid1, uuid2;
-
- uuid_unpack(uu1, &uuid1);
- uuid_unpack(uu2, &uuid2);
-
- UUCMP(uuid1.time_low, uuid2.time_low);
- UUCMP(uuid1.time_mid, uuid2.time_mid);
- UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version);
- UUCMP(uuid1.clock_seq, uuid2.clock_seq);
- return memcmp(uuid1.node, uuid2.node, 6);
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/gen_uuid.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/gen_uuid.c
deleted file mode 100644
index 4310c17db9..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/gen_uuid.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * gen_uuid.c --- generate a DCE-compatible uuid
- *
- * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o.
- *
- * %Begin-Header%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, and the entire permission notice in its entirety,
- * including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
- * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- * %End-Header%
- */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/file.h>
-#include <sys/time.h>
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#include <sys/socket.h>
-#ifdef HAVE_SYS_SOCKIO_H
-#include <sys/sockio.h>
-#endif
-#ifdef HAVE_NET_IF_H
-#include <net/if.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_NET_IF_DL_H
-#include <net/if_dl.h>
-#endif
-
-#include "uuidP.h"
-
-#ifdef HAVE_SRANDOM
-#define srand(x) srandom(x)
-#define rand() random()
-#endif
-
-static int get_random_fd(void)
-{
- struct timeval tv;
- static int fd = -2;
- int i;
-
- if (fd == -2) {
- gettimeofday(&tv, 0);
- fd = open("/dev/urandom", O_RDONLY);
- if (fd == -1)
- fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
- srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
- }
- /* Crank the random number generator a few times */
- gettimeofday(&tv, 0);
- for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
- rand();
- return fd;
-}
-
-
-/*
- * Generate a series of random bytes. Use /dev/urandom if possible,
- * and if not, use srandom/random.
- */
-static void get_random_bytes(void *buf, int nbytes)
-{
- int i, n = nbytes, fd = get_random_fd();
- int lose_counter = 0;
- unsigned char *cp = (unsigned char *) buf;
-
- if (fd >= 0) {
- while (n > 0) {
- i = read(fd, cp, n);
- if (i <= 0) {
- if (lose_counter++ > 16)
- break;
- continue;
- }
- n -= i;
- cp += i;
- lose_counter = 0;
- }
- }
-
- /*
- * We do this all the time, but this is the only source of
- * randomness if /dev/random/urandom is out to lunch.
- */
- for (cp = buf, i = 0; i < nbytes; i++)
- *cp++ ^= (rand() >> 7) & 0xFF;
-}
-
-/*
- * Get the ethernet hardware address, if we can find it...
- */
-static int get_node_id(unsigned char *node_id)
-{
-#ifdef HAVE_NET_IF_H
- int sd;
- struct ifreq ifr, *ifrp;
- struct ifconf ifc;
- char buf[1024];
- int n, i;
- unsigned char *a;
-#ifdef HAVE_NET_IF_DL_H
- struct sockaddr_dl *sdlp;
-#endif
-
-/*
- * BSD 4.4 defines the size of an ifreq to be
- * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
- * However, under earlier systems, sa_len isn't present, so the size is
- * just sizeof(struct ifreq)
- */
-#ifdef HAVE_SA_LEN
-#ifndef max
-#define max(a,b) ((a) > (b) ? (a) : (b))
-#endif
-#define ifreq_size(i) max(sizeof(struct ifreq),\
- sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
-#else
-#define ifreq_size(i) sizeof(struct ifreq)
-#endif /* HAVE_SA_LEN*/
-
- sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
- if (sd < 0) {
- return -1;
- }
- memset(buf, 0, sizeof(buf));
- ifc.ifc_len = sizeof(buf);
- ifc.ifc_buf = buf;
- if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) {
- close(sd);
- return -1;
- }
- n = ifc.ifc_len;
- for (i = 0; i < n; i+= ifreq_size(*ifrp) ) {
- ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
- strncpy_IFNAMSIZ(ifr.ifr_name, ifrp->ifr_name);
-#ifdef SIOCGIFHWADDR
- if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
- continue;
- a = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
-#else
-#ifdef SIOCGENADDR
- if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
- continue;
- a = (unsigned char *) ifr.ifr_enaddr;
-#else
-#ifdef HAVE_NET_IF_DL_H
- sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr;
- if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6))
- continue;
- a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen];
-#else
- /*
- * XXX we don't have a way of getting the hardware
- * address
- */
- close(sd);
- return 0;
-#endif /* HAVE_NET_IF_DL_H */
-#endif /* SIOCGENADDR */
-#endif /* SIOCGIFHWADDR */
- if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
- continue;
- if (node_id) {
- memcpy(node_id, a, 6);
- close(sd);
- return 1;
- }
- }
- close(sd);
-#endif
- return 0;
-}
-
-/* Assume that the gettimeofday() has microsecond granularity */
-#define MAX_ADJUSTMENT 10
-
-static int get_clock(uint32_t *clock_high, uint32_t *clock_low, uint16_t *ret_clock_seq)
-{
- static int adjustment = 0;
- static struct timeval last = {0, 0};
- static uint16_t clock_seq;
- struct timeval tv;
- unsigned long long clock_reg;
-
-try_again:
- gettimeofday(&tv, 0);
- if ((last.tv_sec == 0) && (last.tv_usec == 0)) {
- get_random_bytes(&clock_seq, sizeof(clock_seq));
- clock_seq &= 0x3FFF;
- last = tv;
- last.tv_sec--;
- }
- if ((tv.tv_sec < last.tv_sec) ||
- ((tv.tv_sec == last.tv_sec) &&
- (tv.tv_usec < last.tv_usec))) {
- clock_seq = (clock_seq+1) & 0x3FFF;
- adjustment = 0;
- last = tv;
- } else if ((tv.tv_sec == last.tv_sec) &&
- (tv.tv_usec == last.tv_usec)) {
- if (adjustment >= MAX_ADJUSTMENT)
- goto try_again;
- adjustment++;
- } else {
- adjustment = 0;
- last = tv;
- }
-
- clock_reg = tv.tv_usec*10 + adjustment;
- clock_reg += ((unsigned long long) tv.tv_sec)*10000000;
- clock_reg += (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000;
-
- *clock_high = clock_reg >> 32;
- *clock_low = clock_reg;
- *ret_clock_seq = clock_seq;
- return 0;
-}
-
-void uuid_generate_time(uuid_t out)
-{
- static unsigned char node_id[6];
- static int has_init = 0;
- struct uuid uu;
- uint32_t clock_mid;
-
- if (!has_init) {
- if (get_node_id(node_id) <= 0) {
- get_random_bytes(node_id, 6);
- /*
- * Set multicast bit, to prevent conflicts
- * with IEEE 802 addresses obtained from
- * network cards
- */
- node_id[0] |= 0x01;
- }
- has_init = 1;
- }
- get_clock(&clock_mid, &uu.time_low, &uu.clock_seq);
- uu.clock_seq |= 0x8000;
- uu.time_mid = (uint16_t) clock_mid;
- uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000;
- memcpy(uu.node, node_id, 6);
- uuid_pack(&uu, out);
-}
-
-void uuid_generate_random(uuid_t out)
-{
- uuid_t buf;
- struct uuid uu;
-
- get_random_bytes(buf, sizeof(buf));
- uuid_unpack(buf, &uu);
-
- uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
- uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000;
- uuid_pack(&uu, out);
-}
-
-/*
- * This is the generic front-end to uuid_generate_random and
- * uuid_generate_time. It uses uuid_generate_random only if
- * /dev/urandom is available, since otherwise we won't have
- * high-quality randomness.
- */
-void uuid_generate(uuid_t out)
-{
- if (get_random_fd() >= 0)
- uuid_generate_random(out);
- else
- uuid_generate_time(out);
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/pack.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/pack.c
deleted file mode 100644
index 217cfce5d7..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/pack.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * Internal routine for packing UUID's
- *
- * Copyright (C) 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, and the entire permission notice in its entirety,
- * including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
- * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- * %End-Header%
- */
-
-#include <string.h>
-#include "uuidP.h"
-
-void uuid_pack(const struct uuid *uu, uuid_t ptr)
-{
- uint32_t tmp;
- unsigned char *out = ptr;
-
- tmp = uu->time_low;
- out[3] = (unsigned char) tmp;
- tmp >>= 8;
- out[2] = (unsigned char) tmp;
- tmp >>= 8;
- out[1] = (unsigned char) tmp;
- tmp >>= 8;
- out[0] = (unsigned char) tmp;
-
- tmp = uu->time_mid;
- out[5] = (unsigned char) tmp;
- tmp >>= 8;
- out[4] = (unsigned char) tmp;
-
- tmp = uu->time_hi_and_version;
- out[7] = (unsigned char) tmp;
- tmp >>= 8;
- out[6] = (unsigned char) tmp;
-
- tmp = uu->clock_seq;
- out[9] = (unsigned char) tmp;
- tmp >>= 8;
- out[8] = (unsigned char) tmp;
-
- memcpy(out+10, uu->node, 6);
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/parse.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/parse.c
deleted file mode 100644
index 9a3f9cb921..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/parse.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * parse.c --- UUID parsing
- *
- * Copyright (C) 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, and the entire permission notice in its entirety,
- * including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
- * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- * %End-Header%
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-
-#include "uuidP.h"
-
-int uuid_parse(const char *in, uuid_t uu)
-{
- struct uuid uuid;
- int i;
- const char *cp;
- char buf[3];
-
- if (strlen(in) != 36)
- return -1;
- for (i=0, cp = in; i <= 36; i++,cp++) {
- if ((i == 8) || (i == 13) || (i == 18) ||
- (i == 23)) {
- if (*cp == '-')
- continue;
- else
- return -1;
- }
- if (i== 36)
- if (*cp == 0)
- continue;
- if (!isxdigit(*cp))
- return -1;
- }
- uuid.time_low = strtoul(in, NULL, 16);
- uuid.time_mid = strtoul(in+9, NULL, 16);
- uuid.time_hi_and_version = strtoul(in+14, NULL, 16);
- uuid.clock_seq = strtoul(in+19, NULL, 16);
- cp = in+24;
- buf[2] = 0;
- for (i=0; i < 6; i++) {
- buf[0] = *cp++;
- buf[1] = *cp++;
- uuid.node[i] = strtoul(buf, NULL, 16);
- }
-
- uuid_pack(&uuid, uu);
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/unpack.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/unpack.c
deleted file mode 100644
index 95d3aab4a2..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/unpack.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * Internal routine for unpacking UUID
- *
- * Copyright (C) 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, and the entire permission notice in its entirety,
- * including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
- * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- * %End-Header%
- */
-
-#include <string.h>
-#include "uuidP.h"
-
-void uuid_unpack(const uuid_t in, struct uuid *uu)
-{
- const uint8_t *ptr = in;
- uint32_t tmp;
-
- tmp = *ptr++;
- tmp = (tmp << 8) | *ptr++;
- tmp = (tmp << 8) | *ptr++;
- tmp = (tmp << 8) | *ptr++;
- uu->time_low = tmp;
-
- tmp = *ptr++;
- tmp = (tmp << 8) | *ptr++;
- uu->time_mid = tmp;
-
- tmp = *ptr++;
- tmp = (tmp << 8) | *ptr++;
- uu->time_hi_and_version = tmp;
-
- tmp = *ptr++;
- tmp = (tmp << 8) | *ptr++;
- uu->clock_seq = tmp;
-
- memcpy(uu->node, ptr, 6);
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/unparse.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/unparse.c
deleted file mode 100644
index d2948fe6dc..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/unparse.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * unparse.c -- convert a UUID to string
- *
- * Copyright (C) 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, and the entire permission notice in its entirety,
- * including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
- * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- * %End-Header%
- */
-
-#include <stdio.h>
-
-#include "uuidP.h"
-
-static const char *fmt_lower =
- "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
-
-static const char *fmt_upper =
- "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X";
-
-#ifdef UUID_UNPARSE_DEFAULT_UPPER
-#define FMT_DEFAULT fmt_upper
-#else
-#define FMT_DEFAULT fmt_lower
-#endif
-
-static void uuid_unparse_x(const uuid_t uu, char *out, const char *fmt)
-{
- struct uuid uuid;
-
- uuid_unpack(uu, &uuid);
- sprintf(out, fmt,
- uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
- uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
- uuid.node[0], uuid.node[1], uuid.node[2],
- uuid.node[3], uuid.node[4], uuid.node[5]);
-}
-
-void uuid_unparse_lower(const uuid_t uu, char *out)
-{
- uuid_unparse_x(uu, out, fmt_lower);
-}
-
-void uuid_unparse_upper(const uuid_t uu, char *out)
-{
- uuid_unparse_x(uu, out, fmt_upper);
-}
-
-void uuid_unparse(const uuid_t uu, char *out)
-{
- uuid_unparse_x(uu, out, FMT_DEFAULT);
-}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/uuid.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/uuid.h
deleted file mode 100644
index 7a9706449b..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/uuid.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * Public include file for the UUID library
- *
- * Copyright (C) 1996, 1997, 1998 Theodore Ts'o.
- *
- * %Begin-Header%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, and the entire permission notice in its entirety,
- * including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
- * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- * %End-Header%
- */
-#ifndef UUID_UUID_H
-#define UUID_UUID_H 1
-
-#include <sys/types.h>
-#include <time.h>
-
-typedef unsigned char uuid_t[16];
-
-/* UUID Variant definitions */
-#define UUID_VARIANT_NCS 0
-#define UUID_VARIANT_DCE 1
-#define UUID_VARIANT_MICROSOFT 2
-#define UUID_VARIANT_OTHER 3
-
-/* UUID Type definitions */
-#define UUID_TYPE_DCE_TIME 1
-#define UUID_TYPE_DCE_RANDOM 4
-
-/* Allow UUID constants to be defined */
-#ifdef __GNUC__
-#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \
- static const uuid_t name UNUSED_PARAM = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15}
-#else
-#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \
- static const uuid_t name = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15}
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* clear.c */
-/*void uuid_clear(uuid_t uu);*/
-#define uuid_clear(uu) memset(uu, 0, sizeof(uu))
-
-/* compare.c */
-int uuid_compare(const uuid_t uu1, const uuid_t uu2);
-
-/* copy.c */
-/*void uuid_copy(uuid_t dst, const uuid_t src);*/
-#define uuid_copy(dst,src) memcpy(dst, src, sizeof(dst))
-
-/* gen_uuid.c */
-void uuid_generate(uuid_t out);
-void uuid_generate_random(uuid_t out);
-void uuid_generate_time(uuid_t out);
-
-/* isnull.c */
-/*int uuid_is_null(const uuid_t uu);*/
-#define uuid_is_null(uu) (!memcmp(uu, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", sizeof(uu)))
-
-/* parse.c */
-int uuid_parse(const char *in, uuid_t uu);
-
-/* unparse.c */
-void uuid_unparse(const uuid_t uu, char *out);
-void uuid_unparse_lower(const uuid_t uu, char *out);
-void uuid_unparse_upper(const uuid_t uu, char *out);
-
-/* uuid_time.c */
-time_t uuid_time(const uuid_t uu, struct timeval *ret_tv);
-int uuid_type(const uuid_t uu);
-int uuid_variant(const uuid_t uu);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _UUID_UUID_H */
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/uuidP.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/uuidP.h
deleted file mode 100644
index 87041ef0a2..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/uuidP.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * uuid.h -- private header file for uuids
- *
- * Copyright (C) 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, and the entire permission notice in its entirety,
- * including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
- * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- * %End-Header%
- */
-
-#include <inttypes.h>
-#include <sys/types.h>
-
-#include "uuid.h"
-
-/*
- * Offset between 15-Oct-1582 and 1-Jan-70
- */
-#define TIME_OFFSET_HIGH 0x01B21DD2
-#define TIME_OFFSET_LOW 0x13814000
-
-struct uuid {
- uint32_t time_low;
- uint16_t time_mid;
- uint16_t time_hi_and_version;
- uint16_t clock_seq;
- uint8_t node[6];
-};
-
-
-/*
- * prototypes
- */
-void uuid_pack(const struct uuid *uu, uuid_t ptr);
-void uuid_unpack(const uuid_t in, struct uuid *uu);
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/uuid_time.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/uuid_time.c
deleted file mode 100644
index b6f73e6dc9..0000000000
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/uuid_time.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * uuid_time.c --- Interpret the time field from a uuid. This program
- * violates the UUID abstraction barrier by reaching into the guts
- * of a UUID and interpreting it.
- *
- * Copyright (C) 1998, 1999 Theodore Ts'o.
- *
- * %Begin-Header%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, and the entire permission notice in its entirety,
- * including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
- * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <time.h>
-
-#include "uuidP.h"
-
-time_t uuid_time(const uuid_t uu, struct timeval *ret_tv)
-{
- struct uuid uuid;
- uint32_t high;
- struct timeval tv;
- unsigned long long clock_reg;
-
- uuid_unpack(uu, &uuid);
-
- high = uuid.time_mid | ((uuid.time_hi_and_version & 0xFFF) << 16);
- clock_reg = uuid.time_low | ((unsigned long long) high << 32);
-
- clock_reg -= (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000;
- tv.tv_sec = clock_reg / 10000000;
- tv.tv_usec = (clock_reg % 10000000) / 10;
-
- if (ret_tv)
- *ret_tv = tv;
-
- return tv.tv_sec;
-}
-
-int uuid_type(const uuid_t uu)
-{
- struct uuid uuid;
-
- uuid_unpack(uu, &uuid);
- return ((uuid.time_hi_and_version >> 12) & 0xF);
-}
-
-int uuid_variant(const uuid_t uu)
-{
- struct uuid uuid;
- int var;
-
- uuid_unpack(uu, &uuid);
- var = uuid.clock_seq;
-
- if ((var & 0x8000) == 0)
- return UUID_VARIANT_NCS;
- if ((var & 0x4000) == 0)
- return UUID_VARIANT_DCE;
- if ((var & 0x2000) == 0)
- return UUID_VARIANT_MICROSOFT;
- return UUID_VARIANT_OTHER;
-}
-
-#ifdef DEBUG
-static const char *variant_string(int variant)
-{
- switch (variant) {
- case UUID_VARIANT_NCS:
- return "NCS";
- case UUID_VARIANT_DCE:
- return "DCE";
- case UUID_VARIANT_MICROSOFT:
- return "Microsoft";
- default:
- return "Other";
- }
-}
-
-
-int
-main(int argc, char **argv)
-{
- uuid_t buf;
- time_t time_reg;
- struct timeval tv;
- int type, variant;
-
- if (argc != 2) {
- fprintf(stderr, "Usage: %s uuid\n", argv[0]);
- exit(1);
- }
- if (uuid_parse(argv[1], buf)) {
- fprintf(stderr, "Invalid UUID: %s\n", argv[1]);
- exit(1);
- }
- variant = uuid_variant(buf);
- type = uuid_type(buf);
- time_reg = uuid_time(buf, &tv);
-
- printf("UUID variant is %d (%s)\n", variant, variant_string(variant));
- if (variant != UUID_VARIANT_DCE) {
- printf("Warning: This program only knows how to interpret "
- "DCE UUIDs.\n\tThe rest of the output is likely "
- "to be incorrect!!\n");
- }
- printf("UUID type is %d", type);
- switch (type) {
- case 1:
- printf(" (time based)\n");
- break;
- case 2:
- printf(" (DCE)\n");
- break;
- case 3:
- printf(" (name-based)\n");
- break;
- case 4:
- printf(" (random)\n");
- break;
- default:
- bb_putchar('\n');
- }
- if (type != 1) {
- printf("Warning: not a time-based UUID, so UUID time "
- "decoding will likely not work!\n");
- }
- printf("UUID time is: (%ld, %ld): %s\n", tv.tv_sec, tv.tv_usec,
- ctime(&time_reg));
-
- return 0;
-}
-#endif
diff --git a/release/src/router/busybox/e2fsprogs/tune2fs.c b/release/src/router/busybox/e2fsprogs/tune2fs.c
index 3e3d7959f6..c9f88b39d3 100644
--- a/release/src/router/busybox/e2fsprogs/tune2fs.c
+++ b/release/src/router/busybox/e2fsprogs/tune2fs.c
@@ -1,730 +1,118 @@
/* vi: set sw=4 ts=4: */
/*
- * tune2fs.c - Change the file system parameters on an ext2 file system
+ * tune2fs: utility to modify EXT2 filesystem
*
- * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr>
- * Laboratoire MASI, Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o.
+ * Busybox'ed (2009) by Vladimir Dronnikov <dronnikov@gmail.com>
*
* Licensed under GPLv2, see file LICENSE in this source tree.
*/
+//config:config TUNE2FS
+//config: bool "tune2fs"
+//config: default n # off: it is too limited compared to upstream version
+//config: help
+//config: tune2fs allows the system administrator to adjust various tunable
+//config: filesystem parameters on Linux ext2/ext3 filesystems.
+
+//applet:IF_TUNE2FS(APPLET(tune2fs, BB_DIR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_TUNE2FS) += tune2fs.o
//usage:#define tune2fs_trivial_usage
-//usage: "[-c MOUNT_CNT] "
-//usage: "[-e errors-behavior] [-g group] "
+//usage: "[-c MAX_MOUNT_COUNT] "
+////usage: "[-e errors-behavior] [-g group] "
//usage: "[-i DAYS] "
-//usage: "[-j] [-J journal-options] [-l] [-s sparse-flag] "
-//usage: "[-m reserved-blocks-percent] [-o [^]mount-options[,...]] "
-//usage: "[-r reserved-blocks-count] [-u user] [-C mount-count] "
+////usage: "[-j] [-J journal-options] [-l] [-s sparse-flag] "
+////usage: "[-m reserved-blocks-percent] [-o [^]mount-options[,...]] "
+////usage: "[-r reserved-blocks-count] [-u user] "
+//usage: "[-C MOUNT_COUNT] "
//usage: "[-L LABEL] "
-//usage: "[-M last-mounted-dir] [-O [^]feature[,...]] "
-//usage: "[-T last-check-time] [-U UUID] "
+////usage: "[-M last-mounted-dir] [-O [^]feature[,...]] "
+////usage: "[-T last-check-time] [-U UUID] "
//usage: "BLOCKDEV"
//usage:
//usage:#define tune2fs_full_usage "\n\n"
//usage: "Adjust filesystem options on ext[23] filesystems"
-/*
- * History:
- * 93/06/01 - Creation
- * 93/10/31 - Added the -c option to change the maximal mount counts
- * 93/12/14 - Added -l flag to list contents of superblock
- * M.J.E. Mol (marcel@duteca.et.tudelft.nl)
- * F.W. ten Wolde (franky@duteca.et.tudelft.nl)
- * 93/12/29 - Added the -e option to change errors behavior
- * 94/02/27 - Ported to use the ext2fs library
- * 94/03/06 - Added the checks interval from Uwe Ohse (uwe@tirka.gun.de)
- */
-
-#include <sys/types.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <getopt.h>
-
-#include "e2fsbb.h"
-#include "ext2fs/ext2_fs.h"
-#include "ext2fs/ext2fs.h"
-#include "../e2fs_lib.h"
-#include "e2p/e2p.h"
-#include "ext2fs/kernel-jbd.h"
-#include "util.h"
-#include "volume_id.h"
-
#include "libbb.h"
-#if LINUX_KERNEL_VERSION >= KERNEL_VERSION(3,3,0)
-typedef unsigned short umode_t;
-#endif
-
-static char * device_name = NULL;
-static char * new_label, *new_last_mounted, *new_UUID;
-static char * io_options;
-static int c_flag, C_flag, e_flag, f_flag, g_flag, i_flag, l_flag, L_flag;
-static int m_flag, M_flag, r_flag, s_flag = -1, u_flag, U_flag, T_flag;
-static time_t last_check_time;
-static int print_label;
-static int max_mount_count, mount_count, mount_flags;
-static unsigned long interval, reserved_blocks;
-static unsigned reserved_ratio;
-static unsigned long resgid, resuid;
-static unsigned short errors;
-static int open_flag;
-static char *features_cmd;
-static char *mntopts_cmd;
-
-static int journal_size, journal_flags;
-static char *journal_device = NULL;
-
-static const char *please_fsck = "Please run e2fsck on the filesystem\n";
-
-static __u32 ok_features[3] = {
- EXT3_FEATURE_COMPAT_HAS_JOURNAL | EXT2_FEATURE_COMPAT_DIR_INDEX,
- EXT2_FEATURE_INCOMPAT_FILETYPE,
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
+#include <linux/fs.h>
+#include "bb_e2fs_defs.h"
+
+// storage helpers
+char BUG_wrong_field_size(void);
+#define STORE_LE(field, value) \
+do { \
+ if (sizeof(field) == 4) \
+ field = SWAP_LE32(value); \
+ else if (sizeof(field) == 2) \
+ field = SWAP_LE16(value); \
+ else if (sizeof(field) == 1) \
+ field = (value); \
+ else \
+ BUG_wrong_field_size(); \
+} while (0)
+
+#define FETCH_LE32(field) \
+ (sizeof(field) == 4 ? SWAP_LE32(field) : BUG_wrong_field_size())
+
+enum {
+ OPT_L = 1 << 0, // label
+ OPT_c = 1 << 1, // max mount count
+ OPT_i = 1 << 2, // check interval
+ OPT_C = 1 << 3, // current mount count
};
-/*
- * Remove an external journal from the filesystem
- */
-static void remove_journal_device(ext2_filsys fs)
-{
- char *journal_path;
- ext2_filsys jfs;
- char buf[1024];
- journal_superblock_t *jsb;
- int i, nr_users;
- errcode_t retval;
- int commit_remove_journal = 0;
- io_manager io_ptr;
-
- if (f_flag)
- commit_remove_journal = 1; /* force removal even if error */
-
- unparse_uuid(fs->super->s_journal_uuid, buf);
- journal_path = get_devname_from_uuid(buf);
-
- if (!journal_path) {
- journal_path =
- ext2fs_find_block_device(fs->super->s_journal_dev);
- if (!journal_path)
- return;
- }
-
- io_ptr = unix_io_manager;
- retval = ext2fs_open(journal_path, EXT2_FLAG_RW|
- EXT2_FLAG_JOURNAL_DEV_OK, 0,
- fs->blocksize, io_ptr, &jfs);
- if (retval) {
- bb_error_msg("Failed to open external journal");
- goto no_valid_journal;
- }
- if (!(jfs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
- bb_error_msg("%s is not a journal device", journal_path);
- goto no_valid_journal;
- }
-
- /* Get the journal superblock */
- if ((retval = io_channel_read_blk(jfs->io, 1, -1024, buf))) {
- bb_error_msg("Failed to read journal superblock");
- goto no_valid_journal;
- }
-
- jsb = (journal_superblock_t *) buf;
- if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) ||
- (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2))) {
- bb_error_msg("Journal superblock not found!");
- goto no_valid_journal;
- }
-
- /* Find the filesystem UUID */
- nr_users = ntohl(jsb->s_nr_users);
- for (i=0; i < nr_users; i++) {
- if (memcmp(fs->super->s_uuid,
- &jsb->s_users[i*16], 16) == 0)
- break;
- }
- if (i >= nr_users) {
- bb_error_msg("Filesystem's UUID not found on journal device");
- commit_remove_journal = 1;
- goto no_valid_journal;
- }
- nr_users--;
- for (i=0; i < nr_users; i++)
- memcpy(&jsb->s_users[i*16], &jsb->s_users[(i+1)*16], 16);
- jsb->s_nr_users = htonl(nr_users);
-
- /* Write back the journal superblock */
- if ((retval = io_channel_write_blk(jfs->io, 1, -1024, buf))) {
- bb_error_msg("Failed to write journal superblock");
- goto no_valid_journal;
- }
-
- commit_remove_journal = 1;
-
-no_valid_journal:
- if (commit_remove_journal == 0)
- bb_error_msg_and_die("Journal NOT removed");
- fs->super->s_journal_dev = 0;
- uuid_clear(fs->super->s_journal_uuid);
- ext2fs_mark_super_dirty(fs);
- puts("Journal removed");
- free(journal_path);
-}
-
-/* Helper function for remove_journal_inode */
-static int release_blocks_proc(ext2_filsys fs, blk_t *blocknr,
- int blockcnt EXT2FS_ATTR((unused)),
- void *private EXT2FS_ATTR((unused)))
-{
- blk_t block;
- int group;
-
- block = *blocknr;
- ext2fs_unmark_block_bitmap(fs->block_map,block);
- group = ext2fs_group_of_blk(fs, block);
- fs->group_desc[group].bg_free_blocks_count++;
- fs->super->s_free_blocks_count++;
- return 0;
-}
-
-/*
- * Remove the journal inode from the filesystem
- */
-static void remove_journal_inode(ext2_filsys fs)
-{
- struct ext2_inode inode;
- errcode_t retval;
- ino_t ino = fs->super->s_journal_inum;
- const char *msg = "to read";
- const char *s = "journal inode";
-
- retval = ext2fs_read_inode(fs, ino, &inode);
- if (retval)
- goto REMOVE_JOURNAL_INODE_ERROR;
- if (ino == EXT2_JOURNAL_INO) {
- retval = ext2fs_read_bitmaps(fs);
- if (retval) {
- msg = "to read bitmaps";
- s = "";
- goto REMOVE_JOURNAL_INODE_ERROR;
- }
- retval = ext2fs_block_iterate(fs, ino, 0, NULL,
- release_blocks_proc, NULL);
- if (retval) {
- msg = "clearing";
- goto REMOVE_JOURNAL_INODE_ERROR;
- }
- memset(&inode, 0, sizeof(inode));
- ext2fs_mark_bb_dirty(fs);
- fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
- } else
- inode.i_flags &= ~EXT2_IMMUTABLE_FL;
- retval = ext2fs_write_inode(fs, ino, &inode);
- if (retval) {
- msg = "writing";
-REMOVE_JOURNAL_INODE_ERROR:
- bb_error_msg_and_die("Failed %s %s", msg, s);
- }
- fs->super->s_journal_inum = 0;
- ext2fs_mark_super_dirty(fs);
-}
-
-/*
- * Update the default mount options
- */
-static void update_mntopts(ext2_filsys fs, char *mntopts)
-{
- struct ext2_super_block *sb= fs->super;
-
- if (e2p_edit_mntopts(mntopts, &sb->s_default_mount_opts, ~0))
- bb_error_msg_and_die("Invalid mount option set: %s", mntopts);
- ext2fs_mark_super_dirty(fs);
-}
-
-/*
- * Update the feature set as provided by the user.
- */
-static void update_feature_set(ext2_filsys fs, char *features)
+int tune2fs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int tune2fs_main(int argc UNUSED_PARAM, char **argv)
{
- int sparse, old_sparse, filetype, old_filetype;
- int journal, old_journal, dxdir, old_dxdir;
- struct ext2_super_block *sb= fs->super;
- __u32 old_compat, old_incompat, old_ro_compat;
+ unsigned opts;
+ const char *label, *str_c, *str_i, *str_C;
+ struct ext2_super_block *sb;
+ int fd;
- old_compat = sb->s_feature_compat;
- old_ro_compat = sb->s_feature_ro_compat;
- old_incompat = sb->s_feature_incompat;
+ opt_complementary = "=1";
+ opts = getopt32(argv, "L:c:i:C:", &label, &str_c, &str_i, &str_C);
+ if (!opts)
+ bb_show_usage();
+ argv += optind; // argv[0] -- device
- old_sparse = sb->s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
- old_filetype = sb->s_feature_incompat &
- EXT2_FEATURE_INCOMPAT_FILETYPE;
- old_journal = sb->s_feature_compat &
- EXT3_FEATURE_COMPAT_HAS_JOURNAL;
- old_dxdir = sb->s_feature_compat &
- EXT2_FEATURE_COMPAT_DIR_INDEX;
- if (e2p_edit_feature(features, &sb->s_feature_compat, ok_features))
- bb_error_msg_and_die("Invalid filesystem option set: %s", features);
- sparse = sb->s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
- filetype = sb->s_feature_incompat &
- EXT2_FEATURE_INCOMPAT_FILETYPE;
- journal = sb->s_feature_compat &
- EXT3_FEATURE_COMPAT_HAS_JOURNAL;
- dxdir = sb->s_feature_compat &
- EXT2_FEATURE_COMPAT_DIR_INDEX;
- if (old_journal && !journal) {
- if ((mount_flags & EXT2_MF_MOUNTED) &&
- !(mount_flags & EXT2_MF_READONLY)) {
- bb_error_msg_and_die(
- "The has_journal flag may only be "
- "cleared when the filesystem is\n"
- "unmounted or mounted "
- "read-only");
- }
- if (sb->s_feature_incompat &
- EXT3_FEATURE_INCOMPAT_RECOVER) {
- bb_error_msg_and_die(
- "The needs_recovery flag is set. "
- "%s before clearing the has_journal flag.",
- please_fsck);
- }
- if (sb->s_journal_inum) {
- remove_journal_inode(fs);
- }
- if (sb->s_journal_dev) {
- remove_journal_device(fs);
- }
- }
- if (journal && !old_journal) {
- /*
- * If adding a journal flag, let the create journal
- * code below handle creating setting the flag and
- * creating the journal. We supply a default size if
- * necessary.
- */
- if (!journal_size)
- journal_size = -1;
- sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
- }
- if (dxdir && !old_dxdir) {
- if (!sb->s_def_hash_version)
- sb->s_def_hash_version = EXT2_HASH_TEA;
- if (uuid_is_null((unsigned char *) sb->s_hash_seed))
- generate_uuid((unsigned char *) sb->s_hash_seed);
- }
+ // read superblock
+ fd = xopen(argv[0], O_RDWR);
+ xlseek(fd, 1024, SEEK_SET);
+ sb = xzalloc(1024);
+ xread(fd, sb, 1024);
- if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
- (sb->s_feature_compat || sb->s_feature_ro_compat ||
- sb->s_feature_incompat))
- ext2fs_update_dynamic_rev(fs);
- if ((sparse != old_sparse) ||
- (filetype != old_filetype)) {
- sb->s_state &= ~EXT2_VALID_FS;
- printf("\n%s\n", please_fsck);
- }
- if ((old_compat != sb->s_feature_compat) ||
- (old_ro_compat != sb->s_feature_ro_compat) ||
- (old_incompat != sb->s_feature_incompat))
- ext2fs_mark_super_dirty(fs);
-}
+ // mangle superblock
+ //STORE_LE(sb->s_wtime, time(NULL)); - why bother?
-/*
- * Add a journal to the filesystem.
- */
-static void add_journal(ext2_filsys fs)
-{
- if (fs->super->s_feature_compat &
- EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
- bb_error_msg_and_die("The filesystem already has a journal");
- }
- if (journal_device) {
- make_journal_device(journal_device, fs, 0, 0);
- } else if (journal_size) {
- make_journal_blocks(fs, journal_size, journal_flags, 0);
- /*
- * If the filesystem wasn't mounted, we need to force
- * the block group descriptors out.
- */
- if ((mount_flags & EXT2_MF_MOUNTED) == 0)
- fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
+ if (opts & OPT_C) {
+ int n = xatoi_range(str_C, 1, 0xfffe);
+ STORE_LE(sb->s_mnt_count, (unsigned)n);
}
- print_check_message(fs);
-}
-
-/*
- * Busybox stuff
- */
-static char * x_blkid_get_devname(const char *token)
-{
- char *dev_name = (char *)token;
-
- if (resolve_mount_spec(&dev_name) != 1 || !dev_name)
- bb_error_msg_and_die("Unable to resolve '%s'", token);
- return dev_name;
-}
-
-#ifdef CONFIG_E2LABEL
-static void parse_e2label_options(int argc, char ** argv)
-{
- if ((argc < 2) || (argc > 3))
- bb_show_usage();
- io_options = strchr(argv[1], '?');
- if (io_options)
- *io_options++ = 0;
- device_name = x_blkid_get_devname(argv[1]);
- if (argc == 3) {
- open_flag = EXT2_FLAG_RW | EXT2_FLAG_JOURNAL_DEV_OK;
- L_flag = 1;
- new_label = argv[2];
- } else
- print_label++;
-}
-#else
-#define parse_e2label_options(x,y)
-#endif
-static time_t parse_time(char *str)
-{
- struct tm ts;
+ // set the label
+ if (opts & OPT_L)
+ safe_strncpy((char *)sb->s_volume_name, label, sizeof(sb->s_volume_name));
- if (strcmp(str, "now") == 0) {
- return time(0);
+ if (opts & OPT_c) {
+ int n = xatoi_range(str_c, -1, 0xfffe);
+ if (n == 0)
+ n = -1;
+ STORE_LE(sb->s_max_mnt_count, (unsigned)n);
}
- memset(&ts, 0, sizeof(ts));
-#ifdef HAVE_STRPTIME
- strptime(str, "%Y%m%d%H%M%S", &ts);
-#else
- sscanf(str, "%4d%2d%2d%2d%2d%2d", &ts.tm_year, &ts.tm_mon,
- &ts.tm_mday, &ts.tm_hour, &ts.tm_min, &ts.tm_sec);
- ts.tm_year -= 1900;
- ts.tm_mon -= 1;
- if (ts.tm_year < 0 || ts.tm_mon < 0 || ts.tm_mon > 11 ||
- ts.tm_mday < 0 || ts.tm_mday > 31 || ts.tm_hour > 23 ||
- ts.tm_min > 59 || ts.tm_sec > 61)
- ts.tm_mday = 0;
-#endif
- if (ts.tm_mday == 0) {
- bb_error_msg_and_die("can't parse date/time specifier: %s", str);
- }
- return mktime(&ts);
-}
-
-static void parse_tune2fs_options(int argc, char **argv)
-{
- int c;
- char * tmp;
-
- printf("tune2fs %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE);
- while ((c = getopt(argc, argv, "c:e:fg:i:jlm:o:r:s:u:C:J:L:M:O:T:U:")) != EOF)
- switch (c)
- {
- case 'c':
- max_mount_count = xatou_range(optarg, 0, 16000);
- if (max_mount_count == 0)
- max_mount_count = -1;
- c_flag = 1;
- open_flag = EXT2_FLAG_RW;
- break;
- case 'C':
- mount_count = xatou_range(optarg, 0, 16000);
- C_flag = 1;
- open_flag = EXT2_FLAG_RW;
- break;
- case 'e':
- if (strcmp (optarg, "continue") == 0)
- errors = EXT2_ERRORS_CONTINUE;
- else if (strcmp (optarg, "remount-ro") == 0)
- errors = EXT2_ERRORS_RO;
- else if (strcmp (optarg, "panic") == 0)
- errors = EXT2_ERRORS_PANIC;
- else {
- bb_error_msg_and_die("bad error behavior - %s", optarg);
- }
- e_flag = 1;
- open_flag = EXT2_FLAG_RW;
- break;
- case 'f': /* Force */
- f_flag = 1;
- break;
- case 'g':
- resgid = bb_strtoul(optarg, NULL, 10);
- if (errno)
- resgid = xgroup2gid(optarg);
- g_flag = 1;
- open_flag = EXT2_FLAG_RW;
- break;
- case 'i':
- interval = strtoul(optarg, &tmp, 0);
- switch (*tmp) {
- case 's':
- tmp++;
- break;
- case '\0':
- case 'd':
- case 'D': /* days */
- interval *= 86400;
- if (*tmp != '\0')
- tmp++;
- break;
- case 'm':
- case 'M': /* months! */
- interval *= 86400 * 30;
- tmp++;
- break;
- case 'w':
- case 'W': /* weeks */
- interval *= 86400 * 7;
- tmp++;
- break;
- }
- if (*tmp || interval > (365 * 86400)) {
- bb_error_msg_and_die("bad interval - %s", optarg);
- }
- i_flag = 1;
- open_flag = EXT2_FLAG_RW;
- break;
- case 'j':
- if (!journal_size)
- journal_size = -1;
- open_flag = EXT2_FLAG_RW;
- break;
- case 'J':
- parse_journal_opts(&journal_device, &journal_flags, &journal_size, optarg);
- open_flag = EXT2_FLAG_RW;
- break;
- case 'l':
- l_flag = 1;
- break;
- case 'L':
- new_label = optarg;
- L_flag = 1;
- open_flag = EXT2_FLAG_RW |
- EXT2_FLAG_JOURNAL_DEV_OK;
- break;
- case 'm':
- reserved_ratio = xatou_range(optarg, 0, 50);
- m_flag = 1;
- open_flag = EXT2_FLAG_RW;
- break;
- case 'M':
- new_last_mounted = optarg;
- M_flag = 1;
- open_flag = EXT2_FLAG_RW;
- break;
- case 'o':
- if (mntopts_cmd) {
- bb_error_msg_and_die("-o may only be specified once");
- }
- mntopts_cmd = optarg;
- open_flag = EXT2_FLAG_RW;
- break;
- case 'O':
- if (features_cmd) {
- bb_error_msg_and_die("-O may only be specified once");
- }
- features_cmd = optarg;
- open_flag = EXT2_FLAG_RW;
- break;
- case 'r':
- reserved_blocks = xatoul(optarg);
- r_flag = 1;
- open_flag = EXT2_FLAG_RW;
- break;
- case 's':
- s_flag = atoi(optarg);
- open_flag = EXT2_FLAG_RW;
- break;
- case 'T':
- T_flag = 1;
- last_check_time = parse_time(optarg);
- open_flag = EXT2_FLAG_RW;
- break;
- case 'u':
- resuid = bb_strtoul(optarg, NULL, 10);
- if (errno)
- resuid = xuname2uid(optarg);
- u_flag = 1;
- open_flag = EXT2_FLAG_RW;
- break;
- case 'U':
- new_UUID = optarg;
- U_flag = 1;
- open_flag = EXT2_FLAG_RW |
- EXT2_FLAG_JOURNAL_DEV_OK;
- break;
- default:
- bb_show_usage();
- }
- if (optind < argc - 1 || optind == argc)
- bb_show_usage();
- if (!open_flag && !l_flag)
- bb_show_usage();
- io_options = strchr(argv[optind], '?');
- if (io_options)
- *io_options++ = 0;
- device_name = x_blkid_get_devname(argv[optind]);
-}
-
-static void tune2fs_clean_up(void)
-{
- if (ENABLE_FEATURE_CLEAN_UP && device_name) free(device_name);
- if (ENABLE_FEATURE_CLEAN_UP && journal_device) free(journal_device);
-}
-
-int tune2fs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int tune2fs_main(int argc, char **argv)
-{
- errcode_t retval;
- ext2_filsys fs;
- struct ext2_super_block *sb;
- io_manager io_ptr;
-
- if (ENABLE_FEATURE_CLEAN_UP)
- atexit(tune2fs_clean_up);
-
- if (ENABLE_E2LABEL && (applet_name[0] == 'e')) /* e2label */
- parse_e2label_options(argc, argv);
- else
- parse_tune2fs_options(argc, argv); /* tune2fs */
-
- io_ptr = unix_io_manager;
- retval = ext2fs_open2(device_name, io_options, open_flag,
- 0, 0, io_ptr, &fs);
- if (retval)
- bb_error_msg_and_die("No valid superblock on %s", device_name);
- sb = fs->super;
- if (print_label) {
- /* For e2label emulation */
- printf("%.*s\n", (int) sizeof(sb->s_volume_name),
- sb->s_volume_name);
- return 0;
+ if (opts & OPT_i) {
+ unsigned n = xatou_range(str_i, 0, (unsigned)0xffffffff / (24*60*60)) * 24*60*60;
+ STORE_LE(sb->s_checkinterval, n);
}
- retval = ext2fs_check_if_mounted(device_name, &mount_flags);
- if (retval)
- bb_error_msg_and_die("can't determine if %s is mounted", device_name);
- /* Normally we only need to write out the superblock */
- fs->flags |= EXT2_FLAG_SUPER_ONLY;
- if (c_flag) {
- sb->s_max_mnt_count = max_mount_count;
- ext2fs_mark_super_dirty(fs);
- printf("Setting maximal mount count to %d\n", max_mount_count);
- }
- if (C_flag) {
- sb->s_mnt_count = mount_count;
- ext2fs_mark_super_dirty(fs);
- printf("Setting current mount count to %d\n", mount_count);
- }
- if (e_flag) {
- sb->s_errors = errors;
- ext2fs_mark_super_dirty(fs);
- printf("Setting error behavior to %d\n", errors);
- }
- if (g_flag) {
- sb->s_def_resgid = resgid;
- ext2fs_mark_super_dirty(fs);
- printf("Setting reserved blocks gid to %lu\n", resgid);
- }
- if (i_flag) {
- sb->s_checkinterval = interval;
- ext2fs_mark_super_dirty(fs);
- printf("Setting interval between check %lu seconds\n", interval);
- }
- if (m_flag) {
- sb->s_r_blocks_count = (sb->s_blocks_count / 100)
- * reserved_ratio;
- ext2fs_mark_super_dirty(fs);
- printf("Setting reserved blocks percentage to %u (%u blocks)\n",
- reserved_ratio, sb->s_r_blocks_count);
- }
- if (r_flag) {
- if (reserved_blocks >= sb->s_blocks_count/2)
- bb_error_msg_and_die("reserved blocks count is too big (%lu)", reserved_blocks);
- sb->s_r_blocks_count = reserved_blocks;
- ext2fs_mark_super_dirty(fs);
- printf("Setting reserved blocks count to %lu\n", reserved_blocks);
- }
- if (s_flag == 1) {
- if (sb->s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)
- bb_error_msg("\nThe filesystem already has sparse superblocks");
- else {
- sb->s_feature_ro_compat |=
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
- sb->s_state &= ~EXT2_VALID_FS;
- ext2fs_mark_super_dirty(fs);
- printf("\nSparse superblock flag set. %s", please_fsck);
- }
- }
- if (s_flag == 0) {
- if (!(sb->s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
- bb_error_msg("\nThe filesystem already has sparse superblocks disabled");
- else {
- sb->s_feature_ro_compat &=
- ~EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
- sb->s_state &= ~EXT2_VALID_FS;
- fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
- ext2fs_mark_super_dirty(fs);
- printf("\nSparse superblock flag cleared. %s", please_fsck);
- }
- }
- if (T_flag) {
- sb->s_lastcheck = last_check_time;
- ext2fs_mark_super_dirty(fs);
- printf("Setting time filesystem last checked to %s\n",
- ctime(&last_check_time));
- }
- if (u_flag) {
- sb->s_def_resuid = resuid;
- ext2fs_mark_super_dirty(fs);
- printf("Setting reserved blocks uid to %lu\n", resuid);
- }
- if (L_flag) {
- if (strlen(new_label) > sizeof(sb->s_volume_name))
- bb_error_msg("Warning: label too long, truncating");
- memset(sb->s_volume_name, 0, sizeof(sb->s_volume_name));
- safe_strncpy(sb->s_volume_name, new_label,
- sizeof(sb->s_volume_name));
- ext2fs_mark_super_dirty(fs);
- }
- if (M_flag) {
- memset(sb->s_last_mounted, 0, sizeof(sb->s_last_mounted));
- safe_strncpy(sb->s_last_mounted, new_last_mounted,
- sizeof(sb->s_last_mounted));
- ext2fs_mark_super_dirty(fs);
- }
- if (mntopts_cmd)
- update_mntopts(fs, mntopts_cmd);
- if (features_cmd)
- update_feature_set(fs, features_cmd);
- if (journal_size || journal_device)
- add_journal(fs);
+ // write superblock
+ xlseek(fd, 1024, SEEK_SET);
+ xwrite(fd, sb, 1024);
- if (U_flag) {
- if ((strcasecmp(new_UUID, "null") == 0) ||
- (strcasecmp(new_UUID, "clear") == 0)) {
- uuid_clear(sb->s_uuid);
-/*
- } else if (strcasecmp(new_UUID, "time") == 0) {
- uuid_generate_time(sb->s_uuid);
-*/
- } else if (strcasecmp(new_UUID, "random") == 0) {
- generate_uuid(sb->s_uuid);
- } else if (parse_uuid(new_UUID, sb->s_uuid)) {
- bb_error_msg_and_die("Invalid UUID format");
- }
- ext2fs_mark_super_dirty(fs);
+ if (ENABLE_FEATURE_CLEAN_UP) {
+ free(sb);
}
- if (l_flag)
- list_super (sb);
- return (ext2fs_close (fs) ? 1 : 0);
+ xclose(fd);
+ return EXIT_SUCCESS;
}
diff --git a/release/src/router/busybox/e2fsprogs/util.c b/release/src/router/busybox/e2fsprogs/util.c
deleted file mode 100644
index ca1837bcb6..0000000000
--- a/release/src/router/busybox/e2fsprogs/util.c
+++ /dev/null
@@ -1,264 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * util.c --- helper functions used by tune2fs and mke2fs
- *
- * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o.
- *
- * Licensed under GPLv2, see file LICENSE in this source tree.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <linux/major.h>
-#include <sys/stat.h>
-
-#include "e2fsbb.h"
-#include "e2p/e2p.h"
-#include "ext2fs/ext2_fs.h"
-#include "ext2fs/ext2fs.h"
-#include "volume_id.h"
-#include "util.h"
-
-void proceed_question(void)
-{
- fputs("Proceed anyway? (y,n) ", stdout);
- if (bb_ask_confirmation() == 0)
- exit(1);
-}
-
-void check_plausibility(const char *device, int force)
-{
- int val;
- struct stat s;
- val = stat(device, &s);
- if (force)
- return;
- if (val == -1)
- bb_perror_msg_and_die("can't stat '%s'", device);
- if (!S_ISBLK(s.st_mode)) {
- printf("%s is not a block special device.\n", device);
- proceed_question();
- return;
- }
-
-#ifdef HAVE_LINUX_MAJOR_H
-#ifndef MAJOR
-#define MAJOR(dev) ((dev)>>8)
-#define MINOR(dev) ((dev) & 0xff)
-#endif
-#ifndef SCSI_BLK_MAJOR
-#ifdef SCSI_DISK0_MAJOR
-#ifdef SCSI_DISK8_MAJOR
-#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
- ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR) || \
- ((M) >= SCSI_DISK8_MAJOR && (M) <= SCSI_DISK15_MAJOR))
-#else
-#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
- ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
-#endif /* defined(SCSI_DISK8_MAJOR) */
-#define SCSI_BLK_MAJOR(M) (SCSI_DISK_MAJOR((M)) || (M) == SCSI_CDROM_MAJOR)
-#else
-#define SCSI_BLK_MAJOR(M) ((M) == SCSI_DISK_MAJOR || (M) == SCSI_CDROM_MAJOR)
-#endif /* defined(SCSI_DISK0_MAJOR) */
-#endif /* defined(SCSI_BLK_MAJOR) */
- if (((MAJOR(s.st_rdev) == HD_MAJOR &&
- MINOR(s.st_rdev)%64 == 0) ||
- (SCSI_BLK_MAJOR(MAJOR(s.st_rdev)) &&
- MINOR(s.st_rdev)%16 == 0))) {
- printf("%s is entire device, not just one partition!\n", device);
- proceed_question();
- }
-#endif
-}
-
-void check_mount(const char *device, int force, const char *type UNUSED_PARAM)
-{
- errcode_t retval;
- int mount_flags;
-
- retval = ext2fs_check_if_mounted(device, &mount_flags);
- if (retval) {
- bb_error_msg("can't determine if %s is mounted", device);
- return;
- }
- if (mount_flags & EXT2_MF_MOUNTED) {
- bb_error_msg("%s is mounted !", device);
-force_check:
- if (force)
- bb_error_msg("badblocks forced anyways");
- else
- bb_error_msg_and_die("it's not safe to run badblocks!");
- }
-
- if (mount_flags & EXT2_MF_BUSY) {
- bb_error_msg("%s is apparently in use by the system", device);
- goto force_check;
- }
-}
-
-void parse_journal_opts(char **journal_device, int *journal_flags,
- int *journal_size, const char *opts)
-{
- char *buf, *token, *next, *p, *arg;
- int journal_usage = 0;
- buf = xstrdup(opts);
- for (token = buf; token && *token; token = next) {
- p = strchr(token, ',');
- next = 0;
- if (p) {
- *p = 0;
- next = p+1;
- }
- arg = strchr(token, '=');
- if (arg) {
- *arg = 0;
- arg++;
- }
- if (strcmp(token, "device") == 0) {
- *journal_device = arg;
- if (resolve_mount_spec(journal_device) < 0 ||
- !(*journal_device)) {
- journal_usage++;
- continue;
- }
- } else if (strcmp(token, "size") == 0) {
- if (!arg) {
- journal_usage++;
- continue;
- }
- (*journal_size) = strtoul(arg, &p, 0);
- if (*p)
- journal_usage++;
- } else if (strcmp(token, "v1_superblock") == 0) {
- (*journal_flags) |= EXT2_MKJOURNAL_V1_SUPER;
- continue;
- } else
- journal_usage++;
- }
- if (journal_usage)
- bb_error_msg_and_die(
- "\nBad journal options specified.\n\n"
- "Journal options are separated by commas, "
- "and may take an argument which\n"
- "\tis set off by an equals ('=') sign.\n\n"
- "Valid journal options are:\n"
- "\tsize=<journal size in megabytes>\n"
- "\tdevice=<journal device>\n\n"
- "The journal size must be between "
- "1024 and 102400 filesystem blocks.\n\n");
-}
-
-/*
- * Determine the number of journal blocks to use, either via
- * user-specified # of megabytes, or via some intelligently selected
- * defaults.
- *
- * Find a reasonable journal file size (in blocks) given the number of blocks
- * in the filesystem. For very small filesystems, it is not reasonable to
- * have a journal that fills more than half of the filesystem.
- */
-int figure_journal_size(int size, ext2_filsys fs)
-{
- blk_t j_blocks;
-
- if (fs->super->s_blocks_count < 2048) {
- bb_error_msg("Filesystem too small for a journal");
- return 0;
- }
-
- if (size >= 0) {
- j_blocks = size * 1024 / (fs->blocksize / 1024);
- if (j_blocks < 1024 || j_blocks > 102400)
- bb_error_msg_and_die("\nThe requested journal "
- "size is %d blocks;\n it must be "
- "between 1024 and 102400 blocks; Aborting",
- j_blocks);
- if (j_blocks > fs->super->s_free_blocks_count)
- bb_error_msg_and_die("Journal size too big for filesystem");
- return j_blocks;
- }
-
- if (fs->super->s_blocks_count < 32768)
- j_blocks = 1024;
- else if (fs->super->s_blocks_count < 256*1024)
- j_blocks = 4096;
- else if (fs->super->s_blocks_count < 512*1024)
- j_blocks = 8192;
- else if (fs->super->s_blocks_count < 1024*1024)
- j_blocks = 16384;
- else
- j_blocks = 32768;
-
- return j_blocks;
-}
-
-void print_check_message(ext2_filsys fs)
-{
- printf("This filesystem will be automatically "
- "checked every %d mounts or\n"
- "%g days, whichever comes first. "
- "Use tune2fs -c or -i to override.\n",
- fs->super->s_max_mnt_count,
- (double)fs->super->s_checkinterval / (3600 * 24));
-}
-
-void make_journal_device(char *journal_device, ext2_filsys fs, int quiet, int force)
-{
- errcode_t retval;
- ext2_filsys jfs;
- io_manager io_ptr;
-
- check_plausibility(journal_device, force);
- check_mount(journal_device, force, "journal");
- io_ptr = unix_io_manager;
- retval = ext2fs_open(journal_device, EXT2_FLAG_RW|
- EXT2_FLAG_JOURNAL_DEV_OK, 0,
- fs->blocksize, io_ptr, &jfs);
- if (retval)
- bb_error_msg_and_die("can't journal device %s", journal_device);
- if (!quiet)
- printf("Adding journal to device %s: ", journal_device);
- fflush(stdout);
- retval = ext2fs_add_journal_device(fs, jfs);
- if (retval)
- bb_error_msg_and_die("\nFailed to add journal to device %s", journal_device);
- if (!quiet)
- puts("done");
- ext2fs_close(jfs);
-}
-
-void make_journal_blocks(ext2_filsys fs, int journal_size, int journal_flags, int quiet)
-{
- unsigned long journal_blocks;
- errcode_t retval;
-
- journal_blocks = figure_journal_size(journal_size, fs);
- if (!journal_blocks) {
- fs->super->s_feature_compat &=
- ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
- return;
- }
- if (!quiet)
- printf("Creating journal (%ld blocks): ", journal_blocks);
- fflush(stdout);
- retval = ext2fs_add_journal_inode(fs, journal_blocks,
- journal_flags);
- if (retval)
- bb_error_msg_and_die("can't create journal");
- if (!quiet)
- puts("done");
-}
-
-char *e2fs_set_sbin_path(void)
-{
- char *oldpath = getenv("PATH");
- /* Update our PATH to include /sbin */
-#define PATH_SET "/sbin"
- if (oldpath)
- oldpath = xasprintf("%s:%s", PATH_SET, oldpath);
- else
- oldpath = (char *)PATH_SET;
- putenv(oldpath);
- return oldpath;
-}
diff --git a/release/src/router/busybox/e2fsprogs/util.h b/release/src/router/busybox/e2fsprogs/util.h
deleted file mode 100644
index 80d2417185..0000000000
--- a/release/src/router/busybox/e2fsprogs/util.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * util.h --- header file defining prototypes for helper functions
- * used by tune2fs and mke2fs
- *
- * Copyright 2000 by Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-extern void proceed_question(void);
-extern void check_plausibility(const char *device, int force);
-extern void parse_journal_opts(char **, int *, int *, const char *opts);
-extern void check_mount(const char *device, int force, const char *type);
-extern int figure_journal_size(int size, ext2_filsys fs);
-extern void print_check_message(ext2_filsys fs);
-extern void make_journal_device(char *journal_device, ext2_filsys fs, int quiet, int force);
-extern void make_journal_blocks(ext2_filsys fs, int journal_size, int journal_flags, int quiet);
-extern char *e2fs_set_sbin_path(void);
diff --git a/release/src/router/busybox/e2fsprogs/uuid/Kbuild.src b/release/src/router/busybox/e2fsprogs/uuid/Kbuild.src
deleted file mode 100644
index b8c687d30c..0000000000
--- a/release/src/router/busybox/e2fsprogs/uuid/Kbuild.src
+++ /dev/null
@@ -1,16 +0,0 @@
-# Makefile for busybox
-#
-# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
-#
-# Licensed under GPLv2, see file LICENSE in this source tree.
-
-NEEDED-$(CONFIG_E2FSCK) = y
-NEEDED-$(CONFIG_FSCK) = y
-NEEDED-$(CONFIG_MKE2FS) = y
-NEEDED-$(CONFIG_TUNE2FS) = y
-
-lib-y:=
-
-INSERT
-lib-$(NEEDED-y) += compare.o gen_uuid.o pack.o parse.o unpack.o unparse.o \
- uuid_time.o
diff --git a/release/src/router/busybox/e2fsprogs/uuid/compare.c b/release/src/router/busybox/e2fsprogs/uuid/compare.c
deleted file mode 100644
index 348ea7c1f9..0000000000
--- a/release/src/router/busybox/e2fsprogs/uuid/compare.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * compare.c --- compare whether or not two UUID's are the same
- *
- * Returns 0 if the two UUID's are different, and 1 if they are the same.
- *
- * Copyright (C) 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, and the entire permission notice in its entirety,
- * including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
- * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- * %End-Header%
- */
-
-#include "uuidP.h"
-#include <string.h>
-
-#define UUCMP(u1,u2) if (u1 != u2) return (u1 < u2) ? -1 : 1;
-
-int uuid_compare(const uuid_t uu1, const uuid_t uu2)
-{
- struct uuid uuid1, uuid2;
-
- uuid_unpack(uu1, &uuid1);
- uuid_unpack(uu2, &uuid2);
-
- UUCMP(uuid1.time_low, uuid2.time_low);
- UUCMP(uuid1.time_mid, uuid2.time_mid);
- UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version);
- UUCMP(uuid1.clock_seq, uuid2.clock_seq);
- return memcmp(uuid1.node, uuid2.node, 6);
-}
diff --git a/release/src/router/busybox/e2fsprogs/uuid/gen_uuid.c b/release/src/router/busybox/e2fsprogs/uuid/gen_uuid.c
deleted file mode 100644
index 4310c17db9..0000000000
--- a/release/src/router/busybox/e2fsprogs/uuid/gen_uuid.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * gen_uuid.c --- generate a DCE-compatible uuid
- *
- * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o.
- *
- * %Begin-Header%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, and the entire permission notice in its entirety,
- * including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
- * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- * %End-Header%
- */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/file.h>
-#include <sys/time.h>
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#include <sys/socket.h>
-#ifdef HAVE_SYS_SOCKIO_H
-#include <sys/sockio.h>
-#endif
-#ifdef HAVE_NET_IF_H
-#include <net/if.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_NET_IF_DL_H
-#include <net/if_dl.h>
-#endif
-
-#include "uuidP.h"
-
-#ifdef HAVE_SRANDOM
-#define srand(x) srandom(x)
-#define rand() random()
-#endif
-
-static int get_random_fd(void)
-{
- struct timeval tv;
- static int fd = -2;
- int i;
-
- if (fd == -2) {
- gettimeofday(&tv, 0);
- fd = open("/dev/urandom", O_RDONLY);
- if (fd == -1)
- fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
- srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
- }
- /* Crank the random number generator a few times */
- gettimeofday(&tv, 0);
- for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
- rand();
- return fd;
-}
-
-
-/*
- * Generate a series of random bytes. Use /dev/urandom if possible,
- * and if not, use srandom/random.
- */
-static void get_random_bytes(void *buf, int nbytes)
-{
- int i, n = nbytes, fd = get_random_fd();
- int lose_counter = 0;
- unsigned char *cp = (unsigned char *) buf;
-
- if (fd >= 0) {
- while (n > 0) {
- i = read(fd, cp, n);
- if (i <= 0) {
- if (lose_counter++ > 16)
- break;
- continue;
- }
- n -= i;
- cp += i;
- lose_counter = 0;
- }
- }
-
- /*
- * We do this all the time, but this is the only source of
- * randomness if /dev/random/urandom is out to lunch.
- */
- for (cp = buf, i = 0; i < nbytes; i++)
- *cp++ ^= (rand() >> 7) & 0xFF;
-}
-
-/*
- * Get the ethernet hardware address, if we can find it...
- */
-static int get_node_id(unsigned char *node_id)
-{
-#ifdef HAVE_NET_IF_H
- int sd;
- struct ifreq ifr, *ifrp;
- struct ifconf ifc;
- char buf[1024];
- int n, i;
- unsigned char *a;
-#ifdef HAVE_NET_IF_DL_H
- struct sockaddr_dl *sdlp;
-#endif
-
-/*
- * BSD 4.4 defines the size of an ifreq to be
- * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
- * However, under earlier systems, sa_len isn't present, so the size is
- * just sizeof(struct ifreq)
- */
-#ifdef HAVE_SA_LEN
-#ifndef max
-#define max(a,b) ((a) > (b) ? (a) : (b))
-#endif
-#define ifreq_size(i) max(sizeof(struct ifreq),\
- sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
-#else
-#define ifreq_size(i) sizeof(struct ifreq)
-#endif /* HAVE_SA_LEN*/
-
- sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
- if (sd < 0) {
- return -1;
- }
- memset(buf, 0, sizeof(buf));
- ifc.ifc_len = sizeof(buf);
- ifc.ifc_buf = buf;
- if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) {
- close(sd);
- return -1;
- }
- n = ifc.ifc_len;
- for (i = 0; i < n; i+= ifreq_size(*ifrp) ) {
- ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
- strncpy_IFNAMSIZ(ifr.ifr_name, ifrp->ifr_name);
-#ifdef SIOCGIFHWADDR
- if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
- continue;
- a = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
-#else
-#ifdef SIOCGENADDR
- if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
- continue;
- a = (unsigned char *) ifr.ifr_enaddr;
-#else
-#ifdef HAVE_NET_IF_DL_H
- sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr;
- if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6))
- continue;
- a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen];
-#else
- /*
- * XXX we don't have a way of getting the hardware
- * address
- */
- close(sd);
- return 0;
-#endif /* HAVE_NET_IF_DL_H */
-#endif /* SIOCGENADDR */
-#endif /* SIOCGIFHWADDR */
- if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
- continue;
- if (node_id) {
- memcpy(node_id, a, 6);
- close(sd);
- return 1;
- }
- }
- close(sd);
-#endif
- return 0;
-}
-
-/* Assume that the gettimeofday() has microsecond granularity */
-#define MAX_ADJUSTMENT 10
-
-static int get_clock(uint32_t *clock_high, uint32_t *clock_low, uint16_t *ret_clock_seq)
-{
- static int adjustment = 0;
- static struct timeval last = {0, 0};
- static uint16_t clock_seq;
- struct timeval tv;
- unsigned long long clock_reg;
-
-try_again:
- gettimeofday(&tv, 0);
- if ((last.tv_sec == 0) && (last.tv_usec == 0)) {
- get_random_bytes(&clock_seq, sizeof(clock_seq));
- clock_seq &= 0x3FFF;
- last = tv;
- last.tv_sec--;
- }
- if ((tv.tv_sec < last.tv_sec) ||
- ((tv.tv_sec == last.tv_sec) &&
- (tv.tv_usec < last.tv_usec))) {
- clock_seq = (clock_seq+1) & 0x3FFF;
- adjustment = 0;
- last = tv;
- } else if ((tv.tv_sec == last.tv_sec) &&
- (tv.tv_usec == last.tv_usec)) {
- if (adjustment >= MAX_ADJUSTMENT)
- goto try_again;
- adjustment++;
- } else {
- adjustment = 0;
- last = tv;
- }
-
- clock_reg = tv.tv_usec*10 + adjustment;
- clock_reg += ((unsigned long long) tv.tv_sec)*10000000;
- clock_reg += (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000;
-
- *clock_high = clock_reg >> 32;
- *clock_low = clock_reg;
- *ret_clock_seq = clock_seq;
- return 0;
-}
-
-void uuid_generate_time(uuid_t out)
-{
- static unsigned char node_id[6];
- static int has_init = 0;
- struct uuid uu;
- uint32_t clock_mid;
-
- if (!has_init) {
- if (get_node_id(node_id) <= 0) {
- get_random_bytes(node_id, 6);
- /*
- * Set multicast bit, to prevent conflicts
- * with IEEE 802 addresses obtained from
- * network cards
- */
- node_id[0] |= 0x01;
- }
- has_init = 1;
- }
- get_clock(&clock_mid, &uu.time_low, &uu.clock_seq);
- uu.clock_seq |= 0x8000;
- uu.time_mid = (uint16_t) clock_mid;
- uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000;
- memcpy(uu.node, node_id, 6);
- uuid_pack(&uu, out);
-}
-
-void uuid_generate_random(uuid_t out)
-{
- uuid_t buf;
- struct uuid uu;
-
- get_random_bytes(buf, sizeof(buf));
- uuid_unpack(buf, &uu);
-
- uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
- uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000;
- uuid_pack(&uu, out);
-}
-
-/*
- * This is the generic front-end to uuid_generate_random and
- * uuid_generate_time. It uses uuid_generate_random only if
- * /dev/urandom is available, since otherwise we won't have
- * high-quality randomness.
- */
-void uuid_generate(uuid_t out)
-{
- if (get_random_fd() >= 0)
- uuid_generate_random(out);
- else
- uuid_generate_time(out);
-}
diff --git a/release/src/router/busybox/e2fsprogs/uuid/pack.c b/release/src/router/busybox/e2fsprogs/uuid/pack.c
deleted file mode 100644
index 217cfce5d7..0000000000
--- a/release/src/router/busybox/e2fsprogs/uuid/pack.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * Internal routine for packing UUID's
- *
- * Copyright (C) 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, and the entire permission notice in its entirety,
- * including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
- * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- * %End-Header%
- */
-
-#include <string.h>
-#include "uuidP.h"
-
-void uuid_pack(const struct uuid *uu, uuid_t ptr)
-{
- uint32_t tmp;
- unsigned char *out = ptr;
-
- tmp = uu->time_low;
- out[3] = (unsigned char) tmp;
- tmp >>= 8;
- out[2] = (unsigned char) tmp;
- tmp >>= 8;
- out[1] = (unsigned char) tmp;
- tmp >>= 8;
- out[0] = (unsigned char) tmp;
-
- tmp = uu->time_mid;
- out[5] = (unsigned char) tmp;
- tmp >>= 8;
- out[4] = (unsigned char) tmp;
-
- tmp = uu->time_hi_and_version;
- out[7] = (unsigned char) tmp;
- tmp >>= 8;
- out[6] = (unsigned char) tmp;
-
- tmp = uu->clock_seq;
- out[9] = (unsigned char) tmp;
- tmp >>= 8;
- out[8] = (unsigned char) tmp;
-
- memcpy(out+10, uu->node, 6);
-}
diff --git a/release/src/router/busybox/e2fsprogs/uuid/parse.c b/release/src/router/busybox/e2fsprogs/uuid/parse.c
deleted file mode 100644
index 9a3f9cb921..0000000000
--- a/release/src/router/busybox/e2fsprogs/uuid/parse.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * parse.c --- UUID parsing
- *
- * Copyright (C) 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, and the entire permission notice in its entirety,
- * including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
- * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- * %End-Header%
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-
-#include "uuidP.h"
-
-int uuid_parse(const char *in, uuid_t uu)
-{
- struct uuid uuid;
- int i;
- const char *cp;
- char buf[3];
-
- if (strlen(in) != 36)
- return -1;
- for (i=0, cp = in; i <= 36; i++,cp++) {
- if ((i == 8) || (i == 13) || (i == 18) ||
- (i == 23)) {
- if (*cp == '-')
- continue;
- else
- return -1;
- }
- if (i== 36)
- if (*cp == 0)
- continue;
- if (!isxdigit(*cp))
- return -1;
- }
- uuid.time_low = strtoul(in, NULL, 16);
- uuid.time_mid = strtoul(in+9, NULL, 16);
- uuid.time_hi_and_version = strtoul(in+14, NULL, 16);
- uuid.clock_seq = strtoul(in+19, NULL, 16);
- cp = in+24;
- buf[2] = 0;
- for (i=0; i < 6; i++) {
- buf[0] = *cp++;
- buf[1] = *cp++;
- uuid.node[i] = strtoul(buf, NULL, 16);
- }
-
- uuid_pack(&uuid, uu);
- return 0;
-}
diff --git a/release/src/router/busybox/e2fsprogs/uuid/unpack.c b/release/src/router/busybox/e2fsprogs/uuid/unpack.c
deleted file mode 100644
index 95d3aab4a2..0000000000
--- a/release/src/router/busybox/e2fsprogs/uuid/unpack.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * Internal routine for unpacking UUID
- *
- * Copyright (C) 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, and the entire permission notice in its entirety,
- * including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
- * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- * %End-Header%
- */
-
-#include <string.h>
-#include "uuidP.h"
-
-void uuid_unpack(const uuid_t in, struct uuid *uu)
-{
- const uint8_t *ptr = in;
- uint32_t tmp;
-
- tmp = *ptr++;
- tmp = (tmp << 8) | *ptr++;
- tmp = (tmp << 8) | *ptr++;
- tmp = (tmp << 8) | *ptr++;
- uu->time_low = tmp;
-
- tmp = *ptr++;
- tmp = (tmp << 8) | *ptr++;
- uu->time_mid = tmp;
-
- tmp = *ptr++;
- tmp = (tmp << 8) | *ptr++;
- uu->time_hi_and_version = tmp;
-
- tmp = *ptr++;
- tmp = (tmp << 8) | *ptr++;
- uu->clock_seq = tmp;
-
- memcpy(uu->node, ptr, 6);
-}
diff --git a/release/src/router/busybox/e2fsprogs/uuid/unparse.c b/release/src/router/busybox/e2fsprogs/uuid/unparse.c
deleted file mode 100644
index d2948fe6dc..0000000000
--- a/release/src/router/busybox/e2fsprogs/uuid/unparse.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * unparse.c -- convert a UUID to string
- *
- * Copyright (C) 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, and the entire permission notice in its entirety,
- * including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
- * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- * %End-Header%
- */
-
-#include <stdio.h>
-
-#include "uuidP.h"
-
-static const char *fmt_lower =
- "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
-
-static const char *fmt_upper =
- "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X";
-
-#ifdef UUID_UNPARSE_DEFAULT_UPPER
-#define FMT_DEFAULT fmt_upper
-#else
-#define FMT_DEFAULT fmt_lower
-#endif
-
-static void uuid_unparse_x(const uuid_t uu, char *out, const char *fmt)
-{
- struct uuid uuid;
-
- uuid_unpack(uu, &uuid);
- sprintf(out, fmt,
- uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
- uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
- uuid.node[0], uuid.node[1], uuid.node[2],
- uuid.node[3], uuid.node[4], uuid.node[5]);
-}
-
-void uuid_unparse_lower(const uuid_t uu, char *out)
-{
- uuid_unparse_x(uu, out, fmt_lower);
-}
-
-void uuid_unparse_upper(const uuid_t uu, char *out)
-{
- uuid_unparse_x(uu, out, fmt_upper);
-}
-
-void uuid_unparse(const uuid_t uu, char *out)
-{
- uuid_unparse_x(uu, out, FMT_DEFAULT);
-}
diff --git a/release/src/router/busybox/e2fsprogs/uuid/uuid.h b/release/src/router/busybox/e2fsprogs/uuid/uuid.h
deleted file mode 100644
index 7a9706449b..0000000000
--- a/release/src/router/busybox/e2fsprogs/uuid/uuid.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * Public include file for the UUID library
- *
- * Copyright (C) 1996, 1997, 1998 Theodore Ts'o.
- *
- * %Begin-Header%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, and the entire permission notice in its entirety,
- * including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
- * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- * %End-Header%
- */
-#ifndef UUID_UUID_H
-#define UUID_UUID_H 1
-
-#include <sys/types.h>
-#include <time.h>
-
-typedef unsigned char uuid_t[16];
-
-/* UUID Variant definitions */
-#define UUID_VARIANT_NCS 0
-#define UUID_VARIANT_DCE 1
-#define UUID_VARIANT_MICROSOFT 2
-#define UUID_VARIANT_OTHER 3
-
-/* UUID Type definitions */
-#define UUID_TYPE_DCE_TIME 1
-#define UUID_TYPE_DCE_RANDOM 4
-
-/* Allow UUID constants to be defined */
-#ifdef __GNUC__
-#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \
- static const uuid_t name UNUSED_PARAM = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15}
-#else
-#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \
- static const uuid_t name = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15}
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* clear.c */
-/*void uuid_clear(uuid_t uu);*/
-#define uuid_clear(uu) memset(uu, 0, sizeof(uu))
-
-/* compare.c */
-int uuid_compare(const uuid_t uu1, const uuid_t uu2);
-
-/* copy.c */
-/*void uuid_copy(uuid_t dst, const uuid_t src);*/
-#define uuid_copy(dst,src) memcpy(dst, src, sizeof(dst))
-
-/* gen_uuid.c */
-void uuid_generate(uuid_t out);
-void uuid_generate_random(uuid_t out);
-void uuid_generate_time(uuid_t out);
-
-/* isnull.c */
-/*int uuid_is_null(const uuid_t uu);*/
-#define uuid_is_null(uu) (!memcmp(uu, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", sizeof(uu)))
-
-/* parse.c */
-int uuid_parse(const char *in, uuid_t uu);
-
-/* unparse.c */
-void uuid_unparse(const uuid_t uu, char *out);
-void uuid_unparse_lower(const uuid_t uu, char *out);
-void uuid_unparse_upper(const uuid_t uu, char *out);
-
-/* uuid_time.c */
-time_t uuid_time(const uuid_t uu, struct timeval *ret_tv);
-int uuid_type(const uuid_t uu);
-int uuid_variant(const uuid_t uu);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _UUID_UUID_H */
diff --git a/release/src/router/busybox/e2fsprogs/uuid/uuidP.h b/release/src/router/busybox/e2fsprogs/uuid/uuidP.h
deleted file mode 100644
index 87041ef0a2..0000000000
--- a/release/src/router/busybox/e2fsprogs/uuid/uuidP.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * uuid.h -- private header file for uuids
- *
- * Copyright (C) 1996, 1997 Theodore Ts'o.
- *
- * %Begin-Header%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, and the entire permission notice in its entirety,
- * including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
- * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- * %End-Header%
- */
-
-#include <inttypes.h>
-#include <sys/types.h>
-
-#include "uuid.h"
-
-/*
- * Offset between 15-Oct-1582 and 1-Jan-70
- */
-#define TIME_OFFSET_HIGH 0x01B21DD2
-#define TIME_OFFSET_LOW 0x13814000
-
-struct uuid {
- uint32_t time_low;
- uint16_t time_mid;
- uint16_t time_hi_and_version;
- uint16_t clock_seq;
- uint8_t node[6];
-};
-
-
-/*
- * prototypes
- */
-void uuid_pack(const struct uuid *uu, uuid_t ptr);
-void uuid_unpack(const uuid_t in, struct uuid *uu);
diff --git a/release/src/router/busybox/e2fsprogs/uuid/uuid_time.c b/release/src/router/busybox/e2fsprogs/uuid/uuid_time.c
deleted file mode 100644
index b6f73e6dc9..0000000000
--- a/release/src/router/busybox/e2fsprogs/uuid/uuid_time.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * uuid_time.c --- Interpret the time field from a uuid. This program
- * violates the UUID abstraction barrier by reaching into the guts
- * of a UUID and interpreting it.
- *
- * Copyright (C) 1998, 1999 Theodore Ts'o.
- *
- * %Begin-Header%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, and the entire permission notice in its entirety,
- * including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
- * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <time.h>
-
-#include "uuidP.h"
-
-time_t uuid_time(const uuid_t uu, struct timeval *ret_tv)
-{
- struct uuid uuid;
- uint32_t high;
- struct timeval tv;
- unsigned long long clock_reg;
-
- uuid_unpack(uu, &uuid);
-
- high = uuid.time_mid | ((uuid.time_hi_and_version & 0xFFF) << 16);
- clock_reg = uuid.time_low | ((unsigned long long) high << 32);
-
- clock_reg -= (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000;
- tv.tv_sec = clock_reg / 10000000;
- tv.tv_usec = (clock_reg % 10000000) / 10;
-
- if (ret_tv)
- *ret_tv = tv;
-
- return tv.tv_sec;
-}
-
-int uuid_type(const uuid_t uu)
-{
- struct uuid uuid;
-
- uuid_unpack(uu, &uuid);
- return ((uuid.time_hi_and_version >> 12) & 0xF);
-}
-
-int uuid_variant(const uuid_t uu)
-{
- struct uuid uuid;
- int var;
-
- uuid_unpack(uu, &uuid);
- var = uuid.clock_seq;
-
- if ((var & 0x8000) == 0)
- return UUID_VARIANT_NCS;
- if ((var & 0x4000) == 0)
- return UUID_VARIANT_DCE;
- if ((var & 0x2000) == 0)
- return UUID_VARIANT_MICROSOFT;
- return UUID_VARIANT_OTHER;
-}
-
-#ifdef DEBUG
-static const char *variant_string(int variant)
-{
- switch (variant) {
- case UUID_VARIANT_NCS:
- return "NCS";
- case UUID_VARIANT_DCE:
- return "DCE";
- case UUID_VARIANT_MICROSOFT:
- return "Microsoft";
- default:
- return "Other";
- }
-}
-
-
-int
-main(int argc, char **argv)
-{
- uuid_t buf;
- time_t time_reg;
- struct timeval tv;
- int type, variant;
-
- if (argc != 2) {
- fprintf(stderr, "Usage: %s uuid\n", argv[0]);
- exit(1);
- }
- if (uuid_parse(argv[1], buf)) {
- fprintf(stderr, "Invalid UUID: %s\n", argv[1]);
- exit(1);
- }
- variant = uuid_variant(buf);
- type = uuid_type(buf);
- time_reg = uuid_time(buf, &tv);
-
- printf("UUID variant is %d (%s)\n", variant, variant_string(variant));
- if (variant != UUID_VARIANT_DCE) {
- printf("Warning: This program only knows how to interpret "
- "DCE UUIDs.\n\tThe rest of the output is likely "
- "to be incorrect!!\n");
- }
- printf("UUID type is %d", type);
- switch (type) {
- case 1:
- printf(" (time based)\n");
- break;
- case 2:
- printf(" (DCE)\n");
- break;
- case 3:
- printf(" (name-based)\n");
- break;
- case 4:
- printf(" (random)\n");
- break;
- default:
- bb_putchar('\n');
- }
- if (type != 1) {
- printf("Warning: not a time-based UUID, so UUID time "
- "decoding will likely not work!\n");
- }
- printf("UUID time is: (%ld, %ld): %s\n", tv.tv_sec, tv.tv_usec,
- ctime(&time_reg));
-
- return 0;
-}
-#endif
diff --git a/release/src/router/busybox/editors/Config.src b/release/src/router/busybox/editors/Config.src
index af1e1de5eb..c6e9d92af5 100644
--- a/release/src/router/busybox/editors/Config.src
+++ b/release/src/router/busybox/editors/Config.src
@@ -7,66 +7,6 @@ menu "Editors"
INSERT
-config AWK
- bool "awk"
- default y
- help
- Awk is used as a pattern scanning and processing language. This is
- the BusyBox implementation of that programming language.
-
-config FEATURE_AWK_LIBM
- bool "Enable math functions (requires libm)"
- default y
- depends on AWK
- help
- Enable math functions of the Awk programming language.
- NOTE: This will require libm to be present for linking.
-
-config CMP
- bool "cmp"
- default y
- help
- cmp is used to compare two files and returns the result
- to standard output.
-
-config DIFF
- bool "diff"
- default y
- help
- diff compares two files or directories and outputs the
- differences between them in a form that can be given to
- the patch command.
-
-config FEATURE_DIFF_LONG_OPTIONS
- bool "Enable long options"
- default y
- depends on DIFF && LONG_OPTS
- help
- Enable use of long options.
-
-config FEATURE_DIFF_DIR
- bool "Enable directory support"
- default y
- depends on DIFF
- help
- This option enables support for directory and subdirectory
- comparison.
-
-config ED
- bool "ed"
- default y
- help
- The original 1970's Unix text editor, from the days of teletypes.
- Small, simple, evil. Part of SUSv3. If you're not already using
- this, you don't need it.
-
-config SED
- bool "sed"
- default y
- help
- sed is used to perform text transformations on a file
- or input from a pipeline.
-
config FEATURE_ALLOW_EXEC
bool "Allow vi and awk to execute shell commands"
default y
diff --git a/release/src/router/busybox/editors/Kbuild.src b/release/src/router/busybox/editors/Kbuild.src
index 8888cba126..6b4fb74700 100644
--- a/release/src/router/busybox/editors/Kbuild.src
+++ b/release/src/router/busybox/editors/Kbuild.src
@@ -7,8 +7,3 @@
lib-y:=
INSERT
-lib-$(CONFIG_AWK) += awk.o
-lib-$(CONFIG_CMP) += cmp.o
-lib-$(CONFIG_DIFF) += diff.o
-lib-$(CONFIG_ED) += ed.o
-lib-$(CONFIG_SED) += sed.o
diff --git a/release/src/router/busybox/editors/awk.c b/release/src/router/busybox/editors/awk.c
index 71abca215a..ea3770d7b9 100644
--- a/release/src/router/busybox/editors/awk.c
+++ b/release/src/router/busybox/editors/awk.c
@@ -7,12 +7,45 @@
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//config:config AWK
+//config: bool "awk"
+//config: default y
+//config: help
+//config: Awk is used as a pattern scanning and processing language. This is
+//config: the BusyBox implementation of that programming language.
+//config:
+//config:config FEATURE_AWK_LIBM
+//config: bool "Enable math functions (requires libm)"
+//config: default y
+//config: depends on AWK
+//config: help
+//config: Enable math functions of the Awk programming language.
+//config: NOTE: This will require libm to be present for linking.
+//config:
+//config:config FEATURE_AWK_GNU_EXTENSIONS
+//config: bool "Enable a few GNU extensions"
+//config: default y
+//config: depends on AWK
+//config: help
+//config: Enable a few features from gawk:
+//config: * command line option -e AWK_PROGRAM
+//config: * simultaneous use of -f and -e on the command line.
+//config: This enables the use of awk library files.
+//config: Ex: awk -f mylib.awk -e '{print myfunction($1);}' ...
+
+//applet:IF_AWK(APPLET_NOEXEC(awk, awk, BB_DIR_USR_BIN, BB_SUID_DROP, awk))
+
+//kbuild:lib-$(CONFIG_AWK) += awk.o
+
//usage:#define awk_trivial_usage
//usage: "[OPTIONS] [AWK_PROGRAM] [FILE]..."
//usage:#define awk_full_usage "\n\n"
//usage: " -v VAR=VAL Set variable"
//usage: "\n -F SEP Use SEP as field separator"
//usage: "\n -f FILE Read program from FILE"
+//usage: IF_FEATURE_AWK_GNU_EXTENSIONS(
+//usage: "\n -e AWK_PROGRAM"
+//usage: )
#include "libbb.h"
#include "xregex.h"
@@ -38,6 +71,25 @@
#endif
+#define OPTSTR_AWK \
+ "F:v:f:" \
+ IF_FEATURE_AWK_GNU_EXTENSIONS("e:") \
+ "W:"
+#define OPTCOMPLSTR_AWK \
+ "v::f::" \
+ IF_FEATURE_AWK_GNU_EXTENSIONS("e::")
+enum {
+ OPTBIT_F, /* define field separator */
+ OPTBIT_v, /* define variable */
+ OPTBIT_f, /* pull in awk program from file */
+ IF_FEATURE_AWK_GNU_EXTENSIONS(OPTBIT_e,) /* -e AWK_PROGRAM */
+ OPTBIT_W, /* -W ignored */
+ OPT_F = 1 << OPTBIT_F,
+ OPT_v = 1 << OPTBIT_v,
+ OPT_f = 1 << OPTBIT_f,
+ OPT_e = IF_FEATURE_AWK_GNU_EXTENSIONS((1 << OPTBIT_e)) + 0,
+ OPT_W = 1 << OPTBIT_W
+};
#define MAXVARFMT 240
#define MINNVBLOCK 64
@@ -155,7 +207,7 @@ typedef struct tsplitter_s {
/* simple token classes */
/* Order and hex values are very important!!! See next_token() */
-#define TC_SEQSTART 1 /* ( */
+#define TC_SEQSTART (1 << 0) /* ( */
#define TC_SEQTERM (1 << 1) /* ) */
#define TC_REGEXP (1 << 2) /* /.../ */
#define TC_OUTRDR (1 << 3) /* | > >> */
@@ -175,31 +227,39 @@ typedef struct tsplitter_s {
#define TC_WHILE (1 << 17)
#define TC_ELSE (1 << 18)
#define TC_BUILTIN (1 << 19)
-#define TC_GETLINE (1 << 20)
-#define TC_FUNCDECL (1 << 21) /* `function' `func' */
-#define TC_BEGIN (1 << 22)
-#define TC_END (1 << 23)
-#define TC_EOF (1 << 24)
-#define TC_VARIABLE (1 << 25)
-#define TC_ARRAY (1 << 26)
-#define TC_FUNCTION (1 << 27)
-#define TC_STRING (1 << 28)
-#define TC_NUMBER (1 << 29)
+/* This costs ~50 bytes of code.
+ * A separate class to support deprecated "length" form. If we don't need that
+ * (i.e. if we demand that only "length()" with () is valid), then TC_LENGTH
+ * can be merged with TC_BUILTIN:
+ */
+#define TC_LENGTH (1 << 20)
+#define TC_GETLINE (1 << 21)
+#define TC_FUNCDECL (1 << 22) /* `function' `func' */
+#define TC_BEGIN (1 << 23)
+#define TC_END (1 << 24)
+#define TC_EOF (1 << 25)
+#define TC_VARIABLE (1 << 26)
+#define TC_ARRAY (1 << 27)
+#define TC_FUNCTION (1 << 28)
+#define TC_STRING (1 << 29)
+#define TC_NUMBER (1 << 30)
#define TC_UOPPRE (TC_UOPPRE1 | TC_UOPPRE2)
/* combined token classes */
#define TC_BINOP (TC_BINOPX | TC_COMMA | TC_PIPE | TC_IN)
-#define TC_UNARYOP (TC_UOPPRE | TC_UOPPOST)
+//#define TC_UNARYOP (TC_UOPPRE | TC_UOPPOST)
#define TC_OPERAND (TC_VARIABLE | TC_ARRAY | TC_FUNCTION \
- | TC_BUILTIN | TC_GETLINE | TC_SEQSTART | TC_STRING | TC_NUMBER)
+ | TC_BUILTIN | TC_LENGTH | TC_GETLINE \
+ | TC_SEQSTART | TC_STRING | TC_NUMBER)
#define TC_STATEMNT (TC_STATX | TC_WHILE)
#define TC_OPTERM (TC_SEMICOL | TC_NEWLINE)
/* word tokens, cannot mean something else if not expected */
-#define TC_WORD (TC_IN | TC_STATEMNT | TC_ELSE | TC_BUILTIN \
- | TC_GETLINE | TC_FUNCDECL | TC_BEGIN | TC_END)
+#define TC_WORD (TC_IN | TC_STATEMNT | TC_ELSE \
+ | TC_BUILTIN | TC_LENGTH | TC_GETLINE \
+ | TC_FUNCDECL | TC_BEGIN | TC_END)
/* discard newlines after these */
#define TC_NOTERM (TC_COMMA | TC_GRPSTART | TC_GRPTERM \
@@ -294,54 +354,54 @@ enum {
#define NTC "\377" /* switch to next token class (tc<<1) */
#define NTCC '\377'
-#define OC_B OC_BUILTIN
-
static const char tokenlist[] ALIGN1 =
- "\1(" NTC
- "\1)" NTC
- "\1/" NTC /* REGEXP */
- "\2>>" "\1>" "\1|" NTC /* OUTRDR */
- "\2++" "\2--" NTC /* UOPPOST */
- "\2++" "\2--" "\1$" NTC /* UOPPRE1 */
- "\2==" "\1=" "\2+=" "\2-=" /* BINOPX */
+ "\1(" NTC /* TC_SEQSTART */
+ "\1)" NTC /* TC_SEQTERM */
+ "\1/" NTC /* TC_REGEXP */
+ "\2>>" "\1>" "\1|" NTC /* TC_OUTRDR */
+ "\2++" "\2--" NTC /* TC_UOPPOST */
+ "\2++" "\2--" "\1$" NTC /* TC_UOPPRE1 */
+ "\2==" "\1=" "\2+=" "\2-=" /* TC_BINOPX */
"\2*=" "\2/=" "\2%=" "\2^="
"\1+" "\1-" "\3**=" "\2**"
"\1/" "\1%" "\1^" "\1*"
"\2!=" "\2>=" "\2<=" "\1>"
"\1<" "\2!~" "\1~" "\2&&"
"\2||" "\1?" "\1:" NTC
- "\2in" NTC
- "\1," NTC
- "\1|" NTC
- "\1+" "\1-" "\1!" NTC /* UOPPRE2 */
- "\1]" NTC
- "\1{" NTC
- "\1}" NTC
- "\1;" NTC
- "\1\n" NTC
- "\2if" "\2do" "\3for" "\5break" /* STATX */
+ "\2in" NTC /* TC_IN */
+ "\1," NTC /* TC_COMMA */
+ "\1|" NTC /* TC_PIPE */
+ "\1+" "\1-" "\1!" NTC /* TC_UOPPRE2 */
+ "\1]" NTC /* TC_ARRTERM */
+ "\1{" NTC /* TC_GRPSTART */
+ "\1}" NTC /* TC_GRPTERM */
+ "\1;" NTC /* TC_SEMICOL */
+ "\1\n" NTC /* TC_NEWLINE */
+ "\2if" "\2do" "\3for" "\5break" /* TC_STATX */
"\10continue" "\6delete" "\5print"
"\6printf" "\4next" "\10nextfile"
"\6return" "\4exit" NTC
- "\5while" NTC
- "\4else" NTC
-
- "\3and" "\5compl" "\6lshift" "\2or"
+ "\5while" NTC /* TC_WHILE */
+ "\4else" NTC /* TC_ELSE */
+ "\3and" "\5compl" "\6lshift" "\2or" /* TC_BUILTIN */
"\6rshift" "\3xor"
- "\5close" "\6system" "\6fflush" "\5atan2" /* BUILTIN */
+ "\5close" "\6system" "\6fflush" "\5atan2"
"\3cos" "\3exp" "\3int" "\3log"
"\4rand" "\3sin" "\4sqrt" "\5srand"
- "\6gensub" "\4gsub" "\5index" "\6length"
+ "\6gensub" "\4gsub" "\5index" /* "\6length" was here */
"\5match" "\5split" "\7sprintf" "\3sub"
"\6substr" "\7systime" "\10strftime" "\6mktime"
"\7tolower" "\7toupper" NTC
- "\7getline" NTC
- "\4func" "\10function" NTC
- "\5BEGIN" NTC
- "\3END"
+ "\6length" NTC /* TC_LENGTH */
+ "\7getline" NTC /* TC_GETLINE */
+ "\4func" "\10function" NTC /* TC_FUNCDECL */
+ "\5BEGIN" NTC /* TC_BEGIN */
+ "\3END" /* TC_END */
/* compiler adds trailing "\0" */
;
+#define OC_B OC_BUILTIN
+
static const uint32_t tokeninfo[] = {
0,
0,
@@ -356,7 +416,7 @@ static const uint32_t tokeninfo[] = {
OC_COMPARE|VV|P(39)|4, OC_COMPARE|VV|P(39)|3, OC_COMPARE|VV|P(39)|0, OC_COMPARE|VV|P(39)|1,
OC_COMPARE|VV|P(39)|2, OC_MATCH|Sx|P(45)|'!', OC_MATCH|Sx|P(45)|'~', OC_LAND|Vx|P(55),
OC_LOR|Vx|P(59), OC_TERNARY|Vx|P(64)|'?', OC_COLON|xx|P(67)|':',
- OC_IN|SV|P(49), /* in */
+ OC_IN|SV|P(49), /* TC_IN */
OC_COMMA|SS|P(80),
OC_PGETLINE|SV|P(37),
OC_UNARY|xV|P(19)|'+', OC_UNARY|xV|P(19)|'-', OC_UNARY|xV|P(19)|'!',
@@ -371,20 +431,20 @@ static const uint32_t tokeninfo[] = {
OC_RETURN|Vx, OC_EXIT|Nx,
ST_WHILE,
0, /* else */
-
OC_B|B_an|P(0x83), OC_B|B_co|P(0x41), OC_B|B_ls|P(0x83), OC_B|B_or|P(0x83),
OC_B|B_rs|P(0x83), OC_B|B_xo|P(0x83),
OC_FBLTIN|Sx|F_cl, OC_FBLTIN|Sx|F_sy, OC_FBLTIN|Sx|F_ff, OC_B|B_a2|P(0x83),
OC_FBLTIN|Nx|F_co, OC_FBLTIN|Nx|F_ex, OC_FBLTIN|Nx|F_in, OC_FBLTIN|Nx|F_lg,
OC_FBLTIN|F_rn, OC_FBLTIN|Nx|F_si, OC_FBLTIN|Nx|F_sq, OC_FBLTIN|Nx|F_sr,
- OC_B|B_ge|P(0xd6), OC_B|B_gs|P(0xb6), OC_B|B_ix|P(0x9b), OC_FBLTIN|Sx|F_le,
+ OC_B|B_ge|P(0xd6), OC_B|B_gs|P(0xb6), OC_B|B_ix|P(0x9b), /* OC_FBLTIN|Sx|F_le, was here */
OC_B|B_ma|P(0x89), OC_B|B_sp|P(0x8b), OC_SPRINTF, OC_B|B_su|P(0xb6),
OC_B|B_ss|P(0x8f), OC_FBLTIN|F_ti, OC_B|B_ti|P(0x0b), OC_B|B_mt|P(0x0b),
OC_B|B_lo|P(0x49), OC_B|B_up|P(0x49),
+ OC_FBLTIN|Sx|F_le, /* TC_LENGTH */
OC_GETLINE|SV|P(0),
0, 0,
0,
- 0 /* END */
+ 0 /* TC_END */
};
/* internal variable names and their initial values */
@@ -696,6 +756,10 @@ static char nextchar(char **s)
pps = *s;
if (c == '\\')
c = bb_process_escape_sequence((const char**)s);
+ /* Example awk statement:
+ * s = "abc\"def"
+ * we must treat \" as "
+ */
if (c == '\\' && *s == pps) { /* unrecognized \z? */
c = *(*s); /* yes, fetch z */
if (c)
@@ -704,6 +768,15 @@ static char nextchar(char **s)
return c;
}
+/* TODO: merge with strcpy_and_process_escape_sequences()?
+ */
+static void unescape_string_in_place(char *s1)
+{
+ char *s = s1;
+ while ((*s1 = nextchar(&s)) != '\0')
+ s1++;
+}
+
static ALWAYS_INLINE int isalnum_(int c)
{
return (isalnum(c) || c == '_');
@@ -995,12 +1068,10 @@ static uint32_t next_token(uint32_t expected)
if (t_rollback) {
t_rollback = FALSE;
-
} else if (concat_inserted) {
concat_inserted = FALSE;
t_tclass = save_tclass;
t_info = save_info;
-
} else {
p = g_pos;
readnext:
@@ -1016,7 +1087,6 @@ static uint32_t next_token(uint32_t expected)
if (*p == '\0') {
tc = TC_EOF;
debug_printf_parse("%s: token found: TC_EOF\n", __func__);
-
} else if (*p == '\"') {
/* it's a string */
t_string = s = ++p;
@@ -1032,7 +1102,6 @@ static uint32_t next_token(uint32_t expected)
*s = '\0';
tc = TC_STRING;
debug_printf_parse("%s: token found:'%s' TC_STRING\n", __func__, t_string);
-
} else if ((expected & TC_REGEXP) && *p == '/') {
/* it's regexp */
t_string = s = ++p;
@@ -1065,7 +1134,6 @@ static uint32_t next_token(uint32_t expected)
syntax_error(EMSG_UNEXP_TOKEN);
tc = TC_NUMBER;
debug_printf_parse("%s: token found:%f TC_NUMBER\n", __func__, t_double);
-
} else {
/* search for something known */
tl = tokenlist;
@@ -1142,9 +1210,10 @@ static uint32_t next_token(uint32_t expected)
ltclass = t_tclass;
/* Are we ready for this? */
- if (!(ltclass & expected))
+ if (!(ltclass & expected)) {
syntax_error((ltclass & (TC_NEWLINE | TC_EOF)) ?
EMSG_UNEXP_EOS : EMSG_UNEXP_TOKEN);
+ }
return ltclass;
#undef concat_inserted
@@ -1311,6 +1380,16 @@ static node *parse_expr(uint32_t iexp)
debug_printf_parse("%s: TC_BUILTIN\n", __func__);
cn->l.n = condition();
break;
+
+ case TC_LENGTH:
+ debug_printf_parse("%s: TC_LENGTH\n", __func__);
+ next_token(TC_SEQSTART | TC_OPTERM | TC_GRPTERM);
+ rollback_token();
+ if (t_tclass & TC_SEQSTART) {
+ /* It was a "(" token. Handle just like TC_BUILTIN */
+ cn->l.n = condition();
+ }
+ break;
}
}
}
@@ -1475,12 +1554,14 @@ static void chain_group(void)
debug_printf_parse("%s: OC_BREAK\n", __func__);
n = chain_node(OC_EXEC);
n->a.n = break_ptr;
+ chain_expr(t_info);
break;
case OC_CONTINUE:
debug_printf_parse("%s: OC_CONTINUE\n", __func__);
n = chain_node(OC_EXEC);
n->a.n = continue_ptr;
+ chain_expr(t_info);
break;
/* delete, next, nextfile, return, exit */
@@ -1513,12 +1594,10 @@ static void parse_program(char *p)
debug_printf_parse("%s: TC_BEGIN\n", __func__);
seq = &beginseq;
chain_group();
-
} else if (tclass & TC_END) {
debug_printf_parse("%s: TC_END\n", __func__);
seq = &endseq;
chain_group();
-
} else if (tclass & TC_FUNCDECL) {
debug_printf_parse("%s: TC_FUNCDECL\n", __func__);
next_token(TC_FUNCTION);
@@ -1536,7 +1615,6 @@ static void parse_program(char *p)
seq = &f->body;
chain_group();
clear_array(ahash);
-
} else if (tclass & TC_OPSEQ) {
debug_printf_parse("%s: TC_OPSEQ\n", __func__);
rollback_token();
@@ -1551,7 +1629,6 @@ static void parse_program(char *p)
chain_node(OC_PRINT);
}
cn->r.n = mainseq.last;
-
} else /* if (tclass & TC_GRPSTART) */ {
debug_printf_parse("%s: TC_GRPSTART(?)\n", __func__);
rollback_token();
@@ -1799,14 +1876,25 @@ static void handle_special(var *v)
is_f0_split = FALSE;
} else if (v == intvar[FS]) {
- mk_splitter(getvar_s(v), &fsplitter);
+ /*
+ * The POSIX-2008 standard says that changing FS should have no effect on the
+ * current input line, but only on the next one. The language is:
+ *
+ * > Before the first reference to a field in the record is evaluated, the record
+ * > shall be split into fields, according to the rules in Regular Expressions,
+ * > using the value of FS that was current at the time the record was read.
+ *
+ * So, split up current line before assignment to FS:
+ */
+#if 0 /* ASUS still using non-posix scripts */
+ split_f0();
+#endif
+ mk_splitter(getvar_s(v), &fsplitter);
} else if (v == intvar[RS]) {
mk_splitter(getvar_s(v), &rsplitter);
-
} else if (v == intvar[IGNORECASE]) {
icase = istrue(v);
-
} else { /* $n */
n = getvar_i(intvar[NF]);
setvar_i(intvar[NF], n > v-Fields ? n : v-Fields+1);
@@ -1990,8 +2078,8 @@ static int fmt_num(char *b, int size, const char *format, double n, int int_as_i
char c;
const char *s = format;
- if (int_as_int && n == (int)n) {
- r = snprintf(b, size, "%d", (int)n);
+ if (int_as_int && n == (long long)n) {
+ r = snprintf(b, size, "%lld", (long long)n);
} else {
do { c = *s; } while (c && *++s);
if (strchr("diouxX", c)) {
@@ -2636,7 +2724,8 @@ static var *evaluate(node *op, var *res)
var *vbeg, *v;
const char *sv_progname;
- if (!op->r.f->body.first)
+ /* The body might be empty, still has to eval the args */
+ if (!op->r.n->info && !op->r.f->body.first)
syntax_error(EMSG_UNDEF_FUNC);
vbeg = v = nvalloc(op->r.f->nargs + 1);
@@ -2707,7 +2796,7 @@ static var *evaluate(node *op, var *res)
switch (opn) {
case F_in:
- R_d = (int)L_d;
+ R_d = (long long)L_d;
break;
case F_rn:
@@ -2758,8 +2847,16 @@ static var *evaluate(node *op, var *res)
break;
case F_le:
- if (!op1)
+ debug_printf_eval("length: L.s:'%s'\n", L.s);
+ if (!op1) {
L.s = getvar_s(intvar[F0]);
+ debug_printf_eval("length: L.s='%s'\n", L.s);
+ }
+ else if (L.v->type & VF_ARRAY) {
+ R_d = L.v->x.array->nel;
+ debug_printf_eval("length: array_len:%d\n", L.v->x.array->nel);
+ break;
+ }
R_d = strlen(L.s);
break;
@@ -2905,7 +3002,7 @@ static var *evaluate(node *op, var *res)
case '%':
if (R_d == 0)
syntax_error(EMSG_DIV_BY_ZERO);
- L_d -= (int)(L_d / R_d) * R_d;
+ L_d -= (long long)(L_d / R_d) * R_d;
break;
}
debug_printf_eval("BINARY/REPLACE result:%f\n", L_d);
@@ -2992,7 +3089,7 @@ static int awk_exit(int r)
* otherwise return 0 */
static int is_assignment(const char *expr)
{
- char *exprc, *val, *s, *s1;
+ char *exprc, *val;
if (!isalnum_(*expr) || (val = strchr(expr, '=')) == NULL) {
return FALSE;
@@ -3002,10 +3099,7 @@ static int is_assignment(const char *expr)
val = exprc + (val - expr);
*val++ = '\0';
- s = s1 = val;
- while ((*s1 = nextchar(&s)) != '\0')
- s1++;
-
+ unescape_string_in_place(val);
setvar_u(newvar(exprc), val);
free(exprc);
return TRUE;
@@ -3056,6 +3150,9 @@ int awk_main(int argc, char **argv)
char *opt_F;
llist_t *list_v = NULL;
llist_t *list_f = NULL;
+#if ENABLE_FEATURE_AWK_GNU_EXTENSIONS
+ llist_t *list_e = NULL;
+#endif
int i, j;
var *v;
var tv;
@@ -3114,45 +3211,51 @@ int awk_main(int argc, char **argv)
*s1 = '=';
}
}
- opt_complementary = "v::f::"; /* -v and -f can occur multiple times */
- opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f, NULL);
+ opt_complementary = OPTCOMPLSTR_AWK;
+ opt = getopt32(argv, OPTSTR_AWK, &opt_F, &list_v, &list_f, IF_FEATURE_AWK_GNU_EXTENSIONS(&list_e,) NULL);
argv += optind;
argc -= optind;
- if (opt & 0x1)
- setvar_s(intvar[FS], opt_F); // -F
- while (list_v) { /* -v */
+ if (opt & OPT_W)
+ bb_error_msg("warning: option -W is ignored");
+ if (opt & OPT_F) {
+ unescape_string_in_place(opt_F);
+ setvar_s(intvar[FS], opt_F);
+ }
+ while (list_v) {
if (!is_assignment(llist_pop(&list_v)))
bb_show_usage();
}
- if (list_f) { /* -f */
- do {
- char *s = NULL;
- FILE *from_file;
-
- g_progname = llist_pop(&list_f);
- from_file = xfopen_stdin(g_progname);
- /* one byte is reserved for some trick in next_token */
- for (i = j = 1; j > 0; i += j) {
- s = xrealloc(s, i + 4096);
- j = fread(s + i, 1, 4094, from_file);
- }
- s[i] = '\0';
- fclose(from_file);
- parse_program(s + 1);
- free(s);
- } while (list_f);
- argc++;
- } else { // no -f: take program from 1st parameter
- if (!argc)
+ while (list_f) {
+ char *s = NULL;
+ FILE *from_file;
+
+ g_progname = llist_pop(&list_f);
+ from_file = xfopen_stdin(g_progname);
+ /* one byte is reserved for some trick in next_token */
+ for (i = j = 1; j > 0; i += j) {
+ s = xrealloc(s, i + 4096);
+ j = fread(s + i, 1, 4094, from_file);
+ }
+ s[i] = '\0';
+ fclose(from_file);
+ parse_program(s + 1);
+ free(s);
+ }
+ g_progname = "cmd. line";
+#if ENABLE_FEATURE_AWK_GNU_EXTENSIONS
+ while (list_e) {
+ parse_program(llist_pop(&list_e));
+ }
+#endif
+ if (!(opt & (OPT_f | OPT_e))) {
+ if (!*argv)
bb_show_usage();
- g_progname = "cmd. line";
parse_program(*argv++);
+ argc--;
}
- if (opt & 0x8) // -W
- bb_error_msg("warning: option -W is ignored");
/* fill in ARGV array */
- setvar_i(intvar[ARGC], argc);
+ setvar_i(intvar[ARGC], argc + 1);
setari_u(intvar[ARGV], 0, "awk");
i = 0;
while (*argv)
diff --git a/release/src/router/busybox/editors/cmp.c b/release/src/router/busybox/editors/cmp.c
index fbe6b97538..a4af6f4809 100644
--- a/release/src/router/busybox/editors/cmp.c
+++ b/release/src/router/busybox/editors/cmp.c
@@ -10,6 +10,17 @@
/* BB_AUDIT SUSv3 (virtually) compliant -- uses nicer GNU format for -l. */
/* http://www.opengroup.org/onlinepubs/007904975/utilities/cmp.html */
+//config:config CMP
+//config: bool "cmp"
+//config: default y
+//config: help
+//config: cmp is used to compare two files and returns the result
+//config: to standard output.
+
+//kbuild:lib-$(CONFIG_CMP) += cmp.o
+
+//applet:IF_CMP(APPLET(cmp, BB_DIR_USR_BIN, BB_SUID_DROP))
+
//usage:#define cmp_trivial_usage
//usage: "[-l] [-s] FILE1 [FILE2" IF_DESKTOP(" [SKIP1 [SKIP2]]") "]"
//usage:#define cmp_full_usage "\n\n"
diff --git a/release/src/router/busybox/editors/diff.c b/release/src/router/busybox/editors/diff.c
index 3a33346402..ff269360f6 100644
--- a/release/src/router/busybox/editors/diff.c
+++ b/release/src/router/busybox/editors/diff.c
@@ -76,6 +76,33 @@
* 6n words for files of length n.
*/
+//config:config DIFF
+//config: bool "diff"
+//config: default y
+//config: help
+//config: diff compares two files or directories and outputs the
+//config: differences between them in a form that can be given to
+//config: the patch command.
+//config:
+//config:config FEATURE_DIFF_LONG_OPTIONS
+//config: bool "Enable long options"
+//config: default y
+//config: depends on DIFF && LONG_OPTS
+//config: help
+//config: Enable use of long options.
+//config:
+//config:config FEATURE_DIFF_DIR
+//config: bool "Enable directory support"
+//config: default y
+//config: depends on DIFF
+//config: help
+//config: This option enables support for directory and subdirectory
+//config: comparison.
+
+//kbuild:lib-$(CONFIG_DIFF) += diff.o
+
+//applet:IF_DIFF(APPLET(diff, BB_DIR_USR_BIN, BB_SUID_DROP))
+
//usage:#define diff_trivial_usage
//usage: "[-abBdiNqrTstw] [-L LABEL] [-S FILE] [-U LINES] FILE1 FILE2"
//usage:#define diff_full_usage "\n\n"
@@ -98,6 +125,7 @@
//usage: "\n -w Ignore all whitespace"
#include "libbb.h"
+#include "common_bufsiz.h"
#if 0
# define dbg_error_msg(...) bb_error_msg(__VA_ARGS__)
@@ -336,7 +364,7 @@ static void stone(const int *a, int n, const int *b, int *J, int pref)
}
struct line {
- /* 'serial' is not used in the begining, so we reuse it
+ /* 'serial' is not used in the beginning, so we reuse it
* to store line offsets, thus reducing memory pressure
*/
union {
@@ -406,7 +434,7 @@ static void fetch(FILE_and_pos_t *ft, const off_t *ix, int a, int b, int ch)
for (j = 0, col = 0; j < ix[i] - ix[i - 1]; j++) {
int c = fgetc(ft->ft_fp);
if (c == EOF) {
- printf("\n\\ No newline at end of file\n");
+ puts("\n\\ No newline at end of file");
return;
}
ft->ft_pos++;
@@ -631,8 +659,8 @@ static bool diff(FILE* fp[2], char *file[2])
}
for (j = 0; j < 2; j++)
- for (k = v[j].a; k < v[j].b; k++)
- nonempty |= (ix[j][k+1] - ix[j][k] != 1);
+ for (k = v[j].a; k <= v[j].b; k++)
+ nonempty |= (ix[j][k] - ix[j][k - 1] != 1);
vec = xrealloc_vector(vec, 6, ++idx);
memcpy(vec[idx], v, sizeof(v));
@@ -665,7 +693,7 @@ static bool diff(FILE* fp[2], char *file[2])
continue;
printf(",%d", (a < b) ? b - a + 1 : 0);
}
- printf(" @@\n");
+ puts(" @@");
/*
* Output changes in "unified" diff format--the old and new lines
* are printed together.
@@ -713,13 +741,15 @@ static int diffreg(char *file[2])
unlink(name);
if (bb_copyfd_eof(fd, fd_tmp) < 0)
xfunc_die();
- if (fd) /* Prevents closing of stdin */
+ if (fd != STDIN_FILENO)
close(fd);
fd = fd_tmp;
+ xlseek(fd, 0, SEEK_SET);
}
fp[i] = fdopen(fd, "r");
}
+ setup_common_bufsiz();
while (1) {
const size_t sz = COMMON_BUFSIZE / 2;
char *const buf0 = bb_common_bufsiz1;
@@ -843,7 +873,7 @@ static void diffdir(char *p[2], const char *s_start)
* add_to_dirlist will remove it. */
list[i].len = strlen(p[i]);
recursive_action(p[i], ACTION_RECURSE | ACTION_FOLLOWLINKS,
- add_to_dirlist, skip_dir, &list[i], 0);
+ add_to_dirlist, skip_dir, &list[i], 0);
/* Sort dl alphabetically.
* GNU diff does this ignoring any number of trailing dots.
* We don't, so for us dotted files almost always are
diff --git a/release/src/router/busybox/editors/ed.c b/release/src/router/busybox/editors/ed.c
index dbb51306cc..c028b78cb8 100644
--- a/release/src/router/busybox/editors/ed.c
+++ b/release/src/router/busybox/editors/ed.c
@@ -7,10 +7,23 @@
* The "ed" built-in command (much simplified)
*/
+//config:config ED
+//config: bool "ed"
+//config: default y
+//config: help
+//config: The original 1970's Unix text editor, from the days of teletypes.
+//config: Small, simple, evil. Part of SUSv3. If you're not already using
+//config: this, you don't need it.
+
+//kbuild:lib-$(CONFIG_ED) += ed.o
+
+//applet:IF_ED(APPLET(ed, BB_DIR_BIN, BB_SUID_DROP))
+
//usage:#define ed_trivial_usage ""
//usage:#define ed_full_usage ""
#include "libbb.h"
+#include "common_bufsiz.h"
typedef struct LINE {
struct LINE *next;
@@ -23,8 +36,8 @@ typedef struct LINE {
#define searchString bb_common_bufsiz1
enum {
- USERSIZE = sizeof(searchString) > 1024 ? 1024
- : sizeof(searchString) - 1, /* max line length typed in by user */
+ USERSIZE = COMMON_BUFSIZE > 1024 ? 1024
+ : COMMON_BUFSIZE - 1, /* max line length typed in by user */
INITBUF_SIZE = 1024, /* initial buffer size */
};
@@ -54,6 +67,7 @@ struct globals {
#define lines (G.lines )
#define marks (G.marks )
#define INIT_G() do { \
+ setup_common_bufsiz(); \
SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
} while (0)
@@ -194,7 +208,7 @@ static void doCommands(void)
if (fileName)
printf("\"%s\"\n", fileName);
else
- printf("No file name\n");
+ puts("No file name");
break;
}
free(fileName);
@@ -720,7 +734,6 @@ static int readLines(const char *file, int num)
cc = safe_read(fd, bufPtr, bufSize - bufUsed);
bufUsed += cc;
bufPtr = bufBase;
-
} while (cc > 0);
if (cc < 0) {
diff --git a/release/src/router/busybox/editors/patch.c b/release/src/router/busybox/editors/patch.c
index 13785ef460..988021d776 100644
--- a/release/src/router/busybox/editors/patch.c
+++ b/release/src/router/busybox/editors/patch.c
@@ -345,6 +345,8 @@ done:
// state 1: Found +++ file indicator, look for @@
// state 2: In hunk: counting initial context lines
// state 3: In hunk: getting body
+// Like GNU patch, we don't require a --- line before the +++, and
+// also allow the --- after the +++ line.
int patch_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int patch_main(int argc UNUSED_PARAM, char **argv)
@@ -370,10 +372,6 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
xmove_fd(xopen_stdin(argv[1]), STDIN_FILENO);
}
}
- if (argv[0]) {
- oldname = xstrdup(argv[0]);
- newname = xstrdup(argv[0]);
- }
// Loop through the lines in the patch
for(;;) {
@@ -412,7 +410,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
}
// Open a new file?
- if (!strncmp("--- ", patchline, 4) || !strncmp("+++ ", patchline, 4)) {
+ if (is_prefixed_with(patchline, "--- ") || is_prefixed_with(patchline, "+++ ")) {
char *s, **name = reverse ? &newname : &oldname;
int i;
@@ -444,7 +442,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
// Start a new hunk? Usually @@ -oldline,oldlen +newline,newlen @@
// but a missing ,value means the value is 1.
- } else if (state == 1 && !strncmp("@@ -", patchline, 4)) {
+ } else if (state == 1 && is_prefixed_with(patchline, "@@ -")) {
int i;
char *s = patchline+4;
@@ -462,6 +460,14 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
TT.context = 0;
state = 2;
+ // If the --- line is missing or malformed, either oldname
+ // or (for -R) newname could be NULL -- but not both. Like
+ // GNU patch, proceed based on the +++ line, and avoid SEGVs.
+ if (!oldname)
+ oldname = xstrdup("MISSING_FILENAME");
+ if (!newname)
+ newname = xstrdup("MISSING_FILENAME");
+
// If this is the first hunk, open the file.
if (TT.filein == -1) {
int oldsum, newsum, empty = 0;
@@ -476,10 +482,10 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
// or if new hunk is empty (zero context) after patching
if (!strcmp(name, "/dev/null") || !(reverse ? oldsum : newsum)) {
name = reverse ? newname : oldname;
- empty++;
+ empty = 1;
}
- // handle -p path truncation.
+ // Handle -p path truncation.
for (i = 0, s = name; *s;) {
if ((option_mask32 & FLAG_PATHLEN) && TT.prefix == i)
break;
@@ -490,6 +496,9 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
i++;
name = s;
}
+ // If "patch FILE_TO_PATCH", completely ignore name from patch
+ if (argv[0])
+ name = argv[0];
if (empty) {
// File is empty after the patches have been applied
diff --git a/release/src/router/busybox/editors/patch_bbox.c b/release/src/router/busybox/editors/patch_bbox.c
index 78aa5fde8a..aae7b79878 100644
--- a/release/src/router/busybox/editors/patch_bbox.c
+++ b/release/src/router/busybox/editors/patch_bbox.c
@@ -188,8 +188,8 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
unsigned src_last_line = 1;
unsigned dst_last_line = 1;
- if ((sscanf(patch_line, "@@ -%d,%d +%d,%d", &src_beg_line, &src_last_line, &dst_beg_line, &dst_last_line) < 3)
- && (sscanf(patch_line, "@@ -%d +%d,%d", &src_beg_line, &dst_beg_line, &dst_last_line) < 2)
+ if ((sscanf(patch_line, "@@ -%u,%u +%u,%u", &src_beg_line, &src_last_line, &dst_beg_line, &dst_last_line) < 3)
+ && (sscanf(patch_line, "@@ -%u +%u,%u", &src_beg_line, &dst_beg_line, &dst_last_line) < 2)
) {
/* No more hunks for this file */
break;
diff --git a/release/src/router/busybox/editors/sed.c b/release/src/router/busybox/editors/sed.c
index 9e8e1b494d..f37c37d88c 100644
--- a/release/src/router/busybox/editors/sed.c
+++ b/release/src/router/busybox/editors/sed.c
@@ -23,9 +23,6 @@
* resulting sed_cmd_t structures are appended to a linked list
* (G.sed_cmd_head/G.sed_cmd_tail).
*
- * add_input_file() adds a FILE* to the list of input files. We need to
- * know all input sources ahead of time to find the last line for the $ match.
- *
* process_files() does actual sedding, reading data lines from each input FILE*
* (which could be stdin) and applying the sed command list (sed_cmd_head) to
* each of the resulting lines.
@@ -53,18 +50,33 @@
* Todo:
* - Create a wrapper around regex to make libc's regex conform with sed
*
- * Reference http://www.opengroup.org/onlinepubs/007904975/utilities/sed.html
+ * Reference
+ * http://www.opengroup.org/onlinepubs/007904975/utilities/sed.html
+ * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sed.html
+ * http://sed.sourceforge.net/sedfaq3.html
*/
+//config:config SED
+//config: bool "sed"
+//config: default y
+//config: help
+//config: sed is used to perform text transformations on a file
+//config: or input from a pipeline.
+
+//kbuild:lib-$(CONFIG_SED) += sed.o
+
+//applet:IF_SED(APPLET(sed, BB_DIR_BIN, BB_SUID_DROP))
+
//usage:#define sed_trivial_usage
-//usage: "[-inr] [-f FILE]... [-e CMD]... [FILE]...\n"
-//usage: "or: sed [-inr] CMD [FILE]..."
+//usage: "[-inrE] [-f FILE]... [-e CMD]... [FILE]...\n"
+//usage: "or: sed [-inrE] CMD [FILE]..."
//usage:#define sed_full_usage "\n\n"
//usage: " -e CMD Add CMD to sed commands to be executed"
//usage: "\n -f FILE Add FILE contents to sed commands to be executed"
-//usage: "\n -i Edit files in-place (else sends result to stdout)"
+//usage: "\n -i[SFX] Edit files in-place (otherwise sends to stdout)"
+//usage: "\n Optionally back files up, appending SFX"
//usage: "\n -n Suppress automatic printing of pattern space"
-//usage: "\n -r Use extended regex syntax"
+//usage: "\n -r,-E Use extended regex syntax"
//usage: "\n"
//usage: "\nIf no -e or -f, the first non-option argument is the sed command string."
//usage: "\nRemaining arguments are input files (stdin if none)."
@@ -74,6 +86,7 @@
//usage: "bar\n"
#include "libbb.h"
+#include "common_bufsiz.h"
#include "xregex.h"
#if 0
@@ -98,9 +111,10 @@ typedef struct sed_cmd_s {
regex_t *sub_match; /* For 's/sub_match/string/' */
int beg_line; /* 'sed 1p' 0 == apply commands to all lines */
int beg_line_orig; /* copy of the above, needed for -i */
- int end_line; /* 'sed 1,3p' 0 == one line only. -1 = last line ($) */
+ int end_line; /* 'sed 1,3p' 0 == one line only. -1 = last line ($). -2-N = +N */
+ int end_line_orig;
- FILE *sw_file; /* File (sw) command writes to, -1 for none. */
+ FILE *sw_file; /* File (sw) command writes to, NULL for none. */
char *string; /* Data string for (saicytb) commands. */
unsigned which_match; /* (s) Which match to replace (0 for all) */
@@ -121,12 +135,15 @@ static const char semicolon_whitespace[] ALIGN1 = "; \n\r\t\v";
struct globals {
/* options */
int be_quiet, regex_type;
+
FILE *nonstdout;
char *outname, *hold_space;
+ smallint exitcode;
- /* List of input files */
- int input_file_count, current_input_file;
- FILE **input_file_list;
+ /* list of input files */
+ int current_input_file, last_input_file;
+ char **input_file_list;
+ FILE *current_fp;
regmatch_t regmatch[10];
regex_t *previous_regex_ptr;
@@ -134,7 +151,7 @@ struct globals {
/* linked list of sed commands */
sed_cmd_t *sed_cmd_head, **sed_cmd_tail;
- /* Linked list of append lines */
+ /* linked list of append lines */
llist_t *append_head;
char *add_cmd_line;
@@ -145,11 +162,10 @@ struct globals {
int len; /* Space allocated */
} pipeline;
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
-struct BUG_G_too_big {
- char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
-};
+#define G (*(struct globals*)bb_common_bufsiz1)
#define INIT_G() do { \
+ setup_common_bufsiz(); \
+ BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
G.sed_cmd_tail = &G.sed_cmd_head; \
} while (0)
@@ -165,7 +181,7 @@ static void sed_free_and_close_stuff(void)
sed_cmd_t *sed_cmd_next = sed_cmd->next;
if (sed_cmd->sw_file)
- xprint_and_close_file(sed_cmd->sw_file);
+ fclose(sed_cmd->sw_file);
if (sed_cmd->beg_match) {
regfree(sed_cmd->beg_match);
@@ -186,8 +202,8 @@ static void sed_free_and_close_stuff(void)
free(G.hold_space);
- while (G.current_input_file < G.input_file_count)
- fclose(G.input_file_list[G.current_input_file++]);
+ if (G.current_fp)
+ fclose(G.current_fp);
}
#else
void sed_free_and_close_stuff(void);
@@ -202,23 +218,33 @@ static void cleanup_outname(void)
/* strcpy, replacing "\from" with 'to'. If to is NUL, replacing "\any" with 'any' */
-static void parse_escapes(char *dest, const char *string, int len, char from, char to)
+static unsigned parse_escapes(char *dest, const char *string, int len, char from, char to)
{
+ char *d = dest;
int i = 0;
+ if (len == -1)
+ len = strlen(string);
+
while (i < len) {
if (string[i] == '\\') {
if (!to || string[i+1] == from) {
- *dest++ = to ? to : string[i+1];
+ if ((*d = to ? to : string[i+1]) == '\0')
+ return d - dest;
i += 2;
+ d++;
continue;
}
- *dest++ = string[i++];
+ i++; /* skip backslash in string[] */
+ *d++ = '\\';
+ /* fall through: copy next char verbatim */
}
- /* TODO: is it safe wrt a string with trailing '\\' ? */
- *dest++ = string[i++];
+ if ((*d = string[i++]) == '\0')
+ return d - dest;
+ d++;
}
- *dest = '\0';
+ *d = '\0';
+ return d - dest;
}
static char *copy_parsing_escapes(const char *string, int len)
@@ -229,9 +255,8 @@ static char *copy_parsing_escapes(const char *string, int len)
/* sed recognizes \n */
/* GNU sed also recognizes \t and \r */
for (s = "\nn\tt\rr"; *s; s += 2) {
- parse_escapes(dest, string, len, s[1], s[0]);
+ len = parse_escapes(dest, string, len, s[1], s[0]);
string = dest;
- len = strlen(dest);
}
return dest;
}
@@ -327,7 +352,7 @@ static int get_address(const char *my_str, int *linenum, regex_t ** regex)
next = index_of_next_unescaped_regexp_delim(delimiter, ++pos);
temp = copy_parsing_escapes(pos, next);
*regex = xzalloc(sizeof(regex_t));
- xregcomp(*regex, temp, G.regex_type|REG_NEWLINE);
+ xregcomp(*regex, temp, G.regex_type);
free(temp);
/* Move position to next character after last delimiter */
pos += (next+1);
@@ -367,7 +392,7 @@ static int parse_subst_cmd(sed_cmd_t *sed_cmd, const char *substr)
/*
* A substitution command should look something like this:
- * s/match/replace/ #gIpw
+ * s/match/replace/ #giIpw
* || | |||
* mandatory optional
*/
@@ -381,7 +406,9 @@ static int parse_subst_cmd(sed_cmd_t *sed_cmd, const char *substr)
/* process the flags */
sed_cmd->which_match = 1;
+ dbg("s flags:'%s'", substr + idx + 1);
while (substr[++idx]) {
+ dbg("s flag:'%c'", substr[idx]);
/* Parse match number */
if (isdigit(substr[idx])) {
if (match[0] != '^') {
@@ -389,7 +416,7 @@ static int parse_subst_cmd(sed_cmd_t *sed_cmd, const char *substr)
const char *pos = substr + idx;
/* FIXME: error check? */
sed_cmd->which_match = (unsigned)strtol(substr+idx, (char**) &pos, 10);
- idx = pos - substr;
+ idx = pos - substr - 1;
}
continue;
}
@@ -410,11 +437,15 @@ static int parse_subst_cmd(sed_cmd_t *sed_cmd, const char *substr)
/* Write to file */
case 'w':
{
- char *temp;
- idx += parse_file_cmd(/*sed_cmd,*/ substr+idx, &temp);
+ char *fname;
+ idx += parse_file_cmd(/*sed_cmd,*/ substr+idx+1, &fname);
+ sed_cmd->sw_file = xfopen_for_write(fname);
+ sed_cmd->sw_last_char = '\n';
+ free(fname);
break;
}
/* Ignore case (gnu exension) */
+ case 'i':
case 'I':
cflags |= REG_ICASE;
break;
@@ -428,6 +459,7 @@ static int parse_subst_cmd(sed_cmd_t *sed_cmd, const char *substr)
case '}':
goto out;
default:
+ dbg("s bad flags:'%s'", substr + idx);
bb_error_msg_and_die("bad option in substitution expression");
}
}
@@ -450,7 +482,7 @@ static int parse_subst_cmd(sed_cmd_t *sed_cmd, const char *substr)
*/
static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr)
{
- static const char cmd_letters[] = "saicrw:btTydDgGhHlnNpPqx={}";
+ static const char cmd_letters[] ALIGN1 = "saicrw:btTydDgGhHlnNpPqx={}";
enum {
IDX_s = 0,
IDX_a,
@@ -481,9 +513,11 @@ static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr)
IDX_rbrace,
IDX_nul
};
- struct chk { char chk[sizeof(cmd_letters)-1 == IDX_nul ? 1 : -1]; };
+ unsigned idx;
+
+ BUILD_BUG_ON(sizeof(cmd_letters)-1 != IDX_nul);
- unsigned idx = strchrnul(cmd_letters, sed_cmd->cmd) - cmd_letters;
+ idx = strchrnul(cmd_letters, sed_cmd->cmd) - cmd_letters;
/* handle (s)ubstitution command */
if (idx == IDX_s) {
@@ -491,8 +525,12 @@ static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr)
}
/* handle edit cmds: (a)ppend, (i)nsert, and (c)hange */
else if (idx <= IDX_c) { /* a,i,c */
- if ((sed_cmd->end_line || sed_cmd->end_match) && sed_cmd->cmd != 'c')
- bb_error_msg_and_die("only a beginning address can be specified for edit commands");
+ unsigned len;
+
+ if (idx < IDX_c) { /* a,i */
+ if (sed_cmd->end_line || sed_cmd->end_match)
+ bb_error_msg_and_die("command '%c' uses only one address", sed_cmd->cmd);
+ }
for (;;) {
if (*cmdstr == '\n' || *cmdstr == '\\') {
cmdstr++;
@@ -502,15 +540,18 @@ static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr)
break;
cmdstr++;
}
- sed_cmd->string = xstrdup(cmdstr);
+ len = strlen(cmdstr);
+ sed_cmd->string = copy_parsing_escapes(cmdstr, len);
+ cmdstr += len;
/* "\anychar" -> "anychar" */
- parse_escapes(sed_cmd->string, sed_cmd->string, strlen(cmdstr), '\0', '\0');
- cmdstr += strlen(cmdstr);
+ parse_escapes(sed_cmd->string, sed_cmd->string, -1, '\0', '\0');
}
/* handle file cmds: (r)ead */
else if (idx <= IDX_w) { /* r,w */
- if (sed_cmd->end_line || sed_cmd->end_match)
- bb_error_msg_and_die("command only uses one address");
+ if (idx < IDX_w) { /* r */
+ if (sed_cmd->end_line || sed_cmd->end_match)
+ bb_error_msg_and_die("command '%c' uses only one address", sed_cmd->cmd);
+ }
cmdstr += parse_file_cmd(/*sed_cmd,*/ cmdstr, &sed_cmd->string);
if (sed_cmd->cmd == 'w') {
sed_cmd->sw_file = xfopen_for_write(sed_cmd->string);
@@ -535,8 +576,8 @@ static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr)
cmdstr += parse_regex_delim(cmdstr, &match, &replace)+1;
/* \n already parsed, but \delimiter needs unescaping. */
- parse_escapes(match, match, strlen(match), i, i);
- parse_escapes(replace, replace, strlen(replace), i, i);
+ parse_escapes(match, match, -1, i, i);
+ parse_escapes(replace, replace, -1, i, i);
sed_cmd->string = xzalloc((strlen(match) + 1) * 2);
for (i = 0; match[i] && replace[i]; i++) {
@@ -618,10 +659,29 @@ static void add_cmd(const char *cmdstr)
int idx;
cmdstr++;
- idx = get_address(cmdstr, &sed_cmd->end_line, &sed_cmd->end_match);
- if (!idx)
+ if (*cmdstr == '+' && isdigit(cmdstr[1])) {
+ /* http://sed.sourceforge.net/sedfaq3.html#s3.3
+ * Under GNU sed 3.02+, ssed, and sed15+, <address2>
+ * may also be a notation of the form +num,
+ * indicating the next num lines after <address1> is
+ * matched.
+ * GNU sed 4.2.1 accepts even "+" (meaning "+0").
+ * We don't (we check for isdigit, see above), think
+ * about the "+-3" case.
+ */
+ char *end;
+ /* code is smaller compared to using &cmdstr here: */
+ idx = strtol(cmdstr+1, &end, 10);
+ sed_cmd->end_line = -2 - idx;
+ cmdstr = end;
+ } else {
+ idx = get_address(cmdstr, &sed_cmd->end_line, &sed_cmd->end_match);
+ cmdstr += idx;
+ idx--; /* if 0, trigger error check below */
+ }
+ if (idx < 0)
bb_error_msg_and_die("no address after comma");
- cmdstr += idx;
+ sed_cmd->end_line_orig = sed_cmd->end_line;
}
/* skip whitespace before the command */
@@ -642,6 +702,12 @@ static void add_cmd(const char *cmdstr)
sed_cmd->cmd = *cmdstr++;
cmdstr = parse_cmd_args(sed_cmd, cmdstr);
+ /* cmdstr now points past args.
+ * GNU sed requires a separator, if there are more commands,
+ * else it complains "char N: extra characters after command".
+ * Example: "sed 'p;d'". We also allow "sed 'pd'".
+ */
+
/* Add the command to the command array */
*G.sed_cmd_tail = sed_cmd;
G.sed_cmd_tail = &sed_cmd->next;
@@ -835,46 +901,109 @@ static sed_cmd_t *branch_to(char *label)
static void append(char *s)
{
- llist_add_to_end(&G.append_head, xstrdup(s));
+ llist_add_to_end(&G.append_head, s);
}
-static void flush_append(void)
+/* Output line of text. */
+/* Note:
+ * The tricks with NO_EOL_CHAR and last_puts_char are there to emulate gnu sed.
+ * Without them, we had this:
+ * echo -n thingy >z1
+ * echo -n again >z2
+ * >znull
+ * sed "s/i/z/" z1 z2 znull | hexdump -vC
+ * output:
+ * gnu sed 4.1.5:
+ * 00000000 74 68 7a 6e 67 79 0a 61 67 61 7a 6e |thzngy.agazn|
+ * bbox:
+ * 00000000 74 68 7a 6e 67 79 61 67 61 7a 6e |thzngyagazn|
+ */
+enum {
+ NO_EOL_CHAR = 1,
+ LAST_IS_NUL = 2,
+};
+static void puts_maybe_newline(char *s, FILE *file, char *last_puts_char, char last_gets_char)
{
- char *data;
+ char lpc = *last_puts_char;
- /* Output appended lines. */
- while ((data = (char *)llist_pop(&G.append_head))) {
- fprintf(G.nonstdout, "%s\n", data);
- free(data);
+ /* Need to insert a '\n' between two files because first file's
+ * last line wasn't terminated? */
+ if (lpc != '\n' && lpc != '\0') {
+ fputc('\n', file);
+ lpc = '\n';
}
+ fputs(s, file);
+
+ /* 'x' - just something which is not '\n', '\0' or NO_EOL_CHAR */
+ if (s[0])
+ lpc = 'x';
+
+ /* had trailing '\0' and it was last char of file? */
+ if (last_gets_char == LAST_IS_NUL) {
+ fputc('\0', file);
+ lpc = 'x'; /* */
+ } else
+ /* had trailing '\n' or '\0'? */
+ if (last_gets_char != NO_EOL_CHAR) {
+ fputc(last_gets_char, file);
+ lpc = last_gets_char;
+ }
+
+ if (ferror(file)) {
+ xfunc_error_retval = 4; /* It's what gnu sed exits with... */
+ bb_error_msg_and_die(bb_msg_write_error);
+ }
+ *last_puts_char = lpc;
}
-static void add_input_file(FILE *file)
+static void flush_append(char *last_puts_char)
{
- G.input_file_list = xrealloc_vector(G.input_file_list, 2, G.input_file_count);
- G.input_file_list[G.input_file_count++] = file;
+ char *data;
+
+ /* Output appended lines. */
+ while ((data = (char *)llist_pop(&G.append_head)) != NULL) {
+ /* Append command does not respect "nonterminated-ness"
+ * of last line. Try this:
+ * $ echo -n "woot" | sed -e '/woot/a woo' -
+ * woot
+ * woo
+ * (both lines are terminated with \n)
+ * Therefore we do not propagate "last_gets_char" here,
+ * pass '\n' instead:
+ */
+ puts_maybe_newline(data, G.nonstdout, last_puts_char, '\n');
+ free(data);
+ }
}
/* Get next line of input from G.input_file_list, flushing append buffer and
* noting if we ran out of files without a newline on the last line we read.
*/
-enum {
- NO_EOL_CHAR = 1,
- LAST_IS_NUL = 2,
-};
-static char *get_next_line(char *gets_char)
+static char *get_next_line(char *gets_char, char *last_puts_char)
{
char *temp = NULL;
int len;
char gc;
- flush_append();
+ flush_append(last_puts_char);
/* will be returned if last line in the file
* doesn't end with either '\n' or '\0' */
gc = NO_EOL_CHAR;
- while (G.current_input_file < G.input_file_count) {
- FILE *fp = G.input_file_list[G.current_input_file];
+ for (; G.current_input_file <= G.last_input_file; G.current_input_file++) {
+ FILE *fp = G.current_fp;
+ if (!fp) {
+ const char *path = G.input_file_list[G.current_input_file];
+ fp = stdin;
+ if (path != bb_msg_standard_input) {
+ fp = fopen_or_warn(path, "r");
+ if (!fp) {
+ G.exitcode = EXIT_FAILURE;
+ continue;
+ }
+ }
+ G.current_fp = fp;
+ }
/* Read line up to a newline or NUL byte, inclusive,
* return malloc'ed char[]. length of the chunk read
* is stored in len. NULL if EOF/error */
@@ -905,61 +1034,13 @@ static char *get_next_line(char *gets_char)
* (note: *no* newline after "b bang"!) */
}
/* Close this file and advance to next one */
- fclose(fp);
- G.current_input_file++;
+ fclose_if_not_stdin(fp);
+ G.current_fp = NULL;
}
*gets_char = gc;
return temp;
}
-/* Output line of text. */
-/* Note:
- * The tricks with NO_EOL_CHAR and last_puts_char are there to emulate gnu sed.
- * Without them, we had this:
- * echo -n thingy >z1
- * echo -n again >z2
- * >znull
- * sed "s/i/z/" z1 z2 znull | hexdump -vC
- * output:
- * gnu sed 4.1.5:
- * 00000000 74 68 7a 6e 67 79 0a 61 67 61 7a 6e |thzngy.agazn|
- * bbox:
- * 00000000 74 68 7a 6e 67 79 61 67 61 7a 6e |thzngyagazn|
- */
-static void puts_maybe_newline(char *s, FILE *file, char *last_puts_char, char last_gets_char)
-{
- char lpc = *last_puts_char;
-
- /* Need to insert a '\n' between two files because first file's
- * last line wasn't terminated? */
- if (lpc != '\n' && lpc != '\0') {
- fputc('\n', file);
- lpc = '\n';
- }
- fputs(s, file);
-
- /* 'x' - just something which is not '\n', '\0' or NO_EOL_CHAR */
- if (s[0])
- lpc = 'x';
-
- /* had trailing '\0' and it was last char of file? */
- if (last_gets_char == LAST_IS_NUL) {
- fputc('\0', file);
- lpc = 'x'; /* */
- } else
- /* had trailing '\n' or '\0'? */
- if (last_gets_char != NO_EOL_CHAR) {
- fputc(last_gets_char, file);
- lpc = last_gets_char;
- }
-
- if (ferror(file)) {
- xfunc_error_retval = 4; /* It's what gnu sed exits with... */
- bb_error_msg_and_die(bb_msg_write_error);
- }
- *last_puts_char = lpc;
-}
-
#define sed_puts(s, n) (puts_maybe_newline(s, G.nonstdout, &last_puts_char, n))
static int beg_match(sed_cmd_t *sed_cmd, const char *pattern_space)
@@ -982,7 +1063,7 @@ static void process_files(void)
int substituted;
/* Prime the pump */
- next_line = get_next_line(&next_gets_char);
+ next_line = get_next_line(&next_gets_char, &last_puts_char);
/* Go through every line in each file */
again:
@@ -996,7 +1077,7 @@ static void process_files(void)
/* Read one line in advance so we can act on the last line,
* the '$' address */
- next_line = get_next_line(&next_gets_char);
+ next_line = get_next_line(&next_gets_char, &last_puts_char);
linenum++;
/* For every line, go through all the commands */
@@ -1055,10 +1136,19 @@ static void process_files(void)
/* Is this line the end of the current match? */
if (matched) {
+ if (sed_cmd->end_line <= -2) {
+ /* address2 is +N, i.e. N lines from beg_line */
+ sed_cmd->end_line = linenum + (-sed_cmd->end_line - 2);
+ }
/* once matched, "n,xxx" range is dead, disabling it */
if (sed_cmd->beg_line > 0) {
sed_cmd->beg_line = -2;
}
+ dbg("end1:%d", sed_cmd->end_line ? sed_cmd->end_line == -1
+ ? !next_line : (sed_cmd->end_line <= linenum)
+ : !sed_cmd->end_match);
+ dbg("end2:%d", sed_cmd->end_match && old_matched
+ && !regexec(sed_cmd->end_match,pattern_space, 0, NULL, 0));
sed_cmd->in_match = !(
/* has the ending line come, or is this a single address command? */
(sed_cmd->end_line
@@ -1070,7 +1160,7 @@ static void process_files(void)
/* or does this line matches our last address regex */
|| (sed_cmd->end_match && old_matched
&& (regexec(sed_cmd->end_match,
- pattern_space, 0, NULL, 0) == 0)
+ pattern_space, 0, NULL, 0) == 0)
)
);
}
@@ -1168,7 +1258,7 @@ static void process_files(void)
/* Append line to linked list to be printed later */
case 'a':
- append(sed_cmd->string);
+ append(xstrdup(sed_cmd->string));
break;
/* Insert text before this line */
@@ -1190,11 +1280,10 @@ static void process_files(void)
rfile = fopen_for_read(sed_cmd->string);
if (rfile) {
char *line;
-
while ((line = xmalloc_fgetline(rfile))
!= NULL)
append(line);
- xprint_and_close_file(rfile);
+ fclose(rfile);
}
break;
@@ -1215,7 +1304,7 @@ static void process_files(void)
free(pattern_space);
pattern_space = next_line;
last_gets_char = next_gets_char;
- next_line = get_next_line(&next_gets_char);
+ next_line = get_next_line(&next_gets_char, &last_puts_char);
substituted = 0;
linenum++;
break;
@@ -1251,7 +1340,7 @@ static void process_files(void)
pattern_space[len] = '\n';
strcpy(pattern_space + len+1, next_line);
last_gets_char = next_gets_char;
- next_line = get_next_line(&next_gets_char);
+ next_line = get_next_line(&next_gets_char, &last_puts_char);
linenum++;
break;
}
@@ -1355,7 +1444,7 @@ static void process_files(void)
/* Delete and such jump here. */
discard_line:
- flush_append();
+ flush_append(&last_puts_char /*,last_gets_char*/);
free(pattern_space);
goto again;
@@ -1364,7 +1453,7 @@ static void process_files(void)
/* It is possible to have a command line argument with embedded
* newlines. This counts as multiple command lines.
* However, newline can be escaped: 's/e/z\<newline>z/'
- * We check for this.
+ * add_cmd() handles this.
*/
static void add_cmd_block(char *cmdstr)
@@ -1374,22 +1463,8 @@ static void add_cmd_block(char *cmdstr)
cmdstr = sv = xstrdup(cmdstr);
do {
eol = strchr(cmdstr, '\n');
- next:
- if (eol) {
- /* Count preceding slashes */
- int slashes = 0;
- char *sl = eol;
-
- while (sl != cmdstr && *--sl == '\\')
- slashes++;
- /* Odd number of preceding slashes - newline is escaped */
- if (slashes & 1) {
- overlapping_strcpy(eol - 1, eol);
- eol = strchr(eol, '\n');
- goto next;
- }
+ if (eol)
*eol = '\0';
- }
add_cmd(cmdstr);
cmdstr = eol + 1;
} while (eol);
@@ -1401,7 +1476,18 @@ int sed_main(int argc UNUSED_PARAM, char **argv)
{
unsigned opt;
llist_t *opt_e, *opt_f;
- int status = EXIT_SUCCESS;
+ char *opt_i;
+
+#if ENABLE_LONG_OPTS
+ static const char sed_longopts[] ALIGN1 =
+ /* name has_arg short */
+ "in-place\0" Optional_argument "i"
+ "regexp-extended\0" No_argument "r"
+ "quiet\0" No_argument "n"
+ "silent\0" No_argument "n"
+ "expression\0" Required_argument "e"
+ "file\0" Required_argument "f";
+#endif
INIT_G();
@@ -1409,40 +1495,50 @@ int sed_main(int argc UNUSED_PARAM, char **argv)
if (ENABLE_FEATURE_CLEAN_UP) atexit(sed_free_and_close_stuff);
/* Lie to autoconf when it starts asking stupid questions. */
- if (argv[1] && !strcmp(argv[1], "--version")) {
+ if (argv[1] && strcmp(argv[1], "--version") == 0) {
puts("This is not GNU sed version 4.0");
return 0;
}
/* do normal option parsing */
opt_e = opt_f = NULL;
+ opt_i = NULL;
opt_complementary = "e::f::" /* can occur multiple times */
"nn"; /* count -n */
+
+ IF_LONG_OPTS(applet_long_options = sed_longopts);
+
/* -i must be first, to match OPT_in_place definition */
- opt = getopt32(argv, "irne:f:", &opt_e, &opt_f,
+ /* -E is a synonym of -r:
+ * GNU sed 4.2.1 mentions it in neither --help
+ * nor manpage, but does recognize it.
+ */
+ opt = getopt32(argv, "i::rEne:f:", &opt_i, &opt_e, &opt_f,
&G.be_quiet); /* counter for -n */
//argc -= optind;
argv += optind;
if (opt & OPT_in_place) { // -i
atexit(cleanup_outname);
}
- if (opt & 0x2) G.regex_type |= REG_EXTENDED; // -r
- //if (opt & 0x4) G.be_quiet++; // -n
+ if (opt & (2|4))
+ G.regex_type |= REG_EXTENDED; // -r or -E
+ //if (opt & 8)
+ // G.be_quiet++; // -n (implemented with a counter instead)
while (opt_e) { // -e
add_cmd_block(llist_pop(&opt_e));
}
while (opt_f) { // -f
char *line;
FILE *cmdfile;
- cmdfile = xfopen_for_read(llist_pop(&opt_f));
+ cmdfile = xfopen_stdin(llist_pop(&opt_f));
while ((line = xmalloc_fgetline(cmdfile)) != NULL) {
add_cmd(line);
free(line);
}
- fclose(cmdfile);
+ fclose_if_not_stdin(cmdfile);
}
/* if we didn't get a pattern from -e or -f, use argv[0] */
- if (!(opt & 0x18)) {
+ if (!(opt & 0x30)) {
if (!*argv)
bb_show_usage();
add_cmd_block(*argv++);
@@ -1456,42 +1552,42 @@ int sed_main(int argc UNUSED_PARAM, char **argv)
/* argv[0..(argc-1)] should be names of file to process. If no
* files were specified or '-' was specified, take input from stdin.
* Otherwise, we process all the files specified. */
- if (argv[0] == NULL) {
+ G.input_file_list = argv;
+ if (!argv[0]) {
if (opt & OPT_in_place)
bb_error_msg_and_die(bb_msg_requires_arg, "-i");
- add_input_file(stdin);
+ argv[0] = (char*)bb_msg_standard_input;
+ /* G.last_input_file = 0; - already is */
} else {
- int i;
+ goto start;
- for (i = 0; argv[i]; i++) {
+ for (; *argv; argv++) {
struct stat statbuf;
int nonstdoutfd;
- FILE *file;
sed_cmd_t *sed_cmd;
- if (LONE_DASH(argv[i]) && !(opt & OPT_in_place)) {
- add_input_file(stdin);
- process_files();
- continue;
- }
- file = fopen_or_warn(argv[i], "r");
- if (!file) {
- status = EXIT_FAILURE;
- continue;
- }
- add_input_file(file);
+ G.last_input_file++;
+ start:
if (!(opt & OPT_in_place)) {
+ if (LONE_DASH(*argv)) {
+ *argv = (char*)bb_msg_standard_input;
+ process_files();
+ }
continue;
}
/* -i: process each FILE separately: */
- G.outname = xasprintf("%sXXXXXX", argv[i]);
+ if (stat(*argv, &statbuf) != 0) {
+ bb_simple_perror_msg(*argv);
+ G.exitcode = EXIT_FAILURE;
+ G.current_input_file++;
+ continue;
+ }
+ G.outname = xasprintf("%sXXXXXX", *argv);
nonstdoutfd = xmkstemp(G.outname);
G.nonstdout = xfdopen_for_write(nonstdoutfd);
-
/* Set permissions/owner of output file */
- fstat(fileno(file), &statbuf);
/* chmod'ing AFTER chown would preserve suid/sgid bits,
* but GNU sed 4.2.1 does not preserve them either */
fchmod(nonstdoutfd, statbuf.st_mode);
@@ -1501,23 +1597,30 @@ int sed_main(int argc UNUSED_PARAM, char **argv)
fclose(G.nonstdout);
G.nonstdout = stdout;
- /* unlink(argv[i]); */
- xrename(G.outname, argv[i]);
+ if (opt_i) {
+ char *backupname = xasprintf("%s%s", *argv, opt_i);
+ xrename(*argv, backupname);
+ free(backupname);
+ }
+ /* else unlink(*argv); - rename below does this */
+ xrename(G.outname, *argv); //TODO: rollback backup on error?
free(G.outname);
G.outname = NULL;
- /* Re-enable disabled range matches */
+ /* Fix disabled range matches and mangled ",+N" ranges */
for (sed_cmd = G.sed_cmd_head; sed_cmd; sed_cmd = sed_cmd->next) {
sed_cmd->beg_line = sed_cmd->beg_line_orig;
+ sed_cmd->end_line = sed_cmd->end_line_orig;
}
}
/* Here, to handle "sed 'cmds' nonexistent_file" case we did:
- * if (G.current_input_file >= G.input_file_count)
- * return status;
+ * if (G.current_input_file[G.current_input_file] == NULL)
+ * return G.exitcode;
* but it's not needed since process_files() works correctly
* in this case too. */
}
+
process_files();
- return status;
+ return G.exitcode;
}
diff --git a/release/src/router/busybox/editors/vi.c b/release/src/router/busybox/editors/vi.c
index 0dd8bd1ab9..974f9978b9 100644
--- a/release/src/router/busybox/editors/vi.c
+++ b/release/src/router/busybox/editors/vi.c
@@ -14,10 +14,9 @@
* add :help command
* :map macros
* if mark[] values were line numbers rather than pointers
- * it would be easier to change the mark when add/delete lines
+ * it would be easier to change the mark when add/delete lines
* More intelligence in refresh()
* ":r !cmd" and "!cmd" to filter text through an external command
- * A true "undo" facility
* An "ex" line oriented mode- maybe using "cmdedit"
*/
@@ -136,14 +135,36 @@
//config: cursor position using "ESC [ 6 n" escape sequence, then read stdin.
//config:
//config: This is not clean but helps a lot on serial lines and such.
-//config:
-//config:config FEATURE_VI_OPTIMIZE_CURSOR
-//config: bool "Optimize cursor movement"
+//config:config FEATURE_VI_UNDO
+//config: bool "Support undo command 'u'"
//config: default y
//config: depends on VI
//config: help
-//config: This will make the cursor movement faster, but requires more memory
-//config: and it makes the applet a tiny bit larger.
+//config: Support the 'u' command to undo insertion, deletion, and replacement
+//config: of text.
+//config:config FEATURE_VI_UNDO_QUEUE
+//config: bool "Enable undo operation queuing"
+//config: default y
+//config: depends on FEATURE_VI_UNDO
+//config: help
+//config: The vi undo functions can use an intermediate queue to greatly lower
+//config: malloc() calls and overhead. When the maximum size of this queue is
+//config: reached, the contents of the queue are committed to the undo stack.
+//config: This increases the size of the undo code and allows some undo
+//config: operations (especially un-typing/backspacing) to be far more useful.
+//config:config FEATURE_VI_UNDO_QUEUE_MAX
+//config: int "Maximum undo character queue size"
+//config: default 256
+//config: range 32 65536
+//config: depends on FEATURE_VI_UNDO_QUEUE
+//config: help
+//config: This option sets the number of bytes used at runtime for the queue.
+//config: Smaller values will create more undo objects and reduce the amount
+//config: of typed or backspaced characters that are grouped into one undo
+//config: operation; larger values increase the potential size of each undo
+//config: and will generally malloc() larger objects and less frequently.
+//config: Unless you want more (or less) frequent "undo points" while typing,
+//config: you should probably leave this unchanged.
//applet:IF_VI(APPLET(vi, BB_DIR_BIN, BB_SUID_DROP))
@@ -154,12 +175,12 @@
//usage:#define vi_full_usage "\n\n"
//usage: "Edit FILE\n"
//usage: IF_FEATURE_VI_COLON(
-//usage: "\n -c Initial command to run ($EXINIT also available)"
+//usage: "\n -c CMD Initial command to run ($EXINIT also available)"
//usage: )
//usage: IF_FEATURE_VI_READONLY(
//usage: "\n -R Read-only"
//usage: )
-//usage: "\n -H Short help regarding available features"
+//usage: "\n -H List available features"
#include "libbb.h"
/* Should be after libbb.h: on some systems regex.h needs sys/types.h: */
@@ -202,26 +223,35 @@ enum {
MAX_SCR_ROWS = CONFIG_FEATURE_VI_MAX_LEN,
};
-/* vt102 typical ESC sequence */
-/* terminal standout start/normal ESC sequence */
-#define SOs "\033[7m"
-#define SOn "\033[0m"
-/* terminal bell sequence */
-#define bell "\007"
-/* Clear-end-of-line and Clear-end-of-screen ESC sequence */
-#define Ceol "\033[K"
-#define Ceos "\033[J"
-/* Cursor motion arbitrary destination ESC sequence */
-#define CMrc "\033[%u;%uH"
-/* Cursor motion up and down ESC sequence */
-#define CMup "\033[A"
-#define CMdown "\n"
+/* VT102 ESC sequences.
+ * See "Xterm Control Sequences"
+ * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
+ */
+/* Inverse/Normal text */
+#define ESC_BOLD_TEXT "\033[7m"
+#define ESC_NORM_TEXT "\033[0m"
+/* Bell */
+#define ESC_BELL "\007"
+/* Clear-to-end-of-line */
+#define ESC_CLEAR2EOL "\033[K"
+/* Clear-to-end-of-screen.
+ * (We use default param here.
+ * Full sequence is "ESC [ <num> J",
+ * <num> is 0/1/2 = "erase below/above/all".)
+ */
+#define ESC_CLEAR2EOS "\033[J"
+/* Cursor to given coordinate (1,1: top left) */
+#define ESC_SET_CURSOR_POS "\033[%u;%uH"
+//UNUSED
+///* Cursor up and down */
+//#define ESC_CURSOR_UP "\033[A"
+//#define ESC_CURSOR_DOWN "\n"
#if ENABLE_FEATURE_VI_DOT_CMD || ENABLE_FEATURE_VI_YANKMARK
// cmds modifying text[]
// vda: removed "aAiIs" as they switch us into insert mode
// and remembering input for replay after them makes no sense
-static const char modifying_cmds[] = "cCdDJoOpPrRxX<>~";
+static const char modifying_cmds[] ALIGN1 = "cCdDJoOpPrRxX<>~";
#endif
enum {
@@ -276,8 +306,8 @@ struct globals {
smallint editing; // >0 while we are editing a file
// [code audit says "can be 0, 1 or 2 only"]
smallint cmd_mode; // 0=command 1=insert 2=replace
- int file_modified; // buffer contents changed (counter, not flag!)
- int last_file_modified; // = -1;
+ int modified_count; // buffer contents changed if !0
+ int last_modified_count; // = -1;
int save_argc; // how many file names on cmd line
int cmdcnt; // repetition count
unsigned rows, columns; // the terminal screen is this size
@@ -303,9 +333,6 @@ struct globals {
int lmc_len; // length of last_modifying_cmd
char *ioq, *ioq_start; // pointer to string for get_one_char to "read"
#endif
-#if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR
- int last_row; // where the cursor was last moved to
-#endif
#if ENABLE_FEATURE_VI_USE_SIGNALS || ENABLE_FEATURE_VI_CRASHME
int my_pid;
#endif
@@ -349,6 +376,41 @@ struct globals {
char get_input_line__buf[MAX_INPUT_LEN]; /* former static */
char scr_out_buf[MAX_SCR_COLS + MAX_TABSTOP * 2];
+#if ENABLE_FEATURE_VI_UNDO
+// undo_push() operations
+#define UNDO_INS 0
+#define UNDO_DEL 1
+#define UNDO_INS_CHAIN 2
+#define UNDO_DEL_CHAIN 3
+// UNDO_*_QUEUED must be equal to UNDO_xxx ORed with UNDO_QUEUED_FLAG
+#define UNDO_QUEUED_FLAG 4
+#define UNDO_INS_QUEUED 4
+#define UNDO_DEL_QUEUED 5
+#define UNDO_USE_SPOS 32
+#define UNDO_EMPTY 64
+// Pass-through flags for functions that can be undone
+#define NO_UNDO 0
+#define ALLOW_UNDO 1
+#define ALLOW_UNDO_CHAIN 2
+# if ENABLE_FEATURE_VI_UNDO_QUEUE
+#define ALLOW_UNDO_QUEUED 3
+ char undo_queue_state;
+ int undo_q;
+ char *undo_queue_spos; // Start position of queued operation
+ char undo_queue[CONFIG_FEATURE_VI_UNDO_QUEUE_MAX];
+# else
+// If undo queuing disabled, don't invoke the missing queue logic
+#define ALLOW_UNDO_QUEUED 1
+# endif
+
+ struct undo_object {
+ struct undo_object *prev; // Linking back avoids list traversal (LIFO)
+ int start; // Offset where the data should be restored/deleted
+ int length; // total data size
+ uint8_t u_type; // 0=deleted, 1=inserted, 2=swapped
+ char undo_text[1]; // text that was deleted (if deletion)
+ } *undo_stack_tail;
+#endif /* ENABLE_FEATURE_VI_UNDO */
};
#define G (*ptr_to_globals)
#define text (G.text )
@@ -360,8 +422,8 @@ struct globals {
#define vi_setops (G.vi_setops )
#define editing (G.editing )
#define cmd_mode (G.cmd_mode )
-#define file_modified (G.file_modified )
-#define last_file_modified (G.last_file_modified )
+#define modified_count (G.modified_count )
+#define last_modified_count (G.last_modified_count)
#define save_argc (G.save_argc )
#define cmdcnt (G.cmdcnt )
#define rows (G.rows )
@@ -389,7 +451,6 @@ struct globals {
#define lmc_len (G.lmc_len )
#define ioq (G.ioq )
#define ioq_start (G.ioq_start )
-#define last_row (G.last_row )
#define my_pid (G.my_pid )
#define last_search_pattern (G.last_search_pattern)
@@ -411,15 +472,24 @@ struct globals {
#define last_modifying_cmd (G.last_modifying_cmd )
#define get_input_line__buf (G.get_input_line__buf)
+#if ENABLE_FEATURE_VI_UNDO
+#define undo_stack_tail (G.undo_stack_tail )
+# if ENABLE_FEATURE_VI_UNDO_QUEUE
+#define undo_queue_state (G.undo_queue_state)
+#define undo_q (G.undo_q )
+#define undo_queue (G.undo_queue )
+#define undo_queue_spos (G.undo_queue_spos )
+# endif
+#endif
+
#define INIT_G() do { \
SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
- last_file_modified = -1; \
+ last_modified_count = -1; \
/* "" but has space for 2 chars: */ \
IF_FEATURE_VI_SEARCH(last_search_pattern = xzalloc(2);) \
} while (0)
-static int init_text_buffer(char *); // init from file or create new
static void edit_file(char *); // edit one file
static void do_cmd(int); // execute a command
static int next_tabstop(int);
@@ -430,7 +500,7 @@ static char *prev_line(char *); // return pointer to prev line B-o-l
static char *next_line(char *); // return pointer to next line B-o-l
static char *end_screen(void); // get pointer to last char on screen
static int count_lines(char *, char *); // count line from start to stop
-static char *find_line(int); // find begining of line #li
+static char *find_line(int); // find beginning of line #li
static char *move_to_col(char *, int); // move "p" to column l
static void dot_left(void); // move dot left- dont leave line
static void dot_right(void); // move dot right- dont leave line
@@ -440,10 +510,12 @@ static void dot_next(void); // move dot to next line B-o-l
static void dot_prev(void); // move dot to prev line B-o-l
static void dot_scroll(int, int); // move the screen up or down
static void dot_skip_over_ws(void); // move dot pat WS
-static void dot_delete(void); // delete the char at 'dot'
static char *bound_dot(char *); // make sure text[0] <= P < "end"
static char *new_screen(int, int); // malloc virtual screen memory
-static char *char_insert(char *, char); // insert the char c at 'p'
+#if !ENABLE_FEATURE_VI_UNDO
+#define char_insert(a,b,c) char_insert(a,b)
+#endif
+static char *char_insert(char *, char, int); // insert the char c at 'p'
// might reallocate text[]! use p += stupid_insert(p, ...),
// and be careful to not use pointers into potentially freed text[]!
static uintptr_t stupid_insert(char *, char); // stupidly insert the char c at 'p'
@@ -451,11 +523,17 @@ static int find_range(char **, char **, char); // return pointers for an object
static int st_test(char *, int, int, char *); // helper for skip_thing()
static char *skip_thing(char *, int, int, int); // skip some object
static char *find_pair(char *, char); // find matching pair () [] {}
-static char *text_hole_delete(char *, char *); // at "p", delete a 'size' byte hole
+#if !ENABLE_FEATURE_VI_UNDO
+#define text_hole_delete(a,b,c) text_hole_delete(a,b)
+#endif
+static char *text_hole_delete(char *, char *, int); // at "p", delete a 'size' byte hole
// might reallocate text[]! use p += text_hole_make(p, ...),
// and be careful to not use pointers into potentially freed text[]!
static uintptr_t text_hole_make(char *, int); // at "p", make a 'size' byte hole
-static char *yank_delete(char *, char *, int, int); // yank text[] into register then delete
+#if !ENABLE_FEATURE_VI_UNDO
+#define yank_delete(a,b,c,d,e) yank_delete(a,b,c,d)
+#endif
+static char *yank_delete(char *, char *, int, int, int); // yank text[] into register then delete
static void show_help(void); // display some help info
static void rawmode(void); // set "raw" mode on tty
static void cookmode(void); // return to "cooked" mode on tty
@@ -463,17 +541,10 @@ static void cookmode(void); // return to "cooked" mode on tty
static int mysleep(int);
static int readit(void); // read (maybe cursor) key from stdin
static int get_one_char(void); // read 1 char from stdin
-static int file_size(const char *); // what is the byte size of "fn"
-#if !ENABLE_FEATURE_VI_READONLY
-#define file_insert(fn, p, update_ro_status) file_insert(fn, p)
-#endif
// file_insert might reallocate text[]!
static int file_insert(const char *, char *, int);
static int file_write(char *, char *, char *);
-#if !ENABLE_FEATURE_VI_OPTIMIZE_CURSOR
-#define place_cursor(a, b, optimize) place_cursor(a, b)
-#endif
-static void place_cursor(int, int, int);
+static void place_cursor(int, int);
static void screen_erase(void);
static void clear_to_eol(void);
static void clear_to_eos(void);
@@ -484,14 +555,14 @@ static void flash(int); // flash the terminal screen
static void show_status_line(void); // put a message on the bottom line
static void status_line(const char *, ...); // print to status buf
static void status_line_bold(const char *, ...);
+static void status_line_bold_errno(const char *fn);
static void not_implemented(const char *); // display "Not implemented" message
static int format_edit_status(void); // format file status on status line
static void redraw(int); // force a full screen refresh
static char* format_line(char* /*, int*/);
static void refresh(int); // update the terminal from screen[]
-static void Indicate_Error(void); // use flash or beep to indicate error
-#define indicate_error(c) Indicate_Error()
+static void indicate_error(void); // use flash or beep to indicate error
static void Hit_Return(void);
#if ENABLE_FEATURE_VI_SEARCH
@@ -500,8 +571,8 @@ static char *char_search(char *, const char *, int, int); // search for pattern
#if ENABLE_FEATURE_VI_COLON
static char *get_one_address(char *, int *); // get colon addr, if present
static char *get_address(char *, int *, int *); // get two colon addrs, if present
-static void colon(char *); // execute the "colon" mode cmds
#endif
+static void colon(char *); // execute the "colon" mode cmds
#if ENABLE_FEATURE_VI_USE_SIGNALS
static void winch_sig(int); // catch window size changes
static void suspend_sig(int); // catch ctrl-Z
@@ -519,20 +590,36 @@ static void showmatching(char *); // show the matching pair () [] {}
#if ENABLE_FEATURE_VI_YANKMARK || (ENABLE_FEATURE_VI_COLON && ENABLE_FEATURE_VI_SEARCH) || ENABLE_FEATURE_VI_CRASHME
// might reallocate text[]! use p += string_insert(p, ...),
// and be careful to not use pointers into potentially freed text[]!
-static uintptr_t string_insert(char *, const char *); // insert the string at 'p'
+# if !ENABLE_FEATURE_VI_UNDO
+#define string_insert(a,b,c) string_insert(a,b)
+# endif
+static uintptr_t string_insert(char *, const char *, int); // insert the string at 'p'
#endif
#if ENABLE_FEATURE_VI_YANKMARK
static char *text_yank(char *, char *, int); // save copy of "p" into a register
static char what_reg(void); // what is letter of current YDreg
static void check_context(char); // remember context for '' command
#endif
+#if ENABLE_FEATURE_VI_UNDO
+static void flush_undo_data(void);
+static void undo_push(char *, unsigned int, unsigned char); // Push an operation on the undo stack
+static void undo_pop(void); // Undo the last operation
+# if ENABLE_FEATURE_VI_UNDO_QUEUE
+static void undo_queue_commit(void); // Flush any queued objects to the undo stack
+# else
+# define undo_queue_commit() ((void)0)
+# endif
+#else
+#define flush_undo_data() ((void)0)
+#define undo_queue_commit() ((void)0)
+#endif
+
#if ENABLE_FEATURE_VI_CRASHME
static void crash_dummy();
static void crash_test();
static int crashme = 0;
#endif
-
static void write1(const char *out)
{
fputs(out, stdout);
@@ -545,6 +632,14 @@ int vi_main(int argc, char **argv)
INIT_G();
+#if ENABLE_FEATURE_VI_UNDO
+ /* undo_stack_tail = NULL; - already is */
+#if ENABLE_FEATURE_VI_UNDO_QUEUE
+ undo_queue_state = UNDO_EMPTY;
+ /* undo_q = 0; - already is */
+#endif
+#endif
+
#if ENABLE_FEATURE_VI_USE_SIGNALS || ENABLE_FEATURE_VI_CRASHME
my_pid = getpid();
#endif
@@ -558,7 +653,8 @@ int vi_main(int argc, char **argv)
}
#endif
- vi_setops = VI_AUTOINDENT | VI_SHOWMATCH | VI_IGNORECASE;
+ // autoindent is not default in vim 7.3
+ vi_setops = /*VI_AUTOINDENT |*/ VI_SHOWMATCH | VI_IGNORECASE;
// 1- process $HOME/.exrc file (not inplemented yet)
// 2- process EXINIT variable from environment
// 3- process command line args
@@ -584,7 +680,7 @@ int vi_main(int argc, char **argv)
#if ENABLE_FEATURE_VI_COLON
case 'c': // cmd line vi command
if (*optarg)
- initial_cmds[initial_cmds[0] != 0] = xstrndup(optarg, MAX_INPUT_LEN);
+ initial_cmds[initial_cmds[0] != NULL] = xstrndup(optarg, MAX_INPUT_LEN);
break;
#endif
case 'H':
@@ -599,15 +695,19 @@ int vi_main(int argc, char **argv)
// The argv array can be used by the ":next" and ":rewind" commands
argv += optind;
argc -= optind;
- save_argc = argc;
- optind = 0;
//----- This is the main file handling loop --------------
+ save_argc = argc;
+ optind = 0;
+ // "Save cursor, use alternate screen buffer, clear screen"
+ write1("\033[?1049h");
while (1) {
edit_file(argv[optind]); /* param might be NULL */
if (++optind >= argc)
break;
}
+ // "Use normal screen buffer, restore cursor"
+ write1("\033[?1049l");
//-----------------------------------------------------------
return 0;
@@ -618,30 +718,29 @@ int vi_main(int argc, char **argv)
static int init_text_buffer(char *fn)
{
int rc;
- int size = file_size(fn); // file size. -1 means does not exist.
+
+ flush_undo_data();
+ modified_count = 0;
+ last_modified_count = -1;
+#if ENABLE_FEATURE_VI_YANKMARK
+ /* init the marks */
+ memset(mark, 0, sizeof(mark));
+#endif
/* allocate/reallocate text buffer */
free(text);
- text_size = size + 10240;
+ text_size = 10240;
screenbegin = dot = end = text = xzalloc(text_size);
if (fn != current_filename) {
free(current_filename);
current_filename = xstrdup(fn);
}
- if (size < 0) {
- // file dont exist. Start empty buf with dummy line
- char_insert(text, '\n');
- rc = 0;
- } else {
- rc = file_insert(fn, text, 1);
+ rc = file_insert(fn, text, 1);
+ if (rc < 0) {
+ // file doesnt exist. Start empty buf with dummy line
+ char_insert(text, '\n', NO_UNDO);
}
- file_modified = 0;
- last_file_modified = -1;
-#if ENABLE_FEATURE_VI_YANKMARK
- /* init the marks. */
- memset(mark, 0, sizeof(mark));
-#endif
return rc;
}
@@ -756,7 +855,7 @@ static void edit_file(char *fn)
crash_dummy(); // generate a random command
} else {
crashme = 0;
- string_insert(text, "\n\n##### Ran out of text to work on. #####\n\n"); // insert the string
+ string_insert(text, "\n\n##### Ran out of text to work on. #####\n\n", NO_UNDO); // insert the string
dot = text;
refresh(FALSE);
}
@@ -909,13 +1008,71 @@ static void setops(const char *args, const char *opname, int flg_no,
}
#endif
+#endif /* FEATURE_VI_COLON */
+
// buf must be no longer than MAX_INPUT_LEN!
static void colon(char *buf)
{
+#if !ENABLE_FEATURE_VI_COLON
+ /* Simple ":cmd" handler with minimal set of commands */
+ char *p = buf;
+ int cnt;
+
+ if (*p == ':')
+ p++;
+ cnt = strlen(p);
+ if (cnt == 0)
+ return;
+ if (strncmp(p, "quit", cnt) == 0
+ || strncmp(p, "q!", cnt) == 0
+ ) {
+ if (modified_count && p[1] != '!') {
+ status_line_bold("No write since last change (:%s! overrides)", p);
+ } else {
+ editing = 0;
+ }
+ return;
+ }
+ if (strncmp(p, "write", cnt) == 0
+ || strncmp(p, "wq", cnt) == 0
+ || strncmp(p, "wn", cnt) == 0
+ || (p[0] == 'x' && !p[1])
+ ) {
+ cnt = file_write(current_filename, text, end - 1);
+ if (cnt < 0) {
+ if (cnt == -1)
+ status_line_bold("Write error: %s", strerror(errno));
+ } else {
+ modified_count = 0;
+ last_modified_count = -1;
+ status_line("'%s' %dL, %dC",
+ current_filename,
+ count_lines(text, end - 1), cnt
+ );
+ if (p[0] == 'x' || p[1] == 'q' || p[1] == 'n'
+ || p[0] == 'X' || p[1] == 'Q' || p[1] == 'N'
+ ) {
+ editing = 0;
+ }
+ }
+ return;
+ }
+ if (strncmp(p, "file", cnt) == 0) {
+ last_status_cksum = 0; // force status update
+ return;
+ }
+ if (sscanf(p, "%d", &cnt) > 0) {
+ dot = find_line(cnt);
+ dot_skip_over_ws();
+ return;
+ }
+ not_implemented(p);
+#else
+
char c, *orig_buf, *buf1, *q, *r;
char *fn, cmd[MAX_INPUT_LEN], args[MAX_INPUT_LEN];
- int i, l, li, ch, b, e;
- int useforce, forced = FALSE;
+ int i, l, li, b, e;
+ int useforce;
// :3154 // if (-e line 3154) goto it else stay put
// :4,33w! foo // write a portion of buffer to file "foo"
@@ -937,7 +1094,7 @@ static void colon(char *buf)
if (*buf == ':')
buf++; // move past the ':'
- li = ch = i = 0;
+ li = i = 0;
b = e = -1;
q = text; // assume 1,$ for the range
r = end - 1;
@@ -1015,11 +1172,13 @@ static void colon(char *buf)
q = begin_line(dot); // assume .,. for the range
r = end_line(dot);
}
- dot = yank_delete(q, r, 1, YANKDEL); // save, then delete lines
+ dot = yank_delete(q, r, 1, YANKDEL, ALLOW_UNDO); // save, then delete lines
dot_skip_over_ws();
} else if (strncmp(cmd, "edit", i) == 0) { // Edit a file
+ int size;
+
// don't edit, if the current file has been modified
- if (file_modified && !useforce) {
+ if (modified_count && !useforce) {
status_line_bold("No write since last change (:%s! overrides)", cmd);
goto ret;
}
@@ -1035,8 +1194,7 @@ static void colon(char *buf)
goto ret;
}
- if (init_text_buffer(fn) < 0)
- goto ret;
+ size = init_text_buffer(fn);
#if ENABLE_FEATURE_VI_YANKMARK
if (Ureg >= 0 && Ureg < 28) {
@@ -1050,14 +1208,16 @@ static void colon(char *buf)
#endif
// how many lines in text[]?
li = count_lines(text, end - 1);
- status_line("\"%s\"%s"
+ status_line("'%s'%s"
IF_FEATURE_VI_READONLY("%s")
- " %dL, %dC", current_filename,
- (file_size(fn) < 0 ? " [New file]" : ""),
+ " %dL, %dC",
+ current_filename,
+ (size < 0 ? " [New file]" : ""),
IF_FEATURE_VI_READONLY(
((readonly_mode) ? " [Readonly]" : ""),
)
- li, ch);
+ li, (int)(end - text)
+ );
} else if (strncmp(cmd, "file", i) == 0) { // what File is this
if (b != -1 || e != -1) {
status_line_bold("No address allowed on this command");
@@ -1122,7 +1282,7 @@ static void colon(char *buf)
goto ret;
}
// don't exit if the file been modified
- if (file_modified) {
+ if (modified_count) {
status_line_bold("No write since last change (:%s! overrides)", cmd);
goto ret;
}
@@ -1146,6 +1306,8 @@ static void colon(char *buf)
}
editing = 0;
} else if (strncmp(cmd, "read", i) == 0) { // read file into text[]
+ int size;
+
fn = args;
if (!fn[0]) {
status_line_bold("No filename given");
@@ -1155,30 +1317,35 @@ static void colon(char *buf)
q = begin_line(dot); // assume "dot"
}
// read after current line- unless user said ":0r foo"
- if (b != 0)
+ if (b != 0) {
q = next_line(q);
+ // read after last line
+ if (q == end-1)
+ ++q;
+ }
{ // dance around potentially-reallocated text[]
uintptr_t ofs = q - text;
- ch = file_insert(fn, q, 0);
+ size = file_insert(fn, q, 0);
q = text + ofs;
}
- if (ch < 0)
+ if (size < 0)
goto ret; // nothing was inserted
// how many lines in text[]?
- li = count_lines(q, q + ch - 1);
- status_line("\"%s\""
+ li = count_lines(q, q + size - 1);
+ status_line("'%s'"
IF_FEATURE_VI_READONLY("%s")
- " %dL, %dC", fn,
+ " %dL, %dC",
+ fn,
IF_FEATURE_VI_READONLY((readonly_mode ? " [Readonly]" : ""),)
- li, ch);
- if (ch > 0) {
+ li, size
+ );
+ if (size > 0) {
// if the insert is before "dot" then we need to update
if (q <= dot)
- dot += ch;
- /*file_modified++; - done by file_insert */
+ dot += size;
}
} else if (strncmp(cmd, "rewind", i) == 0) { // rewind cmd line args
- if (file_modified && !useforce) {
+ if (modified_count && !useforce) {
status_line_bold("No write since last change (:%s! overrides)", cmd);
} else {
// reset the filenames to edit
@@ -1191,7 +1358,7 @@ static void colon(char *buf)
char *argp;
#endif
i = 0; // offset into args
- // only blank is regarded as args delmiter. What about tab '\t' ?
+ // only blank is regarded as args delimiter. What about tab '\t'?
if (!args[0] || strcasecmp(args, "all") == 0) {
// print out values of all options
#if ENABLE_FEATURE_VI_SETOPTS
@@ -1235,6 +1402,9 @@ static void colon(char *buf)
char *F, *R, *flags;
size_t len_F, len_R;
int gflag; // global replace flag
+#if ENABLE_FEATURE_VI_UNDO
+ int dont_chain_first_item = ALLOW_UNDO;
+#endif
// F points to the "find" pattern
// R points to the "replace" pattern
@@ -1269,9 +1439,13 @@ static void colon(char *buf)
if (found) {
uintptr_t bias;
// we found the "find" pattern - delete it
- text_hole_delete(found, found + len_F - 1);
- // inset the "replace" patern
- bias = string_insert(found, R); // insert the string
+ // For undo support, the first item should not be chained
+ text_hole_delete(found, found + len_F - 1, dont_chain_first_item);
+#if ENABLE_FEATURE_VI_UNDO
+ dont_chain_first_item = ALLOW_UNDO_CHAIN;
+#endif
+ // insert the "replace" patern
+ bias = string_insert(found, R, ALLOW_UNDO_CHAIN);
found += bias;
ls += bias;
/*q += bias; - recalculated anyway */
@@ -1293,46 +1467,48 @@ static void colon(char *buf)
|| strncmp(cmd, "wn", i) == 0
|| (cmd[0] == 'x' && !cmd[1])
) {
+ int size;
+ //int forced = FALSE;
+
// is there a file name to write to?
if (args[0]) {
fn = args;
}
#if ENABLE_FEATURE_VI_READONLY
if (readonly_mode && !useforce) {
- status_line_bold("\"%s\" File is read only", fn);
+ status_line_bold("'%s' is read only", fn);
goto ret;
}
#endif
// how many lines in text[]?
li = count_lines(q, r);
- ch = r - q + 1;
- // see if file exists- if not, its just a new file request
- if (useforce) {
+ size = r - q + 1;
+ //if (useforce) {
// if "fn" is not write-able, chmod u+w
// sprintf(syscmd, "chmod u+w %s", fn);
// system(syscmd);
- forced = TRUE;
- }
+ // forced = TRUE;
+ //}
l = file_write(fn, q, r);
- if (useforce && forced) {
+ //if (useforce && forced) {
// chmod u-w
// sprintf(syscmd, "chmod u-w %s", fn);
// system(syscmd);
- forced = FALSE;
- }
+ // forced = FALSE;
+ //}
if (l < 0) {
if (l == -1)
- status_line_bold("\"%s\" %s", fn, strerror(errno));
+ status_line_bold_errno(fn);
} else {
- status_line("\"%s\" %dL, %dC", fn, li, l);
- if (q == text && r == end - 1 && l == ch) {
- file_modified = 0;
- last_file_modified = -1;
+ status_line("'%s' %dL, %dC", fn, li, l);
+ if (q == text && r == end - 1 && l == size) {
+ modified_count = 0;
+ last_modified_count = -1;
}
if ((cmd[0] == 'x' || cmd[1] == 'q' || cmd[1] == 'n'
|| cmd[0] == 'X' || cmd[1] == 'Q' || cmd[1] == 'N'
)
- && l == ch
+ && l == size
) {
editing = 0;
}
@@ -1359,9 +1535,8 @@ static void colon(char *buf)
colon_s_fail:
status_line(":s expression missing delimiters");
#endif
-}
-
#endif /* FEATURE_VI_COLON */
+}
static void Hit_Return(void)
{
@@ -1508,10 +1683,10 @@ static char *dollar_line(char *p) // return pointer to just before NL line
static char *prev_line(char *p) // return pointer first char prev line
{
- p = begin_line(p); // goto begining of cur line
+ p = begin_line(p); // goto beginning of cur line
if (p > text && p[-1] == '\n')
p--; // step to prev line
- p = begin_line(p); // goto begining of prev line
+ p = begin_line(p); // goto beginning of prev line
return p;
}
@@ -1559,7 +1734,7 @@ static int count_lines(char *start, char *stop)
return cnt;
}
-static char *find_line(int li) // find begining of line #li
+static char *find_line(int li) // find beginning of line #li
{
char *q;
@@ -1572,23 +1747,27 @@ static char *find_line(int li) // find begining of line #li
//----- Dot Movement Routines ----------------------------------
static void dot_left(void)
{
+ undo_queue_commit();
if (dot > text && dot[-1] != '\n')
dot--;
}
static void dot_right(void)
{
+ undo_queue_commit();
if (dot < end - 1 && *dot != '\n')
dot++;
}
static void dot_begin(void)
{
+ undo_queue_commit();
dot = begin_line(dot); // return pointer to first char cur line
}
static void dot_end(void)
{
+ undo_queue_commit();
dot = end_line(dot); // return pointer to last char cur line
}
@@ -1614,11 +1793,13 @@ static char *move_to_col(char *p, int l)
static void dot_next(void)
{
+ undo_queue_commit();
dot = next_line(dot);
}
static void dot_prev(void)
{
+ undo_queue_commit();
dot = prev_line(dot);
}
@@ -1626,6 +1807,7 @@ static void dot_scroll(int cnt, int dir)
{
char *q;
+ undo_queue_commit();
for (; cnt > 0; cnt--) {
if (dir < 0) {
// scroll Backwards
@@ -1653,20 +1835,15 @@ static void dot_skip_over_ws(void)
dot++;
}
-static void dot_delete(void) // delete the char at 'dot'
-{
- text_hole_delete(dot, dot);
-}
-
static char *bound_dot(char *p) // make sure text[0] <= P < "end"
{
if (p >= end && end > text) {
p = end - 1;
- indicate_error('1');
+ indicate_error();
}
if (p < text) {
p = text;
- indicate_error('2');
+ indicate_error();
}
return p;
}
@@ -1707,65 +1884,53 @@ static char *new_screen(int ro, int co)
// search for pattern starting at p
static char *char_search(char *p, const char *pat, int dir, int range)
{
- char *q;
struct re_pattern_buffer preg;
+ const char *err;
+ char *q;
int i;
int size;
re_syntax_options = RE_SYNTAX_POSIX_EXTENDED;
- preg.translate = 0;
- preg.fastmap = 0;
- preg.buffer = 0;
- preg.allocated = 0;
+ if (ignorecase)
+ re_syntax_options = RE_SYNTAX_POSIX_EXTENDED | RE_ICASE;
+
+ memset(&preg, 0, sizeof(preg));
+ err = re_compile_pattern(pat, strlen(pat), &preg);
+ if (err != NULL) {
+ status_line_bold("bad search pattern '%s': %s", pat, err);
+ return p;
+ }
// assume a LIMITED forward search
- q = next_line(p);
- q = end_line(q);
q = end - 1;
- if (dir == BACK) {
- q = prev_line(p);
+ if (dir == BACK)
q = text;
- }
- // count the number of chars to search over, forward or backward
- size = q - p;
- if (size < 0)
- size = p - q;
// RANGE could be negative if we are searching backwards
range = q - p;
-
- q = (char *)re_compile_pattern(pat, strlen(pat), (struct re_pattern_buffer *)&preg);
- if (q != 0) {
- // The pattern was not compiled
- status_line_bold("bad search pattern: \"%s\": %s", pat, q);
- i = 0; // return p if pattern not compiled
- goto cs1;
- }
-
q = p;
+ size = range;
if (range < 0) {
+ size = -size;
q = p - size;
if (q < text)
q = text;
}
// search for the compiled pattern, preg, in p[]
- // range < 0- search backward
- // range > 0- search forward
+ // range < 0: search backward
+ // range > 0: search forward
// 0 < start < size
- // re_search() < 0 not found or error
- // re_search() > 0 index of found pattern
- // struct pattern char int int int struct reg
- // re_search (*pattern_buffer, *string, size, start, range, *regs)
- i = re_search(&preg, q, size, 0, range, 0);
- if (i == -1) {
- p = 0;
- i = 0; // return NULL if pattern not found
- }
- cs1:
- if (dir == FORWARD) {
+ // re_search() < 0: not found or error
+ // re_search() >= 0: index of found pattern
+ // struct pattern char int int int struct reg
+ // re_search(*pattern_buffer, *string, size, start, range, *regs)
+ i = re_search(&preg, q, size, /*start:*/ 0, range, /*struct re_registers*:*/ NULL);
+ regfree(&preg);
+ if (i < 0)
+ return NULL;
+ if (dir == FORWARD)
p = p + i;
- } else {
+ else
p = p - i;
- }
return p;
}
@@ -1790,7 +1955,7 @@ static char *char_search(char *p, const char *pat, int dir, int range)
len = strlen(pat);
if (dir == FORWARD) {
- stop = end - 1; // assume range is p - end-1
+ stop = end - 1; // assume range is p..end-1
if (range == LIMITED)
stop = next_line(p); // range is to next line
for (start = p; start < stop; start++) {
@@ -1799,7 +1964,7 @@ static char *char_search(char *p, const char *pat, int dir, int range)
}
}
} else if (dir == BACK) {
- stop = text; // assume range is text - p
+ stop = text; // assume range is text..p
if (range == LIMITED)
stop = prev_line(p); // range is to prev line
for (start = p - len; start >= stop; start--) {
@@ -1816,17 +1981,34 @@ static char *char_search(char *p, const char *pat, int dir, int range)
#endif /* FEATURE_VI_SEARCH */
-static char *char_insert(char *p, char c) // insert the char c at 'p'
+static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
{
if (c == 22) { // Is this an ctrl-V?
p += stupid_insert(p, '^'); // use ^ to indicate literal next
refresh(FALSE); // show the ^
c = get_one_char();
*p = c;
+#if ENABLE_FEATURE_VI_UNDO
+ switch (undo) {
+ case ALLOW_UNDO:
+ undo_push(p, 1, UNDO_INS);
+ break;
+ case ALLOW_UNDO_CHAIN:
+ undo_push(p, 1, UNDO_INS_CHAIN);
+ break;
+# if ENABLE_FEATURE_VI_UNDO_QUEUE
+ case ALLOW_UNDO_QUEUED:
+ undo_push(p, 1, UNDO_INS_QUEUED);
+ break;
+# endif
+ }
+#else
+ modified_count++;
+#endif /* ENABLE_FEATURE_VI_UNDO */
p++;
- file_modified++;
} else if (c == 27) { // Is this an ESC?
cmd_mode = 0;
+ undo_queue_commit();
cmdcnt = 0;
end_cmd_q(); // stop adding to q
last_status_cksum = 0; // force status update
@@ -1834,26 +2016,39 @@ static char *char_insert(char *p, char c) // insert the char c at 'p'
p--;
}
} else if (c == erase_char || c == 8 || c == 127) { // Is this a BS
- // 123456789
- if ((p[-1] != '\n') && (dot>text)) {
+ if (p > text) {
p--;
- p = text_hole_delete(p, p); // shrink buffer 1 char
+ p = text_hole_delete(p, p, ALLOW_UNDO_QUEUED); // shrink buffer 1 char
}
} else {
-#if ENABLE_FEATURE_VI_SETOPTS
// insert a char into text[]
- char *sp; // "save p"
-#endif
-
if (c == 13)
c = '\n'; // translate \r to \n
-#if ENABLE_FEATURE_VI_SETOPTS
- sp = p; // remember addr of insert
-#endif
+#if ENABLE_FEATURE_VI_UNDO
+# if ENABLE_FEATURE_VI_UNDO_QUEUE
+ if (c == '\n')
+ undo_queue_commit();
+# endif
+ switch (undo) {
+ case ALLOW_UNDO:
+ undo_push(p, 1, UNDO_INS);
+ break;
+ case ALLOW_UNDO_CHAIN:
+ undo_push(p, 1, UNDO_INS_CHAIN);
+ break;
+# if ENABLE_FEATURE_VI_UNDO_QUEUE
+ case ALLOW_UNDO_QUEUED:
+ undo_push(p, 1, UNDO_INS_QUEUED);
+ break;
+# endif
+ }
+#else
+ modified_count++;
+#endif /* ENABLE_FEATURE_VI_UNDO */
p += 1 + stupid_insert(p, c); // insert the char
#if ENABLE_FEATURE_VI_SETOPTS
- if (showmatch && strchr(")]}", *sp) != NULL) {
- showmatching(sp);
+ if (showmatch && strchr(")]}", c) != NULL) {
+ showmatching(p - 1);
}
if (autoindent && c == '\n') { // auto indent the new line
char *q;
@@ -1865,6 +2060,9 @@ static char *char_insert(char *p, char c) // insert the char c at 'p'
bias = text_hole_make(p, len);
p += bias;
q += bias;
+#if ENABLE_FEATURE_VI_UNDO
+ undo_push(p, len, UNDO_INS);
+#endif
memcpy(p, q, len);
p += len;
}
@@ -1882,7 +2080,6 @@ static uintptr_t stupid_insert(char *p, char c) // stupidly insert the char c at
bias = text_hole_make(p, 1);
p += bias;
*p = c;
- //file_modified++; - done by text_hole_make()
return bias;
}
@@ -1930,11 +2127,11 @@ static int find_range(char **start, char **stop, char c)
dot_end(); // find NL
q = dot;
} else {
- // nothing -- this causes any other values of c to
- // represent the one-character range under the
- // cursor. this is correct for ' ' and 'l', but
- // perhaps no others.
- //
+ // nothing -- this causes any other values of c to
+ // represent the one-character range under the
+ // cursor. this is correct for ' ' and 'l', but
+ // perhaps no others.
+ //
}
if (q < p) {
t = q;
@@ -2011,34 +2208,32 @@ static char *skip_thing(char *p, int linecnt, int dir, int type)
}
// find matching char of pair () [] {}
+// will crash if c is not one of these
static char *find_pair(char *p, const char c)
{
- char match, *q;
+ const char *braces = "()[]{}";
+ char match;
int dir, level;
- match = ')';
+ dir = strchr(braces, c) - braces;
+ dir ^= 1;
+ match = braces[dir];
+ dir = ((dir & 1) << 1) - 1; /* 1 for ([{, -1 for )\} */
+
+ // look for match, count levels of pairs (( ))
level = 1;
- dir = 1; // assume forward
- switch (c) {
- case '(': match = ')'; break;
- case '[': match = ']'; break;
- case '{': match = '}'; break;
- case ')': match = '('; dir = -1; break;
- case ']': match = '['; dir = -1; break;
- case '}': match = '{'; dir = -1; break;
- }
- for (q = p + dir; text <= q && q < end; q += dir) {
- // look for match, count levels of pairs (( ))
- if (*q == c)
+ for (;;) {
+ p += dir;
+ if (p < text || p >= end)
+ return NULL;
+ if (*p == c)
level++; // increase pair levels
- if (*q == match)
+ if (*p == match) {
level--; // reduce pair level
- if (level == 0)
- break; // found matching pair
+ if (level == 0)
+ return p; // found matching pair
+ }
}
- if (level != 0)
- q = NULL; // indicate no match
- return q;
}
#if ENABLE_FEATURE_VI_SETOPTS
@@ -2050,7 +2245,7 @@ static void showmatching(char *p)
// we found half of a pair
q = find_pair(p, *p); // get loc of matching char
if (q == NULL) {
- indicate_error('3'); // no matching char
+ indicate_error(); // no matching char
} else {
// "q" now points to matching pair
save_dot = dot; // remember where we are
@@ -2063,6 +2258,199 @@ static void showmatching(char *p)
}
#endif /* FEATURE_VI_SETOPTS */
+#if ENABLE_FEATURE_VI_UNDO
+static void flush_undo_data(void)
+{
+ struct undo_object *undo_entry;
+
+ while (undo_stack_tail) {
+ undo_entry = undo_stack_tail;
+ undo_stack_tail = undo_entry->prev;
+ free(undo_entry);
+ }
+}
+
+// Undo functions and hooks added by Jody Bruchon (jody@jodybruchon.com)
+static void undo_push(char *src, unsigned int length, uint8_t u_type) // Add to the undo stack
+{
+ struct undo_object *undo_entry;
+
+ // "u_type" values
+ // UNDO_INS: insertion, undo will remove from buffer
+ // UNDO_DEL: deleted text, undo will restore to buffer
+ // UNDO_{INS,DEL}_CHAIN: Same as above but also calls undo_pop() when complete
+ // The CHAIN operations are for handling multiple operations that the user
+ // performs with a single action, i.e. REPLACE mode or find-and-replace commands
+ // UNDO_{INS,DEL}_QUEUED: If queuing feature is enabled, allow use of the queue
+ // for the INS/DEL operation. The raw values should be equal to the values of
+ // UNDO_{INS,DEL} ORed with UNDO_QUEUED_FLAG
+
+#if ENABLE_FEATURE_VI_UNDO_QUEUE
+ // This undo queuing functionality groups multiple character typing or backspaces
+ // into a single large undo object. This greatly reduces calls to malloc() for
+ // single-character operations while typing and has the side benefit of letting
+ // an undo operation remove chunks of text rather than a single character.
+ switch (u_type) {
+ case UNDO_EMPTY: // Just in case this ever happens...
+ return;
+ case UNDO_DEL_QUEUED:
+ if (length != 1)
+ return; // Only queue single characters
+ switch (undo_queue_state) {
+ case UNDO_EMPTY:
+ undo_queue_state = UNDO_DEL;
+ case UNDO_DEL:
+ undo_queue_spos = src;
+ undo_q++;
+ undo_queue[CONFIG_FEATURE_VI_UNDO_QUEUE_MAX - undo_q] = *src;
+ // If queue is full, dump it into an object
+ if (undo_q == CONFIG_FEATURE_VI_UNDO_QUEUE_MAX)
+ undo_queue_commit();
+ return;
+ case UNDO_INS:
+ // Switch from storing inserted text to deleted text
+ undo_queue_commit();
+ undo_push(src, length, UNDO_DEL_QUEUED);
+ return;
+ }
+ break;
+ case UNDO_INS_QUEUED:
+ if (length != 1)
+ return;
+ switch (undo_queue_state) {
+ case UNDO_EMPTY:
+ undo_queue_state = UNDO_INS;
+ undo_queue_spos = src;
+ case UNDO_INS:
+ undo_q++; // Don't need to save any data for insertions
+ if (undo_q == CONFIG_FEATURE_VI_UNDO_QUEUE_MAX)
+ undo_queue_commit();
+ return;
+ case UNDO_DEL:
+ // Switch from storing deleted text to inserted text
+ undo_queue_commit();
+ undo_push(src, length, UNDO_INS_QUEUED);
+ return;
+ }
+ break;
+ }
+#else
+ // If undo queuing is disabled, ignore the queuing flag entirely
+ u_type = u_type & ~UNDO_QUEUED_FLAG;
+#endif
+
+ // Allocate a new undo object
+ if (u_type == UNDO_DEL || u_type == UNDO_DEL_CHAIN) {
+ // For UNDO_DEL objects, save deleted text
+ if ((src + length) == end)
+ length--;
+ // If this deletion empties text[], strip the newline. When the buffer becomes
+ // zero-length, a newline is added back, which requires this to compensate.
+ undo_entry = xzalloc(offsetof(struct undo_object, undo_text) + length);
+ memcpy(undo_entry->undo_text, src, length);
+ } else {
+ undo_entry = xzalloc(sizeof(*undo_entry));
+ }
+ undo_entry->length = length;
+#if ENABLE_FEATURE_VI_UNDO_QUEUE
+ if ((u_type & UNDO_USE_SPOS) != 0) {
+ undo_entry->start = undo_queue_spos - text; // use start position from queue
+ } else {
+ undo_entry->start = src - text; // use offset from start of text buffer
+ }
+ u_type = (u_type & ~UNDO_USE_SPOS);
+#else
+ undo_entry->start = src - text;
+#endif
+ undo_entry->u_type = u_type;
+
+ // Push it on undo stack
+ undo_entry->prev = undo_stack_tail;
+ undo_stack_tail = undo_entry;
+ modified_count++;
+}
+
+static void undo_pop(void) // Undo the last operation
+{
+ int repeat;
+ char *u_start, *u_end;
+ struct undo_object *undo_entry;
+
+ // Commit pending undo queue before popping (should be unnecessary)
+ undo_queue_commit();
+
+ undo_entry = undo_stack_tail;
+ // Check for an empty undo stack
+ if (!undo_entry) {
+ status_line("Already at oldest change");
+ return;
+ }
+
+ switch (undo_entry->u_type) {
+ case UNDO_DEL:
+ case UNDO_DEL_CHAIN:
+ // make hole and put in text that was deleted; deallocate text
+ u_start = text + undo_entry->start;
+ text_hole_make(u_start, undo_entry->length);
+ memcpy(u_start, undo_entry->undo_text, undo_entry->length);
+ status_line("Undo [%d] %s %d chars at position %d",
+ modified_count, "restored",
+ undo_entry->length, undo_entry->start
+ );
+ break;
+ case UNDO_INS:
+ case UNDO_INS_CHAIN:
+ // delete what was inserted
+ u_start = undo_entry->start + text;
+ u_end = u_start - 1 + undo_entry->length;
+ text_hole_delete(u_start, u_end, NO_UNDO);
+ status_line("Undo [%d] %s %d chars at position %d",
+ modified_count, "deleted",
+ undo_entry->length, undo_entry->start
+ );
+ break;
+ }
+ repeat = 0;
+ switch (undo_entry->u_type) {
+ // If this is the end of a chain, lower modification count and refresh display
+ case UNDO_DEL:
+ case UNDO_INS:
+ dot = (text + undo_entry->start);
+ refresh(FALSE);
+ break;
+ case UNDO_DEL_CHAIN:
+ case UNDO_INS_CHAIN:
+ repeat = 1;
+ break;
+ }
+ // Deallocate the undo object we just processed
+ undo_stack_tail = undo_entry->prev;
+ free(undo_entry);
+ modified_count--;
+ // For chained operations, continue popping all the way down the chain.
+ if (repeat) {
+ undo_pop(); // Follow the undo chain if one exists
+ }
+}
+
+#if ENABLE_FEATURE_VI_UNDO_QUEUE
+static void undo_queue_commit(void) // Flush any queued objects to the undo stack
+{
+ // Pushes the queue object onto the undo stack
+ if (undo_q > 0) {
+ // Deleted character undo events grow from the end
+ undo_push(undo_queue + CONFIG_FEATURE_VI_UNDO_QUEUE_MAX - undo_q,
+ undo_q,
+ (undo_queue_state | UNDO_USE_SPOS)
+ );
+ undo_queue_state = UNDO_EMPTY;
+ undo_q = 0;
+ }
+}
+#endif
+
+#endif /* ENABLE_FEATURE_VI_UNDO */
+
// open a hole in text[]
// might reallocate text[]! use p += text_hole_make(p, ...),
// and be careful to not use pointers into potentially freed text[]!
@@ -2094,12 +2482,12 @@ static uintptr_t text_hole_make(char *p, int size) // at "p", make a 'size' byte
}
memmove(p + size, p, end - size - p);
memset(p, ' ', size); // clear new hole
- file_modified++;
return bias;
}
// close a hole in text[]
-static char *text_hole_delete(char *p, char *q) // delete "p" through "q", inclusive
+// "undo" value indicates if this operation should be undo-able
+static char *text_hole_delete(char *p, char *q, int undo) // delete "p" through "q", inclusive
{
char *src, *dest;
int cnt, hole_size;
@@ -2114,10 +2502,29 @@ static char *text_hole_delete(char *p, char *q) // delete "p" through "q", inclu
}
hole_size = q - p + 1;
cnt = end - src;
+#if ENABLE_FEATURE_VI_UNDO
+ switch (undo) {
+ case NO_UNDO:
+ break;
+ case ALLOW_UNDO:
+ undo_push(p, hole_size, UNDO_DEL);
+ break;
+ case ALLOW_UNDO_CHAIN:
+ undo_push(p, hole_size, UNDO_DEL_CHAIN);
+ break;
+# if ENABLE_FEATURE_VI_UNDO_QUEUE
+ case ALLOW_UNDO_QUEUED:
+ undo_push(p, hole_size, UNDO_DEL_QUEUED);
+ break;
+# endif
+ }
+ modified_count--;
+#endif
if (src < text || src > end)
goto thd0;
if (dest < text || dest >= end)
goto thd0;
+ modified_count++;
if (src >= end)
goto thd_atend; // just delete the end of the buffer
memmove(dest, src, cnt);
@@ -2127,7 +2534,6 @@ static char *text_hole_delete(char *p, char *q) // delete "p" through "q", inclu
dest = end - 1; // make sure dest in below end-1
if (end <= text)
dest = end = text; // keep pointers valid
- file_modified++;
thd0:
return dest;
}
@@ -2135,7 +2541,7 @@ static char *text_hole_delete(char *p, char *q) // delete "p" through "q", inclu
// copy text into register, then delete text.
// if dist <= 0, do not include, or go past, a NewLine
//
-static char *yank_delete(char *start, char *stop, int dist, int yf)
+static char *yank_delete(char *start, char *stop, int dist, int yf, int undo)
{
char *p;
@@ -2164,7 +2570,7 @@ static char *yank_delete(char *start, char *stop, int dist, int yf)
text_yank(start, stop, YDreg);
#endif
if (yf == YANKDEL) {
- p = text_hole_delete(start, stop);
+ p = text_hole_delete(start, stop, undo);
} // delete lines
return p;
}
@@ -2176,7 +2582,7 @@ static void show_help(void)
"\n\tPattern searches with / and ?"
#endif
#if ENABLE_FEATURE_VI_DOT_CMD
- "\n\tLast command repeat with \'.\'"
+ "\n\tLast command repeat with ."
#endif
#if ENABLE_FEATURE_VI_YANKMARK
"\n\tLine marking with 'x"
@@ -2187,7 +2593,7 @@ static void show_help(void)
//redundant: usage text says this too: "\n\tReadonly with -R command line arg"
#endif
#if ENABLE_FEATURE_VI_SET
- "\n\tSome colon mode commands with \':\'"
+ "\n\tSome colon mode commands with :"
#endif
#if ENABLE_FEATURE_VI_SETOPTS
"\n\tSettable options with \":set\""
@@ -2230,12 +2636,22 @@ static void end_cmd_q(void)
|| ENABLE_FEATURE_VI_CRASHME
// might reallocate text[]! use p += string_insert(p, ...),
// and be careful to not use pointers into potentially freed text[]!
-static uintptr_t string_insert(char *p, const char *s) // insert the string at 'p'
+static uintptr_t string_insert(char *p, const char *s, int undo) // insert the string at 'p'
{
uintptr_t bias;
int i;
i = strlen(s);
+#if ENABLE_FEATURE_VI_UNDO
+ switch (undo) {
+ case ALLOW_UNDO:
+ undo_push(p, i, UNDO_INS);
+ break;
+ case ALLOW_UNDO_CHAIN:
+ undo_push(p, i, UNDO_INS_CHAIN);
+ break;
+ }
+#endif
bias = text_hole_make(p, i);
p += bias;
memcpy(p, s, i);
@@ -2388,6 +2804,9 @@ static int mysleep(int hund) // sleep for 'hund' 1/100 seconds or stdin ready
{
struct pollfd pfd[1];
+ if (hund != 0)
+ fflush_all();
+
pfd[0].fd = STDIN_FILENO;
pfd[0].events = POLLIN;
return safe_poll(pfd, 1, hund*10) > 0;
@@ -2484,62 +2903,50 @@ static char *get_input_line(const char *prompt)
#undef buf
}
-static int file_size(const char *fn) // what is the byte size of "fn"
-{
- struct stat st_buf;
- int cnt;
-
- cnt = -1;
- if (fn && stat(fn, &st_buf) == 0) // see if file exists
- cnt = (int) st_buf.st_size;
- return cnt;
-}
-
// might reallocate text[]!
-static int file_insert(const char *fn, char *p, int update_ro_status)
+static int file_insert(const char *fn, char *p, int initial)
{
int cnt = -1;
int fd, size;
struct stat statbuf;
- /* Validate file */
- if (stat(fn, &statbuf) < 0) {
- status_line_bold("\"%s\" %s", fn, strerror(errno));
- goto fi0;
- }
- if (!S_ISREG(statbuf.st_mode)) {
- // This is not a regular file
- status_line_bold("\"%s\" Not a regular file", fn);
- goto fi0;
- }
- if (p < text || p > end) {
- status_line_bold("Trying to insert file outside of memory");
- goto fi0;
- }
+ if (p < text)
+ p = text;
+ if (p > end)
+ p = end;
- // read file to buffer
fd = open(fn, O_RDONLY);
if (fd < 0) {
- status_line_bold("\"%s\" %s", fn, strerror(errno));
- goto fi0;
+ if (!initial)
+ status_line_bold_errno(fn);
+ return cnt;
+ }
+
+ /* Validate file */
+ if (fstat(fd, &statbuf) < 0) {
+ status_line_bold_errno(fn);
+ goto fi;
+ }
+ if (!S_ISREG(statbuf.st_mode)) {
+ status_line_bold("'%s' is not a regular file", fn);
+ goto fi;
}
- size = statbuf.st_size;
+ size = (statbuf.st_size < INT_MAX ? (int)statbuf.st_size : INT_MAX);
p += text_hole_make(p, size);
- cnt = safe_read(fd, p, size);
+ cnt = full_read(fd, p, size);
if (cnt < 0) {
- status_line_bold("\"%s\" %s", fn, strerror(errno));
- p = text_hole_delete(p, p + size - 1); // un-do buffer insert
+ status_line_bold_errno(fn);
+ p = text_hole_delete(p, p + size - 1, NO_UNDO); // un-do buffer insert
} else if (cnt < size) {
- // There was a partial read, shrink unused space text[]
- p = text_hole_delete(p + cnt, p + (size - cnt) - 1); // un-do buffer insert
- status_line_bold("can't read all of file \"%s\"", fn);
+ // There was a partial read, shrink unused space
+ p = text_hole_delete(p + cnt, p + size - 1, NO_UNDO);
+ status_line_bold("can't read '%s'", fn);
}
- if (cnt >= size)
- file_modified++;
+ fi:
close(fd);
- fi0:
+
#if ENABLE_FEATURE_VI_READONLY
- if (update_ro_status
+ if (initial
&& ((access(fn, W_OK) < 0) ||
/* root will always have access()
* so we check fileperms too */
@@ -2564,15 +2971,15 @@ static int file_write(char *fn, char *first, char *last)
* but instead ftruncate() it _after_ successful write.
* Might reduce amount of data lost on power fail etc.
*/
- fd = open(fn, (O_WRONLY | O_CREAT | O_TRUNC), 0666); // zzz
+ fd = open(fn, (O_WRONLY | O_CREAT), 0666);
if (fd < 0)
return -1;
cnt = last - first + 1;
charcnt = full_write(fd, first, cnt);
-/* ftruncate(fd, charcnt); buggy for us - zzz */
+ ftruncate(fd, charcnt);
if (charcnt == cnt) {
// good write
- //file_modified = FALSE;
+ //modified_count = FALSE;
} else {
charcnt = 0;
}
@@ -2592,118 +2999,67 @@ static int file_write(char *fn, char *first, char *last)
// 23,0 ... 23,79 <- status line
//----- Move the cursor to row x col (count from 0, not 1) -------
-static void place_cursor(int row, int col, int optimize)
+static void place_cursor(int row, int col)
{
- char cm1[sizeof(CMrc) + sizeof(int)*3 * 2];
-#if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR
- enum {
- SZ_UP = sizeof(CMup),
- SZ_DN = sizeof(CMdown),
- SEQ_SIZE = SZ_UP > SZ_DN ? SZ_UP : SZ_DN,
- };
- char cm2[SEQ_SIZE * 5 + 32]; // bigger than worst case size
-#endif
- char *cm;
+ char cm1[sizeof(ESC_SET_CURSOR_POS) + sizeof(int)*3 * 2];
if (row < 0) row = 0;
if (row >= rows) row = rows - 1;
if (col < 0) col = 0;
if (col >= columns) col = columns - 1;
- //----- 1. Try the standard terminal ESC sequence
- sprintf(cm1, CMrc, row + 1, col + 1);
- cm = cm1;
-
-#if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR
- if (optimize && col < 16) {
- char *screenp;
- int Rrow = last_row;
- int diff = Rrow - row;
-
- if (diff < -5 || diff > 5)
- goto skip;
-
- //----- find the minimum # of chars to move cursor -------------
- //----- 2. Try moving with discreet chars (Newline, [back]space, ...)
- cm2[0] = '\0';
-
- // move to the correct row
- while (row < Rrow) {
- // the cursor has to move up
- strcat(cm2, CMup);
- Rrow--;
- }
- while (row > Rrow) {
- // the cursor has to move down
- strcat(cm2, CMdown);
- Rrow++;
- }
-
- // now move to the correct column
- strcat(cm2, "\r"); // start at col 0
- // just send out orignal source char to get to correct place
- screenp = &screen[row * columns]; // start of screen line
- strncat(cm2, screenp, col);
-
- // pick the shortest cursor motion to send out
- if (strlen(cm2) < strlen(cm)) {
- cm = cm2;
- }
- skip: ;
- }
- last_row = row;
-#endif /* FEATURE_VI_OPTIMIZE_CURSOR */
- write1(cm);
+ sprintf(cm1, ESC_SET_CURSOR_POS, row + 1, col + 1);
+ write1(cm1);
}
//----- Erase from cursor to end of line -----------------------
static void clear_to_eol(void)
{
- write1(Ceol); // Erase from cursor to end of line
+ write1(ESC_CLEAR2EOL);
}
static void go_bottom_and_clear_to_eol(void)
{
- place_cursor(rows - 1, 0, FALSE); // go to bottom of screen
- clear_to_eol(); // erase to end of line
+ place_cursor(rows - 1, 0);
+ clear_to_eol();
}
//----- Erase from cursor to end of screen -----------------------
static void clear_to_eos(void)
{
- write1(Ceos); // Erase from cursor to end of screen
+ write1(ESC_CLEAR2EOS);
}
//----- Start standout mode ------------------------------------
-static void standout_start(void) // send "start reverse video" sequence
+static void standout_start(void)
{
- write1(SOs); // Start reverse video mode
+ write1(ESC_BOLD_TEXT);
}
//----- End standout mode --------------------------------------
-static void standout_end(void) // send "end reverse video" sequence
+static void standout_end(void)
{
- write1(SOn); // End reverse video mode
+ write1(ESC_NORM_TEXT);
}
//----- Flash the screen --------------------------------------
static void flash(int h)
{
- standout_start(); // send "start reverse video" sequence
+ standout_start();
redraw(TRUE);
mysleep(h);
- standout_end(); // send "end reverse video" sequence
+ standout_end();
redraw(TRUE);
}
-static void Indicate_Error(void)
+static void indicate_error(void)
{
#if ENABLE_FEATURE_VI_CRASHME
if (crashme > 0)
return; // generate a random command
#endif
if (!err_method) {
- write1(bell); // send out a bell character
+ write1(ESC_BELL);
} else {
flash(10);
}
@@ -2749,7 +3105,7 @@ static void show_status_line(void)
}
have_status_msg = 0;
}
- place_cursor(crow, ccol, FALSE); // put cursor back in correct place
+ place_cursor(crow, ccol); // put cursor back in correct place
}
fflush_all();
}
@@ -2761,12 +3117,17 @@ static void status_line_bold(const char *format, ...)
va_list args;
va_start(args, format);
- strcpy(status_buffer, SOs); // Terminal standout mode on
- vsprintf(status_buffer + sizeof(SOs)-1, format, args);
- strcat(status_buffer, SOn); // Terminal standout mode off
+ strcpy(status_buffer, ESC_BOLD_TEXT);
+ vsprintf(status_buffer + sizeof(ESC_BOLD_TEXT)-1, format, args);
+ strcat(status_buffer, ESC_NORM_TEXT);
va_end(args);
- have_status_msg = 1 + sizeof(SOs) + sizeof(SOn) - 2;
+ have_status_msg = 1 + sizeof(ESC_BOLD_TEXT) + sizeof(ESC_NORM_TEXT) - 2;
+}
+
+static void status_line_bold_errno(const char *fn)
+{
+ status_line_bold("'%s' %s", fn, strerror(errno));
}
// format status buffer
@@ -2798,8 +3159,8 @@ static void print_literal(char *buf, const char *s)
c = *s;
c_is_no_print = (c & 0x80) && !Isprint(c);
if (c_is_no_print) {
- strcpy(d, SOn);
- d += sizeof(SOn)-1;
+ strcpy(d, ESC_NORM_TEXT);
+ d += sizeof(ESC_NORM_TEXT)-1;
c = '.';
}
if (c < ' ' || c == 0x7f) {
@@ -2811,8 +3172,8 @@ static void print_literal(char *buf, const char *s)
*d++ = c;
*d = '\0';
if (c_is_no_print) {
- strcpy(d, SOs);
- d += sizeof(SOs)-1;
+ strcpy(d, ESC_BOLD_TEXT);
+ d += sizeof(ESC_BOLD_TEXT)-1;
}
if (*s == '\n') {
*d++ = '$';
@@ -2840,7 +3201,7 @@ static int format_edit_status(void)
int cur, percent, ret, trunc_at;
- // file_modified is now a counter rather than a flag. this
+ // modified_count is now a counter rather than a flag. this
// helps reduce the amount of line counting we need to do.
// (this will cause a mis-reporting of modified status
// once every MAXINT editing operations.)
@@ -2850,11 +3211,12 @@ static int format_edit_status(void)
// we're on, then we shouldn't have to do this count_lines()
cur = count_lines(text, dot);
- // reduce counting -- the total lines can't have
- // changed if we haven't done any edits.
- if (file_modified != last_file_modified) {
+ // count_lines() is expensive.
+ // Call it only if something was changed since last time
+ // we were here:
+ if (modified_count != last_modified_count) {
tot = cur + count_lines(dot, end - 1) - 1;
- last_file_modified = file_modified;
+ last_modified_count = modified_count;
}
// current line percent
@@ -2881,7 +3243,7 @@ static int format_edit_status(void)
#if ENABLE_FEATURE_VI_READONLY
(readonly_mode ? " [Readonly]" : ""),
#endif
- (file_modified ? " [Modified]" : ""),
+ (modified_count ? " [Modified]" : ""),
cur, tot, percent);
if (ret >= 0 && ret < trunc_at)
@@ -2894,8 +3256,8 @@ static int format_edit_status(void)
//----- Force refresh of all Lines -----------------------------
static void redraw(int full_screen)
{
- place_cursor(0, 0, FALSE); // put cursor in correct place
- clear_to_eos(); // tell terminal to erase display
+ place_cursor(0, 0);
+ clear_to_eos();
screen_erase(); // erase the internal screen buffer
last_status_cksum = 0; // force status update
refresh(full_screen); // this will redraw the entire display
@@ -2994,7 +3356,7 @@ static void refresh(int full_screen)
tp = t + 1;
}
- // see if there are any changes between vitual screen and out_buf
+ // see if there are any changes between virtual screen and out_buf
changed = FALSE; // assume no change
cs = 0;
ce = columns - 1;
@@ -3031,26 +3393,17 @@ static void refresh(int full_screen)
if (cs < 0) cs = 0;
if (ce > columns - 1) ce = columns - 1;
if (cs > ce) { cs = 0; ce = columns - 1; }
- // is there a change between vitual screen and out_buf
+ // is there a change between virtual screen and out_buf
if (changed) {
// copy changed part of buffer to virtual screen
memcpy(sp+cs, out_buf+cs, ce-cs+1);
-
- // move cursor to column of first change
- //if (offset != old_offset) {
- // // place_cursor is still too stupid
- // // to handle offsets correctly
- // place_cursor(li, cs, FALSE);
- //} else {
- place_cursor(li, cs, TRUE);
- //}
-
+ place_cursor(li, cs);
// write line out to terminal
fwrite(&sp[cs], ce - cs + 1, 1, stdout);
}
}
- place_cursor(crow, ccol, TRUE);
+ place_cursor(crow, ccol);
old_offset = offset;
#undef old_offset
@@ -3115,11 +3468,12 @@ static void do_cmd(int c)
if (*dot == '\n') {
// don't Replace past E-o-l
cmd_mode = 1; // convert to insert
+ undo_queue_commit();
} else {
if (1 <= c || Isprint(c)) {
if (c != 27)
- dot = yank_delete(dot, dot, 0, YANKDEL); // delete char
- dot = char_insert(dot, c); // insert new char
+ dot = yank_delete(dot, dot, 0, YANKDEL, ALLOW_UNDO); // delete char
+ dot = char_insert(dot, c, ALLOW_UNDO_CHAIN); // insert new char
}
goto dc1;
}
@@ -3129,7 +3483,7 @@ static void do_cmd(int c)
if (c == KEYCODE_INSERT) goto dc5;
// insert the char c at "dot"
if (1 <= c || Isprint(c)) {
- dot = char_insert(dot, c);
+ dot = char_insert(dot, c, ALLOW_UNDO_QUEUED);
}
goto dc1;
}
@@ -3175,7 +3529,6 @@ static void do_cmd(int c)
//case ']': // ]-
//case '_': // _-
//case '`': // `-
- //case 'u': // u- FIXME- there is no undo
//case 'v': // v-
default: // unrecognized command
buf[0] = c;
@@ -3220,9 +3573,9 @@ static void do_cmd(int c)
break;
case 12: // ctrl-L force redraw whole screen
case 18: // ctrl-R force redraw
- place_cursor(0, 0, FALSE); // put cursor in correct place
- clear_to_eos(); // tel terminal to erase display
- mysleep(10);
+ place_cursor(0, 0);
+ clear_to_eos();
+ //mysleep(10); // why???
screen_erase(); // erase the internal screen buffer
last_status_cksum = 0; // force status update
refresh(TRUE); // this will redraw the entire display
@@ -3242,8 +3595,9 @@ static void do_cmd(int c)
break;
case 27: // esc
if (cmd_mode == 0)
- indicate_error(c);
+ indicate_error();
cmd_mode = 0; // stop insrting
+ undo_queue_commit();
end_cmd_q();
last_status_cksum = 0; // force status update
break;
@@ -3260,7 +3614,7 @@ static void do_cmd(int c)
if ((unsigned)c1 <= 25) { // a-z?
YDreg = c1;
} else {
- indicate_error(c);
+ indicate_error();
}
break;
case '\'': // '- goto a specific mark
@@ -3278,7 +3632,7 @@ static void do_cmd(int c)
dot_begin(); // go to B-o-l
dot_skip_over_ws();
} else {
- indicate_error(c);
+ indicate_error();
}
break;
case 'm': // m- Mark a line
@@ -3291,7 +3645,7 @@ static void do_cmd(int c)
// remember the line
mark[c1] = dot;
} else {
- indicate_error(c);
+ indicate_error();
}
break;
case 'P': // P- Put register before
@@ -3318,20 +3672,25 @@ static void do_cmd(int c)
if (c == 'p')
dot_right(); // move to right, can move to NL
}
- string_insert(dot, p); // insert the string
+ string_insert(dot, p, ALLOW_UNDO); // insert the string
end_cmd_q(); // stop adding to q
break;
case 'U': // U- Undo; replace current line with original version
if (reg[Ureg] != NULL) {
p = begin_line(dot);
q = end_line(dot);
- p = text_hole_delete(p, q); // delete cur line
- p += string_insert(p, reg[Ureg]); // insert orig line
+ p = text_hole_delete(p, q, ALLOW_UNDO); // delete cur line
+ p += string_insert(p, reg[Ureg], ALLOW_UNDO_CHAIN); // insert orig line
dot = p;
dot_skip_over_ws();
}
break;
#endif /* FEATURE_VI_YANKMARK */
+#if ENABLE_FEATURE_VI_UNDO
+ case 'u': // u- undo last operation
+ undo_pop();
+ break;
+#endif
case '$': // $- goto end of line
case KEYCODE_END: // Cursor Key End
for (;;) {
@@ -3347,7 +3706,7 @@ static void do_cmd(int c)
// we found half of a pair
p = find_pair(q, *q);
if (p == NULL) {
- indicate_error(c);
+ indicate_error();
} else {
dot = p;
}
@@ -3355,7 +3714,7 @@ static void do_cmd(int c)
}
}
if (*q == '\n')
- indicate_error(c);
+ indicate_error();
break;
case 'f': // f- forward to a user specified char
last_forward_char = get_one_char(); // get the search char
@@ -3411,7 +3770,7 @@ static void do_cmd(int c)
buf[1] = '\0';
q = get_input_line(buf); // get input line- use "status line"
if (q[0] && !q[1]) {
- if (last_search_pattern)
+ if (last_search_pattern[0])
last_search_pattern[0] = c;
goto dc3; // if no pat re-use old pat
}
@@ -3484,7 +3843,7 @@ static void do_cmd(int c)
}
break;
#endif /* FEATURE_VI_SEARCH */
- case '0': // 0- goto begining of line
+ case '0': // 0- goto beginning of line
case '1': // 1-
case '2': // 2-
case '3': // 3-
@@ -3502,57 +3861,14 @@ static void do_cmd(int c)
break;
case ':': // :- the colon mode commands
p = get_input_line(":"); // get input line- use "status line"
-#if ENABLE_FEATURE_VI_COLON
colon(p); // execute the command
-#else
- if (*p == ':')
- p++; // move past the ':'
- cnt = strlen(p);
- if (cnt <= 0)
- break;
- if (strncmp(p, "quit", cnt) == 0
- || strncmp(p, "q!", cnt) == 0 // delete lines
- ) {
- if (file_modified && p[1] != '!') {
- status_line_bold("No write since last change (:%s! overrides)", p);
- } else {
- editing = 0;
- }
- } else if (strncmp(p, "write", cnt) == 0
- || strncmp(p, "wq", cnt) == 0
- || strncmp(p, "wn", cnt) == 0
- || (p[0] == 'x' && !p[1])
- ) {
- cnt = file_write(current_filename, text, end - 1);
- if (cnt < 0) {
- if (cnt == -1)
- status_line_bold("Write error: %s", strerror(errno));
- } else {
- file_modified = 0;
- last_file_modified = -1;
- status_line("\"%s\" %dL, %dC", current_filename, count_lines(text, end - 1), cnt);
- if (p[0] == 'x' || p[1] == 'q' || p[1] == 'n'
- || p[0] == 'X' || p[1] == 'Q' || p[1] == 'N'
- ) {
- editing = 0;
- }
- }
- } else if (strncmp(p, "file", cnt) == 0) {
- last_status_cksum = 0; // force status update
- } else if (sscanf(p, "%d", &j) > 0) {
- dot = find_line(j); // go to line # j
- dot_skip_over_ws();
- } else { // unrecognized cmd
- not_implemented(p);
- }
-#endif /* !FEATURE_VI_COLON */
break;
case '<': // <- Left shift something
case '>': // >- Right shift something
cnt = count_lines(text, dot); // remember what line we are on
c1 = get_one_char(); // get the type of thing to delete
find_range(&p, &q, c1);
- yank_delete(p, q, 1, YANKONLY); // save copy before change
+ yank_delete(p, q, 1, YANKONLY, NO_UNDO); // save copy before change
p = begin_line(p);
q = end_line(q);
i = count_lines(p, q); // # of lines we are shifting
@@ -3561,16 +3877,16 @@ static void do_cmd(int c)
// shift left- remove tab or 8 spaces
if (*p == '\t') {
// shrink buffer 1 char
- text_hole_delete(p, p);
+ text_hole_delete(p, p, NO_UNDO);
} else if (*p == ' ') {
// we should be calculating columns, not just SPACE
for (j = 0; *p == ' ' && j < tabstop; j++) {
- text_hole_delete(p, p);
+ text_hole_delete(p, p, NO_UNDO);
}
}
} else if (c == '>') {
// shift right -- add tab or 8 spaces
- char_insert(p, '\t');
+ char_insert(p, '\t', ALLOW_UNDO);
}
}
dot = find_line(cnt); // what line were we on
@@ -3605,7 +3921,7 @@ static void do_cmd(int c)
save_dot = dot;
dot = dollar_line(dot); // move to before NL
// copy text into a register and delete
- dot = yank_delete(save_dot, dot, 0, YANKDEL); // delete to e-o-l
+ dot = yank_delete(save_dot, dot, 0, YANKDEL, ALLOW_UNDO); // delete to e-o-l
if (c == 'C')
goto dc_i; // start inserting
#if ENABLE_FEATURE_VI_DOT_CMD
@@ -3650,15 +3966,22 @@ static void do_cmd(int c)
case KEYCODE_INSERT: // Cursor Key Insert
dc_i:
cmd_mode = 1; // start inserting
+ undo_queue_commit(); // commit queue when cmd_mode changes
break;
case 'J': // J- join current and next lines together
do {
dot_end(); // move to NL
if (dot < end - 1) { // make sure not last char in text[]
+#if ENABLE_FEATURE_VI_UNDO
+ undo_push(dot, 1, UNDO_DEL);
*dot++ = ' '; // replace NL with space
- file_modified++;
+ undo_push((dot - 1), 1, UNDO_INS_CHAIN);
+#else
+ *dot++ = ' ';
+ modified_count++;
+#endif
while (isblank(*dot)) { // delete leading WS
- dot_delete();
+ text_hole_delete(dot, dot, ALLOW_UNDO_CHAIN);
}
}
} while (--cmdcnt > 0);
@@ -3687,10 +4010,10 @@ static void do_cmd(int c)
dot_prev();
case 'o': // o- open a empty line below; Yes, I know it is in the middle of the "if (..."
dot_end();
- dot = char_insert(dot, '\n');
+ dot = char_insert(dot, '\n', ALLOW_UNDO);
} else {
dot_begin(); // 0
- dot = char_insert(dot, '\n'); // i\n ESC
+ dot = char_insert(dot, '\n', ALLOW_UNDO); // i\n ESC
dot_prev(); // -
}
goto dc_i;
@@ -3698,10 +4021,12 @@ static void do_cmd(int c)
case 'R': // R- continuous Replace char
dc5:
cmd_mode = 2;
+ undo_queue_commit();
break;
case KEYCODE_DELETE:
- c = 'x';
- // fall through
+ if (dot < end - 1)
+ dot = yank_delete(dot, dot, 1, YANKDEL, ALLOW_UNDO);
+ break;
case 'X': // X- delete char before dot
case 'x': // x- delete the current char
case 's': // s- substitute the current char
@@ -3712,7 +4037,7 @@ static void do_cmd(int c)
if (dot[dir] != '\n') {
if (c == 'X')
dot--; // delete prev char
- dot = yank_delete(dot, dot, 0, YANKDEL); // delete char
+ dot = yank_delete(dot, dot, 0, YANKDEL, ALLOW_UNDO); // delete char
}
} while (--cmdcnt > 0);
end_cmd_q(); // stop adding to q
@@ -3723,12 +4048,12 @@ static void do_cmd(int c)
// ZZ means to save file (if necessary), then exit
c1 = get_one_char();
if (c1 != 'Z') {
- indicate_error(c);
+ indicate_error();
break;
}
- if (file_modified) {
+ if (modified_count) {
if (ENABLE_FEATURE_VI_READONLY && readonly_mode) {
- status_line_bold("\"%s\" File is read only", current_filename);
+ status_line_bold("'%s' is read only", current_filename);
break;
}
cnt = file_write(current_filename, text, end - 1);
@@ -3783,6 +4108,7 @@ static void do_cmd(int c)
c1 = get_one_char(); // get the type of thing to delete
// determine range, and whether it spans lines
ml = find_range(&p, &q, c1);
+ place_cursor(0, 0);
if (c1 == 27) { // ESC- user changed mind and wants out
c = c1 = 27; // Escape- do nothing
} else if (strchr("wW", c1)) {
@@ -3794,23 +4120,23 @@ static void do_cmd(int c)
q--;
}
}
- dot = yank_delete(p, q, ml, yf); // delete word
+ dot = yank_delete(p, q, ml, yf, ALLOW_UNDO); // delete word
} else if (strchr("^0bBeEft%$ lh\b\177", c1)) {
// partial line copy text into a register and delete
- dot = yank_delete(p, q, ml, yf); // delete word
+ dot = yank_delete(p, q, ml, yf, ALLOW_UNDO); // delete word
} else if (strchr("cdykjHL+-{}\r\n", c1)) {
// whole line copy text into a register and delete
- dot = yank_delete(p, q, ml, yf); // delete lines
+ dot = yank_delete(p, q, ml, yf, ALLOW_UNDO); // delete lines
whole = 1;
} else {
// could not recognize object
c = c1 = 27; // error-
ml = 0;
- indicate_error(c);
+ indicate_error();
}
if (ml && whole) {
if (c == 'c') {
- dot = char_insert(dot, '\n');
+ dot = char_insert(dot, '\n', ALLOW_UNDO_CHAIN);
// on the last line of file don't move to prev line
if (whole && dot != (end-1)) {
dot_prev();
@@ -3856,8 +4182,14 @@ static void do_cmd(int c)
case 'r': // r- replace the current char with user input
c1 = get_one_char(); // get the replacement char
if (*dot != '\n') {
+#if ENABLE_FEATURE_VI_UNDO
+ undo_push(dot, 1, UNDO_DEL);
+ *dot = c1;
+ undo_push(dot, 1, UNDO_INS_CHAIN);
+#else
*dot = c1;
- file_modified++;
+ modified_count++;
+#endif
}
end_cmd_q(); // stop adding to q
break;
@@ -3897,13 +4229,25 @@ static void do_cmd(int c)
break;
case '~': // ~- flip the case of letters a-z -> A-Z
do {
+#if ENABLE_FEATURE_VI_UNDO
if (islower(*dot)) {
+ undo_push(dot, 1, UNDO_DEL);
*dot = toupper(*dot);
- file_modified++;
+ undo_push(dot, 1, UNDO_INS_CHAIN);
} else if (isupper(*dot)) {
+ undo_push(dot, 1, UNDO_DEL);
*dot = tolower(*dot);
- file_modified++;
+ undo_push(dot, 1, UNDO_INS_CHAIN);
}
+#else
+ if (islower(*dot)) {
+ *dot = toupper(*dot);
+ modified_count++;
+ } else if (isupper(*dot)) {
+ *dot = tolower(*dot);
+ modified_count++;
+ }
+#endif
dot_right();
} while (--cmdcnt > 0);
end_cmd_q(); // stop adding to q
@@ -3933,7 +4277,7 @@ static void do_cmd(int c)
dc1:
// if text[] just became empty, add back an empty line
if (end == text) {
- char_insert(text, '\n'); // start empty buf with dummy line
+ char_insert(text, '\n', NO_UNDO); // start empty buf with dummy line
dot = text;
}
// it is OK for dot to exactly equal to end, otherwise check dot validity
@@ -4141,7 +4485,7 @@ static void crash_test()
if (msg[0]) {
printf("\n\n%d: \'%c\' %s\n\n\n%s[Hit return to continue]%s",
- totalcmds, last_input_char, msg, SOs, SOn);
+ totalcmds, last_input_char, msg, ESC_BOLD_TEXT, ESC_NORM_TEXT);
fflush_all();
while (safe_read(STDIN_FILENO, d, 1) > 0) {
if (d[0] == '\n' || d[0] == '\r')
diff --git a/release/src/router/busybox/examples/android-build b/release/src/router/busybox/examples/android-build
index 89f3b637ab..123ba966ec 100755
--- a/release/src/router/busybox/examples/android-build
+++ b/release/src/router/busybox/examples/android-build
@@ -29,4 +29,6 @@ else
LDLIBS="dl m c gcc"
fi
+# It's possible with newer version
+# you need to use CFLAGS_busybox instead of EXTRA_LDFLAGS below:
make EXTRA_LDFLAGS="$LDFLAGS" LDLIBS="$LDLIBS" "$@"
diff --git a/release/src/router/busybox/examples/depmod.pl b/release/src/router/busybox/examples/depmod.pl
index 86adfca392..2f21d3e559 100755
--- a/release/src/router/busybox/examples/depmod.pl
+++ b/release/src/router/busybox/examples/depmod.pl
@@ -118,7 +118,7 @@ warn "**** Finished locating modules\n" if $verbose;
foreach my $obj ( @liblist ){
# turn the input file name into a target tag name
my ($tgtname) = $obj =~ m-(/lib/modules/.*)$-;
-
+
warn "\nMODULE = $tgtname\n" if $verbose;
# get a list of symbols
@@ -205,7 +205,7 @@ foreach my $module ( keys %$mod ) {
if($kseries eq '2.4') {
print "$module:\t";
my @sorted = sort bydep keys %{$mod->{$module}};
- print join(" ",@sorted);
+ print join(" \\\n\t",@sorted);
print "\n\n";
} else {
my $shortmod = $module;
diff --git a/release/src/router/busybox/examples/inittab b/release/src/router/busybox/examples/inittab
index c4e0af5147..01ceaef25c 100644
--- a/release/src/router/busybox/examples/inittab
+++ b/release/src/router/busybox/examples/inittab
@@ -15,10 +15,7 @@
# the specified process to run on. The contents of this field are
# appended to "/dev/" and used as-is. There is no need for this field to
# be unique, although if it isn't you may have strange results. If this
-# field is left blank, it is completely ignored. Also note that if
-# BusyBox detects that a serial console is in use, then all entries
-# containing non-empty id fields will be ignored. BusyBox init does
-# nothing with utmp. We don't need no stinkin' utmp.
+# field is left blank, then the init's stdin/out will be used.
#
# <runlevels>: The runlevels field is completely ignored.
#
@@ -43,9 +40,6 @@
# ::shutdown:/sbin/swapoff -a
# ::shutdown:/bin/umount -a -r
# ::restart:/sbin/init
-#
-# if it detects that /dev/console is _not_ a serial console, it will
-# also run:
# tty2::askfirst:/bin/sh
# tty3::askfirst:/bin/sh
# tty4::askfirst:/bin/sh
diff --git a/release/src/router/busybox/examples/mdev.conf b/release/src/router/busybox/examples/mdev.conf
index cdbb4fcfea..51795694d9 100644
--- a/release/src/router/busybox/examples/mdev.conf
+++ b/release/src/router/busybox/examples/mdev.conf
@@ -7,8 +7,14 @@
# instead of the default 0:0 660.
#
# Syntax:
-# %s %d:%d %s
-# devicename_regex user:group mode
+# [-]devicename_regex user:group mode [=path]|[>path]|[!] [@|$|*cmd args...]
+# [-]$ENVVAR=regex user:group mode [=path]|[>path]|[!] [@|$|*cmd args...]
+# [-]@maj,min[-min2] user:group mode [=path]|[>path]|[!] [@|$|*cmd args...]
+#
+# [-]: do not stop on this match, continue reading mdev.conf
+# =: move, >: move and create a symlink
+# !: do not create device node
+# @|$|*: run@cmd if $ACTION=add, $cmd if $ACTION=remove, *cmd in all cases
null 0:0 666
zero 0:0 666
diff --git a/release/src/router/busybox/examples/mdev.conf.change_blockdev.sh b/release/src/router/busybox/examples/mdev.conf.change_blockdev.sh
new file mode 100755
index 0000000000..512e43fccc
--- /dev/null
+++ b/release/src/router/busybox/examples/mdev.conf.change_blockdev.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+# Seconds to try to reread partition table
+cnt=60
+
+exec </dev/null
+exec >"/tmp/${0##*/}.$$.out"
+exec 2>&1
+
+(
+echo "Running: $0"
+echo "Env:"
+env | sort
+
+while sleep 1; test $cnt != 0; do
+ echo "Trying to reread partition table on $DEVNAME ($cnt)"
+ : $((cnt--))
+ # If device node doesn't exist, it means the device was removed.
+ # Stop trying.
+ test -e "$DEVNAME" || { echo "$DEVNAME doesn't exist, aborting"; exit 1; }
+ #echo "$DEVNAME exists"
+ if blockdev --rereadpt "$DEVNAME"; then
+ echo "blockdev --rereadpt succeeded"
+ exit 0
+ fi
+ echo "blockdev --rereadpt failed, exit code: $?"
+done
+echo "Timed out"
+) &
diff --git a/release/src/router/busybox/examples/mdev_fat.conf b/release/src/router/busybox/examples/mdev_fat.conf
index df329b4b54..630d2700a2 100644
--- a/release/src/router/busybox/examples/mdev_fat.conf
+++ b/release/src/router/busybox/examples/mdev_fat.conf
@@ -7,15 +7,19 @@
# instead of the default 0:0 660.
#
# Syntax:
-# [-]devicename_regex user:group mode [>|=path] [@|$|*cmd args...]
+# [-][ENVVAR=regex;]...devicename_regex user:group mode [=path]|[>path]|[!] [@|$|*cmd args...]
+# [-][ENVVAR=regex;]...@maj,min[-min2] user:group mode [=path]|[>path]|[!] [@|$|*cmd args...]
+# [-]$ENVVAR=regex user:group mode [=path]|[>path]|[!] [@|$|*cmd args...]
#
+# [-]: do not stop on this match, continue reading mdev.conf
# =: move, >: move and create a symlink
-# @|$|*: run $cmd on delete, @cmd on create, *cmd on both
+# !: do not create device node
+# @|$|*: run cmd if $ACTION=remove, @cmd if $ACTION=add, *cmd in all cases
# support module loading on hotplug
$MODALIAS=.* root:root 660 @modprobe "$MODALIAS"
-# null may already exist; therefore ownership has to be changed with command
+# null may already exist; therefore mode has to be changed with command
null root:root 666 @chmod 666 $MDEV
zero root:root 666
full root:root 666
@@ -27,7 +31,7 @@ grsec root:root 660
kmem root:root 640
mem root:root 640
port root:root 640
-# console may already exist; therefore ownership has to be changed with command
+# console may already exist; therefore mode has to be changed with command
console root:tty 600 @chmod 600 $MDEV
ptmx root:tty 666
pty.* root:tty 660
@@ -49,7 +53,7 @@ sr[0-9]* root:cdrom 660 @ln -sf $MDEV cdrom
fd[0-9]* root:floppy 660
# net devices
--net/.* root:root 600 @nameif
+SUBSYSTEM=net;.* root:root 600 @nameif
tun[0-9]* root:root 600 =net/
tap[0-9]* root:root 600 =net/
@@ -59,6 +63,12 @@ control.* root:audio 660 =snd/
midi.* root:audio 660 =snd/
seq root:audio 660 =snd/
timer root:audio 660 =snd/
+# for kernels/mdevs which expose full path of alsa devices:
+snd/pcm.* root:audio 660
+snd/control.* root:audio 660
+snd/midi.* root:audio 660
+snd/seq root:audio 660
+snd/timer root:audio 660
adsp root:audio 660 >sound/
audio root:audio 660 >sound/
@@ -108,3 +118,33 @@ usbdev[0-9].[0-9]_.* root:root 660
# zaptel devices
zap(.*) root:dialout 660 =zap/%1
dahdi!(.*) root:dialout 660 =dahdi/%1
+
+# HTC Android
+# Attaching it via USB cable causes a flurry of activity:
+#
+# mdev[1271]: 48.639459 ACTION:add SUBSYSTEM:usb DEVNAME:bus/usb/001/009 DEVPATH:/devices/pci0000:00/0000:00:02.1/usb1/1-5
+# mdev[1271]: mknod bus/usb/001/009 (189,8) 20660 0:0
+# mdev[1272]: 48.642354 ACTION:add SUBSYSTEM:usb DEVNAME:(null) DEVPATH:/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0
+# mdev[1272]: running: modprobe "$MODALIAS"
+# mdev[1273]: 48.650078 ACTION:add SUBSYSTEM:scsi DEVNAME:(null) DEVPATH:/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0/host11
+# mdev[1274]: 48.651297 ACTION:add SUBSYSTEM:scsi_host DEVNAME:(null) DEVPATH:/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0/host11/scsi_host/host11
+# mdev[1275]: 49.649422 ACTION:add SUBSYSTEM:scsi DEVNAME:(null) DEVPATH:/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0/host11/target11:0:0
+# mdev[1276]: 49.650703 ACTION:add SUBSYSTEM:scsi DEVNAME:(null) DEVPATH:/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0/host11/target11:0:0/11:0:0:0
+# mdev[1276]: running: modprobe "$MODALIAS"
+# modprobe: module scsi:t-0x00 not found in modules.dep
+# mdev[1277]: 49.658002 ACTION:add SUBSYSTEM:scsi_disk DEVNAME:(null) DEVPATH:/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0/host11/target11:0:0/11:0:0:0/scsi_disk/11:0:0:0
+# mdev[1278]: 49.659244 ACTION:add SUBSYSTEM:scsi_device DEVNAME:(null) DEVPATH:/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0/host11/target11:0:0/11:0:0:0/scsi_device/11:0:0:
+# mdev[1279]: 49.660535 ACTION:add SUBSYSTEM:bsg DEVNAME:bsg/11:0:0:0 DEVPATH:/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0/host11/target11:0:0/11:0:0:0/bsg/11:0:0:0
+# mdev[1279]: mknod bsg/11:0:0:0 (253,1) 20660 0:0
+# mdev[1280]: 49.663516 ACTION:add SUBSYSTEM:bdi DEVNAME:(null) DEVPATH:/devices/virtual/bdi/8:16
+# mdev[1281]: 49.664748 ACTION:add SUBSYSTEM:block DEVNAME:sdb DEVPATH:/block/sdb
+# mdev[1281]: mknod sdb (8,16) 60660 0:0
+# mdev[1282]: 49.677597 ACTION:change SUBSYSTEM:block DEVNAME:sdb DEVPATH:/block/sdb
+# mdev[1283]: 50.692936 ACTION:change SUBSYSTEM:block DEVNAME:sdb DEVPATH:/block/sdb
+#
+# We are hooking to the last events. To avoid having two scripts running,
+# we check for DISK_MEDIA_CHANGE=1 (prev to last event has it,
+# and it's the _only_ difference in env for these two events as of kernel 3.7.7)
+# Unfortunately, there is no event for "user pressed [Turn USB storage on] btn"!
+# Script merely backgrounds and tries to rescan partition table for 1 minute:
+ACTION=change;SUBSYSTEM=block;DISK_MEDIA_CHANGE=1;.* 0:0 660 */etc/mdev.conf.change_blockdev.sh
diff --git a/release/src/router/busybox/examples/udhcp/sample.bound b/release/src/router/busybox/examples/udhcp/sample.bound
index bd3569c776..7c9d857e03 100755
--- a/release/src/router/busybox/examples/udhcp/sample.bound
+++ b/release/src/router/busybox/examples/udhcp/sample.bound
@@ -22,10 +22,14 @@ then
done
fi
-echo -n > $RESOLV_CONF
-[ -n "$domain" ] && echo domain $domain >> $RESOLV_CONF
-for i in $dns
-do
- echo adding dns $i
- echo nameserver $i >> $RESOLV_CONF
-done
+# Only replace resolv.conf is we have at least one DNS server
+if [ -n "$dns" ]
+then
+ echo -n > $RESOLV_CONF
+ [ -n "$domain" ] && echo domain $domain >> $RESOLV_CONF
+ for i in $dns
+ do
+ echo adding dns $i
+ echo nameserver $i >> $RESOLV_CONF
+ done
+fi
diff --git a/release/src/router/busybox/examples/udhcp/sample.renew b/release/src/router/busybox/examples/udhcp/sample.renew
index ea368fc9ef..4dce8486a6 100755
--- a/release/src/router/busybox/examples/udhcp/sample.renew
+++ b/release/src/router/busybox/examples/udhcp/sample.renew
@@ -22,10 +22,14 @@ then
done
fi
-echo -n > $RESOLV_CONF
-[ -n "$domain" ] && echo domain $domain >> $RESOLV_CONF
-for i in $dns
-do
- echo adding dns $i
- echo nameserver $i >> $RESOLV_CONF
-done
+# Only replace resolv.conf is we have at least one DNS server
+if [ -n "$dns" ]
+then
+ echo -n > $RESOLV_CONF
+ [ -n "$domain" ] && echo domain $domain >> $RESOLV_CONF
+ for i in $dns
+ do
+ echo adding dns $i
+ echo nameserver $i >> $RESOLV_CONF
+ done
+fi
diff --git a/release/src/router/busybox/examples/udhcp/simple.script b/release/src/router/busybox/examples/udhcp/simple.script
index 40ee738225..2a917eb6ce 100755
--- a/release/src/router/busybox/examples/udhcp/simple.script
+++ b/release/src/router/busybox/examples/udhcp/simple.script
@@ -29,18 +29,23 @@ case "$1" in
metric=0
for i in $router ; do
echo "Adding router $i"
- route add default gw $i dev $interface metric $((metric++))
+ route add default gw $i dev $interface metric $metric
+ : $(( metric += 1 ))
done
fi
echo "Recreating $RESOLV_CONF"
- echo -n > $RESOLV_CONF-$$
- [ -n "$domain" ] && echo "search $domain" >> $RESOLV_CONF-$$
+ # If the file is a symlink somewhere (like /etc/resolv.conf
+ # pointing to /run/resolv.conf), make sure things work.
+ realconf=$(readlink -f "$RESOLV_CONF" 2>/dev/null || echo "$RESOLV_CONF")
+ tmpfile="$realconf-$$"
+ > "$tmpfile"
+ [ -n "$domain" ] && echo "search $domain" >> "$tmpfile"
for i in $dns ; do
echo " Adding DNS server $i"
- echo "nameserver $i" >> $RESOLV_CONF-$$
+ echo "nameserver $i" >> "$tmpfile"
done
- mv $RESOLV_CONF-$$ $RESOLV_CONF
+ mv "$tmpfile" "$realconf"
;;
esac
diff --git a/release/src/router/busybox/examples/undeb b/release/src/router/busybox/examples/undeb
index 37104e9d81..c30baf31b4 100755
--- a/release/src/router/busybox/examples/undeb
+++ b/release/src/router/busybox/examples/undeb
@@ -5,49 +5,55 @@
# Requires the programs (ar, tar, gzip, and the pager more or less).
#
usage() {
-echo "Usage: undeb -c package.deb <Print control file info>"
-echo " undeb -l package.deb <List contents of deb package>"
-echo " undeb -x package.deb /foo/boo <Extract deb package to this directory,"
-echo " put . for current directory>"
-exit
+ cat <<EOF
+Usage: undeb -c package.deb <Print control file info>
+ undeb -l package.deb <List contents of deb package>
+ undeb -x package.deb /foo/boo <Extract deb package to this directory,
+ put . for current directory>
+EOF
+ exit
}
deb=$2
exist() {
-if [ "$deb" = "" ]; then
-usage
-elif [ ! -s "$deb" ]; then
-echo "Can't find $deb!"
-exit
-fi
+ if [ -z "${deb}" ]; then
+ usage
+ elif [ ! -s "${deb}" ]; then
+ echo "Can't find ${deb}!"
+ exit 1
+ fi
}
-if [ "$1" = "" ]; then
-usage
+if [ -z "$1" ]; then
+ usage
elif [ "$1" = "-l" ]; then
-exist
-type more >/dev/null 2>&1 && pager=more
-type less >/dev/null 2>&1 && pager=less
-[ "$pager" = "" ] && echo "No pager found!" && exit
-(ar -p $deb control.tar.gz | tar -xzO *control ; echo -e "\nPress enter to scroll, q to Quit!\n" ; ar -p $deb data.tar.gz | tar -tzv) | $pager
-exit
+ exist
+ type more >/dev/null 2>&1 && pager=more
+ type less >/dev/null 2>&1 && pager=less
+ [ -z "${pager}" ] && echo "No pager found!" && exit 1
+ (
+ ar -p "${deb}" control.tar.gz | tar -xzO *control
+ printf "\nPress enter to scroll, q to Quit!\n\n"
+ ar -p "${deb}" data.tar.gz | tar -tzv
+ ) | ${pager}
+ exit
elif [ "$1" = "-c" ]; then
-exist
-ar -p $deb control.tar.gz | tar -xzO *control
-exit
+ exist
+ ar -p "${deb}" control.tar.gz | tar -xzO *control
+ exit
elif [ "$1" = "-x" ]; then
-exist
-if [ "$3" = "" ]; then
-usage
-elif [ ! -d "$3" ]; then
-echo "No such directory $3!"
-exit
-fi
-ar -p $deb data.tar.gz | tar -xzvpf - -C $3 || exit
-echo
-echo "Extracted $deb to $3!"
-exit
+ exist
+ if [ -z "$3" ]; then
+ usage
+ elif [ ! -d "$3" ]; then
+ echo "No such directory $3!"
+ exit 1
+ fi
+ ar -p "${deb}" data.tar.gz | tar -xzvpf - -C "$3" || exit
+ echo
+ echo "Extracted ${deb} to $3!"
+ exit
else
-usage
+ usage
fi
diff --git a/release/src/router/busybox/examples/unrpm b/release/src/router/busybox/examples/unrpm
index 7fd3676f64..f48550b0ac 100755
--- a/release/src/router/busybox/examples/unrpm
+++ b/release/src/router/busybox/examples/unrpm
@@ -5,44 +5,49 @@
# Requires the programs (cpio, gzip, and the pager more or less).
#
usage() {
-echo "Usage: unrpm -l package.rpm <List contents of rpm package>"
-echo " unrpm -x package.rpm /foo/boo <Extract rpm package to this directory,"
-echo " put . for current directory>"
-exit
+ cat <<EOF
+Usage: unrpm -l package.rpm <List contents of rpm package>
+ unrpm -x package.rpm /foo/boo <Extract rpm package to this directory,
+ put . for current directory>
+EOF
+ exit
}
rpm=$2
exist() {
-if [ "$rpm" = "" ]; then
-usage
-elif [ ! -s "$rpm" ]; then
-echo "Can't find $rpm!"
-exit
-fi
+ if [ -z "${rpm}" ]; then
+ usage
+ elif [ ! -s "${rpm}" ]; then
+ echo "Can't find ${rpm}!"
+ exit 1
+ fi
}
-if [ "$1" = "" ]; then
-usage
+if [ -z "$1" ]; then
+ usage
elif [ "$1" = "-l" ]; then
-exist
-type more >/dev/null 2>&1 && pager=more
-type less >/dev/null 2>&1 && pager=less
-[ "$pager" = "" ] && echo "No pager found!" && exit
-(echo -e "\nPress enter to scroll, q to Quit!\n" ; rpm2cpio $rpm | cpio -tv --quiet) | $pager
-exit
+ exist
+ type more >/dev/null 2>&1 && pager=more
+ type less >/dev/null 2>&1 && pager=less
+ [ "$pager" = "" ] && echo "No pager found!" && exit
+ (
+ printf "\nPress enter to scroll, q to Quit!\n\n"
+ rpm2cpio "${rpm}" | cpio -tv --quiet
+ ) | ${pager}
+ exit
elif [ "$1" = "-x" ]; then
-exist
-if [ "$3" = "" ]; then
-usage
-elif [ ! -d "$3" ]; then
-echo "No such directory $3!"
-exit
-fi
-rpm2cpio $rpm | (umask 0 ; cd $3 ; cpio -idmuv) || exit
-echo
-echo "Extracted $rpm to $3!"
-exit
+ exist
+ if [ -z "$3" ]; then
+ usage
+ elif [ ! -d "$3" ]; then
+ echo "No such directory $3!"
+ exit 1
+ fi
+ rpm2cpio "${rpm}" | (umask 0 ; cd "$3" ; cpio -idmuv) || exit
+ echo
+ echo "Extracted ${rpm} to $3!"
+ exit
else
-usage
+ usage
fi
diff --git a/release/src/router/busybox/examples/var_service/README b/release/src/router/busybox/examples/var_service/README
index 06817c8bcd..d096ad0b92 100644
--- a/release/src/router/busybox/examples/var_service/README
+++ b/release/src/router/busybox/examples/var_service/README
@@ -9,6 +9,15 @@ env - PATH=... <other vars=...> runsvdir /var/service &
from one of system startup scripts. (Google "man runsvdir" and "man runsv"
for more info about these tools).
+You can try or debug an individual service by running its SERVICE_DIR/run script.
+In this case, its stdout and stderr go to your terminal.
+
+You can also run "runsv SERVICE_DIR", which runs both the service
+and its logger service (SERVICE_DIR/log/run) if logger service exists.
+If logger service exists, the output will go to it instead of the terminal.
+
+"runsvdir DIR" merely runs "runsv SERVICE_DIR" for every subdirectory in DIR.
+
Some existing examples:
var_service/dhcp_if -
@@ -27,10 +36,10 @@ service accordingly. In effect, it allows you to unplug/plug-to-different-networ
and have your IP properly re-negotiated at once.
var_service/dhcp_if_pinger -
-Uses var_service/dhcp_if's data (/var/service/dhcp_if/dhcp_if.out file)
-to determine router IP. Pings it. If ping fails, restarts /var/service/dhcp_if
-service. Basically, an example of watchdog service for networks
-which are not reliable and need babysitting.
+Uses var_service/dhcp_if's data to determine router IP. Pings it.
+If ping fails, restarts /var/service/dhcp_if service.
+Basically, an example of watchdog service for networks which are not reliable
+and need babysitting.
var_service/fw -
A *one-shot* service which reconfigures network based on current known state
@@ -47,8 +56,8 @@ This even works while fw service runs: if dhcp signals fw to (re)start
while fw runs, fw will not stop after its execution, but will re-execute once,
picking up dhcp's new configuration.
This is achieved very simply by having
-# Make ourself one-shot
-sv o .
+ # Make ourself one-shot
+ sv o .
at the very beginning of fw/run script, not at the end.
Therefore, any "sv u /var/run/service/fw" command by any other
script "undoes" o(ne-shot) command if fw still runs, thus
diff --git a/release/src/router/busybox/examples/var_service/dhcp_if/README b/release/src/router/busybox/examples/var_service/dhcp_if/README
new file mode 100644
index 0000000000..4ddccb22d7
--- /dev/null
+++ b/release/src/router/busybox/examples/var_service/dhcp_if/README
@@ -0,0 +1,5 @@
+The real README file is one directory up.
+
+This directory's run script can have useful comments.
+If it doesn't but you feel it should, please send a patch
+to busybox's mailing list.
diff --git a/release/src/router/busybox/examples/var_service/dhcp_if/convert2ntpconf b/release/src/router/busybox/examples/var_service/dhcp_if/convert2ntpconf
index debf1ebfe7..e9d829308f 100755
--- a/release/src/router/busybox/examples/var_service/dhcp_if/convert2ntpconf
+++ b/release/src/router/busybox/examples/var_service/dhcp_if/convert2ntpconf
@@ -29,6 +29,6 @@ test "$ip" || exit 1
{
for n in $ntpsrv; do
echo "let cfg=cfg+1"
- echo "ntpip[\$cfg]='$n'";
+ echo "ntpip[\$cfg]='$n'"
done
} >"$1"
diff --git a/release/src/router/busybox/examples/var_service/dhcp_if/dhcp_handler b/release/src/router/busybox/examples/var_service/dhcp_if/dhcp_handler
index 927e02a176..3d2a5cb791 100755
--- a/release/src/router/busybox/examples/var_service/dhcp_if/dhcp_handler
+++ b/release/src/router/busybox/examples/var_service/dhcp_if/dhcp_handler
@@ -36,7 +36,7 @@ service=${PWD##*/}
file_ipconf="$service.ipconf"
file_ntpconf="$service.ntpconf"
dir_ipconf="/var/run/service/fw"
-dir_ntpconf="/var/run/service/ntp"
+dir_ntpconf="/var/run/service/ntpd"
exec >/dev/null
#exec >>"$0.out" #debug
@@ -47,7 +47,7 @@ echo "`date`: Params: $*"
if test x"$1" != x"bound" && test x"$1" != x"renew" ; then
# Reconfigure network with this interface disabled
echo "Deconfiguring"
- rm "$service.out"
+ rm "env.out"
rm "$file_ipconf"
rm "$file_ntpconf"
rm "$dir_ipconf/$file_ipconf"
@@ -57,7 +57,8 @@ if test x"$1" != x"bound" && test x"$1" != x"renew" ; then
fi
# Bound: we've got the lease
-#env >"$service.out" # debug
+# Record information for e.g. dhcp_$IF_pinger service
+env >"env.out"
./convert2ipconf "$file_ipconf"
# Reconfigure routing and firewall if needed
@@ -69,7 +70,7 @@ if test $? != 0; then
sv u /var/service/fw
fi
-if test -d /var/service/ntp; then
+if test -d /var/service/ntpd; then
./convert2ntpconf "$file_ntpconf"
# Reconfigure ntp server addresses if needed
diff --brief "$file_ntpconf" "$dir_ntpconf/$file_ntpconf" >/dev/null 2>&1
@@ -77,7 +78,7 @@ if test -d /var/service/ntp; then
echo "Reconfiguring ntp"
mkdir -p "$dir_ntpconf" 2>/dev/null
cp "$file_ntpconf" "$dir_ntpconf/$file_ntpconf"
- sv t /var/service/ntp
- sv u /var/service/ntp
+ sv t /var/service/ntpd
+ sv u /var/service/ntpd
fi
fi
diff --git a/release/src/router/busybox/examples/var_service/dhcp_if/finish b/release/src/router/busybox/examples/var_service/dhcp_if/finish
new file mode 100755
index 0000000000..5e7667a2d6
--- /dev/null
+++ b/release/src/router/busybox/examples/var_service/dhcp_if/finish
@@ -0,0 +1,17 @@
+#!/bin/sh
+# executed when service is taken down ("sv d .")
+
+service=${PWD##*/}
+file_ipconf="$service.ipconf"
+file_ntpconf="$service.ntpconf"
+dir_ipconf="/var/run/service/fw"
+dir_ntpconf="/var/run/service/ntpd"
+
+# Reconfigure network with this interface disabled
+echo "Finish: deconfiguring"
+rm "env.out"
+rm "$file_ipconf"
+rm "$file_ntpconf"
+rm "$dir_ipconf/$file_ipconf"
+rm "$dir_ntpconf/$file_ntpconf"
+sv u /var/service/fw
diff --git a/release/src/router/busybox/examples/var_service/dhcp_if/log/run b/release/src/router/busybox/examples/var_service/dhcp_if/log/run
index 560d1b19f6..69d74b73f5 100755
--- a/release/src/router/busybox/examples/var_service/dhcp_if/log/run
+++ b/release/src/router/busybox/examples/var_service/dhcp_if/log/run
@@ -6,7 +6,7 @@ logdir="/var/log/service/`(cd ..;basename $PWD)`"
mkdir -p "$logdir" 2>/dev/null
chown -R "$user": "$logdir"
chmod -R go-rwxst,u+rwX "$logdir"
-rm logdir
+rm -rf logdir
ln -s "$logdir" logdir
# make this dir accessible to logger
diff --git a/release/src/router/busybox/examples/var_service/dhcp_if_pinger/README b/release/src/router/busybox/examples/var_service/dhcp_if_pinger/README
new file mode 100644
index 0000000000..4ddccb22d7
--- /dev/null
+++ b/release/src/router/busybox/examples/var_service/dhcp_if_pinger/README
@@ -0,0 +1,5 @@
+The real README file is one directory up.
+
+This directory's run script can have useful comments.
+If it doesn't but you feel it should, please send a patch
+to busybox's mailing list.
diff --git a/release/src/router/busybox/examples/var_service/dhcp_if_pinger/run b/release/src/router/busybox/examples/var_service/dhcp_if_pinger/run
index 20b2fc5161..e0e87a16ab 100755
--- a/release/src/router/busybox/examples/var_service/dhcp_if_pinger/run
+++ b/release/src/router/busybox/examples/var_service/dhcp_if_pinger/run
@@ -1,23 +1,47 @@
#!/bin/sh
-delay=67
-
+# How often to test, seconds
+ping_time=67
+# "One ping, must have reply in 1 sec"
+ping_opts="-c1 -W1 -w1"
+# If ping failed, how soon to retry
+retry_time=5
+# Reinit after this many consecutive ping error
+max_fail=5
+# Interface whose DHCP data to use
if=${PWD##*/dhcp_}
if=${if%%_pinger}
+msg() {
+ echo "`date '+%Y-%m-%d %H:%M:%S'` $*" >>"$0.log"
+}
+
if test -f "$0.log"; then
tail -999 "$0.log" >"$0.log.new"
mv "$0.log.new" "$0.log"
fi
-test -f "/var/service/dhcp_$if/dhcp_$if.out" || exec env - sleep "$delay"
-. "/var/service/dhcp_$if/dhcp_$if.out"
-test x"$router" != x"" || exec env - sleep "$delay"
+test -f "/var/service/dhcp_$if/env.out" || exec env - sleep "$ping_time"
-#echo "`date '+%Y-%m-%d %H:%M:%S'` Testing ping -c3 $router" >>"$0.log"
-ping -c3 "$router" && exec env - sleep "$delay"
+. "/var/service/dhcp_$if/env.out"
+test x"$router" != x"" || exec env - sleep "$ping_time"
-echo "`date '+%Y-%m-%d %H:%M:%S'` Restarting /var/service/dhcp_$if" >>"$0.log"
-sv t "/var/service/dhcp_$if"
+#msg "Pinging $router"
+failcnt=0
+while true; do
+ ping $ping_opts "$router" && exec env - sleep "$ping_time"
+ : $((failcnt++))
+ msg "Failed to ping $router, fail count:$failcnt"
+ test $failcnt -ge $max_fail && break
+ env - sleep "$retry_time"
+done
-exec env - sleep "$delay"
+test -d "/var/service/dhcp_$if" && {
+ msg "Restarting /var/service/dhcp_$if"
+ sv t "/var/service/dhcp_$if"
+}
+test -d "/var/service/supplicant_$if" && {
+ msg "Restarting /var/service/supplicant_$if"
+ sv t "/var/service/supplicant_$if"
+}
+exec env - sleep "$ping_time"
diff --git a/release/src/router/busybox/examples/var_service/ftpd/README b/release/src/router/busybox/examples/var_service/ftpd/README
new file mode 100644
index 0000000000..4ddccb22d7
--- /dev/null
+++ b/release/src/router/busybox/examples/var_service/ftpd/README
@@ -0,0 +1,5 @@
+The real README file is one directory up.
+
+This directory's run script can have useful comments.
+If it doesn't but you feel it should, please send a patch
+to busybox's mailing list.
diff --git a/release/src/router/busybox/examples/var_service/ftpd/log/run b/release/src/router/busybox/examples/var_service/ftpd/log/run
index 560d1b19f6..69d74b73f5 100755
--- a/release/src/router/busybox/examples/var_service/ftpd/log/run
+++ b/release/src/router/busybox/examples/var_service/ftpd/log/run
@@ -6,7 +6,7 @@ logdir="/var/log/service/`(cd ..;basename $PWD)`"
mkdir -p "$logdir" 2>/dev/null
chown -R "$user": "$logdir"
chmod -R go-rwxst,u+rwX "$logdir"
-rm logdir
+rm -rf logdir
ln -s "$logdir" logdir
# make this dir accessible to logger
diff --git a/release/src/router/busybox/examples/var_service/fw/README b/release/src/router/busybox/examples/var_service/fw/README
new file mode 100644
index 0000000000..4ddccb22d7
--- /dev/null
+++ b/release/src/router/busybox/examples/var_service/fw/README
@@ -0,0 +1,5 @@
+The real README file is one directory up.
+
+This directory's run script can have useful comments.
+If it doesn't but you feel it should, please send a patch
+to busybox's mailing list.
diff --git a/release/src/router/busybox/examples/var_service/fw/run b/release/src/router/busybox/examples/var_service/fw/run
index 396b678ab8..81c7f2e7cf 100755
--- a/release/src/router/busybox/examples/var_service/fw/run
+++ b/release/src/router/busybox/examples/var_service/fw/run
@@ -62,7 +62,7 @@ umask 077
# Make sure rundir/ exists
mkdir -p "$rundir" 2>/dev/null
-chown -R "$user:" "$rundir"
+chown -R "$user": "$rundir"
chmod -R a=rX "$rundir"
rm -rf rundir 2>/dev/null
ln -s "$rundir" rundir
diff --git a/release/src/router/busybox/examples/var_service/getty_tty1/README b/release/src/router/busybox/examples/var_service/getty_tty1/README
new file mode 100644
index 0000000000..4ddccb22d7
--- /dev/null
+++ b/release/src/router/busybox/examples/var_service/getty_tty1/README
@@ -0,0 +1,5 @@
+The real README file is one directory up.
+
+This directory's run script can have useful comments.
+If it doesn't but you feel it should, please send a patch
+to busybox's mailing list.
diff --git a/release/src/router/busybox/examples/var_service/gpm/README b/release/src/router/busybox/examples/var_service/gpm/README
new file mode 100644
index 0000000000..4ddccb22d7
--- /dev/null
+++ b/release/src/router/busybox/examples/var_service/gpm/README
@@ -0,0 +1,5 @@
+The real README file is one directory up.
+
+This directory's run script can have useful comments.
+If it doesn't but you feel it should, please send a patch
+to busybox's mailing list.
diff --git a/release/src/router/busybox/examples/var_service/httpd/README b/release/src/router/busybox/examples/var_service/httpd/README
new file mode 100644
index 0000000000..4ddccb22d7
--- /dev/null
+++ b/release/src/router/busybox/examples/var_service/httpd/README
@@ -0,0 +1,5 @@
+The real README file is one directory up.
+
+This directory's run script can have useful comments.
+If it doesn't but you feel it should, please send a patch
+to busybox's mailing list.
diff --git a/release/src/router/busybox/examples/var_service/httpd/log/run b/release/src/router/busybox/examples/var_service/httpd/log/run
index 560d1b19f6..69d74b73f5 100755
--- a/release/src/router/busybox/examples/var_service/httpd/log/run
+++ b/release/src/router/busybox/examples/var_service/httpd/log/run
@@ -6,7 +6,7 @@ logdir="/var/log/service/`(cd ..;basename $PWD)`"
mkdir -p "$logdir" 2>/dev/null
chown -R "$user": "$logdir"
chmod -R go-rwxst,u+rwX "$logdir"
-rm logdir
+rm -rf logdir
ln -s "$logdir" logdir
# make this dir accessible to logger
diff --git a/release/src/router/busybox/examples/var_service/ifplugd_if/README b/release/src/router/busybox/examples/var_service/ifplugd_if/README
new file mode 100644
index 0000000000..4ddccb22d7
--- /dev/null
+++ b/release/src/router/busybox/examples/var_service/ifplugd_if/README
@@ -0,0 +1,5 @@
+The real README file is one directory up.
+
+This directory's run script can have useful comments.
+If it doesn't but you feel it should, please send a patch
+to busybox's mailing list.
diff --git a/release/src/router/busybox/examples/var_service/ifplugd_if/log/run b/release/src/router/busybox/examples/var_service/ifplugd_if/log/run
index 560d1b19f6..69d74b73f5 100755
--- a/release/src/router/busybox/examples/var_service/ifplugd_if/log/run
+++ b/release/src/router/busybox/examples/var_service/ifplugd_if/log/run
@@ -6,7 +6,7 @@ logdir="/var/log/service/`(cd ..;basename $PWD)`"
mkdir -p "$logdir" 2>/dev/null
chown -R "$user": "$logdir"
chmod -R go-rwxst,u+rwX "$logdir"
-rm logdir
+rm -rf logdir
ln -s "$logdir" logdir
# make this dir accessible to logger
diff --git a/release/src/router/busybox/examples/var_service/ifplugd_if/run b/release/src/router/busybox/examples/var_service/ifplugd_if/run
index 2781cf9f9f..c4f766e880 100755
--- a/release/src/router/busybox/examples/var_service/ifplugd_if/run
+++ b/release/src/router/busybox/examples/var_service/ifplugd_if/run
@@ -8,6 +8,9 @@ pwd="$PWD"
if="${PWD##*/ifplugd_}"
+echo "* Upping iface $if"
+ip link set dev "$if" up
+
echo "* Starting ifplugd on $if [$$]"
exec \
env - PATH="$PATH" \
diff --git a/release/src/router/busybox/examples/var_service/inetd/README b/release/src/router/busybox/examples/var_service/inetd/README
new file mode 100644
index 0000000000..4ddccb22d7
--- /dev/null
+++ b/release/src/router/busybox/examples/var_service/inetd/README
@@ -0,0 +1,5 @@
+The real README file is one directory up.
+
+This directory's run script can have useful comments.
+If it doesn't but you feel it should, please send a patch
+to busybox's mailing list.
diff --git a/release/src/router/busybox/examples/var_service/inetd/log/run b/release/src/router/busybox/examples/var_service/inetd/log/run
index 560d1b19f6..69d74b73f5 100755
--- a/release/src/router/busybox/examples/var_service/inetd/log/run
+++ b/release/src/router/busybox/examples/var_service/inetd/log/run
@@ -6,7 +6,7 @@ logdir="/var/log/service/`(cd ..;basename $PWD)`"
mkdir -p "$logdir" 2>/dev/null
chown -R "$user": "$logdir"
chmod -R go-rwxst,u+rwX "$logdir"
-rm logdir
+rm -rf logdir
ln -s "$logdir" logdir
# make this dir accessible to logger
diff --git a/release/src/router/busybox/examples/var_service/nmeter/README b/release/src/router/busybox/examples/var_service/nmeter/README
new file mode 100644
index 0000000000..4ddccb22d7
--- /dev/null
+++ b/release/src/router/busybox/examples/var_service/nmeter/README
@@ -0,0 +1,5 @@
+The real README file is one directory up.
+
+This directory's run script can have useful comments.
+If it doesn't but you feel it should, please send a patch
+to busybox's mailing list.
diff --git a/release/src/router/busybox/examples/var_service/ntpd/README b/release/src/router/busybox/examples/var_service/ntpd/README
new file mode 100644
index 0000000000..4ddccb22d7
--- /dev/null
+++ b/release/src/router/busybox/examples/var_service/ntpd/README
@@ -0,0 +1,5 @@
+The real README file is one directory up.
+
+This directory's run script can have useful comments.
+If it doesn't but you feel it should, please send a patch
+to busybox's mailing list.
diff --git a/release/src/router/busybox/examples/var_service/ntpd/log/run b/release/src/router/busybox/examples/var_service/ntpd/log/run
index 560d1b19f6..69d74b73f5 100755
--- a/release/src/router/busybox/examples/var_service/ntpd/log/run
+++ b/release/src/router/busybox/examples/var_service/ntpd/log/run
@@ -6,7 +6,7 @@ logdir="/var/log/service/`(cd ..;basename $PWD)`"
mkdir -p "$logdir" 2>/dev/null
chown -R "$user": "$logdir"
chmod -R go-rwxst,u+rwX "$logdir"
-rm logdir
+rm -rf logdir
ln -s "$logdir" logdir
# make this dir accessible to logger
diff --git a/release/src/router/busybox/examples/var_service/ntpd/ntp.script b/release/src/router/busybox/examples/var_service/ntpd/ntp.script
index 76c34bf74a..8542181eb4 100755
--- a/release/src/router/busybox/examples/var_service/ntpd/ntp.script
+++ b/release/src/router/busybox/examples/var_service/ntpd/ntp.script
@@ -10,12 +10,30 @@
dt=`date '+%Y-%m-%d %H:%M:%S'`
+echo "`tail -n 199 -- "$0.log" 2>/dev/null`" >"$0.log.$$"
+
+if test x"$1" = x"unsync" \
+; then
+ # No replies for our NTP requests were seen for some time.
+ #
+ # Among more mundate cases like network outages, this happens
+ # if we ran for a LONG time (days) and ntp server's IP has changed.
+ # ntpd has no code to re-resolve peers' addresses to IPs,
+ # we need to help it:
+ #
+ echo "$dt: $1"\
+ "syncronization lost, restarting ntpd"\
+ >>"$0.log.$$"
+ mv -- "$0.log.$$" "$0.log"
+ kill $PPID
+ exit
+fi
+
if test x"$stratum" != x"" \
&& test x"$poll_interval" != x"" \
&& test 4 -ge "$stratum" \
&& test 128 -le "$poll_interval" \
; then
- echo "`tail -n 199 -- "$0.log" 2>/dev/null`" >"$0.log.$$"
echo "$dt: $1"\
"freq_drift_ppm=$freq_drift_ppm"\
"offset=$offset"\
@@ -27,7 +45,6 @@ if test x"$stratum" != x"" \
exec hwclock --systohc
fi
-echo "`tail -n 199 -- "$0.log" 2>/dev/null`" >"$0.log.$$"
echo "$dt: $1"\
"freq_drift_ppm=$freq_drift_ppm"\
"offset=$offset"\
diff --git a/release/src/router/busybox/examples/var_service/ntpd/run b/release/src/router/busybox/examples/var_service/ntpd/run
index 581d231a39..6f2a681883 100755
--- a/release/src/router/busybox/examples/var_service/ntpd/run
+++ b/release/src/router/busybox/examples/var_service/ntpd/run
@@ -15,7 +15,7 @@ default_p_opt="-p 0.$pool -p 1.$pool -p 2.$pool -p 3.$pool"
# Make sure rundir/ exists
mkdir -p "$rundir" 2>/dev/null
-chown -R "$user:" "$rundir"
+chown -R "$user": "$rundir"
chmod -R a=rX "$rundir"
rm -rf rundir 2>/dev/null
ln -s "$rundir" rundir
diff --git a/release/src/router/busybox/examples/var_service/tftpd/README b/release/src/router/busybox/examples/var_service/tftpd/README
new file mode 100644
index 0000000000..4ddccb22d7
--- /dev/null
+++ b/release/src/router/busybox/examples/var_service/tftpd/README
@@ -0,0 +1,5 @@
+The real README file is one directory up.
+
+This directory's run script can have useful comments.
+If it doesn't but you feel it should, please send a patch
+to busybox's mailing list.
diff --git a/release/src/router/busybox/examples/var_service/tftpd/log/run b/release/src/router/busybox/examples/var_service/tftpd/log/run
index 560d1b19f6..69d74b73f5 100755
--- a/release/src/router/busybox/examples/var_service/tftpd/log/run
+++ b/release/src/router/busybox/examples/var_service/tftpd/log/run
@@ -6,7 +6,7 @@ logdir="/var/log/service/`(cd ..;basename $PWD)`"
mkdir -p "$logdir" 2>/dev/null
chown -R "$user": "$logdir"
chmod -R go-rwxst,u+rwX "$logdir"
-rm logdir
+rm -rf logdir
ln -s "$logdir" logdir
# make this dir accessible to logger
diff --git a/release/src/router/busybox/examples/var_service/zcip_if/README b/release/src/router/busybox/examples/var_service/zcip_if/README
new file mode 100644
index 0000000000..4ddccb22d7
--- /dev/null
+++ b/release/src/router/busybox/examples/var_service/zcip_if/README
@@ -0,0 +1,5 @@
+The real README file is one directory up.
+
+This directory's run script can have useful comments.
+If it doesn't but you feel it should, please send a patch
+to busybox's mailing list.
diff --git a/release/src/router/busybox/examples/var_service/zcip_if/convert2ipconf b/release/src/router/busybox/examples/var_service/zcip_if/convert2ipconf
new file mode 100755
index 0000000000..c858723fb8
--- /dev/null
+++ b/release/src/router/busybox/examples/var_service/zcip_if/convert2ipconf
@@ -0,0 +1,24 @@
+#!/bin/sh
+# convert:
+
+#interface=eth1
+#ip=169.254.x.y
+
+# into:
+
+#let cfg=cfg+1
+#if[$cfg]=...; ip[$cfg]=...; ipmask[$cfg]=.../...; gw[$cfg]=...; net[$cfg]=... dns[$cfg]=...
+
+exec >/dev/null
+#exec >"$0.out" # debug
+exec 2>&1
+
+test "$interface" || exit 1
+test "$ip" || exit 1
+
+{
+echo "let cfg=cfg+1"
+test "$interface" && echo "if[\$cfg]='$interface'"
+test "$ip" && echo "ip[\$cfg]='$ip'"
+test "$ip" && echo "ipmask[\$cfg]='$ip/16'"
+} >"$1"
diff --git a/release/src/router/busybox/examples/var_service/zcip_if/finish b/release/src/router/busybox/examples/var_service/zcip_if/finish
new file mode 100755
index 0000000000..95995cf5f1
--- /dev/null
+++ b/release/src/router/busybox/examples/var_service/zcip_if/finish
@@ -0,0 +1,13 @@
+#!/bin/sh
+# executed when service is taken down ("sv d .")
+
+service=${PWD##*/}
+file_ipconf="$service.ipconf"
+dir_ipconf="/var/run/service/fw"
+
+# Reconfigure network with this interface disabled
+echo "Finish: deconfiguring"
+rm "env.out"
+rm "$file_ipconf"
+rm "$dir_ipconf/$file_ipconf"
+sv u /var/service/fw
diff --git a/release/src/router/busybox/examples/var_service/zcip_if/log/run b/release/src/router/busybox/examples/var_service/zcip_if/log/run
new file mode 100755
index 0000000000..69d74b73f5
--- /dev/null
+++ b/release/src/router/busybox/examples/var_service/zcip_if/log/run
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+user=logger
+
+logdir="/var/log/service/`(cd ..;basename $PWD)`"
+mkdir -p "$logdir" 2>/dev/null
+chown -R "$user": "$logdir"
+chmod -R go-rwxst,u+rwX "$logdir"
+rm -rf logdir
+ln -s "$logdir" logdir
+
+# make this dir accessible to logger
+chmod a+rX .
+
+exec >/dev/null
+exec 2>&1
+exec \
+env - PATH="$PATH" \
+softlimit \
+setuidgid "$user" \
+svlogd -tt "$logdir"
diff --git a/release/src/router/busybox/examples/var_service/zcip_if/p_log b/release/src/router/busybox/examples/var_service/zcip_if/p_log
new file mode 100755
index 0000000000..a2521be055
--- /dev/null
+++ b/release/src/router/busybox/examples/var_service/zcip_if/p_log
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+cd log/logdir || exit 1
+cat @* current | $PAGER
diff --git a/release/src/router/busybox/examples/var_service/zcip_if/run b/release/src/router/busybox/examples/var_service/zcip_if/run
new file mode 100755
index 0000000000..94a8754650
--- /dev/null
+++ b/release/src/router/busybox/examples/var_service/zcip_if/run
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+exec 2>&1
+exec </dev/null
+
+pwd="$PWD"
+
+if="${PWD##*/zcip_}"
+
+echo "* Upping iface $if"
+ip link set dev "$if" up
+
+echo "* Starting zcip"
+exec \
+env - PATH="$PATH" \
+softlimit \
+setuidgid root \
+zcip -fvv \
+ "$if" \
+ "$pwd/zcip_handler"
diff --git a/release/src/router/busybox/examples/var_service/zcip_if/w_log b/release/src/router/busybox/examples/var_service/zcip_if/w_log
new file mode 100755
index 0000000000..aa36ef13be
--- /dev/null
+++ b/release/src/router/busybox/examples/var_service/zcip_if/w_log
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+cd log/logdir || exit 1
+watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))'
diff --git a/release/src/router/busybox/examples/var_service/zcip_if/zcip_handler b/release/src/router/busybox/examples/var_service/zcip_if/zcip_handler
new file mode 100755
index 0000000000..3c6ca788bd
--- /dev/null
+++ b/release/src/router/busybox/examples/var_service/zcip_if/zcip_handler
@@ -0,0 +1,47 @@
+#!/bin/sh
+# executed by zcip
+# parameters: $1 and environment
+# $1 is:
+#
+# init: zcip starts. Environment:
+# interface=eth0
+#
+# config: Address is obtained.
+# interface=eth0
+# ip=169.254.a.b
+#
+# deconfig: Conflict or link went down.
+# interface=eth0
+
+service=${PWD##*/}
+file_ipconf="$service.ipconf"
+dir_ipconf="/var/run/service/fw"
+
+exec >/dev/null
+#exec >>"$0.out" #debug
+exec 2>&1
+
+echo "`date`: Params: $*"
+
+if test x"$1" != x"config"; then
+ # Reconfigure network with this interface disabled
+ echo "Deconfiguring"
+ rm "$file_ipconf"
+ rm "$dir_ipconf/$file_ipconf"
+ sv u /var/service/fw
+ exit
+fi
+
+# "config": we've got the address
+# Record information for e.g. dhcp_$IF_pinger service
+env >"env.out"
+
+./convert2ipconf "$file_ipconf"
+# Reconfigure routing and firewall if needed
+diff --brief "$file_ipconf" "$dir_ipconf/$file_ipconf" >/dev/null 2>&1
+if test $? != 0; then
+ echo "Reconfiguring fw"
+ mkdir -p "$dir_ipconf" 2>/dev/null
+ cp "$file_ipconf" "$dir_ipconf/$file_ipconf"
+ sv u /var/service/fw
+fi
diff --git a/release/src/router/busybox/findutils/.gitignore b/release/src/router/busybox/findutils/.gitignore
deleted file mode 100644
index 7a30caf5cd..0000000000
--- a/release/src/router/busybox/findutils/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# Config.in and Kbuild are auto-generated
-Config.in
-Kbuild
diff --git a/release/src/router/busybox/findutils/find.c b/release/src/router/busybox/findutils/find.c
index 0ec5bdfeaa..d71c697827 100644
--- a/release/src/router/busybox/findutils/find.c
+++ b/release/src/router/busybox/findutils/find.c
@@ -137,6 +137,16 @@
//config: Support the 'find -exec' option for executing commands based upon
//config: the files matched.
//config:
+//config:config FEATURE_FIND_EXEC_PLUS
+//config: bool "Enable -exec ... {} +"
+//config: default y
+//config: depends on FEATURE_FIND_EXEC
+//config: help
+//config: Support the 'find -exec ... {} +' option for executing commands
+//config: for all matched files at once.
+//config: Without this option, -exec + is a synonym for -exec ;
+//config: (IOW: it works correctly, but without expected speedup)
+//config:
//config:config FEATURE_FIND_USER
//config: bool "Enable -user: username/uid matching"
//config: default y
@@ -231,12 +241,13 @@
//kbuild:lib-$(CONFIG_FIND) += find.o
//usage:#define find_trivial_usage
-//usage: "[PATH]... [OPTIONS] [ACTIONS]"
+//usage: "[-HL] [PATH]... [OPTIONS] [ACTIONS]"
//usage:#define find_full_usage "\n\n"
//usage: "Search for files and perform actions on them.\n"
//usage: "First failed action stops processing of current file.\n"
//usage: "Defaults: PATH is current directory, action is '-print'\n"
-//usage: "\n -follow Follow symlinks"
+//usage: "\n -L,-follow Follow symlinks"
+//usage: "\n -H ...on command line only"
//usage: IF_FEATURE_FIND_XDEV(
//usage: "\n -xdev Don't descend directories on other filesystems"
//usage: )
@@ -318,6 +329,9 @@
//usage: "\n -exec CMD ARG ; Run CMD with all instances of {} replaced by"
//usage: "\n file name. Fails if CMD exits with nonzero"
//usage: )
+//usage: IF_FEATURE_FIND_EXEC_PLUS(
+//usage: "\n -exec CMD ARG + Run CMD with {} replaced by list of file names"
+//usage: )
//usage: IF_FEATURE_FIND_DELETE(
//usage: "\n -delete Delete current file/directory. Turns on -depth option"
//usage: )
@@ -328,6 +342,7 @@
#include <fnmatch.h>
#include "libbb.h"
+#include "common_bufsiz.h"
#if ENABLE_FEATURE_FIND_REGEX
# include "xregex.h"
#endif
@@ -336,8 +351,12 @@
# define FNM_CASEFOLD 0
#endif
-#define dbg(...) ((void)0)
-/* #define dbg(...) bb_error_msg(__VA_ARGS__) */
+#if 1
+# define dbg(...) ((void)0)
+#else
+# define dbg(...) bb_error_msg(__VA_ARGS__)
+#endif
+
/* This is a NOEXEC applet. Be very careful! */
@@ -374,7 +393,20 @@ IF_FEATURE_FIND_CONTEXT(ACTS(context, security_context_t context;))
IF_FEATURE_FIND_PAREN( ACTS(paren, action ***subexpr;))
IF_FEATURE_FIND_PRUNE( ACTS(prune))
IF_FEATURE_FIND_DELETE( ACTS(delete))
-IF_FEATURE_FIND_EXEC( ACTS(exec, char **exec_argv; unsigned *subst_count; int exec_argc;))
+IF_FEATURE_FIND_EXEC( ACTS(exec,
+ char **exec_argv; /* -exec ARGS */
+ unsigned *subst_count;
+ int exec_argc; /* count of ARGS */
+ IF_FEATURE_FIND_EXEC_PLUS(
+ /*
+ * filelist is NULL if "exec ;"
+ * non-NULL if "exec +"
+ */
+ char **filelist;
+ int filelist_idx;
+ int file_len;
+ )
+ ))
IF_FEATURE_FIND_GROUP( ACTS(group, gid_t gid;))
IF_FEATURE_FIND_LINKS( ACTS(links, char links_char; int links_count;))
@@ -388,49 +420,20 @@ struct globals {
smallint need_print;
smallint xdev_on;
recurse_flags_t recurse_flags;
+ IF_FEATURE_FIND_EXEC_PLUS(unsigned max_argv_len;)
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define INIT_G() do { \
- struct G_sizecheck { \
- char G_sizecheck[sizeof(G) > COMMON_BUFSIZE ? -1 : 1]; \
- }; \
+ setup_common_bufsiz(); \
+ BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
/* we have to zero it out because of NOEXEC */ \
memset(&G, 0, sizeof(G)); \
IF_FEATURE_FIND_MAXDEPTH(G.minmaxdepth[1] = INT_MAX;) \
+ IF_FEATURE_FIND_EXEC_PLUS(G.max_argv_len = bb_arg_max() - 2048;) \
G.need_print = 1; \
G.recurse_flags = ACTION_RECURSE; \
} while (0)
-#if ENABLE_FEATURE_FIND_EXEC
-static unsigned count_subst(const char *str)
-{
- unsigned count = 0;
- while ((str = strstr(str, "{}")) != NULL) {
- count++;
- str++;
- }
- return count;
-}
-
-
-static char* subst(const char *src, unsigned count, const char* filename)
-{
- char *buf, *dst, *end;
- size_t flen = strlen(filename);
- /* we replace each '{}' with filename: growth by strlen-2 */
- buf = dst = xmalloc(strlen(src) + count*(flen-2) + 1);
- while ((end = strstr(src, "{}"))) {
- memcpy(dst, src, end - src);
- dst += end - src;
- src = end + 2;
- memcpy(dst, filename, flen);
- dst += flen;
- }
- strcpy(dst, src);
- return buf;
-}
-#endif
-
/* Return values of ACTFs ('action functions') are a bit mask:
* bit 1=1: prune (use SKIP constant for setting it)
* bit 0=1: matched successfully (TRUE)
@@ -481,7 +484,6 @@ static int exec_actions(action ***appp, const char *fileName, const struct stat
return rc ^ TRUE; /* restore TRUE bit */
}
-
#if !FNM_CASEFOLD
static char *strcpy_upcase(char *dst, const char *src)
{
@@ -556,8 +558,8 @@ ACTF(type)
#if ENABLE_FEATURE_FIND_PERM
ACTF(perm)
{
- /* -perm +mode: at least one of perm_mask bits are set */
- if (ap->perm_char == '+')
+ /* -perm [+/]mode: at least one of perm_mask bits are set */
+ if (ap->perm_char == '+' || ap->perm_char == '/')
return (statbuf->st_mode & ap->perm_mask) != 0;
/* -perm -mode: all of perm_mask are set */
if (ap->perm_char == '-')
@@ -605,17 +607,57 @@ ACTF(inum)
}
#endif
#if ENABLE_FEATURE_FIND_EXEC
-ACTF(exec)
+static int do_exec(action_exec *ap, const char *fileName)
{
int i, rc;
-#if ENABLE_USE_PORTABLE_CODE
- char **argv = alloca(sizeof(char*) * (ap->exec_argc + 1));
-#else /* gcc 4.3.1 generates smaller code: */
- char *argv[ap->exec_argc + 1];
-#endif
- for (i = 0; i < ap->exec_argc; i++)
- argv[i] = subst(ap->exec_argv[i], ap->subst_count[i], fileName);
- argv[i] = NULL; /* terminate the list */
+# if ENABLE_FEATURE_FIND_EXEC_PLUS
+ int size = ap->exec_argc + ap->filelist_idx + 1;
+# else
+ int size = ap->exec_argc + 1;
+# endif
+# if ENABLE_USE_PORTABLE_CODE
+ char **argv = alloca(sizeof(char*) * size);
+# else /* gcc 4.3.1 generates smaller code: */
+ char *argv[size];
+# endif
+ char **pp = argv;
+
+ for (i = 0; i < ap->exec_argc; i++) {
+ const char *arg = ap->exec_argv[i];
+
+# if ENABLE_FEATURE_FIND_EXEC_PLUS
+ if (ap->filelist) {
+ /* Handling "-exec +"
+ * Only one exec_argv[i] has substitution in it.
+ * Expand that one exec_argv[i] into file list.
+ */
+ if (ap->subst_count[i] == 0) {
+ *pp++ = xstrdup(arg);
+ } else {
+ int j = 0;
+ while (ap->filelist[j]) {
+ /* 2nd arg here should be ap->subst_count[i], but it is always 1: */
+ *pp++ = xmalloc_substitute_string(arg, 1, "{}", ap->filelist[j]);
+ free(ap->filelist[j]);
+ j++;
+ }
+ }
+ } else
+# endif
+ {
+ /* Handling "-exec ;" */
+ *pp++ = xmalloc_substitute_string(arg, ap->subst_count[i], "{}", fileName);
+ }
+ }
+ *pp = NULL; /* terminate the list */
+
+# if ENABLE_FEATURE_FIND_EXEC_PLUS
+ if (ap->filelist) {
+ ap->filelist[0] = NULL;
+ ap->filelist_idx = 0;
+ ap->file_len = 0;
+ }
+# endif
rc = spawn_and_wait(argv);
if (rc < 0)
@@ -626,6 +668,48 @@ ACTF(exec)
free(argv[i++]);
return rc == 0; /* return 1 if exitcode 0 */
}
+ACTF(exec)
+{
+# if ENABLE_FEATURE_FIND_EXEC_PLUS
+ if (ap->filelist) {
+ int rc;
+
+ ap->filelist = xrealloc_vector(ap->filelist, 8, ap->filelist_idx);
+ ap->filelist[ap->filelist_idx++] = xstrdup(fileName);
+ ap->file_len += strlen(fileName) + sizeof(char*) + 1;
+ /* If we have lots of files already, exec the command */
+ rc = 1;
+ if (ap->file_len >= G.max_argv_len)
+ rc = do_exec(ap, NULL);
+ return rc;
+ }
+# endif
+ return do_exec(ap, fileName);
+}
+# if ENABLE_FEATURE_FIND_EXEC_PLUS
+static int flush_exec_plus(void)
+{
+ action *ap;
+ action **app;
+ action ***appp = G.actions;
+ while ((app = *appp++) != NULL) {
+ while ((ap = *app++) != NULL) {
+ if (ap->f == (action_fp)func_exec) {
+ action_exec *ae = (void*)ap;
+ if (ae->filelist_idx != 0) {
+ int rc = do_exec(ae, NULL);
+# if ENABLE_FEATURE_FIND_NOT
+ if (ap->invert) rc = !rc;
+# endif
+ if (rc == 0)
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+# endif
#endif
#if ENABLE_FEATURE_FIND_USER
ACTF(user)
@@ -684,7 +768,10 @@ ACTF(delete)
{
int rc;
if (S_ISDIR(statbuf->st_mode)) {
- rc = rmdir(fileName);
+ /* "find . -delete" skips rmdir(".") */
+ rc = 0;
+ if (NOT_LONE_CHAR(fileName, '.'))
+ rc = rmdir(fileName);
} else {
rc = unlink(fileName);
}
@@ -728,10 +815,27 @@ static int FAST_FUNC fileAction(const char *fileName,
int depth IF_NOT_FEATURE_FIND_MAXDEPTH(UNUSED_PARAM))
{
int r;
+ int same_fs = 1;
+
+#if ENABLE_FEATURE_FIND_XDEV
+ if (S_ISDIR(statbuf->st_mode) && G.xdev_count) {
+ int i;
+ for (i = 0; i < G.xdev_count; i++) {
+ if (G.xdev_dev[i] == statbuf->st_dev)
+ goto found;
+ }
+ //bb_error_msg("'%s': not same fs", fileName);
+ same_fs = 0;
+ found: ;
+ }
+#endif
#if ENABLE_FEATURE_FIND_MAXDEPTH
- if (depth < G.minmaxdepth[0])
- return TRUE; /* skip this, continue recursing */
+ if (depth < G.minmaxdepth[0]) {
+ if (same_fs)
+ return TRUE; /* skip this, continue recursing */
+ return SKIP; /* stop recursing */
+ }
if (depth > G.minmaxdepth[1])
return SKIP; /* stop recursing */
#endif
@@ -747,21 +851,11 @@ static int FAST_FUNC fileAction(const char *fileName,
return SKIP;
}
#endif
-#if ENABLE_FEATURE_FIND_XDEV
/* -xdev stops on mountpoints, but AFTER mountpoit itself
* is processed as usual */
- if (S_ISDIR(statbuf->st_mode)) {
- if (G.xdev_count) {
- int i;
- for (i = 0; i < G.xdev_count; i++) {
- if (G.xdev_dev[i] == statbuf->st_dev)
- goto found;
- }
- return SKIP;
- found: ;
- }
+ if (!same_fs) {
+ return SKIP;
}
-#endif
/* Cannot return 0: our caller, recursive_action(),
* will perror() and skip dirs (if called on dir) */
@@ -790,7 +884,7 @@ static int find_type(const char *type)
mask = S_IFSOCK;
if (mask == 0 || type[1] != '\0')
- bb_error_msg_and_die(bb_msg_invalid_arg, type, "-type");
+ bb_error_msg_and_die(bb_msg_invalid_arg_to, type, "-type");
return mask;
}
@@ -807,6 +901,31 @@ static const char* plus_minus_num(const char* str)
}
#endif
+/* Say no to GCCism */
+#define USE_NESTED_FUNCTION 0
+
+#if !USE_NESTED_FUNCTION
+struct pp_locals {
+ action*** appp;
+ unsigned cur_group;
+ unsigned cur_action;
+ IF_FEATURE_FIND_NOT( bool invert_flag; )
+};
+static action* alloc_action(struct pp_locals *ppl, int sizeof_struct, action_fp f)
+{
+ action *ap = xzalloc(sizeof_struct);
+ action **app;
+ action ***group = &ppl->appp[ppl->cur_group];
+ *group = app = xrealloc(*group, (ppl->cur_action+2) * sizeof(ppl->appp[0][0]));
+ app[ppl->cur_action++] = ap;
+ app[ppl->cur_action] = NULL;
+ ap->f = f;
+ IF_FEATURE_FIND_NOT( ap->invert = ppl->invert_flag; )
+ IF_FEATURE_FIND_NOT( ppl->invert_flag = 0; )
+ return ap;
+}
+#endif
+
static action*** parse_params(char **argv)
{
enum {
@@ -871,8 +990,8 @@ static action*** parse_params(char **argv)
IF_FEATURE_FIND_EXEC( "-exec\0" )
IF_FEATURE_FIND_PAREN( "(\0" )
/* All options/actions starting from here require argument */
- "-name\0"
- "-iname\0"
+ "-name\0"
+ "-iname\0"
IF_FEATURE_FIND_PATH( "-path\0" )
#if ENABLE_DESKTOP
IF_FEATURE_FIND_PATH( "-wholename\0")
@@ -893,10 +1012,18 @@ static action*** parse_params(char **argv)
IF_FEATURE_FIND_MAXDEPTH("-mindepth\0""-maxdepth\0")
;
+#if !USE_NESTED_FUNCTION
+ struct pp_locals ppl;
+#define appp (ppl.appp )
+#define cur_group (ppl.cur_group )
+#define cur_action (ppl.cur_action )
+#define invert_flag (ppl.invert_flag)
+#define ALLOC_ACTION(name) (action_##name*)alloc_action(&ppl, sizeof(action_##name), (action_fp) func_##name)
+#else
action*** appp;
- unsigned cur_group = 0;
- unsigned cur_action = 0;
- IF_FEATURE_FIND_NOT( bool invert_flag = 0; )
+ unsigned cur_group;
+ unsigned cur_action;
+ IF_FEATURE_FIND_NOT( bool invert_flag; )
/* This is the only place in busybox where we use nested function.
* So far more standard alternatives were bigger. */
@@ -905,7 +1032,7 @@ static action*** parse_params(char **argv)
action* alloc_action(int sizeof_struct, action_fp f)
{
action *ap;
- appp[cur_group] = xrealloc(appp[cur_group], (cur_action+2) * sizeof(*appp));
+ appp[cur_group] = xrealloc(appp[cur_group], (cur_action+2) * sizeof(appp[0][0]));
appp[cur_group][cur_action++] = ap = xzalloc(sizeof_struct);
appp[cur_group][cur_action] = NULL;
ap->f = f;
@@ -913,9 +1040,12 @@ static action*** parse_params(char **argv)
IF_FEATURE_FIND_NOT( invert_flag = 0; )
return ap;
}
-
#define ALLOC_ACTION(name) (action_##name*)alloc_action(sizeof(action_##name), (action_fp) func_##name)
+#endif
+ cur_group = 0;
+ cur_action = 0;
+ IF_FEATURE_FIND_NOT( invert_flag = 0; )
appp = xzalloc(2 * sizeof(appp[0])); /* appp[0],[1] == NULL */
while (*argv) {
@@ -941,8 +1071,8 @@ static action*** parse_params(char **argv)
*/
/* Options */
if (parm == OPT_FOLLOW) {
- dbg("follow enabled: %d", __LINE__);
- G.recurse_flags |= ACTION_FOLLOWLINKS | ACTION_DANGLING_OK;
+ dbg("follow enabled: %d", __LINE__);
+ G.recurse_flags |= ACTION_FOLLOWLINKS | ACTION_DANGLING_OK;
}
#if ENABLE_FEATURE_FIND_XDEV
else if (parm == OPT_XDEV) {
@@ -980,7 +1110,7 @@ static action*** parse_params(char **argv)
dbg("%d", __LINE__);
/* start new OR group */
cur_group++;
- appp = xrealloc(appp, (cur_group+2) * sizeof(*appp));
+ appp = xrealloc(appp, (cur_group+2) * sizeof(appp[0]));
/*appp[cur_group] = NULL; - already NULL */
appp[cur_group+1] = NULL;
cur_action = 0;
@@ -1023,6 +1153,7 @@ static action*** parse_params(char **argv)
else if (parm == PARM_exec) {
int i;
action_exec *ap;
+ IF_FEATURE_FIND_EXEC_PLUS(int all_subst = 0;)
dbg("%d", __LINE__);
G.need_print = 0;
ap = ALLOC_ACTION(exec);
@@ -1035,10 +1166,13 @@ static action*** parse_params(char **argv)
// executes "echo Foo >FILENAME<",
// find -exec echo Foo ">{}<" "+"
// executes "echo Foo FILENAME1 FILENAME2 FILENAME3...".
- // TODO (so far we treat "+" just like ";")
if ((argv[0][0] == ';' || argv[0][0] == '+')
&& argv[0][1] == '\0'
) {
+# if ENABLE_FEATURE_FIND_EXEC_PLUS
+ if (argv[0][0] == '+')
+ ap->filelist = xzalloc(sizeof(ap->filelist[0]));
+# endif
break;
}
argv++;
@@ -1048,8 +1182,17 @@ static action*** parse_params(char **argv)
bb_error_msg_and_die(bb_msg_requires_arg, arg);
ap->subst_count = xmalloc(ap->exec_argc * sizeof(int));
i = ap->exec_argc;
- while (i--)
- ap->subst_count[i] = count_subst(ap->exec_argv[i]);
+ while (i--) {
+ ap->subst_count[i] = count_strstr(ap->exec_argv[i], "{}");
+ IF_FEATURE_FIND_EXEC_PLUS(all_subst += ap->subst_count[i];)
+ }
+# if ENABLE_FEATURE_FIND_EXEC_PLUS
+ /*
+ * coreutils expects {} to appear only once in "-exec +"
+ */
+ if (all_subst != 1 && ap->filelist)
+ bb_error_msg_and_die("only one '{}' allowed for -exec +");
+# endif
}
#endif
#if ENABLE_FEATURE_FIND_PAREN
@@ -1112,16 +1255,17 @@ static action*** parse_params(char **argv)
/* -perm BITS File's mode bits are exactly BITS (octal or symbolic).
* Symbolic modes use mode 0 as a point of departure.
* -perm -BITS All of the BITS are set in file's mode.
- * -perm +BITS At least one of the BITS is set in file's mode.
+ * -perm [+/]BITS At least one of the BITS is set in file's mode.
*/
else if (parm == PARM_perm) {
action_perm *ap;
dbg("%d", __LINE__);
ap = ALLOC_ACTION(perm);
ap->perm_char = arg1[0];
- arg1 = plus_minus_num(arg1);
+ arg1 = (arg1[0] == '/' ? arg1+1 : plus_minus_num(arg1));
/*ap->perm_mask = 0; - ALLOC_ACTION did it */
- if (!bb_parse_mode(arg1, &ap->perm_mask))
+ ap->perm_mask = bb_parse_mode(arg1, ap->perm_mask);
+ if (ap->perm_mask == (mode_t)-1)
bb_error_msg_and_die("invalid mode '%s'", arg1);
}
#endif
@@ -1238,16 +1382,46 @@ static action*** parse_params(char **argv)
dbg("exiting %s", __func__);
return appp;
#undef ALLOC_ACTION
+#undef appp
+#undef cur_action
+#undef invert_flag
}
int find_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int find_main(int argc UNUSED_PARAM, char **argv)
{
int i, firstopt, status = EXIT_SUCCESS;
+ char **past_HLP, *saved;
INIT_G();
- argv++;
+ /* "find -type f" + getopt("+HLP") => disaster.
+ * Need to avoid getopt running into a non-HLP option.
+ * Do this by temporarily storing NULL there:
+ */
+ past_HLP = argv;
+ for (;;) {
+ saved = *++past_HLP;
+ if (!saved)
+ break;
+ if (saved[0] != '-')
+ break;
+ if (!saved[1])
+ break; /* it is "-" */
+ if ((saved+1)[strspn(saved+1, "HLP")] != '\0')
+ break;
+ }
+ *past_HLP = NULL;
+ /* "+": stop on first non-option */
+ i = getopt32(argv, "+HLP");
+ if (i & (1<<0))
+ G.recurse_flags |= ACTION_FOLLOWLINKS_L0 | ACTION_DANGLING_OK;
+ if (i & (1<<1))
+ G.recurse_flags |= ACTION_FOLLOWLINKS | ACTION_DANGLING_OK;
+ /* -P is default and is ignored */
+ argv = past_HLP; /* same result as "argv += optind;" */
+ *past_HLP = saved;
+
for (firstopt = 0; argv[firstopt]; firstopt++) {
if (argv[firstopt][0] == '-')
break;
@@ -1290,9 +1464,10 @@ int find_main(int argc UNUSED_PARAM, char **argv)
NULL, /* user data */
0) /* depth */
) {
- status = EXIT_FAILURE;
+ status |= EXIT_FAILURE;
}
}
+ IF_FEATURE_FIND_EXEC_PLUS(status |= flush_exec_plus();)
return status;
}
diff --git a/release/src/router/busybox/findutils/grep.c b/release/src/router/busybox/findutils/grep.c
index f14d6e6c1c..aeb7977e95 100644
--- a/release/src/router/busybox/findutils/grep.c
+++ b/release/src/router/busybox/findutils/grep.c
@@ -58,6 +58,7 @@
//config: Print the specified number of context lines (-C).
#include "libbb.h"
+#include "common_bufsiz.h"
#include "xregex.h"
@@ -201,11 +202,10 @@ struct globals {
llist_t *pattern_head; /* growable list of patterns to match */
const char *cur_file; /* the current file we are reading */
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define INIT_G() do { \
- struct G_sizecheck { \
- char G_sizecheck[sizeof(G) > COMMON_BUFSIZE ? -1 : 1]; \
- }; \
+ setup_common_bufsiz(); \
+ BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
} while (0)
#define max_matches (G.max_matches )
#if !ENABLE_EXTRA_COMPAT
@@ -344,11 +344,42 @@ static int grep_file(FILE *file)
while (pattern_ptr) {
gl = (grep_list_data_t *)pattern_ptr->data;
if (FGREP_FLAG) {
- found |= (((option_mask32 & OPT_i)
- ? strcasestr(line, gl->pattern)
- : strstr(line, gl->pattern)
- ) != NULL);
+ char *match;
+ char *str = line;
+ opt_f_again:
+ match = ((option_mask32 & OPT_i)
+ ? strcasestr(str, gl->pattern)
+ : strstr(str, gl->pattern)
+ );
+ if (match) {
+ if (option_mask32 & OPT_x) {
+ if (match != str)
+ goto opt_f_not_found;
+ if (str[strlen(gl->pattern)] != '\0')
+ goto opt_f_not_found;
+ } else
+ if (option_mask32 & OPT_w) {
+ char c = (match != str) ? match[-1] : ' ';
+ if (!isalnum(c) && c != '_') {
+ c = match[strlen(gl->pattern)];
+ if (!c || (!isalnum(c) && c != '_'))
+ goto opt_f_found;
+ }
+ str = match + 1;
+ goto opt_f_again;
+ }
+ opt_f_found:
+ found = 1;
+ opt_f_not_found: ;
+ }
} else {
+#if ENABLE_EXTRA_COMPAT
+ unsigned start_pos;
+#else
+ int match_flg;
+#endif
+ char *match_at;
+
if (!(gl->flg_mem_alocated_compiled & COMPILED)) {
gl->flg_mem_alocated_compiled |= COMPILED;
#if !ENABLE_EXTRA_COMPAT
@@ -363,29 +394,58 @@ static int grep_file(FILE *file)
#if !ENABLE_EXTRA_COMPAT
gl->matched_range.rm_so = 0;
gl->matched_range.rm_eo = 0;
+ match_flg = 0;
+#else
+ start_pos = 0;
#endif
+ match_at = line;
+ opt_w_again:
+//bb_error_msg("'%s' start_pos:%d line_len:%d", match_at, start_pos, line_len);
if (
#if !ENABLE_EXTRA_COMPAT
- regexec(&gl->compiled_regex, line, 1, &gl->matched_range, 0) == 0
+ regexec(&gl->compiled_regex, match_at, 1, &gl->matched_range, match_flg) == 0
#else
- re_search(&gl->compiled_regex, line, line_len,
- /*start:*/ 0, /*range:*/ line_len,
+ re_search(&gl->compiled_regex, match_at, line_len,
+ start_pos, /*range:*/ line_len,
&gl->matched_range) >= 0
#endif
) {
if (option_mask32 & OPT_x) {
found = (gl->matched_range.rm_so == 0
- && line[gl->matched_range.rm_eo] == '\0');
- } else if (!(option_mask32 & OPT_w)) {
+ && match_at[gl->matched_range.rm_eo] == '\0');
+ } else
+ if (!(option_mask32 & OPT_w)) {
found = 1;
} else {
char c = ' ';
- if (gl->matched_range.rm_so)
- c = line[gl->matched_range.rm_so - 1];
+ if (match_at > line || gl->matched_range.rm_so != 0) {
+ c = match_at[gl->matched_range.rm_so - 1];
+ }
if (!isalnum(c) && c != '_') {
- c = line[gl->matched_range.rm_eo];
- if (!c || (!isalnum(c) && c != '_'))
- found = 1;
+ c = match_at[gl->matched_range.rm_eo];
+ }
+ if (!isalnum(c) && c != '_') {
+ found = 1;
+ } else {
+ /*
+ * Why check gl->matched_range.rm_eo?
+ * Zero-length match makes -w skip the line:
+ * "echo foo | grep ^" prints "foo",
+ * "echo foo | grep -w ^" prints nothing.
+ * Without such check, we can loop forever.
+ */
+#if !ENABLE_EXTRA_COMPAT
+ if (gl->matched_range.rm_eo != 0) {
+ match_at += gl->matched_range.rm_eo;
+ match_flg |= REG_NOTBOL;
+ goto opt_w_again;
+ }
+#else
+ if (gl->matched_range.rm_eo > start_pos) {
+ start_pos = gl->matched_range.rm_eo;
+ goto opt_w_again;
+ }
+#endif
}
}
}
@@ -608,7 +668,7 @@ static int grep_dir(const char *dir)
int matched = 0;
recursive_action(dir,
/* recurse=yes */ ACTION_RECURSE |
- /* followLinks=no */
+ /* followLinks=command line only */ ACTION_FOLLOWLINKS_L0 |
/* depthFirst=yes */ ACTION_DEPTHFIRST,
/* fileAction= */ file_action_grep,
/* dirAction= */ NULL,
@@ -623,11 +683,16 @@ int grep_main(int argc UNUSED_PARAM, char **argv)
FILE *file;
int matched;
llist_t *fopt = NULL;
-
- /* do normal option parsing */
#if ENABLE_FEATURE_GREP_CONTEXT
int Copt, opts;
+#endif
+ INIT_G();
+ /* For grep, exitcode of 1 is "not found". Other errors are 2: */
+ xfunc_error_retval = 2;
+
+ /* do normal option parsing */
+#if ENABLE_FEATURE_GREP_CONTEXT
/* -H unsets -h; -C unsets -A,-B; -e,-f are lists;
* -m,-A,-B,-C have numeric param */
opt_complementary = "H-h:C-AB:e::f::m+:A+:B+:C+";
@@ -638,7 +703,7 @@ int grep_main(int argc UNUSED_PARAM, char **argv)
if (opts & OPT_C) {
/* -C unsets prev -A and -B, but following -A or -B
- may override it */
+ * may override it */
if (!(opts & OPT_A)) /* not overridden */
lines_after = Copt;
if (!(opts & OPT_B)) /* not overridden */
@@ -683,7 +748,7 @@ int grep_main(int argc UNUSED_PARAM, char **argv)
option_mask32 |= OPT_F;
#if !ENABLE_EXTRA_COMPAT
- if (!(option_mask32 & (OPT_o | OPT_w)))
+ if (!(option_mask32 & (OPT_o | OPT_w | OPT_x)))
reflags = REG_NOSUB;
#endif
diff --git a/release/src/router/busybox/findutils/xargs.c b/release/src/router/busybox/findutils/xargs.c
index 0d1bb43fc8..ae01a49bea 100644
--- a/release/src/router/busybox/findutils/xargs.c
+++ b/release/src/router/busybox/findutils/xargs.c
@@ -53,12 +53,20 @@
//config: Support -0: input items are terminated by a NUL character
//config: instead of whitespace, and the quotes and backslash
//config: are not special.
+//config:
+//config:config FEATURE_XARGS_SUPPORT_REPL_STR
+//config: bool "Enable -I STR: string to replace"
+//config: default y
+//config: depends on XARGS
+//config: help
+//config: Support -I STR and -i[STR] options.
//applet:IF_XARGS(APPLET_NOEXEC(xargs, xargs, BB_DIR_USR_BIN, BB_SUID_DROP, xargs))
//kbuild:lib-$(CONFIG_XARGS) += xargs.o
#include "libbb.h"
+#include "common_bufsiz.h"
/* This is a NOEXEC applet. Be very careful! */
@@ -85,19 +93,23 @@
struct globals {
char **args;
+#if ENABLE_FEATURE_XARGS_SUPPORT_REPL_STR
+ char **argv;
+ const char *repl_str;
+ char eol_ch;
+#endif
const char *eof_str;
int idx;
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define INIT_G() do { \
+ setup_common_bufsiz(); \
G.eof_str = NULL; /* need to clear by hand because we are NOEXEC applet */ \
+ IF_FEATURE_XARGS_SUPPORT_REPL_STR(G.repl_str = "{}";) \
+ IF_FEATURE_XARGS_SUPPORT_REPL_STR(G.eol_ch = '\n';) \
} while (0)
-/*
- * This function has special algorithm.
- * Don't use fork and include to main!
- */
static int xargs_exec(void)
{
int status;
@@ -112,7 +124,7 @@ static int xargs_exec(void)
return 124;
}
if (status >= 0x180) {
- bb_error_msg("%s: terminated by signal %d",
+ bb_error_msg("'%s' terminated by signal %d",
G.args[0], status - 0x180);
return 125;
}
@@ -141,7 +153,7 @@ static void store_param(char *s)
* is seen, store the address of a new parameter to args[].
* If reading discovers that last chars do not form the complete
* parameter, the pointer to the first such "tail character" is returned.
- * (buf has extra byte at the end to accomodate terminating NUL
+ * (buf has extra byte at the end to accommodate terminating NUL
* of "tail characters" string).
* Otherwise, the returned pointer points to NUL byte.
* On entry, buf[] may contain some "seed chars" which are to become
@@ -301,7 +313,7 @@ static char* FAST_FUNC process0_stdin(int n_max_chars, int n_max_arg, char *buf)
c = '\0';
}
*p++ = c;
- if (c == '\0') { /* word's delimiter or EOF detected */
+ if (c == '\0') { /* NUL or EOF detected */
/* A full word is loaded */
store_param(s);
dbg_msg("args[]:'%s'", s);
@@ -323,10 +335,71 @@ static char* FAST_FUNC process0_stdin(int n_max_chars, int n_max_arg, char *buf)
}
#endif /* FEATURE_XARGS_SUPPORT_ZERO_TERM */
+#if ENABLE_FEATURE_XARGS_SUPPORT_REPL_STR
+/*
+ * Used if -I<repl> was specified.
+ * In this mode, words aren't appended to PROG ARGS.
+ * Instead, entire input line is read, then <repl> string
+ * in every PROG and ARG is replaced with the line:
+ * echo -e "ho ho\nhi" | xargs -I_ cmd __ _
+ * results in "cmd 'ho hoho ho' 'ho ho'"; "cmd 'hihi' 'hi'".
+ * -n MAX_ARGS seems to be ignored.
+ * Tested with GNU findutils 4.5.10.
+ */
+//FIXME: n_max_chars is not handled the same way as in GNU findutils.
+//FIXME: quoting is not implemented.
+static char* FAST_FUNC process_stdin_with_replace(int n_max_chars, int n_max_arg UNUSED_PARAM, char *buf)
+{
+ int i;
+ char *end, *p;
+
+ /* Free strings from last invocation, if any */
+ for (i = 0; G.args && G.args[i]; i++)
+ if (G.args[i] != G.argv[i])
+ free(G.args[i]);
+
+ end = buf + n_max_chars;
+ p = buf;
+
+ while (1) {
+ int c = getchar();
+ if (c == EOF || c == G.eol_ch) {
+ if (p == buf)
+ goto ret; /* empty line */
+ c = '\0';
+ }
+ *p++ = c;
+ if (c == '\0') { /* EOL or EOF detected */
+ i = 0;
+ while (G.argv[i]) {
+ char *arg = G.argv[i];
+ int count = count_strstr(arg, G.repl_str);
+ if (count != 0)
+ arg = xmalloc_substitute_string(arg, count, G.repl_str, buf);
+ store_param(arg);
+ dbg_msg("args[]:'%s'", arg);
+ i++;
+ }
+ p = buf;
+ goto ret;
+ }
+ if (p == end) {
+ goto ret;
+ }
+ }
+ ret:
+ *p = '\0';
+ /* store_param(NULL) - caller will do it */
+ dbg_msg("return:'%s'", buf);
+ return buf;
+}
+#endif
+
#if ENABLE_FEATURE_XARGS_SUPPORT_CONFIRMATION
/* Prompt the user for a response, and
- if the user responds affirmatively, return true;
- otherwise, return false. Uses "/dev/tty", not stdin. */
+ * if user responds affirmatively, return true;
+ * otherwise, return false. Uses "/dev/tty", not stdin.
+ */
static int xargs_ask_confirmation(void)
{
FILE *tty_stream;
@@ -360,6 +433,9 @@ static int xargs_ask_confirmation(void)
//usage: "\n -e[STR] STR stops input processing"
//usage: "\n -n N Pass no more than N args to PROG"
//usage: "\n -s N Pass command line of no more than N bytes"
+//usage: IF_FEATURE_XARGS_SUPPORT_REPL_STR(
+//usage: "\n -I STR Replace STR within PROG ARGS with input line"
+//usage: )
//usage: IF_FEATURE_XARGS_SUPPORT_TERMOPT(
//usage: "\n -x Exit if size is exceeded"
//usage: )
@@ -378,6 +454,8 @@ enum {
IF_FEATURE_XARGS_SUPPORT_CONFIRMATION(OPTBIT_INTERACTIVE,)
IF_FEATURE_XARGS_SUPPORT_TERMOPT( OPTBIT_TERMINATE ,)
IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( OPTBIT_ZEROTERM ,)
+ IF_FEATURE_XARGS_SUPPORT_REPL_STR( OPTBIT_REPLSTR ,)
+ IF_FEATURE_XARGS_SUPPORT_REPL_STR( OPTBIT_REPLSTR1 ,)
OPT_VERBOSE = 1 << OPTBIT_VERBOSE ,
OPT_NO_EMPTY = 1 << OPTBIT_NO_EMPTY ,
@@ -388,11 +466,14 @@ enum {
OPT_INTERACTIVE = IF_FEATURE_XARGS_SUPPORT_CONFIRMATION((1 << OPTBIT_INTERACTIVE)) + 0,
OPT_TERMINATE = IF_FEATURE_XARGS_SUPPORT_TERMOPT( (1 << OPTBIT_TERMINATE )) + 0,
OPT_ZEROTERM = IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( (1 << OPTBIT_ZEROTERM )) + 0,
+ OPT_REPLSTR = IF_FEATURE_XARGS_SUPPORT_REPL_STR( (1 << OPTBIT_REPLSTR )) + 0,
+ OPT_REPLSTR1 = IF_FEATURE_XARGS_SUPPORT_REPL_STR( (1 << OPTBIT_REPLSTR1 )) + 0,
};
#define OPTION_STR "+trn:s:e::E:" \
IF_FEATURE_XARGS_SUPPORT_CONFIRMATION("p") \
IF_FEATURE_XARGS_SUPPORT_TERMOPT( "x") \
- IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( "0")
+ IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( "0") \
+ IF_FEATURE_XARGS_SUPPORT_REPL_STR( "I:i::")
int xargs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int xargs_main(int argc, char **argv)
@@ -405,7 +486,8 @@ int xargs_main(int argc, char **argv)
unsigned opt;
int n_max_chars;
int n_max_arg;
-#if ENABLE_FEATURE_XARGS_SUPPORT_ZERO_TERM
+#if ENABLE_FEATURE_XARGS_SUPPORT_ZERO_TERM \
+ || ENABLE_FEATURE_XARGS_SUPPORT_REPL_STR
char* FAST_FUNC (*read_args)(int, int, char*) = process_stdin;
#else
#define read_args process_stdin
@@ -419,7 +501,10 @@ int xargs_main(int argc, char **argv)
"no-run-if-empty\0" No_argument "r"
;
#endif
- opt = getopt32(argv, OPTION_STR, &max_args, &max_chars, &G.eof_str, &G.eof_str);
+ opt = getopt32(argv, OPTION_STR,
+ &max_args, &max_chars, &G.eof_str, &G.eof_str
+ IF_FEATURE_XARGS_SUPPORT_REPL_STR(, &G.repl_str, &G.repl_str)
+ );
/* -E ""? You may wonder why not just omit -E?
* This is used for portability:
@@ -427,8 +512,10 @@ int xargs_main(int argc, char **argv)
if ((opt & OPT_EOF_STRING1) && G.eof_str[0] == '\0')
G.eof_str = NULL;
- if (opt & OPT_ZEROTERM)
- IF_FEATURE_XARGS_SUPPORT_ZERO_TERM(read_args = process0_stdin);
+ if (opt & OPT_ZEROTERM) {
+ IF_FEATURE_XARGS_SUPPORT_ZERO_TERM(read_args = process0_stdin;)
+ IF_FEATURE_XARGS_SUPPORT_REPL_STR(G.eol_ch = '\0';)
+ }
argv += optind;
argc -= optind;
@@ -438,12 +525,7 @@ int xargs_main(int argc, char **argv)
argc++;
}
- /* -s NUM default. fileutils-4.4.2 uses 128k, but I heasitate
- * to use such a big value - first need to change code to use
- * growable buffer instead of fixed one.
- */
- n_max_chars = 32 * 1024;
- /* Make smaller if system does not allow our default value.
+ /*
* The Open Group Base Specifications Issue 6:
* "The xargs utility shall limit the command line length such that
* when the command line is invoked, the combined argument
@@ -451,16 +533,15 @@ int xargs_main(int argc, char **argv)
* in the System Interfaces volume of IEEE Std 1003.1-2001)
* shall not exceed {ARG_MAX}-2048 bytes".
*/
- {
- long arg_max = 0;
-#if defined _SC_ARG_MAX
- arg_max = sysconf(_SC_ARG_MAX) - 2048;
-#elif defined ARG_MAX
- arg_max = ARG_MAX - 2048;
-#endif
- if (arg_max > 0 && n_max_chars > arg_max)
- n_max_chars = arg_max;
- }
+ n_max_chars = bb_arg_max();
+ if (n_max_chars > 32 * 1024)
+ n_max_chars = 32 * 1024;
+ /*
+ * POSIX suggests substracting 2048 bytes from sysconf(_SC_ARG_MAX)
+ * so that the process may safely modify its environment.
+ */
+ n_max_chars -= 2048;
+
if (opt & OPT_UPTO_SIZE) {
n_max_chars = xatou_range(max_chars, 1, INT_MAX);
}
@@ -486,20 +567,39 @@ int xargs_main(int argc, char **argv)
/* if (n_max_arg > n_max_chars) n_max_arg = n_max_chars */
}
- /* Allocate pointers for execvp */
- /* We can statically allocate (argc + n_max_arg + 1) elements
- * and do not bother with resizing args[], but on 64-bit machines
- * this results in args[] vector which is ~8 times bigger
- * than n_max_chars! That is, with n_max_chars == 20k,
- * args[] will take 160k (!), which will most likely be
- * almost entirely unused.
- */
- /* See store_param() for matching 256-step growth logic */
- G.args = xmalloc(sizeof(G.args[0]) * ((argc + 0xff) & ~0xff));
-
- /* Store the command to be executed, part 1 */
- for (i = 0; argv[i]; i++)
- G.args[i] = argv[i];
+#if ENABLE_FEATURE_XARGS_SUPPORT_REPL_STR
+ if (opt & (OPT_REPLSTR | OPT_REPLSTR1)) {
+ /*
+ * -I<str>:
+ * Unmodified args are kept in G.argv[i],
+ * G.args[i] receives malloced G.argv[i] with <str> replaced
+ * with input line. Setting this up:
+ */
+ G.args = NULL;
+ G.argv = argv;
+ argc = 0;
+ read_args = process_stdin_with_replace;
+ /* Make -I imply -r. GNU findutils seems to do the same: */
+ /* (otherwise "echo -n | xargs -I% echo %" would SEGV) */
+ opt |= OPT_NO_EMPTY;
+ } else
+#endif
+ {
+ /* Allocate pointers for execvp.
+ * We can statically allocate (argc + n_max_arg + 1) elements
+ * and do not bother with resizing args[], but on 64-bit machines
+ * this results in args[] vector which is ~8 times bigger
+ * than n_max_chars! That is, with n_max_chars == 20k,
+ * args[] will take 160k (!), which will most likely be
+ * almost entirely unused.
+ *
+ * See store_param() for matching 256-step growth logic
+ */
+ G.args = xmalloc(sizeof(G.args[0]) * ((argc + 0xff) & ~0xff));
+ /* Store the command to be executed, part 1 */
+ for (i = 0; argv[i]; i++)
+ G.args[i] = argv[i];
+ }
while (1) {
char *rem;
diff --git a/release/src/router/busybox/include/.gitignore b/release/src/router/busybox/include/.gitignore
index 9d9b6c4996..75afff9ca4 100644
--- a/release/src/router/busybox/include/.gitignore
+++ b/release/src/router/busybox/include/.gitignore
@@ -8,3 +8,4 @@
/NUM_APPLETS.h
/usage_compressed.h
/usage.h
+/common_bufsiz.h*
diff --git a/release/src/router/busybox/include/applets.src.h b/release/src/router/busybox/include/applets.src.h
index 2999e90d26..6e1b02fc39 100644
--- a/release/src/router/busybox/include/applets.src.h
+++ b/release/src/router/busybox/include/applets.src.h
@@ -8,7 +8,7 @@
/*
name - applet name as it is typed on command line
-name2 - applet name, converted to C (ether-wake: name2 = ether_wake)
+help - applet name, converted to C (ether-wake: help = ether_wake)
main - corresponding <applet>_main to call (bzcat: main = bunzip2)
l - location to install link to: [/usr]/[s]bin
s - suid type:
@@ -24,40 +24,46 @@ s - suid type:
#if defined(PROTOTYPES)
# define APPLET(name,l,s) int name##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-# define APPLET_ODDNAME(name,main,l,s,name2) int main##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-# define APPLET_NOEXEC(name,main,l,s,name2) int main##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-# define APPLET_NOFORK(name,main,l,s,name2) int main##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+# define APPLET_ODDNAME(name,main,l,s,help) int main##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+# define APPLET_NOEXEC(name,main,l,s,help) int main##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+# define APPLET_NOFORK(name,main,l,s,help) int main##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-#elif defined(NAME_MAIN_CNAME)
-# define APPLET(name,l,s) name name##_main name
-# define APPLET_ODDNAME(name,main,l,s,name2) name main##_main name2
-# define APPLET_NOEXEC(name,main,l,s,name2) name main##_main name2
-# define APPLET_NOFORK(name,main,l,s,name2) name main##_main name2
+#elif defined(NAME_MAIN)
+# define APPLET(name,l,s) name name##_main
+# define APPLET_ODDNAME(name,main,l,s,help) name main##_main
+# define APPLET_NOEXEC(name,main,l,s,help) name main##_main
+# define APPLET_NOFORK(name,main,l,s,help) name main##_main
#elif defined(MAKE_USAGE) && ENABLE_FEATURE_VERBOSE_USAGE
# define APPLET(name,l,s) MAKE_USAGE(#name, name##_trivial_usage name##_full_usage)
-# define APPLET_ODDNAME(name,main,l,s,name2) MAKE_USAGE(#name, name2##_trivial_usage name2##_full_usage)
-# define APPLET_NOEXEC(name,main,l,s,name2) MAKE_USAGE(#name, name2##_trivial_usage name2##_full_usage)
-# define APPLET_NOFORK(name,main,l,s,name2) MAKE_USAGE(#name, name2##_trivial_usage name2##_full_usage)
+# define APPLET_ODDNAME(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage help##_full_usage)
+# define APPLET_NOEXEC(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage help##_full_usage)
+# define APPLET_NOFORK(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage help##_full_usage)
#elif defined(MAKE_USAGE) && !ENABLE_FEATURE_VERBOSE_USAGE
# define APPLET(name,l,s) MAKE_USAGE(#name, name##_trivial_usage)
-# define APPLET_ODDNAME(name,main,l,s,name2) MAKE_USAGE(#name, name2##_trivial_usage)
-# define APPLET_NOEXEC(name,main,l,s,name2) MAKE_USAGE(#name, name2##_trivial_usage)
-# define APPLET_NOFORK(name,main,l,s,name2) MAKE_USAGE(#name, name2##_trivial_usage)
+# define APPLET_ODDNAME(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage)
+# define APPLET_NOEXEC(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage)
+# define APPLET_NOFORK(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage)
#elif defined(MAKE_LINKS)
# define APPLET(name,l,c) LINK l name
-# define APPLET_ODDNAME(name,main,l,s,name2) LINK l name
-# define APPLET_NOEXEC(name,main,l,s,name2) LINK l name
-# define APPLET_NOFORK(name,main,l,s,name2) LINK l name
+# define APPLET_ODDNAME(name,main,l,s,help) LINK l name
+# define APPLET_NOEXEC(name,main,l,s,help) LINK l name
+# define APPLET_NOFORK(name,main,l,s,help) LINK l name
+
+#elif defined(MAKE_SUID)
+# define APPLET(name,l,s) SUID s l name
+# define APPLET_ODDNAME(name,main,l,s,help) SUID s l name
+# define APPLET_NOEXEC(name,main,l,s,help) SUID s l name
+# define APPLET_NOFORK(name,main,l,s,help) SUID s l name
#else
static struct bb_applet applets[] = { /* name, main, location, need_suid */
# define APPLET(name,l,s) { #name, #name, l, s },
-# define APPLET_ODDNAME(name,main,l,s,name2) { #name, #main, l, s },
-# define APPLET_NOEXEC(name,main,l,s,name2) { #name, #main, l, s, 1 },
-# define APPLET_NOFORK(name,main,l,s,name2) { #name, #main, l, s, 1, 1 },
+# define APPLET_ODDNAME(name,main,l,s,help) { #name, #main, l, s },
+# define APPLET_NOEXEC(name,main,l,s,help) { #name, #main, l, s, 1 },
+# define APPLET_NOFORK(name,main,l,s,help) { #name, #main, l, s, 1, 1 },
#endif
#if ENABLE_INSTALL_NO_USR
@@ -70,75 +76,53 @@ INSERT
IF_TEST(APPLET_NOFORK([, test, BB_DIR_USR_BIN, BB_SUID_DROP, test))
IF_TEST(APPLET_NOFORK([[, test, BB_DIR_USR_BIN, BB_SUID_DROP, test))
IF_ACPID(APPLET(acpid, BB_DIR_SBIN, BB_SUID_DROP))
-IF_ADDGROUP(APPLET(addgroup, BB_DIR_BIN, BB_SUID_DROP))
-IF_ADDUSER(APPLET(adduser, BB_DIR_BIN, BB_SUID_DROP))
IF_ADJTIMEX(APPLET(adjtimex, BB_DIR_SBIN, BB_SUID_DROP))
-IF_AR(APPLET(ar, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_ARP(APPLET(arp, BB_DIR_SBIN, BB_SUID_DROP))
-IF_ARPING(APPLET(arping, BB_DIR_USR_BIN, BB_SUID_DROP))
-IF_AWK(APPLET_NOEXEC(awk, awk, BB_DIR_USR_BIN, BB_SUID_DROP, awk))
+IF_ARPING(APPLET(arping, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_BASENAME(APPLET_NOFORK(basename, basename, BB_DIR_USR_BIN, BB_SUID_DROP, basename))
IF_BBCONFIG(APPLET(bbconfig, BB_DIR_BIN, BB_SUID_DROP))
IF_BEEP(APPLET(beep, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_BLKID(APPLET(blkid, BB_DIR_SBIN, BB_SUID_DROP))
IF_BRCTL(APPLET(brctl, BB_DIR_USR_SBIN, BB_SUID_DROP))
-IF_BZIP2(APPLET(bzip2, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_CAL(APPLET(cal, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_CAT(APPLET_NOFORK(cat, cat, BB_DIR_BIN, BB_SUID_DROP, cat))
IF_CATV(APPLET(catv, BB_DIR_BIN, BB_SUID_DROP))
-IF_CHAT(APPLET(chat, BB_DIR_USR_BIN, BB_SUID_DROP))
-IF_CHATTR(APPLET(chattr, BB_DIR_BIN, BB_SUID_DROP))
+IF_CHAT(APPLET(chat, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_CHCON(APPLET(chcon, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_CHGRP(APPLET_NOEXEC(chgrp, chgrp, BB_DIR_BIN, BB_SUID_DROP, chgrp))
IF_CHMOD(APPLET_NOEXEC(chmod, chmod, BB_DIR_BIN, BB_SUID_DROP, chmod))
IF_CHOWN(APPLET_NOEXEC(chown, chown, BB_DIR_BIN, BB_SUID_DROP, chown))
-IF_CHPASSWD(APPLET(chpasswd, BB_DIR_USR_SBIN, BB_SUID_DROP))
-IF_CHPST(APPLET(chpst, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_CHROOT(APPLET(chroot, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_CHRT(APPLET(chrt, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_CHVT(APPLET(chvt, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_CKSUM(APPLET_NOEXEC(cksum, cksum, BB_DIR_USR_BIN, BB_SUID_DROP, cksum))
IF_CLEAR(APPLET(clear, BB_DIR_USR_BIN, BB_SUID_DROP))
-IF_CMP(APPLET(cmp, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_COMM(APPLET(comm, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_CP(APPLET_NOEXEC(cp, cp, BB_DIR_BIN, BB_SUID_DROP, cp))
-IF_CPIO(APPLET(cpio, BB_DIR_BIN, BB_SUID_DROP))
-IF_CROND(APPLET(crond, BB_DIR_USR_SBIN, BB_SUID_DROP))
/* Needs to be run by root or be suid root - needs to change /var/spool/cron* files: */
IF_CRONTAB(APPLET(crontab, BB_DIR_USR_BIN, BB_SUID_REQUIRE))
-IF_CRYPTPW(APPLET(cryptpw, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_CUT(APPLET_NOEXEC(cut, cut, BB_DIR_USR_BIN, BB_SUID_DROP, cut))
IF_DC(APPLET(dc, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_DD(APPLET_NOEXEC(dd, dd, BB_DIR_BIN, BB_SUID_DROP, dd))
IF_DEALLOCVT(APPLET(deallocvt, BB_DIR_USR_BIN, BB_SUID_DROP))
-IF_DELGROUP(APPLET_ODDNAME(delgroup, deluser, BB_DIR_BIN, BB_SUID_DROP, delgroup))
-IF_DELUSER(APPLET(deluser, BB_DIR_BIN, BB_SUID_DROP))
IF_DEVFSD(APPLET(devfsd, BB_DIR_SBIN, BB_SUID_DROP))
IF_DEVMEM(APPLET(devmem, BB_DIR_SBIN, BB_SUID_DROP))
IF_DF(APPLET(df, BB_DIR_BIN, BB_SUID_DROP))
-IF_DHCP6C(APPLET(dhcp6c, BB_DIR_SBIN, BB_SUID_DROP))
-IF_DHCP6RELAY(APPLET(dhcp6relay, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_DHCPRELAY(APPLET(dhcprelay, BB_DIR_USR_SBIN, BB_SUID_DROP))
-IF_DIFF(APPLET(diff, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_DIRNAME(APPLET_NOFORK(dirname, dirname, BB_DIR_USR_BIN, BB_SUID_DROP, dirname))
IF_DMESG(APPLET(dmesg, BB_DIR_BIN, BB_SUID_DROP))
IF_DNSD(APPLET(dnsd, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_HOSTNAME(APPLET_ODDNAME(dnsdomainname, hostname, BB_DIR_BIN, BB_SUID_DROP, dnsdomainname))
IF_DOS2UNIX(APPLET_NOEXEC(dos2unix, dos2unix, BB_DIR_USR_BIN, BB_SUID_DROP, dos2unix))
-IF_DPKG(APPLET(dpkg, BB_DIR_USR_BIN, BB_SUID_DROP))
-IF_DPKG_DEB(APPLET_ODDNAME(dpkg-deb, dpkg_deb, BB_DIR_USR_BIN, BB_SUID_DROP, dpkg_deb))
IF_DU(APPLET(du, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_DUMPKMAP(APPLET(dumpkmap, BB_DIR_BIN, BB_SUID_DROP))
IF_DUMPLEASES(APPLET(dumpleases, BB_DIR_USR_BIN, BB_SUID_DROP))
//IF_E2FSCK(APPLET(e2fsck, BB_DIR_SBIN, BB_SUID_DROP))
//IF_E2LABEL(APPLET_ODDNAME(e2label, tune2fs, BB_DIR_SBIN, BB_SUID_DROP, e2label))
IF_ECHO(APPLET_NOFORK(echo, echo, BB_DIR_BIN, BB_SUID_DROP, echo))
-IF_ED(APPLET(ed, BB_DIR_BIN, BB_SUID_DROP))
IF_EJECT(APPLET(eject, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_ENV(APPLET_NOEXEC(env, env, BB_DIR_USR_BIN, BB_SUID_DROP, env))
-IF_ENVDIR(APPLET_ODDNAME(envdir, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, envdir))
-IF_ENVUIDGID(APPLET_ODDNAME(envuidgid, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, envuidgid))
-IF_ETHER_WAKE(APPLET_ODDNAME(ether-wake, ether_wake, BB_DIR_USR_BIN, BB_SUID_DROP, ether_wake))
+IF_ETHER_WAKE(APPLET_ODDNAME(ether-wake, ether_wake, BB_DIR_USR_SBIN, BB_SUID_DROP, ether_wake))
IF_EXPAND(APPLET(expand, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_EXPR(APPLET(expr, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_FAKEIDENTD(APPLET(fakeidentd, BB_DIR_USR_SBIN, BB_SUID_DROP))
@@ -146,7 +130,7 @@ IF_FALSE(APPLET_NOFORK(false, false, BB_DIR_BIN, BB_SUID_DROP, false))
IF_FBSET(APPLET(fbset, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_FBSPLASH(APPLET(fbsplash, BB_DIR_SBIN, BB_SUID_DROP))
IF_FDFLUSH(APPLET_ODDNAME(fdflush, freeramdisk, BB_DIR_BIN, BB_SUID_DROP, fdflush))
-IF_FDFORMAT(APPLET(fdformat, BB_DIR_USR_BIN, BB_SUID_DROP))
+IF_FDFORMAT(APPLET(fdformat, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_FDISK(APPLET(fdisk, BB_DIR_SBIN, BB_SUID_DROP))
IF_FGCONSOLE(APPLET(fgconsole, BB_DIR_USR_BIN, BB_SUID_DROP))
/* Benefits from suid root: better access to /dev/BLOCKDEVs: */
@@ -159,7 +143,6 @@ IF_FLOCK(APPLET(flock, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_FOLD(APPLET_NOEXEC(fold, fold, BB_DIR_USR_BIN, BB_SUID_DROP, fold))
IF_FREE(APPLET(free, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_FREERAMDISK(APPLET(freeramdisk, BB_DIR_SBIN, BB_SUID_DROP))
-IF_FSCK(APPLET(fsck, BB_DIR_SBIN, BB_SUID_DROP))
//IF_E2FSCK(APPLET_ODDNAME(fsck.ext2, e2fsck, BB_DIR_SBIN, BB_SUID_DROP, fsck_ext2))
//IF_E2FSCK(APPLET_ODDNAME(fsck.ext3, e2fsck, BB_DIR_SBIN, BB_SUID_DROP, fsck_ext3))
IF_FSCK_MINIX(APPLET_ODDNAME(fsck.minix, fsck_minix, BB_DIR_SBIN, BB_SUID_DROP, fsck_minix))
@@ -171,9 +154,6 @@ IF_FUSER(APPLET(fuser, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_GETENFORCE(APPLET(getenforce, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_GETOPT(APPLET(getopt, BB_DIR_BIN, BB_SUID_DROP))
IF_GETSEBOOL(APPLET(getsebool, BB_DIR_USR_SBIN, BB_SUID_DROP))
-IF_GETTY(APPLET(getty, BB_DIR_SBIN, BB_SUID_DROP))
-IF_GUNZIP(APPLET(gunzip, BB_DIR_BIN, BB_SUID_DROP))
-IF_GZIP(APPLET(gzip, BB_DIR_BIN, BB_SUID_DROP))
IF_HD(APPLET_NOEXEC(hd, hexdump, BB_DIR_USR_BIN, BB_SUID_DROP, hd))
IF_HDPARM(APPLET(hdparm, BB_DIR_SBIN, BB_SUID_DROP))
IF_HEAD(APPLET_NOEXEC(head, head, BB_DIR_USR_BIN, BB_SUID_DROP, head))
@@ -184,7 +164,7 @@ IF_HWCLOCK(APPLET(hwclock, BB_DIR_SBIN, BB_SUID_DROP))
IF_IFCONFIG(APPLET(ifconfig, BB_DIR_SBIN, BB_SUID_DROP))
IF_IFUPDOWN(APPLET_ODDNAME(ifdown, ifupdown, BB_DIR_SBIN, BB_SUID_DROP, ifdown))
IF_IFENSLAVE(APPLET(ifenslave, BB_DIR_SBIN, BB_SUID_DROP))
-IF_IFPLUGD(APPLET(ifplugd, BB_DIR_USR_BIN, BB_SUID_DROP))
+IF_IFPLUGD(APPLET(ifplugd, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_IFUPDOWN(APPLET_ODDNAME(ifup, ifupdown, BB_DIR_SBIN, BB_SUID_DROP, ifup))
IF_INETD(APPLET(inetd, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_INOTIFYD(APPLET(inotifyd, BB_DIR_SBIN, BB_SUID_DROP))
@@ -195,66 +175,49 @@ IF_IONICE(APPLET(ionice, BB_DIR_BIN, BB_SUID_DROP))
|| ENABLE_FEATURE_IP_LINK \
|| ENABLE_FEATURE_IP_TUNNEL \
|| ENABLE_FEATURE_IP_RULE
-IF_IP(APPLET(ip, BB_DIR_BIN, BB_SUID_DROP))
+IF_IP(APPLET(ip, BB_DIR_SBIN, BB_SUID_DROP))
#endif
-IF_IPADDR(APPLET(ipaddr, BB_DIR_BIN, BB_SUID_DROP))
+IF_IPADDR(APPLET(ipaddr, BB_DIR_SBIN, BB_SUID_DROP))
IF_IPCALC(APPLET(ipcalc, BB_DIR_BIN, BB_SUID_DROP))
IF_IPCRM(APPLET(ipcrm, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_IPCS(APPLET(ipcs, BB_DIR_USR_BIN, BB_SUID_DROP))
-IF_IPLINK(APPLET(iplink, BB_DIR_BIN, BB_SUID_DROP))
-IF_IPROUTE(APPLET(iproute, BB_DIR_BIN, BB_SUID_DROP))
-IF_IPRULE(APPLET(iprule, BB_DIR_BIN, BB_SUID_DROP))
-IF_IPTUNNEL(APPLET(iptunnel, BB_DIR_BIN, BB_SUID_DROP))
-IF_KBD_MODE(APPLET(kbd_mode, BB_DIR_USR_BIN, BB_SUID_DROP))
+IF_IPLINK(APPLET(iplink, BB_DIR_SBIN, BB_SUID_DROP))
+IF_IPROUTE(APPLET(iproute, BB_DIR_SBIN, BB_SUID_DROP))
+IF_IPRULE(APPLET(iprule, BB_DIR_SBIN, BB_SUID_DROP))
+IF_IPTUNNEL(APPLET(iptunnel, BB_DIR_SBIN, BB_SUID_DROP))
+IF_KBD_MODE(APPLET(kbd_mode, BB_DIR_BIN, BB_SUID_DROP))
IF_KILL(APPLET(kill, BB_DIR_BIN, BB_SUID_DROP))
IF_KILLALL(APPLET_ODDNAME(killall, kill, BB_DIR_USR_BIN, BB_SUID_DROP, killall))
-IF_KILLALL5(APPLET_ODDNAME(killall5, kill, BB_DIR_USR_BIN, BB_SUID_DROP, killall5))
-IF_KLOGD(APPLET(klogd, BB_DIR_SBIN, BB_SUID_DROP))
+IF_KILLALL5(APPLET_ODDNAME(killall5, kill, BB_DIR_USR_SBIN, BB_SUID_DROP, killall5))
IF_LAST(APPLET(last, BB_DIR_USR_BIN, BB_SUID_DROP))
//IF_LENGTH(APPLET_NOFORK(length, length, BB_DIR_USR_BIN, BB_SUID_DROP, length))
IF_LESS(APPLET(less, BB_DIR_USR_BIN, BB_SUID_DROP))
-IF_SETARCH(APPLET_ODDNAME(linux32, setarch, BB_DIR_BIN, BB_SUID_DROP, linux32))
-IF_SETARCH(APPLET_ODDNAME(linux64, setarch, BB_DIR_BIN, BB_SUID_DROP, linux64))
IF_LN(APPLET_NOEXEC(ln, ln, BB_DIR_BIN, BB_SUID_DROP, ln))
IF_LOAD_POLICY(APPLET(load_policy, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_LOADFONT(APPLET(loadfont, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_LOADKMAP(APPLET(loadkmap, BB_DIR_SBIN, BB_SUID_DROP))
-IF_LOGGER(APPLET(logger, BB_DIR_USR_BIN, BB_SUID_DROP))
-/* Needs to be run by root or be suid root - needs to change uid and gid: */
-IF_LOGIN(APPLET(login, BB_DIR_BIN, BB_SUID_REQUIRE))
IF_LOGNAME(APPLET_NOFORK(logname, logname, BB_DIR_USR_BIN, BB_SUID_DROP, logname))
-IF_LOGREAD(APPLET(logread, BB_DIR_SBIN, BB_SUID_DROP))
IF_LOSETUP(APPLET(losetup, BB_DIR_SBIN, BB_SUID_DROP))
-IF_LPD(APPLET(lpd, BB_DIR_USR_SBIN, BB_SUID_DROP))
-IF_LPQ(APPLET_ODDNAME(lpq, lpqr, BB_DIR_USR_BIN, BB_SUID_DROP, lpq))
-IF_LPR(APPLET_ODDNAME(lpr, lpqr, BB_DIR_USR_BIN, BB_SUID_DROP, lpr))
IF_LS(APPLET_NOEXEC(ls, ls, BB_DIR_BIN, BB_SUID_DROP, ls))
-IF_LSATTR(APPLET(lsattr, BB_DIR_BIN, BB_SUID_DROP))
IF_LSPCI(APPLET(lspci, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_LSUSB(APPLET(lsusb, BB_DIR_USR_BIN, BB_SUID_DROP))
-IF_UNLZMA(APPLET_ODDNAME(lzcat, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzcat))
-IF_LZMA(APPLET_ODDNAME(lzma, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzma))
-IF_LZOP(APPLET(lzop, BB_DIR_BIN, BB_SUID_DROP))
-IF_LZOP(APPLET_ODDNAME(lzopcat, lzop, BB_DIR_USR_BIN, BB_SUID_DROP, lzopcat))
IF_MAKEDEVS(APPLET(makedevs, BB_DIR_SBIN, BB_SUID_DROP))
IF_MAKEMIME(APPLET(makemime, BB_DIR_BIN, BB_SUID_DROP))
-IF_MAN(APPLET(man, BB_DIR_SBIN, BB_SUID_DROP))
+IF_MAN(APPLET(man, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_MATCHPATHCON(APPLET(matchpathcon, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_MD5SUM(APPLET_NOEXEC(md5sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, md5sum))
IF_MICROCOM(APPLET(microcom, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_MKDIR(APPLET_NOFORK(mkdir, mkdir, BB_DIR_BIN, BB_SUID_DROP, mkdir))
IF_MKFS_VFAT(APPLET_ODDNAME(mkdosfs, mkfs_vfat, BB_DIR_SBIN, BB_SUID_DROP, mkfs_vfat))
-//IF_MKE2FS(APPLET_ODDNAME(mke2fs, mkfs_ext2, BB_DIR_SBIN, BB_SUID_DROP, mkfs_ext2))
+IF_MKFS_EXT2(APPLET_ODDNAME(mke2fs, mkfs_ext2, BB_DIR_SBIN, BB_SUID_DROP, mkfs_ext2))
IF_MKFIFO(APPLET_NOEXEC(mkfifo, mkfifo, BB_DIR_USR_BIN, BB_SUID_DROP, mkfifo))
-//IF_MKE2FS(APPLET_ODDNAME(mkfs.ext2, mkfs_ext2, BB_DIR_SBIN, BB_SUID_DROP, mkfs_ext2))
-//IF_MKE2FS(APPLET_ODDNAME(mkfs.ext3, mkfs_ext2, BB_DIR_SBIN, BB_SUID_DROP, mkfs_ext3))
+IF_MKFS_EXT2(APPLET_ODDNAME(mkfs.ext2, mkfs_ext2, BB_DIR_SBIN, BB_SUID_DROP, mkfs_ext2))
+//IF_MKE2FS(APPLET_ODDNAME(mkfs.ext3, mke2fs, BB_DIR_SBIN, BB_SUID_DROP, mkfs_ext3))
IF_MKFS_MINIX(APPLET_ODDNAME(mkfs.minix, mkfs_minix, BB_DIR_SBIN, BB_SUID_DROP, mkfs_minix))
IF_MKFS_REISER(APPLET_ODDNAME(mkfs.reiser, mkfs_reiser, BB_DIR_SBIN, BB_SUID_DROP, mkfs_reiser))
IF_MKFS_VFAT(APPLET_ODDNAME(mkfs.vfat, mkfs_vfat, BB_DIR_SBIN, BB_SUID_DROP, mkfs_vfat))
IF_MKNOD(APPLET_NOEXEC(mknod, mknod, BB_DIR_BIN, BB_SUID_DROP, mknod))
-IF_CRYPTPW(APPLET_ODDNAME(mkpasswd, cryptpw, BB_DIR_USR_BIN, BB_SUID_DROP, mkpasswd))
IF_MKSWAP(APPLET(mkswap, BB_DIR_SBIN, BB_SUID_DROP))
-IF_MKTEMP(APPLET(mktemp, BB_DIR_BIN, BB_SUID_DROP))
IF_MORE(APPLET(more, BB_DIR_BIN, BB_SUID_DROP))
/* On full-blown systems, requires suid for user mounts.
* But it's not unthinkable to have it available in non-suid flavor on some systems,
@@ -274,11 +237,8 @@ IF_NTPD(APPLET(ntpd, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_OD(APPLET(od, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_OPENVT(APPLET(openvt, BB_DIR_USR_BIN, BB_SUID_DROP))
//IF_PARSE(APPLET(parse, BB_DIR_USR_BIN, BB_SUID_DROP))
-/* Needs to be run by root or be suid root - needs to change /etc/{passwd,shadow}: */
-IF_PASSWD(APPLET(passwd, BB_DIR_USR_BIN, BB_SUID_REQUIRE))
IF_PGREP(APPLET(pgrep, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_PIDOF(APPLET(pidof, BB_DIR_BIN, BB_SUID_DROP))
-IF_PIPE_PROGRESS(APPLET(pipe_progress, BB_DIR_BIN, BB_SUID_DROP))
IF_PIVOT_ROOT(APPLET(pivot_root, BB_DIR_SBIN, BB_SUID_DROP))
IF_PKILL(APPLET_ODDNAME(pkill, pgrep, BB_DIR_USR_BIN, BB_SUID_DROP, pkill))
IF_POPMAILDIR(APPLET(popmaildir, BB_DIR_USR_SBIN, BB_SUID_DROP))
@@ -290,7 +250,7 @@ IF_PWD(APPLET_NOFORK(pwd, pwd, BB_DIR_BIN, BB_SUID_DROP, pwd))
IF_RAIDAUTORUN(APPLET(raidautorun, BB_DIR_SBIN, BB_SUID_DROP))
IF_RDATE(APPLET(rdate, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_RDEV(APPLET(rdev, BB_DIR_USR_SBIN, BB_SUID_DROP))
-IF_READAHEAD(APPLET(readahead, BB_DIR_USR_BIN, BB_SUID_DROP))
+IF_READAHEAD(APPLET(readahead, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_READLINK(APPLET(readlink, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_READPROFILE(APPLET(readprofile, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_REALPATH(APPLET(realpath, BB_DIR_USR_BIN, BB_SUID_DROP))
@@ -299,27 +259,19 @@ IF_RENICE(APPLET(renice, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_RESET(APPLET(reset, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_RESIZE(APPLET(resize, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_RESTORECON(APPLET_ODDNAME(restorecon, setfiles, BB_DIR_SBIN, BB_SUID_DROP, restorecon))
-IF_RFKILL(APPLET(rfkill, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_RM(APPLET_NOFORK(rm, rm, BB_DIR_BIN, BB_SUID_DROP, rm))
IF_RMDIR(APPLET_NOFORK(rmdir, rmdir, BB_DIR_BIN, BB_SUID_DROP, rmdir))
IF_ROUTE(APPLET(route, BB_DIR_SBIN, BB_SUID_DROP))
-IF_RPM(APPLET(rpm, BB_DIR_BIN, BB_SUID_DROP))
-IF_RPM2CPIO(APPLET(rpm2cpio, BB_DIR_USR_BIN, BB_SUID_DROP))
-IF_RTCWAKE(APPLET(rtcwake, BB_DIR_USR_BIN, BB_SUID_DROP))
-IF_RUN_PARTS(APPLET_ODDNAME(run-parts, run_parts, BB_DIR_BIN, BB_SUID_DROP, run_parts))
+IF_RTCWAKE(APPLET(rtcwake, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_RUNCON(APPLET(runcon, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_RUNLEVEL(APPLET(runlevel, BB_DIR_SBIN, BB_SUID_DROP))
-IF_RUNSV(APPLET(runsv, BB_DIR_USR_BIN, BB_SUID_DROP))
-IF_RUNSVDIR(APPLET(runsvdir, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_RX(APPLET(rx, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_SCRIPT(APPLET(script, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_SCRIPTREPLAY(APPLET(scriptreplay, BB_DIR_BIN, BB_SUID_DROP))
-IF_SED(APPLET(sed, BB_DIR_BIN, BB_SUID_DROP))
IF_SELINUXENABLED(APPLET(selinuxenabled, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_SENDMAIL(APPLET(sendmail, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_SEQ(APPLET_NOFORK(seq, seq, BB_DIR_USR_BIN, BB_SUID_DROP, seq))
IF_SESTATUS(APPLET(sestatus, BB_DIR_USR_SBIN, BB_SUID_DROP))
-IF_SETARCH(APPLET(setarch, BB_DIR_BIN, BB_SUID_DROP))
IF_SETCONSOLE(APPLET(setconsole, BB_DIR_SBIN, BB_SUID_DROP))
IF_SETENFORCE(APPLET(setenforce, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_SETFILES(APPLET(setfiles, BB_DIR_SBIN, BB_SUID_DROP))
@@ -328,37 +280,26 @@ IF_SETKEYCODES(APPLET(setkeycodes, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_SETLOGCONS(APPLET(setlogcons, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_SETSEBOOL(APPLET(setsebool, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_SETSID(APPLET(setsid, BB_DIR_USR_BIN, BB_SUID_DROP))
-IF_SETUIDGID(APPLET_ODDNAME(setuidgid, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, setuidgid))
IF_SHA1SUM(APPLET_NOEXEC(sha1sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha1sum))
+IF_SHA3SUM(APPLET_NOEXEC(sha3sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha3sum))
IF_SHA256SUM(APPLET_NOEXEC(sha256sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha256sum))
IF_SHA512SUM(APPLET_NOEXEC(sha512sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha512sum))
IF_SHOWKEY(APPLET(showkey, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_SLATTACH(APPLET(slattach, BB_DIR_SBIN, BB_SUID_DROP))
/* Do not make this applet NOFORK. It breaks ^C-ing of pauses in shells: */
IF_SLEEP(APPLET(sleep, BB_DIR_BIN, BB_SUID_DROP))
-IF_SOFTLIMIT(APPLET_ODDNAME(softlimit, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, softlimit))
IF_SORT(APPLET_NOEXEC(sort, sort, BB_DIR_USR_BIN, BB_SUID_DROP, sort))
IF_SPLIT(APPLET(split, BB_DIR_USR_BIN, BB_SUID_DROP))
-IF_START_STOP_DAEMON(APPLET_ODDNAME(start-stop-daemon, start_stop_daemon, BB_DIR_SBIN, BB_SUID_DROP, start_stop_daemon))
IF_STAT(APPLET(stat, BB_DIR_BIN, BB_SUID_DROP))
IF_STRINGS(APPLET(strings, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_STTY(APPLET(stty, BB_DIR_BIN, BB_SUID_DROP))
-/* Needs to be run by root or be suid root - needs to change uid and gid: */
-IF_SU(APPLET(su, BB_DIR_BIN, BB_SUID_REQUIRE))
-IF_SULOGIN(APPLET(sulogin, BB_DIR_SBIN, BB_SUID_DROP))
IF_SUM(APPLET(sum, BB_DIR_USR_BIN, BB_SUID_DROP))
-IF_SV(APPLET(sv, BB_DIR_USR_BIN, BB_SUID_DROP))
-IF_SVLOGD(APPLET(svlogd, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_SWAPONOFF(APPLET_ODDNAME(swapoff, swap_on_off, BB_DIR_SBIN, BB_SUID_DROP, swapoff))
IF_SWAPONOFF(APPLET_ODDNAME(swapon, swap_on_off, BB_DIR_SBIN, BB_SUID_DROP, swapon))
IF_SWITCH_ROOT(APPLET(switch_root, BB_DIR_SBIN, BB_SUID_DROP))
-IF_SYNC(APPLET_NOFORK(sync, sync, BB_DIR_BIN, BB_SUID_DROP, sync))
IF_BB_SYSCTL(APPLET(sysctl, BB_DIR_SBIN, BB_SUID_DROP))
-IF_SYSLOGD(APPLET(syslogd, BB_DIR_SBIN, BB_SUID_DROP))
IF_TAC(APPLET_NOEXEC(tac, tac, BB_DIR_USR_BIN, BB_SUID_DROP, tac))
IF_TAIL(APPLET(tail, BB_DIR_USR_BIN, BB_SUID_DROP))
-IF_TAR(APPLET(tar, BB_DIR_BIN, BB_SUID_DROP))
-IF_TASKSET(APPLET(taskset, BB_DIR_USR_BIN, BB_SUID_DROP))
/* IF_TC(APPLET(tc, BB_DIR_SBIN, BB_SUID_DROP)) */
IF_TCPSVD(APPLET_ODDNAME(tcpsvd, tcpudpsvd, BB_DIR_USR_BIN, BB_SUID_DROP, tcpsvd))
IF_TEE(APPLET(tee, BB_DIR_USR_BIN, BB_SUID_DROP))
@@ -367,7 +308,7 @@ IF_TELNETD(APPLET(telnetd, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_TEST(APPLET_NOFORK(test, test, BB_DIR_USR_BIN, BB_SUID_DROP, test))
#if ENABLE_FEATURE_TFTP_GET || ENABLE_FEATURE_TFTP_PUT
IF_TFTP(APPLET(tftp, BB_DIR_USR_BIN, BB_SUID_DROP))
-IF_TFTPD(APPLET(tftpd, BB_DIR_USR_BIN, BB_SUID_DROP))
+IF_TFTPD(APPLET(tftpd, BB_DIR_USR_SBIN, BB_SUID_DROP))
#endif
IF_TIME(APPLET(time, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_TIMEOUT(APPLET(timeout, BB_DIR_USR_BIN, BB_SUID_DROP))
@@ -380,46 +321,29 @@ IF_TRUE(APPLET_NOFORK(true, true, BB_DIR_BIN, BB_SUID_DROP, true))
IF_TTY(APPLET(tty, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_TTYSIZE(APPLET(ttysize, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_TUNCTL(APPLET(tunctl, BB_DIR_SBIN, BB_SUID_DROP))
-IF_TUNE2FS(APPLET(tune2fs, BB_DIR_SBIN, BB_SUID_DROP))
IF_UDHCPC(APPLET(udhcpc, BB_DIR_SBIN, BB_SUID_DROP))
IF_UDHCPD(APPLET(udhcpd, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_UDPSVD(APPLET_ODDNAME(udpsvd, tcpudpsvd, BB_DIR_USR_BIN, BB_SUID_DROP, udpsvd))
IF_UMOUNT(APPLET(umount, BB_DIR_BIN, BB_SUID_DROP))
IF_UNAME(APPLET(uname, BB_DIR_BIN, BB_SUID_DROP))
-IF_UNCOMPRESS(APPLET(uncompress, BB_DIR_BIN, BB_SUID_DROP))
IF_UNEXPAND(APPLET_ODDNAME(unexpand, expand, BB_DIR_USR_BIN, BB_SUID_DROP, unexpand))
IF_UNIQ(APPLET(uniq, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_UNIX2DOS(APPLET_NOEXEC(unix2dos, dos2unix, BB_DIR_USR_BIN, BB_SUID_DROP, unix2dos))
-IF_UNXZ(APPLET(unxz, BB_DIR_USR_BIN, BB_SUID_DROP))
-IF_UNLZMA(APPLET(unlzma, BB_DIR_USR_BIN, BB_SUID_DROP))
-IF_LZOP(APPLET_ODDNAME(unlzop, lzop, BB_DIR_USR_BIN, BB_SUID_DROP, unlzop))
-IF_UNZIP(APPLET(unzip, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_UPTIME(APPLET(uptime, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_USLEEP(APPLET_NOFORK(usleep, usleep, BB_DIR_BIN, BB_SUID_DROP, usleep))
IF_UUDECODE(APPLET(uudecode, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_UUENCODE(APPLET(uuencode, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_VCONFIG(APPLET(vconfig, BB_DIR_SBIN, BB_SUID_DROP))
-/* Needs to be run by root or be suid root - needs to change uid and gid: */
-IF_VLOCK(APPLET(vlock, BB_DIR_USR_BIN, BB_SUID_REQUIRE))
IF_VOLNAME(APPLET(volname, BB_DIR_USR_BIN, BB_SUID_DROP))
-/* Needs to be run by root or be suid root - needs to write to /dev/TTY: */
-IF_WALL(APPLET(wall, BB_DIR_USR_BIN, BB_SUID_REQUIRE))
IF_WATCH(APPLET(watch, BB_DIR_BIN, BB_SUID_DROP))
IF_WATCHDOG(APPLET(watchdog, BB_DIR_SBIN, BB_SUID_DROP))
-IF_MDMM(APPLET(md, _BB_DIR_BIN, _BB_SUID_DROP))
-IF_MDMM(APPLET(mm, _BB_DIR_BIN, _BB_SUID_DROP))
-IF_ETHREG(APPLET(ethreg, _BB_DIR_BIN, _BB_SUID_DROP))
IF_WC(APPLET(wc, BB_DIR_USR_BIN, BB_SUID_DROP))
-IF_WGET(APPLET(wget, BB_DIR_USR_BIN, BB_SUID_DROP))
-IF_WHICH(APPLET(which, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_WHOAMI(APPLET_NOFORK(whoami, whoami, BB_DIR_USR_BIN, BB_SUID_DROP, whoami))
-IF_UNXZ(APPLET_ODDNAME(xzcat, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xzcat))
-IF_XZ(APPLET_ODDNAME(xz, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xz))
IF_YES(APPLET_NOFORK(yes, yes, BB_DIR_USR_BIN, BB_SUID_DROP, yes))
-IF_GUNZIP(APPLET_ODDNAME(zcat, gunzip, BB_DIR_BIN, BB_SUID_DROP, zcat))
IF_ZCIP(APPLET(zcip, BB_DIR_SBIN, BB_SUID_DROP))
-#if !defined(PROTOTYPES) && !defined(NAME_MAIN_CNAME) && !defined(MAKE_USAGE)
+#if !defined(PROTOTYPES) && !defined(NAME_MAIN) && !defined(MAKE_USAGE) \
+ && !defined(MAKE_LINKS) && !defined(MAKE_SUID)
};
#endif
diff --git a/release/src/router/busybox/include/bb_archive.h b/release/src/router/busybox/include/bb_archive.h
index 2043d8570d..2b9c5f04c6 100644
--- a/release/src/router/busybox/include/bb_archive.h
+++ b/release/src/router/busybox/include/bb_archive.h
@@ -77,6 +77,9 @@ typedef struct archive_handle_t {
off_t offset;
/* Archiver specific. Can make it a union if it ever gets big */
+#if ENABLE_FEATURE_TAR_LONG_OPTIONS
+ unsigned tar__strip_components;
+#endif
#define PAX_NEXT_FILE 0
#define PAX_GLOBAL 1
#if ENABLE_TAR || ENABLE_DPKG || ENABLE_DPKG_DEB
@@ -95,6 +98,7 @@ typedef struct archive_handle_t {
#endif
#if ENABLE_CPIO || ENABLE_RPM2CPIO || ENABLE_RPM
uoff_t cpio__blocks;
+ struct bb_uidgid_t cpio__owner;
struct hardlinks_t *cpio__hardlinks_to_create;
struct hardlinks_t *cpio__created_hardlinks;
#endif
@@ -121,6 +125,10 @@ typedef struct archive_handle_t {
#define ARCHIVE_DONT_RESTORE_PERM (1 << 6)
#define ARCHIVE_NUMERIC_OWNER (1 << 7)
#define ARCHIVE_O_TRUNC (1 << 8)
+#define ARCHIVE_REMEMBER_NAMES (1 << 9)
+#if ENABLE_RPM
+#define ARCHIVE_REPLACE_VIA_RENAME (1 << 10)
+#endif
/* POSIX tar Header Block, from POSIX 1003.1-1990 */
@@ -155,6 +163,8 @@ struct BUG_tar_header {
};
+extern const char cpio_TRAILER[];
+
archive_handle_t *init_handle(void) FAST_FUNC;
@@ -180,6 +190,7 @@ char get_header_tar(archive_handle_t *archive_handle) FAST_FUNC;
char get_header_tar_gz(archive_handle_t *archive_handle) FAST_FUNC;
char get_header_tar_bz2(archive_handle_t *archive_handle) FAST_FUNC;
char get_header_tar_lzma(archive_handle_t *archive_handle) FAST_FUNC;
+char get_header_tar_xz(archive_handle_t *archive_handle) FAST_FUNC;
void seek_by_jump(int fd, off_t amount) FAST_FUNC;
void seek_by_read(int fd, off_t amount) FAST_FUNC;
@@ -199,43 +210,57 @@ int read_bunzip(bunzip_data *bd, char *outbuf, int len) FAST_FUNC;
void dealloc_bunzip(bunzip_data *bd) FAST_FUNC;
/* Meaning and direction (input/output) of the fields are transformer-specific */
-typedef struct transformer_aux_data_t {
- smallint check_signature; /* most often referenced member */
+typedef struct transformer_state_t {
+ smallint signature_skipped; /* most often referenced member */
+
+ IF_DESKTOP(long long) int FAST_FUNC (*xformer)(struct transformer_state_t *xstate);
+ USE_FOR_NOMMU(const char *xformer_prog;)
+
+ /* Source */
+ int src_fd;
+ /* Output */
+ int dst_fd;
+ size_t mem_output_size_max; /* if non-zero, decompress to RAM instead of fd */
+ size_t mem_output_size;
+ char *mem_output_buf;
+
off_t bytes_out;
off_t bytes_in; /* used in unzip code only: needs to know packed size */
uint32_t crc32;
time_t mtime; /* gunzip code may set this on exit */
-} transformer_aux_data_t;
+} transformer_state_t;
-void init_transformer_aux_data(transformer_aux_data_t *aux) FAST_FUNC;
-int FAST_FUNC check_signature16(transformer_aux_data_t *aux, int src_fd, unsigned magic16) FAST_FUNC;
+void init_transformer_state(transformer_state_t *xstate) FAST_FUNC;
+ssize_t transformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize) FAST_FUNC;
+ssize_t xtransformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize) FAST_FUNC;
+int check_signature16(transformer_state_t *xstate, unsigned magic16) FAST_FUNC;
-IF_DESKTOP(long long) int inflate_unzip(transformer_aux_data_t *aux, int src_fd, int dst_fd) FAST_FUNC;
-IF_DESKTOP(long long) int unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) FAST_FUNC;
-IF_DESKTOP(long long) int unpack_gz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) FAST_FUNC;
-IF_DESKTOP(long long) int unpack_bz2_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) FAST_FUNC;
-IF_DESKTOP(long long) int unpack_lzma_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) FAST_FUNC;
-IF_DESKTOP(long long) int unpack_xz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) FAST_FUNC;
+IF_DESKTOP(long long) int inflate_unzip(transformer_state_t *xstate) FAST_FUNC;
+IF_DESKTOP(long long) int unpack_Z_stream(transformer_state_t *xstate) FAST_FUNC;
+IF_DESKTOP(long long) int unpack_gz_stream(transformer_state_t *xstate) FAST_FUNC;
+IF_DESKTOP(long long) int unpack_bz2_stream(transformer_state_t *xstate) FAST_FUNC;
+IF_DESKTOP(long long) int unpack_lzma_stream(transformer_state_t *xstate) FAST_FUNC;
+IF_DESKTOP(long long) int unpack_xz_stream(transformer_state_t *xstate) FAST_FUNC;
char* append_ext(char *filename, const char *expected_ext) FAST_FUNC;
int bbunpack(char **argv,
- IF_DESKTOP(long long) int FAST_FUNC (*unpacker)(transformer_aux_data_t *aux),
- char* FAST_FUNC (*make_new_name)(char *filename, const char *expected_ext),
- const char *expected_ext
+ IF_DESKTOP(long long) int FAST_FUNC (*unpacker)(transformer_state_t *xstate),
+ char* FAST_FUNC (*make_new_name)(char *filename, const char *expected_ext),
+ const char *expected_ext
) FAST_FUNC;
void check_errors_in_children(int signo);
#if BB_MMU
-void open_transformer(int fd,
- int check_signature,
- IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_aux_data_t *aux, int src_fd, int dst_fd)
+void fork_transformer(int fd,
+ int signature_skipped,
+ IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate)
) FAST_FUNC;
-#define open_transformer_with_sig(fd, transformer, transform_prog) open_transformer((fd), 1, (transformer))
-#define open_transformer_with_no_sig(fd, transformer) open_transformer((fd), 0, (transformer))
+#define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), 0, (transformer))
+#define fork_transformer_with_no_sig(fd, transformer) fork_transformer((fd), 1, (transformer))
#else
-void open_transformer(int fd, const char *transform_prog) FAST_FUNC;
-#define open_transformer_with_sig(fd, transformer, transform_prog) open_transformer((fd), (transform_prog))
-/* open_transformer_with_no_sig() does not exist on NOMMU */
+void fork_transformer(int fd, const char *transform_prog) FAST_FUNC;
+#define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), (transform_prog))
+/* fork_transformer_with_no_sig() does not exist on NOMMU */
#endif
diff --git a/release/src/router/busybox/include/bb_e2fs_defs.h b/release/src/router/busybox/include/bb_e2fs_defs.h
index 3edff8377c..3f5e3c45bd 100644
--- a/release/src/router/busybox/include/bb_e2fs_defs.h
+++ b/release/src/router/busybox/include/bb_e2fs_defs.h
@@ -406,21 +406,21 @@ struct ext2_super_block {
* Performance hints. Directory preallocation should only
* happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
*/
- uint8_t s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
- uint8_t s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
+ uint8_t s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
+ uint8_t s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
uint16_t s_reserved_gdt_blocks; /* Per group table for online growth */
/*
* Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
*/
- uint8_t s_journal_uuid[16]; /* uuid of journal superblock */
- uint32_t s_journal_inum; /* inode number of journal file */
+/*D0*/ uint8_t s_journal_uuid[16]; /* uuid of journal superblock */
+/*E0*/ uint32_t s_journal_inum; /* inode number of journal file */
uint32_t s_journal_dev; /* device number of journal file */
uint32_t s_last_orphan; /* start of list of inodes to delete */
uint32_t s_hash_seed[4]; /* HTREE hash seed */
uint8_t s_def_hash_version; /* Default hash version to use */
uint8_t s_jnl_backup_type; /* Default type of journal backup */
uint16_t s_reserved_word_pad;
- uint32_t s_default_mount_opts;
+/*100*/ uint32_t s_default_mount_opts;
uint32_t s_first_meta_bg; /* First metablock group */
/* ext3 additions */
uint32_t s_mkfs_time; /* When the filesystem was created */
@@ -442,7 +442,7 @@ struct ext2_super_block {
uint32_t s_reserved[162]; /* Padding to the end of the block */
};
struct BUG_ext2_super_block {
- char bug[sizeof(struct ext2_super_block) == 1024 ? 1 : -1];
+ char bug[sizeof(struct ext2_super_block) == 1024 ? 1 : -1];
};
/*
@@ -481,6 +481,7 @@ struct BUG_ext2_super_block {
#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \
( EXT2_SB(sb)->s_feature_incompat & (mask) )
+/* for s_feature_compat */
#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001
#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002
#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
@@ -488,23 +489,45 @@ struct BUG_ext2_super_block {
#define EXT2_FEATURE_COMPAT_RESIZE_INO 0x0010
#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020
+/* for s_feature_ro_compat */
#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
-/* #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 not used */
+#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 /* not used */
+#define EXT4_FEATURE_RO_COMPAT_HUGE_FILE 0x0008
+#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010
+#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020
+#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040
+/* for s_feature_incompat */
#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
-#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
-#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
+#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004
+#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008
#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010
-#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040
+#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040
+#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080
+#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
+#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
#define EXT2_FEATURE_COMPAT_SUPP 0
-#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE)
#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
+#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \
+ EXT2_FEATURE_INCOMPAT_META_BG)
+#define EXT2_FEATURE_INCOMPAT_UNSUPPORTED (~EXT2_FEATURE_INCOMPAT_SUPP)
+#define EXT2_FEATURE_RO_COMPAT_UNSUPPORTED (~EXT2_FEATURE_RO_COMPAT_SUPP)
+
+#define EXT3_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+ EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
+ EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
+#define EXT3_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \
+ EXT3_FEATURE_INCOMPAT_RECOVER| \
+ EXT2_FEATURE_INCOMPAT_META_BG)
+#define EXT3_FEATURE_INCOMPAT_UNSUPPORTED (~EXT3_FEATURE_INCOMPAT_SUPP)
+#define EXT3_FEATURE_RO_COMPAT_UNSUPPORTED (~EXT3_FEATURE_RO_COMPAT_SUPP)
+
/*
* Default values for user and/or group using reserved blocks
diff --git a/release/src/router/busybox/include/busybox.h b/release/src/router/busybox/include/busybox.h
index 315ef8f266..737627bd0d 100644
--- a/release/src/router/busybox/include/busybox.h
+++ b/release/src/router/busybox/include/busybox.h
@@ -13,27 +13,22 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
/* Defined in appletlib.c (by including generated applet_tables.h) */
/* Keep in sync with applets/applet_tables.c! */
-extern const char applet_names[];
+extern const char applet_names[] ALIGN1;
extern int (*const applet_main[])(int argc, char **argv);
-extern const uint16_t applet_nameofs[];
-extern const uint8_t applet_install_loc[];
-
-#if ENABLE_FEATURE_SUID || ENABLE_FEATURE_PREFER_APPLETS
-# define APPLET_NAME(i) (applet_names + (applet_nameofs[i] & 0x0fff))
-#else
-# define APPLET_NAME(i) (applet_names + applet_nameofs[i])
-#endif
+extern const uint8_t applet_flags[] ALIGN1;
+extern const uint8_t applet_suid[] ALIGN1;
+extern const uint8_t applet_install_loc[] ALIGN1;
#if ENABLE_FEATURE_PREFER_APPLETS
-# define APPLET_IS_NOFORK(i) (applet_nameofs[i] & (1 << 12))
-# define APPLET_IS_NOEXEC(i) (applet_nameofs[i] & (1 << 13))
+# define APPLET_IS_NOFORK(i) (applet_flags[(i)/4] & (1 << (2 * ((i)%4))))
+# define APPLET_IS_NOEXEC(i) (applet_flags[(i)/4] & (1 << ((2 * ((i)%4))+1)))
#else
# define APPLET_IS_NOFORK(i) 0
# define APPLET_IS_NOEXEC(i) 0
#endif
#if ENABLE_FEATURE_SUID
-# define APPLET_SUID(i) ((applet_nameofs[i] >> 14) & 0x3)
+# define APPLET_SUID(i) ((applet_suid[(i)/4] >> (2 * ((i)%4)) & 3))
#endif
#if ENABLE_FEATURE_INSTALLER
diff --git a/release/src/router/busybox/include/grp_.h b/release/src/router/busybox/include/grp_.h
index 82ad904921..db13ce3b42 100644
--- a/release/src/router/busybox/include/grp_.h
+++ b/release/src/router/busybox/include/grp_.h
@@ -30,89 +30,36 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
* so that function calls are directed to bb_internal_XXX replacements
*/
#undef endgrent
-#define setgrent bb_internal_setgrent
#define endgrent bb_internal_endgrent
-#define getgrent bb_internal_getgrent
-#define fgetgrent bb_internal_fgetgrent
-#define putgrent bb_internal_putgrent
#define getgrgid bb_internal_getgrgid
#define getgrnam bb_internal_getgrnam
-#define getgrent_r bb_internal_getgrent_r
-#define getgrgid_r bb_internal_getgrgid_r
-#define getgrnam_r bb_internal_getgrnam_r
-#define fgetgrent_r bb_internal_fgetgrent_r
#define getgrouplist bb_internal_getgrouplist
#define initgroups bb_internal_initgroups
-
/* All function names below should be remapped by #defines above
* in order to not collide with libc names. */
-
-/* Rewind the group-file stream. */
-extern void setgrent(void);
-
/* Close the group-file stream. */
-extern void endgrent(void);
-
-#ifdef UNUSED_SINCE_WE_AVOID_STATIC_BUFS
-/* Read an entry from the group-file stream, opening it if necessary. */
-extern struct group *getgrent(void);
-
-/* Read a group entry from STREAM. */
-extern struct group *fgetgrent(FILE *__stream);
-
-/* Write the given entry onto the given stream. */
-extern int putgrent(const struct group *__restrict __p,
- FILE *__restrict __f);
-#endif
-
-/* Search for an entry with a matching group ID. */
-extern struct group *getgrgid(gid_t __gid);
-
-/* Search for an entry with a matching group name. */
-extern struct group *getgrnam(const char *__name);
-
-/* Reentrant versions of some of the functions above.
-
- PLEASE NOTE: the `getgrent_r' function is not (yet) standardized.
- The interface may change in later versions of this library. But
- the interface is designed following the principals used for the
- other reentrant functions so the chances are good this is what the
- POSIX people would choose. */
-
-extern int getgrent_r(struct group *__restrict __resultbuf,
- char *__restrict __buffer, size_t __buflen,
- struct group **__restrict __result);
+void FAST_FUNC endgrent(void);
/* Search for an entry with a matching group ID. */
-extern int getgrgid_r(gid_t __gid, struct group *__restrict __resultbuf,
- char *__restrict __buffer, size_t __buflen,
- struct group **__restrict __result);
+struct group* FAST_FUNC getgrgid(gid_t __gid);
/* Search for an entry with a matching group name. */
-extern int getgrnam_r(const char *__restrict __name,
- struct group *__restrict __resultbuf,
- char *__restrict __buffer, size_t __buflen,
- struct group **__restrict __result);
+struct group* FAST_FUNC getgrnam(const char *__name);
-/* Read a group entry from STREAM. This function is not standardized
- an probably never will. */
-extern int fgetgrent_r(FILE *__restrict __stream,
- struct group *__restrict __resultbuf,
- char *__restrict __buffer, size_t __buflen,
- struct group **__restrict __result);
+/* Reentrant versions of some of the functions above. */
/* Store at most *NGROUPS members of the group set for USER into
*GROUPS. Also include GROUP. The actual number of groups found is
returned in *NGROUPS. Return -1 if the if *NGROUPS is too small. */
-extern int getgrouplist(const char *__user, gid_t __group,
- gid_t *__groups, int *__ngroups);
+int FAST_FUNC getgrouplist(const char *__user, gid_t __group,
+ gid_t *__groups, int *__ngroups);
/* Initialize the group set for the current user
by reading the group database and using all groups
of which USER is a member. Also include GROUP. */
-extern int initgroups(const char *__user, gid_t __group);
+int FAST_FUNC initgroups(const char *__user, gid_t __group);
POP_SAVED_FUNCTION_VISIBILITY
diff --git a/release/src/router/busybox/include/libbb.h b/release/src/router/busybox/include/libbb.h
index 8a2edd790c..031a463103 100644
--- a/release/src/router/busybox/include/libbb.h
+++ b/release/src/router/busybox/include/libbb.h
@@ -20,6 +20,7 @@
#include <netdb.h>
#include <setjmp.h>
#include <signal.h>
+#include <paths.h>
#if defined __UCLIBC__ /* TODO: and glibc? */
/* use inlined versions of these: */
# define sigfillset(s) __sigfillset(s)
@@ -32,12 +33,12 @@
#include <stdarg.h>
#include <stddef.h>
#include <string.h>
-/* There are two incompatible basename's, let not use them! */
+/* There are two incompatible basename's, let's not use them! */
/* See the dirname/basename man page for details */
#include <libgen.h> /* dirname,basename */
#undef basename
#define basename dont_use_basename
-#include <sys/poll.h>
+#include <poll.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/socket.h>
@@ -84,7 +85,34 @@
# include <selinux/av_permissions.h>
#endif
#if ENABLE_FEATURE_UTMP
-# include <utmp.h>
+# if defined __UCLIBC__ && ( \
+ (UCLIBC_VERSION >= KERNEL_VERSION(0, 9, 32) \
+ && UCLIBC_VERSION < KERNEL_VERSION(0, 9, 34) \
+ && defined __UCLIBC_HAS_UTMPX__ \
+ ) || ( \
+ UCLIBC_VERSION >= KERNEL_VERSION(0, 9, 34) \
+ ) \
+ )
+# include <utmpx.h>
+# elif defined __UCLIBC__
+# include <utmp.h>
+# define utmpx utmp
+# define setutxent setutent
+# define endutxent endutent
+# define getutxent getutent
+# define getutxid getutid
+# define getutxline getutline
+# define pututxline pututline
+# define utmpxname utmpname
+# define updwtmpx updwtmp
+# define _PATH_UTMPX _PATH_UTMP
+# else
+# include <utmp.h>
+# include <utmpx.h>
+# if defined _PATH_UTMP && !defined _PATH_UTMPX
+# define _PATH_UTMPX _PATH_UTMP
+# endif
+# endif
#endif
#if ENABLE_LOCALE_SUPPORT
# include <locale.h>
@@ -114,14 +142,18 @@
# include <netinet/in.h>
#else
# include <arpa/inet.h>
-# if !defined(__socklen_t_defined) && !defined(_SOCKLEN_T_DECLARED)
-/* We #define socklen_t *after* includes, otherwise we get
- * typedef redefinition errors from system headers
- * (in case "is it defined already" detection above failed)
- */
-# define socklen_t bb_socklen_t
- typedef unsigned socklen_t;
-# endif
+//This breaks on bionic:
+//# if !defined(__socklen_t_defined) && !defined(_SOCKLEN_T_DECLARED)
+///* We #define socklen_t *after* includes, otherwise we get
+// * typedef redefinition errors from system headers
+// * (in case "is it defined already" detection above failed)
+// */
+//# define socklen_t bb_socklen_t
+// typedef unsigned socklen_t;
+//# endif
+//if this is still needed, add a fix along the lines of
+// ifdef SPECIFIC_BROKEN_LIBC_CHECK / typedef socklen_t / endif
+//in platform.h instead!
#endif
#ifndef HAVE_CLEARENV
# define clearenv() do { if (environ) environ[0] = NULL; } while (0)
@@ -252,10 +284,10 @@ typedef unsigned long uoff_t;
/* Users report bionic to use 32-bit off_t even if LARGEFILE support is requested.
* We misdetected that. Don't let it build:
*/
-/* FIXME: This test was added recently - was it always broken in Tomato/Asuswrt? */
-//struct BUG_off_t_size_is_misdetected {
-// char BUG_off_t_size_is_misdetected[sizeof(off_t) == sizeof(uoff_t) ? 1 : -1];
-//};
+/* FIXME: This test was added recently - was it always broken in Tomato/Asuswrt?
+struct BUG_off_t_size_is_misdetected {
+ char BUG_off_t_size_is_misdetected[sizeof(off_t) == sizeof(uoff_t) ? 1 : -1];
+}; */
/* Some useful definitions */
#undef FALSE
@@ -320,7 +352,7 @@ extern char *strrstr(const char *haystack, const char *needle) FAST_FUNC;
//TODO: supply a pointer to char[11] buffer (avoid statics)?
extern const char *bb_mode_string(mode_t mode) FAST_FUNC;
extern int is_directory(const char *name, int followLinks) FAST_FUNC;
-enum { /* DO NOT CHANGE THESE VALUES! cp.c, mv.c, install.c depend on them. */
+enum { /* cp.c, mv.c, install.c depend on these values. CAREFUL when changing them! */
FILEUTILS_PRESERVE_STATUS = 1 << 0, /* -p */
FILEUTILS_DEREFERENCE = 1 << 1, /* !-d */
FILEUTILS_RECUR = 1 << 2, /* -R */
@@ -330,12 +362,25 @@ enum { /* DO NOT CHANGE THESE VALUES! cp.c, mv.c, install.c depend on them. */
FILEUTILS_MAKE_SOFTLINK = 1 << 6, /* -s */
FILEUTILS_DEREF_SOFTLINK = 1 << 7, /* -L */
FILEUTILS_DEREFERENCE_L0 = 1 << 8, /* -H */
+ /* -a = -pdR (mapped in cp.c) */
+ /* -r = -dR (mapped in cp.c) */
+ /* -P = -d (mapped in cp.c) */
+ FILEUTILS_VERBOSE = (1 << 12) * ENABLE_FEATURE_VERBOSE, /* -v */
+ FILEUTILS_UPDATE = 1 << 13, /* -u */
#if ENABLE_SELINUX
- FILEUTILS_PRESERVE_SECURITY_CONTEXT = 1 << 9, /* -c */
- FILEUTILS_SET_SECURITY_CONTEXT = 1 << 10,
+ FILEUTILS_PRESERVE_SECURITY_CONTEXT = 1 << 14, /* -c */
#endif
+ FILEUTILS_RMDEST = 1 << (15 - !ENABLE_SELINUX), /* --remove-destination */
+ /*
+ * Hole. cp may have some bits set here,
+ * they should not affect remove_file()/copy_file()
+ */
+#if ENABLE_SELINUX
+ FILEUTILS_SET_SECURITY_CONTEXT = 1 << 30,
+#endif
+ FILEUTILS_IGNORE_CHMOD_ERR = 1 << 31,
};
-#define FILEUTILS_CP_OPTSTR "pdRfilsLH" IF_SELINUX("c")
+#define FILEUTILS_CP_OPTSTR "pdRfilsLHarPvu" IF_SELINUX("c")
extern int remove_file(const char *path, int flags) FAST_FUNC;
/* NB: without FILEUTILS_RECUR in flags, it will basically "cat"
* the source, not copy (unless "source" is a directory).
@@ -386,9 +431,12 @@ char *bb_get_last_path_component_nostrip(const char *path) FAST_FUNC;
const char *bb_basename(const char *name) FAST_FUNC;
/* NB: can violate const-ness (similarly to strchr) */
char *last_char_is(const char *s, int c) FAST_FUNC;
+const char* endofname(const char *name) FAST_FUNC;
+char *is_prefixed_with(const char *string, const char *key) FAST_FUNC;
+char *is_suffixed_with(const char *string, const char *key) FAST_FUNC;
-void ndelay_on(int fd) FAST_FUNC;
-void ndelay_off(int fd) FAST_FUNC;
+int ndelay_on(int fd) FAST_FUNC;
+int ndelay_off(int fd) FAST_FUNC;
void close_on_exec_on(int fd) FAST_FUNC;
void xdup2(int, int) FAST_FUNC;
void xmove_fd(int, int) FAST_FUNC;
@@ -460,7 +508,10 @@ void record_signo(int signo); /* not FAST_FUNC! */
void xsetgid(gid_t gid) FAST_FUNC;
void xsetuid(uid_t uid) FAST_FUNC;
+void xsetegid(gid_t egid) FAST_FUNC;
+void xseteuid(uid_t euid) FAST_FUNC;
void xchdir(const char *path) FAST_FUNC;
+void xfchdir(int fd) FAST_FUNC;
void xchroot(const char *path) FAST_FUNC;
void xsetenv(const char *key, const char *value) FAST_FUNC;
void bb_unsetenv(const char *key) FAST_FUNC;
@@ -468,11 +519,12 @@ void bb_unsetenv_and_free(char *key) FAST_FUNC;
void xunlink(const char *pathname) FAST_FUNC;
void xstat(const char *pathname, struct stat *buf) FAST_FUNC;
void xfstat(int fd, struct stat *buf, const char *errmsg) FAST_FUNC;
+int open3_or_warn(const char *pathname, int flags, int mode) FAST_FUNC;
+int open_or_warn(const char *pathname, int flags) FAST_FUNC;
+int xopen3(const char *pathname, int flags, int mode) FAST_FUNC;
int xopen(const char *pathname, int flags) FAST_FUNC;
int xopen_nonblocking(const char *pathname) FAST_FUNC;
-int xopen3(const char *pathname, int flags, int mode) FAST_FUNC;
-int open_or_warn(const char *pathname, int flags) FAST_FUNC;
-int open3_or_warn(const char *pathname, int flags, int mode) FAST_FUNC;
+int xopen_as_uid_gid(const char *pathname, int flags, uid_t u, gid_t g) FAST_FUNC;
int open_or_warn_stdin(const char *pathname) FAST_FUNC;
int xopen_stdin(const char *pathname) FAST_FUNC;
void xrename(const char *oldpath, const char *newpath) FAST_FUNC;
@@ -482,9 +534,9 @@ int xmkstemp(char *template) FAST_FUNC;
off_t fdlength(int fd) FAST_FUNC;
uoff_t FAST_FUNC get_volume_size_in_bytes(int fd,
- const char *override,
- unsigned override_units,
- int extend);
+ const char *override,
+ unsigned override_units,
+ int extend);
void xpipe(int filedes[2]) FAST_FUNC;
/* In this form code with pipes is much more readable */
@@ -522,7 +574,8 @@ struct BUG_too_small {
void parse_datestr(const char *date_str, struct tm *ptm) FAST_FUNC;
time_t validate_tm_time(const char *date_str, struct tm *ptm) FAST_FUNC;
-
+char *strftime_HHMMSS(char *buf, unsigned len, time_t *tp) FAST_FUNC;
+char *strftime_YYYYMMDDHHMMSS(char *buf, unsigned len, time_t *tp) FAST_FUNC;
int xsocket(int domain, int type, int protocol) FAST_FUNC;
void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen) FAST_FUNC;
@@ -530,6 +583,11 @@ void xlisten(int s, int backlog) FAST_FUNC;
void xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen) FAST_FUNC;
ssize_t xsendto(int s, const void *buf, size_t len, const struct sockaddr *to,
socklen_t tolen) FAST_FUNC;
+
+int setsockopt_int(int fd, int level, int optname, int optval) FAST_FUNC;
+int setsockopt_1(int fd, int level, int optname) FAST_FUNC;
+int setsockopt_SOL_SOCKET_int(int fd, int optname, int optval) FAST_FUNC;
+int setsockopt_SOL_SOCKET_1(int fd, int optname) FAST_FUNC;
/* SO_REUSEADDR allows a server to rebind to an address that is already
* "in use" by old connections to e.g. previous server instance which is
* killed or crashed. Without it bind will fail until all such connections
@@ -537,6 +595,7 @@ ssize_t xsendto(int s, const void *buf, size_t len, const struct sockaddr *to,
* regardless of SO_REUSEADDR (unlike some other flavors of Unix).
* Turn it on before you call bind(). */
void setsockopt_reuseaddr(int fd) FAST_FUNC; /* On Linux this never fails. */
+int setsockopt_keepalive(int fd) FAST_FUNC;
int setsockopt_broadcast(int fd) FAST_FUNC;
int setsockopt_bindtodevice(int fd, const char *iface) FAST_FUNC;
/* NB: returns port in host byte order */
@@ -642,15 +701,19 @@ uint16_t inet_cksum(uint16_t *addr, int len) FAST_FUNC;
char *xstrdup(const char *s) FAST_FUNC RETURNS_MALLOC;
char *xstrndup(const char *s, int n) FAST_FUNC RETURNS_MALLOC;
+void *xmemdup(const void *s, int n) FAST_FUNC RETURNS_MALLOC;
void overlapping_strcpy(char *dst, const char *src) FAST_FUNC;
char *safe_strncpy(char *dst, const char *src, size_t size) FAST_FUNC;
char *strncpy_IFNAMSIZ(char *dst, const char *src) FAST_FUNC;
+unsigned count_strstr(const char *str, const char *sub) FAST_FUNC;
+char *xmalloc_substitute_string(const char *src, int count, const char *sub, const char *repl) FAST_FUNC;
/* Guaranteed to NOT be a macro (smallest code). Saves nearly 2k on uclibc.
* But potentially slow, don't use in one-billion-times loops */
int bb_putchar(int ch) FAST_FUNC;
/* Note: does not use stdio, writes to fd 2 directly */
int bb_putchar_stderr(char ch) FAST_FUNC;
char *xasprintf(const char *format, ...) __attribute__ ((format(printf, 1, 2))) FAST_FUNC RETURNS_MALLOC;
+char *auto_string(char *str) FAST_FUNC;
// gcc-4.1.1 still isn't good enough at optimizing it
// (+200 bytes compared to macro)
//static ALWAYS_INLINE
@@ -676,6 +739,13 @@ const char* FAST_FUNC printable_string(uni_stat_t *stats, const char *str);
* else it is printed as-is (except for ch = 0x9b) */
enum { PRINTABLE_META = 0x100 };
void fputc_printable(int ch, FILE *file) FAST_FUNC;
+/* Return a string that is the printable representation of character ch.
+ * Buffer must hold at least four characters. */
+enum {
+ VISIBLE_ENDLINE = 1 << 0,
+ VISIBLE_SHOW_TABS = 1 << 1,
+};
+void visible(unsigned ch, char *buf, int flags) FAST_FUNC;
/* dmalloc will redefine these to it's own implementation. It is safe
* to have the prototypes here unconditionally. */
@@ -696,7 +766,7 @@ void* xrealloc_vector_helper(void *vector, unsigned sizeof_and_shift, int idx) F
extern ssize_t safe_read(int fd, void *buf, size_t count) FAST_FUNC;
-extern ssize_t nonblock_immune_read(int fd, void *buf, size_t count, int loop_on_EINTR) FAST_FUNC;
+extern ssize_t nonblock_immune_read(int fd, void *buf, size_t count) FAST_FUNC;
// NB: will return short read on error, not -1,
// if some data was read before error occurred
extern ssize_t full_read(int fd, void *buf, size_t count) FAST_FUNC;
@@ -715,6 +785,18 @@ extern void *xmalloc_open_read_close(const char *filename, size_t *maxsz_p) FAST
/* Never returns NULL */
extern void *xmalloc_xopen_read_close(const char *filename, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC;
+#if defined(ARG_MAX) && (ARG_MAX >= 60*1024 || !defined(_SC_ARG_MAX))
+/* Use _constant_ maximum if: defined && (big enough || no variable one exists) */
+# define bb_arg_max() ((unsigned)ARG_MAX)
+#elif defined(_SC_ARG_MAX)
+/* Else use variable one (a bit more expensive) */
+unsigned bb_arg_max(void) FAST_FUNC;
+#else
+/* If all else fails */
+# define bb_arg_max() ((unsigned)(32 * 1024))
+#endif
+unsigned bb_clk_tck(void) FAST_FUNC;
+
#define SEAMLESS_COMPRESSION (0 \
|| ENABLE_FEATURE_SEAMLESS_XZ \
|| ENABLE_FEATURE_SEAMLESS_LZMA \
@@ -724,14 +806,15 @@ extern void *xmalloc_xopen_read_close(const char *filename, size_t *maxsz_p) FAS
#if SEAMLESS_COMPRESSION
/* Autodetects gzip/bzip2 formats. fd may be in the middle of the file! */
-extern int setup_unzip_on_fd(int fd, int fail_if_not_detected) FAST_FUNC;
+extern int setup_unzip_on_fd(int fd, int fail_if_not_compressed) FAST_FUNC;
/* Autodetects .gz etc */
-extern int open_zipped(const char *fname) FAST_FUNC;
+extern int open_zipped(const char *fname, int fail_if_not_compressed) FAST_FUNC;
+extern void *xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC;
#else
# define setup_unzip_on_fd(...) (0)
-# define open_zipped(fname) open((fname), O_RDONLY);
+# define open_zipped(fname, fail_if_not_compressed) open((fname), O_RDONLY);
+# define xmalloc_open_zipped_read_close(fname, maxsz_p) xmalloc_open_read_close((fname), (maxsz_p))
#endif
-extern void *xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC;
extern ssize_t safe_write(int fd, const void *buf, size_t count) FAST_FUNC;
// NB: will return short write on error, not -1,
@@ -806,8 +889,8 @@ char *itoa(int n) FAST_FUNC;
char *utoa_to_buf(unsigned n, char *buf, unsigned buflen) FAST_FUNC;
char *itoa_to_buf(int n, char *buf, unsigned buflen) FAST_FUNC;
/* Intelligent formatters of bignums */
-void smart_ulltoa4(unsigned long long ul, char buf[4], const char *scale) FAST_FUNC;
-void smart_ulltoa5(unsigned long long ul, char buf[5], const char *scale) FAST_FUNC;
+char *smart_ulltoa4(unsigned long long ul, char buf[4], const char *scale) FAST_FUNC;
+char *smart_ulltoa5(unsigned long long ul, char buf[5], const char *scale) FAST_FUNC;
/* If block_size == 0, display size without fractional part,
* else display (size * block_size) with one decimal digit.
* If display_unit == 0, show value no bigger than 1024 with suffix (K,M,G...),
@@ -824,16 +907,17 @@ char* hex2bin(char *dst, const char *src, int count) FAST_FUNC;
/* Generate a UUID */
void generate_uuid(uint8_t *buf) FAST_FUNC;
-/* expand UUID to human readable format */
-char *unparse_uuid(const uint8_t *uu, char *out) FAST_FUNC;
-/* parse UUID */
-int parse_uuid(const char *in, uint8_t *uuid) FAST_FUNC;
/* Last element is marked by mult == 0 */
struct suffix_mult {
char suffix[4];
unsigned mult;
};
+extern const struct suffix_mult bkm_suffixes[];
+#define km_suffixes (bkm_suffixes + 1)
+extern const struct suffix_mult cwbkMG_suffixes[];
+#define kMG_suffixes (cwbkMG_suffixes + 3)
+
#include "xatonum.h"
/* Specialized: */
@@ -857,14 +941,13 @@ long xuname2uid(const char *name) FAST_FUNC;
long xgroup2gid(const char *name) FAST_FUNC;
/* wrapper: allows string to contain numeric uid or gid */
unsigned long get_ug_id(const char *s, long FAST_FUNC (*xname2id)(const char *)) FAST_FUNC;
-/* from chpst. Does not die, returns 0 on failure */
struct bb_uidgid_t {
uid_t uid;
gid_t gid;
};
-/* always sets uid and gid */
-int get_uidgid(struct bb_uidgid_t*, const char*, int numeric_ok) FAST_FUNC;
-/* always sets uid and gid, allows numeric; exits on failure */
+/* always sets uid and gid; returns 0 on failure */
+int get_uidgid(struct bb_uidgid_t*, const char*) FAST_FUNC;
+/* always sets uid and gid; exits on failure */
void xget_uidgid(struct bb_uidgid_t*, const char*) FAST_FUNC;
/* chown-like handling of "user[:[group]" */
void parse_chown_usergroup_or_die(struct bb_uidgid_t *u, char *user_group) FAST_FUNC;
@@ -893,15 +976,17 @@ void die_if_bad_username(const char* name) FAST_FUNC;
#if ENABLE_FEATURE_UTMP
void FAST_FUNC write_new_utmp(pid_t pid, int new_type, const char *tty_name, const char *username, const char *hostname);
void FAST_FUNC update_utmp(pid_t pid, int new_type, const char *tty_name, const char *username, const char *hostname);
+void FAST_FUNC update_utmp_DEAD_PROCESS(pid_t pid);
#else
# define write_new_utmp(pid, new_type, tty_name, username, hostname) ((void)0)
# define update_utmp(pid, new_type, tty_name, username, hostname) ((void)0)
+# define update_utmp_DEAD_PROCESS(pid) ((void)0)
#endif
-int execable_file(const char *name) FAST_FUNC;
-char *find_execable(const char *filename, char **PATHp) FAST_FUNC;
-int exists_execable(const char *filename) FAST_FUNC;
+int file_is_executable(const char *name) FAST_FUNC;
+char *find_executable(const char *filename, char **PATHp) FAST_FUNC;
+int executable_exists(const char *filename) FAST_FUNC;
/* BB_EXECxx always execs (it's not doing NOFORK/NOEXEC stuff),
* but it may exec busybox and call applet instead of searching PATH.
@@ -918,9 +1003,10 @@ int BB_EXECVP(const char *file, char *const argv[]) FAST_FUNC;
#define BB_EXECVP(prog,cmd) execvp(prog,cmd)
#define BB_EXECLP(prog,cmd,...) execlp(prog,cmd,__VA_ARGS__)
#endif
-int BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC;
+void BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC;
+void exec_prog_or_SHELL(char **argv) NORETURN FAST_FUNC;
-/* xvfork() can't be a _function_, return after vfork mangles stack
+/* xvfork() can't be a _function_, return after vfork in child mangles stack
* in the parent. It must be a macro. */
#define xvfork() \
({ \
@@ -932,6 +1018,7 @@ int BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC;
#if BB_MMU
pid_t xfork(void) FAST_FUNC;
#endif
+void xvfork_parent_waits_and_exits(void) FAST_FUNC;
/* NOMMU friendy fork+exec: */
pid_t spawn(char **argv) FAST_FUNC;
@@ -948,6 +1035,7 @@ pid_t wait_any_nohang(int *wstat) FAST_FUNC;
* if (rc > 0) bb_error_msg("exit code: %d", rc & 0xff);
*/
int wait4pid(pid_t pid) FAST_FUNC;
+int wait_for_exitstatus(pid_t pid) FAST_FUNC;
/* Same as wait4pid(spawn(argv)), but with NOFORK/NOEXEC if configured: */
int spawn_and_wait(char **argv) FAST_FUNC;
/* Does NOT check that applet is NOFORK, just blindly runs it */
@@ -1061,10 +1149,10 @@ enum {
LOGMODE_BOTH = LOGMODE_SYSLOG + LOGMODE_STDIO,
};
extern const char *msg_eol;
+extern smallint syslog_level;
extern smallint logmode;
-extern int die_sleep;
extern uint8_t xfunc_error_retval;
-extern jmp_buf die_jmp;
+extern void (*die_func)(void);
extern void xfunc_die(void) NORETURN FAST_FUNC;
extern void bb_show_usage(void) NORETURN FAST_FUNC;
extern void bb_error_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC;
@@ -1077,8 +1165,8 @@ extern void bb_herror_msg(const char *s, ...) __attribute__ ((format (printf, 1,
extern void bb_herror_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))) FAST_FUNC;
extern void bb_perror_nomsg_and_die(void) NORETURN FAST_FUNC;
extern void bb_perror_nomsg(void) FAST_FUNC;
-extern void bb_info_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC;
extern void bb_verror_msg(const char *s, va_list p, const char *strerr) FAST_FUNC;
+extern void bb_logenv_override(void) FAST_FUNC;
/* We need to export XXX_main from libbusybox
* only if we build "individual" binaries
@@ -1111,9 +1199,6 @@ void bb_displayroutes(int noresolve, int netstatfmt) FAST_FUNC;
/* Networking */
-int create_icmp_socket(void) FAST_FUNC;
-int create_icmp6_socket(void) FAST_FUNC;
-/* interface.c */
/* This structure defines protocol families and their handlers. */
struct aftype {
const char *name;
@@ -1142,6 +1227,7 @@ struct hwtype {
};
extern smallint interface_opt_a;
int display_interfaces(char *ifname) FAST_FUNC;
+int in_ether(const char *bufp, struct sockaddr *sap) FAST_FUNC;
#if ENABLE_FEATURE_HWIB
int in_ib(const char *bufp, struct sockaddr *sap) FAST_FUNC;
#else
@@ -1154,8 +1240,6 @@ const struct hwtype *get_hwntype(int type) FAST_FUNC;
#ifndef BUILD_INDIVIDUAL
extern int find_applet_by_name(const char *name) FAST_FUNC;
-/* Returns only if applet is not found. */
-extern void run_applet_and_exit(const char *name, char **argv) FAST_FUNC;
extern void run_applet_no_and_exit(int a, char **argv) NORETURN FAST_FUNC;
#endif
@@ -1187,7 +1271,8 @@ char *bb_ask_stdin(const char * prompt) FAST_FUNC;
char *bb_ask(const int fd, int timeout, const char * prompt) FAST_FUNC;
int bb_ask_confirmation(void) FAST_FUNC;
-int bb_parse_mode(const char* s, mode_t* theMode) FAST_FUNC;
+/* Returns -1 if input is invalid. current_mode is a base for e.g. "u+rw" */
+int bb_parse_mode(const char* s, unsigned cur_mode) FAST_FUNC;
/*
* Config file parser
@@ -1243,7 +1328,9 @@ char *bb_simplify_path(const char *path) FAST_FUNC;
/* Returns ptr to NUL */
char *bb_simplify_abs_path_inplace(char *path) FAST_FUNC;
+#ifndef LOGIN_FAIL_DELAY
#define LOGIN_FAIL_DELAY 3
+#endif
extern void bb_do_delay(int seconds) FAST_FUNC;
extern void change_identity(const struct passwd *pw) FAST_FUNC;
extern void run_shell(const char *shell, int loginshell, const char *command, const char **additional_args) NORETURN FAST_FUNC;
@@ -1252,7 +1339,7 @@ extern void run_shell(const char *shell, int loginshell, const char *command, co
* Note that getpwuid result might need xstrdup'ing
* if there is a possibility of intervening getpwxxx() calls.
*/
-const char *get_shell_name(void);
+const char *get_shell_name(void) FAST_FUNC;
#if ENABLE_SELINUX
extern void renew_current_security_context(void) FAST_FUNC;
@@ -1267,11 +1354,6 @@ extern void selinux_preserve_fcontext(int fdesc) FAST_FUNC;
extern void selinux_or_die(void) FAST_FUNC;
-/* systemd support */
-#define SD_LISTEN_FDS_START 3
-int sd_listen_fds(void);
-
-
/* setup_environment:
* if chdir pw->pw_dir: ok: else if to_tmp == 1: goto /tmp else: goto / or die
* if clear_env = 1: cd(pw->pw_dir), clear environment, then set
@@ -1290,8 +1372,12 @@ int sd_listen_fds(void);
#define SETUP_ENV_CHANGEENV (1 << 0)
#define SETUP_ENV_CLEARENV (1 << 1)
#define SETUP_ENV_TO_TMP (1 << 2)
-extern void setup_environment(const char *shell, int flags, const struct passwd *pw) FAST_FUNC;
-extern int correct_password(const struct passwd *pw) FAST_FUNC;
+#define SETUP_ENV_NO_CHDIR (1 << 4)
+void setup_environment(const char *shell, int flags, const struct passwd *pw) FAST_FUNC;
+void nuke_str(char *str) FAST_FUNC;
+int check_password(const struct passwd *pw, const char *plaintext) FAST_FUNC;
+int ask_and_check_password_extended(const struct passwd *pw, int timeout, const char *prompt) FAST_FUNC;
+int ask_and_check_password(const struct passwd *pw) FAST_FUNC;
/* Returns a malloced string */
#if !ENABLE_USE_BB_CRYPT
#define pw_encrypt(clear, salt, cleanup) pw_encrypt(clear, salt)
@@ -1334,6 +1420,7 @@ extern void print_login_prompt(void) FAST_FUNC;
char *xmalloc_ttyname(int fd) FAST_FUNC RETURNS_MALLOC;
/* NB: typically you want to pass fd 0, not 1. Think 'applet | grep something' */
int get_terminal_width_height(int fd, unsigned *width, unsigned *height) FAST_FUNC;
+int get_terminal_width(int fd) FAST_FUNC;
int tcsetattr_stdin_TCSANOW(const struct termios *tp) FAST_FUNC;
@@ -1437,7 +1524,7 @@ void read_key_ungets(char *buffer, const char *str, unsigned len) FAST_FUNC;
/* It's NOT just ENABLEd or disabled. It's a number: */
# if defined CONFIG_FEATURE_EDITING_HISTORY && CONFIG_FEATURE_EDITING_HISTORY > 0
# define MAX_HISTORY (CONFIG_FEATURE_EDITING_HISTORY + 0)
-unsigned size_from_HISTFILESIZE(const char *hp);
+unsigned size_from_HISTFILESIZE(const char *hp) FAST_FUNC;
# else
# define MAX_HISTORY 0
# endif
@@ -1479,6 +1566,7 @@ line_input_t *new_line_input_t(int flags) FAST_FUNC;
* >0 length of input string, including terminating '\n'
*/
int read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout) FAST_FUNC;
+void show_history(const line_input_t *st) FAST_FUNC;
# if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
void save_history(line_input_t *st);
# endif
@@ -1519,7 +1607,7 @@ struct smaprec {
procps_read_smaps(pid, total)
#endif
int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total,
- void (*cb)(struct smaprec *, void *), void *data);
+ void (*cb)(struct smaprec *, void *), void *data);
typedef struct procps_status_t {
DIR *dir;
@@ -1615,8 +1703,8 @@ unsigned get_cpu_count(void) FAST_FUNC;
char *percent_decode_in_place(char *str, int strict) FAST_FUNC;
-extern const char bb_uuenc_tbl_base64[];
-extern const char bb_uuenc_tbl_std[];
+extern const char bb_uuenc_tbl_base64[] ALIGN1;
+extern const char bb_uuenc_tbl_std[] ALIGN1;
void bb_uuencode(char *store, const void *s, int length, const char *tbl) FAST_FUNC;
enum {
BASE64_FLAG_UU_STOP = 0x100,
@@ -1639,8 +1727,12 @@ typedef struct sha512_ctx_t {
uint64_t hash[8];
uint8_t wbuffer[128]; /* always correctly aligned for uint64_t */
} sha512_ctx_t;
+typedef struct sha3_ctx_t {
+ uint64_t state[25];
+ unsigned bytes_queued;
+} sha3_ctx_t;
void md5_begin(md5_ctx_t *ctx) FAST_FUNC;
-void md5_hash(md5_ctx_t *ctx, const void *data, size_t length) FAST_FUNC;
+void md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC;
void md5_end(md5_ctx_t *ctx, void *resbuf) FAST_FUNC;
void sha1_begin(sha1_ctx_t *ctx) FAST_FUNC;
#define sha1_hash md5_hash
@@ -1651,6 +1743,9 @@ void sha256_begin(sha256_ctx_t *ctx) FAST_FUNC;
void sha512_begin(sha512_ctx_t *ctx) FAST_FUNC;
void sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC;
void sha512_end(sha512_ctx_t *ctx, void *resbuf) FAST_FUNC;
+void sha3_begin(sha3_ctx_t *ctx) FAST_FUNC;
+void sha3_hash(sha3_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC;
+void sha3_end(sha3_ctx_t *ctx, void *resbuf) FAST_FUNC;
extern uint32_t *global_crc32_table;
uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC;
@@ -1684,6 +1779,9 @@ void bb_progress_update(bb_progress_t *p,
uoff_t transferred,
uoff_t totalsize) FAST_FUNC;
+unsigned ubi_devnum_from_devname(const char *str) FAST_FUNC;
+int ubi_get_volid_by_name(unsigned ubi_devnum, const char *vol_name) FAST_FUNC;
+
extern const char *applet_name;
@@ -1697,24 +1795,24 @@ extern const char *applet_name;
* Therefore now we use #defines.
*/
/* "BusyBox vN.N.N (timestamp or extra_version)" */
-extern const char bb_banner[];
-extern const char bb_msg_memory_exhausted[];
-extern const char bb_msg_invalid_date[];
+extern const char bb_banner[] ALIGN1;
+extern const char bb_msg_memory_exhausted[] ALIGN1;
+extern const char bb_msg_invalid_date[] ALIGN1;
#define bb_msg_read_error "read error"
#define bb_msg_write_error "write error"
-extern const char bb_msg_unknown[];
-extern const char bb_msg_can_not_create_raw_socket[];
-extern const char bb_msg_perm_denied_are_you_root[];
-extern const char bb_msg_you_must_be_root[];
-extern const char bb_msg_requires_arg[];
-extern const char bb_msg_invalid_arg[];
-extern const char bb_msg_standard_input[];
-extern const char bb_msg_standard_output[];
+extern const char bb_msg_unknown[] ALIGN1;
+extern const char bb_msg_can_not_create_raw_socket[] ALIGN1;
+extern const char bb_msg_perm_denied_are_you_root[] ALIGN1;
+extern const char bb_msg_you_must_be_root[] ALIGN1;
+extern const char bb_msg_requires_arg[] ALIGN1;
+extern const char bb_msg_invalid_arg_to[] ALIGN1;
+extern const char bb_msg_standard_input[] ALIGN1;
+extern const char bb_msg_standard_output[] ALIGN1;
/* NB: (bb_hexdigits_upcase[i] | 0x20) -> lowercase hex digit */
-extern const char bb_hexdigits_upcase[];
+extern const char bb_hexdigits_upcase[] ALIGN1;
-extern const char bb_path_wtmp_file[];
+extern const char bb_path_wtmp_file[] ALIGN1;
/* Busybox mount uses either /proc/mounts or /etc/mtab to
* get the list of currently mounted filesystems */
@@ -1728,20 +1826,16 @@ extern const char bb_path_wtmp_file[];
#define bb_path_motd_file "/etc/motd"
#define bb_dev_null "/dev/null"
-extern const char bb_busybox_exec_path[];
+extern const char bb_busybox_exec_path[] ALIGN1;
/* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin,
* but I want to save a few bytes here */
-extern const char bb_PATH_root_path[]; /* "PATH=/sbin:/usr/sbin:/bin:/usr/bin" */
+extern const char bb_PATH_root_path[] ALIGN1; /* "PATH=/sbin:/usr/sbin:/bin:/usr/bin" */
#define bb_default_root_path (bb_PATH_root_path + sizeof("PATH"))
#define bb_default_path (bb_PATH_root_path + sizeof("PATH=/sbin:/usr/sbin:/opt/sbin"))
extern const int const_int_0;
-extern const int const_int_1;
+//extern const int const_int_1;
-
-/* Providing hard guarantee on minimum size (think of BUFSIZ == 128) */
-enum { COMMON_BUFSIZE = (BUFSIZ >= 256*sizeof(void*) ? BUFSIZ+1 : 256*sizeof(void*)) };
-extern char bb_common_bufsiz1[COMMON_BUFSIZE];
/* This struct is deliberately not defined. */
/* See docs/keep_data_small.txt */
struct globals;
@@ -1755,13 +1849,18 @@ extern struct globals *const ptr_to_globals;
(*(struct globals**)&ptr_to_globals) = (void*)(x); \
barrier(); \
} while (0)
+#define FREE_PTR_TO_GLOBALS() do { \
+ if (ENABLE_FEATURE_CLEAN_UP) { \
+ free(ptr_to_globals); \
+ } \
+} while (0)
/* You can change LIBBB_DEFAULT_LOGIN_SHELL, but don't use it,
* use bb_default_login_shell and following defines.
* If you change LIBBB_DEFAULT_LOGIN_SHELL,
* don't forget to change increment constant. */
#define LIBBB_DEFAULT_LOGIN_SHELL "-/bin/sh"
-extern const char bb_default_login_shell[];
+extern const char bb_default_login_shell[] ALIGN1;
/* "/bin/sh" */
#define DEFAULT_SHELL (bb_default_login_shell+1)
/* "sh" */
@@ -1796,7 +1895,7 @@ extern const char bb_default_login_shell[];
# define VC_4 "/dev/vc/4"
# define VC_5 "/dev/vc/5"
# define VC_FORMAT "/dev/vc/%d"
-# define LOOP_FORMAT "/dev/loop/%d"
+# define LOOP_FORMAT "/dev/loop/%u"
# define LOOP_NAMESIZE (sizeof("/dev/loop/") + sizeof(int)*3 + 1)
# define LOOP_NAME "/dev/loop/"
# define FB_0 "/dev/fb/0"
@@ -1809,7 +1908,7 @@ extern const char bb_default_login_shell[];
# define VC_4 "/dev/tty4"
# define VC_5 "/dev/tty5"
# define VC_FORMAT "/dev/tty%d"
-# define LOOP_FORMAT "/dev/loop%d"
+# define LOOP_FORMAT "/dev/loop%u"
# define LOOP_NAMESIZE (sizeof("/dev/loop") + sizeof(int)*3 + 1)
# define LOOP_NAME "/dev/loop"
# define FB_0 "/dev/fb0"
@@ -1817,6 +1916,7 @@ extern const char bb_default_login_shell[];
#define ARRAY_SIZE(x) ((unsigned)(sizeof(x) / sizeof((x)[0])))
+#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
/* We redefine ctype macros. Unicode-correct handling of char types
@@ -1902,6 +2002,140 @@ static ALWAYS_INLINE unsigned char bb_ascii_tolower(unsigned char a)
#define isprint_asciionly(a) ((unsigned)((a) - 0x20) <= 0x7e - 0x20)
+/* Simple unit-testing framework */
+
+typedef void (*bbunit_testfunc)(void);
+
+struct bbunit_listelem {
+ const char* name;
+ bbunit_testfunc testfunc;
+};
+
+void bbunit_registertest(struct bbunit_listelem* test);
+void bbunit_settestfailed(void);
+
+#define BBUNIT_DEFINE_TEST(NAME) \
+ static void bbunit_##NAME##_test(void); \
+ static struct bbunit_listelem bbunit_##NAME##_elem = { \
+ .name = #NAME, \
+ .testfunc = bbunit_##NAME##_test, \
+ }; \
+ static void INIT_FUNC bbunit_##NAME##_register(void) \
+ { \
+ bbunit_registertest(&bbunit_##NAME##_elem); \
+ } \
+ static void bbunit_##NAME##_test(void)
+
+/*
+ * Both 'goto bbunit_end' and 'break' are here only to get rid
+ * of compiler warnings.
+ */
+#define BBUNIT_ENDTEST \
+ do { \
+ goto bbunit_end; \
+ bbunit_end: \
+ break; \
+ } while (0)
+
+#define BBUNIT_PRINTASSERTFAIL \
+ do { \
+ bb_error_msg( \
+ "[ERROR] Assertion failed in file %s, line %d", \
+ __FILE__, __LINE__); \
+ } while (0)
+
+#define BBUNIT_ASSERTION_FAILED \
+ do { \
+ bbunit_settestfailed(); \
+ goto bbunit_end; \
+ } while (0)
+
+/*
+ * Assertions.
+ * For now we only offer assertions which cause tests to fail
+ * immediately. In the future 'expects' might be added too -
+ * similar to those offered by the gtest framework.
+ */
+#define BBUNIT_ASSERT_EQ(EXPECTED, ACTUAL) \
+ do { \
+ if ((EXPECTED) != (ACTUAL)) { \
+ BBUNIT_PRINTASSERTFAIL; \
+ bb_error_msg("[ERROR] '%s' isn't equal to '%s'", \
+ #EXPECTED, #ACTUAL); \
+ BBUNIT_ASSERTION_FAILED; \
+ } \
+ } while (0)
+
+#define BBUNIT_ASSERT_NOTEQ(EXPECTED, ACTUAL) \
+ do { \
+ if ((EXPECTED) == (ACTUAL)) { \
+ BBUNIT_PRINTASSERTFAIL; \
+ bb_error_msg("[ERROR] '%s' is equal to '%s'", \
+ #EXPECTED, #ACTUAL); \
+ BBUNIT_ASSERTION_FAILED; \
+ } \
+ } while (0)
+
+#define BBUNIT_ASSERT_NOTNULL(PTR) \
+ do { \
+ if ((PTR) == NULL) { \
+ BBUNIT_PRINTASSERTFAIL; \
+ bb_error_msg("[ERROR] '%s' is NULL!", #PTR); \
+ BBUNIT_ASSERTION_FAILED; \
+ } \
+ } while (0)
+
+#define BBUNIT_ASSERT_NULL(PTR) \
+ do { \
+ if ((PTR) != NULL) { \
+ BBUNIT_PRINTASSERTFAIL; \
+ bb_error_msg("[ERROR] '%s' is not NULL!", #PTR); \
+ BBUNIT_ASSERTION_FAILED; \
+ } \
+ } while (0)
+
+#define BBUNIT_ASSERT_FALSE(STATEMENT) \
+ do { \
+ if ((STATEMENT)) { \
+ BBUNIT_PRINTASSERTFAIL; \
+ bb_error_msg("[ERROR] Statement '%s' evaluated to true!", \
+ #STATEMENT); \
+ BBUNIT_ASSERTION_FAILED; \
+ } \
+ } while (0)
+
+#define BBUNIT_ASSERT_TRUE(STATEMENT) \
+ do { \
+ if (!(STATEMENT)) { \
+ BBUNIT_PRINTASSERTFAIL; \
+ bb_error_msg("[ERROR] Statement '%s' evaluated to false!", \
+ #STATEMENT); \
+ BBUNIT_ASSERTION_FAILED; \
+ } \
+ } while (0)
+
+#define BBUNIT_ASSERT_STREQ(STR1, STR2) \
+ do { \
+ if (strcmp(STR1, STR2) != 0) { \
+ BBUNIT_PRINTASSERTFAIL; \
+ bb_error_msg("[ERROR] Strings '%s' and '%s' " \
+ "are not the same", STR1, STR2); \
+ BBUNIT_ASSERTION_FAILED; \
+ } \
+ } while (0)
+
+#define BBUNIT_ASSERT_STRNOTEQ(STR1, STR2) \
+ do { \
+ if (strcmp(STR1, STR2) == 0) { \
+ BBUNIT_PRINTASSERTFAIL; \
+ bb_error_msg("[ERROR] Strings '%s' and '%s' " \
+ "are the same, but were " \
+ "expected to differ", STR1, STR2); \
+ BBUNIT_ASSERTION_FAILED; \
+ } \
+ } while (0)
+
+
POP_SAVED_FUNCTION_VISIBILITY
#endif
diff --git a/release/src/router/busybox/include/liblzo_interface.h b/release/src/router/busybox/include/liblzo_interface.h
index 9a84c0b6b2..b7f1b639ba 100644
--- a/release/src/router/busybox/include/liblzo_interface.h
+++ b/release/src/router/busybox/include/liblzo_interface.h
@@ -30,7 +30,7 @@
/*
static void die_at(int line)
{
- bb_error_msg_and_die("internal error at %d", line);
+ bb_error_msg_and_die("internal error at %d", line);
}
#define assert(v) if (!(v)) die_at(__LINE__)
*/
diff --git a/release/src/router/busybox/include/platform.h b/release/src/router/busybox/include/platform.h
index 2cf431c806..c987d418cf 100644
--- a/release/src/router/busybox/include/platform.h
+++ b/release/src/router/busybox/include/platform.h
@@ -76,6 +76,9 @@
# define UNUSED_PARAM_RESULT
#endif
+/* used by unit test machinery to run registration functions before calling main() */
+#define INIT_FUNC __attribute__ ((constructor))
+
/* -fwhole-program makes all symbols local. The attribute externally_visible
* forces a symbol global. */
#if __GNUC_PREREQ(4,1)
@@ -205,27 +208,33 @@
#include <stdint.h>
typedef int bb__aliased_int FIX_ALIASING;
+typedef long bb__aliased_long FIX_ALIASING;
typedef uint16_t bb__aliased_uint16_t FIX_ALIASING;
typedef uint32_t bb__aliased_uint32_t FIX_ALIASING;
+typedef uint64_t bb__aliased_uint64_t FIX_ALIASING;
/* NB: unaligned parameter should be a pointer, aligned one -
* a lvalue. This makes it more likely to not swap them by mistake
*/
#if defined(i386) || defined(__x86_64__) || defined(__powerpc__)
-# define move_from_unaligned_int(v, intp) ((v) = *(bb__aliased_int*)(intp))
+# define BB_UNALIGNED_MEMACCESS_OK 1
+# define move_from_unaligned_int(v, intp) ((v) = *(bb__aliased_int*)(intp))
+# define move_from_unaligned_long(v, longp) ((v) = *(bb__aliased_long*)(longp))
# define move_from_unaligned16(v, u16p) ((v) = *(bb__aliased_uint16_t*)(u16p))
# define move_from_unaligned32(v, u32p) ((v) = *(bb__aliased_uint32_t*)(u32p))
# define move_to_unaligned16(u16p, v) (*(bb__aliased_uint16_t*)(u16p) = (v))
# define move_to_unaligned32(u32p, v) (*(bb__aliased_uint32_t*)(u32p) = (v))
/* #elif ... - add your favorite arch today! */
#else
+# define BB_UNALIGNED_MEMACCESS_OK 0
/* performs reasonably well (gcc usually inlines memcpy here) */
# define move_from_unaligned_int(v, intp) (memcpy(&(v), (intp), sizeof(int)))
+# define move_from_unaligned_long(v, longp) (memcpy(&(v), (longp), sizeof(long)))
# define move_from_unaligned16(v, u16p) (memcpy(&(v), (u16p), 2))
# define move_from_unaligned32(v, u32p) (memcpy(&(v), (u32p), 4))
# define move_to_unaligned16(u16p, v) do { \
uint16_t __t = (v); \
- memcpy((u16p), &__t, 4); \
+ memcpy((u16p), &__t, 2); \
} while (0)
# define move_to_unaligned32(u32p, v) do { \
uint32_t __t = (v); \
@@ -260,6 +269,12 @@ typedef unsigned smalluint;
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+#ifdef __UCLIBC__
+# define UCLIBC_VERSION KERNEL_VERSION(__UCLIBC_MAJOR__, __UCLIBC_MINOR__, __UCLIBC_SUBLEVEL__)
+#else
+# define UCLIBC_VERSION 0
+#endif
+
/* ---- Miscellaneous --------------------------------------- */
@@ -284,7 +299,8 @@ typedef unsigned smalluint;
#define fdprintf dprintf
/* Useful for defeating gcc's alignment of "char message[]"-like data */
-#if 1 /* if needed: !defined(arch1) && !defined(arch2) */
+#if !defined(__s390__)
+ /* on s390[x], non-word-aligned data accesses require larger code */
# define ALIGN1 __attribute__((aligned(1)))
# define ALIGN2 __attribute__((aligned(2)))
# define ALIGN4 __attribute__((aligned(4)))
@@ -301,8 +317,9 @@ typedef unsigned smalluint;
* for a mmu-less system.
*/
#if ENABLE_NOMMU || \
- (defined __UCLIBC__ && __UCLIBC_MAJOR__ >= 0 && __UCLIBC_MINOR__ >= 9 && \
- __UCLIBC_SUBLEVEL__ > 28 && !defined __ARCH_USE_MMU__)
+ (defined __UCLIBC__ && \
+ UCLIBC_VERSION > KERNEL_VERSION(0, 9, 28) && \
+ !defined __ARCH_USE_MMU__)
# define BB_MMU 0
# define USE_FOR_NOMMU(...) __VA_ARGS__
# define USE_FOR_MMU(...)
@@ -334,6 +351,12 @@ typedef unsigned smalluint;
# define MAXSYMLINKS SYMLOOP_MAX
#endif
+#if defined(ANDROID) || defined(__ANDROID__)
+# define BB_ADDITIONAL_PATH ":/system/sbin:/system/bin:/system/xbin"
+# define SYS_ioprio_set __NR_ioprio_set
+# define SYS_ioprio_get __NR_ioprio_get
+#endif
+
/* ---- Who misses what? ------------------------------------ */
@@ -345,16 +368,19 @@ typedef unsigned smalluint;
#define HAVE_DPRINTF 1
#define HAVE_MEMRCHR 1
#define HAVE_MKDTEMP 1
+#define HAVE_TTYNAME_R 1
#define HAVE_PTSNAME_R 1
#define HAVE_SETBIT 1
#define HAVE_SIGHANDLER_T 1
#define HAVE_STPCPY 1
+#define HAVE_MEMPCPY 1
#define HAVE_STRCASESTR 1
#define HAVE_STRCHRNUL 1
#define HAVE_STRSEP 1
#define HAVE_STRSIGNAL 1
#define HAVE_STRVERSCMP 1
#define HAVE_VASPRINTF 1
+#define HAVE_USLEEP 1
#define HAVE_UNLOCKED_STDIO 1
#define HAVE_UNLOCKED_LINE_OPS 1
#define HAVE_GETLINE 1
@@ -363,17 +389,15 @@ typedef unsigned smalluint;
#define HAVE_NET_ETHERNET_H 1
#define HAVE_SYS_STATFS_H 1
-#if defined(__UCLIBC_MAJOR__)
-# if __UCLIBC_MAJOR__ == 0 \
- && ( __UCLIBC_MINOR__ < 9 \
- || (__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ < 30) \
- )
+#if defined(__UCLIBC__)
+# if UCLIBC_VERSION < KERNEL_VERSION(0, 9, 32)
# undef HAVE_STRVERSCMP
# endif
-#endif
-
-#if defined(__dietlibc__)
-# undef HAVE_STRCHRNUL
+# if UCLIBC_VERSION >= KERNEL_VERSION(0, 9, 30)
+# ifndef __UCLIBC_SUSV3_LEGACY__
+# undef HAVE_USLEEP
+# endif
+# endif
#endif
#if defined(__WATCOMC__)
@@ -406,7 +430,7 @@ typedef unsigned smalluint;
/* These BSD-derived OSes share many similarities */
#if (defined __digital__ && defined __unix__) \
|| defined __APPLE__ \
- || defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__
+ || defined __OpenBSD__ || defined __NetBSD__
# undef HAVE_CLEARENV
# undef HAVE_FDATASYNC
# undef HAVE_GETLINE
@@ -421,10 +445,32 @@ typedef unsigned smalluint;
# undef HAVE_UNLOCKED_LINE_OPS
#endif
-#if defined(__FreeBSD__)
+#if defined(__dietlibc__)
+# undef HAVE_STRCHRNUL
+#endif
+
+#if defined(__APPLE__)
# undef HAVE_STRCHRNUL
#endif
+#if defined(__FreeBSD__)
+/* users say mempcpy is not present in FreeBSD 9.x */
+# undef HAVE_MEMPCPY
+# undef HAVE_CLEARENV
+# undef HAVE_FDATASYNC
+# undef HAVE_MNTENT_H
+# undef HAVE_PTSNAME_R
+# undef HAVE_SYS_STATFS_H
+# undef HAVE_SIGHANDLER_T
+# undef HAVE_STRVERSCMP
+# undef HAVE_XTABS
+# undef HAVE_UNLOCKED_LINE_OPS
+# include <osreldate.h>
+# if __FreeBSD_version < 1000029
+# undef HAVE_STRCHRNUL /* FreeBSD added strchrnul() between 1000028 and 1000029 */
+# endif
+#endif
+
#if defined(__NetBSD__)
# define HAVE_GETLINE 1 /* Recent NetBSD versions have getline() */
#endif
@@ -434,9 +480,21 @@ typedef unsigned smalluint;
#endif
#if defined(ANDROID) || defined(__ANDROID__)
-# undef HAVE_DPRINTF
-# undef HAVE_GETLINE
-# undef HAVE_STPCPY
+# if __ANDROID_API__ < 8
+ /* ANDROID < 8 has no [f]dprintf at all */
+# undef HAVE_DPRINTF
+# elif __ANDROID_API__ < 21
+ /* ANDROID < 21 has fdprintf */
+# define dprintf fdprintf
+# else
+ /* ANDROID >= 21 has standard dprintf */
+# endif
+# if __ANDROID_API__ < 21
+# undef HAVE_TTYNAME_R
+# undef HAVE_GETLINE
+# undef HAVE_STPCPY
+# endif
+# undef HAVE_MEMPCPY
# undef HAVE_STRCHRNUL
# undef HAVE_STRVERSCMP
# undef HAVE_UNLOCKED_LINE_OPS
@@ -460,6 +518,11 @@ extern void *memrchr(const void *s, int c, size_t n) FAST_FUNC;
extern char *mkdtemp(char *template) FAST_FUNC;
#endif
+#ifndef HAVE_TTYNAME_R
+#define ttyname_r bb_ttyname_r
+extern int ttyname_r(int fd, char *buf, size_t buflen);
+#endif
+
#ifndef HAVE_SETBIT
# define setbit(a, b) ((a)[(b) >> 3] |= 1 << ((b) & 7))
# define clrbit(a, b) ((a)[(b) >> 3] &= ~(1 << ((b) & 7)))
@@ -473,6 +536,18 @@ typedef void (*sighandler_t)(int);
extern char *stpcpy(char *p, const char *to_add) FAST_FUNC;
#endif
+#ifndef HAVE_MEMPCPY
+#include <string.h>
+/* In case we are wrong about !HAVE_MEMPCPY, and toolchain _does_ have
+ * mempcpy(), avoid colliding with it:
+ */
+#define mempcpy bb__mempcpy
+static ALWAYS_INLINE void *mempcpy(void *dest, const void *src, size_t len)
+{
+ return memcpy(dest, src, len) + len;
+}
+#endif
+
#ifndef HAVE_STRCASESTR
extern char *strcasestr(const char *s, const char *pattern) FAST_FUNC;
#endif
@@ -490,6 +565,10 @@ extern char *strsep(char **stringp, const char *delim) FAST_FUNC;
# define strsignal(sig) get_signame(sig)
#endif
+#ifndef HAVE_USLEEP
+extern int usleep(unsigned) FAST_FUNC;
+#endif
+
#ifndef HAVE_VASPRINTF
extern int vasprintf(char **string_ptr, const char *format, va_list p) FAST_FUNC;
#endif
diff --git a/release/src/router/busybox/include/pwd_.h b/release/src/router/busybox/include/pwd_.h
index ea158da452..17348298a0 100644
--- a/release/src/router/busybox/include/pwd_.h
+++ b/release/src/router/busybox/include/pwd_.h
@@ -34,72 +34,33 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
#define setpwent bb_internal_setpwent
#define endpwent bb_internal_endpwent
#define getpwent bb_internal_getpwent
-#define fgetpwent bb_internal_fgetpwent
-#define putpwent bb_internal_putpwent
#define getpwuid bb_internal_getpwuid
#define getpwnam bb_internal_getpwnam
-#define getpwent_r bb_internal_getpwent_r
-#define getpwuid_r bb_internal_getpwuid_r
#define getpwnam_r bb_internal_getpwnam_r
-#define fgetpwent_r bb_internal_fgetpwent_r
-
/* All function names below should be remapped by #defines above
* in order to not collide with libc names. */
-
/* Rewind the password-file stream. */
-extern void setpwent(void);
+void FAST_FUNC setpwent(void);
/* Close the password-file stream. */
-extern void endpwent(void);
+void FAST_FUNC endpwent(void);
-#ifdef UNUSED_SINCE_WE_AVOID_STATIC_BUFS
/* Read an entry from the password-file stream, opening it if necessary. */
-extern struct passwd *getpwent(void);
-
-/* Read an entry from STREAM. */
-extern struct passwd *fgetpwent(FILE *__stream);
-
-/* Write the given entry onto the given stream. */
-extern int putpwent(const struct passwd *__restrict __p,
- FILE *__restrict __f);
-#endif
+struct passwd* FAST_FUNC getpwent(void);
/* Search for an entry with a matching user ID. */
-extern struct passwd *getpwuid(uid_t __uid);
+struct passwd* FAST_FUNC getpwuid(uid_t __uid);
/* Search for an entry with a matching username. */
-extern struct passwd *getpwnam(const char *__name);
-
-/* Reentrant versions of some of the functions above.
-
- PLEASE NOTE: the `getpwent_r' function is not (yet) standardized.
- The interface may change in later versions of this library. But
- the interface is designed following the principals used for the
- other reentrant functions so the chances are good this is what the
- POSIX people would choose. */
-
-extern int getpwent_r(struct passwd *__restrict __resultbuf,
- char *__restrict __buffer, size_t __buflen,
- struct passwd **__restrict __result);
-
-extern int getpwuid_r(uid_t __uid,
- struct passwd *__restrict __resultbuf,
- char *__restrict __buffer, size_t __buflen,
- struct passwd **__restrict __result);
-
-extern int getpwnam_r(const char *__restrict __name,
- struct passwd *__restrict __resultbuf,
- char *__restrict __buffer, size_t __buflen,
- struct passwd **__restrict __result);
-
-/* Read an entry from STREAM. This function is not standardized and
- probably never will. */
-extern int fgetpwent_r(FILE *__restrict __stream,
- struct passwd *__restrict __resultbuf,
- char *__restrict __buffer, size_t __buflen,
- struct passwd **__restrict __result);
+struct passwd* FAST_FUNC getpwnam(const char *__name);
+
+/* Reentrant versions of some of the functions above. */
+int FAST_FUNC getpwnam_r(const char *__restrict __name,
+ struct passwd *__restrict __resultbuf,
+ char *__restrict __buffer, size_t __buflen,
+ struct passwd **__restrict __result);
POP_SAVED_FUNCTION_VISIBILITY
diff --git a/release/src/router/busybox/include/shadow_.h b/release/src/router/busybox/include/shadow_.h
index 648a62ab32..8e2581e7cd 100644
--- a/release/src/router/busybox/include/shadow_.h
+++ b/release/src/router/busybox/include/shadow_.h
@@ -57,48 +57,48 @@ struct spwd {
#ifdef UNUSED_FOR_NOW
/* Open database for reading */
-extern void setspent(void);
+void FAST_FUNC setspent(void);
/* Close database */
-extern void endspent(void);
+void FAST_FUNC endspent(void);
/* Get next entry from database, perhaps after opening the file */
-extern struct spwd *getspent(void);
+struct spwd* FAST_FUNC getspent(void);
/* Get shadow entry matching NAME */
-extern struct spwd *getspnam(const char *__name);
+struct spwd* FAST_FUNC getspnam(const char *__name);
/* Read shadow entry from STRING */
-extern struct spwd *sgetspent(const char *__string);
+struct spwd* FAST_FUNC sgetspent(const char *__string);
/* Read next shadow entry from STREAM */
-extern struct spwd *fgetspent(FILE *__stream);
+struct spwd* FAST_FUNC fgetspent(FILE *__stream);
/* Write line containing shadow password entry to stream */
-extern int putspent(const struct spwd *__p, FILE *__stream);
+int FAST_FUNC putspent(const struct spwd *__p, FILE *__stream);
/* Reentrant versions of some of the functions above */
-extern int getspent_r(struct spwd *__result_buf, char *__buffer,
- size_t __buflen, struct spwd **__result);
+int FAST_FUNC getspent_r(struct spwd *__result_buf, char *__buffer,
+ size_t __buflen, struct spwd **__result);
#endif
-extern int getspnam_r(const char *__name, struct spwd *__result_buf,
- char *__buffer, size_t __buflen,
- struct spwd **__result);
+int FAST_FUNC getspnam_r(const char *__name, struct spwd *__result_buf,
+ char *__buffer, size_t __buflen,
+ struct spwd **__result);
#ifdef UNUSED_FOR_NOW
-extern int sgetspent_r(const char *__string, struct spwd *__result_buf,
- char *__buffer, size_t __buflen,
- struct spwd **__result);
+int FAST_FUNC sgetspent_r(const char *__string, struct spwd *__result_buf,
+ char *__buffer, size_t __buflen,
+ struct spwd **__result);
-extern int fgetspent_r(FILE *__stream, struct spwd *__result_buf,
- char *__buffer, size_t __buflen,
- struct spwd **__result);
+int FAST_FUNC fgetspent_r(FILE *__stream, struct spwd *__result_buf,
+ char *__buffer, size_t __buflen,
+ struct spwd **__result);
/* Protect password file against multi writers */
-extern int lckpwdf(void);
+int FAST_FUNC lckpwdf(void);
/* Unlock password file */
-extern int ulckpwdf(void);
+int FAST_FUNC ulckpwdf(void);
#endif
POP_SAVED_FUNCTION_VISIBILITY
diff --git a/release/src/router/busybox/include/usage.src.h b/release/src/router/busybox/include/usage.src.h
index fd3994747c..78beccf4d7 100644
--- a/release/src/router/busybox/include/usage.src.h
+++ b/release/src/router/busybox/include/usage.src.h
@@ -20,27 +20,3 @@ INSERT
"Hello world!\n"
#endif
-/* Asus added these on top of their 1.17.4. The code came from
- * Qualcomm, so we can't backport it properly from 1.2x.
- * Putting these here for now, however this shouldn't matter
- as these two applets are only for QCA devices
- (which we don't support). If it fails to build we can
- always simply remove these Qualcomm-specific additions.
-*/
-
-#define md_trivial_usage \
- "md address [count]"
-#define md_full_usage "\n\n" \
- "md address [count]\n"
-
-#define mm_trivial_usage \
- "mm address value"
-#define mm_full_usage "\n\n" \
- "mm address value\n"
-
-#define ethreg_trivial_usage \
- "ethreg ......"
-#define ethreg_full_usage "\n\n" \
- "ethreg ......\n"
-
-
diff --git a/release/src/router/busybox/include/volume_id.h b/release/src/router/busybox/include/volume_id.h
index b61f100eb9..a83da899e4 100644
--- a/release/src/router/busybox/include/volume_id.h
+++ b/release/src/router/busybox/include/volume_id.h
@@ -20,14 +20,12 @@
char *get_devname_from_label(const char *spec);
char *get_devname_from_uuid(const char *spec);
-char *get_devname_from_device(dev_t dev);
void display_uuid_cache(int scan_devices);
/* Returns:
- * 0 : no UUID= or LABEL= prefix found
- * 1 : UUID= or LABEL= prefix found. In this case,
- * *fsname is replaced if device with such UUID or LABEL is found
- * -2: UUID= or LABEL= prefixes cannot be resolved
+ * 0: no UUID= or LABEL= prefix found
+ * 1: UUID= or LABEL= prefix found. In this case,
+ * *fsname is replaced if device with such UUID or LABEL is found
*/
int resolve_mount_spec(char **fsname);
-int add_to_uuid_cache(const char *device, dev_t devno);
+int add_to_uuid_cache(const char *device);
diff --git a/release/src/router/busybox/init/bootchartd.c b/release/src/router/busybox/init/bootchartd.c
index 9fd6233578..92aaade0ff 100644
--- a/release/src/router/busybox/init/bootchartd.c
+++ b/release/src/router/busybox/init/bootchartd.c
@@ -47,6 +47,7 @@
//config: and /etc/bootchartd.conf files.
#include "libbb.h"
+#include "common_bufsiz.h"
/* After libbb.h, since it needs sys/types.h on some systems */
#include <sys/utsname.h>
@@ -60,6 +61,12 @@
# endif
#endif
+#if !ENABLE_TAR && !ENABLE_WERROR
+# warning Note: bootchartd requires tar command, but you did not select it.
+#elif !ENABLE_FEATURE_SEAMLESS_GZ && !ENABLE_WERROR
+# warning Note: bootchartd requires tar -z support, but you did not select it.
+#endif
+
#define BC_VERSION_STR "0.8"
/* For debugging, set to 0:
@@ -109,8 +116,8 @@
struct globals {
char jiffy_line[COMMON_BUFSIZE];
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
-#define INIT_G() do { } while (0)
+#define G (*(struct globals*)bb_common_bufsiz1)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
static void dump_file(FILE *fp, const char *filename)
{
@@ -187,7 +194,7 @@ static char *make_tempdir(void)
* Since we unmount it at once, we can mount it anywhere.
* Try a few locations which are likely ti exist.
*/
- static const char dirs[] = "/mnt\0""/tmp\0""/boot\0""/proc\0";
+ static const char dirs[] ALIGN1 = "/mnt\0""/tmp\0""/boot\0""/proc\0";
const char *try_dir = dirs;
while (mount("none", try_dir, "tmpfs", MS_SILENT, "size=16m") != 0) {
try_dir += strlen(try_dir) + 1;
diff --git a/release/src/router/busybox/init/halt.c b/release/src/router/busybox/init/halt.c
index 7974adb17f..572d751b00 100644
--- a/release/src/router/busybox/init/halt.c
+++ b/release/src/router/busybox/init/halt.c
@@ -74,7 +74,7 @@
static void write_wtmp(void)
{
- struct utmp utmp;
+ struct utmpx utmp;
struct utsname uts;
/* "man utmp" says wtmp file should *not* be created automagically */
/*if (access(bb_path_wtmp_file, R_OK|W_OK) == -1) {
@@ -88,7 +88,7 @@ static void write_wtmp(void)
utmp.ut_line[0] = '~'; utmp.ut_line[1] = '~'; /* = strcpy(utmp.ut_line, "~~"); */
uname(&uts);
safe_strncpy(utmp.ut_host, uts.release, sizeof(utmp.ut_host));
- updwtmp(bb_path_wtmp_file, &utmp);
+ updwtmpx(bb_path_wtmp_file, &utmp);
}
#else
#define write_wtmp() ((void)0)
@@ -135,7 +135,7 @@ int halt_main(int argc UNUSED_PARAM, char **argv)
if (!(flags & 4)) { /* no -f */
//TODO: I tend to think that signalling linuxrc is wrong
// pity original author didn't comment on it...
- if (ENABLE_FEATURE_INITRD) {
+ if (ENABLE_LINUXRC) {
/* talk to linuxrc */
/* bbox init/linuxrc assumed */
pid_t *pidlist = find_pid_by_name("linuxrc");
diff --git a/release/src/router/busybox/init/init.c b/release/src/router/busybox/init/init.c
index 7248946988..6eb76b80e4 100644
--- a/release/src/router/busybox/init/init.c
+++ b/release/src/router/busybox/init/init.c
@@ -9,11 +9,6 @@
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
-//applet:IF_INIT(APPLET(init, BB_DIR_SBIN, BB_SUID_DROP))
-//applet:IF_FEATURE_INITRD(APPLET_ODDNAME(linuxrc, init, BB_DIR_ROOT, BB_SUID_DROP, linuxrc))
-
-//kbuild:lib-$(CONFIG_INIT) += init.o
-
//config:config INIT
//config: bool "init"
//config: default y
@@ -21,10 +16,21 @@
//config: help
//config: init is the first program run when the system boots.
//config:
+//config:config LINUXRC
+//config: bool "Support running init from within an initrd (not initramfs)"
+//config: default y
+//config: select FEATURE_SYSLOG
+//config: help
+//config: Legacy support for running init under the old-style initrd. Allows
+//config: the name linuxrc to act as init, and it doesn't assume init is PID 1.
+//config:
+//config: This does not apply to initramfs, which runs /init as PID 1 and
+//config: requires no special support.
+//config:
//config:config FEATURE_USE_INITTAB
//config: bool "Support reading an inittab file"
//config: default y
-//config: depends on INIT
+//config: depends on INIT || LINUXRC
//config: help
//config: Allow init to read an inittab file when the system boot.
//config:
@@ -51,7 +57,7 @@
//config:config FEATURE_INIT_SCTTY
//config: bool "Run commands with leading dash with controlling tty"
//config: default y
-//config: depends on INIT
+//config: depends on INIT || LINUXRC
//config: help
//config: If this option is enabled, init will try to give a controlling
//config: tty to any command which has leading hyphen (often it's "-/bin/sh").
@@ -66,40 +72,29 @@
//config:config FEATURE_INIT_SYSLOG
//config: bool "Enable init to write to syslog"
//config: default y
-//config: depends on INIT
+//config: depends on INIT || LINUXRC
//config:
//config:config FEATURE_EXTRA_QUIET
//config: bool "Be _extra_ quiet on boot"
//config: default y
-//config: depends on INIT
+//config: depends on INIT || LINUXRC
//config: help
//config: Prevent init from logging some messages to the console during boot.
//config:
//config:config FEATURE_INIT_COREDUMPS
//config: bool "Support dumping core for child processes (debugging only)"
//config: default y
-//config: depends on INIT
+//config: depends on INIT || LINUXRC
//config: help
//config: If this option is enabled and the file /.init_enable_core
//config: exists, then init will call setrlimit() to allow unlimited
//config: core file sizes. If this option is disabled, processes
//config: will not generate any core files.
//config:
-//config:config FEATURE_INITRD
-//config: bool "Support running init from within an initrd (not initramfs)"
-//config: default y
-//config: depends on INIT
-//config: help
-//config: Legacy support for running init under the old-style initrd. Allows
-//config: the name linuxrc to act as init, and it doesn't assume init is PID 1.
-//config:
-//config: This does not apply to initramfs, which runs /init as PID 1 and
-//config: requires no special support.
-//config:
//config:config INIT_TERMINAL_TYPE
//config: string "Initial terminal type"
//config: default "linux"
-//config: depends on INIT
+//config: depends on INIT || LINUXRC
//config: help
//config: This is the initial value set by init for the TERM environment
//config: variable. This variable is used by programs which make use of
@@ -107,12 +102,32 @@
//config:
//config: Note that on Linux, init attempts to detect serial terminal and
//config: sets TERM to "vt102" if one is found.
+//config:
+//config:config FEATURE_INIT_MODIFY_CMDLINE
+//config: bool "Modify the command-line to \"init\""
+//config: default y
+//config: depends on INIT || LINUXRC
+//config: help
+//config: When launched as PID 1 and after parsing its arguments, init
+//config: wipes all the arguments but argv[0] and rewrites argv[0] to
+//config: contain only "init", so that its command-line appears solely as
+//config: "init" in tools such as ps.
+//config: If this option is set to Y, init will keep its original behavior,
+//config: otherwise, all the arguments including argv[0] will be preserved,
+//config: be they parsed or ignored by init.
+//config: The original command-line used to launch init can then be
+//config: retrieved in /proc/1/cmdline on Linux, for example.
+
+//applet:IF_INIT(APPLET(init, BB_DIR_SBIN, BB_SUID_DROP))
+//applet:IF_LINUXRC(APPLET_ODDNAME(linuxrc, init, BB_DIR_ROOT, BB_SUID_DROP, linuxrc))
+
+//kbuild:lib-$(CONFIG_INIT) += init.o
+//kbuild:lib-$(CONFIG_LINUXRC) += init.o
#define DEBUG_SEGV_HANDLER 0
#include "libbb.h"
#include <syslog.h>
-#include <paths.h>
#include <sys/resource.h>
#ifdef __linux__
# include <linux/vt.h>
@@ -140,12 +155,11 @@
* not fully functional init by switching it on! */
#define DEBUG_INIT 0
-#define COMMAND_SIZE 256
#define CONSOLE_NAME_SIZE 32
/* Default sysinit script. */
#ifndef INIT_SCRIPT
-#define INIT_SCRIPT "/etc/init.d/rcS"
+# define INIT_SCRIPT "/etc/init.d/rcS"
#endif
/* Each type of actions can appear many times. They will be
@@ -195,7 +209,7 @@ struct init_action {
pid_t pid;
uint8_t action_type;
char terminal[CONSOLE_NAME_SIZE];
- char command[COMMAND_SIZE];
+ char command[1];
};
static struct init_action *init_action_list = NULL;
@@ -223,8 +237,8 @@ static void message(int where, const char *fmt, ...)
msg[0] = '\r';
va_start(arguments, fmt);
l = 1 + vsnprintf(msg + 1, sizeof(msg) - 2, fmt, arguments);
- if (l > sizeof(msg) - 1)
- l = sizeof(msg) - 1;
+ if (l > sizeof(msg) - 2)
+ l = sizeof(msg) - 2;
va_end(arguments);
#if ENABLE_FEATURE_INIT_SYSLOG
@@ -398,7 +412,7 @@ static void reset_sighandlers_and_unblock_sigs(void)
}
/* Wrapper around exec:
- * Takes string (max COMMAND_SIZE chars).
+ * Takes string.
* If chars like '>' detected, execs '[-]/bin/sh -c "exec ......."'.
* Otherwise splits words on whitespace, deals with leading dash,
* and uses plain exec().
@@ -406,10 +420,15 @@ static void reset_sighandlers_and_unblock_sigs(void)
*/
static void init_exec(const char *command)
{
- char *cmd[COMMAND_SIZE / 2];
- char buf[COMMAND_SIZE + 6]; /* COMMAND_SIZE+strlen("exec ")+1 */
- int dash = (command[0] == '-' /* maybe? && command[1] == '/' */);
-
+ /* +8 allows to write VLA sizes below more efficiently: */
+ unsigned command_size = strlen(command) + 8;
+ /* strlen(command) + strlen("exec ")+1: */
+ char buf[command_size];
+ /* strlen(command) / 2 + 4: */
+ char *cmd[command_size / 2];
+ int dash;
+
+ dash = (command[0] == '-' /* maybe? && command[1] == '/' */);
command += dash;
/* See if any special /bin/sh requiring characters are present */
@@ -520,7 +539,7 @@ static pid_t run(const struct init_action *a)
/* Log the process name and args */
message(L_LOG, "starting pid %d, tty '%s': '%s'",
- getpid(), a->terminal, a->command);
+ getpid(), a->terminal, a->command);
/* Now run it. The new program will take over this PID,
* so nothing further in init.c should be run. */
@@ -534,11 +553,7 @@ static struct init_action *mark_terminated(pid_t pid)
struct init_action *a;
if (pid > 0) {
- update_utmp(pid, DEAD_PROCESS,
- /*tty_name:*/ NULL,
- /*username:*/ NULL,
- /*hostname:*/ NULL
- );
+ update_utmp_DEAD_PROCESS(pid);
for (a = init_action_list; a; a = a->next) {
if (a->pid == pid) {
a->pid = 0;
@@ -626,21 +641,21 @@ static void new_init_action(uint8_t action_type, const char *command, const char
nextp = &a->next;
}
- a = xzalloc(sizeof(*a));
+ a = xzalloc(sizeof(*a) + strlen(command));
/* Append to the end of the list */
append:
*nextp = a;
a->action_type = action_type;
- safe_strncpy(a->command, command, sizeof(a->command));
+ strcpy(a->command, command);
safe_strncpy(a->terminal, cons, sizeof(a->terminal));
- dbg_message(L_LOG | L_CONSOLE, "command='%s' action=%d tty='%s'\n",
+ dbg_message(L_LOG | L_CONSOLE, "command='%s' action=%x tty='%s'\n",
a->command, a->action_type, a->terminal);
}
/* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined,
* then parse_inittab() simply adds in some default
- * actions(i.e., runs INIT_SCRIPT and then starts a pair
+ * actions (i.e., runs INIT_SCRIPT and then starts a pair
* of "askfirst" shells). If CONFIG_FEATURE_USE_INITTAB
* _is_ defined, but /etc/inittab is missing, this
* results in the same set of default behaviors.
@@ -655,23 +670,22 @@ static void parse_inittab(void)
#endif
{
/* No inittab file - set up some default behavior */
- /* Reboot on Ctrl-Alt-Del */
- new_init_action(CTRLALTDEL, "reboot", "");
- /* Umount all filesystems on halt/reboot */
- new_init_action(SHUTDOWN, "umount -a -r", "");
- /* Swapoff on halt/reboot */
- if (ENABLE_SWAPONOFF)
- new_init_action(SHUTDOWN, "swapoff -a", "");
- /* Prepare to restart init when a QUIT is received */
- new_init_action(RESTART, "init", "");
+ /* Sysinit */
+ new_init_action(SYSINIT, INIT_SCRIPT, "");
/* Askfirst shell on tty1-4 */
new_init_action(ASKFIRST, bb_default_login_shell, "");
//TODO: VC_1 instead of ""? "" is console -> ctty problems -> angry users
new_init_action(ASKFIRST, bb_default_login_shell, VC_2);
new_init_action(ASKFIRST, bb_default_login_shell, VC_3);
new_init_action(ASKFIRST, bb_default_login_shell, VC_4);
- /* sysinit */
- new_init_action(SYSINIT, INIT_SCRIPT, "");
+ /* Reboot on Ctrl-Alt-Del */
+ new_init_action(CTRLALTDEL, "reboot", "");
+ /* Umount all filesystems on halt/reboot */
+ new_init_action(SHUTDOWN, "umount -a -r", "");
+ /* Swapoff on halt/reboot */
+ new_init_action(SHUTDOWN, "swapoff -a", "");
+ /* Restart init when a QUIT is received */
+ new_init_action(RESTART, "init", "");
return;
}
@@ -786,7 +800,7 @@ static void run_shutdown_and_kill_processes(void)
* and only one will be remembered and acted upon.
*/
-/* The SIGUSR[12]/SIGTERM handler */
+/* The SIGPWR/SIGUSR[12]/SIGTERM handler */
static void halt_reboot_pwoff(int sig) NORETURN;
static void halt_reboot_pwoff(int sig)
{
@@ -819,7 +833,7 @@ static void halt_reboot_pwoff(int sig)
/* Handler for QUIT - exec "restart" action,
* else (no such action defined) do nothing */
-static void restart_handler(int sig UNUSED_PARAM)
+static void exec_restart_action(void)
{
struct init_action *a;
@@ -931,10 +945,17 @@ static void reload_inittab(void)
/* Remove stale entries and SYSINIT entries.
* We never rerun SYSINIT entries anyway,
- * removing them too saves a few bytes */
+ * removing them too saves a few bytes
+ */
nextp = &init_action_list;
while ((a = *nextp) != NULL) {
- if ((a->action_type & ~SYSINIT) == 0) {
+ /*
+ * Why pid == 0 check?
+ * Process can be removed from inittab and added *later*.
+ * If we delete its entry but process still runs,
+ * duplicate is spawned when the entry is re-added.
+ */
+ if ((a->action_type & ~SYSINIT) == 0 && a->pid == 0) {
*nextp = a->next;
free(a);
} else {
@@ -965,6 +986,20 @@ static int check_delayed_sigs(void)
#endif
if (sig == SIGINT)
run_actions(CTRLALTDEL);
+ if (sig == SIGQUIT) {
+ exec_restart_action();
+ /* returns only if no restart action defined */
+ }
+ if ((1 << sig) & (0
+#ifdef SIGPWR
+ + (1 << SIGPWR)
+#endif
+ + (1 << SIGUSR1)
+ + (1 << SIGUSR2)
+ + (1 << SIGTERM)
+ )) {
+ halt_reboot_pwoff(sig);
+ }
}
}
@@ -995,6 +1030,11 @@ void handle_sigsegv(int sig, siginfo_t *info, void *ucontext)
}
#endif
+static void sleep_much(void)
+{
+ sleep(30 * 24*60*60);
+}
+
int init_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int init_main(int argc UNUSED_PARAM, char **argv)
{
@@ -1018,7 +1058,7 @@ int init_main(int argc UNUSED_PARAM, char **argv)
if (!DEBUG_INIT) {
/* Expect to be invoked as init with PID=1 or be invoked as linuxrc */
if (getpid() != 1
- && (!ENABLE_FEATURE_INITRD || applet_name[0] != 'l') /* not linuxrc? */
+ && (!ENABLE_LINUXRC || applet_name[0] != 'l') /* not linuxrc? */
) {
bb_error_msg_and_die("must be run as PID 1");
}
@@ -1031,12 +1071,12 @@ int init_main(int argc UNUSED_PARAM, char **argv)
/* If, say, xmalloc would ever die, we don't want to oops kernel
* by exiting.
- * NB: we set die_sleep *after* PID 1 check and bb_show_usage.
+ * NB: we set die_func *after* PID 1 check and bb_show_usage.
* Otherwise, for example, "init u" ("please rexec yourself"
* command for sysvinit) will show help text (which isn't too bad),
* *and sleep forever* (which is bad!)
*/
- die_sleep = 30 * 24*60*60;
+ die_func = sleep_much;
/* Figure out where the default console should be */
console_init();
@@ -1058,10 +1098,13 @@ int init_main(int argc UNUSED_PARAM, char **argv)
message(L_CONSOLE | L_LOG, "init started: %s", bb_banner);
#endif
+#if 0
+/* It's 2013, does anyone really still depend on this? */
+/* If you do, consider adding swapon to sysinit actions then! */
/* struct sysinfo is linux-specific */
-#ifdef __linux__
+# ifdef __linux__
/* Make sure there is enough memory to do something useful. */
- if (ENABLE_SWAPONOFF) {
+ /*if (ENABLE_SWAPONOFF) - WRONG: we may have non-bbox swapon*/ {
struct sysinfo info;
if (sysinfo(&info) == 0
@@ -1075,6 +1118,7 @@ int init_main(int argc UNUSED_PARAM, char **argv)
run_actions(SYSINIT); /* wait and removing */
}
}
+# endif
#endif
/* Check if we are supposed to be in single user mode */
@@ -1089,8 +1133,8 @@ int init_main(int argc UNUSED_PARAM, char **argv)
/* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined,
* then parse_inittab() simply adds in some default
- * actions(i.e., INIT_SCRIPT and a pair
- * of "askfirst" shells */
+ * actions (i.e., INIT_SCRIPT and a pair
+ * of "askfirst" shells) */
parse_inittab();
}
@@ -1110,23 +1154,18 @@ int init_main(int argc UNUSED_PARAM, char **argv)
}
#endif
- /* Make the command line just say "init" - thats all, nothing else */
- strncpy(argv[0], "init", strlen(argv[0]));
- /* Wipe argv[1]-argv[N] so they don't clutter the ps listing */
- while (*++argv)
- memset(*argv, 0, strlen(*argv));
+ if (ENABLE_FEATURE_INIT_MODIFY_CMDLINE) {
+ /* Make the command line just say "init" - that's all, nothing else */
+ strncpy(argv[0], "init", strlen(argv[0]));
+ /* Wipe argv[1]-argv[N] so they don't clutter the ps listing */
+ while (*++argv)
+ nuke_str(*argv);
+ }
/* Set up signal handlers */
if (!DEBUG_INIT) {
struct sigaction sa;
- bb_signals(0
- + (1 << SIGUSR1) /* halt */
- + (1 << SIGTERM) /* reboot */
- + (1 << SIGUSR2) /* poweroff */
- , halt_reboot_pwoff);
- signal(SIGQUIT, restart_handler); /* re-exec another init */
-
/* Stop handler must allow only SIGCONT inside itself */
memset(&sa, 0, sizeof(sa));
sigfillset(&sa.sa_mask);
@@ -1141,18 +1180,24 @@ int init_main(int argc UNUSED_PARAM, char **argv)
*/
sigaction_set(SIGSTOP, &sa); /* pause */
- /* SIGINT (Ctrl-Alt-Del) must interrupt wait(),
+ /* These signals must interrupt wait(),
* setting handler without SA_RESTART flag.
*/
- bb_signals_recursive_norestart((1 << SIGINT), record_signo);
+ bb_signals_recursive_norestart(0
+ + (1 << SIGINT) /* Ctrl-Alt-Del */
+ + (1 << SIGQUIT) /* re-exec another init */
+#ifdef SIGPWR
+ + (1 << SIGPWR) /* halt */
+#endif
+ + (1 << SIGUSR1) /* halt */
+ + (1 << SIGTERM) /* reboot */
+ + (1 << SIGUSR2) /* poweroff */
+#if ENABLE_FEATURE_USE_INITTAB
+ + (1 << SIGHUP) /* reread /etc/inittab */
+#endif
+ , record_signo);
}
- /* Set up "reread /etc/inittab" handler.
- * Handler is set up without SA_RESTART, it will interrupt syscalls.
- */
- if (!DEBUG_INIT && ENABLE_FEATURE_USE_INITTAB)
- bb_signals_recursive_norestart((1 << SIGHUP), record_signo);
-
/* Now run everything that needs to be run */
/* First run the sysinit command */
run_actions(SYSINIT);
@@ -1216,7 +1261,14 @@ int init_main(int argc UNUSED_PARAM, char **argv)
//usage:#define init_trivial_usage
//usage: ""
//usage:#define init_full_usage "\n\n"
-//usage: "Init is the parent of all processes"
+//usage: "Init is the first process started during boot. It never exits."
+//usage: IF_FEATURE_USE_INITTAB(
+//usage: "\n""It (re)spawns children according to /etc/inittab."
+//usage: )
+//usage: IF_NOT_FEATURE_USE_INITTAB(
+//usage: "\n""This version of init doesn't use /etc/inittab,"
+//usage: "\n""has fixed set of processed to run."
+//usage: )
//usage:
//usage:#define init_notes_usage
//usage: "This version of init is designed to be run only by the kernel.\n"
@@ -1234,9 +1286,6 @@ int init_main(int argc UNUSED_PARAM, char **argv)
//usage: " ::shutdown:/sbin/swapoff -a\n"
//usage: " ::shutdown:/bin/umount -a -r\n"
//usage: " ::restart:/sbin/init\n"
-//usage: "\n"
-//usage: "if it detects that /dev/console is _not_ a serial console, it will also run:\n"
-//usage: "\n"
//usage: " tty2::askfirst:/bin/sh\n"
//usage: " tty3::askfirst:/bin/sh\n"
//usage: " tty4::askfirst:/bin/sh\n"
@@ -1252,11 +1301,7 @@ int init_main(int argc UNUSED_PARAM, char **argv)
//usage: " the specified process to run on. The contents of this field are\n"
//usage: " appended to \"/dev/\" and used as-is. There is no need for this field to\n"
//usage: " be unique, although if it isn't you may have strange results. If this\n"
-//usage: " field is left blank, the controlling tty is set to the console. Also\n"
-//usage: " note that if BusyBox detects that a serial console is in use, then only\n"
-//usage: " entries whose controlling tty is either the serial console or /dev/null\n"
-//usage: " will be run. BusyBox init does nothing with utmp. We don't need no\n"
-//usage: " stinkin' utmp.\n"
+//usage: " field is left blank, then the init's stdin/out will be used.\n"
//usage: "\n"
//usage: " <runlevels>:\n"
//usage: "\n"
diff --git a/release/src/router/busybox/libbb/Config.src b/release/src/router/busybox/libbb/Config.src
index ee1b66a458..6ba256290e 100644
--- a/release/src/router/busybox/libbb/Config.src
+++ b/release/src/router/busybox/libbb/Config.src
@@ -16,7 +16,7 @@ config PASSWORD_MINLEN
config MD5_SMALL
int "MD5: Trade bytes for speed (0:fast, 3:slow)"
- default 1
+ default 1 # all "fast or small" options default to small
range 0 3
help
Trade binary size versus speed for the md5sum algorithm.
@@ -28,9 +28,19 @@ config MD5_SMALL
2 3.0 5088
3 (smallest) 5.1 4912
+config SHA3_SMALL
+ int "SHA3: Trade bytes for speed (0:fast, 1:slow)"
+ default 1 # all "fast or small" options default to small
+ range 0 1
+ help
+ Trade binary size versus speed for the sha3sum algorithm.
+ SHA3_SMALL=0 compared to SHA3_SMALL=1 (approximate):
+ 64-bit x86: +270 bytes of code, 45% faster
+ 32-bit x86: +450 bytes of code, 75% faster
+
config FEATURE_FAST_TOP
bool "Faster /proc scanning code (+100 bytes)"
- default y
+ default n # all "fast or small" options default to small
help
This option makes top (and ps) ~20% faster (or 20% less CPU hungry),
but code size is slightly bigger.
@@ -104,7 +114,7 @@ config FEATURE_EDITING_SAVE_ON_EXIT
config FEATURE_REVERSE_SEARCH
bool "Reverse history search"
default y
- depends on FEATURE_EDITING_SAVEHISTORY
+ depends on FEATURE_EDITING
help
Enable readline-like Ctrl-R combination for reverse history search.
Increases code by about 0.5k.
@@ -198,7 +208,7 @@ config FEATURE_SKIP_ROOTFS
config MONOTONIC_SYSCALL
bool "Use clock_gettime(CLOCK_MONOTONIC) syscall"
- default n
+ default y
select PLATFORM_LINUX
help
Use clock_gettime(CLOCK_MONOTONIC) syscall for measuring
diff --git a/release/src/router/busybox/libbb/Kbuild.src b/release/src/router/busybox/libbb/Kbuild.src
index 0adfdd8746..52a90e9a1e 100644
--- a/release/src/router/busybox/libbb/Kbuild.src
+++ b/release/src/router/busybox/libbb/Kbuild.src
@@ -27,12 +27,10 @@ lib-y += concat_subpath_file.o
lib-y += copy_file.o
lib-y += copyfd.o
lib-y += crc32.o
-lib-y += create_icmp6_socket.o
-lib-y += create_icmp_socket.o
lib-y += default_error_retval.o
lib-y += device_open.o
lib-y += dump.o
-lib-y += execable.o
+lib-y += executable.o
lib-y += fclose_nonstdin.o
lib-y += fflush_stdout_and_exit.o
lib-y += fgets_str.o
@@ -48,7 +46,6 @@ lib-y += get_volsize.o
lib-y += herror_msg.o
lib-y += human_readable.o
lib-y += inet_common.o
-lib-y += info_msg.o
lib-y += inode_hash.o
lib-y += isdirectory.o
lib-y += kernel_version.o
@@ -94,6 +91,7 @@ lib-y += skip_whitespace.o
lib-y += speed_table.o
lib-y += str_tolower.o
lib-y += strrstr.o
+lib-y += sysconf.o
lib-y += time.o
lib-y += trim.o
lib-y += u_signal_names.o
@@ -134,7 +132,6 @@ lib-$(CONFIG_TFTPD) += udp_io.o
lib-$(CONFIG_TCPSVD) += udp_io.o
lib-$(CONFIG_UDPSVD) += udp_io.o
lib-$(CONFIG_TRACEROUTE) += udp_io.o
-lib-$(CONFIG_DHCP6C) += udp_io.o
lib-$(CONFIG_LOSETUP) += loop.o
lib-$(CONFIG_FEATURE_MOUNT_LOOP) += loop.o
@@ -144,14 +141,17 @@ lib-$(CONFIG_ADDUSER) += update_passwd.o
lib-$(CONFIG_DELGROUP) += update_passwd.o
lib-$(CONFIG_DELUSER) += update_passwd.o
+lib-$(CONFIG_FTPD) += correct_password.o
lib-$(CONFIG_PASSWD) += pw_encrypt.o update_passwd.o obscure.o
lib-$(CONFIG_CHPASSWD) += pw_encrypt.o update_passwd.o
lib-$(CONFIG_CRYPTPW) += pw_encrypt.o
-lib-$(CONFIG_SULOGIN) += pw_encrypt.o
+lib-$(CONFIG_MKPASSWD) += pw_encrypt.o
+lib-$(CONFIG_SULOGIN) += pw_encrypt.o correct_password.o
lib-$(CONFIG_VLOCK) += pw_encrypt.o correct_password.o
lib-$(CONFIG_SU) += pw_encrypt.o correct_password.o
lib-$(CONFIG_LOGIN) += pw_encrypt.o correct_password.o
lib-$(CONFIG_FEATURE_HTTPD_AUTH_MD5) += pw_encrypt.o
+lib-$(CONFIG_FEATURE_FTP_AUTHENTICATION) += pw_encrypt.o
lib-$(CONFIG_DF) += find_mount_point.o
lib-$(CONFIG_MKFS_MINIX) += find_mount_point.o
@@ -188,3 +188,6 @@ lib-$(CONFIG_PGREP) += xregcomp.o
lib-$(CONFIG_PKILL) += xregcomp.o
lib-$(CONFIG_DEVFSD) += xregcomp.o
lib-$(CONFIG_FEATURE_FIND_REGEX) += xregcomp.o
+
+# Add the experimental logging functionality, only used by zcip
+lib-$(CONFIG_ZCIP) += logenv.o
diff --git a/release/src/router/busybox/libbb/appletlib.c b/release/src/router/busybox/libbb/appletlib.c
index 73f71f1d02..480bf50fc3 100644
--- a/release/src/router/busybox/libbb/appletlib.c
+++ b/release/src/router/busybox/libbb/appletlib.c
@@ -29,7 +29,7 @@
#include "busybox.h"
#if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \
- || defined(__APPLE__) \
+ || defined(__APPLE__) \
)
# include <malloc.h> /* for mallopt */
#endif
@@ -52,6 +52,7 @@
#include "usage_compressed.h"
+static void run_applet_and_exit(const char *name, char **argv) NORETURN;
#if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE
static const char usage_messages[] ALIGN1 = UNPACKED_USAGE;
@@ -130,7 +131,7 @@ void FAST_FUNC bb_show_usage(void)
full_write2_str(applet_name);
full_write2_str(" ");
full_write2_str(p);
- full_write2_str("\n\n");
+ full_write2_str("\n");
}
if (ENABLE_FEATURE_CLEAN_UP)
dealloc_usage_messages((char*)usage_string);
@@ -139,31 +140,127 @@ void FAST_FUNC bb_show_usage(void)
xfunc_die();
}
-#if NUM_APPLETS > 8
-/* NB: any char pointer will work as well, not necessarily applet_names */
-static int applet_name_compare(const void *name, const void *v)
-{
- int i = (const char *)v - applet_names;
- return strcmp(name, APPLET_NAME(i));
-}
-#endif
int FAST_FUNC find_applet_by_name(const char *name)
{
-#if NUM_APPLETS > 8
- /* Do a binary search to find the applet entry given the name. */
+ unsigned i, max;
+ int j;
const char *p;
- p = bsearch(name, applet_names, ARRAY_SIZE(applet_main), 1, applet_name_compare);
- if (!p)
- return -1;
- return p - applet_names;
+
+/* The commented-out word-at-a-time code is ~40% faster, but +160 bytes.
+ * "Faster" here saves ~0.5 microsecond of real time - not worth it.
+ */
+#if 0 /*BB_UNALIGNED_MEMACCESS_OK && BB_LITTLE_ENDIAN*/
+ uint32_t n32;
+
+ /* Handle all names < 2 chars long early */
+ if (name[0] == '\0')
+ return -1; /* "" is not a valid applet name */
+ if (name[1] == '\0') {
+ if (!ENABLE_TEST)
+ return -1; /* 1-char name is not valid */
+ if (name[0] != ']')
+ return -1; /* 1-char name which isn't "[" is not valid */
+ /* applet "[" is always applet #0: */
+ return 0;
+ }
+#endif
+
+ p = applet_names;
+ i = 0;
+#if KNOWN_APPNAME_OFFSETS <= 0
+ max = NUM_APPLETS;
#else
- /* A version which does not pull in bsearch */
- int i = 0;
- const char *p = applet_names;
- while (i < NUM_APPLETS) {
- if (strcmp(name, p) == 0)
+ max = NUM_APPLETS * KNOWN_APPNAME_OFFSETS;
+ for (j = ARRAY_SIZE(applet_nameofs)-1; j >= 0; j--) {
+ const char *pp = applet_names + applet_nameofs[j];
+ if (strcmp(name, pp) >= 0) {
+ //bb_error_msg("name:'%s' >= pp:'%s'", name, pp);
+ p = pp;
+ i = max - NUM_APPLETS;
+ break;
+ }
+ max -= NUM_APPLETS;
+ }
+ max /= (unsigned)KNOWN_APPNAME_OFFSETS;
+ i /= (unsigned)KNOWN_APPNAME_OFFSETS;
+ //bb_error_msg("name:'%s' starting from:'%s' i:%u max:%u", name, p, i, max);
+#endif
+
+ /* Open-coded linear search without strcmp/strlen calls for speed */
+
+#if 0 /*BB_UNALIGNED_MEMACCESS_OK && BB_LITTLE_ENDIAN*/
+ /* skip "[\0" name, it's surely not it */
+ if (ENABLE_TEST && LONE_CHAR(p, '['))
+ i++, p += 2;
+ /* All remaining applet names in p[] are at least 2 chars long */
+ /* name[] is also at least 2 chars long */
+
+ n32 = (name[0] << 0) | (name[1] << 8) | (name[2] << 16);
+ while (i < max) {
+ uint32_t p32;
+ char ch;
+
+ /* Quickly check match of the first 3 bytes */
+ move_from_unaligned32(p32, p);
+ p += 3;
+ if ((p32 & 0x00ffffff) != n32) {
+ /* Most likely case: 3 first bytes do not match */
+ i++;
+ if ((p32 & 0x00ff0000) == '\0')
+ continue; // p[2] was NUL
+ p++;
+ if ((p32 & 0xff000000) == '\0')
+ continue; // p[3] was NUL
+ /* p[0..3] aren't matching and none is NUL, check the rest */
+ while (*p++ != '\0')
+ continue;
+ continue;
+ }
+
+ /* Unlikely branch: first 3 bytes ([0..2]) match */
+ if ((p32 & 0x00ff0000) == '\0') {
+ /* name is 2-byte long, it is full match */
+ //bb_error_msg("found:'%s' i:%u", name, i);
return i;
- p += strlen(p) + 1;
+ }
+ /* Check remaining bytes [3..NUL] */
+ ch = (p32 >> 24);
+ j = 3;
+ while (ch == name[j]) {
+ if (ch == '\0') {
+ //bb_error_msg("found:'%s' i:%u", name, i);
+ return i;
+ }
+ ch = *++p;
+ j++;
+ }
+ /* Not a match. Skip it, including NUL */
+ while (ch != '\0')
+ ch = *++p;
+ p++;
+ i++;
+ }
+ return -1;
+#else
+ while (i < max) {
+ char ch;
+ j = 0;
+ /* Do we see "name\0" in applet_names[p] position? */
+ while ((ch = *p) == name[j]) {
+ if (ch == '\0') {
+ //bb_error_msg("found:'%s' i:%u", name, i);
+ return i; /* yes */
+ }
+ p++;
+ j++;
+ }
+ /* No.
+ * p => 1st non-matching char in applet_names[],
+ * skip to and including NUL.
+ */
+ while (ch != '\0')
+ ch = *++p;
+ p++;
i++;
}
return -1;
@@ -183,8 +280,7 @@ void lbb_prepare(const char *applet
#endif
applet_name = applet;
- /* Set locale for everybody except 'init' */
- if (ENABLE_LOCALE_SUPPORT && getpid() != 1)
+ if (ENABLE_LOCALE_SUPPORT)
setlocale(LC_ALL, "");
#if ENABLE_FEATURE_INDIVIDUAL
@@ -193,7 +289,7 @@ void lbb_prepare(const char *applet
if (argv[1]
&& !argv[2]
&& strcmp(argv[1], "--help") == 0
- && strncmp(applet, "busybox", 7) != 0
+ && !is_prefixed_with(applet, "busybox")
) {
/* Special case. POSIX says "test --help"
* should be no different from e.g. "test --foo". */
@@ -437,7 +533,7 @@ static void parse_config_file(void)
goto pe_label;
}
*e = ':'; /* get_uidgid needs USER:GROUP syntax */
- if (get_uidgid(&sct->m_ugid, s, /*allow_numeric:*/ 1) == 0) {
+ if (get_uidgid(&sct->m_ugid, s) == 0) {
errmsg = "unknown user/group";
goto pe_label;
}
@@ -457,7 +553,6 @@ static void parse_config_file(void)
errmsg = "keyword outside section";
goto pe_label;
}
-
} /* while (1) */
pe_label:
@@ -584,6 +679,7 @@ static void install_links(const char *busybox, int use_symbolic_links,
* busybox.h::bb_install_loc_t, or else... */
int (*lf)(const char *, const char *);
char *fpc;
+ const char *appname = applet_names;
unsigned i;
int rc;
@@ -594,7 +690,7 @@ static void install_links(const char *busybox, int use_symbolic_links,
for (i = 0; i < ARRAY_SIZE(applet_main); i++) {
fpc = concat_path_file(
custom_install_dir ? custom_install_dir : install_dir[APPLET_INSTALL_LOC(i)],
- APPLET_NAME(i));
+ appname);
// debug: bb_error_msg("%slinking %s to busybox",
// use_symbolic_links ? "sym" : "", fpc);
rc = lf(busybox, fpc);
@@ -602,12 +698,19 @@ static void install_links(const char *busybox, int use_symbolic_links,
bb_simple_perror_msg(fpc);
}
free(fpc);
+ while (*appname++ != '\0')
+ continue;
}
}
-# else
-# define install_links(x,y,z) ((void)0)
+# elif ENABLE_BUSYBOX
+static void install_links(const char *busybox UNUSED_PARAM,
+ int use_symbolic_links UNUSED_PARAM,
+ char *custom_install_dir UNUSED_PARAM)
+{
+}
# endif
+# if ENABLE_BUSYBOX
/* If we were called as "busybox..." */
static int busybox_main(char **argv)
{
@@ -620,28 +723,37 @@ static int busybox_main(char **argv)
output_width = 80;
if (ENABLE_FEATURE_AUTOWIDTH) {
/* Obtain the terminal width */
- get_terminal_width_height(0, &output_width, NULL);
+ output_width = get_terminal_width(2);
}
dup2(1, 2);
full_write2_str(bb_banner); /* reuse const string */
full_write2_str(" multi-call binary.\n"); /* reuse */
full_write2_str(
- "Copyright (C) 1998-2011 Erik Andersen, Rob Landley, Denys Vlasenko\n"
- "and others. Licensed under GPLv2.\n"
- "See source distribution for full notice.\n"
+ "BusyBox is copyrighted by many authors between 1998-2015.\n"
+ "Licensed under GPLv2. See source distribution for detailed\n"
+ "copyright notices.\n"
"\n"
- "Usage: busybox [function] [arguments]...\n"
+ "Usage: busybox [function [arguments]...]\n"
" or: busybox --list"IF_FEATURE_INSTALLER("[-full]")"\n"
IF_FEATURE_INSTALLER(
" or: busybox --install [-s] [DIR]\n"
)
" or: function [arguments]...\n"
"\n"
+ IF_NOT_FEATURE_SH_STANDALONE(
"\tBusyBox is a multi-call binary that combines many common Unix\n"
"\tutilities into a single executable. Most people will create a\n"
"\tlink to busybox for each function they wish to use and BusyBox\n"
"\twill act like whatever it was invoked as.\n"
+ )
+ IF_FEATURE_SH_STANDALONE(
+ "\tBusyBox is a multi-call binary that combines many common Unix\n"
+ "\tutilities into a single executable. The shell in this build\n"
+ "\tis configured to run built-in utilities without $PATH search.\n"
+ "\tYou don't need to install a link to busybox for each utility.\n"
+ "\tTo run external program, use full path (/sbin/ip instead of ip).\n"
+ )
"\n"
"Currently defined functions:\n"
);
@@ -669,19 +781,20 @@ static int busybox_main(char **argv)
return 0;
}
- if (strncmp(argv[1], "--list", 6) == 0) {
+ if (is_prefixed_with(argv[1], "--list")) {
unsigned i = 0;
const char *a = applet_names;
dup2(1, 2);
while (*a) {
-# if ENABLE_FEATURE_INSTALLER
+# if ENABLE_FEATURE_INSTALLER
if (argv[1][6]) /* --list-full? */
full_write2_str(install_dir[APPLET_INSTALL_LOC(i)] + 1);
-# endif
+# endif
full_write2_str(a);
full_write2_str("\n");
i++;
- a += strlen(a) + 1;
+ while (*a++ != '\0')
+ continue;
}
return 0;
}
@@ -725,12 +838,8 @@ static int busybox_main(char **argv)
* "#!/bin/busybox"-style wrappers */
applet_name = bb_get_last_path_component_nostrip(argv[0]);
run_applet_and_exit(applet_name, argv);
-
- /*bb_error_msg_and_die("applet not found"); - sucks in printf */
- full_write2_str(applet_name);
- full_write2_str(": applet not found\n");
- xfunc_die();
}
+# endif
void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv)
{
@@ -741,27 +850,53 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv)
/* Reinit some shared global data */
xfunc_error_retval = EXIT_FAILURE;
+ applet_name = bb_get_last_path_component_nostrip(argv[0]);
- applet_name = APPLET_NAME(applet_no);
- if (argc == 2 && strcmp(argv[1], "--help") == 0) {
- /* Special case. POSIX says "test --help"
- * should be no different from e.g. "test --foo". */
-//TODO: just compare applet_no with APPLET_NO_test
- if (!ENABLE_TEST || strcmp(applet_name, "test") != 0)
+ /* Special case. POSIX says "test --help"
+ * should be no different from e.g. "test --foo".
+ * Thus for "test", we skip --help check.
+ * "true" and "false" are also special.
+ */
+ if (1
+#if defined APPLET_NO_test
+ && applet_no != APPLET_NO_test
+#endif
+#if defined APPLET_NO_true
+ && applet_no != APPLET_NO_true
+#endif
+#if defined APPLET_NO_false
+ && applet_no != APPLET_NO_false
+#endif
+ ) {
+ if (argc == 2 && strcmp(argv[1], "--help") == 0) {
+ /* Make "foo --help" exit with 0: */
+ xfunc_error_retval = 0;
bb_show_usage();
+ }
}
if (ENABLE_FEATURE_SUID)
check_suid(applet_no);
exit(applet_main[applet_no](argc, argv));
}
-void FAST_FUNC run_applet_and_exit(const char *name, char **argv)
+static NORETURN void run_applet_and_exit(const char *name, char **argv)
{
- int applet = find_applet_by_name(name);
+ int applet;
+
+# if ENABLE_BUSYBOX
+ if (is_prefixed_with(name, "busybox"))
+ exit(busybox_main(argv));
+# endif
+ /* find_applet_by_name() search is more expensive, so goes second */
+ applet = find_applet_by_name(name);
if (applet >= 0)
run_applet_no_and_exit(applet, argv);
- if (strncmp(name, "busybox", 7) == 0)
- exit(busybox_main(argv));
+
+ /*bb_error_msg_and_die("applet not found"); - links in printf */
+ full_write2_str(applet_name);
+ full_write2_str(": applet not found\n");
+ /* POSIX: "If a command is not found, the exit status shall be 127" */
+ exit(127);
}
#endif /* !defined(SINGLE_APPLET_MAIN) */
@@ -774,6 +909,19 @@ int lbb_main(char **argv)
int main(int argc UNUSED_PARAM, char **argv)
#endif
{
+#if 0
+ /* TODO: find a use for a block of memory between end of .bss
+ * and end of page. For example, I'm getting "_end:0x812e698 2408 bytes"
+ * - more than 2k of wasted memory (in this particular build)
+ * *per each running process*!
+ * (If your linker does not generate "_end" name, weak attribute
+ * makes &_end == NULL, end_len == 0 here.)
+ */
+ extern char _end[] __attribute__((weak));
+ unsigned end_len = (-(int)_end) & 0xfff;
+ printf("_end:%p %u bytes\n", &_end, end_len);
+#endif
+
/* Tweak malloc for reduced memory consumption */
#ifdef M_TRIM_THRESHOLD
/* M_TRIM_THRESHOLD is the maximum amount of freed top-most memory
@@ -799,7 +947,7 @@ int main(int argc UNUSED_PARAM, char **argv)
#if defined(SINGLE_APPLET_MAIN)
/* Only one applet is selected in .config */
- if (argv[1] && strncmp(argv[0], "busybox", 7) == 0) {
+ if (argv[1] && is_prefixed_with(argv[0], "busybox")) {
/* "busybox <applet> <params>" should still work as expected */
argv++;
}
@@ -809,6 +957,10 @@ int main(int argc UNUSED_PARAM, char **argv)
#else
lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv));
+#if !ENABLE_BUSYBOX
+ if (argv[1] && is_prefixed_with(bb_basename(argv[0]), "busybox"))
+ argv++;
+#endif
applet_name = argv[0];
if (applet_name[0] == '-')
applet_name++;
@@ -817,10 +969,5 @@ int main(int argc UNUSED_PARAM, char **argv)
parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */
run_applet_and_exit(applet_name, argv);
-
- /*bb_error_msg_and_die("applet not found"); - sucks in printf */
- full_write2_str(applet_name);
- full_write2_str(": applet not found\n");
- xfunc_die();
#endif
}
diff --git a/release/src/router/busybox/libbb/auto_string.c b/release/src/router/busybox/libbb/auto_string.c
new file mode 100644
index 0000000000..ae940069a2
--- /dev/null
+++ b/release/src/router/busybox/libbb/auto_string.c
@@ -0,0 +1,23 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 2015 Denys Vlasenko
+ *
+ * Licensed under GPLv2, see file LICENSE in this source tree.
+ */
+//kbuild:lib-y += auto_string.o
+
+#include "libbb.h"
+
+char* FAST_FUNC auto_string(char *str)
+{
+ static char *saved[4];
+ static uint8_t cur_saved; /* = 0 */
+
+ free(saved[cur_saved]);
+ saved[cur_saved] = str;
+ cur_saved = (cur_saved + 1) & (ARRAY_SIZE(saved)-1);
+
+ return str;
+}
diff --git a/release/src/router/busybox/libbb/bb_askpass.c b/release/src/router/busybox/libbb/bb_askpass.c
index fe2b50677f..c2580b9ebe 100644
--- a/release/src/router/busybox/libbb/bb_askpass.c
+++ b/release/src/router/busybox/libbb/bb_askpass.c
@@ -1,7 +1,6 @@
/* vi: set sw=4 ts=4: */
/*
* Ask for a password
- * I use a static buffer in this function. Plan accordingly.
*
* Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
*
@@ -23,16 +22,19 @@ char* FAST_FUNC bb_ask(const int fd, int timeout, const char *prompt)
{
/* Was static char[BIGNUM] */
enum { sizeof_passwd = 128 };
- static char *passwd;
+ char *passwd;
char *ret;
int i;
struct sigaction sa, oldsa;
struct termios tio, oldtio;
+ tcflush(fd, TCIFLUSH);
+ /* Was buggy: was printing prompt *before* flushing input,
+ * which was upsetting "expect" based scripts of some users.
+ */
fputs(prompt, stdout);
fflush_all();
- tcflush(fd, TCIFLUSH);
tcgetattr(fd, &oldtio);
tio = oldtio;
@@ -59,13 +61,14 @@ char* FAST_FUNC bb_ask(const int fd, int timeout, const char *prompt)
alarm(timeout);
}
- if (!passwd)
- passwd = xmalloc(sizeof_passwd);
+ passwd = auto_string(xmalloc(sizeof_passwd));
ret = passwd;
i = 0;
while (1) {
int r = read(fd, &ret[i], 1);
- if (r < 0) {
+ if ((i == 0 && r == 0) /* EOF (^D) with no password */
+ || r < 0
+ ) {
/* read is interrupted by timeout or ^C */
ret = NULL;
break;
diff --git a/release/src/router/busybox/libbb/bb_strtonum.c b/release/src/router/busybox/libbb/bb_strtonum.c
index 62699643f2..949f26bee6 100644
--- a/release/src/router/busybox/libbb/bb_strtonum.c
+++ b/release/src/router/busybox/libbb/bb_strtonum.c
@@ -56,16 +56,13 @@ unsigned long long FAST_FUNC bb_strtoull(const char *arg, char **endp, int base)
{
unsigned long long v;
char *endptr;
- char first;
if (!endp) endp = &endptr;
*endp = (char*) arg;
/* strtoul(" -4200000000") returns 94967296, errno 0 (!) */
/* I don't think that this is right. Preventing this... */
- //if (!isalnum(arg[0])) return ret_ERANGE();
- first = (arg[0] != '-' ? arg[0] : arg[1]);
- if (!isalnum(first)) return ret_ERANGE();
+ if (!isalnum(arg[0])) return ret_ERANGE();
/* not 100% correct for lib func, but convenient for the caller */
errno = 0;
@@ -98,14 +95,11 @@ unsigned long FAST_FUNC bb_strtoul(const char *arg, char **endp, int base)
{
unsigned long v;
char *endptr;
- char first;
if (!endp) endp = &endptr;
*endp = (char*) arg;
- first = (arg[0] != '-' ? arg[0] : arg[1]);
- if (!isalnum(first)) return ret_ERANGE();
-
+ if (!isalnum(arg[0])) return ret_ERANGE();
errno = 0;
v = strtoul(arg, endp, base);
return handle_errors(v, endp);
@@ -134,14 +128,11 @@ unsigned FAST_FUNC bb_strtou(const char *arg, char **endp, int base)
{
unsigned long v;
char *endptr;
- char first;
if (!endp) endp = &endptr;
*endp = (char*) arg;
- first = (arg[0] != '-' ? arg[0] : arg[1]);
- if (!isalnum(first)) return ret_ERANGE();
-
+ if (!isalnum(arg[0])) return ret_ERANGE();
errno = 0;
v = strtoul(arg, endp, base);
if (v > UINT_MAX) return ret_ERANGE();
diff --git a/release/src/router/busybox/libbb/bbunit.c b/release/src/router/busybox/libbb/bbunit.c
new file mode 100644
index 0000000000..db67b10810
--- /dev/null
+++ b/release/src/router/busybox/libbb/bbunit.c
@@ -0,0 +1,65 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * bbunit: Simple unit-testing framework for Busybox.
+ *
+ * Copyright (C) 2014 by Bartosz Golaszewski <bartekgola@gmail.com>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+//kbuild:lib-$(CONFIG_UNIT_TEST) += bbunit.o
+//applet:IF_UNIT_TEST(APPLET(unit, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//usage:#define unit_trivial_usage
+//usage: ""
+//usage:#define unit_full_usage "\n\n"
+//usage: "Run the unit-test suite"
+
+#include "libbb.h"
+
+static llist_t *tests = NULL;
+static unsigned tests_registered = 0;
+static int test_retval;
+
+void bbunit_registertest(struct bbunit_listelem *test)
+{
+ llist_add_to_end(&tests, test);
+ tests_registered++;
+}
+
+void bbunit_settestfailed(void)
+{
+ test_retval = -1;
+}
+
+int unit_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) MAIN_EXTERNALLY_VISIBLE;
+int unit_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
+{
+ unsigned tests_run = 0;
+ unsigned tests_failed = 0;
+
+ bb_error_msg("Running %d test(s)...", tests_registered);
+ for (;;) {
+ struct bbunit_listelem* el = llist_pop(&tests);
+ if (!el)
+ break;
+
+ bb_error_msg("Case: [%s]", el->name);
+ test_retval = 0;
+ el->testfunc();
+
+ if (test_retval < 0) {
+ bb_error_msg("[ERROR] [%s]: TEST FAILED", el->name);
+ tests_failed++;
+ }
+ tests_run++;
+ }
+
+ if (tests_failed > 0) {
+ bb_error_msg("[ERROR] %u test(s) FAILED", tests_failed);
+ return EXIT_FAILURE;
+ }
+
+ bb_error_msg("All tests passed");
+ return EXIT_SUCCESS;
+}
diff --git a/release/src/router/busybox/libbb/change_identity.c b/release/src/router/busybox/libbb/change_identity.c
index 619db09a85..d48d863264 100644
--- a/release/src/router/busybox/libbb/change_identity.c
+++ b/release/src/router/busybox/libbb/change_identity.c
@@ -33,9 +33,28 @@
/* Become the user and group(s) specified by PW. */
void FAST_FUNC change_identity(const struct passwd *pw)
{
- if (initgroups(pw->pw_name, pw->pw_gid) == -1)
- bb_perror_msg_and_die("can't set groups");
+ int res;
+
+ res = initgroups(pw->pw_name, pw->pw_gid);
endgrent(); /* helps to close a fd used internally by libc */
+
+ if (res != 0) {
+ /*
+ * If initgroups() fails because a system call is unimplemented
+ * then we are running on a Linux kernel compiled without multiuser
+ * support (CONFIG_MULTIUSER is not defined).
+ *
+ * If we are running without multiuser support *and* the target uid
+ * already matches the current uid then we can skip the change of
+ * identity.
+ */
+ if (errno == ENOSYS && pw->pw_uid == getuid()) {
+ return;
+ }
+
+ bb_perror_msg_and_die("can't set groups");
+ }
+
xsetgid(pw->pw_gid);
xsetuid(pw->pw_uid);
}
diff --git a/release/src/router/busybox/libbb/common_bufsiz.c b/release/src/router/busybox/libbb/common_bufsiz.c
new file mode 100644
index 0000000000..1a35851691
--- /dev/null
+++ b/release/src/router/busybox/libbb/common_bufsiz.c
@@ -0,0 +1,74 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 2016 Denys Vlasenko
+ *
+ * Licensed under GPLv2, see file LICENSE in this source tree.
+ */
+//config:config FEATURE_USE_BSS_TAIL
+//config: bool "Use the end of BSS page"
+//config: default n
+//config: help
+//config: Attempt to reclaim a small unused part of BSS.
+//config:
+//config: Executables have the following parts:
+//config: = read-only executable code and constants, also known as "text"
+//config: = read-write data
+//config: = non-initialized (zeroed on demand) data, also known as "bss"
+//config:
+//config: At link time, "text" is padded to a full page. At runtime, all "text"
+//config: pages are mapped RO and executable.
+//config: "Data" starts on the next page boundary, but is not padded
+//config: to a full page at the end. "Bss" starts wherever "data" ends.
+//config: At runtime, "data" pages are mapped RW and they are file-backed
+//config: (this includes a small portion of "bss" which may live in the last
+//config: partial page of "data").
+//config: Pages which are fully in "bss" are mapped to anonymous memory.
+//config:
+//config: "Bss" end is usually not page-aligned. There is an unused space
+//config: in the last page. Linker marks its start with the "_end" symbol.
+//config:
+//config: This option will attempt to use that space for bb_common_bufsiz1[]
+//config: array. If it fits after _end, it will be used, and COMMON_BUFSIZE
+//config: will be enlarged from its guaranteed minimum size of 1 kbyte.
+//config: This may require recompilation a second time, since value of _end
+//config: is known only after final link.
+//config:
+//config: If you are getting a build error like this:
+//config: appletlib.c:(.text.main+0xd): undefined reference to '_end'
+//config: disable this option.
+
+//kbuild:lib-y += common_bufsiz.o
+
+#include "libbb.h"
+#include "common_bufsiz.h"
+
+#if !ENABLE_FEATURE_USE_BSS_TAIL
+
+/* We use it for "global" data via *(struct global*)bb_common_bufsiz1.
+ * Since gcc insists on aligning struct global's members, it would be a pity
+ * (and an alignment fault on some CPUs) to mess it up. */
+char bb_common_bufsiz1[COMMON_BUFSIZE] ALIGNED(sizeof(long long));
+
+#else
+
+# ifndef setup_common_bufsiz
+/*
+ * It is not defined as a dummy macro.
+ * It means we have to provide this function.
+ */
+char *const bb_common_bufsiz1 __attribute__ ((section (".data")));
+void setup_common_bufsiz(void)
+{
+ if (!bb_common_bufsiz1)
+ *(char**)&bb_common_bufsiz1 = xzalloc(COMMON_BUFSIZE);
+}
+# else
+# ifndef bb_common_bufsiz1
+ /* bb_common_bufsiz1[] is not aliased to _end[] */
+char bb_common_bufsiz1[COMMON_BUFSIZE] ALIGNED(sizeof(long long));
+# endif
+# endif
+
+#endif
diff --git a/release/src/router/busybox/libbb/compare_string_array.c b/release/src/router/busybox/libbb/compare_string_array.c
index 4b10cc138a..2f51237a33 100644
--- a/release/src/router/busybox/libbb/compare_string_array.c
+++ b/release/src/router/busybox/libbb/compare_string_array.c
@@ -5,6 +5,49 @@
#include "libbb.h"
+/*
+ * Return NULL if string is not prefixed with key. Return pointer to the
+ * first character in string after the prefix key. If key is an empty string,
+ * return pointer to the beginning of string.
+ */
+char* FAST_FUNC is_prefixed_with(const char *string, const char *key)
+{
+#if 0 /* Two passes over key - probably slower */
+ int len = strlen(key);
+ if (strncmp(string, key, len) == 0)
+ return string + len;
+ return NULL;
+#else /* Open-coded */
+ while (*key != '\0') {
+ if (*key != *string)
+ return NULL;
+ key++;
+ string++;
+ }
+ return (char*)string;
+#endif
+}
+
+/*
+ * Return NULL if string is not suffixed with key. Return pointer to the
+ * beginning of prefix key in string. If key is an empty string return pointer
+ * to the end of string.
+ */
+char* FAST_FUNC is_suffixed_with(const char *string, const char *key)
+{
+ size_t key_len = strlen(key);
+ ssize_t len_diff = strlen(string) - key_len;
+
+ if (len_diff >= 0) {
+ string += len_diff;
+ if (strcmp(string, key) == 0) {
+ return (char*)string;
+ }
+ }
+
+ return NULL;
+}
+
/* returns the array index of the string */
/* (index of first match is returned, or -1) */
int FAST_FUNC index_in_str_array(const char *const string_array[], const char *key)
@@ -39,10 +82,9 @@ int FAST_FUNC index_in_strings(const char *strings, const char *key)
int FAST_FUNC index_in_substr_array(const char *const string_array[], const char *key)
{
int i;
- int len = strlen(key);
- if (len) {
+ if (key[0]) {
for (i = 0; string_array[i] != 0; i++) {
- if (strncmp(string_array[i], key, len) == 0) {
+ if (is_prefixed_with(string_array[i], key)) {
return i;
}
}
@@ -93,3 +135,37 @@ smallint FAST_FUNC yesno(const char *str)
return ret / 3;
}
#endif
+
+#if ENABLE_UNIT_TEST
+
+BBUNIT_DEFINE_TEST(is_prefixed_with)
+{
+ BBUNIT_ASSERT_STREQ(" bar", is_prefixed_with("foo bar", "foo"));
+ BBUNIT_ASSERT_STREQ("bar", is_prefixed_with("foo bar", "foo "));
+ BBUNIT_ASSERT_STREQ("", is_prefixed_with("foo", "foo"));
+ BBUNIT_ASSERT_STREQ("foo", is_prefixed_with("foo", ""));
+ BBUNIT_ASSERT_STREQ("", is_prefixed_with("", ""));
+
+ BBUNIT_ASSERT_NULL(is_prefixed_with("foo", "bar foo"));
+ BBUNIT_ASSERT_NULL(is_prefixed_with("foo foo", "bar"));
+ BBUNIT_ASSERT_NULL(is_prefixed_with("", "foo"));
+
+ BBUNIT_ENDTEST;
+}
+
+BBUNIT_DEFINE_TEST(is_suffixed_with)
+{
+ BBUNIT_ASSERT_STREQ("bar", is_suffixed_with("foo bar", "bar"));
+ BBUNIT_ASSERT_STREQ("foo", is_suffixed_with("foo", "foo"));
+ BBUNIT_ASSERT_STREQ("", is_suffixed_with("foo", ""));
+ BBUNIT_ASSERT_STREQ("", is_suffixed_with("", ""));
+ BBUNIT_ASSERT_STREQ("foo", is_suffixed_with("barfoofoo", "foo"));
+
+ BBUNIT_ASSERT_NULL(is_suffixed_with("foo", "bar foo"));
+ BBUNIT_ASSERT_NULL(is_suffixed_with("foo foo", "bar"));
+ BBUNIT_ASSERT_NULL(is_suffixed_with("", "foo"));
+
+ BBUNIT_ENDTEST;
+}
+
+#endif /* ENABLE_UNIT_TEST */
diff --git a/release/src/router/busybox/libbb/copy_file.c b/release/src/router/busybox/libbb/copy_file.c
index 9333a8d499..23bcf2e828 100644
--- a/release/src/router/busybox/libbb/copy_file.c
+++ b/release/src/router/busybox/libbb/copy_file.c
@@ -64,6 +64,11 @@ static int ask_and_unlink(const char *dest, int flags)
bb_perror_msg("can't create '%s'", dest);
return -1; /* error */
}
+#if ENABLE_FEATURE_CP_LONG_OPTIONS
+ if (flags & FILEUTILS_RMDEST)
+ if (flags & FILEUTILS_VERBOSE)
+ printf("removed '%s'\n", dest);
+#endif
return 1; /* ok (to try again) */
}
@@ -210,6 +215,22 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
goto preserve_mode_ugid_time;
}
+ if (dest_exists) {
+ if (flags & FILEUTILS_UPDATE) {
+ if (source_stat.st_mtime <= dest_stat.st_mtime) {
+ return 0; /* source file must be newer */
+ }
+ }
+#if ENABLE_FEATURE_CP_LONG_OPTIONS
+ if (flags & FILEUTILS_RMDEST) {
+ ovr = ask_and_unlink(dest, flags);
+ if (ovr <= 0)
+ return ovr;
+ dest_exists = 0;
+ }
+#endif
+ }
+
if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) {
int (*lf)(const char *oldpath, const char *newpath);
make_links:
@@ -389,5 +410,9 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
bb_perror_msg("can't preserve %s of '%s'", "permissions", dest);
}
+ if (flags & FILEUTILS_VERBOSE) {
+ printf("'%s' -> '%s'\n", source, dest);
+ }
+
return retval;
}
diff --git a/release/src/router/busybox/libbb/copyfd.c b/release/src/router/busybox/libbb/copyfd.c
index eda2747f99..7e35319037 100644
--- a/release/src/router/busybox/libbb/copyfd.c
+++ b/release/src/router/busybox/libbb/copyfd.c
@@ -8,6 +8,20 @@
*/
#include "libbb.h"
+#if ENABLE_FEATURE_USE_SENDFILE
+# include <sys/sendfile.h>
+#else
+# define sendfile(a,b,c,d) (-1)
+#endif
+
+/*
+ * We were using 0x7fff0000 as sendfile chunk size, but it
+ * was seen to cause largish delays when user tries to ^C a file copy.
+ * Let's use a saner size.
+ * Note: needs to be >= max(CONFIG_FEATURE_COPYBUF_KB),
+ * or else "copy to eof" code will use neddlesly short reads.
+ */
+#define SENDFILE_BIGBUF (16*1024*1024)
/* Used by NOFORK applets (e.g. cat) - must not use xmalloc.
* size < 0 means "ignore write errors", used by tar --to-command
@@ -18,12 +32,13 @@ static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size)
int status = -1;
off_t total = 0;
bool continue_on_write_error = 0;
-#if CONFIG_FEATURE_COPYBUF_KB <= 4
+ ssize_t sendfile_sz;
+#if CONFIG_FEATURE_COPYBUF_KB > 4
+ char *buffer = buffer; /* for compiler */
+ int buffer_size = 0;
+#else
char buffer[CONFIG_FEATURE_COPYBUF_KB * 1024];
enum { buffer_size = sizeof(buffer) };
-#else
- char *buffer;
- int buffer_size;
#endif
if (size < 0) {
@@ -31,46 +46,58 @@ static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size)
continue_on_write_error = 1;
}
-#if CONFIG_FEATURE_COPYBUF_KB > 4
- if (size > 0 && size <= 4 * 1024)
- goto use_small_buf;
- /* We want page-aligned buffer, just in case kernel is clever
- * and can do page-aligned io more efficiently */
- buffer = mmap(NULL, CONFIG_FEATURE_COPYBUF_KB * 1024,
- PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANON,
- /* ignored: */ -1, 0);
- buffer_size = CONFIG_FEATURE_COPYBUF_KB * 1024;
- if (buffer == MAP_FAILED) {
- use_small_buf:
- buffer = alloca(4 * 1024);
- buffer_size = 4 * 1024;
- }
-#endif
-
if (src_fd < 0)
goto out;
+ sendfile_sz = !ENABLE_FEATURE_USE_SENDFILE
+ ? 0
+ : SENDFILE_BIGBUF;
if (!size) {
- size = buffer_size;
+ size = SENDFILE_BIGBUF;
status = 1; /* copy until eof */
}
while (1) {
ssize_t rd;
- rd = safe_read(src_fd, buffer, size > buffer_size ? buffer_size : size);
-
- if (!rd) { /* eof - all done */
- status = 0;
- break;
+ if (sendfile_sz) {
+ rd = sendfile(dst_fd, src_fd, NULL,
+ size > sendfile_sz ? sendfile_sz : size);
+ if (rd >= 0)
+ goto read_ok;
+ sendfile_sz = 0; /* do not try sendfile anymore */
+ }
+#if CONFIG_FEATURE_COPYBUF_KB > 4
+ if (buffer_size == 0) {
+ if (size > 0 && size <= 4 * 1024)
+ goto use_small_buf;
+ /* We want page-aligned buffer, just in case kernel is clever
+ * and can do page-aligned io more efficiently */
+ buffer = mmap(NULL, CONFIG_FEATURE_COPYBUF_KB * 1024,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON,
+ /* ignored: */ -1, 0);
+ buffer_size = CONFIG_FEATURE_COPYBUF_KB * 1024;
+ if (buffer == MAP_FAILED) {
+ use_small_buf:
+ buffer = alloca(4 * 1024);
+ buffer_size = 4 * 1024;
+ }
}
+#endif
+ rd = safe_read(src_fd, buffer,
+ size > buffer_size ? buffer_size : size);
if (rd < 0) {
bb_perror_msg(bb_msg_read_error);
break;
}
+ read_ok:
+ if (!rd) { /* eof - all done */
+ status = 0;
+ break;
+ }
/* dst_fd == -1 is a fake, else... */
- if (dst_fd >= 0) {
+ if (dst_fd >= 0 && !sendfile_sz) {
ssize_t wr = full_write(dst_fd, buffer, rd);
if (wr < rd) {
if (!continue_on_write_error) {
@@ -92,10 +119,8 @@ static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size)
}
out:
-#if CONFIG_FEATURE_COPYBUF_KB > 4
- if (buffer_size != 4 * 1024)
+ if (buffer_size > 4 * 1024)
munmap(buffer, buffer_size);
-#endif
return status ? -1 : total;
}
diff --git a/release/src/router/busybox/libbb/correct_password.c b/release/src/router/busybox/libbb/correct_password.c
index 6301589e6a..513c930286 100644
--- a/release/src/router/busybox/libbb/correct_password.c
+++ b/release/src/router/busybox/libbb/correct_password.c
@@ -30,51 +30,95 @@
#include "libbb.h"
-/* Ask the user for a password.
- * Return 1 if the user gives the correct password for entry PW,
- * 0 if not. Return 1 without asking if PW has an empty password.
- *
- * NULL pw means "just fake it for login with bad username" */
+#define SHADOW_BUFSIZE 256
-int FAST_FUNC correct_password(const struct passwd *pw)
-{
- char *unencrypted, *encrypted;
- const char *correct;
- int r;
-#if ENABLE_FEATURE_SHADOWPASSWDS
- /* Using _r function to avoid pulling in static buffers */
- struct spwd spw;
- char buffer[256];
+/* Retrieve encrypted password string for pw.
+ * If pw == NULL, return a string which fails password check against any
+ * password.
+ */
+#if !ENABLE_FEATURE_SHADOWPASSWDS
+#define get_passwd(pw, buffer) get_passwd(pw)
#endif
+static const char *get_passwd(const struct passwd *pw, char buffer[SHADOW_BUFSIZE])
+{
+ const char *pass;
- /* fake salt. crypt() can choke otherwise. */
- correct = "aa";
- if (!pw) {
- /* "aa" will never match */
- goto fake_it;
- }
- correct = pw->pw_passwd;
+ if (!pw)
+ return "aa"; /* "aa" will never match */
+
+ pass = pw->pw_passwd;
#if ENABLE_FEATURE_SHADOWPASSWDS
- if ((correct[0] == 'x' || correct[0] == '*') && !correct[1]) {
+ /* Using _r function to avoid pulling in static buffers */
+ if ((pass[0] == 'x' || pass[0] == '*') && !pass[1]) {
+ struct spwd spw;
+ int r;
/* getspnam_r may return 0 yet set result to NULL.
* At least glibc 2.4 does this. Be extra paranoid here. */
struct spwd *result = NULL;
- r = getspnam_r(pw->pw_name, &spw, buffer, sizeof(buffer), &result);
- correct = (r || !result) ? "aa" : result->sp_pwdp;
+ r = getspnam_r(pw->pw_name, &spw, buffer, SHADOW_BUFSIZE, &result);
+ pass = (r || !result) ? "aa" : result->sp_pwdp;
}
#endif
+ return pass;
+}
- if (!correct[0]) /* empty password field? */
- return 1;
+/*
+ * Return 1 if PW has an empty password.
+ * Return 1 if the user gives the correct password for entry PW,
+ * 0 if not.
+ * NULL pw means "just fake it for login with bad username"
+ */
+int FAST_FUNC check_password(const struct passwd *pw, const char *plaintext)
+{
+ IF_FEATURE_SHADOWPASSWDS(char buffer[SHADOW_BUFSIZE];)
+ char *encrypted;
+ const char *pw_pass;
+ int r;
- fake_it:
- unencrypted = bb_ask_stdin("Password: ");
- if (!unencrypted) {
- return 0;
+ pw_pass = get_passwd(pw, buffer);
+ if (!pw_pass[0]) { /* empty password field? */
+ return 1;
}
- encrypted = pw_encrypt(unencrypted, correct, 1);
- r = (strcmp(encrypted, correct) == 0);
+
+ encrypted = pw_encrypt(plaintext, /*salt:*/ pw_pass, 1);
+ r = (strcmp(encrypted, pw_pass) == 0);
free(encrypted);
- memset(unencrypted, 0, strlen(unencrypted));
return r;
}
+
+
+/* Ask the user for a password.
+ * Return 1 without asking if PW has an empty password.
+ * Return -1 on EOF, error while reading input, or timeout.
+ * Return 1 if the user gives the correct password for entry PW,
+ * 0 if not.
+ *
+ * NULL pw means "just fake it for login with bad username"
+ */
+int FAST_FUNC ask_and_check_password_extended(const struct passwd *pw,
+ int timeout, const char *prompt)
+{
+ IF_FEATURE_SHADOWPASSWDS(char buffer[SHADOW_BUFSIZE];)
+ char *plaintext;
+ const char *pw_pass;
+ int r;
+
+ pw_pass = get_passwd(pw, buffer);
+ if (!pw_pass[0]) /* empty password field? */
+ return 1;
+
+ plaintext = bb_ask(STDIN_FILENO, timeout, prompt);
+ if (!plaintext) {
+ /* EOF (such as ^D) or error (such as ^C) or timeout */
+ return -1;
+ }
+
+ r = check_password(pw, plaintext);
+ nuke_str(plaintext);
+ return r;
+}
+
+int FAST_FUNC ask_and_check_password(const struct passwd *pw)
+{
+ return ask_and_check_password_extended(pw, 0, "Password: ");
+}
diff --git a/release/src/router/busybox/libbb/create_icmp6_socket.c b/release/src/router/busybox/libbb/create_icmp6_socket.c
deleted file mode 100644
index 368c690283..0000000000
--- a/release/src/router/busybox/libbb/create_icmp6_socket.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * Utility routines.
- *
- * create raw socket for icmp (IPv6 version) protocol
- * and drop root privileges if running setuid
- *
- * Licensed under GPLv2, see file LICENSE in this source tree.
- */
-
-#include "libbb.h"
-
-#if ENABLE_FEATURE_IPV6
-int FAST_FUNC create_icmp6_socket(void)
-{
- int sock;
-#if 0
- struct protoent *proto;
- proto = getprotobyname("ipv6-icmp");
- /* if getprotobyname failed, just silently force
- * proto->p_proto to have the correct value for "ipv6-icmp" */
- sock = socket(AF_INET6, SOCK_RAW,
- (proto ? proto->p_proto : IPPROTO_ICMPV6));
-#else
- sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
-#endif
- if (sock < 0) {
- if (errno == EPERM)
- bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
- bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket);
- }
-
- /* drop root privs if running setuid */
- xsetuid(getuid());
-
- return sock;
-}
-#endif
diff --git a/release/src/router/busybox/libbb/create_icmp_socket.c b/release/src/router/busybox/libbb/create_icmp_socket.c
deleted file mode 100644
index 5856269835..0000000000
--- a/release/src/router/busybox/libbb/create_icmp_socket.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * Utility routines.
- *
- * create raw socket for icmp protocol
- * and drop root privileges if running setuid
- *
- * Licensed under GPLv2, see file LICENSE in this source tree.
- */
-
-#include "libbb.h"
-
-int FAST_FUNC create_icmp_socket(void)
-{
- int sock;
-#if 0
- struct protoent *proto;
- proto = getprotobyname("icmp");
- /* if getprotobyname failed, just silently force
- * proto->p_proto to have the correct value for "icmp" */
- sock = socket(AF_INET, SOCK_RAW,
- (proto ? proto->p_proto : 1)); /* 1 == ICMP */
-#else
- sock = socket(AF_INET, SOCK_RAW, 1); /* 1 == ICMP */
-#endif
- if (sock < 0) {
- if (errno == EPERM)
- bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
- bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket);
- }
-
- /* drop root privs if running setuid */
- xsetuid(getuid());
-
- return sock;
-}
diff --git a/release/src/router/busybox/libbb/dump.c b/release/src/router/busybox/libbb/dump.c
index 7e435643bd..566881a781 100644
--- a/release/src/router/busybox/libbb/dump.c
+++ b/release/src/router/busybox/libbb/dump.c
@@ -333,7 +333,7 @@ static void do_skip(priv_dumper_t *dumper, const char *fname, int statok)
return;
}
}
- if (fseek(stdin, dumper->pub.dump_skip, SEEK_SET)) {
+ if (fseeko(stdin, dumper->pub.dump_skip, SEEK_SET)) {
bb_simple_perror_msg_and_die(fname);
}
dumper->address += dumper->pub.dump_skip;
diff --git a/release/src/router/busybox/libbb/endofname.c b/release/src/router/busybox/libbb/endofname.c
new file mode 100644
index 0000000000..305f0932b1
--- /dev/null
+++ b/release/src/router/busybox/libbb/endofname.c
@@ -0,0 +1,26 @@
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 2013 Denys Vlasenko
+ *
+ * Licensed under GPLv2, see file LICENSE in this source tree.
+ */
+
+//kbuild:lib-y += endofname.o
+
+#include "libbb.h"
+
+#define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
+#define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
+
+const char* FAST_FUNC
+endofname(const char *name)
+{
+ if (!is_name(*name))
+ return name;
+ while (*++name) {
+ if (!is_in_name(*name))
+ break;
+ }
+ return name;
+}
diff --git a/release/src/router/busybox/libbb/execable.c b/release/src/router/busybox/libbb/executable.c
index 178a00a5f1..05e70312f0 100644
--- a/release/src/router/busybox/libbb/execable.c
+++ b/release/src/router/busybox/libbb/executable.c
@@ -13,7 +13,7 @@
* return 1 if found;
* return 0 otherwise;
*/
-int FAST_FUNC execable_file(const char *name)
+int FAST_FUNC file_is_executable(const char *name)
{
struct stat s;
return (!access(name, X_OK) && !stat(name, &s) && S_ISREG(s.st_mode));
@@ -23,13 +23,21 @@ int FAST_FUNC execable_file(const char *name)
* return allocated string containing full path if found;
* PATHp points to the component after the one where it was found
* (or NULL),
- * you may call find_execable again with this PATHp to continue
+ * you may call find_executable again with this PATHp to continue
* (if it's not NULL).
* return NULL otherwise; (PATHp is undefined)
* in all cases (*PATHp) contents will be trashed (s/:/NUL/).
*/
-char* FAST_FUNC find_execable(const char *filename, char **PATHp)
+char* FAST_FUNC find_executable(const char *filename, char **PATHp)
{
+ /* About empty components in $PATH:
+ * http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html
+ * 8.3 Other Environment Variables - PATH
+ * A zero-length prefix is a legacy feature that indicates the current
+ * working directory. It appears as two adjacent colons ( "::" ), as an
+ * initial colon preceding the rest of the list, or as a trailing colon
+ * following the rest of the list.
+ */
char *p, *n;
p = *PATHp;
@@ -37,14 +45,15 @@ char* FAST_FUNC find_execable(const char *filename, char **PATHp)
n = strchr(p, ':');
if (n)
*n++ = '\0';
- if (*p != '\0') { /* it's not a PATH="foo::bar" situation */
- p = concat_path_file(p, filename);
- if (execable_file(p)) {
- *PATHp = n;
- return p;
- }
- free(p);
+ p = concat_path_file(
+ p[0] ? p : ".", /* handle "::" case */
+ filename
+ );
+ if (file_is_executable(p)) {
+ *PATHp = n;
+ return p;
}
+ free(p);
p = n;
} /* on loop exit p == NULL */
return p;
@@ -54,17 +63,14 @@ char* FAST_FUNC find_execable(const char *filename, char **PATHp)
* return 1 if found;
* return 0 otherwise;
*/
-int FAST_FUNC exists_execable(const char *filename)
+int FAST_FUNC executable_exists(const char *filename)
{
char *path = xstrdup(getenv("PATH"));
char *tmp = path;
- char *ret = find_execable(filename, &tmp);
+ char *ret = find_executable(filename, &tmp);
free(path);
- if (ret) {
- free(ret);
- return 1;
- }
- return 0;
+ free(ret);
+ return ret != NULL;
}
#if ENABLE_FEATURE_PREFER_APPLETS
@@ -77,10 +83,19 @@ int FAST_FUNC BB_EXECVP(const char *file, char *const argv[])
}
#endif
-int FAST_FUNC BB_EXECVP_or_die(char **argv)
+void FAST_FUNC BB_EXECVP_or_die(char **argv)
{
BB_EXECVP(argv[0], argv);
/* SUSv3-mandated exit codes */
xfunc_error_retval = (errno == ENOENT) ? 127 : 126;
bb_perror_msg_and_die("can't execute '%s'", argv[0]);
}
+
+/* Typical idiom for applets which exec *optional* PROG [ARGS] */
+void FAST_FUNC exec_prog_or_SHELL(char **argv)
+{
+ if (argv[0]) {
+ BB_EXECVP_or_die(argv);
+ }
+ run_shell(getenv("SHELL"), /*login:*/ 1, NULL, NULL);
+}
diff --git a/release/src/router/busybox/libbb/fclose_nonstdin.c b/release/src/router/busybox/libbb/fclose_nonstdin.c
index 5ce9d5b486..1b14413474 100644
--- a/release/src/router/busybox/libbb/fclose_nonstdin.c
+++ b/release/src/router/busybox/libbb/fclose_nonstdin.c
@@ -18,7 +18,8 @@ int FAST_FUNC fclose_if_not_stdin(FILE *f)
{
/* Some more paranoid applets want ferror() check too */
int r = ferror(f); /* NB: does NOT set errno! */
- if (r) errno = EIO; /* so we'll help it */
+ if (r)
+ errno = EIO; /* so we'll help it */
if (f != stdin)
return (r | fclose(f)); /* fclose does set errno on error */
return r;
diff --git a/release/src/router/busybox/libbb/fflush_stdout_and_exit.c b/release/src/router/busybox/libbb/fflush_stdout_and_exit.c
index 9ad5dbf968..b4bed865f0 100644
--- a/release/src/router/busybox/libbb/fflush_stdout_and_exit.c
+++ b/release/src/router/busybox/libbb/fflush_stdout_and_exit.c
@@ -15,15 +15,10 @@
void FAST_FUNC fflush_stdout_and_exit(int retval)
{
+ xfunc_error_retval = retval;
if (fflush(stdout))
bb_perror_msg_and_die(bb_msg_standard_output);
-
- if (ENABLE_FEATURE_PREFER_APPLETS && die_sleep < 0) {
- /* We are in NOFORK applet. Do not exit() directly,
- * but use xfunc_die() */
- xfunc_error_retval = retval;
- xfunc_die();
- }
-
- exit(retval);
+ /* In case we are in NOFORK applet. Do not exit() directly,
+ * but use xfunc_die() */
+ xfunc_die();
}
diff --git a/release/src/router/busybox/libbb/get_shell_name.c b/release/src/router/busybox/libbb/get_shell_name.c
index c930afd94e..5aebe9cdcc 100644
--- a/release/src/router/busybox/libbb/get_shell_name.c
+++ b/release/src/router/busybox/libbb/get_shell_name.c
@@ -8,7 +8,7 @@
#include "libbb.h"
-const char *get_shell_name(void)
+const char* FAST_FUNC get_shell_name(void)
{
struct passwd *pw;
char *shell;
diff --git a/release/src/router/busybox/libbb/getpty.c b/release/src/router/busybox/libbb/getpty.c
index 435e4d09f3..391d729f22 100644
--- a/release/src/router/busybox/libbb/getpty.c
+++ b/release/src/router/busybox/libbb/getpty.c
@@ -16,7 +16,7 @@ int FAST_FUNC xgetpty(char *line)
#if ENABLE_FEATURE_DEVPTS
p = open("/dev/ptmx", O_RDWR);
- if (p > 0) {
+ if (p >= 0) {
grantpt(p); /* chmod+chown corresponding slave pty */
unlockpt(p); /* (what does this do?) */
# ifndef HAVE_PTSNAME_R
diff --git a/release/src/router/busybox/libbb/hash_md5.c b/release/src/router/busybox/libbb/hash_md5.c
new file mode 100644
index 0000000000..1ce2b08566
--- /dev/null
+++ b/release/src/router/busybox/libbb/hash_md5.c
@@ -0,0 +1,12 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 2010 Denys Vlasenko
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+#define MD5_ONLY 3
+
+#include "hash_md5_sha.c"
diff --git a/release/src/router/busybox/libbb/hash_md5_sha.c b/release/src/router/busybox/libbb/hash_md5_sha.c
index a313c2a65c..bc6deb5057 100644
--- a/release/src/router/busybox/libbb/hash_md5_sha.c
+++ b/release/src/router/busybox/libbb/hash_md5_sha.c
@@ -31,6 +31,11 @@ static ALWAYS_INLINE uint64_t rotr64(uint64_t x, unsigned n)
return (x >> n) | (x << (64 - n));
}
+/* rotl64 only used for sha3 currently */
+static ALWAYS_INLINE uint64_t rotl64(uint64_t x, unsigned n)
+{
+ return (x << n) | (x >> (64 - n));
+}
/* Feed data through a temporary buffer.
* The internal buffer remembers previous data until it has 64
@@ -51,7 +56,7 @@ static void FAST_FUNC common64_hash(md5_ctx_t *ctx, const void *buffer, size_t l
len -= remaining;
buffer = (const char *)buffer + remaining;
bufpos += remaining;
- /* clever way to do "if (bufpos != 64) break; ... ; bufpos = 0;" */
+ /* Clever way to do "if (bufpos != N) break; ... ; bufpos = 0;" */
bufpos -= 64;
if (bufpos != 0)
break;
@@ -79,7 +84,7 @@ static void FAST_FUNC common64_end(md5_ctx_t *ctx, int swap_needed)
if (swap_needed)
t = bb_bswap_64(t);
/* wbuffer is suitably aligned for this */
- *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t;
+ *(bb__aliased_uint64_t *) (&ctx->wbuffer[64 - 8]) = t;
}
ctx->process_block(ctx);
if (remaining >= 8)
@@ -104,7 +109,9 @@ static void FAST_FUNC common64_end(md5_ctx_t *ctx, int swap_needed)
*/
/* 0: fastest, 3: smallest */
-#if CONFIG_MD5_SMALL < 0
+#ifdef MD5_ONLY
+# define MD5_SMALL MD5_ONLY
+#elif CONFIG_MD5_SMALL < 0
# define MD5_SMALL 0
#elif CONFIG_MD5_SMALL > 3
# define MD5_SMALL 3
@@ -132,7 +139,7 @@ static void FAST_FUNC md5_process_block64(md5_ctx_t *ctx)
#if MD5_SMALL > 0
/* Before we start, one word to the strange constants.
They are defined in RFC 1321 as
- T[i] = (int)(4294967296.0 * fabs(sin(i))), i=1..64
+ T[i] = (int)(2^32 * fabs(sin(i))), i=1..64
*/
static const uint32_t C_array[] = {
/* round 1 */
@@ -185,10 +192,9 @@ static void FAST_FUNC md5_process_block64(md5_ctx_t *ctx)
int i;
uint32_t temp;
-# if BB_BIG_ENDIAN
- for (i = 0; i < 16; i++)
- words[i] = SWAP_LE32(words[i]);
-# endif
+ if (BB_BIG_ENDIAN)
+ for (i = 0; i < 16; i++)
+ words[i] = SWAP_LE32(words[i]);
# if MD5_SMALL == 3
pc = C_array;
@@ -209,7 +215,7 @@ static void FAST_FUNC md5_process_block64(md5_ctx_t *ctx)
case 2:
temp += FH(B, C, D);
break;
- case 3:
+ default: /* case 3 */
temp += FI(B, C, D);
}
temp += words[(int) (*pp++)] + *pc++;
@@ -273,10 +279,6 @@ static void FAST_FUNC md5_process_block64(md5_ctx_t *ctx)
#else /* MD5_SMALL == 0 or 1 */
- uint32_t A_save = A;
- uint32_t B_save = B;
- uint32_t C_save = C;
- uint32_t D_save = D;
# if MD5_SMALL == 1
const uint32_t *pc;
const char *pp;
@@ -421,10 +423,10 @@ static void FAST_FUNC md5_process_block64(md5_ctx_t *ctx)
# undef OP
# endif
/* Add checksum to the starting values */
- ctx->hash[0] = A_save + A;
- ctx->hash[1] = B_save + B;
- ctx->hash[2] = C_save + C;
- ctx->hash[3] = D_save + D;
+ ctx->hash[0] += A;
+ ctx->hash[1] += B;
+ ctx->hash[2] += C;
+ ctx->hash[3] += D;
#endif
}
#undef FF
@@ -462,16 +464,18 @@ void FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf)
common64_end(ctx, /*swap_needed:*/ BB_BIG_ENDIAN);
/* The MD5 result is in little endian byte order */
-#if BB_BIG_ENDIAN
- ctx->hash[0] = SWAP_LE32(ctx->hash[0]);
- ctx->hash[1] = SWAP_LE32(ctx->hash[1]);
- ctx->hash[2] = SWAP_LE32(ctx->hash[2]);
- ctx->hash[3] = SWAP_LE32(ctx->hash[3]);
-#endif
+ if (BB_BIG_ENDIAN) {
+ ctx->hash[0] = SWAP_LE32(ctx->hash[0]);
+ ctx->hash[1] = SWAP_LE32(ctx->hash[1]);
+ ctx->hash[2] = SWAP_LE32(ctx->hash[2]);
+ ctx->hash[3] = SWAP_LE32(ctx->hash[3]);
+ }
+
memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * 4);
}
+#ifndef MD5_ONLY
/*
* SHA1 part is:
* Copyright 2007 Rob Landley <rob@landley.net>
@@ -834,7 +838,7 @@ void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len)
len -= remaining;
buffer = (const char *)buffer + remaining;
bufpos += remaining;
- /* clever way to do "if (bufpos != 128) break; ... ; bufpos = 0;" */
+ /* Clever way to do "if (bufpos != N) break; ... ; bufpos = 0;" */
bufpos -= 128;
if (bufpos != 0)
break;
@@ -878,10 +882,10 @@ void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf)
uint64_t t;
t = ctx->total64[0] << 3;
t = SWAP_BE64(t);
- *(uint64_t *) (&ctx->wbuffer[128 - 8]) = t;
+ *(bb__aliased_uint64_t *) (&ctx->wbuffer[128 - 8]) = t;
t = (ctx->total64[1] << 3) | (ctx->total64[0] >> 61);
t = SWAP_BE64(t);
- *(uint64_t *) (&ctx->wbuffer[128 - 16]) = t;
+ *(bb__aliased_uint64_t *) (&ctx->wbuffer[128 - 16]) = t;
}
sha512_process_block128(ctx);
if (remaining >= 16)
@@ -896,3 +900,548 @@ void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf)
}
memcpy(resbuf, ctx->hash, sizeof(ctx->hash));
}
+
+
+/*
+ * The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
+ * Michael Peeters and Gilles Van Assche. For more information, feedback or
+ * questions, please refer to our website: http://keccak.noekeon.org/
+ *
+ * Implementation by Ronny Van Keer,
+ * hereby denoted as "the implementer".
+ *
+ * To the extent possible under law, the implementer has waived all copyright
+ * and related or neighboring rights to the source code in this file.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Busybox modifications (C) Lauri Kasanen, under the GPLv2.
+ */
+
+#if CONFIG_SHA3_SMALL < 0
+# define SHA3_SMALL 0
+#elif CONFIG_SHA3_SMALL > 1
+# define SHA3_SMALL 1
+#else
+# define SHA3_SMALL CONFIG_SHA3_SMALL
+#endif
+
+#define OPTIMIZE_SHA3_FOR_32 0
+/*
+ * SHA3 can be optimized for 32-bit CPUs with bit-slicing:
+ * every 64-bit word of state[] can be split into two 32-bit words
+ * by even/odd bits. In this form, all rotations of sha3 round
+ * are 32-bit - and there are lots of them.
+ * However, it requires either splitting/combining state words
+ * before/after sha3 round (code does this now)
+ * or shuffling bits before xor'ing them into state and in sha3_end.
+ * Without shuffling, bit-slicing results in -130 bytes of code
+ * and marginal speedup (but of course it gives wrong result).
+ * With shuffling it works, but +260 code bytes, and slower.
+ * Disabled for now:
+ */
+#if 0 /* LONG_MAX == 0x7fffffff */
+# undef OPTIMIZE_SHA3_FOR_32
+# define OPTIMIZE_SHA3_FOR_32 1
+#endif
+
+enum {
+ SHA3_IBLK_BYTES = 72, /* 576 bits / 8 */
+};
+
+#if OPTIMIZE_SHA3_FOR_32
+/* This splits every 64-bit word into a pair of 32-bit words,
+ * even bits go into first word, odd bits go to second one.
+ * The conversion is done in-place.
+ */
+static void split_halves(uint64_t *state)
+{
+ /* Credit: Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
+ uint32_t *s32 = (uint32_t*)state;
+ uint32_t t, x0, x1;
+ int i;
+ for (i = 24; i >= 0; --i) {
+ x0 = s32[0];
+ t = (x0 ^ (x0 >> 1)) & 0x22222222; x0 = x0 ^ t ^ (t << 1);
+ t = (x0 ^ (x0 >> 2)) & 0x0C0C0C0C; x0 = x0 ^ t ^ (t << 2);
+ t = (x0 ^ (x0 >> 4)) & 0x00F000F0; x0 = x0 ^ t ^ (t << 4);
+ t = (x0 ^ (x0 >> 8)) & 0x0000FF00; x0 = x0 ^ t ^ (t << 8);
+ x1 = s32[1];
+ t = (x1 ^ (x1 >> 1)) & 0x22222222; x1 = x1 ^ t ^ (t << 1);
+ t = (x1 ^ (x1 >> 2)) & 0x0C0C0C0C; x1 = x1 ^ t ^ (t << 2);
+ t = (x1 ^ (x1 >> 4)) & 0x00F000F0; x1 = x1 ^ t ^ (t << 4);
+ t = (x1 ^ (x1 >> 8)) & 0x0000FF00; x1 = x1 ^ t ^ (t << 8);
+ *s32++ = (x0 & 0x0000FFFF) | (x1 << 16);
+ *s32++ = (x0 >> 16) | (x1 & 0xFFFF0000);
+ }
+}
+/* The reverse operation */
+static void combine_halves(uint64_t *state)
+{
+ uint32_t *s32 = (uint32_t*)state;
+ uint32_t t, x0, x1;
+ int i;
+ for (i = 24; i >= 0; --i) {
+ x0 = s32[0];
+ x1 = s32[1];
+ t = (x0 & 0x0000FFFF) | (x1 << 16);
+ x1 = (x0 >> 16) | (x1 & 0xFFFF0000);
+ x0 = t;
+ t = (x0 ^ (x0 >> 8)) & 0x0000FF00; x0 = x0 ^ t ^ (t << 8);
+ t = (x0 ^ (x0 >> 4)) & 0x00F000F0; x0 = x0 ^ t ^ (t << 4);
+ t = (x0 ^ (x0 >> 2)) & 0x0C0C0C0C; x0 = x0 ^ t ^ (t << 2);
+ t = (x0 ^ (x0 >> 1)) & 0x22222222; x0 = x0 ^ t ^ (t << 1);
+ *s32++ = x0;
+ t = (x1 ^ (x1 >> 8)) & 0x0000FF00; x1 = x1 ^ t ^ (t << 8);
+ t = (x1 ^ (x1 >> 4)) & 0x00F000F0; x1 = x1 ^ t ^ (t << 4);
+ t = (x1 ^ (x1 >> 2)) & 0x0C0C0C0C; x1 = x1 ^ t ^ (t << 2);
+ t = (x1 ^ (x1 >> 1)) & 0x22222222; x1 = x1 ^ t ^ (t << 1);
+ *s32++ = x1;
+ }
+}
+#endif
+
+/*
+ * In the crypto literature this function is usually called Keccak-f().
+ */
+static void sha3_process_block72(uint64_t *state)
+{
+ enum { NROUNDS = 24 };
+
+#if OPTIMIZE_SHA3_FOR_32
+ /*
+ static const uint32_t IOTA_CONST_0[NROUNDS] = {
+ 0x00000001UL,
+ 0x00000000UL,
+ 0x00000000UL,
+ 0x00000000UL,
+ 0x00000001UL,
+ 0x00000001UL,
+ 0x00000001UL,
+ 0x00000001UL,
+ 0x00000000UL,
+ 0x00000000UL,
+ 0x00000001UL,
+ 0x00000000UL,
+ 0x00000001UL,
+ 0x00000001UL,
+ 0x00000001UL,
+ 0x00000001UL,
+ 0x00000000UL,
+ 0x00000000UL,
+ 0x00000000UL,
+ 0x00000000UL,
+ 0x00000001UL,
+ 0x00000000UL,
+ 0x00000001UL,
+ 0x00000000UL,
+ };
+ ** bits are in lsb: 0101 0000 1111 0100 1111 0001
+ */
+ uint32_t IOTA_CONST_0bits = (uint32_t)(0x0050f4f1);
+ static const uint32_t IOTA_CONST_1[NROUNDS] = {
+ 0x00000000UL,
+ 0x00000089UL,
+ 0x8000008bUL,
+ 0x80008080UL,
+ 0x0000008bUL,
+ 0x00008000UL,
+ 0x80008088UL,
+ 0x80000082UL,
+ 0x0000000bUL,
+ 0x0000000aUL,
+ 0x00008082UL,
+ 0x00008003UL,
+ 0x0000808bUL,
+ 0x8000000bUL,
+ 0x8000008aUL,
+ 0x80000081UL,
+ 0x80000081UL,
+ 0x80000008UL,
+ 0x00000083UL,
+ 0x80008003UL,
+ 0x80008088UL,
+ 0x80000088UL,
+ 0x00008000UL,
+ 0x80008082UL,
+ };
+
+ uint32_t *const s32 = (uint32_t*)state;
+ unsigned round;
+
+ split_halves(state);
+
+ for (round = 0; round < NROUNDS; round++) {
+ unsigned x;
+
+ /* Theta */
+ {
+ uint32_t BC[20];
+ for (x = 0; x < 10; ++x) {
+ BC[x+10] = BC[x] = s32[x]^s32[x+10]^s32[x+20]^s32[x+30]^s32[x+40];
+ }
+ for (x = 0; x < 10; x += 2) {
+ uint32_t ta, tb;
+ ta = BC[x+8] ^ rotl32(BC[x+3], 1);
+ tb = BC[x+9] ^ BC[x+2];
+ s32[x+0] ^= ta;
+ s32[x+1] ^= tb;
+ s32[x+10] ^= ta;
+ s32[x+11] ^= tb;
+ s32[x+20] ^= ta;
+ s32[x+21] ^= tb;
+ s32[x+30] ^= ta;
+ s32[x+31] ^= tb;
+ s32[x+40] ^= ta;
+ s32[x+41] ^= tb;
+ }
+ }
+ /* RhoPi */
+ {
+ uint32_t t0a,t0b, t1a,t1b;
+ t1a = s32[1*2+0];
+ t1b = s32[1*2+1];
+
+#define RhoPi(PI_LANE, ROT_CONST) \
+ t0a = s32[PI_LANE*2+0];\
+ t0b = s32[PI_LANE*2+1];\
+ if (ROT_CONST & 1) {\
+ s32[PI_LANE*2+0] = rotl32(t1b, ROT_CONST/2+1);\
+ s32[PI_LANE*2+1] = ROT_CONST == 1 ? t1a : rotl32(t1a, ROT_CONST/2+0);\
+ } else {\
+ s32[PI_LANE*2+0] = rotl32(t1a, ROT_CONST/2);\
+ s32[PI_LANE*2+1] = rotl32(t1b, ROT_CONST/2);\
+ }\
+ t1a = t0a; t1b = t0b;
+
+ RhoPi(10, 1)
+ RhoPi( 7, 3)
+ RhoPi(11, 6)
+ RhoPi(17,10)
+ RhoPi(18,15)
+ RhoPi( 3,21)
+ RhoPi( 5,28)
+ RhoPi(16,36)
+ RhoPi( 8,45)
+ RhoPi(21,55)
+ RhoPi(24, 2)
+ RhoPi( 4,14)
+ RhoPi(15,27)
+ RhoPi(23,41)
+ RhoPi(19,56)
+ RhoPi(13, 8)
+ RhoPi(12,25)
+ RhoPi( 2,43)
+ RhoPi(20,62)
+ RhoPi(14,18)
+ RhoPi(22,39)
+ RhoPi( 9,61)
+ RhoPi( 6,20)
+ RhoPi( 1,44)
+#undef RhoPi
+ }
+ /* Chi */
+ for (x = 0; x <= 40;) {
+ uint32_t BC0, BC1, BC2, BC3, BC4;
+ BC0 = s32[x + 0*2];
+ BC1 = s32[x + 1*2];
+ BC2 = s32[x + 2*2];
+ s32[x + 0*2] = BC0 ^ ((~BC1) & BC2);
+ BC3 = s32[x + 3*2];
+ s32[x + 1*2] = BC1 ^ ((~BC2) & BC3);
+ BC4 = s32[x + 4*2];
+ s32[x + 2*2] = BC2 ^ ((~BC3) & BC4);
+ s32[x + 3*2] = BC3 ^ ((~BC4) & BC0);
+ s32[x + 4*2] = BC4 ^ ((~BC0) & BC1);
+ x++;
+ BC0 = s32[x + 0*2];
+ BC1 = s32[x + 1*2];
+ BC2 = s32[x + 2*2];
+ s32[x + 0*2] = BC0 ^ ((~BC1) & BC2);
+ BC3 = s32[x + 3*2];
+ s32[x + 1*2] = BC1 ^ ((~BC2) & BC3);
+ BC4 = s32[x + 4*2];
+ s32[x + 2*2] = BC2 ^ ((~BC3) & BC4);
+ s32[x + 3*2] = BC3 ^ ((~BC4) & BC0);
+ s32[x + 4*2] = BC4 ^ ((~BC0) & BC1);
+ x += 9;
+ }
+ /* Iota */
+ s32[0] ^= IOTA_CONST_0bits & 1;
+ IOTA_CONST_0bits >>= 1;
+ s32[1] ^= IOTA_CONST_1[round];
+ }
+
+ combine_halves(state);
+#else
+ /* Native 64-bit algorithm */
+ static const uint16_t IOTA_CONST[NROUNDS] = {
+ /* Elements should be 64-bit, but top half is always zero
+ * or 0x80000000. We encode 63rd bits in a separate word below.
+ * Same is true for 31th bits, which lets us use 16-bit table
+ * instead of 64-bit. The speed penalty is lost in the noise.
+ */
+ 0x0001,
+ 0x8082,
+ 0x808a,
+ 0x8000,
+ 0x808b,
+ 0x0001,
+ 0x8081,
+ 0x8009,
+ 0x008a,
+ 0x0088,
+ 0x8009,
+ 0x000a,
+ 0x808b,
+ 0x008b,
+ 0x8089,
+ 0x8003,
+ 0x8002,
+ 0x0080,
+ 0x800a,
+ 0x000a,
+ 0x8081,
+ 0x8080,
+ 0x0001,
+ 0x8008,
+ };
+ /* bit for CONST[0] is in msb: 0011 0011 0000 0111 1101 1101 */
+ const uint32_t IOTA_CONST_bit63 = (uint32_t)(0x3307dd00);
+ /* bit for CONST[0] is in msb: 0001 0110 0011 1000 0001 1011 */
+ const uint32_t IOTA_CONST_bit31 = (uint32_t)(0x16381b00);
+
+ static const uint8_t ROT_CONST[24] = {
+ 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
+ 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44,
+ };
+ static const uint8_t PI_LANE[24] = {
+ 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
+ 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1,
+ };
+ /*static const uint8_t MOD5[10] = { 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, };*/
+
+ unsigned x;
+ unsigned round;
+
+ if (BB_BIG_ENDIAN) {
+ for (x = 0; x < 25; x++) {
+ state[x] = SWAP_LE64(state[x]);
+ }
+ }
+
+ for (round = 0; round < NROUNDS; ++round) {
+ /* Theta */
+ {
+ uint64_t BC[10];
+ for (x = 0; x < 5; ++x) {
+ BC[x + 5] = BC[x] = state[x]
+ ^ state[x + 5] ^ state[x + 10]
+ ^ state[x + 15] ^ state[x + 20];
+ }
+ /* Using 2x5 vector above eliminates the need to use
+ * BC[MOD5[x+N]] trick below to fetch BC[(x+N) % 5],
+ * and the code is a bit _smaller_.
+ */
+ for (x = 0; x < 5; ++x) {
+ uint64_t temp = BC[x + 4] ^ rotl64(BC[x + 1], 1);
+ state[x] ^= temp;
+ state[x + 5] ^= temp;
+ state[x + 10] ^= temp;
+ state[x + 15] ^= temp;
+ state[x + 20] ^= temp;
+ }
+ }
+
+ /* Rho Pi */
+ if (SHA3_SMALL) {
+ uint64_t t1 = state[1];
+ for (x = 0; x < 24; ++x) {
+ uint64_t t0 = state[PI_LANE[x]];
+ state[PI_LANE[x]] = rotl64(t1, ROT_CONST[x]);
+ t1 = t0;
+ }
+ } else {
+ /* Especially large benefit for 32-bit arch (75% faster):
+ * 64-bit rotations by non-constant usually are SLOW on those.
+ * We resort to unrolling here.
+ * This optimizes out PI_LANE[] and ROT_CONST[],
+ * but generates 300-500 more bytes of code.
+ */
+ uint64_t t0;
+ uint64_t t1 = state[1];
+#define RhoPi_twice(x) \
+ t0 = state[PI_LANE[x ]]; \
+ state[PI_LANE[x ]] = rotl64(t1, ROT_CONST[x ]); \
+ t1 = state[PI_LANE[x+1]]; \
+ state[PI_LANE[x+1]] = rotl64(t0, ROT_CONST[x+1]);
+ RhoPi_twice(0); RhoPi_twice(2);
+ RhoPi_twice(4); RhoPi_twice(6);
+ RhoPi_twice(8); RhoPi_twice(10);
+ RhoPi_twice(12); RhoPi_twice(14);
+ RhoPi_twice(16); RhoPi_twice(18);
+ RhoPi_twice(20); RhoPi_twice(22);
+#undef RhoPi_twice
+ }
+ /* Chi */
+# if LONG_MAX > 0x7fffffff
+ for (x = 0; x <= 20; x += 5) {
+ uint64_t BC0, BC1, BC2, BC3, BC4;
+ BC0 = state[x + 0];
+ BC1 = state[x + 1];
+ BC2 = state[x + 2];
+ state[x + 0] = BC0 ^ ((~BC1) & BC2);
+ BC3 = state[x + 3];
+ state[x + 1] = BC1 ^ ((~BC2) & BC3);
+ BC4 = state[x + 4];
+ state[x + 2] = BC2 ^ ((~BC3) & BC4);
+ state[x + 3] = BC3 ^ ((~BC4) & BC0);
+ state[x + 4] = BC4 ^ ((~BC0) & BC1);
+ }
+# else
+ /* Reduced register pressure version
+ * for register-starved 32-bit arches
+ * (i386: -95 bytes, and it is _faster_)
+ */
+ for (x = 0; x <= 40;) {
+ uint32_t BC0, BC1, BC2, BC3, BC4;
+ uint32_t *const s32 = (uint32_t*)state;
+# if SHA3_SMALL
+ do_half:
+# endif
+ BC0 = s32[x + 0*2];
+ BC1 = s32[x + 1*2];
+ BC2 = s32[x + 2*2];
+ s32[x + 0*2] = BC0 ^ ((~BC1) & BC2);
+ BC3 = s32[x + 3*2];
+ s32[x + 1*2] = BC1 ^ ((~BC2) & BC3);
+ BC4 = s32[x + 4*2];
+ s32[x + 2*2] = BC2 ^ ((~BC3) & BC4);
+ s32[x + 3*2] = BC3 ^ ((~BC4) & BC0);
+ s32[x + 4*2] = BC4 ^ ((~BC0) & BC1);
+ x++;
+# if SHA3_SMALL
+ if (x & 1)
+ goto do_half;
+ x += 8;
+# else
+ BC0 = s32[x + 0*2];
+ BC1 = s32[x + 1*2];
+ BC2 = s32[x + 2*2];
+ s32[x + 0*2] = BC0 ^ ((~BC1) & BC2);
+ BC3 = s32[x + 3*2];
+ s32[x + 1*2] = BC1 ^ ((~BC2) & BC3);
+ BC4 = s32[x + 4*2];
+ s32[x + 2*2] = BC2 ^ ((~BC3) & BC4);
+ s32[x + 3*2] = BC3 ^ ((~BC4) & BC0);
+ s32[x + 4*2] = BC4 ^ ((~BC0) & BC1);
+ x += 9;
+# endif
+ }
+# endif /* long is 32-bit */
+ /* Iota */
+ state[0] ^= IOTA_CONST[round]
+ | (uint32_t)((IOTA_CONST_bit31 << round) & 0x80000000)
+ | (uint64_t)((IOTA_CONST_bit63 << round) & 0x80000000) << 32;
+ }
+
+ if (BB_BIG_ENDIAN) {
+ for (x = 0; x < 25; x++) {
+ state[x] = SWAP_LE64(state[x]);
+ }
+ }
+#endif
+}
+
+void FAST_FUNC sha3_begin(sha3_ctx_t *ctx)
+{
+ memset(ctx, 0, sizeof(*ctx));
+}
+
+void FAST_FUNC sha3_hash(sha3_ctx_t *ctx, const void *buffer, size_t len)
+{
+#if SHA3_SMALL
+ const uint8_t *data = buffer;
+ unsigned bufpos = ctx->bytes_queued;
+
+ while (1) {
+ unsigned remaining = SHA3_IBLK_BYTES - bufpos;
+ if (remaining > len)
+ remaining = len;
+ len -= remaining;
+ /* XOR data into buffer */
+ while (remaining != 0) {
+ uint8_t *buf = (uint8_t*)ctx->state;
+ buf[bufpos] ^= *data++;
+ bufpos++;
+ remaining--;
+ }
+ /* Clever way to do "if (bufpos != N) break; ... ; bufpos = 0;" */
+ bufpos -= SHA3_IBLK_BYTES;
+ if (bufpos != 0)
+ break;
+ /* Buffer is filled up, process it */
+ sha3_process_block72(ctx->state);
+ /*bufpos = 0; - already is */
+ }
+ ctx->bytes_queued = bufpos + SHA3_IBLK_BYTES;
+#else
+ /* +50 bytes code size, but a bit faster because of long-sized XORs */
+ const uint8_t *data = buffer;
+ unsigned bufpos = ctx->bytes_queued;
+
+ /* If already data in queue, continue queuing first */
+ while (len != 0 && bufpos != 0) {
+ uint8_t *buf = (uint8_t*)ctx->state;
+ buf[bufpos] ^= *data++;
+ len--;
+ bufpos++;
+ if (bufpos == SHA3_IBLK_BYTES) {
+ bufpos = 0;
+ goto do_block;
+ }
+ }
+
+ /* Absorb complete blocks */
+ while (len >= SHA3_IBLK_BYTES) {
+ /* XOR data onto beginning of state[].
+ * We try to be efficient - operate one word at a time, not byte.
+ * Careful wrt unaligned access: can't just use "*(long*)data"!
+ */
+ unsigned count = SHA3_IBLK_BYTES / sizeof(long);
+ long *buf = (long*)ctx->state;
+ do {
+ long v;
+ move_from_unaligned_long(v, (long*)data);
+ *buf++ ^= v;
+ data += sizeof(long);
+ } while (--count);
+ len -= SHA3_IBLK_BYTES;
+ do_block:
+ sha3_process_block72(ctx->state);
+ }
+
+ /* Queue remaining data bytes */
+ while (len != 0) {
+ uint8_t *buf = (uint8_t*)ctx->state;
+ buf[bufpos] ^= *data++;
+ bufpos++;
+ len--;
+ }
+
+ ctx->bytes_queued = bufpos;
+#endif
+}
+
+void FAST_FUNC sha3_end(sha3_ctx_t *ctx, void *resbuf)
+{
+ /* Padding */
+ uint8_t *buf = (uint8_t*)ctx->state;
+ buf[ctx->bytes_queued] ^= 1;
+ buf[SHA3_IBLK_BYTES - 1] ^= 0x80;
+
+ sha3_process_block72(ctx->state);
+
+ /* Output */
+ memcpy(resbuf, ctx->state, 64);
+}
+#endif
diff --git a/release/src/router/busybox/libbb/human_readable.c b/release/src/router/busybox/libbb/human_readable.c
index 8b22b0cb55..b4e0ef181a 100644
--- a/release/src/router/busybox/libbb/human_readable.c
+++ b/release/src/router/busybox/libbb/human_readable.c
@@ -14,16 +14,11 @@
* representations (say, powers of 1024) and manipulating coefficients.
* The base ten "bytes" output could be handled similarly.
*
- * 2) This routine always outputs a decimal point and a tenths digit when
- * display_unit != 0. Hence, it isn't uncommon for the returned string
+ * 2) This routine outputs a decimal point and a tenths digit when
+ * display_unit == 0. Hence, it isn't uncommon for the returned string
* to have a length of 5 or 6.
*
- * It might be nice to add a flag to indicate no decimal digits in
- * that case. This could be either an additional parameter, or a
- * special value of display_unit. Such a flag would also be nice for du.
- *
- * Some code to omit the decimal point and tenths digit is sketched out
- * and "#if 0"'d below.
+ * If block_size is also 0, no decimal digits are printed.
*
* Licensed under GPLv2, see file LICENSE in this source tree.
*/
@@ -37,8 +32,6 @@ const char* FAST_FUNC make_human_readable_str(unsigned long long val,
'\0', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'
};
- static char *str;
-
unsigned frac; /* 0..9 - the fractional digit */
const char *u;
const char *fmt;
@@ -81,12 +74,7 @@ const char* FAST_FUNC make_human_readable_str(unsigned long long val,
#endif
}
- if (!str) {
- /* sufficient for any width of val */
- str = xmalloc(sizeof(val)*3 + 2 + 3);
- }
- sprintf(str, fmt, val, frac, *u);
- return str;
+ return auto_string(xasprintf(fmt, val, frac, *u));
}
@@ -94,7 +82,7 @@ const char* FAST_FUNC make_human_readable_str(unsigned long long val,
/* Convert unsigned long long value into compact 5-char representation.
* String is not terminated (buf[5] is untouched) */
-void FAST_FUNC smart_ulltoa5(unsigned long long ul, char buf[5], const char *scale)
+char* FAST_FUNC smart_ulltoa5(unsigned long long ul, char buf[5], const char *scale)
{
const char *fmt;
char c;
@@ -145,12 +133,13 @@ void FAST_FUNC smart_ulltoa5(unsigned long long ul, char buf[5], const char *sca
buf[3] = "0123456789"[v];
buf[4] = scale[idx]; /* typically scale = " kmgt..." */
}
+ return buf + 5;
}
/* Convert unsigned long long value into compact 4-char
* representation. Examples: "1234", "1.2k", " 27M", "123T"
* String is not terminated (buf[4] is untouched) */
-void FAST_FUNC smart_ulltoa4(unsigned long long ul, char buf[4], const char *scale)
+char* FAST_FUNC smart_ulltoa4(unsigned long long ul, char buf[4], const char *scale)
{
const char *fmt;
char c;
@@ -194,4 +183,5 @@ void FAST_FUNC smart_ulltoa4(unsigned long long ul, char buf[4], const char *sca
buf[2] = "0123456789"[v];
buf[3] = scale[idx]; /* typically scale = " kmgt..." */
}
+ return buf + 4;
}
diff --git a/release/src/router/busybox/libbb/in_ether.c b/release/src/router/busybox/libbb/in_ether.c
new file mode 100644
index 0000000000..161c8ea3c1
--- /dev/null
+++ b/release/src/router/busybox/libbb/in_ether.c
@@ -0,0 +1,58 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ */
+
+//kbuild:lib-$(CONFIG_ARP) += in_ether.o
+//kbuild:lib-$(CONFIG_IFCONFIG) += in_ether.o
+//kbuild:lib-$(CONFIG_IFENSLAVE) += in_ether.o
+
+#include "libbb.h"
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+
+/* Convert Ethernet address from "XX[:]XX[:]XX[:]XX[:]XX[:]XX" to sockaddr.
+ * Return nonzero on error.
+ */
+int FAST_FUNC in_ether(const char *bufp, struct sockaddr *sap)
+{
+ char *ptr;
+ int i, j;
+ unsigned char val;
+ unsigned char c;
+
+ sap->sa_family = ARPHRD_ETHER;
+ ptr = (char *) sap->sa_data;
+
+ i = ETH_ALEN;
+ goto first;
+ do {
+ /* We might get a semicolon here */
+ if (*bufp == ':')
+ bufp++;
+ first:
+ j = val = 0;
+ do {
+ c = *bufp;
+ if (((unsigned char)(c - '0')) <= 9) {
+ c -= '0';
+ } else if ((unsigned char)((c|0x20) - 'a') <= 5) {
+ c = (unsigned char)((c|0x20) - 'a') + 10;
+ } else {
+ if (j && (c == ':' || c == '\0'))
+ /* One-digit byte: __:X:__ */
+ break;
+ return -1;
+ }
+ ++bufp;
+ val <<= 4;
+ val += c;
+ j ^= 1;
+ } while (j);
+
+ *ptr++ = val;
+ } while (--i);
+
+ /* Error if we aren't at end of string */
+ return *bufp;
+}
diff --git a/release/src/router/busybox/libbb/inet_common.c b/release/src/router/busybox/libbb/inet_common.c
index 7208db9ea9..5b4a4a10b7 100644
--- a/release/src/router/busybox/libbb/inet_common.c
+++ b/release/src/router/busybox/libbb/inet_common.c
@@ -32,14 +32,12 @@ int FAST_FUNC INET_resolve(const char *name, struct sockaddr_in *s_in, int hostf
return 0;
}
/* If we expect this to be a hostname, try hostname database first */
-#ifdef DEBUG
if (hostfirst) {
+#ifdef DEBUG
bb_error_msg("gethostbyname(%s)", name);
- }
#endif
- if (hostfirst) {
hp = gethostbyname(name);
- if (hp != NULL) {
+ if (hp) {
memcpy(&s_in->sin_addr, hp->h_addr_list[0],
sizeof(struct in_addr));
return 0;
@@ -51,7 +49,7 @@ int FAST_FUNC INET_resolve(const char *name, struct sockaddr_in *s_in, int hostf
bb_error_msg("getnetbyname(%s)", name);
#endif
np = getnetbyname(name);
- if (np != NULL) {
+ if (np) {
s_in->sin_addr.s_addr = htonl(np->n_net);
return 1;
}
@@ -66,7 +64,7 @@ int FAST_FUNC INET_resolve(const char *name, struct sockaddr_in *s_in, int hostf
bb_error_msg("gethostbyname(%s)", name);
#endif
hp = gethostbyname(name);
- if (hp == NULL) {
+ if (!hp) {
return -1;
}
memcpy(&s_in->sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
@@ -74,7 +72,7 @@ int FAST_FUNC INET_resolve(const char *name, struct sockaddr_in *s_in, int hostf
}
-/* numeric: & 0x8000: default instead of *,
+/* numeric: & 0x8000: "default" instead of "*",
* & 0x4000: host instead of net,
* & 0x0fff: don't resolve
*/
@@ -83,80 +81,76 @@ char* FAST_FUNC INET_rresolve(struct sockaddr_in *s_in, int numeric, uint32_t ne
/* addr-to-name cache */
struct addr {
struct addr *next;
- struct sockaddr_in addr;
- int host;
+ uint32_t nip;
+ smallint is_host;
char name[1];
};
static struct addr *cache = NULL;
struct addr *pn;
char *name;
- uint32_t ad, host_ad;
- int host = 0;
+ uint32_t nip;
+ smallint is_host;
if (s_in->sin_family != AF_INET) {
#ifdef DEBUG
bb_error_msg("rresolve: unsupported address family %d!",
- s_in->sin_family);
+ s_in->sin_family);
#endif
errno = EAFNOSUPPORT;
return NULL;
}
- ad = s_in->sin_addr.s_addr;
+ nip = s_in->sin_addr.s_addr;
#ifdef DEBUG
- bb_error_msg("rresolve: %08x, mask %08x, num %08x", (unsigned)ad, netmask, numeric);
+ bb_error_msg("rresolve: %08x mask:%08x num:%08x", (unsigned)nip, netmask, numeric);
#endif
- if (ad == INADDR_ANY) {
- if ((numeric & 0x0FFF) == 0) {
- if (numeric & 0x8000)
- return xstrdup("default");
- return xstrdup("*");
- }
- }
if (numeric & 0x0FFF)
- return xstrdup(inet_ntoa(s_in->sin_addr));
+ return xmalloc_sockaddr2dotted_noport((void*)s_in);
+ if (nip == INADDR_ANY) {
+ if (numeric & 0x8000)
+ return xstrdup("default");
+ return xstrdup("*");
+ }
+
+ is_host = ((nip & (~netmask)) != 0 || (numeric & 0x4000));
- if ((ad & (~netmask)) != 0 || (numeric & 0x4000))
- host = 1;
pn = cache;
while (pn) {
- if (pn->addr.sin_addr.s_addr == ad && pn->host == host) {
+ if (pn->nip == nip && pn->is_host == is_host) {
#ifdef DEBUG
bb_error_msg("rresolve: found %s %08x in cache",
- (host ? "host" : "net"), (unsigned)ad);
+ (is_host ? "host" : "net"), (unsigned)nip);
#endif
return xstrdup(pn->name);
}
pn = pn->next;
}
- host_ad = ntohl(ad);
name = NULL;
- if (host) {
- struct hostent *ent;
+ if (is_host) {
#ifdef DEBUG
- bb_error_msg("gethostbyaddr (%08x)", (unsigned)ad);
+ bb_error_msg("sockaddr2host_noport(%08x)", (unsigned)nip);
#endif
- ent = gethostbyaddr((char *) &ad, 4, AF_INET);
- if (ent)
- name = xstrdup(ent->h_name);
+ name = xmalloc_sockaddr2host_noport((void*)s_in);
} else if (ENABLE_FEATURE_ETC_NETWORKS) {
struct netent *np;
#ifdef DEBUG
- bb_error_msg("getnetbyaddr (%08x)", (unsigned)host_ad);
+ bb_error_msg("getnetbyaddr(%08x)", (unsigned)ntohl(nip));
#endif
- np = getnetbyaddr(host_ad, AF_INET);
+ np = getnetbyaddr(ntohl(nip), AF_INET);
if (np)
name = xstrdup(np->n_name);
}
if (!name)
- name = xstrdup(inet_ntoa(s_in->sin_addr));
+ name = xmalloc_sockaddr2dotted_noport((void*)s_in);
+
pn = xmalloc(sizeof(*pn) + strlen(name)); /* no '+ 1', it's already accounted for */
pn->next = cache;
- pn->addr = *s_in;
- pn->host = host;
+ pn->nip = nip;
+ pn->is_host = is_host;
strcpy(pn->name, name);
cache = pn;
+
return name;
}
@@ -175,8 +169,7 @@ int FAST_FUNC INET6_resolve(const char *name, struct sockaddr_in6 *sin6)
return -1;
}
memcpy(sin6, ai->ai_addr, sizeof(*sin6));
- if (ai)
- freeaddrinfo(ai);
+ freeaddrinfo(ai);
return 0;
}
@@ -189,20 +182,16 @@ int FAST_FUNC INET6_resolve(const char *name, struct sockaddr_in6 *sin6)
char* FAST_FUNC INET6_rresolve(struct sockaddr_in6 *sin6, int numeric)
{
- char name[128];
- int s;
-
if (sin6->sin6_family != AF_INET6) {
#ifdef DEBUG
bb_error_msg("rresolve: unsupported address family %d!",
- sin6->sin6_family);
+ sin6->sin6_family);
#endif
errno = EAFNOSUPPORT;
return NULL;
}
if (numeric & 0x7FFF) {
- inet_ntop(AF_INET6, &sin6->sin6_addr, name, sizeof(name));
- return xstrdup(name);
+ return xmalloc_sockaddr2dotted_noport((void*)sin6);
}
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
if (numeric & 0x8000)
@@ -210,15 +199,7 @@ char* FAST_FUNC INET6_rresolve(struct sockaddr_in6 *sin6, int numeric)
return xstrdup("*");
}
- s = getnameinfo((struct sockaddr *) sin6, sizeof(*sin6),
- name, sizeof(name),
- /*serv,servlen:*/ NULL, 0,
- 0);
- if (s != 0) {
- bb_error_msg("getnameinfo failed");
- return NULL;
- }
- return xstrdup(name);
+ return xmalloc_sockaddr2host_noport((void*)sin6);
}
#endif /* CONFIG_FEATURE_IPV6 */
diff --git a/release/src/router/busybox/libbb/info_msg.c b/release/src/router/busybox/libbb/info_msg.c
deleted file mode 100644
index 56ca2efd4d..0000000000
--- a/release/src/router/busybox/libbb/info_msg.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * Utility routines.
- *
- * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
- *
- * Licensed under GPLv2 or later, see file LICENSE in this source tree.
- */
-
-#include "libbb.h"
-#if ENABLE_FEATURE_SYSLOG
-# include <syslog.h>
-#endif
-
-void FAST_FUNC bb_info_msg(const char *s, ...)
-{
-#ifdef THIS_ONE_DOESNT_DO_SINGLE_WRITE
- va_list p;
- /* va_copy is used because it is not portable
- * to use va_list p twice */
- va_list p2;
-
- va_start(p, s);
- va_copy(p2, p);
- if (logmode & LOGMODE_STDIO) {
- vprintf(s, p);
- fputs(msg_eol, stdout);
- }
-# if ENABLE_FEATURE_SYSLOG
- if (logmode & LOGMODE_SYSLOG)
- vsyslog(LOG_INFO, s, p2);
-# endif
- va_end(p2);
- va_end(p);
-#else
- int used;
- char *msg;
- va_list p;
-
- if (logmode == 0)
- return;
-
- va_start(p, s);
- used = vasprintf(&msg, s, p);
- va_end(p);
- if (used < 0)
- return;
-
-# if ENABLE_FEATURE_SYSLOG
- if (logmode & LOGMODE_SYSLOG)
- syslog(LOG_INFO, "%s", msg);
-# endif
- if (logmode & LOGMODE_STDIO) {
- fflush_all();
- /* used = strlen(msg); - must be true already */
- msg[used++] = '\n';
- full_write(STDOUT_FILENO, msg, used);
- }
-
- free(msg);
-#endif
-}
diff --git a/release/src/router/busybox/libbb/inode_hash.c b/release/src/router/busybox/libbb/inode_hash.c
index 715535ef53..f11c2afb2e 100644
--- a/release/src/router/busybox/libbb/inode_hash.c
+++ b/release/src/router/busybox/libbb/inode_hash.c
@@ -11,14 +11,23 @@
#include "libbb.h"
typedef struct ino_dev_hash_bucket_struct {
- struct ino_dev_hash_bucket_struct *next;
ino_t ino;
dev_t dev;
+ /*
+ * Above fields can be 64-bit, while pointer may be 32-bit.
+ * Putting "next" field here may reduce size of this struct:
+ */
+ struct ino_dev_hash_bucket_struct *next;
+ /*
+ * Reportedly, on cramfs a file and a dir can have same ino.
+ * Need to also remember "file/dir" bit:
+ */
+ char isdir; /* bool */
char name[1];
} ino_dev_hashtable_bucket_t;
-#define HASH_SIZE 311 /* Should be prime */
-#define hash_inode(i) ((i) % HASH_SIZE)
+#define HASH_SIZE 311u /* Should be prime */
+#define hash_inode(i) ((unsigned)(i) % HASH_SIZE)
/* array of [HASH_SIZE] elements */
static ino_dev_hashtable_bucket_t **ino_dev_hashtable;
@@ -38,6 +47,7 @@ char* FAST_FUNC is_in_ino_dev_hashtable(const struct stat *statbuf)
while (bucket != NULL) {
if ((bucket->ino == statbuf->st_ino)
&& (bucket->dev == statbuf->st_dev)
+ && (bucket->isdir == !!S_ISDIR(statbuf->st_mode))
) {
return bucket->name;
}
@@ -52,17 +62,18 @@ void FAST_FUNC add_to_ino_dev_hashtable(const struct stat *statbuf, const char *
int i;
ino_dev_hashtable_bucket_t *bucket;
- i = hash_inode(statbuf->st_ino);
if (!name)
name = "";
bucket = xmalloc(sizeof(ino_dev_hashtable_bucket_t) + strlen(name));
bucket->ino = statbuf->st_ino;
bucket->dev = statbuf->st_dev;
+ bucket->isdir = !!S_ISDIR(statbuf->st_mode);
strcpy(bucket->name, name);
if (!ino_dev_hashtable)
ino_dev_hashtable = xzalloc(HASH_SIZE * sizeof(*ino_dev_hashtable));
+ i = hash_inode(statbuf->st_ino);
bucket->next = ino_dev_hashtable[i];
ino_dev_hashtable[i] = bucket;
}
@@ -72,13 +83,18 @@ void FAST_FUNC add_to_ino_dev_hashtable(const struct stat *statbuf, const char *
void FAST_FUNC reset_ino_dev_hashtable(void)
{
int i;
- ino_dev_hashtable_bucket_t *bucket;
+ ino_dev_hashtable_bucket_t *bucket, *next;
+
+ if (!ino_dev_hashtable)
+ return;
+
+ for (i = 0; i < HASH_SIZE; i++) {
+ bucket = ino_dev_hashtable[i];
- for (i = 0; ino_dev_hashtable && i < HASH_SIZE; i++) {
- while (ino_dev_hashtable[i] != NULL) {
- bucket = ino_dev_hashtable[i]->next;
- free(ino_dev_hashtable[i]);
- ino_dev_hashtable[i] = bucket;
+ while (bucket != NULL) {
+ next = bucket->next;
+ free(bucket);
+ bucket = next;
}
}
free(ino_dev_hashtable);
diff --git a/release/src/router/busybox/libbb/kernel_version.c b/release/src/router/busybox/libbb/kernel_version.c
index 738ed022b3..9b6c622991 100644
--- a/release/src/router/busybox/libbb/kernel_version.c
+++ b/release/src/router/busybox/libbb/kernel_version.c
@@ -20,16 +20,16 @@
int FAST_FUNC get_linux_version_code(void)
{
struct utsname name;
- char *s, *t;
+ char *t;
int i, r;
uname(&name); /* never fails */
- s = name.release;
+ t = name.release;
r = 0;
for (i = 0; i < 3; i++) {
- t = strtok(s, ".");
+ t = strtok(t, ".");
r = r * 256 + (t ? atoi(t) : 0);
- s = NULL;
+ t = NULL;
}
return r;
}
diff --git a/release/src/router/busybox/libbb/lineedit.c b/release/src/router/busybox/libbb/lineedit.c
index dbe616466d..3e62f46b4c 100644
--- a/release/src/router/busybox/libbb/lineedit.c
+++ b/release/src/router/busybox/libbb/lineedit.c
@@ -38,8 +38,17 @@
* and the \] escape to signal the end of such a sequence. Example:
*
* PS1='\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\] '
+ *
+ * Unicode in PS1 is not fully supported: prompt length calulation is wrong,
+ * resulting in line wrap problems with long (multi-line) input.
+ *
+ * Multi-line PS1 (e.g. PS1="\n[\w]\n$ ") has problems with history
+ * browsing: up/down arrows result in scrolling.
+ * It stems from simplistic "cmdedit_y = cmdedit_prmt_len / cmdedit_termw"
+ * calculation of how many lines the prompt takes.
*/
-#include "libbb.h"
+#include "busybox.h"
+#include "NUM_APPLETS.h"
#include "unicode.h"
#ifndef _POSIX_VDISABLE
# define _POSIX_VDISABLE '\0'
@@ -133,9 +142,6 @@ struct lineedit_statics {
CHAR_T *command_ps;
const char *cmdedit_prompt;
-#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
- int num_ok_lines; /* = 1; */
-#endif
#if ENABLE_USERNAME_OR_HOMEDIR
char *user_buf;
@@ -172,7 +178,6 @@ extern struct lineedit_statics *const lineedit_ptr_to_statics;
#define command_len (S.command_len )
#define command_ps (S.command_ps )
#define cmdedit_prompt (S.cmdedit_prompt )
-#define num_ok_lines (S.num_ok_lines )
#define user_buf (S.user_buf )
#define home_pwd_buf (S.home_pwd_buf )
#define matches (S.matches )
@@ -185,8 +190,8 @@ extern struct lineedit_statics *const lineedit_ptr_to_statics;
(*(struct lineedit_statics**)&lineedit_ptr_to_statics) = xzalloc(sizeof(S)); \
barrier(); \
cmdedit_termw = 80; \
- IF_FEATURE_EDITING_FANCY_PROMPT(num_ok_lines = 1;) \
IF_USERNAME_OR_HOMEDIR(home_pwd_buf = (char*)null_str;) \
+ IF_FEATURE_EDITING_VI(delptr = delbuf;) \
} while (0)
static void deinit_S(void)
@@ -668,23 +673,20 @@ static char *username_path_completion(char *ud)
*/
static NOINLINE unsigned complete_username(const char *ud)
{
- /* Using _r function to avoid pulling in static buffers */
- char line_buff[256];
- struct passwd pwd;
- struct passwd *result;
+ struct passwd *pw;
unsigned userlen;
ud++; /* skip ~ */
userlen = strlen(ud);
setpwent();
- while (!getpwent_r(&pwd, line_buff, sizeof(line_buff), &result)) {
+ while ((pw = getpwent()) != NULL) {
/* Null usernames should result in all users as possible completions. */
- if (/*!userlen || */ strncmp(ud, pwd.pw_name, userlen) == 0) {
- add_match(xasprintf("~%s/", pwd.pw_name));
+ if (/* !ud[0] || */ is_prefixed_with(pw->pw_name, ud)) {
+ add_match(xasprintf("~%s/", pw->pw_name));
}
}
- endpwent();
+ endpwent(); /* don't keep password file open */
return 1 + userlen;
}
@@ -773,6 +775,19 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
}
pf_len = strlen(pfind);
+#if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1
+ if (type == FIND_EXE_ONLY) {
+ const char *p = applet_names;
+
+ while (*p) {
+ if (strncmp(pfind, p, pf_len) == 0)
+ add_match(xstrdup(p));
+ while (*p++ != '\0')
+ continue;
+ }
+ }
+#endif
+
for (i = 0; i < npaths; i++) {
DIR *dir;
struct dirent *next;
@@ -791,7 +806,7 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
if (!pfind[0] && DOT_OR_DOTDOT(name_found))
continue;
/* match? */
- if (strncmp(name_found, pfind, pf_len) != 0)
+ if (!is_prefixed_with(name_found, pfind))
continue; /* no */
found = concat_path_file(paths[i], name_found);
@@ -1251,14 +1266,16 @@ line_input_t* FAST_FUNC new_line_input_t(int flags)
{
line_input_t *n = xzalloc(sizeof(*n));
n->flags = flags;
+#if MAX_HISTORY > 0
n->max_history = MAX_HISTORY;
+#endif
return n;
}
#if MAX_HISTORY > 0
-unsigned size_from_HISTFILESIZE(const char *hp)
+unsigned FAST_FUNC size_from_HISTFILESIZE(const char *hp)
{
int size = MAX_HISTORY;
if (hp) {
@@ -1313,6 +1330,17 @@ static int get_next_history(void)
return 0;
}
+/* Lists command history. Used by shell 'history' builtins */
+void FAST_FUNC show_history(const line_input_t *st)
+{
+ int i;
+
+ if (!st)
+ return;
+ for (i = 0; i < st->cnt_history; i++)
+ printf("%4d %s\n", i, st->history[i]);
+}
+
# if ENABLE_FEATURE_EDITING_SAVEHISTORY
/* We try to ensure that concurrent additions to the history
* do not overwrite each other.
@@ -1531,7 +1559,6 @@ static void remember_in_history(char *str)
# if ENABLE_FEATURE_EDITING_SAVEHISTORY && !ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
save_history(str);
# endif
- IF_FEATURE_EDITING_FANCY_PROMPT(num_ok_lines++;)
}
#else /* MAX_HISTORY == 0 */
@@ -1753,43 +1780,84 @@ static void ask_terminal(void)
#define ask_terminal() ((void)0)
#endif
+/* Called just once at read_line_input() init time */
#if !ENABLE_FEATURE_EDITING_FANCY_PROMPT
static void parse_and_put_prompt(const char *prmt_ptr)
{
+ const char *p;
cmdedit_prompt = prmt_ptr;
- cmdedit_prmt_len = strlen(prmt_ptr);
+ p = strrchr(prmt_ptr, '\n');
+ cmdedit_prmt_len = unicode_strwidth(p ? p+1 : prmt_ptr);
put_prompt();
}
#else
static void parse_and_put_prompt(const char *prmt_ptr)
{
- int prmt_len = 0;
- size_t cur_prmt_len = 0;
- char flg_not_length = '[';
+ int prmt_size = 0;
char *prmt_mem_ptr = xzalloc(1);
- char *cwd_buf = xrealloc_getcwd_or_warn(NULL);
+# if ENABLE_USERNAME_OR_HOMEDIR
+ char *cwd_buf = NULL;
+# endif
+ char flg_not_length = '[';
char cbuf[2];
- char c;
- char *pbuf;
-
- cmdedit_prmt_len = 0;
- if (!cwd_buf) {
- cwd_buf = (char *)bb_msg_unknown;
- }
+ /*cmdedit_prmt_len = 0; - already is */
cbuf[1] = '\0'; /* never changes */
while (*prmt_ptr) {
+ char timebuf[sizeof("HH:MM:SS")];
char *free_me = NULL;
+ char *pbuf;
+ char c;
pbuf = cbuf;
c = *prmt_ptr++;
if (c == '\\') {
- const char *cp = prmt_ptr;
+ const char *cp;
int l;
-
- c = bb_process_escape_sequence(&prmt_ptr);
+/*
+ * Supported via bb_process_escape_sequence:
+ * \a ASCII bell character (07)
+ * \e ASCII escape character (033)
+ * \n newline
+ * \r carriage return
+ * \\ backslash
+ * \nnn char with octal code nnn
+ * Supported:
+ * \$ if the effective UID is 0, a #, otherwise a $
+ * \w current working directory, with $HOME abbreviated with a tilde
+ * Note: we do not support $PROMPT_DIRTRIM=n feature
+ * \W basename of the current working directory, with $HOME abbreviated with a tilde
+ * \h hostname up to the first '.'
+ * \H hostname
+ * \u username
+ * \[ begin a sequence of non-printing characters
+ * \] end a sequence of non-printing characters
+ * \T current time in 12-hour HH:MM:SS format
+ * \@ current time in 12-hour am/pm format
+ * \A current time in 24-hour HH:MM format
+ * \t current time in 24-hour HH:MM:SS format
+ * (all of the above work as \A)
+ * Not supported:
+ * \! history number of this command
+ * \# command number of this command
+ * \j number of jobs currently managed by the shell
+ * \l basename of the shell's terminal device name
+ * \s name of the shell, the basename of $0 (the portion following the final slash)
+ * \V release of bash, version + patch level (e.g., 2.00.0)
+ * \d date in "Weekday Month Date" format (e.g., "Tue May 26")
+ * \D{format}
+ * format is passed to strftime(3).
+ * An empty format results in a locale-specific time representation.
+ * The braces are required.
+ * Mishandled by bb_process_escape_sequence:
+ * \v version of bash (e.g., 2.00)
+ */
+ cp = prmt_ptr;
+ c = *cp;
+ if (c != 't') /* don't treat \t as tab */
+ c = bb_process_escape_sequence(&prmt_ptr);
if (prmt_ptr == cp) {
if (*cp == '\0')
break;
@@ -1801,39 +1869,55 @@ static void parse_and_put_prompt(const char *prmt_ptr)
pbuf = user_buf ? user_buf : (char*)"";
break;
# endif
+ case 'H':
case 'h':
pbuf = free_me = safe_gethostname();
- *strchrnul(pbuf, '.') = '\0';
+ if (c == 'h')
+ strchrnul(pbuf, '.')[0] = '\0';
break;
case '$':
c = (geteuid() == 0 ? '#' : '$');
break;
+ case 'T': /* 12-hour HH:MM:SS format */
+ case '@': /* 12-hour am/pm format */
+ case 'A': /* 24-hour HH:MM format */
+ case 't': /* 24-hour HH:MM:SS format */
+ /* We show all of them as 24-hour HH:MM */
+ strftime_HHMMSS(timebuf, sizeof(timebuf), NULL)[-3] = '\0';
+ pbuf = timebuf;
+ break;
# if ENABLE_USERNAME_OR_HOMEDIR
- case 'w':
- /* /home/user[/something] -> ~[/something] */
- pbuf = cwd_buf;
- l = strlen(home_pwd_buf);
- if (l != 0
- && strncmp(home_pwd_buf, cwd_buf, l) == 0
- && (cwd_buf[l]=='/' || cwd_buf[l]=='\0')
- && strlen(cwd_buf + l) < PATH_MAX
- ) {
- pbuf = free_me = xasprintf("~%s", cwd_buf + l);
+ case 'w': /* current dir */
+ case 'W': /* basename of cur dir */
+ if (!cwd_buf) {
+ cwd_buf = xrealloc_getcwd_or_warn(NULL);
+ if (!cwd_buf)
+ cwd_buf = (char *)bb_msg_unknown;
+ else if (home_pwd_buf[0]) {
+ char *after_home_user;
+
+ /* /home/user[/something] -> ~[/something] */
+ after_home_user = is_prefixed_with(cwd_buf, home_pwd_buf);
+ if (after_home_user
+ && (*after_home_user == '/' || *after_home_user == '\0')
+ ) {
+ cwd_buf[0] = '~';
+ overlapping_strcpy(cwd_buf + 1, after_home_user);
+ }
+ }
}
- break;
-# endif
- case 'W':
pbuf = cwd_buf;
+ if (c == 'w')
+ break;
cp = strrchr(pbuf, '/');
- if (cp != NULL && cp != pbuf)
- pbuf += (cp-pbuf) + 1;
- break;
- case '!':
- pbuf = free_me = xasprintf("%d", num_ok_lines);
- break;
- case 'e': case 'E': /* \e \E = \033 */
- c = '\033';
+ if (cp)
+ pbuf = (char*)cp + 1;
break;
+# endif
+// bb_process_escape_sequence does this now:
+// case 'e': case 'E': /* \e \E = \033 */
+// c = '\033';
+// break;
case 'x': case 'X': {
char buf2[4];
for (l = 0; l < 3;) {
@@ -1855,7 +1939,8 @@ static void parse_and_put_prompt(const char *prmt_ptr)
}
case '[': case ']':
if (c == flg_not_length) {
- flg_not_length = (flg_not_length == '[' ? ']' : '[');
+ /* Toggle '['/']' hex 5b/5d */
+ flg_not_length ^= 6;
continue;
}
break;
@@ -1863,16 +1948,29 @@ static void parse_and_put_prompt(const char *prmt_ptr)
} /* if */
} /* if */
cbuf[0] = c;
- cur_prmt_len = strlen(pbuf);
- prmt_len += cur_prmt_len;
- if (flg_not_length != ']')
- cmdedit_prmt_len += cur_prmt_len;
- prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_len+1), pbuf);
+ {
+ int n = strlen(pbuf);
+ prmt_size += n;
+ if (c == '\n')
+ cmdedit_prmt_len = 0;
+ else if (flg_not_length != ']') {
+#if 0 /*ENABLE_UNICODE_SUPPORT*/
+/* Won't work, pbuf is one BYTE string here instead of an one Unicode char string. */
+/* FIXME */
+ cmdedit_prmt_len += unicode_strwidth(pbuf);
+#else
+ cmdedit_prmt_len += n;
+#endif
+ }
+ }
+ prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_size+1), pbuf);
free(free_me);
} /* while */
+# if ENABLE_USERNAME_OR_HOMEDIR
if (cwd_buf != (char *)bb_msg_unknown)
free(cwd_buf);
+# endif
cmdedit_prompt = prmt_mem_ptr;
put_prompt();
}
@@ -1934,7 +2032,15 @@ static int lineedit_read_key(char *read_key_buffer, int timeout)
S.sent_ESC_br6n = 0;
if (cursor == 0) { /* otherwise it may be bogus */
int col = ((ic >> 32) & 0x7fff) - 1;
- if (col > cmdedit_prmt_len) {
+ /*
+ * Is col > cmdedit_prmt_len?
+ * If yes (terminal says cursor is farther to the right
+ * of where we think it should be),
+ * the prompt wasn't printed starting at col 1,
+ * there was additional text before it.
+ */
+ if ((int)(col - cmdedit_prmt_len) > 0) {
+ /* Fix our understanding of current x position */
cmdedit_x += (col - cmdedit_prmt_len);
while (cmdedit_x >= cmdedit_termw) {
cmdedit_x -= cmdedit_termw;
@@ -2025,6 +2131,7 @@ static int32_t reverse_i_search(void)
char read_key_buffer[KEYCODE_BUFFER_SIZE];
const char *matched_history_line;
const char *saved_prompt;
+ unsigned saved_prmt_len;
int32_t ic;
matched_history_line = NULL;
@@ -2033,6 +2140,7 @@ static int32_t reverse_i_search(void)
/* Save and replace the prompt */
saved_prompt = cmdedit_prompt;
+ saved_prmt_len = cmdedit_prmt_len;
goto set_prompt;
while (1) {
@@ -2108,7 +2216,7 @@ static int32_t reverse_i_search(void)
free((char*)cmdedit_prompt);
set_prompt:
cmdedit_prompt = xasprintf("(reverse-i-search)'%s': ", match_buf);
- cmdedit_prmt_len = strlen(cmdedit_prompt);
+ cmdedit_prmt_len = unicode_strwidth(cmdedit_prompt);
goto do_redraw;
}
}
@@ -2130,7 +2238,7 @@ static int32_t reverse_i_search(void)
free((char*)cmdedit_prompt);
cmdedit_prompt = saved_prompt;
- cmdedit_prmt_len = strlen(cmdedit_prompt);
+ cmdedit_prmt_len = saved_prmt_len;
redraw(cmdedit_y, command_len - cursor);
return ic;
@@ -2160,9 +2268,13 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
INIT_S();
if (tcgetattr(STDIN_FILENO, &initial_settings) < 0
- || !(initial_settings.c_lflag & ECHO)
+ || (initial_settings.c_lflag & (ECHO|ICANON)) == ICANON
) {
- /* Happens when e.g. stty -echo was run before */
+ /* Happens when e.g. stty -echo was run before.
+ * But if ICANON is not set, we don't come here.
+ * (example: interactive python ^Z-backgrounded,
+ * tty is still in "raw mode").
+ */
parse_and_put_prompt(prompt);
/* fflush_all(); - done by parse_and_put_prompt */
if (fgets(command, maxsize, stdin) == NULL)
@@ -2511,7 +2623,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
* standard readline bindings (IOW: bash) do.
* Often, Alt-<key> generates ESC-<key>.
*/
- ic = lineedit_read_key(read_key_buffer, timeout);
+ ic = lineedit_read_key(read_key_buffer, 50);
switch (ic) {
//case KEYCODE_LEFT: - bash doesn't do this
case 'b':
@@ -2698,8 +2810,9 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
free(command_ps);
#endif
- if (command_len > 0)
+ if (command_len > 0) {
remember_in_history(command);
+ }
if (break_out > 0) {
command[command_len++] = '\n';
diff --git a/release/src/router/busybox/libbb/logenv.c b/release/src/router/busybox/libbb/logenv.c
new file mode 100644
index 0000000000..66c60bd4e8
--- /dev/null
+++ b/release/src/router/busybox/libbb/logenv.c
@@ -0,0 +1,24 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 2014 by Fugro Intersite B.V. <m.stam@fugro.nl>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+#include "libbb.h"
+
+void FAST_FUNC bb_logenv_override(void)
+{
+ const char* mode = getenv("LOGGING");
+
+ if (!mode)
+ return;
+
+ if (strcmp(mode, "none") == 0)
+ logmode = LOGMODE_NONE;
+#if ENABLE_FEATURE_SYSLOG
+ else if (strcmp(mode, "syslog") == 0)
+ logmode = LOGMODE_SYSLOG;
+#endif
+}
diff --git a/release/src/router/busybox/libbb/login.c b/release/src/router/busybox/libbb/login.c
index 8a82c6add7..8f080b7754 100644
--- a/release/src/router/busybox/libbb/login.c
+++ b/release/src/router/busybox/libbb/login.c
@@ -16,7 +16,6 @@
#define LOGIN " login: "
static const char fmtstr_d[] ALIGN1 = "%A, %d %B %Y";
-static const char fmtstr_t[] ALIGN1 = "%H:%M:%S";
void FAST_FUNC print_login_issue(const char *issue_file, const char *tty)
{
@@ -73,7 +72,7 @@ void FAST_FUNC print_login_issue(const char *issue_file, const char *tty)
strftime(buf, sizeof(buf), fmtstr_d, localtime(&t));
break;
case 't':
- strftime(buf, sizeof(buf), fmtstr_t, localtime(&t));
+ strftime_HHMMSS(buf, sizeof(buf), &t);
break;
case 'l':
outbuf = tty;
diff --git a/release/src/router/busybox/libbb/loop.c b/release/src/router/busybox/libbb/loop.c
index b3a5208481..d30b378d75 100644
--- a/release/src/router/busybox/libbb/loop.c
+++ b/release/src/router/busybox/libbb/loop.c
@@ -94,19 +94,19 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
/* Open the file. Barf if this doesn't work. */
mode = ro ? O_RDONLY : O_RDWR;
+ open_ffd:
ffd = open(file, mode);
if (ffd < 0) {
if (mode != O_RDONLY) {
mode = O_RDONLY;
- ffd = open(file, mode);
+ goto open_ffd;
}
- if (ffd < 0)
- return -errno;
+ return -errno;
}
/* Find a loop device. */
try = *device ? *device : dev;
- /* 1048575 is a max possible minor number in Linux circa 2010 */
+ /* 1048575 (0xfffff) is a max possible minor number in Linux circa 2010 */
for (i = 0; rc && i < 1048576; i++) {
sprintf(dev, LOOP_FORMAT, i);
@@ -121,7 +121,7 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
goto try_to_open;
}
/* Ran out of block devices, return failure. */
- rc = -ENOENT;
+ rc = -1;
break;
}
try_to_open:
@@ -131,8 +131,14 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
mode = O_RDONLY;
dfd = open(try, mode);
}
- if (dfd < 0)
+ if (dfd < 0) {
+ if (errno == ENXIO) {
+ /* Happens if loop module is not loaded */
+ rc = -1;
+ break;
+ }
goto try_again;
+ }
rc = ioctl(dfd, BB_LOOP_GET_STATUS, &loopinfo);
@@ -148,16 +154,7 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
else
ioctl(dfd, LOOP_CLR_FD, 0);
}
-
- /* If this block device already set up right, re-use it.
- (Yes this is racy, but associating two loop devices with the same
- file isn't pretty either. In general, mounting the same file twice
- without using losetup manually is problematic.)
- */
- } else
- if (strcmp(file, (char *)loopinfo.lo_file_name) != 0
- || offset != loopinfo.lo_offset
- ) {
+ } else {
rc = -1;
}
close(dfd);
diff --git a/release/src/router/busybox/libbb/make_directory.c b/release/src/router/busybox/libbb/make_directory.c
index 72303e7a30..89352ca1f1 100644
--- a/release/src/router/busybox/libbb/make_directory.c
+++ b/release/src/router/busybox/libbb/make_directory.c
@@ -99,6 +99,10 @@ int FAST_FUNC bb_make_directory(char *path, long mode, int flags)
if (!c) {
goto ret0;
}
+ } else {
+ if (flags & FILEUTILS_VERBOSE) {
+ printf("created directory: '%s'\n", path);
+ }
}
if (!c) {
@@ -107,6 +111,10 @@ int FAST_FUNC bb_make_directory(char *path, long mode, int flags)
* an error. */
if ((mode != -1) && (chmod(path, mode) < 0)) {
fail_msg = "set permissions of";
+ if (flags & FILEUTILS_IGNORE_CHMOD_ERR) {
+ flags = 0;
+ goto print_err;
+ }
break;
}
goto ret0;
@@ -116,8 +124,9 @@ int FAST_FUNC bb_make_directory(char *path, long mode, int flags)
*s = c;
} /* while (1) */
- bb_perror_msg("can't %s directory '%s'", fail_msg, path);
flags = -1;
+ print_err:
+ bb_perror_msg("can't %s directory '%s'", fail_msg, path);
goto ret;
ret0:
flags = 0;
diff --git a/release/src/router/busybox/libbb/match_fstype.c b/release/src/router/busybox/libbb/match_fstype.c
index 32c3d7f188..b066b42117 100644
--- a/release/src/router/busybox/libbb/match_fstype.c
+++ b/release/src/router/busybox/libbb/match_fstype.c
@@ -17,7 +17,6 @@
int FAST_FUNC match_fstype(const struct mntent *mt, const char *t_fstype)
{
int match = 1;
- int len;
if (!t_fstype)
return match;
@@ -27,10 +26,10 @@ int FAST_FUNC match_fstype(const struct mntent *mt, const char *t_fstype)
t_fstype += 2;
}
- len = strlen(mt->mnt_type);
while (1) {
- if (strncmp(mt->mnt_type, t_fstype, len) == 0
- && (t_fstype[len] == '\0' || t_fstype[len] == ',')
+ char *after_mnt_type = is_prefixed_with(t_fstype, mt->mnt_type);
+ if (after_mnt_type
+ && (*after_mnt_type == '\0' || *after_mnt_type == ',')
) {
return match;
}
diff --git a/release/src/router/busybox/libbb/messages.c b/release/src/router/busybox/libbb/messages.c
index 7ee434c559..c6c49c561a 100644
--- a/release/src/router/busybox/libbb/messages.c
+++ b/release/src/router/busybox/libbb/messages.c
@@ -29,7 +29,7 @@ const char bb_msg_can_not_create_raw_socket[] ALIGN1 = "can't create raw socket"
const char bb_msg_perm_denied_are_you_root[] ALIGN1 = "permission denied (are you root?)";
const char bb_msg_you_must_be_root[] ALIGN1 = "you must be root";
const char bb_msg_requires_arg[] ALIGN1 = "%s requires an argument";
-const char bb_msg_invalid_arg[] ALIGN1 = "invalid argument '%s' to '%s'";
+const char bb_msg_invalid_arg_to[] ALIGN1 = "invalid argument '%s' to '%s'";
const char bb_msg_standard_input[] ALIGN1 = "standard input";
const char bb_msg_standard_output[] ALIGN1 = "standard output";
@@ -43,7 +43,7 @@ const char bb_PATH_root_path[] ALIGN1 =
"PATH=/sbin:/usr/sbin:/opt/sbin:/bin:/usr/bin:/opt/bin" BB_ADDITIONAL_PATH;
-const int const_int_1 = 1;
+//const int const_int_1 = 1;
/* explicitly = 0, otherwise gcc may make it a common variable
* and it will end up in bss */
const int const_int_0 = 0;
@@ -59,8 +59,3 @@ const char bb_path_wtmp_file[] ALIGN1 =
# error unknown path to wtmp file
# endif
#endif
-
-/* We use it for "global" data via *(struct global*)&bb_common_bufsiz1.
- * Since gcc insists on aligning struct global's members, it would be a pity
- * (and an alignment fault on some CPUs) to mess it up. */
-char bb_common_bufsiz1[COMMON_BUFSIZE] ALIGNED(sizeof(long long));
diff --git a/release/src/router/busybox/libbb/missing_syscalls.c b/release/src/router/busybox/libbb/missing_syscalls.c
new file mode 100644
index 0000000000..0934128117
--- /dev/null
+++ b/release/src/router/busybox/libbb/missing_syscalls.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2012, Denys Vlasenko
+ *
+ * Licensed under GPLv2, see file LICENSE in this source tree.
+ */
+
+//kbuild:lib-y += missing_syscalls.o
+
+/*#include <linux/timex.h> - for struct timex, but may collide with <time.h> */
+#include <sys/syscall.h>
+#include "libbb.h"
+
+#if defined(ANDROID) || defined(__ANDROID__)
+pid_t getsid(pid_t pid)
+{
+ return syscall(__NR_getsid, pid);
+}
+
+int stime(const time_t *t)
+{
+ struct timeval tv;
+ tv.tv_sec = *t;
+ tv.tv_usec = 0;
+ return settimeofday(&tv, NULL);
+}
+
+int sethostname(const char *name, size_t len)
+{
+ return syscall(__NR_sethostname, name, len);
+}
+
+struct timex;
+int adjtimex(struct timex *buf)
+{
+ return syscall(__NR_adjtimex, buf);
+}
+
+int pivot_root(const char *new_root, const char *put_old)
+{
+ return syscall(__NR_pivot_root, new_root, put_old);
+}
+
+# if __ANDROID_API__ < 21
+int tcdrain(int fd)
+{
+ return ioctl(fd, TCSBRK, 1);
+}
+# endif
+#endif
diff --git a/release/src/router/busybox/libbb/mode_string.c b/release/src/router/busybox/libbb/mode_string.c
index f1afe7d616..934eb6dc7b 100644
--- a/release/src/router/busybox/libbb/mode_string.c
+++ b/release/src/router/busybox/libbb/mode_string.c
@@ -87,9 +87,9 @@ const char* FAST_FUNC bb_mode_string(mode_t mode)
/* The previous version used "0pcCd?bB-?l?s???". However, the '0', 'C',
* and 'B' types don't appear to be available on linux. So I removed them. */
-static const char type_chars[16] = "?pc?d?b?-?l?s???";
+static const char type_chars[16] ALIGN1 = "?pc?d?b?-?l?s???";
/********************************** 0123456789abcdef */
-static const char mode_chars[7] = "rwxSTst";
+static const char mode_chars[7] ALIGN1 = "rwxSTst";
const char* FAST_FUNC bb_mode_string(mode_t mode)
{
diff --git a/release/src/router/busybox/libbb/nuke_str.c b/release/src/router/busybox/libbb/nuke_str.c
new file mode 100644
index 0000000000..56b808bc7e
--- /dev/null
+++ b/release/src/router/busybox/libbb/nuke_str.c
@@ -0,0 +1,21 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 2008 Denys Vlasenko
+ *
+ * Licensed under GPLv2, see file LICENSE in this source tree.
+ */
+
+//kbuild:lib-y += nuke_str.o
+
+#include "libbb.h"
+
+void FAST_FUNC nuke_str(char *str)
+{
+ if (str) {
+ while (*str)
+ *str++ = 0;
+ /* or: memset(str, 0, strlen(str)); - not as small as above */
+ }
+}
diff --git a/release/src/router/busybox/libbb/obscure.c b/release/src/router/busybox/libbb/obscure.c
index 9ecc1f672c..ad17d1ff1b 100644
--- a/release/src/router/busybox/libbb/obscure.c
+++ b/release/src/router/busybox/libbb/obscure.c
@@ -76,7 +76,7 @@ static int string_checker(const char *p1, const char *p2)
ret |= string_checker_helper(p, p2);
/* clean up */
- memset(p, 0, size);
+ nuke_str(p);
free(p);
return ret;
@@ -182,3 +182,41 @@ int FAST_FUNC obscure(const char *old, const char *newval, const struct passwd *
}
return 0;
}
+
+#if ENABLE_UNIT_TEST
+
+/* Test obscure_msg() instead of obscure() in order not to print anything. */
+
+static const struct passwd pw = {
+ .pw_name = (char *)"johndoe",
+ .pw_gecos = (char *)"John Doe",
+};
+
+BBUNIT_DEFINE_TEST(obscure_weak_pass)
+{
+ /* Empty password */
+ BBUNIT_ASSERT_NOTNULL(obscure_msg("Ad4#21?'S|", "", &pw));
+ /* Pure numbers */
+ BBUNIT_ASSERT_NOTNULL(obscure_msg("Ad4#21?'S|", "23577315", &pw));
+ /* Similar to pw_name */
+ BBUNIT_ASSERT_NOTNULL(obscure_msg("Ad4#21?'S|", "johndoe123%", &pw));
+ /* Similar to pw_gecos, reversed */
+ BBUNIT_ASSERT_NOTNULL(obscure_msg("Ad4#21?'S|", "eoD nhoJ^44@", &pw));
+ /* Similar to the old password */
+ BBUNIT_ASSERT_NOTNULL(obscure_msg("Ad4#21?'S|", "d4#21?'S", &pw));
+ /* adjacent letters */
+ BBUNIT_ASSERT_NOTNULL(obscure_msg("Ad4#21?'S|", "qwerty123", &pw));
+ /* Many similar chars */
+ BBUNIT_ASSERT_NOTNULL(obscure_msg("Ad4#21?'S|", "^33Daaaaaa1", &pw));
+
+ BBUNIT_ENDTEST;
+}
+
+BBUNIT_DEFINE_TEST(obscure_strong_pass)
+{
+ BBUNIT_ASSERT_NULL(obscure_msg("Rt4##2&:'|", "}(^#rrSX3S*22", &pw));
+
+ BBUNIT_ENDTEST;
+}
+
+#endif /* ENABLE_UNIT_TEST */
diff --git a/release/src/router/busybox/libbb/parse_mode.c b/release/src/router/busybox/libbb/parse_mode.c
index 5a4e1c579c..bddd39bca9 100644
--- a/release/src/router/busybox/libbb/parse_mode.c
+++ b/release/src/router/busybox/libbb/parse_mode.c
@@ -15,7 +15,7 @@
#define FILEMODEBITS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
-int FAST_FUNC bb_parse_mode(const char *s, mode_t *current_mode)
+int FAST_FUNC bb_parse_mode(const char *s, unsigned current_mode)
{
static const mode_t who_mask[] = {
S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO, /* a */
@@ -46,13 +46,12 @@ int FAST_FUNC bb_parse_mode(const char *s, mode_t *current_mode)
tmp = strtoul(s, &e, 8);
if (*e || (tmp > 07777U)) { /* Check range and trailing chars. */
- return 0;
+ return -1;
}
- *current_mode = tmp;
- return 1;
+ return tmp;
}
- new_mode = *current_mode;
+ new_mode = current_mode;
/* Note: we allow empty clauses, and hence empty modes.
* We treat an empty mode as no change to perms. */
@@ -71,7 +70,7 @@ int FAST_FUNC bb_parse_mode(const char *s, mode_t *current_mode)
if (*p == *s) {
wholist |= who_mask[(int)(p-who_chars)];
if (!*++s) {
- return 0;
+ return -1;
}
goto WHO_LIST;
}
@@ -80,7 +79,7 @@ int FAST_FUNC bb_parse_mode(const char *s, mode_t *current_mode)
do { /* Process action list. */
if ((*s != '+') && (*s != '-')) {
if (*s != '=') {
- return 0;
+ return -1;
}
/* Since op is '=', clear all bits corresponding to the
* wholist, or all file bits if wholist is empty. */
@@ -145,6 +144,5 @@ int FAST_FUNC bb_parse_mode(const char *s, mode_t *current_mode)
} while (*s && (*s != ','));
}
- *current_mode = new_mode;
- return 1;
+ return new_mode;
}
diff --git a/release/src/router/busybox/libbb/platform.c b/release/src/router/busybox/libbb/platform.c
index 19734517b1..03bbb798bd 100644
--- a/release/src/router/busybox/libbb/platform.c
+++ b/release/src/router/busybox/libbb/platform.c
@@ -17,6 +17,24 @@ char* FAST_FUNC strchrnul(const char *s, int c)
}
#endif
+#ifndef HAVE_USLEEP
+int FAST_FUNC usleep(unsigned usec)
+{
+ struct timespec ts;
+ ts.tv_sec = usec / 1000000u;
+ ts.tv_nsec = (usec % 1000000u) * 1000u;
+ /*
+ * If a signal has non-default handler, nanosleep returns early.
+ * Our version of usleep doesn't return early
+ * if interrupted by such signals:
+ *
+ */
+ while (nanosleep(&ts, &ts) != 0)
+ continue;
+ return 0;
+}
+#endif
+
#ifndef HAVE_VASPRINTF
int FAST_FUNC vasprintf(char **string_ptr, const char *format, va_list p)
{
@@ -176,3 +194,22 @@ ssize_t FAST_FUNC getline(char **lineptr, size_t *n, FILE *stream)
return len;
}
#endif
+
+#ifndef HAVE_TTYNAME_R
+int ttyname_r(int fd, char *buf, size_t buflen)
+{
+ int r;
+ char path[sizeof("/proc/self/fd/%d") + sizeof(int)*3];
+
+ if (!isatty(fd))
+ return errno == EINVAL ? ENOTTY : errno;
+ sprintf(path, "/proc/self/fd/%d", fd);
+ r = readlink(path, buf, buflen);
+ if (r < 0)
+ return errno;
+ if (r >= buflen)
+ return ERANGE;
+ buf[r] = '\0';
+ return 0;
+}
+#endif
diff --git a/release/src/router/busybox/libbb/printable.c b/release/src/router/busybox/libbb/printable.c
index f6ada4904e..9a423431e6 100644
--- a/release/src/router/busybox/libbb/printable.c
+++ b/release/src/router/busybox/libbb/printable.c
@@ -32,3 +32,27 @@ void FAST_FUNC fputc_printable(int ch, FILE *file)
}
fputc(ch, file);
}
+
+void FAST_FUNC visible(unsigned ch, char *buf, int flags)
+{
+ if (ch == '\t' && !(flags & VISIBLE_SHOW_TABS)) {
+ goto raw;
+ }
+ if (ch == '\n') {
+ if (flags & VISIBLE_ENDLINE)
+ *buf++ = '$';
+ } else {
+ if (ch >= 128) {
+ ch -= 128;
+ *buf++ = 'M';
+ *buf++ = '-';
+ }
+ if (ch < 32 || ch == 127) {
+ *buf++ = '^';
+ ch ^= 0x40;
+ }
+ }
+ raw:
+ *buf++ = ch;
+ *buf = '\0';
+}
diff --git a/release/src/router/busybox/libbb/printable_string.c b/release/src/router/busybox/libbb/printable_string.c
index a316f60de5..077d58d32f 100644
--- a/release/src/router/busybox/libbb/printable_string.c
+++ b/release/src/router/busybox/libbb/printable_string.c
@@ -11,9 +11,6 @@
const char* FAST_FUNC printable_string(uni_stat_t *stats, const char *str)
{
- static char *saved[4];
- static unsigned cur_saved; /* = 0 */
-
char *dst;
const char *s;
@@ -56,10 +53,5 @@ const char* FAST_FUNC printable_string(uni_stat_t *stats, const char *str)
}
}
#endif
-
- free(saved[cur_saved]);
- saved[cur_saved] = dst;
- cur_saved = (cur_saved + 1) & (ARRAY_SIZE(saved)-1);
-
- return dst;
+ return auto_string(dst);
}
diff --git a/release/src/router/busybox/libbb/procps.c b/release/src/router/busybox/libbb/procps.c
index 40587db82b..4edc54d486 100644
--- a/release/src/router/busybox/libbb/procps.c
+++ b/release/src/router/busybox/libbb/procps.c
@@ -180,7 +180,7 @@ static char *skip_fields(char *str, int count)
#if ENABLE_FEATURE_TOPMEM || ENABLE_PMAP
int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total,
- void (*cb)(struct smaprec *, void *), void *data)
+ void (*cb)(struct smaprec *, void *), void *data)
{
FILE *file;
struct smaprec currec;
@@ -205,11 +205,11 @@ int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total,
// Rss: nnn kB
// .....
- char *tp = buf, *p;
+ char *tp, *p;
#define SCAN(S, X) \
- if (strncmp(tp, S, sizeof(S)-1) == 0) { \
- tp = skip_whitespace(tp + sizeof(S)-1); \
+ if ((tp = is_prefixed_with(buf, S)) != NULL) { \
+ tp = skip_whitespace(tp); \
total->X += currec.X = fast_strtoul_10(&tp); \
continue; \
}
@@ -247,7 +247,7 @@ int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total,
// skipping "rw-s FILEOFS M:m INODE "
tp = skip_whitespace(skip_fields(tp, 4));
// filter out /dev/something (something != zero)
- if (strncmp(tp, "/dev/", 5) != 0 || strcmp(tp, "/dev/zero\n") == 0) {
+ if (!is_prefixed_with(tp, "/dev/") || strcmp(tp, "/dev/zero\n") == 0) {
if (currec.smap_mode[1] == 'w') {
currec.mapped_rw = currec.smap_size;
total->mapped_rw += currec.smap_size;
@@ -283,7 +283,6 @@ int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total,
}
#endif
-void BUG_comm_size(void);
procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
{
if (!sp)
@@ -385,8 +384,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
/*if (!cp || cp[1] != ' ')
continue;*/
cp[0] = '\0';
- if (sizeof(sp->comm) < 16)
- BUG_comm_size();
+ BUILD_BUG_ON(sizeof(sp->comm) < 16);
comm1 = strchr(buf, '(');
/*if (comm1)*/
safe_strncpy(sp->comm, comm1 + 1, sizeof(sp->comm));
@@ -425,7 +423,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
if (n < 11)
continue; /* bogus data, get next /proc/XXX */
# if ENABLE_FEATURE_TOP_SMP_PROCESS
- if (n < 11+15)
+ if (n == 11)
sp->last_seen_on_cpu = 0;
# endif
@@ -497,8 +495,8 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
while (fgets(buf, sizeof(buf), file)) {
char *tp;
#define SCAN_TWO(str, name, statement) \
- if (strncmp(buf, str, sizeof(str)-1) == 0) { \
- tp = skip_whitespace(buf + sizeof(str)-1); \
+ if ((tp = is_prefixed_with(buf, str)) != NULL) { \
+ tp = skip_whitespace(tp); \
sscanf(tp, "%u", &sp->name); \
statement; \
}
@@ -554,8 +552,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
break;
if (flags & PSSCAN_ARGVN) {
sp->argv_len = n;
- sp->argv0 = xmalloc(n + 1);
- memcpy(sp->argv0, buf, n + 1);
+ sp->argv0 = xmemdup(buf, n + 1);
/* sp->argv0[n] = '\0'; - buf has it */
} else {
sp->argv_len = 0;
@@ -583,18 +580,22 @@ void FAST_FUNC read_cmdline(char *buf, int col, unsigned pid, const char *comm)
buf[sz] = '\0';
while (--sz >= 0 && buf[sz] == '\0')
continue;
+ /* Prevent basename("process foo/bar") = "bar" */
+ strchrnul(buf, ' ')[0] = '\0';
base = bb_basename(buf); /* before we replace argv0's NUL with space */
while (sz >= 0) {
if ((unsigned char)(buf[sz]) < ' ')
buf[sz] = ' ';
sz--;
}
+ if (base[0] == '-') /* "-sh" (login shell)? */
+ base++;
/* If comm differs from argv0, prepend "{comm} ".
* It allows to see thread names set by prctl(PR_SET_NAME).
*/
- if (base[0] == '-') /* "-sh" (login shell)? */
- base++;
+ if (!comm)
+ return;
comm_len = strlen(comm);
/* Why compare up to comm_len, not COMM_LEN-1?
* Well, some processes rewrite argv, and use _spaces_ there
@@ -612,9 +613,8 @@ void FAST_FUNC read_cmdline(char *buf, int col, unsigned pid, const char *comm)
buf[comm_len - 1] = ' ';
buf[col - 1] = '\0';
}
-
} else {
- snprintf(buf, col, "[%s]", comm);
+ snprintf(buf, col, "[%s]", comm ? comm : "?");
}
}
diff --git a/release/src/router/busybox/libbb/progress.c b/release/src/router/busybox/libbb/progress.c
index 372feb0c24..3c2f01667a 100644
--- a/release/src/router/busybox/libbb/progress.c
+++ b/release/src/router/busybox/libbb/progress.c
@@ -45,13 +45,6 @@ enum {
STALLTIME = 5
};
-static unsigned int get_tty2_width(void)
-{
- unsigned width;
- get_terminal_width_height(2, &width, NULL);
- return width;
-}
-
void FAST_FUNC bb_progress_init(bb_progress_t *p, const char *curfile)
{
#if ENABLE_UNICODE_SUPPORT
@@ -80,7 +73,7 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p,
{
uoff_t beg_and_transferred;
unsigned since_last_update, elapsed;
- int barlength;
+ int notty;
int kiloscale;
//transferred = 1234; /* use for stall detection testing */
@@ -137,18 +130,21 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p,
}
}
+ notty = !isatty(STDERR_FILENO);
+
if (ENABLE_UNICODE_SUPPORT)
- fprintf(stderr, "\r%s", p->curfile);
+ fprintf(stderr, "\r%s" + notty, p->curfile);
else
- fprintf(stderr, "\r%-20.20s", p->curfile);
+ fprintf(stderr, "\r%-20.20s" + notty, p->curfile);
beg_and_transferred = beg_size + transferred;
if (totalsize != 0) {
+ int barlength;
unsigned ratio = 100 * beg_and_transferred / totalsize;
fprintf(stderr, "%4u%%", ratio);
- barlength = get_tty2_width() - 49;
+ barlength = get_terminal_width(2) - 49;
if (barlength > 0) {
/* god bless gcc for variable arrays :) */
char buf[barlength + 1];
@@ -204,4 +200,6 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p,
hours = eta / 3600;
fprintf(stderr, "%3u:%02u:%02u ETA", hours, secs / 60, secs % 60);
}
+ if (notty)
+ fputc('\n', stderr);
}
diff --git a/release/src/router/busybox/libbb/pw_encrypt.c b/release/src/router/busybox/libbb/pw_encrypt.c
index 39ffa084f2..4cdc2de763 100644
--- a/release/src/router/busybox/libbb/pw_encrypt.c
+++ b/release/src/router/busybox/libbb/pw_encrypt.c
@@ -9,7 +9,7 @@
#include "libbb.h"
-/* static const uint8_t ascii64[] =
+/* static const uint8_t ascii64[] ALIGN1 =
* "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
*/
@@ -52,14 +52,18 @@ char* FAST_FUNC crypt_make_pw_salt(char salt[MAX_PW_SALT_LEN], const char *algo)
{
int len = 2/2;
char *salt_ptr = salt;
- if (algo[0] != 'd') { /* not des */
+
+ /* Standard chpasswd uses uppercase algos ("MD5", not "md5").
+ * Need to be case-insensitive in the code below.
+ */
+ if ((algo[0]|0x20) != 'd') { /* not des */
len = 8/2; /* so far assuming md5 */
*salt_ptr++ = '$';
*salt_ptr++ = '1';
*salt_ptr++ = '$';
#if !ENABLE_USE_BB_CRYPT || ENABLE_USE_BB_CRYPT_SHA
- if (algo[0] == 's') { /* sha */
- salt[1] = '5' + (strcmp(algo, "sha512") == 0);
+ if ((algo[0]|0x20) == 's') { /* sha */
+ salt[1] = '5' + (strcasecmp(algo, "sha512") == 0);
len = 16/2;
}
#endif
@@ -142,7 +146,14 @@ char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup)
char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup)
{
- return xstrdup(crypt(clear, salt));
+ char *s;
+
+ s = crypt(clear, salt);
+ /*
+ * glibc used to return "" on malformed salts (for example, ""),
+ * but since 2.17 it returns NULL.
+ */
+ return xstrdup(s ? s : "");
}
#endif
diff --git a/release/src/router/busybox/libbb/pw_encrypt_md5.c b/release/src/router/busybox/libbb/pw_encrypt_md5.c
index 889e09cab0..1e52ecaea8 100644
--- a/release/src/router/busybox/libbb/pw_encrypt_md5.c
+++ b/release/src/router/busybox/libbb/pw_encrypt_md5.c
@@ -86,7 +86,7 @@ md5_crypt(char result[MD5_OUT_BUFSIZE], const unsigned char *pw, const unsigned
/* Get the length of the salt including "$1$" */
sl = 3;
- while (salt[sl] && salt[sl] != '$' && sl < (3 + 8))
+ while (sl < (3 + 8) && salt[sl] && salt[sl] != '$')
sl++;
/* Hash. the password first, since that is what is most unknown */
diff --git a/release/src/router/busybox/libbb/read_key.c b/release/src/router/busybox/libbb/read_key.c
index 8d72d2a63c..ace23defb8 100644
--- a/release/src/router/busybox/libbb/read_key.c
+++ b/release/src/router/busybox/libbb/read_key.c
@@ -15,7 +15,10 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout)
const char *seq;
int n;
- /* Known escape sequences for cursor and function keys */
+ /* Known escape sequences for cursor and function keys.
+ * See "Xterm Control Sequences"
+ * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
+ */
static const char esccmds[] ALIGN1 = {
'O','A' |0x80,KEYCODE_UP ,
'O','B' |0x80,KEYCODE_DOWN ,
@@ -44,6 +47,8 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout)
/* ESC [ 1 ; 4 x, where x = A/B/C/D: Alt-Shift-<arrow> */
/* ESC [ 1 ; 5 x, where x = A/B/C/D: Ctrl-<arrow> - implemented below */
/* ESC [ 1 ; 6 x, where x = A/B/C/D: Ctrl-Shift-<arrow> */
+ /* ESC [ 1 ; 7 x, where x = A/B/C/D: Ctrl-Alt-<arrow> */
+ /* ESC [ 1 ; 8 x, where x = A/B/C/D: Ctrl-Alt-Shift-<arrow> */
'[','H' |0x80,KEYCODE_HOME , /* xterm */
'[','F' |0x80,KEYCODE_END , /* xterm */
/* [ESC] ESC [ [2] H - [Alt-][Shift-]Home (End similarly?) */
@@ -64,10 +69,10 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout)
'[','7','~' |0x80,KEYCODE_HOME , /* vt100? linux vt? or what? */
'[','8','~' |0x80,KEYCODE_END , /* vt100? linux vt? or what? */
#if 0
- '[','1','1','~'|0x80,KEYCODE_FUN1 ,
- '[','1','2','~'|0x80,KEYCODE_FUN2 ,
- '[','1','3','~'|0x80,KEYCODE_FUN3 ,
- '[','1','4','~'|0x80,KEYCODE_FUN4 ,
+ '[','1','1','~'|0x80,KEYCODE_FUN1 , /* old xterm, deprecated by ESC O P */
+ '[','1','2','~'|0x80,KEYCODE_FUN2 , /* old xterm... */
+ '[','1','3','~'|0x80,KEYCODE_FUN3 , /* old xterm... */
+ '[','1','4','~'|0x80,KEYCODE_FUN4 , /* old xterm... */
'[','1','5','~'|0x80,KEYCODE_FUN5 ,
/* [ESC] ESC [ 1 5 [;2] ~ - [Alt-][Shift-]F5 */
'[','1','7','~'|0x80,KEYCODE_FUN6 ,
diff --git a/release/src/router/busybox/libbb/read_printf.c b/release/src/router/busybox/libbb/read_printf.c
index 5ed6e36328..b6a17cc364 100644
--- a/release/src/router/busybox/libbb/read_printf.c
+++ b/release/src/router/busybox/libbb/read_printf.c
@@ -45,20 +45,20 @@
* which detects EAGAIN and uses poll() to wait on the fd.
* Thankfully, poll() doesn't care about O_NONBLOCK flag.
*/
-ssize_t FAST_FUNC nonblock_immune_read(int fd, void *buf, size_t count, int loop_on_EINTR)
+ssize_t FAST_FUNC nonblock_immune_read(int fd, void *buf, size_t count)
{
struct pollfd pfd[1];
ssize_t n;
while (1) {
- n = loop_on_EINTR ? safe_read(fd, buf, count) : read(fd, buf, count);
+ n = safe_read(fd, buf, count);
if (n >= 0 || errno != EAGAIN)
return n;
/* fd is in O_NONBLOCK mode. Wait using poll and repeat */
pfd[0].fd = fd;
pfd[0].events = POLLIN;
/* note: safe_poll pulls in printf */
- loop_on_EINTR ? safe_poll(pfd, 1, -1) : poll(pfd, 1, -1);
+ safe_poll(pfd, 1, -1);
}
}
@@ -81,7 +81,7 @@ char* FAST_FUNC xmalloc_reads(int fd, size_t *maxsz_p)
p = buf + sz;
sz += 128;
}
- if (nonblock_immune_read(fd, p, 1, /*loop_on_EINTR:*/ 1) != 1) {
+ if (nonblock_immune_read(fd, p, 1) != 1) {
/* EOF/error */
if (p == buf) { /* we read nothing */
free(buf);
diff --git a/release/src/router/busybox/libbb/remove_file.c b/release/src/router/busybox/libbb/remove_file.c
index c6531a0b99..eaca293d99 100644
--- a/release/src/router/busybox/libbb/remove_file.c
+++ b/release/src/router/busybox/libbb/remove_file.c
@@ -33,7 +33,7 @@ int FAST_FUNC remove_file(const char *path, int flags)
int status = 0;
if (!(flags & FILEUTILS_RECUR)) {
- bb_error_msg("%s: is a directory", path);
+ bb_error_msg("'%s' is a directory", path);
return -1;
}
@@ -78,6 +78,10 @@ int FAST_FUNC remove_file(const char *path, int flags)
return -1;
}
+ if (flags & FILEUTILS_VERBOSE) {
+ printf("removed directory: '%s'\n", path);
+ }
+
return status;
}
@@ -98,5 +102,9 @@ int FAST_FUNC remove_file(const char *path, int flags)
return -1;
}
+ if (flags & FILEUTILS_VERBOSE) {
+ printf("removed '%s'\n", path);
+ }
+
return 0;
}
diff --git a/release/src/router/busybox/libbb/replace.c b/release/src/router/busybox/libbb/replace.c
new file mode 100644
index 0000000000..8711f957da
--- /dev/null
+++ b/release/src/router/busybox/libbb/replace.c
@@ -0,0 +1,45 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+//kbuild:lib-y += replace.o
+
+#include "libbb.h"
+
+unsigned FAST_FUNC count_strstr(const char *str, const char *sub)
+{
+ size_t sub_len = strlen(sub);
+ unsigned count = 0;
+
+ while ((str = strstr(str, sub)) != NULL) {
+ count++;
+ str += sub_len;
+ }
+ return count;
+}
+
+char* FAST_FUNC xmalloc_substitute_string(const char *src, int count, const char *sub, const char *repl)
+{
+ char *buf, *dst, *end;
+ size_t sub_len = strlen(sub);
+ size_t repl_len = strlen(repl);
+
+ //dbg_msg("subst(s:'%s',count:%d,sub:'%s',repl:'%s'", src, count, sub, repl);
+
+ buf = dst = xmalloc(strlen(src) + count * ((int)repl_len - (int)sub_len) + 1);
+ /* we replace each sub with repl */
+ while ((end = strstr(src, sub)) != NULL) {
+ dst = mempcpy(dst, src, end - src);
+ dst = mempcpy(dst, repl, repl_len);
+ /*src = end + 1; - GNU findutils 4.5.10 doesn't do this... */
+ src = end + sub_len; /* but this. Try "xargs -Iaa echo aaa" */
+ }
+ strcpy(dst, src);
+ //dbg_msg("subst9:'%s'", buf);
+ return buf;
+}
diff --git a/release/src/router/busybox/libbb/rtc.c b/release/src/router/busybox/libbb/rtc.c
index 97455e86ae..c4117ba34f 100644
--- a/release/src/router/busybox/libbb/rtc.c
+++ b/release/src/router/busybox/libbb/rtc.c
@@ -22,7 +22,7 @@ int FAST_FUNC rtc_adjtime_is_utc(void)
char buffer[128];
while (fgets(buffer, sizeof(buffer), f)) {
- if (strncmp(buffer, "UTC", 3) == 0) {
+ if (is_prefixed_with(buffer, "UTC")) {
utc = 1;
break;
}
@@ -33,23 +33,55 @@ int FAST_FUNC rtc_adjtime_is_utc(void)
return utc;
}
+/* rtc opens are exclusive.
+ * Try to run two "hwclock -w" at the same time to see it.
+ * Users wouldn't expect that to fail merely because /dev/rtc
+ * was momentarily busy, let's try a bit harder on errno == EBUSY.
+ */
+static int open_loop_on_busy(const char *name, int flags)
+{
+ int rtc;
+ /*
+ * Tested with two parallel "hwclock -w" loops.
+ * With try = 10, no failures with 2x1000000 loop iterations.
+ */
+ int try = 1000 / 20;
+ again:
+ errno = 0;
+ rtc = open(name, flags);
+ if (errno == EBUSY) {
+ usleep(20 * 1000);
+ if (--try != 0)
+ goto again;
+ /* EBUSY. Last try, exit on error instead of returning -1 */
+ return xopen(name, flags);
+ }
+ return rtc;
+}
+
+/* Never fails */
int FAST_FUNC rtc_xopen(const char **default_rtc, int flags)
{
int rtc;
+ const char *name =
+ "/dev/rtc""\0"
+ "/dev/rtc0""\0"
+ "/dev/misc/rtc""\0";
- if (!*default_rtc) {
- *default_rtc = "/dev/rtc";
- rtc = open(*default_rtc, flags);
- if (rtc >= 0)
- return rtc;
- *default_rtc = "/dev/rtc0";
- rtc = open(*default_rtc, flags);
+ if (!*default_rtc)
+ goto try_name;
+ name = ""; /*else: we have rtc name, don't try other names */
+
+ for (;;) {
+ rtc = open_loop_on_busy(*default_rtc, flags);
if (rtc >= 0)
return rtc;
- *default_rtc = "/dev/misc/rtc";
+ if (!name[0])
+ return xopen(*default_rtc, flags);
+ try_name:
+ *default_rtc = name;
+ name += strlen(name) + 1;
}
-
- return xopen(*default_rtc, flags);
}
void FAST_FUNC rtc_read_tm(struct tm *ptm, int fd)
diff --git a/release/src/router/busybox/libbb/selinux_common.c b/release/src/router/busybox/libbb/selinux_common.c
index 62910e2856..c2585557f2 100644
--- a/release/src/router/busybox/libbb/selinux_common.c
+++ b/release/src/router/busybox/libbb/selinux_common.c
@@ -10,7 +10,7 @@
#include <selinux/context.h>
context_t FAST_FUNC set_security_context_component(security_context_t cur_context,
- char *user, char *role, char *type, char *range)
+ char *user, char *role, char *type, char *range)
{
context_t con = context_new(cur_context);
if (!con)
diff --git a/release/src/router/busybox/libbb/setup_environment.c b/release/src/router/busybox/libbb/setup_environment.c
index 73229ca6ce..4258656fea 100644
--- a/release/src/router/busybox/libbb/setup_environment.c
+++ b/release/src/router/busybox/libbb/setup_environment.c
@@ -37,9 +37,11 @@ void FAST_FUNC setup_environment(const char *shell, int flags, const struct pass
/* Change the current working directory to be the home directory
* of the user */
- if (chdir(pw->pw_dir)) {
- xchdir((flags & SETUP_ENV_TO_TMP) ? "/tmp" : "/");
- bb_error_msg("can't chdir to home directory '%s'", pw->pw_dir);
+ if (!(flags & SETUP_ENV_NO_CHDIR)) {
+ if (chdir(pw->pw_dir) != 0) {
+ bb_error_msg("can't change directory to '%s'", pw->pw_dir);
+ xchdir((flags & SETUP_ENV_TO_TMP) ? "/tmp" : "/");
+ }
}
if (flags & SETUP_ENV_CLEARENV) {
diff --git a/release/src/router/busybox/libbb/signals.c b/release/src/router/busybox/libbb/signals.c
index cdc37b1ef2..56512473a2 100644
--- a/release/src/router/busybox/libbb/signals.c
+++ b/release/src/router/busybox/libbb/signals.c
@@ -39,7 +39,7 @@ void FAST_FUNC bb_signals(int sigs, void (*f)(int))
while (sigs) {
if (sigs & bit) {
- sigs &= ~bit;
+ sigs -= bit;
signal(sig_no, f);
}
sig_no++;
@@ -60,7 +60,7 @@ void FAST_FUNC bb_signals_recursive_norestart(int sigs, void (*f)(int))
while (sigs) {
if (sigs & bit) {
- sigs &= ~bit;
+ sigs -= bit;
sigaction_set(sig_no, &sa);
}
sig_no++;
@@ -97,7 +97,7 @@ void FAST_FUNC kill_myself_with_sig(int sig)
signal(sig, SIG_DFL);
sig_unblock(sig);
raise(sig);
- _exit(EXIT_FAILURE); /* Should not reach it */
+ _exit(sig | 128); /* Should not reach it */
}
void FAST_FUNC signal_SA_RESTART_empty_mask(int sig, void (*handler)(int))
diff --git a/release/src/router/busybox/libbb/skip_whitespace.c b/release/src/router/busybox/libbb/skip_whitespace.c
index 8c7b674c3e..b6cfbba4dc 100644
--- a/release/src/router/busybox/libbb/skip_whitespace.c
+++ b/release/src/router/busybox/libbb/skip_whitespace.c
@@ -33,7 +33,7 @@ char* FAST_FUNC skip_non_whitespace(const char *s)
char* FAST_FUNC skip_dev_pfx(const char *tty_name)
{
- if (strncmp(tty_name, "/dev/", 5) == 0)
+ if (is_prefixed_with(tty_name, "/dev/"))
tty_name += 5;
return (char*)tty_name;
}
diff --git a/release/src/router/busybox/libbb/speed_table.c b/release/src/router/busybox/libbb/speed_table.c
index 45159f1f3b..174d531b27 100644
--- a/release/src/router/busybox/libbb/speed_table.c
+++ b/release/src/router/busybox/libbb/speed_table.c
@@ -10,7 +10,12 @@
#include "libbb.h"
struct speed_map {
+#if defined __FreeBSD__
+ /* On FreeBSD, B<num> constants don't fit into a short */
+ unsigned speed;
+#else
unsigned short speed;
+#endif
unsigned short value;
};
diff --git a/release/src/router/busybox/libbb/strrstr.c b/release/src/router/busybox/libbb/strrstr.c
index d8823fc511..93d970a1b1 100644
--- a/release/src/router/busybox/libbb/strrstr.c
+++ b/release/src/router/busybox/libbb/strrstr.c
@@ -7,13 +7,7 @@
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
-#ifdef __DO_STRRSTR_TEST
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#else
#include "libbb.h"
-#endif
/*
* The strrstr() function finds the last occurrence of the substring needle
@@ -34,8 +28,9 @@ char* FAST_FUNC strrstr(const char *haystack, const char *needle)
}
}
-#ifdef __DO_STRRSTR_TEST
-int main(int argc, char **argv)
+#if ENABLE_UNIT_TEST
+
+BBUNIT_DEFINE_TEST(strrstr)
{
static const struct {
const char *h, *n;
@@ -59,13 +54,13 @@ int main(int argc, char **argv)
i = 0;
while (i < sizeof(test_array) / sizeof(test_array[0])) {
const char *r = strrstr(test_array[i].h, test_array[i].n);
- printf("'%s' vs. '%s': '%s' - ", test_array[i].h, test_array[i].n, r);
if (r == NULL)
r = test_array[i].h - 1;
- printf("%s\n", r == test_array[i].h + test_array[i].pos ? "PASSED" : "FAILED");
+ BBUNIT_ASSERT_EQ(r, test_array[i].h + test_array[i].pos);
i++;
}
- return 0;
+ BBUNIT_ENDTEST;
}
-#endif
+
+#endif /* ENABLE_UNIT_TEST */
diff --git a/release/src/router/busybox/libbb/sysconf.c b/release/src/router/busybox/libbb/sysconf.c
new file mode 100644
index 0000000000..8c1caef5cd
--- /dev/null
+++ b/release/src/router/busybox/libbb/sysconf.c
@@ -0,0 +1,30 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Various system configuration helpers.
+ *
+ * Copyright (C) 2014 Bartosz Golaszewski <bartekgola@gmail.com>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+#include "libbb.h"
+
+#if !defined(bb_arg_max)
+unsigned FAST_FUNC bb_arg_max(void)
+{
+ long r = sysconf(_SC_ARG_MAX);
+
+ /* I've seen a version of uclibc which returned -1.
+ * Guard about it, and also avoid insanely large values
+ */
+ if ((unsigned long)r > 64*1024*1024)
+ r = 64*1024*1024;
+
+ return r;
+}
+#endif
+
+/* Return the number of clock ticks per second. */
+unsigned FAST_FUNC bb_clk_tck(void)
+{
+ return sysconf(_SC_CLK_TCK);
+}
diff --git a/release/src/router/busybox/libbb/systemd_support.c b/release/src/router/busybox/libbb/systemd_support.c
deleted file mode 100644
index 542a3efffc..0000000000
--- a/release/src/router/busybox/libbb/systemd_support.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2011 Davide Cavalca <davide@geexbox.org>
- *
- * Based on http://cgit.freedesktop.org/systemd/tree/src/sd-daemon.c
- * Copyright 2010 Lennart Poettering
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#include "libbb.h"
-
-//config:config FEATURE_SYSTEMD
-//config: bool "Enable systemd support"
-//config: default y
-//config: help
-//config: If you plan to use busybox daemons on a system where daemons
-//config: are controlled by systemd, enable this option.
-//config: If you don't use systemd, it is still safe to enable it,
-//config: but the downside is increased code size.
-
-//kbuild:lib-$(CONFIG_FEATURE_SYSTEMD) += systemd_support.o
-
-int sd_listen_fds(void)
-{
- const char *e;
- int n;
- int fd;
-
- e = getenv("LISTEN_PID");
- if (!e)
- return 0;
- n = xatoi_positive(e);
- /* Is this for us? */
- if (getpid() != (pid_t) n)
- return 0;
-
- e = getenv("LISTEN_FDS");
- if (!e)
- return 0;
- n = xatoi_positive(e);
- for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++)
- close_on_exec_on(fd);
-
- return n;
-}
diff --git a/release/src/router/busybox/libbb/time.c b/release/src/router/busybox/libbb/time.c
index e2b9384713..82e6cb172d 100644
--- a/release/src/router/busybox/libbb/time.c
+++ b/release/src/router/busybox/libbb/time.c
@@ -23,14 +23,16 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm)
if (sscanf(date_str, "%u:%u%c",
&ptm->tm_hour,
&ptm->tm_min,
- &end) >= 2) {
+ &end) >= 2
+ ) {
/* no adjustments needed */
} else
/* mm.dd-HH:MM */
if (sscanf(date_str, "%u.%u-%u:%u%c",
&ptm->tm_mon, &ptm->tm_mday,
&ptm->tm_hour, &ptm->tm_min,
- &end) >= 4) {
+ &end) >= 4
+ ) {
/* Adjust month from 1-12 to 0-11 */
ptm->tm_mon -= 1;
} else
@@ -38,15 +40,13 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm)
if (sscanf(date_str, "%u.%u.%u-%u:%u%c", &ptm->tm_year,
&ptm->tm_mon, &ptm->tm_mday,
&ptm->tm_hour, &ptm->tm_min,
- &end) >= 5) {
- ptm->tm_year -= 1900; /* Adjust years */
- ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */
- } else
+ &end) >= 5
/* yyyy-mm-dd HH:MM */
- if (sscanf(date_str, "%u-%u-%u %u:%u%c", &ptm->tm_year,
+ || sscanf(date_str, "%u-%u-%u %u:%u%c", &ptm->tm_year,
&ptm->tm_mon, &ptm->tm_mday,
&ptm->tm_hour, &ptm->tm_min,
- &end) >= 5) {
+ &end) >= 5
+ ) {
ptm->tm_year -= 1900; /* Adjust years */
ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */
} else
@@ -58,7 +58,6 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm)
return; /* don't fall through to end == ":" check */
} else
#endif
-//TODO: coreutils 6.9 also accepts "yyyy-mm-dd HH" (no minutes)
{
bb_error_msg_and_die(bb_msg_invalid_date, date_str);
}
@@ -68,7 +67,29 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm)
end = '\0';
/* else end != NUL and we error out */
}
- } else if (date_str[0] == '@') {
+ } else
+ if (strchr(date_str, '-')
+ /* Why strchr('-') check?
+ * sscanf below will trash ptm->tm_year, this breaks
+ * if parse_str is "10101010" (iow, "MMddhhmm" form)
+ * because we destroy year. Do these sscanf
+ * only if we saw a dash in parse_str.
+ */
+ /* yyyy-mm-dd HH */
+ && (sscanf(date_str, "%u-%u-%u %u%c", &ptm->tm_year,
+ &ptm->tm_mon, &ptm->tm_mday,
+ &ptm->tm_hour,
+ &end) >= 4
+ /* yyyy-mm-dd */
+ || sscanf(date_str, "%u-%u-%u%c", &ptm->tm_year,
+ &ptm->tm_mon, &ptm->tm_mday,
+ &end) >= 3
+ )
+ ) {
+ ptm->tm_year -= 1900; /* Adjust years */
+ ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */
+ } else
+ if (date_str[0] == '@') {
time_t t = bb_strtol(date_str + 1, NULL, 10);
if (!errno) {
struct tm *lt = localtime(&t);
@@ -165,6 +186,7 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm)
} else {
bb_error_msg_and_die(bb_msg_invalid_date, date_str);
}
+ ptm->tm_sec = 0; /* assume zero if [.SS] is not given */
if (end == '.') {
/* xxx.SS */
if (sscanf(strchr(date_str, '.') + 1, "%u%c",
@@ -187,6 +209,27 @@ time_t FAST_FUNC validate_tm_time(const char *date_str, struct tm *ptm)
return t;
}
+static char* strftime_fmt(char *buf, unsigned len, time_t *tp, const char *fmt)
+{
+ time_t t;
+ if (!tp) {
+ tp = &t;
+ time(tp);
+ }
+ /* Returns pointer to NUL */
+ return buf + strftime(buf, len, fmt, localtime(tp));
+}
+
+char* FAST_FUNC strftime_HHMMSS(char *buf, unsigned len, time_t *tp)
+{
+ return strftime_fmt(buf, len, tp, "%H:%M:%S");
+}
+
+char* FAST_FUNC strftime_YYYYMMDDHHMMSS(char *buf, unsigned len, time_t *tp)
+{
+ return strftime_fmt(buf, len, tp, "%Y-%m-%d %H:%M:%S");
+}
+
#if ENABLE_MONOTONIC_SYSCALL
#include <sys/syscall.h>
diff --git a/release/src/router/busybox/libbb/u_signal_names.c b/release/src/router/busybox/libbb/u_signal_names.c
index 8c78f5e20c..b49714f2a6 100644
--- a/release/src/router/busybox/libbb/u_signal_names.c
+++ b/release/src/router/busybox/libbb/u_signal_names.c
@@ -19,7 +19,7 @@
/* Believe it or not, but some arches have more than 32 SIGs!
* HPPA: SIGSTKFLT == 36. */
-static const char signals[][7] = {
+static const char signals[][7] ALIGN1 = {
// SUSv3 says kill must support these, and specifies the numerical values,
// http://www.opengroup.org/onlinepubs/009695399/utilities/kill.html
// {0, "EXIT"}, {1, "HUP"}, {2, "INT"}, {3, "QUIT"},
diff --git a/release/src/router/busybox/libbb/ubi.c b/release/src/router/busybox/libbb/ubi.c
new file mode 100644
index 0000000000..34595d7979
--- /dev/null
+++ b/release/src/router/busybox/libbb/ubi.c
@@ -0,0 +1,43 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 2016 Denys Vlasenko
+ *
+ * Licensed under GPLv2, see file LICENSE in this source tree.
+ */
+//kbuild:lib-y += ubi.o
+
+#include "libbb.h"
+
+// from ubi-media.h
+#define UBI_MAX_VOLUME_NAME 127
+#define UBI_MAX_VOLUMES 128
+
+unsigned FAST_FUNC ubi_devnum_from_devname(const char *str)
+{
+ unsigned ubi_devnum;
+
+ if (sscanf(str, "/dev/ubi%u", &ubi_devnum) != 1)
+ bb_error_msg_and_die("not an UBI device: '%s'", str);
+ return ubi_devnum;
+}
+
+int FAST_FUNC ubi_get_volid_by_name(unsigned ubi_devnum, const char *vol_name)
+{
+ unsigned i;
+
+ for (i = 0; i < UBI_MAX_VOLUMES; i++) {
+ char buf[UBI_MAX_VOLUME_NAME + 1];
+ char fname[sizeof("/sys/class/ubi/ubi%u_%u/name") + 2 * sizeof(int)*3];
+
+ sprintf(fname, "/sys/class/ubi/ubi%u_%u/name", ubi_devnum, i);
+ if (open_read_close(fname, buf, sizeof(buf)) <= 0)
+ continue;
+
+ strchrnul(buf, '\n')[0] = '\0';
+ if (strcmp(vol_name, buf) == 0)
+ return i;
+ }
+ bb_error_msg_and_die("volume '%s' not found", vol_name);
+}
diff --git a/release/src/router/busybox/libbb/udp_io.c b/release/src/router/busybox/libbb/udp_io.c
index c2bdb7ced9..8d1c9333c5 100644
--- a/release/src/router/busybox/libbb/udp_io.c
+++ b/release/src/router/busybox/libbb/udp_io.c
@@ -16,14 +16,16 @@ void FAST_FUNC
socket_want_pktinfo(int fd UNUSED_PARAM)
{
#ifdef IP_PKTINFO
- setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &const_int_1, sizeof(int));
+ setsockopt_1(fd, IPPROTO_IP, IP_PKTINFO);
#endif
-#if ENABLE_FEATURE_IPV6
+#if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO)
# ifdef IPV6_RECVPKTINFO
- setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &const_int_1, sizeof(int));
- setsockopt(fd, IPPROTO_IPV6, IPV6_2292PKTINFO, &const_int_1, sizeof(int));
-# elif defined(IPV6_PKTINFO)
- setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &const_int_1, sizeof(int));
+ setsockopt_1(fd, SOL_IPV6, IPV6_RECVPKTINFO);
+# ifdef IPV6_2292PKTINFO
+ setsockopt_1(fd, SOL_IPV6, IPV6_2292PKTINFO);
+# endif
+# else
+ setsockopt_1(fd, IPPROTO_IPV6, IPV6_PKTINFO);
# endif
#endif
}
@@ -168,16 +170,18 @@ recv_from_to(int fd, void *buf, size_t len, int flags,
# if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO)
if (cmsgptr->cmsg_level == IPPROTO_IPV6
&& (cmsgptr->cmsg_type == IPV6_PKTINFO
-#if defined(IPV6_2292PKTINFO) && defined(IPV6_RECVPKTINFO)
- || cmsgptr->cmsg_type == IPV6_2292PKTINFO
-#endif
+# if defined(IPV6_RECVPKTINFO) && defined(IPV6_2292PKTINFO)
+ || cmsgptr->cmsg_type == IPV6_2292PKTINFO
+# endif
)) {
const int IPI6_ADDR_OFF = offsetof(struct in6_pktinfo, ipi6_addr);
+ const int IPI6_IFINDEX_OFF = offsetof(struct in6_pktinfo, ipi6_ifindex);
to->sa_family = AF_INET6;
/*# define pktinfo(cmsgptr) ( (struct in6_pktinfo*)(CMSG_DATA(cmsgptr)) )*/
/*to6->sin6_addr = pktinfo(cmsgptr)->ipi6_addr; - may be unaligned */
memcpy(&to6->sin6_addr, (char*)(CMSG_DATA(cmsgptr)) + IPI6_ADDR_OFF, sizeof(to6->sin6_addr));
/*to6->sin6_port = 123; */
+ move_from_unaligned_int(to6->sin6_scope_id, (char*)(CMSG_DATA(cmsgptr)) + IPI6_IFINDEX_OFF);
break;
}
# endif
diff --git a/release/src/router/busybox/libbb/unicode.c b/release/src/router/busybox/libbb/unicode.c
index 99dc1dfa6a..9c4da50d3b 100644
--- a/release/src/router/busybox/libbb/unicode.c
+++ b/release/src/router/busybox/libbb/unicode.c
@@ -28,19 +28,37 @@ void FAST_FUNC reinit_unicode(const char *LANG)
static const char unicode_0x394[] = { 0xce, 0x94, 0 };
size_t width;
+ /* We pass "" instead of "C" because some libc's have
+ * non-ASCII default locale for setlocale("") call
+ * (this allows users of such libc to have Unicoded
+ * system without having to mess with env).
+ *
+ * We set LC_CTYPE because (a) we may be called with $LC_CTYPE
+ * value in LANG, not with $LC_ALL, (b) internationalized
+ * LC_NUMERIC and LC_TIME are more PITA than benefit
+ * (for one, some utilities have hard time with comma
+ * used as a fractional separator).
+ */
//TODO: avoid repeated calls by caching last string?
- setlocale(LC_ALL, (LANG && LANG[0]) ? LANG : "C");
+ setlocale(LC_CTYPE, LANG ? LANG : "");
/* In unicode, this is a one character string */
-// can use unicode_strlen(string) too, but otherwise unicode_strlen() is unused
- width = mbstowcs(NULL, unicode_0x394, INT_MAX);
+ width = unicode_strlen(unicode_0x394);
unicode_status = (width == 1 ? UNICODE_ON : UNICODE_OFF);
}
void FAST_FUNC init_unicode(void)
{
- if (unicode_status == UNICODE_UNKNOWN)
- reinit_unicode(getenv("LANG"));
+ /* Some people set only $LC_CTYPE, not $LC_ALL, because they want
+ * only Unicode to be activated on their system, not the whole
+ * shebang of wrong decimal points, strange date formats and so on.
+ */
+ if (unicode_status == UNICODE_UNKNOWN) {
+ char *s = getenv("LC_ALL");
+ if (!s) s = getenv("LC_CTYPE");
+ if (!s) s = getenv("LANG");
+ reinit_unicode(s);
+ }
}
#else
@@ -58,8 +76,12 @@ void FAST_FUNC reinit_unicode(const char *LANG)
void FAST_FUNC init_unicode(void)
{
- if (unicode_status == UNICODE_UNKNOWN)
- reinit_unicode(getenv("LANG"));
+ if (unicode_status == UNICODE_UNKNOWN) {
+ char *s = getenv("LC_ALL");
+ if (!s) s = getenv("LC_CTYPE");
+ if (!s) s = getenv("LANG");
+ reinit_unicode(s);
+ }
}
# endif
@@ -963,7 +985,6 @@ int FAST_FUNC unicode_bidi_is_neutral_wchar(wint_t wc)
/* The rest is mostly same for libc and for "homegrown" support */
-#if 0 // UNUSED
size_t FAST_FUNC unicode_strlen(const char *string)
{
size_t width = mbstowcs(NULL, string, INT_MAX);
@@ -971,7 +992,6 @@ size_t FAST_FUNC unicode_strlen(const char *string)
return strlen(string);
return width;
}
-#endif
size_t FAST_FUNC unicode_strwidth(const char *string)
{
diff --git a/release/src/router/busybox/libbb/update_passwd.c b/release/src/router/busybox/libbb/update_passwd.c
index a30af6f723..a2004f480c 100644
--- a/release/src/router/busybox/libbb/update_passwd.c
+++ b/release/src/router/busybox/libbb/update_passwd.c
@@ -62,6 +62,8 @@ static void check_selinux_update_passwd(const char *username)
only if CONFIG_PASSWD=y and applet_name[0] == 'p' like in passwd
or if CONFIG_CHPASSWD=y and applet_name[0] == 'c' like in chpasswd
+ 8) delete a user from all groups: update_passwd(FILE, NULL, NULL, MEMBER)
+
This function does not validate the arguments fed to it
so the calling program should take care of that.
@@ -82,7 +84,6 @@ int FAST_FUNC update_passwd(const char *filename,
char *fnamesfx;
char *sfx_char;
char *name_colon;
- unsigned user_len;
int old_fd;
int new_fd;
int i;
@@ -99,13 +100,13 @@ int FAST_FUNC update_passwd(const char *filename,
if (filename == NULL)
return ret;
- check_selinux_update_passwd(name);
+ if (name)
+ check_selinux_update_passwd(name);
/* New passwd file, "/etc/passwd+" for now */
fnamesfx = xasprintf("%s+", filename);
sfx_char = &fnamesfx[strlen(fnamesfx)-1];
- name_colon = xasprintf("%s:", name);
- user_len = strlen(name_colon);
+ name_colon = xasprintf("%s:", name ? name : "");
if (shadow)
old_fp = fopen(filename, "r+");
@@ -167,13 +168,45 @@ int FAST_FUNC update_passwd(const char *filename,
line = xmalloc_fgetline(old_fp);
if (!line) /* EOF/error */
break;
- if (strncmp(name_colon, line, user_len) != 0) {
+
+ if (!name && member) {
+ /* Delete member from all groups */
+ /* line is "GROUP:PASSWD:[member1[,member2]...]" */
+ unsigned member_len = strlen(member);
+ char *list = strrchr(line, ':');
+ while (list) {
+ list++;
+ next_list_element:
+ if (is_prefixed_with(list, member)) {
+ char c;
+ changed_lines++;
+ c = list[member_len];
+ if (c == '\0') {
+ if (list[-1] == ',')
+ list--;
+ *list = '\0';
+ break;
+ }
+ if (c == ',') {
+ overlapping_strcpy(list, list + member_len + 1);
+ goto next_list_element;
+ }
+ changed_lines--;
+ }
+ list = strchr(list, ',');
+ }
+ fprintf(new_fp, "%s\n", line);
+ goto next;
+ }
+
+ cp = is_prefixed_with(line, name_colon);
+ if (!cp) {
fprintf(new_fp, "%s\n", line);
goto next;
}
/* We have a match with "name:"... */
- cp = line + user_len; /* move past name: */
+ /* cp points past "name:" */
#if ENABLE_FEATURE_ADDUSER_TO_GROUP || ENABLE_FEATURE_DEL_USER_FROM_GROUP
if (member) {
diff --git a/release/src/router/busybox/libbb/utmp.c b/release/src/router/busybox/libbb/utmp.c
index 09443fb6c4..bd07670dba 100644
--- a/release/src/router/busybox/libbb/utmp.c
+++ b/release/src/router/busybox/libbb/utmp.c
@@ -16,7 +16,7 @@ static void touch(const char *filename)
void FAST_FUNC write_new_utmp(pid_t pid, int new_type, const char *tty_name, const char *username, const char *hostname)
{
- struct utmp utent;
+ struct utmpx utent;
char *id;
unsigned width;
@@ -45,17 +45,17 @@ void FAST_FUNC write_new_utmp(pid_t pid, int new_type, const char *tty_name, con
tty_name += 3;
strncpy(id, tty_name, width);
- touch(_PATH_UTMP);
- //utmpname(_PATH_UTMP);
- setutent();
+ touch(_PATH_UTMPX);
+ //utmpxname(_PATH_UTMPX);
+ setutxent();
/* Append new one (hopefully, unless we collide on ut_id) */
- pututline(&utent);
- endutent();
+ pututxline(&utent);
+ endutxent();
#if ENABLE_FEATURE_WTMP
/* "man utmp" says wtmp file should *not* be created automagically */
/*touch(bb_path_wtmp_file);*/
- updwtmp(bb_path_wtmp_file, &utent);
+ updwtmpx(bb_path_wtmp_file, &utent);
#endif
}
@@ -64,17 +64,17 @@ void FAST_FUNC write_new_utmp(pid_t pid, int new_type, const char *tty_name, con
*/
void FAST_FUNC update_utmp(pid_t pid, int new_type, const char *tty_name, const char *username, const char *hostname)
{
- struct utmp utent;
- struct utmp *utp;
+ struct utmpx utent;
+ struct utmpx *utp;
- touch(_PATH_UTMP);
- //utmpname(_PATH_UTMP);
- setutent();
+ touch(_PATH_UTMPX);
+ //utmpxname(_PATH_UTMPX);
+ setutxent();
/* Did init/getty/telnetd/sshd/... create an entry for us?
* It should be (new_type-1), but we'd also reuse
* any other potentially stale xxx_PROCESS entry */
- while ((utp = getutent()) != NULL) {
+ while ((utp = getutxent()) != NULL) {
if (utp->ut_pid == pid
// && ut->ut_line[0]
&& utp->ut_id[0] /* must have nonzero id */
@@ -88,25 +88,25 @@ void FAST_FUNC update_utmp(pid_t pid, int new_type, const char *tty_name, const
/* Stale record. Nuke hostname */
memset(utp->ut_host, 0, sizeof(utp->ut_host));
}
- /* NB: pututline (see later) searches for matching utent
- * using getutid(utent) - we must not change ut_id
+ /* NB: pututxline (see later) searches for matching utxent
+ * using getutxid(utent) - we must not change ut_id
* if we want *exactly this* record to be overwritten!
*/
break;
}
}
- //endutent(); - no need, pututline can deal with (and actually likes)
+ //endutxent(); - no need, pututxline can deal with (and actually likes)
//the situation when utmp file is positioned on found record
if (!utp) {
if (new_type != DEAD_PROCESS)
write_new_utmp(pid, new_type, tty_name, username, hostname);
else
- endutent();
+ endutxent();
return;
}
- /* Make a copy. We can't use *utp, pututline's internal getutid
+ /* Make a copy. We can't use *utp, pututxline's internal getutxid
* will overwrite it before it is used! */
utent = *utp;
@@ -120,13 +120,27 @@ void FAST_FUNC update_utmp(pid_t pid, int new_type, const char *tty_name, const
utent.ut_tv.tv_sec = time(NULL);
/* Update, or append new one */
- //setutent();
- pututline(&utent);
- endutent();
+ //setutxent();
+ pututxline(&utent);
+ endutxent();
#if ENABLE_FEATURE_WTMP
/* "man utmp" says wtmp file should *not* be created automagically */
/*touch(bb_path_wtmp_file);*/
- updwtmp(bb_path_wtmp_file, &utent);
+ updwtmpx(bb_path_wtmp_file, &utent);
#endif
}
+
+/* man utmp:
+ * When init(8) finds that a process has exited, it locates its utmp entry
+ * by ut_pid, sets ut_type to DEAD_PROCESS, and clears ut_user, ut_host
+ * and ut_time with null bytes.
+ * [same applies to other processes which maintain utmp entries, like telnetd]
+ *
+ * We do not bother actually clearing fields:
+ * it might be interesting to know who was logged in and from where
+ */
+void FAST_FUNC update_utmp_DEAD_PROCESS(pid_t pid)
+{
+ update_utmp(pid, DEAD_PROCESS, NULL, NULL, NULL);
+}
diff --git a/release/src/router/busybox/libbb/verror_msg.c b/release/src/router/busybox/libbb/verror_msg.c
index ee95be3e3a..22c30357b2 100644
--- a/release/src/router/busybox/libbb/verror_msg.c
+++ b/release/src/router/busybox/libbb/verror_msg.c
@@ -11,12 +11,16 @@
# include <syslog.h>
#endif
+#if ENABLE_FEATURE_SYSLOG
+smallint syslog_level = LOG_ERR;
+#endif
smallint logmode = LOGMODE_STDIO;
const char *msg_eol = "\n";
void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr)
{
char *msg, *msg1;
+ char stack_msg[80];
int applet_len, strerr_len, msgeol_len, used;
if (!logmode)
@@ -25,6 +29,27 @@ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr)
if (!s) /* nomsg[_and_die] uses NULL fmt */
s = ""; /* some libc don't like printf(NULL) */
+ applet_len = strlen(applet_name) + 2; /* "applet: " */
+ strerr_len = strerr ? strlen(strerr) : 0;
+ msgeol_len = strlen(msg_eol);
+
+ /* This costs ~90 bytes of code, but avoids costly
+ * malloc()[in vasprintf]+realloc()+memmove()+free() in 99% of cases.
+ * ~40% speedup.
+ */
+ if ((int)sizeof(stack_msg) - applet_len > 0) {
+ va_list p2;
+
+ /* It is not portable to use va_list twice, need to va_copy it */
+ va_copy(p2, p);
+ used = vsnprintf(stack_msg + applet_len, (int)sizeof(stack_msg) - applet_len, s, p2);
+ va_end(p2);
+ msg = stack_msg;
+ used += applet_len;
+ if (used < (int)sizeof(stack_msg) - 3 - msgeol_len - strerr_len)
+ goto add_pfx_and_sfx;
+ }
+
used = vasprintf(&msg, s, p);
if (used < 0)
return;
@@ -34,9 +59,6 @@ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr)
* This is needed for e.g. httpd logging, when multiple
* children can produce log messages simultaneously. */
- applet_len = strlen(applet_name) + 2; /* "applet: " */
- strerr_len = strerr ? strlen(strerr) : 0;
- msgeol_len = strlen(msg_eol);
/* can't use xrealloc: it calls error_msg on failure,
* that may result in a recursion */
/* +3 is for ": " before strerr and for terminating NUL */
@@ -49,6 +71,7 @@ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr)
/* TODO: maybe use writev instead of memmoving? Need full_writev? */
memmove(msg + applet_len, msg, used);
used += applet_len;
+ add_pfx_and_sfx:
strcpy(msg, applet_name);
msg[applet_len - 2] = ':';
msg[applet_len - 1] = ' ';
@@ -70,10 +93,11 @@ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr)
}
#if ENABLE_FEATURE_SYSLOG
if (logmode & LOGMODE_SYSLOG) {
- syslog(LOG_ERR, "%s", msg + applet_len);
+ syslog(syslog_level, "%s", msg + applet_len);
}
#endif
- free(msg);
+ if (msg != stack_msg)
+ free(msg);
}
#ifdef VERSION_WITH_WRITEV
diff --git a/release/src/router/busybox/libbb/vfork_daemon_rexec.c b/release/src/router/busybox/libbb/vfork_daemon_rexec.c
index ed1f86f0c5..1adb5b3c41 100644
--- a/release/src/router/busybox/libbb/vfork_daemon_rexec.c
+++ b/release/src/router/busybox/libbb/vfork_daemon_rexec.c
@@ -69,28 +69,44 @@ pid_t FAST_FUNC xspawn(char **argv)
}
#if ENABLE_FEATURE_PREFER_APPLETS
+static jmp_buf die_jmp;
+static void jump(void)
+{
+ /* Special case. We arrive here if NOFORK applet
+ * calls xfunc, which then decides to die.
+ * We don't die, but jump instead back to caller.
+ * NOFORK applets still cannot carelessly call xfuncs:
+ * p = xmalloc(10);
+ * q = xmalloc(10); // BUG! if this dies, we leak p!
+ */
+ /* | 0x100 allows to pass zero exitcode (longjmp can't pass 0).
+ * This works because exitcodes are bytes,
+ * run_nofork_applet() ensures that by "& 0xff" */
+ longjmp(die_jmp, xfunc_error_retval | 0x100);
+}
+
struct nofork_save_area {
jmp_buf die_jmp;
+ void (*die_func)(void);
const char *applet_name;
uint32_t option_mask32;
- int die_sleep;
uint8_t xfunc_error_retval;
};
static void save_nofork_data(struct nofork_save_area *save)
{
memcpy(&save->die_jmp, &die_jmp, sizeof(die_jmp));
+ save->die_func = die_func;
save->applet_name = applet_name;
- save->xfunc_error_retval = xfunc_error_retval;
save->option_mask32 = option_mask32;
- save->die_sleep = die_sleep;
+ save->xfunc_error_retval = xfunc_error_retval;
}
static void restore_nofork_data(struct nofork_save_area *save)
{
memcpy(&die_jmp, &save->die_jmp, sizeof(die_jmp));
+ die_func = save->die_func;
applet_name = save->applet_name;
- xfunc_error_retval = save->xfunc_error_retval;
option_mask32 = save->option_mask32;
- die_sleep = save->die_sleep;
+ xfunc_error_retval = save->xfunc_error_retval;
}
int FAST_FUNC run_nofork_applet(int applet_no, char **argv)
@@ -100,8 +116,6 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv)
save_nofork_data(&old);
- applet_name = APPLET_NAME(applet_no);
-
xfunc_error_retval = EXIT_FAILURE;
/* In case getopt() or getopt32() was already called:
@@ -133,23 +147,19 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv)
while (argv[argc])
argc++;
- /* Special flag for xfunc_die(). If xfunc will "die"
- * in NOFORK applet, xfunc_die() sees negative
- * die_sleep and longjmp here instead. */
- die_sleep = -1;
-
+ /* If xfunc "dies" in NOFORK applet, die_func longjmp's here instead */
+ die_func = jump;
rc = setjmp(die_jmp);
if (!rc) {
/* Some callers (xargs)
* need argv untouched because they free argv[i]! */
char *tmp_argv[argc+1];
memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0]));
+ applet_name = tmp_argv[0];
/* Finally we can call NOFORK applet's main() */
rc = applet_main[applet_no](argc, tmp_argv);
- } else { /* xfunc died in NOFORK applet */
- /* in case they meant to return 0... */
- if (rc == -2222)
- rc = 0;
+ } else {
+ /* xfunc died in NOFORK applet */
}
/* Restoring some globals */
diff --git a/release/src/router/busybox/libbb/xatonum.c b/release/src/router/busybox/libbb/xatonum.c
index 62bbe53e71..9dd5c3e7e6 100644
--- a/release/src/router/busybox/libbb/xatonum.c
+++ b/release/src/router/busybox/libbb/xatonum.c
@@ -68,3 +68,31 @@ uint16_t FAST_FUNC xatou16(const char *numstr)
{
return xatou_range(numstr, 0, 0xffff);
}
+
+const struct suffix_mult bkm_suffixes[] = {
+ { "b", 512 },
+ { "k", 1024 },
+ { "m", 1024*1024 },
+ { "", 0 }
+};
+
+const struct suffix_mult cwbkMG_suffixes[] = {
+ { "c", 1 },
+ { "w", 2 },
+ { "b", 512 },
+ { "kB", 1000 },
+ { "kD", 1000 },
+ { "k", 1024 },
+ { "KB", 1000 }, /* compat with coreutils dd */
+ { "KD", 1000 }, /* compat with coreutils dd */
+ { "K", 1024 }, /* compat with coreutils dd */
+ { "MB", 1000000 },
+ { "MD", 1000000 },
+ { "M", 1024*1024 },
+ { "GB", 1000000000 },
+ { "GD", 1000000000 },
+ { "G", 1024*1024*1024 },
+ /* "D" suffix for decimal is not in coreutils manpage, looks like it's deprecated */
+ /* coreutils also understands TPEZY suffixes for tera- and so on, with B suffix for decimal */
+ { "", 0 }
+};
diff --git a/release/src/router/busybox/libbb/xatonum_template.c b/release/src/router/busybox/libbb/xatonum_template.c
index 029f66202e..e0471983c9 100644
--- a/release/src/router/busybox/libbb/xatonum_template.c
+++ b/release/src/router/busybox/libbb/xatonum_template.c
@@ -59,7 +59,7 @@ unsigned type FAST_FUNC xstrtou(_range_sfx)(const char *numstr, int base,
}
/* Note: trailing space is an error.
- It would be easy enough to allow though if desired. */
+ * It would be easy enough to allow though if desired. */
if (*e)
goto inval;
chk_range:
diff --git a/release/src/router/busybox/libbb/xconnect.c b/release/src/router/busybox/libbb/xconnect.c
index 1c8bb2b730..6e78e63636 100644
--- a/release/src/router/busybox/libbb/xconnect.c
+++ b/release/src/router/busybox/libbb/xconnect.c
@@ -14,13 +14,34 @@
#include <sys/un.h>
#include "libbb.h"
+int FAST_FUNC setsockopt_int(int fd, int level, int optname, int optval)
+{
+ return setsockopt(fd, level, optname, &optval, sizeof(int));
+}
+int FAST_FUNC setsockopt_1(int fd, int level, int optname)
+{
+ return setsockopt_int(fd, level, optname, 1);
+}
+int FAST_FUNC setsockopt_SOL_SOCKET_int(int fd, int optname, int optval)
+{
+ return setsockopt_int(fd, SOL_SOCKET, optname, optval);
+}
+int FAST_FUNC setsockopt_SOL_SOCKET_1(int fd, int optname)
+{
+ return setsockopt_SOL_SOCKET_int(fd, optname, 1);
+}
+
void FAST_FUNC setsockopt_reuseaddr(int fd)
{
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &const_int_1, sizeof(const_int_1));
+ setsockopt_SOL_SOCKET_1(fd, SO_REUSEADDR);
}
int FAST_FUNC setsockopt_broadcast(int fd)
{
- return setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &const_int_1, sizeof(const_int_1));
+ return setsockopt_SOL_SOCKET_1(fd, SO_BROADCAST);
+}
+int FAST_FUNC setsockopt_keepalive(int fd)
+{
+ return setsockopt_SOL_SOCKET_1(fd, SO_KEEPALIVE);
}
#ifdef SO_BINDTODEVICE
@@ -171,7 +192,7 @@ IF_NOT_FEATURE_IPV6(sa_family_t af = AF_INET;)
const char *cp;
struct addrinfo hint;
- if (ENABLE_FEATURE_UNIX_LOCAL && strncmp(host, "local:", 6) == 0) {
+ if (ENABLE_FEATURE_UNIX_LOCAL && is_prefixed_with(host, "local:")) {
struct sockaddr_un *sun;
r = xzalloc(LSA_LEN_SIZE + sizeof(struct sockaddr_un));
diff --git a/release/src/router/busybox/libbb/xfunc_die.c b/release/src/router/busybox/libbb/xfunc_die.c
index 204e5e49da..73f7998e58 100644
--- a/release/src/router/busybox/libbb/xfunc_die.c
+++ b/release/src/router/busybox/libbb/xfunc_die.c
@@ -7,34 +7,16 @@
* Licensed under GPLv2, see file LICENSE in this source tree.
*/
-/* Keeping it separate allows to NOT suck in stdio for VERY small applets.
+/* Keeping it separate allows to NOT pull in stdio for VERY small applets.
* Try building busybox with only "true" enabled... */
#include "libbb.h"
-int die_sleep;
-#if ENABLE_FEATURE_PREFER_APPLETS || ENABLE_HUSH
-jmp_buf die_jmp;
-#endif
+void (*die_func)(void);
void FAST_FUNC xfunc_die(void)
{
- if (die_sleep) {
- if ((ENABLE_FEATURE_PREFER_APPLETS || ENABLE_HUSH)
- && die_sleep < 0
- ) {
- /* Special case. We arrive here if NOFORK applet
- * calls xfunc, which then decides to die.
- * We don't die, but jump instead back to caller.
- * NOFORK applets still cannot carelessly call xfuncs:
- * p = xmalloc(10);
- * q = xmalloc(10); // BUG! if this dies, we leak p!
- */
- /* -2222 means "zero" (longjmp can't pass 0)
- * run_nofork_applet() catches -2222. */
- longjmp(die_jmp, xfunc_error_retval ? xfunc_error_retval : -2222);
- }
- sleep(die_sleep);
- }
+ if (die_func)
+ die_func();
exit(xfunc_error_retval);
}
diff --git a/release/src/router/busybox/libbb/xfuncs.c b/release/src/router/busybox/libbb/xfuncs.c
index a55020fc9c..3f9a84ad49 100644
--- a/release/src/router/busybox/libbb/xfuncs.c
+++ b/release/src/router/busybox/libbb/xfuncs.c
@@ -25,20 +25,22 @@
#include "libbb.h"
/* Turn on nonblocking I/O on a fd */
-void FAST_FUNC ndelay_on(int fd)
+int FAST_FUNC ndelay_on(int fd)
{
int flags = fcntl(fd, F_GETFL);
if (flags & O_NONBLOCK)
- return;
+ return flags;
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+ return flags;
}
-void FAST_FUNC ndelay_off(int fd)
+int FAST_FUNC ndelay_off(int fd)
{
int flags = fcntl(fd, F_GETFL);
if (!(flags & O_NONBLOCK))
- return;
+ return flags;
fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
+ return flags;
}
void FAST_FUNC close_on_exec_on(int fd)
@@ -205,7 +207,6 @@ off_t FAST_FUNC fdlength(int fd)
else bottom = pos;
// If we can't, it's smaller.
-
} else {
if (bottom == top) {
if (!top) return 0;
@@ -269,6 +270,12 @@ int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *heigh
*width = wh_helper(win.ws_col, 80, "COLUMNS", &err);
return err;
}
+int FAST_FUNC get_terminal_width(int fd)
+{
+ unsigned width;
+ get_terminal_width_height(fd, &width, NULL);
+ return width;
+}
int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp)
{
@@ -309,48 +316,14 @@ int FAST_FUNC wait4pid(pid_t pid)
return 0;
}
-char * FAST_FUNC unparse_uuid(const uint8_t *uu, char *out)
+// Useful when we do know that pid is valid, and we just want to wait
+// for it to exit. Not existing pid is fatal. waitpid() status is not returned.
+int FAST_FUNC wait_for_exitstatus(pid_t pid)
{
- char uuid_string[32];
-
- bin2hex(uuid_string, (char*)uu, 16);
- /* f.e. UUID=dfd9c173-be52-4d27-99a5-c34c6c2ff55f */
- sprintf(out, "%.8s-%.4s-%.4s-%.4s-%.12s",
- uuid_string,
- uuid_string+8,
- uuid_string+8+4,
- uuid_string+8+4+4,
- uuid_string+8+4+4+4
- );
- return out;
-}
+ int exit_status, n;
-static unsigned char fromhex(char c)
-{
- if (isdigit(c))
- return (c - '0');
- return ((c|0x20) - 'a' + 10);
+ n = safe_waitpid(pid, &exit_status, 0);
+ if (n < 0)
+ bb_perror_msg_and_die("waitpid");
+ return exit_status;
}
-
-/* Parse & verify UUID string */
-int FAST_FUNC parse_uuid(const char *s, uint8_t *uuid)
-{
- int i;
-
- if (strlen(s) != 36 || s[8] != '-' || s[13] != '-'
- || s[18] != '-' || s[23] != '-'
- ) {
- return -1;
- }
- for (i = 0; i < 16; i++) {
- if (*s == '-')
- s++;
- if (!isxdigit(s[0]) || !isxdigit(s[1]))
- return -2;
- uuid[i] = ((fromhex(s[0]) << 4) | fromhex(s[1]));
- s += 2;
- }
-
- return 0;
-}
-
diff --git a/release/src/router/busybox/libbb/xfuncs_printf.c b/release/src/router/busybox/libbb/xfuncs_printf.c
index d8a42ba0bc..e9222f6906 100644
--- a/release/src/router/busybox/libbb/xfuncs_printf.c
+++ b/release/src/router/busybox/libbb/xfuncs_printf.c
@@ -112,6 +112,11 @@ char* FAST_FUNC xstrndup(const char *s, int n)
return memcpy(t, s, n);
}
+void* FAST_FUNC xmemdup(const void *s, int n)
+{
+ return memcpy(xmalloc(n), s, n);
+}
+
// Die if we can't open a file and return a FILE* to it.
// Notice we haven't got xfread(), This is for use with fscanf() and friends.
FILE* FAST_FUNC xfopen(const char *path, const char *mode)
@@ -140,15 +145,6 @@ int FAST_FUNC xopen(const char *pathname, int flags)
return xopen3(pathname, flags, 0666);
}
-/* Die if we can't open an existing file readonly with O_NONBLOCK
- * and return the fd.
- * Note that for ioctl O_RDONLY is sufficient.
- */
-int FAST_FUNC xopen_nonblocking(const char *pathname)
-{
- return xopen(pathname, O_RDONLY | O_NONBLOCK);
-}
-
// Warn if we can't open a file and return a fd.
int FAST_FUNC open3_or_warn(const char *pathname, int flags, int mode)
{
@@ -167,6 +163,32 @@ int FAST_FUNC open_or_warn(const char *pathname, int flags)
return open3_or_warn(pathname, flags, 0666);
}
+/* Die if we can't open an existing file readonly with O_NONBLOCK
+ * and return the fd.
+ * Note that for ioctl O_RDONLY is sufficient.
+ */
+int FAST_FUNC xopen_nonblocking(const char *pathname)
+{
+ return xopen(pathname, O_RDONLY | O_NONBLOCK);
+}
+
+int FAST_FUNC xopen_as_uid_gid(const char *pathname, int flags, uid_t u, gid_t g)
+{
+ int fd;
+ uid_t old_euid = geteuid();
+ gid_t old_egid = getegid();
+
+ xsetegid(g);
+ xseteuid(u);
+
+ fd = xopen(pathname, flags);
+
+ xseteuid(old_euid);
+ xsetegid(old_egid);
+
+ return fd;
+}
+
void FAST_FUNC xunlink(const char *pathname)
{
if (unlink(pathname))
@@ -351,17 +373,33 @@ void FAST_FUNC xsetuid(uid_t uid)
if (setuid(uid)) bb_perror_msg_and_die("setuid");
}
+void FAST_FUNC xsetegid(gid_t egid)
+{
+ if (setegid(egid)) bb_perror_msg_and_die("setegid");
+}
+
+void FAST_FUNC xseteuid(uid_t euid)
+{
+ if (seteuid(euid)) bb_perror_msg_and_die("seteuid");
+}
+
// Die if we can't chdir to a new path.
void FAST_FUNC xchdir(const char *path)
{
if (chdir(path))
- bb_perror_msg_and_die("chdir(%s)", path);
+ bb_perror_msg_and_die("can't change directory to '%s'", path);
+}
+
+void FAST_FUNC xfchdir(int fd)
+{
+ if (fchdir(fd))
+ bb_perror_msg_and_die("fchdir");
}
void FAST_FUNC xchroot(const char *path)
{
if (chroot(path))
- bb_perror_msg_and_die("can't change root directory to %s", path);
+ bb_perror_msg_and_die("can't change root directory to '%s'", path);
xchdir("/");
}
@@ -541,13 +579,11 @@ int FAST_FUNC bb_xioctl(int fd, unsigned request, void *argp)
char* FAST_FUNC xmalloc_ttyname(int fd)
{
- char *buf = xzalloc(128);
- int r = ttyname_r(fd, buf, 127);
- if (r) {
- free(buf);
- buf = NULL;
- }
- return buf;
+ char buf[128];
+ int r = ttyname_r(fd, buf, sizeof(buf) - 1);
+ if (r)
+ return NULL;
+ return xstrdup(buf);
}
void FAST_FUNC generate_uuid(uint8_t *buf)
@@ -623,3 +659,19 @@ pid_t FAST_FUNC xfork(void)
return pid;
}
#endif
+
+void FAST_FUNC xvfork_parent_waits_and_exits(void)
+{
+ pid_t pid;
+
+ fflush_all();
+ pid = xvfork();
+ if (pid > 0) {
+ /* Parent */
+ int exit_status = wait_for_exitstatus(pid);
+ if (WIFSIGNALED(exit_status))
+ kill_myself_with_sig(WTERMSIG(exit_status));
+ _exit(WEXITSTATUS(exit_status));
+ }
+ /* Child continues */
+}
diff --git a/release/src/router/busybox/libbb/xreadlink.c b/release/src/router/busybox/libbb/xreadlink.c
index ec95af2229..7d4cb60a52 100644
--- a/release/src/router/busybox/libbb/xreadlink.c
+++ b/release/src/router/busybox/libbb/xreadlink.c
@@ -1,13 +1,19 @@
/* vi: set sw=4 ts=4: */
/*
* xreadlink.c - safe implementation of readlink.
- * Returns a NULL on failure...
+ * Returns a NULL on failure.
*
* Licensed under GPLv2, see file LICENSE in this source tree.
*/
#include "libbb.h"
+/* Some systems (eg Hurd) do not have MAXSYMLINKS definition,
+ * set it to some reasonable value if it isn't defined */
+#ifndef MAXSYMLINKS
+# define MAXSYMLINKS 20
+#endif
+
/*
* NOTE: This function returns a malloced char* that you will have to free
* yourself.
@@ -102,7 +108,11 @@ char* FAST_FUNC xmalloc_readlink_or_warn(const char *path)
char* FAST_FUNC xmalloc_realpath(const char *path)
{
-#if defined(__GLIBC__) && !defined(__UCLIBC__)
+/* NB: uclibc also defines __GLIBC__
+ * Therefore the test "if glibc, or uclibc >= 0.9.31" looks a bit weird:
+ */
+#if defined(__GLIBC__) && \
+ (!defined(__UCLIBC__) || UCLIBC_VERSION >= KERNEL_VERSION(0, 9, 31))
/* glibc provides a non-standard extension */
/* new: POSIX.1-2008 specifies this behavior as well */
return realpath(path, NULL);
diff --git a/release/src/router/busybox/libpwdgrp/pwd_grp.c b/release/src/router/busybox/libpwdgrp/pwd_grp.c
index edf53f350b..cefbc8a7e1 100644
--- a/release/src/router/busybox/libpwdgrp/pwd_grp.c
+++ b/release/src/router/busybox/libpwdgrp/pwd_grp.c
@@ -1,613 +1,540 @@
/* vi: set sw=4 ts=4: */
-/* Copyright (C) 2003 Manuel Novoa III
+/* Copyright (C) 2014 Tito Ragusa <farmatito@tiscali.it>
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
-
-/* Nov 6, 2003 Initial version.
+/* This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY!!
*
- * NOTE: This implementation is quite strict about requiring all
- * field seperators. It also does not allow leading whitespace
- * except when processing the numeric fields. glibc is more
- * lenient. See the various glibc difference comments below.
+ * Rewrite of some parts. Main differences are:
*
- * TODO:
- * Move to dynamic allocation of (currently statically allocated)
- * buffers; especially for the group-related functions since
- * large group member lists will cause error returns.
+ * 1) the buffer for getpwuid, getgrgid, getpwnam, getgrnam is dynamically
+ * allocated.
+ * If ENABLE_FEATURE_CLEAN_UP is set the buffers are freed at program
+ * exit using the atexit function to make valgrind happy.
+ * 2) the passwd/group files:
+ * a) must contain the expected number of fields (as per count of field
+ * delimeters ":") or we will complain with a error message.
+ * b) leading and trailing whitespace in fields is stripped.
+ * c) some fields are not allowed to be empty (e.g. username, uid/gid),
+ * and in this case NULL is returned and errno is set to EINVAL.
+ * This behaviour could be easily changed by modifying PW_DEF, GR_DEF,
+ * SP_DEF strings (uppercase makes a field mandatory).
+ * d) the string representing uid/gid must be convertible by strtoXX
+ * functions, or errno is set to EINVAL.
+ * e) leading and trailing whitespace in group member names is stripped.
+ * 3) the internal function for getgrouplist uses dynamically allocated buffer.
+ * 4) at the moment only the functions really used by busybox code are
+ * implemented, if you need a particular missing function it should be
+ * easy to write it by using the internal common code.
*/
#include "libbb.h"
-#include <assert.h>
-
-/**********************************************************************/
-/* Sizes for statically allocated buffers. */
-
-#define PWD_BUFFER_SIZE 256
-#define GRP_BUFFER_SIZE 256
-/**********************************************************************/
-/* Prototypes for internal functions. */
-
-static int bb__pgsreader(
- int FAST_FUNC (*parserfunc)(void *d, char *line),
- void *data,
- char *__restrict line_buff,
- size_t buflen,
- FILE *f);
+struct const_passdb {
+ const char *filename;
+ char def[7 + 2*ENABLE_USE_BB_SHADOW];
+ uint8_t off[7 + 2*ENABLE_USE_BB_SHADOW];
+ uint8_t numfields;
+ uint8_t size_of;
+};
+struct passdb {
+ const char *filename;
+ char def[7 + 2*ENABLE_USE_BB_SHADOW];
+ uint8_t off[7 + 2*ENABLE_USE_BB_SHADOW];
+ uint8_t numfields;
+ uint8_t size_of;
+ FILE *fp;
+ char *malloced;
+};
+/* Note: for shadow db, def[] will not contain terminating NUL,
+ * but convert_to_struct() logic detects def[] end by "less than SP?",
+ * not by "is it NUL?" condition; and off[0] happens to be zero
+ * for every db anyway, so there _is_ in fact a terminating NUL there.
+ */
-static int FAST_FUNC bb__parsepwent(void *pw, char *line);
-static int FAST_FUNC bb__parsegrent(void *gr, char *line);
+/* S = string not empty, s = string maybe empty,
+ * I = uid,gid, l = long maybe empty, m = members,
+ * r = reserved
+ */
+#define PW_DEF "SsIIsss"
+#define GR_DEF "SsIm"
+#define SP_DEF "Ssllllllr"
+
+static const struct const_passdb const_pw_db = {
+ _PATH_PASSWD, PW_DEF,
+ {
+ offsetof(struct passwd, pw_name), /* 0 S */
+ offsetof(struct passwd, pw_passwd), /* 1 s */
+ offsetof(struct passwd, pw_uid), /* 2 I */
+ offsetof(struct passwd, pw_gid), /* 3 I */
+ offsetof(struct passwd, pw_gecos), /* 4 s */
+ offsetof(struct passwd, pw_dir), /* 5 s */
+ offsetof(struct passwd, pw_shell) /* 6 s */
+ },
+ sizeof(PW_DEF)-1, sizeof(struct passwd)
+};
+static const struct const_passdb const_gr_db = {
+ _PATH_GROUP, GR_DEF,
+ {
+ offsetof(struct group, gr_name), /* 0 S */
+ offsetof(struct group, gr_passwd), /* 1 s */
+ offsetof(struct group, gr_gid), /* 2 I */
+ offsetof(struct group, gr_mem) /* 3 m (char **) */
+ },
+ sizeof(GR_DEF)-1, sizeof(struct group)
+};
#if ENABLE_USE_BB_SHADOW
-static int FAST_FUNC bb__parsespent(void *sp, char *line);
+static const struct const_passdb const_sp_db = {
+ _PATH_SHADOW, SP_DEF,
+ {
+ offsetof(struct spwd, sp_namp), /* 0 S Login name */
+ offsetof(struct spwd, sp_pwdp), /* 1 s Encrypted password */
+ offsetof(struct spwd, sp_lstchg), /* 2 l */
+ offsetof(struct spwd, sp_min), /* 3 l */
+ offsetof(struct spwd, sp_max), /* 4 l */
+ offsetof(struct spwd, sp_warn), /* 5 l */
+ offsetof(struct spwd, sp_inact), /* 6 l */
+ offsetof(struct spwd, sp_expire), /* 7 l */
+ offsetof(struct spwd, sp_flag) /* 8 r Reserved */
+ },
+ sizeof(SP_DEF)-1, sizeof(struct spwd)
+};
#endif
-/**********************************************************************/
/* We avoid having big global data. */
-
struct statics {
- /* Smaller things first */
- /* It's ok to use one buffer for getpwuid and getpwnam. Manpage says:
+ /* We use same buffer (db[0].malloced) for getpwuid and getpwnam.
+ * Manpage says:
* "The return value may point to a static area, and may be overwritten
* by subsequent calls to getpwent(), getpwnam(), or getpwuid()."
*/
- struct passwd getpw_resultbuf;
- struct group getgr_resultbuf;
-
- char getpw_buffer[PWD_BUFFER_SIZE];
- char getgr_buffer[GRP_BUFFER_SIZE];
-#if 0 //ENABLE_USE_BB_SHADOW
- struct spwd getsp_resultbuf;
- char getsp_buffer[PWD_BUFFER_SIZE];
-#endif
-// Not converted - too small to bother
-//pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
-//FILE *pwf /*= NULL*/;
-//FILE *grf /*= NULL*/;
-//FILE *spf /*= NULL*/;
+ struct passdb db[2 + ENABLE_USE_BB_SHADOW];
+ char *tokenize_end;
+ unsigned string_size;
};
static struct statics *ptr_to_statics;
+#define S (*ptr_to_statics)
+#define has_S (ptr_to_statics)
+
+#if ENABLE_FEATURE_CLEAN_UP
+static void free_static(void)
+{
+ free(S.db[0].malloced);
+ free(S.db[1].malloced);
+# if ENABLE_USE_BB_SHADOW
+ free(S.db[2].malloced);
+# endif
+ free(ptr_to_statics);
+}
+#endif
static struct statics *get_S(void)
{
- if (!ptr_to_statics)
- ptr_to_statics = xzalloc(sizeof(*ptr_to_statics));
+ if (!ptr_to_statics) {
+ ptr_to_statics = xzalloc(sizeof(S));
+ memcpy(&S.db[0], &const_pw_db, sizeof(const_pw_db));
+ memcpy(&S.db[1], &const_gr_db, sizeof(const_gr_db));
+#if ENABLE_USE_BB_SHADOW
+ memcpy(&S.db[2], &const_sp_db, sizeof(const_sp_db));
+#endif
+#if ENABLE_FEATURE_CLEAN_UP
+ atexit(free_static);
+#endif
+ }
return ptr_to_statics;
}
-/* Always use in this order, get_S() must be called first */
-#define RESULTBUF(name) &((S = get_S())->name##_resultbuf)
-#define BUFFER(name) (S->name##_buffer)
+/* Internal functions */
-/**********************************************************************/
-/* For the various fget??ent_r funcs, return
- *
- * 0: success
- * ENOENT: end-of-file encountered
- * ERANGE: buflen too small
- * other error values possible. See bb__pgsreader.
- *
- * Also, *result == resultbuf on success and NULL on failure.
- *
- * NOTE: glibc difference - For the ENOENT case, glibc also sets errno.
- * We do not, as it really isn't an error if we reach the end-of-file.
- * Doing so is analogous to having fgetc() set errno on EOF.
+/* Divide the passwd/group/shadow record in fields
+ * by substituting the given delimeter
+ * e.g. ':' or ',' with '\0'.
+ * Returns the number of fields found.
+ * Strips leading and trailing whitespace in fields.
*/
-/**********************************************************************/
-
-int fgetpwent_r(FILE *__restrict stream, struct passwd *__restrict resultbuf,
- char *__restrict buffer, size_t buflen,
- struct passwd **__restrict result)
+static int tokenize(char *buffer, int ch)
{
- int rv;
-
- *result = NULL;
+ char *p = buffer;
+ char *s = p;
+ int num_fields = 0;
- rv = bb__pgsreader(bb__parsepwent, resultbuf, buffer, buflen, stream);
- if (!rv) {
- *result = resultbuf;
+ for (;;) {
+ if (isblank(*s)) {
+ overlapping_strcpy(s, skip_whitespace(s));
+ }
+ if (*p == ch || *p == '\0') {
+ char *end = p;
+ while (p != s && isblank(p[-1]))
+ p--;
+ if (p != end)
+ overlapping_strcpy(p, end);
+ num_fields++;
+ if (*end == '\0') {
+ S.tokenize_end = p + 1;
+ return num_fields;
+ }
+ *p = '\0';
+ s = p + 1;
+ }
+ p++;
}
-
- return rv;
}
-int fgetgrent_r(FILE *__restrict stream, struct group *__restrict resultbuf,
- char *__restrict buffer, size_t buflen,
- struct group **__restrict result)
-{
- int rv;
+/* Returns !NULL on success and matching line broken up in fields by '\0' in buf.
+ * We require the expected number of fields to be found.
+ */
+static char *parse_common(FILE *fp, struct passdb *db,
+ const char *key, int field_pos)
+{
+ char *buf;
+
+ while ((buf = xmalloc_fgetline(fp)) != NULL) {
+ /* Skip empty lines, comment lines */
+ if (buf[0] == '\0' || buf[0] == '#')
+ goto free_and_next;
+ if (tokenize(buf, ':') != db->numfields) {
+ /* number of fields is wrong */
+ bb_error_msg("%s: bad record", db->filename);
+ goto free_and_next;
+ }
- *result = NULL;
+ if (field_pos == -1) {
+ /* no key specified: sequential read, return a record */
+ break;
+ }
+ if (strcmp(key, nth_string(buf, field_pos)) == 0) {
+ /* record found */
+ break;
+ }
+ free_and_next:
+ free(buf);
+ }
- rv = bb__pgsreader(bb__parsegrent, resultbuf, buffer, buflen, stream);
- if (!rv) {
- *result = resultbuf;
+ S.string_size = S.tokenize_end - buf;
+/*
+ * Ugly hack: group db requires additional buffer space
+ * for members[] array. If there is only one group, we need space
+ * for 3 pointers: alignment padding, group name, NULL.
+ * +1 for every additional group.
+ */
+ if (buf && db->numfields == sizeof(GR_DEF)-1) { /* if we read group file... */
+ int cnt = 3;
+ char *p = buf;
+ while (p < S.tokenize_end)
+ if (*p++ == ',')
+ cnt++;
+ S.string_size += cnt * sizeof(char*);
+//bb_error_msg("+%d words = %u key:%s buf:'%s'", cnt, S.string_size, key, buf);
+ buf = xrealloc(buf, S.string_size);
}
- return rv;
+ return buf;
}
-#if ENABLE_USE_BB_SHADOW
-#ifdef UNUSED_FOR_NOW
-int fgetspent_r(FILE *__restrict stream, struct spwd *__restrict resultbuf,
- char *__restrict buffer, size_t buflen,
- struct spwd **__restrict result)
+static char *parse_file(struct passdb *db,
+ const char *key, int field_pos)
{
- int rv;
-
- *result = NULL;
+ char *buf = NULL;
+ FILE *fp = fopen_for_read(db->filename);
- rv = bb__pgsreader(bb__parsespent, resultbuf, buffer, buflen, stream);
- if (!rv) {
- *result = resultbuf;
+ if (fp) {
+ buf = parse_common(fp, db, key, field_pos);
+ fclose(fp);
}
-
- return rv;
+ return buf;
}
-#endif
-#endif
-
-/**********************************************************************/
-/* For the various fget??ent funcs, return NULL on failure and a
- * pointer to the appropriate struct (statically allocated) on success.
- * TODO: audit & stop using these in bbox, they pull in static buffers */
-/**********************************************************************/
-#ifdef UNUSED_SINCE_WE_AVOID_STATIC_BUFS
-struct passwd *fgetpwent(FILE *stream)
+/* Convert passwd/group/shadow file record in buffer to a struct */
+static void *convert_to_struct(struct passdb *db,
+ char *buffer, void *result)
{
- struct statics *S;
- struct passwd *resultbuf = RESULTBUF(getpw);
- char *buffer = BUFFER(getpw);
- struct passwd *result;
+ const char *def = db->def;
+ const uint8_t *off = db->off;
- fgetpwent_r(stream, resultbuf, buffer, sizeof(BUFFER(getpw)), &result);
- return result;
-}
+ /* For consistency, zero out all fields */
+ memset(result, 0, db->size_of);
-struct group *fgetgrent(FILE *stream)
-{
- struct statics *S;
- struct group *resultbuf = RESULTBUF(getgr);
- char *buffer = BUFFER(getgr);
- struct group *result;
-
- fgetgrent_r(stream, resultbuf, buffer, sizeof(BUFFER(getgr)), &result);
- return result;
-}
-#endif
+ for (;;) {
+ void *member = (char*)result + (*off++);
+ if ((*def | 0x20) == 's') { /* s or S */
+ *(char **)member = (char*)buffer;
+ if (!buffer[0] && (*def == 'S')) {
+ errno = EINVAL;
+ }
+ }
+ if (*def == 'I') {
+ *(int *)member = bb_strtou(buffer, NULL, 10);
+ }
#if ENABLE_USE_BB_SHADOW
-#ifdef UNUSED_SINCE_WE_AVOID_STATIC_BUFS
-struct spwd *fgetspent(FILE *stream)
-{
- struct statics *S;
- struct spwd *resultbuf = RESULTBUF(getsp);
- char *buffer = BUFFER(getsp);
- struct spwd *result;
-
- fgetspent_r(stream, resultbuf, buffer, sizeof(BUFFER(getsp)), &result);
- return result;
-}
+ if (*def == 'l') {
+ long n = -1;
+ if (buffer[0])
+ n = bb_strtol(buffer, NULL, 10);
+ *(long *)member = n;
+ }
#endif
-
-#ifdef UNUSED_FOR_NOW
-int sgetspent_r(const char *string, struct spwd *result_buf,
- char *buffer, size_t buflen, struct spwd **result)
-{
- int rv = ERANGE;
-
- *result = NULL;
-
- if (buflen < PWD_BUFFER_SIZE) {
- DO_ERANGE:
- errno = rv;
- goto DONE;
- }
-
- if (string != buffer) {
- if (strlen(string) >= buflen) {
- goto DO_ERANGE;
+ if (*def == 'm') {
+ char **members;
+ int i = tokenize(buffer, ',');
+
+ /* Store members[] after buffer's end.
+ * This is safe ONLY because there is a hack
+ * in parse_common() which allocates additional space
+ * at the end of malloced buffer!
+ */
+ members = (char **)
+ ( ((intptr_t)S.tokenize_end + sizeof(members[0]))
+ & -(intptr_t)sizeof(members[0])
+ );
+ ((struct group *)result)->gr_mem = members;
+ while (--i >= 0) {
+ if (buffer[0]) {
+ *members++ = buffer;
+ // bb_error_msg("member[]='%s'", buffer);
+ }
+ buffer += strlen(buffer) + 1;
+ }
+ *members = NULL;
}
- strcpy(buffer, string);
- }
+ /* def "r" does nothing */
- rv = bb__parsespent(result_buf, buffer);
- if (!rv) {
- *result = result_buf;
+ def++;
+ if ((unsigned char)*def <= (unsigned char)' ')
+ break;
+ buffer += strlen(buffer) + 1;
}
- DONE:
- return rv;
-}
-#endif
-#endif /* ENABLE_USE_BB_SHADOW */
-
-/**********************************************************************/
-
-#define GETXXKEY_R_FUNC getpwnam_r
-#define GETXXKEY_R_PARSER bb__parsepwent
-#define GETXXKEY_R_ENTTYPE struct passwd
-#define GETXXKEY_R_TEST(ENT) (!strcmp((ENT)->pw_name, key))
-#define GETXXKEY_R_KEYTYPE const char *__restrict
-#define GETXXKEY_R_PATHNAME _PATH_PASSWD
-#include "pwd_grp_internal.c"
-
-#define GETXXKEY_R_FUNC getgrnam_r
-#define GETXXKEY_R_PARSER bb__parsegrent
-#define GETXXKEY_R_ENTTYPE struct group
-#define GETXXKEY_R_TEST(ENT) (!strcmp((ENT)->gr_name, key))
-#define GETXXKEY_R_KEYTYPE const char *__restrict
-#define GETXXKEY_R_PATHNAME _PATH_GROUP
-#include "pwd_grp_internal.c"
-
-#if ENABLE_USE_BB_SHADOW
-#define GETXXKEY_R_FUNC getspnam_r
-#define GETXXKEY_R_PARSER bb__parsespent
-#define GETXXKEY_R_ENTTYPE struct spwd
-#define GETXXKEY_R_TEST(ENT) (!strcmp((ENT)->sp_namp, key))
-#define GETXXKEY_R_KEYTYPE const char *__restrict
-#define GETXXKEY_R_PATHNAME _PATH_SHADOW
-#include "pwd_grp_internal.c"
-#endif
-
-#define GETXXKEY_R_FUNC getpwuid_r
-#define GETXXKEY_R_PARSER bb__parsepwent
-#define GETXXKEY_R_ENTTYPE struct passwd
-#define GETXXKEY_R_TEST(ENT) ((ENT)->pw_uid == key)
-#define GETXXKEY_R_KEYTYPE uid_t
-#define GETXXKEY_R_PATHNAME _PATH_PASSWD
-#include "pwd_grp_internal.c"
-
-#define GETXXKEY_R_FUNC getgrgid_r
-#define GETXXKEY_R_PARSER bb__parsegrent
-#define GETXXKEY_R_ENTTYPE struct group
-#define GETXXKEY_R_TEST(ENT) ((ENT)->gr_gid == key)
-#define GETXXKEY_R_KEYTYPE gid_t
-#define GETXXKEY_R_PATHNAME _PATH_GROUP
-#include "pwd_grp_internal.c"
-
-/**********************************************************************/
-/* TODO: audit & stop using these in bbox, they pull in static buffers */
-
-/* This one has many users */
-struct passwd *getpwuid(uid_t uid)
-{
- struct statics *S;
- struct passwd *resultbuf = RESULTBUF(getpw);
- char *buffer = BUFFER(getpw);
- struct passwd *result;
-
- getpwuid_r(uid, resultbuf, buffer, sizeof(BUFFER(getpw)), &result);
+ if (errno)
+ result = NULL;
return result;
}
-/* This one has many users */
-struct group *getgrgid(gid_t gid)
+static int massage_data_for_r_func(struct passdb *db,
+ char *buffer, size_t buflen,
+ void **result,
+ char *buf)
{
- struct statics *S;
- struct group *resultbuf = RESULTBUF(getgr);
- char *buffer = BUFFER(getgr);
- struct group *result;
-
- getgrgid_r(gid, resultbuf, buffer, sizeof(BUFFER(getgr)), &result);
- return result;
-}
-
-#if 0 //ENABLE_USE_BB_SHADOW
-/* This function is non-standard and is currently not built. It seems
- * to have been created as a reentrant version of the non-standard
- * functions getspuid. Why getspuid was added, I do not know. */
-int getspuid_r(uid_t uid, struct spwd *__restrict resultbuf,
- char *__restrict buffer, size_t buflen,
- struct spwd **__restrict result)
-{
- int rv;
- struct passwd *pp;
- struct passwd password;
- char pwd_buff[PWD_BUFFER_SIZE];
-
+ void *result_buf = *result;
*result = NULL;
- rv = getpwuid_r(uid, &password, pwd_buff, sizeof(pwd_buff), &pp);
- if (!rv) {
- rv = getspnam_r(password.pw_name, resultbuf, buffer, buflen, result);
+ if (buf) {
+ if (S.string_size > buflen) {
+ errno = ERANGE;
+ } else {
+ memcpy(buffer, buf, S.string_size);
+ *result = convert_to_struct(db, buffer, result_buf);
+ }
+ free(buf);
}
-
- return rv;
+ /* "The reentrant functions return zero on success.
+ * In case of error, an error number is returned."
+ * NB: not finding the record is also a "success" here:
+ */
+ return errno;
}
-/* This function is non-standard and is currently not built.
- * Why it was added, I do not know. */
-struct spwd *getspuid(uid_t uid)
+static void* massage_data_for_non_r_func(struct passdb *db, char *buf)
{
- struct statics *S;
- struct spwd *resultbuf = RESULTBUF(getsp);
- char *buffer = BUFFER(getsp);
- struct spwd *result;
+ if (!buf)
+ return NULL;
- getspuid_r(uid, resultbuf, buffer, sizeof(BUFFER(getsp)), &result);
- return result;
+ free(db->malloced);
+ /* We enlarge buf and move string data up, freeing space
+ * for struct passwd/group/spwd at the beginning. This way,
+ * entire result of getXXnam is in a single malloced block.
+ * This enables easy creation of xmalloc_getpwnam() API.
+ */
+ db->malloced = buf = xrealloc(buf, db->size_of + S.string_size);
+ memmove(buf + db->size_of, buf, S.string_size);
+ return convert_to_struct(db, buf + db->size_of, buf);
}
-#endif
-/* This one has many users */
-struct passwd *getpwnam(const char *name)
+/****** getXXnam/id_r */
+
+static int FAST_FUNC getXXnam_r(const char *name, uintptr_t db_and_field_pos,
+ char *buffer, size_t buflen,
+ void *result)
{
- struct statics *S;
- struct passwd *resultbuf = RESULTBUF(getpw);
- char *buffer = BUFFER(getpw);
- struct passwd *result;
+ char *buf;
+ struct passdb *db = &get_S()->db[db_and_field_pos >> 2];
- getpwnam_r(name, resultbuf, buffer, sizeof(BUFFER(getpw)), &result);
- return result;
+ buf = parse_file(db, name, 0 /*db_and_field_pos & 3*/);
+ /* "db_and_field_pos & 3" is commented out since so far we don't implement
+ * getXXXid_r() functions which would use that to pass 2 here */
+
+ return massage_data_for_r_func(db, buffer, buflen, result, buf);
}
-/* This one has many users */
-struct group *getgrnam(const char *name)
+int FAST_FUNC getpwnam_r(const char *name, struct passwd *struct_buf,
+ char *buffer, size_t buflen,
+ struct passwd **result)
{
- struct statics *S;
- struct group *resultbuf = RESULTBUF(getgr);
- char *buffer = BUFFER(getgr);
- struct group *result;
-
- getgrnam_r(name, resultbuf, buffer, sizeof(BUFFER(getgr)), &result);
- return result;
+ /* Why the "store buffer address in result" trick?
+ * This way, getXXnam_r has the same ABI signature as getpwnam_r,
+ * hopefully compiler can optimize tail call better in this case.
+ */
+ *result = struct_buf;
+ return getXXnam_r(name, (0 << 2) + 0, buffer, buflen, result);
}
-
-#if 0 //ENABLE_USE_BB_SHADOW
-struct spwd *getspnam(const char *name)
+#if ENABLE_USE_BB_SHADOW
+int FAST_FUNC getspnam_r(const char *name, struct spwd *struct_buf, char *buffer, size_t buflen,
+ struct spwd **result)
{
- struct statics *S;
- struct spwd *resultbuf = RESULTBUF(getsp);
- char *buffer = BUFFER(getsp);
- struct spwd *result;
-
- getspnam_r(name, resultbuf, buffer, sizeof(BUFFER(getsp)), &result);
- return result;
+ *result = struct_buf;
+ return getXXnam_r(name, (2 << 2) + 0, buffer, buflen, result);
}
#endif
-/**********************************************************************/
-
-/* FIXME: we don't have such CONFIG_xx - ?! */
-
-#if defined CONFIG_USE_BB_THREADSAFE_SHADOW && defined PTHREAD_MUTEX_INITIALIZER
-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
-# define LOCK pthread_mutex_lock(&mylock)
-# define UNLOCK pthread_mutex_unlock(&mylock);
-#else
-# define LOCK ((void) 0)
-# define UNLOCK ((void) 0)
-#endif
+#ifdef UNUSED
+/****** getXXent_r */
-static FILE *pwf /*= NULL*/;
-void setpwent(void)
+static int FAST_FUNC getXXent_r(uintptr_t db_idx, char *buffer, size_t buflen,
+ void *result)
{
- LOCK;
- if (pwf) {
- rewind(pwf);
+ char *buf;
+ struct passdb *db = &get_S()->db[db_idx];
+
+ if (!db->fp) {
+ db->fp = fopen_for_read(db->filename);
+ if (!db->fp) {
+ return errno;
+ }
+ close_on_exec_on(fileno(db->fp));
}
- UNLOCK;
+
+ buf = parse_common(db->fp, db, /*no search key:*/ NULL, -1);
+ if (!buf && !errno)
+ errno = ENOENT;
+ return massage_data_for_r_func(db, buffer, buflen, result, buf);
}
-void endpwent(void)
+int FAST_FUNC getpwent_r(struct passwd *struct_buf, char *buffer, size_t buflen,
+ struct passwd **result)
{
- LOCK;
- if (pwf) {
- fclose(pwf);
- pwf = NULL;
- }
- UNLOCK;
+ *result = struct_buf;
+ return getXXent_r(0, buffer, buflen, result);
}
+#endif
+/****** getXXent */
-int getpwent_r(struct passwd *__restrict resultbuf,
- char *__restrict buffer, size_t buflen,
- struct passwd **__restrict result)
+static void* FAST_FUNC getXXent(uintptr_t db_idx)
{
- int rv;
-
- LOCK;
- *result = NULL; /* In case of error... */
+ char *buf;
+ struct passdb *db = &get_S()->db[db_idx];
- if (!pwf) {
- pwf = fopen_for_read(_PATH_PASSWD);
- if (!pwf) {
- rv = errno;
- goto ERR;
+ if (!db->fp) {
+ db->fp = fopen_for_read(db->filename);
+ if (!db->fp) {
+ return NULL;
}
- close_on_exec_on(fileno(pwf));
+ close_on_exec_on(fileno(db->fp));
}
- rv = bb__pgsreader(bb__parsepwent, resultbuf, buffer, buflen, pwf);
- if (!rv) {
- *result = resultbuf;
- }
-
- ERR:
- UNLOCK;
- return rv;
+ buf = parse_common(db->fp, db, /*no search key:*/ NULL, -1);
+ return massage_data_for_non_r_func(db, buf);
}
-static FILE *grf /*= NULL*/;
-void setgrent(void)
+struct passwd* FAST_FUNC getpwent(void)
{
- LOCK;
- if (grf) {
- rewind(grf);
- }
- UNLOCK;
+ return getXXent(0);
}
-void endgrent(void)
-{
- LOCK;
- if (grf) {
- fclose(grf);
- grf = NULL;
- }
- UNLOCK;
-}
+/****** getXXnam/id */
-int getgrent_r(struct group *__restrict resultbuf,
- char *__restrict buffer, size_t buflen,
- struct group **__restrict result)
+static void* FAST_FUNC getXXnam(const char *name, unsigned db_and_field_pos)
{
- int rv;
-
- LOCK;
- *result = NULL; /* In case of error... */
+ char *buf;
+ struct passdb *db = &get_S()->db[db_and_field_pos >> 2];
- if (!grf) {
- grf = fopen_for_read(_PATH_GROUP);
- if (!grf) {
- rv = errno;
- goto ERR;
- }
- close_on_exec_on(fileno(grf));
- }
-
- rv = bb__pgsreader(bb__parsegrent, resultbuf, buffer, buflen, grf);
- if (!rv) {
- *result = resultbuf;
- }
-
- ERR:
- UNLOCK;
- return rv;
+ buf = parse_file(db, name, db_and_field_pos & 3);
+ return massage_data_for_non_r_func(db, buf);
}
-#ifdef UNUSED_FOR_NOW
-#if ENABLE_USE_BB_SHADOW
-static FILE *spf /*= NULL*/;
-void setspent(void)
+struct passwd* FAST_FUNC getpwnam(const char *name)
{
- LOCK;
- if (spf) {
- rewind(spf);
- }
- UNLOCK;
+ return getXXnam(name, (0 << 2) + 0);
}
-
-void endspent(void)
+struct group* FAST_FUNC getgrnam(const char *name)
{
- LOCK;
- if (spf) {
- fclose(spf);
- spf = NULL;
- }
- UNLOCK;
+ return getXXnam(name, (1 << 2) + 0);
}
-
-int getspent_r(struct spwd *resultbuf, char *buffer,
- size_t buflen, struct spwd **result)
+struct passwd* FAST_FUNC getpwuid(uid_t id)
{
- int rv;
-
- LOCK;
- *result = NULL; /* In case of error... */
-
- if (!spf) {
- spf = fopen_for_read(_PATH_SHADOW);
- if (!spf) {
- rv = errno;
- goto ERR;
- }
- close_on_exec_on(fileno(spf));
- }
-
- rv = bb__pgsreader(bb__parsespent, resultbuf, buffer, buflen, spf);
- if (!rv) {
- *result = resultbuf;
- }
-
- ERR:
- UNLOCK;
- return rv;
+ return getXXnam(utoa(id), (0 << 2) + 2);
}
-#endif
-#endif /* UNUSED_FOR_NOW */
-
-#ifdef UNUSED_SINCE_WE_AVOID_STATIC_BUFS
-struct passwd *getpwent(void)
+struct group* FAST_FUNC getgrgid(gid_t id)
{
- static char line_buff[PWD_BUFFER_SIZE];
- static struct passwd pwd;
- struct passwd *result;
-
- getpwent_r(&pwd, line_buff, sizeof(line_buff), &result);
- return result;
+ return getXXnam(utoa(id), (1 << 2) + 2);
}
-struct group *getgrent(void)
-{
- static char line_buff[GRP_BUFFER_SIZE];
- static struct group gr;
- struct group *result;
+/****** end/setXXend */
- getgrent_r(&gr, line_buff, sizeof(line_buff), &result);
- return result;
+void FAST_FUNC endpwent(void)
+{
+ if (has_S && S.db[0].fp) {
+ fclose(S.db[0].fp);
+ S.db[0].fp = NULL;
+ }
}
-
-#if ENABLE_USE_BB_SHADOW
-struct spwd *getspent(void)
+void FAST_FUNC setpwent(void)
{
- static char line_buff[PWD_BUFFER_SIZE];
- static struct spwd spwd;
- struct spwd *result;
-
- getspent_r(&spwd, line_buff, sizeof(line_buff), &result);
- return result;
+ if (has_S && S.db[0].fp) {
+ rewind(S.db[0].fp);
+ }
}
-
-struct spwd *sgetspent(const char *string)
+void FAST_FUNC endgrent(void)
{
- static char line_buff[PWD_BUFFER_SIZE];
- static struct spwd spwd;
- struct spwd *result;
-
- sgetspent_r(string, &spwd, line_buff, sizeof(line_buff), &result);
- return result;
+ if (has_S && S.db[1].fp) {
+ fclose(S.db[1].fp);
+ S.db[1].fp = NULL;
+ }
}
-#endif
-#endif /* UNUSED_SINCE_WE_AVOID_STATIC_BUFS */
-static gid_t *getgrouplist_internal(int *ngroups_ptr, const char *user, gid_t gid)
+/****** initgroups and getgrouplist */
+
+static gid_t* FAST_FUNC getgrouplist_internal(int *ngroups_ptr,
+ const char *user, gid_t gid)
{
- FILE *grfile;
+ FILE *fp;
gid_t *group_list;
int ngroups;
- struct group group;
- char buff[PWD_BUFFER_SIZE];
/* We alloc space for 8 gids at a time. */
- group_list = xmalloc(8 * sizeof(group_list[0]));
+ group_list = xzalloc(8 * sizeof(group_list[0]));
group_list[0] = gid;
ngroups = 1;
- grfile = fopen_for_read(_PATH_GROUP);
- if (grfile) {
- while (!bb__pgsreader(bb__parsegrent, &group, buff, sizeof(buff), grfile)) {
+ fp = fopen_for_read(_PATH_GROUP);
+ if (fp) {
+ struct passdb *db = &get_S()->db[1];
+ char *buf;
+ while ((buf = parse_common(fp, db, NULL, -1)) != NULL) {
char **m;
- assert(group.gr_mem); /* Must have at least a NULL terminator. */
+ struct group group;
+ if (!convert_to_struct(db, buf, &group))
+ goto next;
if (group.gr_gid == gid)
- continue;
+ goto next;
for (m = group.gr_mem; *m; m++) {
if (strcmp(*m, user) != 0)
continue;
group_list = xrealloc_vector(group_list, /*8=2^3:*/ 3, ngroups);
group_list[ngroups++] = group.gr_gid;
- break;
+ goto next;
}
+ next:
+ free(buf);
}
- fclose(grfile);
+ fclose(fp);
}
*ngroups_ptr = ngroups;
return group_list;
}
-int initgroups(const char *user, gid_t gid)
+int FAST_FUNC initgroups(const char *user, gid_t gid)
{
int ngroups;
gid_t *group_list = getgrouplist_internal(&ngroups, user, gid);
@@ -617,7 +544,7 @@ int initgroups(const char *user, gid_t gid)
return ngroups;
}
-int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups)
+int FAST_FUNC getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups)
{
int ngroups_old = *ngroups;
gid_t *group_list = getgrouplist_internal(ngroups, user, gid);
@@ -631,409 +558,3 @@ int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups)
free(group_list);
return ngroups_old;
}
-
-#ifdef UNUSED_SINCE_WE_AVOID_STATIC_BUFS
-int putpwent(const struct passwd *__restrict p, FILE *__restrict f)
-{
- int rv = -1;
-
-#if 0
- /* glibc does this check */
- if (!p || !f) {
- errno = EINVAL;
- return rv;
- }
-#endif
-
- /* No extra thread locking is needed above what fprintf does. */
- if (fprintf(f, "%s:%s:%lu:%lu:%s:%s:%s\n",
- p->pw_name, p->pw_passwd,
- (unsigned long)(p->pw_uid),
- (unsigned long)(p->pw_gid),
- p->pw_gecos, p->pw_dir, p->pw_shell) >= 0
- ) {
- rv = 0;
- }
-
- return rv;
-}
-
-int putgrent(const struct group *__restrict p, FILE *__restrict f)
-{
- int rv = -1;
-
-#if 0
- /* glibc does this check */
- if (!p || !f) {
- errno = EINVAL;
- return rv;
- }
-#endif
-
- if (fprintf(f, "%s:%s:%lu:",
- p->gr_name, p->gr_passwd,
- (unsigned long)(p->gr_gid)) >= 0
- ) {
- static const char format[] ALIGN1 = ",%s";
-
- char **m;
- const char *fmt;
-
- fmt = format + 1;
-
- assert(p->gr_mem);
- m = p->gr_mem;
-
- while (1) {
- if (!*m) {
- if (fputc('\n', f) >= 0) {
- rv = 0;
- }
- break;
- }
- if (fprintf(f, fmt, *m) < 0) {
- break;
- }
- m++;
- fmt = format;
- }
- }
-
- return rv;
-}
-#endif
-
-#if ENABLE_USE_BB_SHADOW
-#ifdef UNUSED_FOR_NOW
-static const unsigned char put_sp_off[] ALIGN1 = {
- offsetof(struct spwd, sp_lstchg), /* 2 - not a char ptr */
- offsetof(struct spwd, sp_min), /* 3 - not a char ptr */
- offsetof(struct spwd, sp_max), /* 4 - not a char ptr */
- offsetof(struct spwd, sp_warn), /* 5 - not a char ptr */
- offsetof(struct spwd, sp_inact), /* 6 - not a char ptr */
- offsetof(struct spwd, sp_expire) /* 7 - not a char ptr */
-};
-
-int putspent(const struct spwd *p, FILE *stream)
-{
- const char *fmt;
- long x;
- int i;
- int rv = -1;
-
- /* Unlike putpwent and putgrent, glibc does not check the args. */
- if (fprintf(stream, "%s:%s:", p->sp_namp,
- (p->sp_pwdp ? p->sp_pwdp : "")) < 0
- ) {
- goto DO_UNLOCK;
- }
-
- for (i = 0; i < sizeof(put_sp_off); i++) {
- fmt = "%ld:";
- x = *(long *)((char *)p + put_sp_off[i]);
- if (x == -1) {
- fmt += 3;
- }
- if (fprintf(stream, fmt, x) < 0) {
- goto DO_UNLOCK;
- }
- }
-
- if ((p->sp_flag != ~0UL) && (fprintf(stream, "%lu", p->sp_flag) < 0)) {
- goto DO_UNLOCK;
- }
-
- if (fputc('\n', stream) > 0) {
- rv = 0;
- }
-
- DO_UNLOCK:
- return rv;
-}
-#endif
-#endif /* USE_BB_SHADOW */
-
-/**********************************************************************/
-/* Internal functions */
-/**********************************************************************/
-
-static const unsigned char pw_off[] ALIGN1 = {
- offsetof(struct passwd, pw_name), /* 0 */
- offsetof(struct passwd, pw_passwd), /* 1 */
- offsetof(struct passwd, pw_uid), /* 2 - not a char ptr */
- offsetof(struct passwd, pw_gid), /* 3 - not a char ptr */
- offsetof(struct passwd, pw_gecos), /* 4 */
- offsetof(struct passwd, pw_dir), /* 5 */
- offsetof(struct passwd, pw_shell) /* 6 */
-};
-
-static int FAST_FUNC bb__parsepwent(void *data, char *line)
-{
- char *endptr;
- char *p;
- int i;
-
- i = 0;
- while (1) {
- p = (char *) data + pw_off[i];
-
- if (i < 2 || i > 3) {
- *((char **) p) = line;
- if (i == 6) {
- return 0;
- }
- /* NOTE: glibc difference - glibc allows omission of
- * ':' seperators after the gid field if all remaining
- * entries are empty. We require all separators. */
- line = strchr(line, ':');
- if (!line) {
- break;
- }
- } else {
- unsigned long t = strtoul(line, &endptr, 10);
- /* Make sure we had at least one digit, and that the
- * failing char is the next field seperator ':'. See
- * glibc difference note above. */
- /* TODO: Also check for leading whitespace? */
- if ((endptr == line) || (*endptr != ':')) {
- break;
- }
- line = endptr;
- if (i & 1) { /* i == 3 -- gid */
- *((gid_t *) p) = t;
- } else { /* i == 2 -- uid */
- *((uid_t *) p) = t;
- }
- }
-
- *line++ = '\0';
- i++;
- } /* while (1) */
-
- return -1;
-}
-
-/**********************************************************************/
-
-static const unsigned char gr_off[] ALIGN1 = {
- offsetof(struct group, gr_name), /* 0 */
- offsetof(struct group, gr_passwd), /* 1 */
- offsetof(struct group, gr_gid) /* 2 - not a char ptr */
-};
-
-static int FAST_FUNC bb__parsegrent(void *data, char *line)
-{
- char *endptr;
- char *p;
- int i;
- char **members;
- char *end_of_buf;
-
- end_of_buf = ((struct group *) data)->gr_name; /* Evil hack! */
- i = 0;
- while (1) {
- p = (char *) data + gr_off[i];
-
- if (i < 2) {
- *((char **) p) = line;
- line = strchr(line, ':');
- if (!line) {
- break;
- }
- *line++ = '\0';
- i++;
- } else {
- *((gid_t *) p) = strtoul(line, &endptr, 10);
-
- /* NOTE: glibc difference - glibc allows omission of the
- * trailing colon when there is no member list. We treat
- * this as an error. */
-
- /* Make sure we had at least one digit, and that the
- * failing char is the next field seperator ':'. See
- * glibc difference note above. */
- if ((endptr == line) || (*endptr != ':')) {
- break;
- }
-
- i = 1; /* Count terminating NULL ptr. */
- p = endptr;
-
- if (p[1]) { /* We have a member list to process. */
- /* Overwrite the last ':' with a ',' before counting.
- * This allows us to (1) test for initial ','
- * and (2) adds one ',' so that the number of commas
- * equals the member count. */
- *p = ',';
- do {
- /* NOTE: glibc difference - glibc allows and trims leading
- * (but not trailing) space. We treat this as an error. */
- /* NOTE: glibc difference - glibc allows consecutive and
- * trailing commas, and ignores "empty string" users. We
- * treat this as an error. */
- if (*p == ',') {
- ++i;
- *p = 0; /* nul-terminate each member string. */
- if (!*++p || (*p == ',') || isspace(*p)) {
- goto ERR;
- }
- }
- } while (*++p);
- }
-
- /* Now align (p+1), rounding up. */
- /* Assumes sizeof(char **) is a power of 2. */
- members = (char **)( (((intptr_t) p) + sizeof(char **))
- & ~((intptr_t)(sizeof(char **) - 1)) );
-
- if (((char *)(members + i)) > end_of_buf) { /* No space. */
- break;
- }
-
- ((struct group *) data)->gr_mem = members;
-
- if (--i) {
- p = endptr; /* Pointing to char prior to first member. */
- while (1) {
- *members++ = ++p;
- if (!--i)
- break;
- while (*++p)
- continue;
- }
- }
- *members = NULL;
-
- return 0;
- }
- } /* while (1) */
-
- ERR:
- return -1;
-}
-
-/**********************************************************************/
-
-#if ENABLE_USE_BB_SHADOW
-static const unsigned char sp_off[] ALIGN1 = {
- offsetof(struct spwd, sp_namp), /* 0: char* */
- offsetof(struct spwd, sp_pwdp), /* 1: char* */
- offsetof(struct spwd, sp_lstchg), /* 2: long */
- offsetof(struct spwd, sp_min), /* 3: long */
- offsetof(struct spwd, sp_max), /* 4: long */
- offsetof(struct spwd, sp_warn), /* 5: long */
- offsetof(struct spwd, sp_inact), /* 6: long */
- offsetof(struct spwd, sp_expire), /* 7: long */
- offsetof(struct spwd, sp_flag) /* 8: unsigned long */
-};
-
-static int FAST_FUNC bb__parsespent(void *data, char *line)
-{
- char *endptr;
- char *p;
- int i;
-
- i = 0;
- while (1) {
- p = (char *) data + sp_off[i];
- if (i < 2) {
- *((char **) p) = line;
- line = strchr(line, ':');
- if (!line) {
- break; /* error */
- }
- } else {
- *((long *) p) = strtoul(line, &endptr, 10);
- if (endptr == line) {
- *((long *) p) = -1L;
- }
- line = endptr;
- if (i == 8) {
- if (*line != '\0') {
- break; /* error */
- }
- return 0; /* all ok */
- }
- if (*line != ':') {
- break; /* error */
- }
- }
- *line++ = '\0';
- i++;
- }
-
- return EINVAL;
-}
-#endif
-
-/**********************************************************************/
-
-/* Reads until EOF, or until it finds a line which fits in the buffer
- * and for which the parser function succeeds.
- *
- * Returns 0 on success and ENOENT for end-of-file (glibc convention).
- */
-static int bb__pgsreader(
- int FAST_FUNC (*parserfunc)(void *d, char *line),
- void *data,
- char *__restrict line_buff,
- size_t buflen,
- FILE *f)
-{
- int skip;
- int rv = ERANGE;
-
- if (buflen < PWD_BUFFER_SIZE) {
- errno = rv;
- return rv;
- }
-
- skip = 0;
- while (1) {
- if (!fgets(line_buff, buflen, f)) {
- if (feof(f)) {
- rv = ENOENT;
- }
- break;
- }
-
- {
- int line_len = strlen(line_buff) - 1;
- if (line_len >= 0 && line_buff[line_len] == '\n') {
- line_buff[line_len] = '\0';
- } else
- if (line_len + 2 == buflen) {
- /* A start (or continuation) of overlong line */
- skip = 1;
- continue;
- } /* else: a last line in the file, and it has no '\n' */
- }
-
- if (skip) {
- /* This "line" is a remainder of overlong line, ignore */
- skip = 0;
- continue;
- }
-
- /* NOTE: glibc difference - glibc strips leading whitespace from
- * records. We do not allow leading whitespace. */
-
- /* Skip empty lines, comment lines, and lines with leading
- * whitespace. */
- if (line_buff[0] != '\0' && line_buff[0] != '#' && !isspace(line_buff[0])) {
- if (parserfunc == bb__parsegrent) {
- /* Do evil group hack:
- * The group entry parsing function needs to know where
- * the end of the buffer is so that it can construct the
- * group member ptr table. */
- ((struct group *) data)->gr_name = line_buff + buflen;
- }
- if (parserfunc(data, line_buff) == 0) {
- rv = 0;
- break;
- }
- }
- } /* while (1) */
-
- return rv;
-}
diff --git a/release/src/router/busybox/libpwdgrp/pwd_grp_internal.c b/release/src/router/busybox/libpwdgrp/pwd_grp_internal.c
deleted file mode 100644
index d6483be844..0000000000
--- a/release/src/router/busybox/libpwdgrp/pwd_grp_internal.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/* Copyright (C) 2003 Manuel Novoa III
- *
- * Licensed under GPLv2 or later, see file LICENSE in this source tree.
- */
-
-/* Nov 6, 2003 Initial version.
- *
- * NOTE: This implementation is quite strict about requiring all
- * field seperators. It also does not allow leading whitespace
- * except when processing the numeric fields. glibc is more
- * lenient. See the various glibc difference comments below.
- *
- * TODO:
- * Move to dynamic allocation of (currently statically allocated)
- * buffers; especially for the group-related functions since
- * large group member lists will cause error returns.
- */
-
-#ifndef GETXXKEY_R_FUNC
-#error GETXXKEY_R_FUNC is not defined!
-#endif
-
-int GETXXKEY_R_FUNC(GETXXKEY_R_KEYTYPE key,
- GETXXKEY_R_ENTTYPE *__restrict resultbuf,
- char *__restrict buffer, size_t buflen,
- GETXXKEY_R_ENTTYPE **__restrict result)
-{
- FILE *stream;
- int rv;
-
- *result = NULL;
-
- stream = fopen_for_read(GETXXKEY_R_PATHNAME);
- if (!stream)
- return errno;
- while (1) {
- rv = bb__pgsreader(GETXXKEY_R_PARSER, resultbuf, buffer, buflen, stream);
- if (!rv) {
- if (GETXXKEY_R_TEST(resultbuf)) { /* found key? */
- *result = resultbuf;
- break;
- }
- } else {
- if (rv == ENOENT) { /* EOF encountered */
- rv = 0;
- }
- break;
- }
- }
- fclose(stream);
-
- return rv;
-}
-
-#undef GETXXKEY_R_FUNC
-#undef GETXXKEY_R_PARSER
-#undef GETXXKEY_R_ENTTYPE
-#undef GETXXKEY_R_TEST
-#undef GETXXKEY_R_KEYTYPE
-#undef GETXXKEY_R_PATHNAME
diff --git a/release/src/router/busybox/libpwdgrp/uidgid_get.c b/release/src/router/busybox/libpwdgrp/uidgid_get.c
index 8388be0dad..1199f23f96 100644
--- a/release/src/router/busybox/libpwdgrp/uidgid_get.c
+++ b/release/src/router/busybox/libpwdgrp/uidgid_get.c
@@ -28,7 +28,7 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "libbb.h"
/* Always sets uid and gid */
-int FAST_FUNC get_uidgid(struct bb_uidgid_t *u, const char *ug, int numeric_ok)
+int FAST_FUNC get_uidgid(struct bb_uidgid_t *u, const char *ug)
{
struct passwd *pwd;
struct group *gr;
@@ -43,18 +43,16 @@ int FAST_FUNC get_uidgid(struct bb_uidgid_t *u, const char *ug, int numeric_ok)
/* copies sz-1 bytes, stores terminating '\0' */
safe_strncpy(user, ug, sz);
}
- if (numeric_ok) {
- n = bb_strtou(user, NULL, 10);
- if (!errno) {
- u->uid = n;
- pwd = getpwuid(n);
- /* If we have e.g. "500" string without user */
- /* with uid 500 in /etc/passwd, we set gid == uid */
- u->gid = pwd ? pwd->pw_gid : n;
- goto skip;
- }
+ n = bb_strtou(user, NULL, 10);
+ if (!errno) {
+ u->uid = n;
+ pwd = getpwuid(n);
+ /* If we have e.g. "500" string without user */
+ /* with uid 500 in /etc/passwd, we set gid == uid */
+ u->gid = pwd ? pwd->pw_gid : n;
+ goto skip;
}
- /* Either it is not numeric, or caller disallows numeric username */
+ /* it is not numeric */
pwd = getpwnam(user);
if (!pwd)
return 0;
@@ -63,12 +61,10 @@ int FAST_FUNC get_uidgid(struct bb_uidgid_t *u, const char *ug, int numeric_ok)
skip:
if (group) {
- if (numeric_ok) {
- n = bb_strtou(group, NULL, 10);
- if (!errno) {
- u->gid = n;
- return 1;
- }
+ n = bb_strtou(group, NULL, 10);
+ if (!errno) {
+ u->gid = n;
+ return 1;
}
gr = getgrnam(group);
if (!gr)
@@ -79,7 +75,7 @@ int FAST_FUNC get_uidgid(struct bb_uidgid_t *u, const char *ug, int numeric_ok)
}
void FAST_FUNC xget_uidgid(struct bb_uidgid_t *u, const char *ug)
{
- if (!get_uidgid(u, ug, 1))
+ if (!get_uidgid(u, ug))
bb_error_msg_and_die("unknown user/group %s", ug);
}
@@ -94,6 +90,8 @@ void FAST_FUNC parse_chown_usergroup_or_die(struct bb_uidgid_t *u, char *user_gr
{
char *group;
+ u->uid = u->gid = (gid_t)-1L;
+
/* Check if there is a group name */
group = strchr(user_group, '.'); /* deprecated? */
if (!group)
@@ -119,16 +117,16 @@ int main()
{
unsigned u;
struct bb_uidgid_t ug;
- u = get_uidgid(&ug, "apache", 0);
+ u = get_uidgid(&ug, "apache");
printf("%u = %u:%u\n", u, ug.uid, ug.gid);
ug.uid = ug.gid = 1111;
- u = get_uidgid(&ug, "apache", 0);
+ u = get_uidgid(&ug, "apache");
printf("%u = %u:%u\n", u, ug.uid, ug.gid);
ug.uid = ug.gid = 1111;
- u = get_uidgid(&ug, "apache:users", 0);
+ u = get_uidgid(&ug, "apache:users");
printf("%u = %u:%u\n", u, ug.uid, ug.gid);
ug.uid = ug.gid = 1111;
- u = get_uidgid(&ug, "apache:users", 0);
+ u = get_uidgid(&ug, "apache:users");
printf("%u = %u:%u\n", u, ug.uid, ug.gid);
return 0;
}
diff --git a/release/src/router/busybox/loginutils/Config.src b/release/src/router/busybox/loginutils/Config.src
index 9bf79afee2..efb954b6c3 100644
--- a/release/src/router/busybox/loginutils/Config.src
+++ b/release/src/router/busybox/loginutils/Config.src
@@ -5,8 +5,6 @@
menu "Login/Password Management Utilities"
-INSERT
-
config FEATURE_SHADOWPASSWDS
bool "Support for shadow passwords"
default y
@@ -93,239 +91,6 @@ config USE_BB_CRYPT_SHA
With this option off, login will fail password check for any
user which has password encrypted with these algorithms.
-config ADDUSER
- bool "adduser"
- default y
- help
- Utility for creating a new user account.
-
-config FEATURE_ADDUSER_LONG_OPTIONS
- bool "Enable long options"
- default y
- depends on ADDUSER && LONG_OPTS
- help
- Support long options for the adduser applet.
-
-config FEATURE_CHECK_NAMES
- bool "Enable sanity check on user/group names in adduser and addgroup"
- default n
- depends on ADDUSER || ADDGROUP
- help
- Enable sanity check on user and group names in adduser and addgroup.
- To avoid problems, the user or group name should consist only of
- letters, digits, underscores, periods, at signs and dashes,
- and not start with a dash (as defined by IEEE Std 1003.1-2001).
- For compatibility with Samba machine accounts "$" is also supported
- at the end of the user or group name.
-
-config FIRST_SYSTEM_ID
- int "First valid system uid or gid for adduser and addgroup"
- depends on ADDUSER || ADDGROUP
- range 0 64900
- default 100
- help
- First valid system uid or gid for adduser and addgroup
-
-config LAST_SYSTEM_ID
- int "Last valid system uid or gid for adduser and addgroup"
- depends on ADDUSER || ADDGROUP
- range 0 64900
- default 999
- help
- Last valid system uid or gid for adduser and addgroup
-
-config ADDGROUP
- bool "addgroup"
- default y
- help
- Utility for creating a new group account.
-
-config FEATURE_ADDGROUP_LONG_OPTIONS
- bool "Enable long options"
- default y
- depends on ADDGROUP && LONG_OPTS
- help
- Support long options for the addgroup applet.
-
-config FEATURE_ADDUSER_TO_GROUP
- bool "Support for adding users to groups"
- default y
- depends on ADDGROUP
- help
- If called with two non-option arguments,
- addgroup will add an existing user to an
- existing group.
-
-config DELUSER
- bool "deluser"
- default y
- help
- Utility for deleting a user account.
-
-config DELGROUP
- bool "delgroup"
- default y
- help
- Utility for deleting a group account.
-
-config FEATURE_DEL_USER_FROM_GROUP
- bool "Support for removing users from groups"
- default y
- depends on DELGROUP
- help
- If called with two non-option arguments, deluser
- or delgroup will remove an user from a specified group.
-
-config GETTY
- bool "getty"
- default y
- select FEATURE_SYSLOG
- help
- getty lets you log in on a tty. It is normally invoked by init.
-
- Note that you can save a few bytes by disabling it and
- using login applet directly.
- If you need to reset tty attributes before calling login,
- this script approximates getty:
-
- exec </dev/$1 >/dev/$1 2>&1 || exit 1
- reset
- stty sane; stty ispeed 38400; stty ospeed 38400
- printf "%s login: " "`hostname`"
- read -r login
- exec /bin/login "$login"
-
-config LOGIN
- bool "login"
- default y
- select FEATURE_SYSLOG
- help
- login is used when signing onto a system.
-
- Note that Busybox binary must be setuid root for this applet to
- work properly.
-
-config LOGIN_SESSION_AS_CHILD
- bool "Run logged in session in a child process"
- default y if PAM
- depends on LOGIN
- help
- Run the logged in session in a child process. This allows
- login to clean up things such as utmp entries or PAM sessions
- when the login session is complete. If you use PAM, you
- almost always would want this to be set to Y, else PAM session
- will not be cleaned up.
-
-config PAM
- bool "Support for PAM (Pluggable Authentication Modules)"
- default n
- depends on LOGIN
- help
- Use PAM in login(1) instead of direct access to password database.
-
-config LOGIN_SCRIPTS
- bool "Support for login scripts"
- depends on LOGIN
- default y
- help
- Enable this if you want login to execute $LOGIN_PRE_SUID_SCRIPT
- just prior to switching from root to logged-in user.
-
-config FEATURE_NOLOGIN
- bool "Support for /etc/nologin"
- default y
- depends on LOGIN
- help
- The file /etc/nologin is used by (some versions of) login(1).
- If it exists, non-root logins are prohibited.
-
-config FEATURE_SECURETTY
- bool "Support for /etc/securetty"
- default y
- depends on LOGIN
- help
- The file /etc/securetty is used by (some versions of) login(1).
- The file contains the device names of tty lines (one per line,
- without leading /dev/) on which root is allowed to login.
-
-config PASSWD
- bool "passwd"
- default y
- select FEATURE_SYSLOG
- help
- passwd changes passwords for user and group accounts. A normal user
- may only change the password for his/her own account, the super user
- may change the password for any account. The administrator of a group
- may change the password for the group.
-
- Note that Busybox binary must be setuid root for this applet to
- work properly.
-
-config FEATURE_PASSWD_WEAK_CHECK
- bool "Check new passwords for weakness"
- default y
- depends on PASSWD
- help
- With this option passwd will refuse new passwords which are "weak".
-
-config CRYPTPW
- bool "cryptpw"
- default y
- help
- Encrypts the given password with the crypt(3) libc function
- using the given salt. Debian has this utility under mkpasswd
- name. Busybox provides mkpasswd as an alias for cryptpw.
-
-config CHPASSWD
- bool "chpasswd"
- default y
- help
- Reads a file of user name and password pairs from standard input
- and uses this information to update a group of existing users.
-
-config FEATURE_DEFAULT_PASSWD_ALGO
- string "Default password encryption method (passwd -a, cryptpw -m parameter)"
- default "des"
- depends on PASSWD || CRYPTPW
- help
- Possible choices are "d[es]", "m[d5]", "s[ha256]" or "sha512".
-
-config SU
- bool "su"
- default y
- select FEATURE_SYSLOG
- help
- su is used to become another user during a login session.
- Invoked without a username, su defaults to becoming the super user.
-
- Note that Busybox binary must be setuid root for this applet to
- work properly.
-
-config FEATURE_SU_SYSLOG
- bool "Enable su to write to syslog"
- default y
- depends on SU
-
-config FEATURE_SU_CHECKS_SHELLS
- bool "Enable su to check user's shell to be listed in /etc/shells"
- depends on SU
- default y
-
-config SULOGIN
- bool "sulogin"
- default y
- select FEATURE_SYSLOG
- help
- sulogin is invoked when the system goes into single user
- mode (this is done through an entry in inittab).
-
-config VLOCK
- bool "vlock"
- default y
- help
- Build the "vlock" applet which allows you to lock (virtual) terminals.
-
- Note that Busybox binary must be setuid root for this applet to
- work properly.
+INSERT
endmenu
diff --git a/release/src/router/busybox/loginutils/Kbuild.src b/release/src/router/busybox/loginutils/Kbuild.src
index ef416a76fd..6b4fb74700 100644
--- a/release/src/router/busybox/loginutils/Kbuild.src
+++ b/release/src/router/busybox/loginutils/Kbuild.src
@@ -7,15 +7,3 @@
lib-y:=
INSERT
-lib-$(CONFIG_ADDGROUP) += addgroup.o
-lib-$(CONFIG_ADDUSER) += adduser.o
-lib-$(CONFIG_CRYPTPW) += cryptpw.o
-lib-$(CONFIG_CHPASSWD) += chpasswd.o
-lib-$(CONFIG_GETTY) += getty.o
-lib-$(CONFIG_LOGIN) += login.o
-lib-$(CONFIG_PASSWD) += passwd.o
-lib-$(CONFIG_SU) += su.o
-lib-$(CONFIG_SULOGIN) += sulogin.o
-lib-$(CONFIG_VLOCK) += vlock.o
-lib-$(CONFIG_DELUSER) += deluser.o
-lib-$(CONFIG_DELGROUP) += deluser.o
diff --git a/release/src/router/busybox/loginutils/add-remove-shell.c b/release/src/router/busybox/loginutils/add-remove-shell.c
index 9a1454430b..ce4a7bbd28 100644
--- a/release/src/router/busybox/loginutils/add-remove-shell.c
+++ b/release/src/router/busybox/loginutils/add-remove-shell.c
@@ -7,13 +7,6 @@
* Licensed under GPLv2 or later, see the LICENSE file in this source tree
* for details.
*/
-
-//applet:IF_ADD_SHELL( APPLET_ODDNAME(add-shell , add_remove_shell, BB_DIR_USR_BIN, BB_SUID_DROP, add_shell ))
-//applet:IF_REMOVE_SHELL(APPLET_ODDNAME(remove-shell, add_remove_shell, BB_DIR_USR_BIN, BB_SUID_DROP, remove_shell))
-
-//kbuild:lib-$(CONFIG_ADD_SHELL) += add-remove-shell.o
-//kbuild:lib-$(CONFIG_REMOVE_SHELL) += add-remove-shell.o
-
//config:config ADD_SHELL
//config: bool "add-shell"
//config: default y if DESKTOP
@@ -26,6 +19,12 @@
//config: help
//config: Remove shells from /etc/shells.
+//applet:IF_ADD_SHELL( APPLET_ODDNAME(add-shell , add_remove_shell, BB_DIR_USR_SBIN, BB_SUID_DROP, add_shell ))
+//applet:IF_REMOVE_SHELL(APPLET_ODDNAME(remove-shell, add_remove_shell, BB_DIR_USR_SBIN, BB_SUID_DROP, remove_shell))
+
+//kbuild:lib-$(CONFIG_ADD_SHELL) += add-remove-shell.o
+//kbuild:lib-$(CONFIG_REMOVE_SHELL) += add-remove-shell.o
+
//usage:#define add_shell_trivial_usage
//usage: "SHELL..."
//usage:#define add_shell_full_usage "\n\n"
@@ -100,7 +99,7 @@ int add_remove_shell_main(int argc UNUSED_PARAM, char **argv)
cpp++;
}
/* copy shell name from old to new file */
- printf("%s\n", line);
+ puts(line);
next_line:
free(line);
}
@@ -112,7 +111,7 @@ int add_remove_shell_main(int argc UNUSED_PARAM, char **argv)
char **cpp = argv;
while (*cpp) {
if (*cpp != dont_add)
- printf("%s\n", *cpp);
+ puts(*cpp);
cpp++;
}
}
diff --git a/release/src/router/busybox/loginutils/addgroup.c b/release/src/router/busybox/loginutils/addgroup.c
index b37270ff0f..4d4fc3f28c 100644
--- a/release/src/router/busybox/loginutils/addgroup.c
+++ b/release/src/router/busybox/loginutils/addgroup.c
@@ -9,11 +9,36 @@
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*
*/
+//config:config ADDGROUP
+//config: bool "addgroup"
+//config: default y
+//config: help
+//config: Utility for creating a new group account.
+//config:
+//config:config FEATURE_ADDGROUP_LONG_OPTIONS
+//config: bool "Enable long options"
+//config: default y
+//config: depends on ADDGROUP && LONG_OPTS
+//config: help
+//config: Support long options for the addgroup applet.
+//config:
+//config:config FEATURE_ADDUSER_TO_GROUP
+//config: bool "Support for adding users to groups"
+//config: default y
+//config: depends on ADDGROUP
+//config: help
+//config: If called with two non-option arguments,
+//config: addgroup will add an existing user to an
+//config: existing group.
+
+//applet:IF_ADDGROUP(APPLET(addgroup, BB_DIR_USR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_ADDGROUP) += addgroup.o
//usage:#define addgroup_trivial_usage
-//usage: "[-g GID] " IF_FEATURE_ADDUSER_TO_GROUP("[USER] ") "GROUP"
+//usage: "[-g GID] [-S] " IF_FEATURE_ADDUSER_TO_GROUP("[USER] ") "GROUP"
//usage:#define addgroup_full_usage "\n\n"
-//usage: "Add a group " IF_FEATURE_ADDUSER_TO_GROUP("or add a user to a group") "\n"
+//usage: "Add a group" IF_FEATURE_ADDUSER_TO_GROUP(" or add a user to a group") "\n"
//usage: "\n -g GID Group id"
//usage: "\n -S Create a system group"
@@ -22,14 +47,16 @@
#if CONFIG_LAST_SYSTEM_ID < CONFIG_FIRST_SYSTEM_ID
#error Bad LAST_SYSTEM_ID or FIRST_SYSTEM_ID in .config
#endif
+#if CONFIG_LAST_ID < CONFIG_LAST_SYSTEM_ID
+#error Bad LAST_ID or LAST_SYSTEM_ID in .config
+#endif
#define OPT_GID (1 << 0)
#define OPT_SYSTEM_ACCOUNT (1 << 1)
-/* We assume GID_T_MAX == INT_MAX */
static void xgroup_study(struct group *g)
{
- unsigned max = INT_MAX;
+ unsigned max = CONFIG_LAST_ID;
/* Make sure gr_name is unused */
if (getgrnam(g->gr_name)) {
@@ -46,7 +73,6 @@ static void xgroup_study(struct group *g)
max = CONFIG_LAST_SYSTEM_ID;
} else {
g->gr_gid = CONFIG_LAST_SYSTEM_ID + 1;
- max = 64999;
}
}
/* Check if the desired gid is free
@@ -125,7 +151,7 @@ int addgroup_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int addgroup_main(int argc UNUSED_PARAM, char **argv)
{
unsigned opts;
- unsigned gid = 0;
+ const char *gid = "0";
/* need to be root */
if (geteuid()) {
@@ -139,7 +165,7 @@ int addgroup_main(int argc UNUSED_PARAM, char **argv)
* addgroup -g num group
* addgroup user group
* Check for min, max and missing args */
- opt_complementary = "-1:?2:g+";
+ opt_complementary = "-1:?2";
opts = getopt32(argv, "g:S", &gid);
/* move past the commandline options */
argv += optind;
@@ -175,7 +201,7 @@ int addgroup_main(int argc UNUSED_PARAM, char **argv)
#endif /* ENABLE_FEATURE_ADDUSER_TO_GROUP */
{
die_if_bad_username(argv[0]);
- new_group(argv[0], gid);
+ new_group(argv[0], xatou_range(gid, 0, CONFIG_LAST_ID));
}
/* Reached only on success */
return EXIT_SUCCESS;
diff --git a/release/src/router/busybox/loginutils/adduser.c b/release/src/router/busybox/loginutils/adduser.c
index 1d082c8767..608fb8437a 100644
--- a/release/src/router/busybox/loginutils/adduser.c
+++ b/release/src/router/busybox/loginutils/adduser.c
@@ -7,11 +7,62 @@
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//config:config ADDUSER
+//config: bool "adduser"
+//config: default y
+//config: help
+//config: Utility for creating a new user account.
+//config:
+//config:config FEATURE_ADDUSER_LONG_OPTIONS
+//config: bool "Enable long options"
+//config: default y
+//config: depends on ADDUSER && LONG_OPTS
+//config: help
+//config: Support long options for the adduser applet.
+//config:
+//config:config FEATURE_CHECK_NAMES
+//config: bool "Enable sanity check on user/group names in adduser and addgroup"
+//config: default n
+//config: depends on ADDUSER || ADDGROUP
+//config: help
+//config: Enable sanity check on user and group names in adduser and addgroup.
+//config: To avoid problems, the user or group name should consist only of
+//config: letters, digits, underscores, periods, at signs and dashes,
+//config: and not start with a dash (as defined by IEEE Std 1003.1-2001).
+//config: For compatibility with Samba machine accounts "$" is also supported
+//config: at the end of the user or group name.
+//config:
+//config:config LAST_ID
+//config: int "Last valid uid or gid for adduser and addgroup"
+//config: depends on ADDUSER || ADDGROUP
+//config: default 60000
+//config: help
+//config: Last valid uid or gid for adduser and addgroup
+//config:
+//config:config FIRST_SYSTEM_ID
+//config: int "First valid system uid or gid for adduser and addgroup"
+//config: depends on ADDUSER || ADDGROUP
+//config: range 0 LAST_ID
+//config: default 100
+//config: help
+//config: First valid system uid or gid for adduser and addgroup
+//config:
+//config:config LAST_SYSTEM_ID
+//config: int "Last valid system uid or gid for adduser and addgroup"
+//config: depends on ADDUSER || ADDGROUP
+//config: range FIRST_SYSTEM_ID LAST_ID
+//config: default 999
+//config: help
+//config: Last valid system uid or gid for adduser and addgroup
+
+//applet:IF_ADDUSER(APPLET(adduser, BB_DIR_USR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_ADDUSER) += adduser.o
//usage:#define adduser_trivial_usage
-//usage: "[OPTIONS] USER"
+//usage: "[OPTIONS] USER [GROUP]"
//usage:#define adduser_full_usage "\n\n"
-//usage: "Add a user\n"
+//usage: "Create new user, or add USER to GROUP\n"
//usage: "\n -h DIR Home directory"
//usage: "\n -g GECOS GECOS field"
//usage: "\n -s SHELL Login shell"
@@ -20,12 +71,17 @@
//usage: "\n -D Don't assign a password"
//usage: "\n -H Don't create home directory"
//usage: "\n -u UID User id"
+//usage: "\n -k SKEL Skeleton directory (/etc/skel)"
#include "libbb.h"
#if CONFIG_LAST_SYSTEM_ID < CONFIG_FIRST_SYSTEM_ID
#error Bad LAST_SYSTEM_ID or FIRST_SYSTEM_ID in .config
#endif
+#if CONFIG_LAST_ID < CONFIG_LAST_SYSTEM_ID
+#error Bad LAST_ID or LAST_SYSTEM_ID in .config
+#endif
+
/* #define OPT_HOME (1 << 0) */ /* unused */
/* #define OPT_GECOS (1 << 1) */ /* unused */
@@ -35,13 +91,13 @@
#define OPT_SYSTEM_ACCOUNT (1 << 5)
#define OPT_DONT_MAKE_HOME (1 << 6)
#define OPT_UID (1 << 7)
+#define OPT_SKEL (1 << 8)
-/* We assume UID_T_MAX == INT_MAX */
/* remix */
/* recoded such that the uid may be passed in *p */
static void passwd_study(struct passwd *p)
{
- int max = UINT_MAX;
+ int max = CONFIG_LAST_ID;
if (getpwnam(p->pw_name)) {
bb_error_msg_and_die("%s '%s' in use", "user", p->pw_name);
@@ -54,7 +110,6 @@ static void passwd_study(struct passwd *p)
max = CONFIG_LAST_SYSTEM_ID;
} else {
p->pw_uid = CONFIG_LAST_SYSTEM_ID + 1;
- max = 64999;
}
}
/* check for a free uid (and maybe gid) */
@@ -80,7 +135,7 @@ static void passwd_study(struct passwd *p)
}
}
-static void addgroup_wrapper(struct passwd *p, const char *group_name)
+static int addgroup_wrapper(struct passwd *p, const char *group_name)
{
char *argv[6];
@@ -110,7 +165,7 @@ static void addgroup_wrapper(struct passwd *p, const char *group_name)
argv[5] = NULL;
}
- spawn_and_wait(argv);
+ return spawn_and_wait(argv);
}
static void passwd_wrapper(const char *login_name) NORETURN;
@@ -132,6 +187,7 @@ static const char adduser_longopts[] ALIGN1 =
"system\0" No_argument "S"
"no-create-home\0" No_argument "H"
"uid\0" Required_argument "u"
+ "skel\0" Required_argument "k"
;
#endif
@@ -147,6 +203,8 @@ int adduser_main(int argc UNUSED_PARAM, char **argv)
const char *usegroup = NULL;
char *p;
unsigned opts;
+ char *uid;
+ const char *skel = "/etc/skel";
#if ENABLE_FEATURE_ADDUSER_LONG_OPTIONS
applet_long_options = adduser_longopts;
@@ -162,22 +220,24 @@ int adduser_main(int argc UNUSED_PARAM, char **argv)
pw.pw_shell = (char *)get_shell_name();
pw.pw_dir = NULL;
- /* exactly one non-option arg */
+ /* at least one and at most two non-option args */
/* disable interactive passwd for system accounts */
- opt_complementary = "=1:SD:u+";
- if (sizeof(pw.pw_uid) == sizeof(int)) {
- opts = getopt32(argv, "h:g:s:G:DSHu:", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup, &pw.pw_uid);
- } else {
- unsigned uid;
- opts = getopt32(argv, "h:g:s:G:DSHu:", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup, &uid);
- if (opts & OPT_UID) {
- pw.pw_uid = uid;
- }
- }
+ opt_complementary = "-1:?2:SD";
+ opts = getopt32(argv, "h:g:s:G:DSHu:k:", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup, &uid, &skel);
+ if (opts & OPT_UID)
+ pw.pw_uid = xatou_range(uid, 0, CONFIG_LAST_ID);
+
argv += optind;
+ pw.pw_name = argv[0];
+
+ if (!opts && argv[1]) {
+ /* if called with two non-option arguments, adduser
+ * will add an existing user to an existing group.
+ */
+ return addgroup_wrapper(&pw, argv[1]);
+ }
/* fill in the passwd struct */
- pw.pw_name = argv[0];
die_if_bad_username(pw.pw_name);
if (!pw.pw_dir) {
/* create string for $HOME if not specified already */
@@ -205,7 +265,6 @@ int adduser_main(int argc UNUSED_PARAM, char **argv)
}
if (ENABLE_FEATURE_CLEAN_UP)
free(p);
-
#if ENABLE_FEATURE_SHADOWPASSWDS
/* /etc/shadow fields:
* 1. username
@@ -246,8 +305,9 @@ int adduser_main(int argc UNUSED_PARAM, char **argv)
NULL
};
/* Be silent on any errors (like: no /etc/skel) */
- logmode = LOGMODE_NONE;
- copy_file("/etc/skel", pw.pw_dir, FILEUTILS_RECUR);
+ if (!(opts & OPT_SKEL))
+ logmode = LOGMODE_NONE;
+ copy_file(skel, pw.pw_dir, FILEUTILS_RECUR);
logmode = LOGMODE_STDIO;
chown_main(4, (char**)args);
}
diff --git a/release/src/router/busybox/loginutils/chpasswd.c b/release/src/router/busybox/loginutils/chpasswd.c
index 54ed73795a..2d268be67c 100644
--- a/release/src/router/busybox/loginutils/chpasswd.c
+++ b/release/src/router/busybox/loginutils/chpasswd.c
@@ -5,27 +5,46 @@
* Written for SLIND (from passwd.c) by Alexander Shishkin <virtuoso@slind.org>
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
-#include "libbb.h"
+//config:config CHPASSWD
+//config: bool "chpasswd"
+//config: default y
+//config: help
+//config: Reads a file of user name and password pairs from standard input
+//config: and uses this information to update a group of existing users.
+//config:
+//config:config FEATURE_DEFAULT_PASSWD_ALGO
+//config: string "Default password encryption method (passwd -a, cryptpw -m parameter)"
+//config: default "des"
+//config: depends on PASSWD || CRYPTPW
+//config: help
+//config: Possible choices are "d[es]", "m[d5]", "s[ha256]" or "sha512".
+
+//applet:IF_CHPASSWD(APPLET(chpasswd, BB_DIR_USR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_CHPASSWD) += chpasswd.o
//usage:#define chpasswd_trivial_usage
-//usage: IF_LONG_OPTS("[--md5|--encrypted]") IF_NOT_LONG_OPTS("[-m|-e]")
+//usage: IF_LONG_OPTS("[--md5|--encrypted|--crypt-method]") IF_NOT_LONG_OPTS("[-m|-e|-c]")
//usage:#define chpasswd_full_usage "\n\n"
//usage: "Read user:password from stdin and update /etc/passwd\n"
//usage: IF_LONG_OPTS(
-//usage: "\n -e,--encrypted Supplied passwords are in encrypted form"
-//usage: "\n -m,--md5 Use MD5 encryption instead of DES"
+//usage: "\n -e,--encrypted Supplied passwords are in encrypted form"
+//usage: "\n -m,--md5 Use MD5 encryption instead of DES"
+//usage: "\n -c,--crypt-method Use the specified method to encrypt the passwords"
//usage: )
//usage: IF_NOT_LONG_OPTS(
//usage: "\n -e Supplied passwords are in encrypted form"
//usage: "\n -m Use MD5 encryption instead of DES"
+//usage: "\n -c Use the specified method to encrypt the passwords"
//usage: )
-//TODO: implement -c ALGO
+#include "libbb.h"
#if ENABLE_LONG_OPTS
static const char chpasswd_longopts[] ALIGN1 =
- "encrypted\0" No_argument "e"
- "md5\0" No_argument "m"
+ "encrypted\0" No_argument "e"
+ "md5\0" No_argument "m"
+ "crypt-method\0" Required_argument "c"
;
#endif
@@ -36,14 +55,15 @@ int chpasswd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int chpasswd_main(int argc UNUSED_PARAM, char **argv)
{
char *name;
+ const char *algo = CONFIG_FEATURE_DEFAULT_PASSWD_ALGO;
int opt;
if (getuid() != 0)
bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
- opt_complementary = "m--e:e--m";
+ opt_complementary = "m--ec:e--mc:c--em";
IF_LONG_OPTS(applet_long_options = chpasswd_longopts;)
- opt = getopt32(argv, "em");
+ opt = getopt32(argv, "emc:", &algo);
while ((name = xmalloc_fgetline(stdin)) != NULL) {
char *free_me;
@@ -59,15 +79,14 @@ int chpasswd_main(int argc UNUSED_PARAM, char **argv)
free_me = NULL;
if (!(opt & OPT_ENC)) {
- char salt[sizeof("$N$XXXXXXXX")];
+ char salt[MAX_PW_SALT_LEN];
- crypt_make_salt(salt, 1);
if (opt & OPT_MD5) {
- salt[0] = '$';
- salt[1] = '1';
- salt[2] = '$';
- crypt_make_salt(salt + 3, 4);
+ /* Force MD5 if the -m flag is set */
+ algo = "md5";
}
+
+ crypt_make_pw_salt(salt, algo);
free_me = pass = pw_encrypt(pass, salt, 0);
}
@@ -86,7 +105,7 @@ int chpasswd_main(int argc UNUSED_PARAM, char **argv)
if (rc < 0)
bb_error_msg_and_die("an error occurred updating password for %s", name);
if (rc)
- bb_info_msg("Password for '%s' changed", name);
+ bb_error_msg("password for '%s' changed", name);
logmode = LOGMODE_STDIO;
free(name);
free(free_me);
diff --git a/release/src/router/busybox/loginutils/cryptpw.c b/release/src/router/busybox/loginutils/cryptpw.c
index a36f920f40..23a1884f42 100644
--- a/release/src/router/busybox/loginutils/cryptpw.c
+++ b/release/src/router/busybox/loginutils/cryptpw.c
@@ -9,6 +9,27 @@
*
* Licensed under GPLv2, see file LICENSE in this source tree.
*/
+//config:config CRYPTPW
+//config: bool "cryptpw"
+//config: default y
+//config: help
+//config: Encrypts the given password with the crypt(3) libc function
+//config: using the given salt.
+//config:
+//config:config MKPASSWD
+//config: bool "mkpasswd"
+//config: default y
+//config: help
+//config: Encrypts the given password with the crypt(3) libc function
+//config: using the given salt. Debian has this utility under mkpasswd
+//config: name. Busybox provides mkpasswd as an alias for cryptpw.
+
+//applet:IF_CRYPTPW(APPLET(cryptpw, BB_DIR_USR_BIN, BB_SUID_DROP))
+// APPLET_ODDNAME:name main location suid_type help
+//applet:IF_MKPASSWD(APPLET_ODDNAME(mkpasswd, cryptpw, BB_DIR_USR_BIN, BB_SUID_DROP, cryptpw))
+
+//kbuild:lib-$(CONFIG_CRYPTPW) += cryptpw.o
+//kbuild:lib-$(CONFIG_MKPASSWD) += cryptpw.o
//usage:#define cryptpw_trivial_usage
//usage: "[OPTIONS] [PASSWORD] [SALT]"
@@ -28,25 +49,6 @@
//usage: "\n -S SALT"
//usage: )
-/* mkpasswd is an alias to cryptpw */
-//usage:#define mkpasswd_trivial_usage
-//usage: "[OPTIONS] [PASSWORD] [SALT]"
-/* We do support -s, we just don't mention it */
-//usage:#define mkpasswd_full_usage "\n\n"
-//usage: "Crypt PASSWORD using crypt(3)\n"
-//usage: IF_LONG_OPTS(
-//usage: "\n -P,--password-fd=N Read password from fd N"
-/* //usage: "\n -s,--stdin Use stdin; like -P0" */
-//usage: "\n -m,--method=TYPE Encryption method"
-//usage: "\n -S,--salt=SALT"
-//usage: )
-//usage: IF_NOT_LONG_OPTS(
-//usage: "\n -P N Read password from fd N"
-/* //usage: "\n -s Use stdin; like -P0" */
-//usage: "\n -m TYPE Encryption method TYPE"
-//usage: "\n -S SALT"
-//usage: )
-
#include "libbb.h"
/* Debian has 'mkpasswd' utility, manpage says:
@@ -92,6 +94,7 @@ int cryptpw_main(int argc UNUSED_PARAM, char **argv)
{
char salt[MAX_PW_SALT_LEN];
char *salt_ptr;
+ char *password;
const char *opt_m, *opt_S;
int fd;
@@ -123,15 +126,19 @@ int cryptpw_main(int argc UNUSED_PARAM, char **argv)
xmove_fd(fd, STDIN_FILENO);
- puts(pw_encrypt(
- argv[0] ? argv[0] : (
- /* Only mkpasswd, and only from tty, prompts.
- * Otherwise it is a plain read. */
- (isatty(STDIN_FILENO) && applet_name[0] == 'm')
+ password = argv[0];
+ if (!password) {
+ /* Only mkpasswd, and only from tty, prompts.
+ * Otherwise it is a plain read. */
+ password = (ENABLE_MKPASSWD && isatty(STDIN_FILENO) && applet_name[0] == 'm')
? bb_ask_stdin("Password: ")
: xmalloc_fgetline(stdin)
- ),
- salt, 1));
+ ;
+ /* may still be NULL on EOF/error */
+ }
+
+ if (password)
+ puts(pw_encrypt(password, salt, 1));
return EXIT_SUCCESS;
}
diff --git a/release/src/router/busybox/loginutils/deluser.c b/release/src/router/busybox/loginutils/deluser.c
index e39ac55069..7c3caf9e35 100644
--- a/release/src/router/busybox/loginutils/deluser.c
+++ b/release/src/router/busybox/loginutils/deluser.c
@@ -7,13 +7,38 @@
* Copyright (C) 2007 by Tito Ragusa <farmatito@tiscali.it>
*
* Licensed under GPLv2, see file LICENSE in this source tree.
- *
*/
+//config:config DELUSER
+//config: bool "deluser"
+//config: default y
+//config: help
+//config: Utility for deleting a user account.
+//config:
+//config:config DELGROUP
+//config: bool "delgroup"
+//config: default y
+//config: help
+//config: Utility for deleting a group account.
+//config:
+//config:config FEATURE_DEL_USER_FROM_GROUP
+//config: bool "Support for removing users from groups"
+//config: default y
+//config: depends on DELGROUP
+//config: help
+//config: If called with two non-option arguments, deluser
+//config: or delgroup will remove an user from a specified group.
+
+//applet:IF_DELUSER(APPLET(deluser, BB_DIR_USR_SBIN, BB_SUID_DROP))
+//applet:IF_DELGROUP(APPLET_ODDNAME(delgroup, deluser, BB_DIR_USR_SBIN, BB_SUID_DROP, delgroup))
+
+//kbuild:lib-$(CONFIG_DELUSER) += deluser.o
+//kbuild:lib-$(CONFIG_DELGROUP) += deluser.o
//usage:#define deluser_trivial_usage
-//usage: "USER"
+//usage: IF_LONG_OPTS("[--remove-home] ") "USER"
//usage:#define deluser_full_usage "\n\n"
//usage: "Delete USER from the system"
+// --remove-home is self-explanatory enough to put it in --help
//usage:#define delgroup_trivial_usage
//usage: IF_FEATURE_DEL_USER_FROM_GROUP("[USER] ")"GROUP"
@@ -37,6 +62,19 @@ int deluser_main(int argc, char **argv)
/* Are we deluser or delgroup? */
int do_deluser = (ENABLE_DELUSER && (!ENABLE_DELGROUP || applet_name[3] == 'u'));
+#if !ENABLE_LONG_OPTS
+ const int opt_delhome = 0;
+#else
+ int opt_delhome = 0;
+ if (do_deluser) {
+ applet_long_options =
+ "remove-home\0" No_argument "\xff";
+ opt_delhome = getopt32(argv, "");
+ argv += opt_delhome;
+ argc -= opt_delhome;
+ }
+#endif
+
if (geteuid() != 0)
bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
@@ -55,10 +93,14 @@ int deluser_main(int argc, char **argv)
case 2:
if (do_deluser) {
/* "deluser USER" */
- xgetpwnam(name); /* bail out if USER is wrong */
+ struct passwd *pw;
+
+ pw = xgetpwnam(name); /* bail out if USER is wrong */
pfile = bb_path_passwd_file;
if (ENABLE_FEATURE_SHADOWPASSWDS)
sfile = bb_path_shadow_file;
+ if (opt_delhome)
+ remove_file(pw->pw_dir, FILEUTILS_RECUR);
} else {
struct group *gr;
do_delgroup:
@@ -73,12 +115,11 @@ int deluser_main(int argc, char **argv)
if (!member) {
/* "delgroup GROUP" */
struct passwd *pw;
- struct passwd pwent;
/* Check if the group is in use */
-#define passwd_buf bb_common_bufsiz1
- while (!getpwent_r(&pwent, passwd_buf, sizeof(passwd_buf), &pw)) {
- if (pwent.pw_gid == gr->gr_gid)
- bb_error_msg_and_die("'%s' still has '%s' as their primary group!", pwent.pw_name, name);
+ while ((pw = getpwent()) != NULL) {
+ if (pw->pw_gid == gr->gr_gid)
+ bb_error_msg_and_die("'%s' still has '%s' as their primary group!",
+ pw->pw_name, name);
}
//endpwent();
}
@@ -97,16 +138,22 @@ int deluser_main(int argc, char **argv)
}
} while (ENABLE_FEATURE_SHADOWPASSWDS && pfile);
- if (ENABLE_DELGROUP && do_deluser > 0) {
- /* "deluser USER" also should try to delete
- * same-named group. IOW: do "delgroup USER"
- */
+ if (do_deluser > 0) {
+ /* Delete user from all groups */
+ if (update_passwd(bb_path_group_file, NULL, NULL, name) == -1)
+ return EXIT_FAILURE;
+
+ if (ENABLE_DELGROUP) {
+ /* "deluser USER" also should try to delete
+ * same-named group. IOW: do "delgroup USER"
+ */
// On debian deluser is a perl script that calls userdel.
// From man userdel:
// If USERGROUPS_ENAB is defined to yes in /etc/login.defs, userdel will
// delete the group with the same name as the user.
- do_deluser = -1;
- goto do_delgroup;
+ do_deluser = -1;
+ goto do_delgroup;
+ }
}
return EXIT_SUCCESS;
}
diff --git a/release/src/router/busybox/loginutils/getty.c b/release/src/router/busybox/loginutils/getty.c
index bbb5a96b42..b10bdbdbf3 100644
--- a/release/src/router/busybox/loginutils/getty.c
+++ b/release/src/router/busybox/loginutils/getty.c
@@ -21,6 +21,28 @@
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//config:config GETTY
+//config: bool "getty"
+//config: default y
+//config: select FEATURE_SYSLOG
+//config: help
+//config: getty lets you log in on a tty. It is normally invoked by init.
+//config:
+//config: Note that you can save a few bytes by disabling it and
+//config: using login applet directly.
+//config: If you need to reset tty attributes before calling login,
+//config: this script approximates getty:
+//config:
+//config: exec </dev/$1 >/dev/$1 2>&1 || exit 1
+//config: reset
+//config: stty sane; stty ispeed 38400; stty ospeed 38400
+//config: printf "%s login: " "`hostname`"
+//config: read -r login
+//config: exec /bin/login "$login"
+
+//applet:IF_GETTY(APPLET(getty, BB_DIR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_GETTY) += getty.o
#include "libbb.h"
#include <syslog.h>
@@ -334,18 +356,19 @@ static void finalize_tty_attrs(void)
* observed to improve backspacing through Unicode chars
*/
- /* line buffered input (NL or EOL or EOF chars end a line);
- * recognize INT/QUIT/SUSP chars;
- * echo input chars;
- * echo BS-SP-BS on erase character;
- * echo kill char specially, not as ^c (ECHOKE controls how exactly);
- * erase all input via BS-SP-BS on kill char (else go to next line)
+ /* ICANON line buffered input (NL or EOL or EOF chars end a line);
+ * ISIG recognize INT/QUIT/SUSP chars;
+ * ECHO echo input chars;
+ * ECHOE echo BS-SP-BS on erase character;
+ * ECHOK echo kill char specially, not as ^c (ECHOKE controls how exactly);
+ * ECHOKE erase all input via BS-SP-BS on kill char (else go to next line)
+ * ECHOCTL Echo ctrl chars as ^c (else echo verbatim:
+ * e.g. up arrow emits "ESC-something" and thus moves cursor up!)
*/
- G.tty_attrs.c_lflag |= ICANON | ISIG | ECHO | ECHOE | ECHOK | ECHOKE;
+ G.tty_attrs.c_lflag |= ICANON | ISIG | ECHO | ECHOE | ECHOK | ECHOKE | ECHOCTL;
/* Other bits in c_lflag:
* XCASE Map uppercase to \lowercase [tried, doesn't work]
* ECHONL Echo NL even if ECHO is not set
- * ECHOCTL Echo ctrl chars as ^c (else don't echo) - maybe set this?
* ECHOPRT On erase, echo erased chars
* [qwe<BS><BS><BS> input looks like "qwe\ewq/" on screen]
* NOFLSH Don't flush input buffer after interrupt or quit chars
@@ -519,6 +542,11 @@ static void alarm_handler(int sig UNUSED_PARAM)
_exit(EXIT_SUCCESS);
}
+static void sleep10(void)
+{
+ sleep(10);
+}
+
int getty_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int getty_main(int argc UNUSED_PARAM, char **argv)
{
@@ -548,8 +576,25 @@ int getty_main(int argc UNUSED_PARAM, char **argv)
* a session leader - which is quite possible for getty!
*/
pid = getpid();
- if (getsid(0) != pid)
+ if (getsid(0) != pid) {
+ //for debugging:
+ //bb_perror_msg_and_die("setsid failed:"
+ // " pid %d ppid %d"
+ // " sid %d pgid %d",
+ // pid, getppid(),
+ // getsid(0), getpgid(0));
bb_perror_msg_and_die("setsid");
+ /*
+ * When we can end up here?
+ * Example: setsid() fails when run alone in interactive shell:
+ * # getty 115200 /dev/tty2
+ * because shell's child (getty) is put in a new process group.
+ * But doesn't fail if shell is not interactive
+ * (and therefore doesn't create process groups for pipes),
+ * or if getty is not the first process in the process group:
+ * # true | getty 115200 /dev/tty2
+ */
+ }
/* Looks like we are already a session leader.
* In this case (setsid failed) we may still have ctty,
* and it may be different from tty we need to control!
@@ -581,7 +626,7 @@ int getty_main(int argc UNUSED_PARAM, char **argv)
close(n--);
/* Logging. We want special flavor of error_msg_and_die */
- die_sleep = 10;
+ die_func = sleep10;
msg_eol = "\r\n";
/* most likely will internally use fd #3 in CLOEXEC mode: */
openlog(applet_name, LOG_PID, LOG_AUTH);
@@ -688,6 +733,6 @@ int getty_main(int argc UNUSED_PARAM, char **argv)
/* We use PATH because we trust that root doesn't set "bad" PATH,
* and getty is not suid-root applet */
/* With -n, logname == NULL, and login will ask for username instead */
- BB_EXECLP(G.login, G.login, "--", logname, NULL);
+ BB_EXECLP(G.login, G.login, "--", logname, (char *)0);
bb_error_msg_and_die("can't execute '%s'", G.login);
}
diff --git a/release/src/router/busybox/loginutils/login.c b/release/src/router/busybox/loginutils/login.c
index bf43f3aba7..94b6c45db3 100644
--- a/release/src/router/busybox/loginutils/login.c
+++ b/release/src/router/busybox/loginutils/login.c
@@ -2,16 +2,67 @@
/*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//config:config LOGIN
+//config: bool "login"
+//config: default y
+//config: select FEATURE_SYSLOG
+//config: help
+//config: login is used when signing onto a system.
+//config:
+//config: Note that Busybox binary must be setuid root for this applet to
+//config: work properly.
+//config:
+//config:config LOGIN_SESSION_AS_CHILD
+//config: bool "Run logged in session in a child process"
+//config: default y if PAM
+//config: depends on LOGIN
+//config: help
+//config: Run the logged in session in a child process. This allows
+//config: login to clean up things such as utmp entries or PAM sessions
+//config: when the login session is complete. If you use PAM, you
+//config: almost always would want this to be set to Y, else PAM session
+//config: will not be cleaned up.
+//config:
+//config:config LOGIN_SCRIPTS
+//config: bool "Support for login scripts"
+//config: depends on LOGIN
+//config: default y
+//config: help
+//config: Enable this if you want login to execute $LOGIN_PRE_SUID_SCRIPT
+//config: just prior to switching from root to logged-in user.
+//config:
+//config:config FEATURE_NOLOGIN
+//config: bool "Support for /etc/nologin"
+//config: default y
+//config: depends on LOGIN
+//config: help
+//config: The file /etc/nologin is used by (some versions of) login(1).
+//config: If it exists, non-root logins are prohibited.
+//config:
+//config:config FEATURE_SECURETTY
+//config: bool "Support for /etc/securetty"
+//config: default y
+//config: depends on LOGIN
+//config: help
+//config: The file /etc/securetty is used by (some versions of) login(1).
+//config: The file contains the device names of tty lines (one per line,
+//config: without leading /dev/) on which root is allowed to login.
+
+//applet:/* Needs to be run by root or be suid root - needs to change uid and gid: */
+//applet:IF_LOGIN(APPLET(login, BB_DIR_BIN, BB_SUID_REQUIRE))
+
+//kbuild:lib-$(CONFIG_LOGIN) += login.o
//usage:#define login_trivial_usage
//usage: "[-p] [-h HOST] [[-f] USER]"
//usage:#define login_full_usage "\n\n"
//usage: "Begin a new session on the system\n"
//usage: "\n -f Don't authenticate (user already authenticated)"
-//usage: "\n -h Name of the remote host"
+//usage: "\n -h HOST Host user came from (for network logins)"
//usage: "\n -p Preserve environment"
#include "libbb.h"
+#include "common_bufsiz.h"
#include <syslog.h>
#include <sys/resource.h>
@@ -28,6 +79,49 @@
* Apparently they like to confuse people. */
# include <security/pam_appl.h>
# include <security/pam_misc.h>
+
+# if 0
+/* This supposedly can be used to avoid double password prompt,
+ * if used instead of standard misc_conv():
+ *
+ * "When we want to authenticate first with local method and then with tacacs for example,
+ * the password is asked for local method and if not good is asked a second time for tacacs.
+ * So if we want to authenticate a user with tacacs, and the user exists localy, the password is
+ * asked two times before authentication is accepted."
+ *
+ * However, code looks shaky. For example, why misc_conv() return value is ignored?
+ * Are msg[i] and resp[i] indexes handled correctly?
+ */
+static char *passwd = NULL;
+static int my_conv(int num_msg, const struct pam_message **msg,
+ struct pam_response **resp, void *data)
+{
+ int i;
+ for (i = 0; i < num_msg; i++) {
+ switch (msg[i]->msg_style) {
+ case PAM_PROMPT_ECHO_OFF:
+ if (passwd == NULL) {
+ misc_conv(num_msg, msg, resp, data);
+ passwd = xstrdup(resp[i]->resp);
+ return PAM_SUCCESS;
+ }
+
+ resp[0] = xzalloc(sizeof(struct pam_response));
+ resp[0]->resp = passwd;
+ passwd = NULL;
+ resp[0]->resp_retcode = PAM_SUCCESS;
+ resp[1] = NULL;
+ return PAM_SUCCESS;
+
+ default:
+ break;
+ }
+ }
+
+ return PAM_SUCCESS;
+}
+# endif
+
static const struct pam_conv conv = {
misc_conv,
NULL
@@ -37,15 +131,16 @@ static const struct pam_conv conv = {
enum {
TIMEOUT = 60,
EMPTY_USERNAME_COUNT = 10,
- USERNAME_SIZE = 32,
+ /* Some users found 32 chars limit to be too low: */
+ USERNAME_SIZE = 64,
TTYNAME_SIZE = 32,
};
struct globals {
struct termios tty_attrs;
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
-#define INIT_G() do { } while (0)
+#define G (*(struct globals*)bb_common_bufsiz1)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
#if ENABLE_FEATURE_NOLOGIN
@@ -419,7 +514,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
* Note that reads (in no-echo mode) trash tty attributes.
* If we get interrupted by SIGALRM, we need to restore attrs.
*/
- if (correct_password(pw))
+ if (ask_and_check_password(pw) > 0)
break;
#endif /* ENABLE_PAM */
auth_failed:
@@ -453,7 +548,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
else {
if (safe_waitpid(child_pid, NULL, 0) == -1)
bb_perror_msg("waitpid");
- update_utmp(child_pid, DEAD_PROCESS, NULL, NULL, NULL);
+ update_utmp_DEAD_PROCESS(child_pid);
}
IF_PAM(login_pam_end(pamh);)
return 0;
@@ -488,7 +583,8 @@ int login_main(int argc UNUSED_PARAM, char **argv)
}
#endif
- motd();
+ if (access(".hushlogin", F_OK) != 0)
+ motd();
if (pw->pw_uid == 0)
syslog(LOG_INFO, "root login%s", fromhost);
diff --git a/release/src/router/busybox/loginutils/passwd.c b/release/src/router/busybox/loginutils/passwd.c
index b83db00836..52b66ca505 100644
--- a/release/src/router/busybox/loginutils/passwd.c
+++ b/release/src/router/busybox/loginutils/passwd.c
@@ -2,6 +2,30 @@
/*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//config:config PASSWD
+//config: bool "passwd"
+//config: default y
+//config: select FEATURE_SYSLOG
+//config: help
+//config: passwd changes passwords for user and group accounts. A normal user
+//config: may only change the password for his/her own account, the super user
+//config: may change the password for any account. The administrator of a group
+//config: may change the password for the group.
+//config:
+//config: Note that Busybox binary must be setuid root for this applet to
+//config: work properly.
+//config:
+//config:config FEATURE_PASSWD_WEAK_CHECK
+//config: bool "Check new passwords for weakness"
+//config: default y
+//config: depends on PASSWD
+//config: help
+//config: With this option passwd will refuse new passwords which are "weak".
+
+//applet:/* Needs to be run by root or be suid root - needs to change /etc/{passwd,shadow}: */
+//applet:IF_PASSWD(APPLET(passwd, BB_DIR_USR_BIN, BB_SUID_REQUIRE))
+
+//kbuild:lib-$(CONFIG_PASSWD) += passwd.o
//usage:#define passwd_trivial_usage
//usage: "[OPTIONS] [USER]"
@@ -15,11 +39,7 @@
#include "libbb.h"
#include <syslog.h>
-
-static void nuke_str(char *str)
-{
- if (str) memset(str, 0, strlen(str));
-}
+#include <sys/resource.h> /* setrlimit */
static char* new_password(const struct passwd *pw, uid_t myuid, const char *algo)
{
@@ -210,7 +230,7 @@ int passwd_main(int argc UNUSED_PARAM, char **argv)
/* LOGMODE_BOTH */
if (rc < 0)
bb_error_msg_and_die("can't update password file %s", filename);
- bb_info_msg("Password for %s changed by %s", name, myname);
+ bb_error_msg("password for %s changed by %s", name, myname);
/*if (ENABLE_FEATURE_CLEAN_UP) free(newp); - can't, it may be non-malloced */
skip:
diff --git a/release/src/router/busybox/loginutils/su.c b/release/src/router/busybox/loginutils/su.c
index 57ea738f4c..3c0e8c100a 100644
--- a/release/src/router/busybox/loginutils/su.c
+++ b/release/src/router/busybox/loginutils/su.c
@@ -4,9 +4,31 @@
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
-
-#include "libbb.h"
-#include <syslog.h>
+//config:config SU
+//config: bool "su"
+//config: default y
+//config: select FEATURE_SYSLOG
+//config: help
+//config: su is used to become another user during a login session.
+//config: Invoked without a username, su defaults to becoming the super user.
+//config:
+//config: Note that Busybox binary must be setuid root for this applet to
+//config: work properly.
+//config:
+//config:config FEATURE_SU_SYSLOG
+//config: bool "Enable su to write to syslog"
+//config: default y
+//config: depends on SU
+//config:
+//config:config FEATURE_SU_CHECKS_SHELLS
+//config: bool "Enable su to check user's shell to be listed in /etc/shells"
+//config: depends on SU
+//config: default y
+
+//applet:/* Needs to be run by root or be suid root - needs to change uid and gid: */
+//applet:IF_SU(APPLET(su, BB_DIR_BIN, BB_SUID_REQUIRE))
+
+//kbuild:lib-$(CONFIG_SU) += su.o
//usage:#define su_trivial_usage
//usage: "[OPTIONS] [-] [USER]"
@@ -17,6 +39,9 @@
//usage: "\n -c CMD Command to pass to 'sh -c'"
//usage: "\n -s SH Shell to use instead of user's default"
+#include "libbb.h"
+#include <syslog.h>
+
#if ENABLE_FEATURE_SU_CHECKS_SHELLS
/* Return 1 if SHELL is a restricted shell (one not returned by
* getusershell), else 0, meaning it is a standard shell. */
@@ -93,7 +118,7 @@ int su_main(int argc UNUSED_PARAM, char **argv)
pw = xgetpwnam(opt_username);
- if (cur_uid == 0 || correct_password(pw)) {
+ if (cur_uid == 0 || ask_and_check_password(pw) > 0) {
if (ENABLE_FEATURE_SU_SYSLOG)
syslog(LOG_NOTICE, "%c %s %s:%s",
'+', tty, old_user, opt_username);
@@ -101,6 +126,7 @@ int su_main(int argc UNUSED_PARAM, char **argv)
if (ENABLE_FEATURE_SU_SYSLOG)
syslog(LOG_NOTICE, "%c %s %s:%s",
'-', tty, old_user, opt_username);
+ bb_do_delay(LOGIN_FAIL_DELAY);
bb_error_msg_and_die("incorrect password");
}
@@ -131,7 +157,8 @@ int su_main(int argc UNUSED_PARAM, char **argv)
change_identity(pw);
setup_environment(opt_shell,
((flags & SU_OPT_l) / SU_OPT_l * SETUP_ENV_CLEARENV)
- + (!(flags & SU_OPT_mp) * SETUP_ENV_CHANGEENV),
+ + (!(flags & SU_OPT_mp) * SETUP_ENV_CHANGEENV)
+ + (!(flags & SU_OPT_l) * SETUP_ENV_NO_CHDIR),
pw);
IF_SELINUX(set_current_security_context(NULL);)
diff --git a/release/src/router/busybox/loginutils/sulogin.c b/release/src/router/busybox/loginutils/sulogin.c
index bd2b09eed8..f324695513 100644
--- a/release/src/router/busybox/loginutils/sulogin.c
+++ b/release/src/router/busybox/loginutils/sulogin.c
@@ -4,6 +4,17 @@
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//config:config SULOGIN
+//config: bool "sulogin"
+//config: default y
+//config: select FEATURE_SYSLOG
+//config: help
+//config: sulogin is invoked when the system goes into single user
+//config: mode (this is done through an entry in inittab).
+
+//applet:IF_SULOGIN(APPLET(sulogin, BB_DIR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_SULOGIN) += sulogin.o
//usage:#define sulogin_trivial_usage
//usage: "[-t N] [TTY]"
@@ -14,24 +25,20 @@
#include "libbb.h"
#include <syslog.h>
-//static void catchalarm(int UNUSED_PARAM junk)
-//{
-// exit(EXIT_FAILURE);
-//}
-
-
int sulogin_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int sulogin_main(int argc UNUSED_PARAM, char **argv)
{
- char *cp;
int timeout = 0;
struct passwd *pwd;
const char *shell;
-#if ENABLE_FEATURE_SHADOWPASSWDS
- /* Using _r function to avoid pulling in static buffers */
- char buffer[256];
- struct spwd spw;
-#endif
+
+ /* Note: sulogin is not a suid app. It is meant to be run by init
+ * for single user / emergency mode. init starts it as root.
+ * Normal users (potentially malisious ones) can only run it under
+ * their UID, therefore no paranoia here is warranted:
+ * $LD_LIBRARY_PATH in env, TTY = /dev/sda
+ * are no more dangerous here than in e.g. cp applet.
+ */
logmode = LOGMODE_BOTH;
openlog(applet_name, 0, LOG_AUTH);
@@ -48,59 +55,31 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv)
dup(0);
}
- /* Malicious use like "sulogin /dev/sda"? */
- if (!isatty(0) || !isatty(1) || !isatty(2)) {
- logmode = LOGMODE_SYSLOG;
- bb_error_msg_and_die("not a tty");
- }
-
- /* Clear dangerous stuff, set PATH */
- sanitize_env_if_suid();
-
pwd = getpwuid(0);
if (!pwd) {
- goto auth_error;
- }
-
-#if ENABLE_FEATURE_SHADOWPASSWDS
- {
- /* getspnam_r may return 0 yet set result to NULL.
- * At least glibc 2.4 does this. Be extra paranoid here. */
- struct spwd *result = NULL;
- int r = getspnam_r(pwd->pw_name, &spw, buffer, sizeof(buffer), &result);
- if (r || !result) {
- goto auth_error;
- }
- pwd->pw_passwd = result->sp_pwdp;
+ bb_error_msg_and_die("no password entry for root");
}
-#endif
while (1) {
- char *encrypted;
int r;
- /* cp points to a static buffer that is zeroed every time */
- cp = bb_ask(STDIN_FILENO, timeout,
- "Give root password for system maintenance\n"
- "(or type Control-D for normal startup):");
-
- if (!cp || !*cp) {
- bb_info_msg("Normal startup");
+ r = ask_and_check_password_extended(pwd, timeout,
+ "Give root password for system maintenance\n"
+ "(or type Control-D for normal startup):"
+ );
+ if (r < 0) {
+ /* ^D, ^C, timeout, or read error */
+ bb_error_msg("normal startup");
return 0;
}
- encrypted = pw_encrypt(cp, pwd->pw_passwd, 1);
- r = strcmp(encrypted, pwd->pw_passwd);
- free(encrypted);
- if (r == 0) {
+ if (r > 0) {
break;
}
bb_do_delay(LOGIN_FAIL_DELAY);
- bb_info_msg("Login incorrect");
+ bb_error_msg("Login incorrect");
}
- memset(cp, 0, strlen(cp));
-// signal(SIGALRM, SIG_DFL);
- bb_info_msg("System Maintenance Mode");
+ bb_error_msg("starting shell for system maintenance");
IF_SELINUX(renew_current_security_context());
@@ -112,7 +91,4 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv)
/* Exec login shell with no additional parameters. Never returns. */
run_shell(shell, 1, NULL, NULL);
-
- auth_error:
- bb_error_msg_and_die("no password entry for root");
}
diff --git a/release/src/router/busybox/loginutils/vlock.c b/release/src/router/busybox/loginutils/vlock.c
index 75af9390e1..52ae607c9e 100644
--- a/release/src/router/busybox/loginutils/vlock.c
+++ b/release/src/router/busybox/loginutils/vlock.c
@@ -13,7 +13,21 @@
* minimalistic vlock.
*/
/* Fixed by Erik Andersen to do passwords the tinylogin way...
- * It now works with md5, sha1, etc passwords. */
+ * It now works with md5, sha1, etc passwords.
+ */
+//config:config VLOCK
+//config: bool "vlock"
+//config: default y
+//config: help
+//config: Build the "vlock" applet which allows you to lock (virtual) terminals.
+//config:
+//config: Note that Busybox binary must be setuid root for this applet to
+//config: work properly.
+
+//applet:/* Needs to be run by root or be suid root - needs to change uid and gid: */
+//applet:IF_VLOCK(APPLET(vlock, BB_DIR_USR_BIN, BB_SUID_REQUIRE))
+
+//kbuild:lib-$(CONFIG_VLOCK) += vlock.o
//usage:#define vlock_trivial_usage
//usage: "[-a]"
@@ -104,7 +118,7 @@ int vlock_main(int argc UNUSED_PARAM, char **argv)
/* "s" if -a, else "": */ "s" + !option_mask32,
pw->pw_name
);
- if (correct_password(pw)) {
+ if (ask_and_check_password(pw) > 0) {
break;
}
bb_do_delay(LOGIN_FAIL_DELAY);
diff --git a/release/src/router/busybox/mailutils/mail.c b/release/src/router/busybox/mailutils/mail.c
index 199f644077..a7e43c0d12 100644
--- a/release/src/router/busybox/mailutils/mail.c
+++ b/release/src/router/busybox/mailutils/mail.c
@@ -154,7 +154,7 @@ void FAST_FUNC encode_base64(char *fname, const char *text, const char *eol)
// encode the buffer we just read in
bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64);
if (fname) {
- printf("%s\n", eol);
+ puts(eol);
} else {
src_buf += size;
len -= size;
diff --git a/release/src/router/busybox/mailutils/reformime.c b/release/src/router/busybox/mailutils/reformime.c
index 8e7d455f60..86b2cfed34 100644
--- a/release/src/router/busybox/mailutils/reformime.c
+++ b/release/src/router/busybox/mailutils/reformime.c
@@ -134,7 +134,6 @@ static int parse(const char *boundary, char **argv)
if (strcasecmp(type + 10, "mixed") != 0)
bb_error_msg_and_die("no support of content type '%s'", type);
parse(xfind_token(tokens, "boundary"), argv);
-
} else {
/* No, process one non-multipart section */
char *end;
diff --git a/release/src/router/busybox/mailutils/sendmail.c b/release/src/router/busybox/mailutils/sendmail.c
index c426e9d851..5143fac8f9 100644
--- a/release/src/router/busybox/mailutils/sendmail.c
+++ b/release/src/router/busybox/mailutils/sendmail.c
@@ -15,7 +15,8 @@
//usage: "Read email from stdin and send it\n"
//usage: "\nStandard options:"
//usage: "\n -t Read additional recipients from message body"
-//usage: "\n -f SENDER Sender (required)"
+//usage: "\n -f SENDER For use in MAIL FROM:<sender>. Can be empty string"
+//usage: "\n Default: -auUSER, or username of current UID"
//usage: "\n -o OPTIONS Various options. -oi implied, others are ignored"
//usage: "\n -i -oi synonym. implied and ignored"
//usage: "\n"
@@ -40,6 +41,52 @@
//usage: "\nUse makemime to create emails with attachments"
//usage: )
+/* Currently we don't sanitize or escape user-supplied SENDER and RECIPIENT_EMAILs.
+ * We may need to do so. For one, '.' in usernames seems to require escaping!
+ *
+ * From http://cr.yp.to/smtp/address.html:
+ *
+ * SMTP offers three ways to encode a character inside an address:
+ *
+ * "safe": the character, if it is not <>()[].,;:@, backslash,
+ * double-quote, space, or an ASCII control character;
+ * "quoted": the character, if it is not \012, \015, backslash,
+ * or double-quote; or
+ * "slashed": backslash followed by the character.
+ *
+ * An encoded box part is either (1) a sequence of one or more slashed
+ * or safe characters or (2) a double quote, a sequence of zero or more
+ * slashed or quoted characters, and a double quote. It represents
+ * the concatenation of the characters encoded inside it.
+ *
+ * For example, the encoded box parts
+ * angels
+ * \a\n\g\e\l\s
+ * "\a\n\g\e\l\s"
+ * "angels"
+ * "ang\els"
+ * all represent the 6-byte string "angels", and the encoded box parts
+ * a\,comma
+ * \a\,\c\o\m\m\a
+ * "a,comma"
+ * all represent the 7-byte string "a,comma".
+ *
+ * An encoded address contains
+ * the byte <;
+ * optionally, a route followed by a colon;
+ * an encoded box part, the byte @, and a domain; and
+ * the byte >.
+ *
+ * It represents an Internet mail address, given by concatenating
+ * the string represented by the encoded box part, the byte @,
+ * and the domain. For example, the encoded addresses
+ * <God@heaven.af.mil>
+ * <\God@heaven.af.mil>
+ * <"God"@heaven.af.mil>
+ * <@gateway.af.mil,@uucp.local:"\G\o\d"@heaven.af.mil>
+ * all represent the Internet mail address "God@heaven.af.mil".
+ */
+
#include "libbb.h"
#include "mail.h"
@@ -92,35 +139,90 @@ static int smtp_check(const char *fmt, int code)
// strip argument of bad chars
static char *sane_address(char *str)
{
- char *s = str;
- char *p = s;
+ char *s;
+
+ trim(str);
+ s = str;
while (*s) {
- if (isalnum(*s) || '_' == *s || '-' == *s || '.' == *s || '@' == *s) {
- *p++ = *s;
+ if (!isalnum(*s) && !strchr("_-.@", *s)) {
+ bb_error_msg("bad address '%s'", str);
+ /* returning "": */
+ str[0] = '\0';
+ return str;
}
s++;
}
- *p = '\0';
return str;
}
+// check for an address inside angle brackets, if not found fall back to normal
+static char *angle_address(char *str)
+{
+ char *s, *e;
+
+ trim(str);
+ e = last_char_is(str, '>');
+ if (e) {
+ s = strrchr(str, '<');
+ if (s) {
+ *e = '\0';
+ str = s + 1;
+ }
+ }
+ return sane_address(str);
+}
+
static void rcptto(const char *s)
{
+ if (!*s)
+ return;
// N.B. we don't die if recipient is rejected, for the other recipients may be accepted
if (250 != smtp_checkp("RCPT TO:<%s>", s, -1))
bb_error_msg("Bad recipient: <%s>", s);
}
+// send to a list of comma separated addresses
+static void rcptto_list(const char *list)
+{
+ char *str = xstrdup(list);
+ char *s = str;
+ char prev = 0;
+ int in_quote = 0;
+
+ while (*s) {
+ char ch = *s++;
+
+ if (ch == '"' && prev != '\\') {
+ in_quote = !in_quote;
+ } else if (!in_quote && ch == ',') {
+ s[-1] = '\0';
+ rcptto(angle_address(str));
+ str = s;
+ }
+ prev = ch;
+ }
+ if (prev != ',')
+ rcptto(angle_address(str));
+ free(str);
+}
+
int sendmail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int sendmail_main(int argc UNUSED_PARAM, char **argv)
{
char *opt_connect = opt_connect;
- char *opt_from;
+ char *opt_from = NULL;
char *s;
llist_t *list = NULL;
char *host = sane_address(safe_gethostname());
unsigned nheaders = 0;
int code;
+ enum {
+ HDR_OTHER = 0,
+ HDR_TOCC,
+ HDR_BCC,
+ } last_hdr = 0;
+ int check_hdr;
+ int has_to = 0;
enum {
//--- standard options
@@ -144,8 +246,8 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv)
G.fp0 = xfdopen_for_read(3);
// parse options
- // -v is a counter, -f is required. -H and -S are mutually exclusive, -a is a list
- opt_complementary = "vv:f:w+:H--S:S--H:a::";
+ // -v is a counter, -H and -S are mutually exclusive, -a is a list
+ opt_complementary = "vv:w+:H--S:S--H:a::";
// N.B. since -H and -S are mutually exclusive they do not interfere in opt_connect
// -a is for ssmtp (http://downloads.openwrt.org/people/nico/man/man8/ssmtp.8.html) compatibility,
// it is still under development.
@@ -168,7 +270,7 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv)
// G.method = xstrdup(a+1);
}
// N.B. list == NULL here
- //bb_info_msg("OPT[%x] AU[%s], AP[%s], AM[%s], ARGV[%s]", opts, au, ap, am, *argv);
+ //bb_error_msg("OPT[%x] AU[%s], AP[%s], AM[%s], ARGV[%s]", opts, au, ap, am, *argv);
// connect to server
@@ -224,7 +326,6 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv)
// we should start with modern EHLO
if (250 != smtp_checkp("EHLO %s", host, -1))
smtp_checkp("HELO %s", host, 250);
- free(host);
// perform authentication
if (opts & OPT_a) {
@@ -249,13 +350,14 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv)
// Since reading from console may defeat usability, the solution is either to read from a predefined
// file descriptor (e.g. 4), or again from a secured file.
- // got no sender address? -> use system username as a resort
- // N.B. we marked -f as required option!
- //if (!G.user) {
- // // N.B. IMHO getenv("USER") can be way easily spoofed!
- // G.user = xuid2uname(getuid());
- // opt_from = xasprintf("%s@%s", G.user, domain);
- //}
+ // got no sender address? use auth name, then UID username as a last resort
+ if (!opt_from) {
+ opt_from = xasprintf("%s@%s",
+ G.user ? G.user : xuid2uname(getuid()),
+ xgethostbyname(host)->h_name);
+ }
+ free(host);
+
smtp_checkp("MAIL FROM:<%s>", opt_from, 250);
// process message
@@ -273,7 +375,7 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv)
// N.B. we need to escape the leading dot regardless of
// whether it is single or not character on the line
if ('.' == s[0] /*&& '\0' == s[1] */)
- printf(".");
+ bb_putchar('.');
// dump read line
send_r_n(s);
free(s);
@@ -282,23 +384,36 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv)
// analyze headers
// To: or Cc: headers add recipients
+ check_hdr = (0 == strncasecmp("To:", s, 3));
+ has_to |= check_hdr;
if (opts & OPT_t) {
- if (0 == strncasecmp("To:", s, 3) || 0 == strncasecmp("Bcc:" + 1, s, 3)) {
- rcptto(sane_address(s+3));
+ if (check_hdr || 0 == strncasecmp("Bcc:" + 1, s, 3)) {
+ rcptto_list(s+3);
+ last_hdr = HDR_TOCC;
goto addheader;
}
// Bcc: header adds blind copy (hidden) recipient
if (0 == strncasecmp("Bcc:", s, 4)) {
- rcptto(sane_address(s+4));
+ rcptto_list(s+4);
free(s);
+ last_hdr = HDR_BCC;
continue; // N.B. Bcc: vanishes from headers!
}
}
- if (strchr(s, ':') || (list && isspace(s[0]))) {
+ check_hdr = (list && isspace(s[0]));
+ if (strchr(s, ':') || check_hdr) {
// other headers go verbatim
// N.B. RFC2822 2.2.3 "Long Header Fields" allows for headers to occupy several lines.
// Continuation is denoted by prefixing additional lines with whitespace(s).
// Thanks (stefan.seyfried at googlemail.com) for pointing this out.
+ if (check_hdr && last_hdr != HDR_OTHER) {
+ rcptto_list(s+1);
+ if (last_hdr == HDR_BCC)
+ continue;
+ // N.B. Bcc: vanishes from headers!
+ } else {
+ last_hdr = HDR_OTHER;
+ }
addheader:
// N.B. we allow MAX_HEADERS generic headers at most to prevent attacks
if (MAX_HEADERS && ++nheaders >= MAX_HEADERS)
@@ -309,12 +424,27 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv)
// so stop "analyze headers" mode
reenter:
// put recipients specified on cmdline
+ check_hdr = 1;
while (*argv) {
char *t = sane_address(*argv);
rcptto(t);
//if (MAX_HEADERS && ++nheaders >= MAX_HEADERS)
// goto bail;
- llist_add_to_end(&list, xasprintf("To: %s", t));
+ if (!has_to) {
+ const char *hdr;
+
+ if (check_hdr && argv[1])
+ hdr = "To: %s,";
+ else if (check_hdr)
+ hdr = "To: %s";
+ else if (argv[1])
+ hdr = "To: %s," + 3;
+ else
+ hdr = "To: %s" + 3;
+ llist_add_to_end(&list,
+ xasprintf(hdr, t));
+ check_hdr = 0;
+ }
argv++;
}
// enter "put message" mode
diff --git a/release/src/router/busybox/miscutils/Config.src b/release/src/router/busybox/miscutils/Config.src
index a51ef1b706..06f1c52ba0 100644
--- a/release/src/router/busybox/miscutils/Config.src
+++ b/release/src/router/busybox/miscutils/Config.src
@@ -133,40 +133,6 @@ config CHRT
manipulate real-time attributes of a process.
This requires sched_{g,s}etparam support in your libc.
-config CROND
- bool "crond"
- default y
- select FEATURE_SYSLOG
- help
- Crond is a background daemon that parses individual crontab
- files and executes commands on behalf of the users in question.
- This is a port of dcron from slackware. It uses files of the
- format /var/spool/cron/crontabs/<username> files, for example:
- $ cat /var/spool/cron/crontabs/root
- # Run daily cron jobs at 4:40 every day:
- 40 4 * * * /etc/cron/daily > /dev/null 2>&1
-
-config FEATURE_CROND_D
- bool "Support option -d to redirect output to stderr"
- depends on CROND
- default y
- help
- -d sets loglevel to 0 (most verbose) and directs all output to stderr.
-
-config FEATURE_CROND_CALL_SENDMAIL
- bool "Report command output via email (using sendmail)"
- default y
- depends on CROND
- help
- Command output will be sent to corresponding user via email.
-
-config FEATURE_CROND_DIR
- string "crond spool directory"
- default "/var/spool/cron"
- depends on CROND || CRONTAB
- help
- Location of crond spool.
-
config CRONTAB
bool "crontab"
default y
@@ -342,23 +308,13 @@ config LAST
help
'last' displays a list of the last users that logged into the system.
-choice
- prompt "Choose last implementation"
- depends on LAST
- default FEATURE_LAST_FANCY
-
-config FEATURE_LAST_SMALL
- bool "small"
- help
- This is a small version of last with just the basic set of
- features.
-
config FEATURE_LAST_FANCY
- bool "huge"
+ bool "Turn on output of extra information"
+ default y
+ depends on LAST
help
'last' displays detailed information about the last users that
logged into the system (mimics sysvinit last). +900 bytes.
-endchoice
config HDPARM
bool "hdparm"
@@ -503,18 +459,6 @@ config READAHEAD
As readahead(2) blocks until each file has been read, it is best to
run this applet as a background job.
-config RFKILL
- bool "rfkill"
- default n # doesn't build on Ubuntu 9.04
- select PLATFORM_LINUX
- help
- Enable/disable wireless devices.
-
- rfkill list : list all wireless devices
- rfkill list bluetooth : list all bluetooth devices
- rfkill list 1 : list device corresponding to the given index
- rfkill block|unblock wlan : block/unblock all wlan(wifi) devices
-
config RUNLEVEL
bool "runlevel"
default y
@@ -545,22 +489,6 @@ config STRINGS
strings prints the printable character sequences for each file
specified.
-config TASKSET
- bool "taskset"
- default n # doesn't build on some non-x86 targets (m68k)
- help
- Retrieve or set a processes's CPU affinity.
- This requires sched_{g,s}etaffinity support in your libc.
-
-config FEATURE_TASKSET_FANCY
- bool "Fancy output"
- default y
- depends on TASKSET
- help
- Add code for fancy output. This merely silences a compiler-warning
- and adds about 135 Bytes. May be needed for machines with alot
- of CPUs.
-
config TIME
bool "time"
default y
@@ -591,13 +519,6 @@ config VOLNAME
help
Prints a CD-ROM volume name.
-config WALL
- bool "wall"
- default y
- depends on FEATURE_UTMP
- help
- Write a message to all users that are logged in.
-
config WATCHDOG
bool "watchdog"
default y
@@ -610,18 +531,4 @@ config WATCHDOG
certain amount of time, the watchdog device assumes the system has
hung, and will cause the hardware to reboot.
-config MDMM
- bool "MDMM Utility"
- default n
- help
- The md/mm utility can be used to read/write memory and memory
- mapped registers.
-
-config ETHREG
- bool "Ethreg Utility"
- default n
- help
- The ethreg utility can be used to read/write MAC and PHY registers
- to change the duplex and speed setting for individual PHYS.
-
endmenu
diff --git a/release/src/router/busybox/miscutils/Kbuild.src b/release/src/router/busybox/miscutils/Kbuild.src
index a911878f81..503f549047 100644
--- a/release/src/router/busybox/miscutils/Kbuild.src
+++ b/release/src/router/busybox/miscutils/Kbuild.src
@@ -12,7 +12,6 @@ lib-$(CONFIG_BBCONFIG) += bbconfig.o
lib-$(CONFIG_BEEP) += beep.o
lib-$(CONFIG_CHAT) += chat.o
lib-$(CONFIG_CHRT) += chrt.o
-lib-$(CONFIG_CROND) += crond.o
lib-$(CONFIG_CRONTAB) += crontab.o
lib-$(CONFIG_DC) += dc.o
lib-$(CONFIG_DEVFSD) += devfsd.o
@@ -26,8 +25,13 @@ lib-$(CONFIG_FLASH_UNLOCK) += flash_lock_unlock.o
lib-$(CONFIG_IONICE) += ionice.o
lib-$(CONFIG_HDPARM) += hdparm.o
lib-$(CONFIG_INOTIFYD) += inotifyd.o
-lib-$(CONFIG_FEATURE_LAST_SMALL)+= last.o
-lib-$(CONFIG_FEATURE_LAST_FANCY)+= last_fancy.o
+
+ifeq ($(CONFIG_FEATURE_LAST_FANCY),y)
+lib-$(CONFIG_FEATURE_LAST_FANCY) += last_fancy.o
+else
+lib-$(CONFIG_LAST) += last.o
+endif
+
lib-$(CONFIG_LESS) += less.o
lib-$(CONFIG_MAKEDEVS) += makedevs.o
lib-$(CONFIG_MAN) += man.o
@@ -36,17 +40,12 @@ lib-$(CONFIG_MOUNTPOINT) += mountpoint.o
lib-$(CONFIG_MT) += mt.o
lib-$(CONFIG_RAIDAUTORUN) += raidautorun.o
lib-$(CONFIG_READAHEAD) += readahead.o
-lib-$(CONFIG_RFKILL) += rfkill.o
lib-$(CONFIG_RUNLEVEL) += runlevel.o
lib-$(CONFIG_RX) += rx.o
lib-$(CONFIG_SETSID) += setsid.o
lib-$(CONFIG_STRINGS) += strings.o
-lib-$(CONFIG_TASKSET) += taskset.o
lib-$(CONFIG_TIME) += time.o
lib-$(CONFIG_TIMEOUT) += timeout.o
lib-$(CONFIG_TTYSIZE) += ttysize.o
lib-$(CONFIG_VOLNAME) += volname.o
-lib-$(CONFIG_WALL) += wall.o
lib-$(CONFIG_WATCHDOG) += watchdog.o
-lib-$(CONFIG_MDMM) += mdmm.o
-lib-$(CONFIG_ETHREG) += ethreg.o
diff --git a/release/src/router/busybox/miscutils/adjtimex.c b/release/src/router/busybox/miscutils/adjtimex.c
index c8816e9e7c..058aa9a5cd 100644
--- a/release/src/router/busybox/miscutils/adjtimex.c
+++ b/release/src/router/busybox/miscutils/adjtimex.c
@@ -14,12 +14,12 @@
//usage:#define adjtimex_trivial_usage
//usage: "[-q] [-o OFF] [-f FREQ] [-p TCONST] [-t TICK]"
//usage:#define adjtimex_full_usage "\n\n"
-//usage: "Read and optionally set system timebase parameters. See adjtimex(2)\n"
+//usage: "Read or set kernel time variables. See adjtimex(2)\n"
//usage: "\n -q Quiet"
//usage: "\n -o OFF Time offset, microseconds"
//usage: "\n -f FREQ Frequency adjust, integer kernel units (65536 is 1ppm)"
-//usage: "\n (positive values make clock run faster)"
//usage: "\n -t TICK Microseconds per tick, usually 10000"
+//usage: "\n (positive -t or -f values make clock run faster)"
//usage: "\n -p TCONST"
#include "libbb.h"
@@ -29,7 +29,7 @@
# include <sys/timex.h>
#endif
-static const uint16_t statlist_bit[] = {
+static const uint16_t statlist_bit[] ALIGN2 = {
STA_PLL,
STA_PPSFREQ,
STA_PPSTIME,
@@ -45,7 +45,7 @@ static const uint16_t statlist_bit[] = {
STA_CLOCKERR,
0
};
-static const char statlist_name[] =
+static const char statlist_name[] ALIGN1 =
"PLL" "\0"
"PPSFREQ" "\0"
"PPSTIME" "\0"
@@ -61,7 +61,7 @@ static const char statlist_name[] =
"CLOCKERR"
;
-static const char ret_code_descript[] =
+static const char ret_code_descript[] ALIGN1 =
"clock synchronized" "\0"
"insert leap second" "\0"
"delete leap second" "\0"
@@ -111,13 +111,13 @@ int adjtimex_main(int argc UNUSED_PARAM, char **argv)
}
if (!(opt & OPT_quiet)) {
- int sep;
+ const char *sep;
const char *name;
printf(
" mode: %d\n"
- "-o offset: %ld\n"
- "-f frequency: %ld\n"
+ "-o offset: %ld us\n"
+ "-f freq.adjust: %ld (65536 = 1ppm)\n"
" maxerror: %ld\n"
" esterror: %ld\n"
" status: %d (",
@@ -125,15 +125,14 @@ int adjtimex_main(int argc UNUSED_PARAM, char **argv)
txc.esterror, txc.status);
/* representative output of next code fragment:
- "PLL | PPSTIME" */
+ * "PLL | PPSTIME"
+ */
name = statlist_name;
- sep = 0;
+ sep = "";
for (i = 0; statlist_bit[i]; i++) {
if (txc.status & statlist_bit[i]) {
- if (sep)
- fputs(" | ", stdout);
- fputs(name, stdout);
- sep = 1;
+ printf("%s%s", sep, name);
+ sep = " | ";
}
name += strlen(name) + 1;
}
@@ -143,9 +142,9 @@ int adjtimex_main(int argc UNUSED_PARAM, char **argv)
descript = nth_string(ret_code_descript, ret);
printf(")\n"
"-p timeconstant: %ld\n"
- " precision: %ld\n"
+ " precision: %ld us\n"
" tolerance: %ld\n"
- "-t tick: %ld\n"
+ "-t tick: %ld us\n"
" time.tv_sec: %ld\n"
" time.tv_usec: %ld\n"
" return value: %d (%s)\n",
diff --git a/release/src/router/busybox/miscutils/beep.c b/release/src/router/busybox/miscutils/beep.c
index 910e03e1b4..18b160cc46 100644
--- a/release/src/router/busybox/miscutils/beep.c
+++ b/release/src/router/busybox/miscutils/beep.c
@@ -88,7 +88,7 @@ int beep_main(int argc, char **argv)
bb_show_usage();
}
while (rep) {
-//bb_info_msg("rep[%d] freq=%d, length=%d, delay=%d", rep, freq, length, delay);
+//bb_error_msg("rep[%d] freq=%d, length=%d, delay=%d", rep, freq, length, delay);
xioctl(speaker, KIOCSOUND, (void*)(uintptr_t)tickrate_div_freq);
usleep(1000 * length);
ioctl(speaker, KIOCSOUND, (void*)0);
diff --git a/release/src/router/busybox/miscutils/chat.c b/release/src/router/busybox/miscutils/chat.c
index ce994f870f..6b429f2a64 100644
--- a/release/src/router/busybox/miscutils/chat.c
+++ b/release/src/router/busybox/miscutils/chat.c
@@ -17,6 +17,7 @@
//usage: "chat '' ATZ OK ATD123456 CONNECT '' ogin: pppuser word: ppppass '~'"
#include "libbb.h"
+#include "common_bufsiz.h"
// default timeout: 45 sec
#define DEFAULT_CHAT_TIMEOUT 45*1000
@@ -285,9 +286,10 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
&& poll(&pfd, 1, timeout) > 0
&& (pfd.revents & POLLIN)
) {
-#define buf bb_common_bufsiz1
llist_t *l;
ssize_t delta;
+#define buf bb_common_bufsiz1
+ setup_common_bufsiz();
// read next char from device
if (safe_read(STDIN_FILENO, buf+buf_len, 1) > 0) {
@@ -296,7 +298,7 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
full_write(record_fd, buf+buf_len, 1);
}
// dump device input if ECHO ON
- if (echo > 0) {
+ if (echo) {
// if (buf[buf_len] < ' ') {
// full_write(STDERR_FILENO, "^", 1);
// buf[buf_len] += '@';
diff --git a/release/src/router/busybox/miscutils/chrt.c b/release/src/router/busybox/miscutils/chrt.c
index 91b5397c48..f2f559fd72 100644
--- a/release/src/router/busybox/miscutils/chrt.c
+++ b/release/src/router/busybox/miscutils/chrt.c
@@ -23,9 +23,6 @@
#include <sched.h>
#include "libbb.h"
-#ifndef _POSIX_PRIORITY_SCHEDULING
-#warning your system may be foobared
-#endif
static const struct {
int policy;
diff --git a/release/src/router/busybox/miscutils/conspy.c b/release/src/router/busybox/miscutils/conspy.c
index 1a46a4340a..f6468c116b 100644
--- a/release/src/router/busybox/miscutils/conspy.c
+++ b/release/src/router/busybox/miscutils/conspy.c
@@ -42,6 +42,7 @@
//usage: "\n -y LINE Starting line"
#include "libbb.h"
+#include "common_bufsiz.h"
#include <sys/kd.h>
#define ESC "\033"
@@ -363,7 +364,6 @@ int conspy_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int conspy_main(int argc UNUSED_PARAM, char **argv)
{
char tty_name[sizeof(DEV_TTY "NN")];
-#define keybuf bb_common_bufsiz1
struct termios termbuf;
unsigned opts;
unsigned ttynum;
@@ -382,6 +382,9 @@ int conspy_main(int argc UNUSED_PARAM, char **argv)
applet_long_options = getopt_longopts;
#endif
+#define keybuf bb_common_bufsiz1
+ setup_common_bufsiz();
+
INIT_G();
strcpy(G.vcsa_name, DEV_VCSA);
@@ -513,7 +516,7 @@ int conspy_main(int argc UNUSED_PARAM, char **argv)
default:
// Read the keys pressed
k = keybuf + G.key_count;
- bytes_read = read(G.kbd_fd, k, sizeof(keybuf) - G.key_count);
+ bytes_read = read(G.kbd_fd, k, COMMON_BUFSIZE - G.key_count);
if (bytes_read < 0)
goto abort;
diff --git a/release/src/router/busybox/miscutils/crond.c b/release/src/router/busybox/miscutils/crond.c
index a0b73c7749..f96c96ee7b 100644
--- a/release/src/router/busybox/miscutils/crond.c
+++ b/release/src/router/busybox/miscutils/crond.c
@@ -1,7 +1,5 @@
/* vi: set sw=4 ts=4: */
/*
- * crond -d[#] -c <crondir> -f -b
- *
* run as root, but NOT setuid root
*
* Copyright 1994 Matthew Dillon (dillon@apollo.west.oic.com)
@@ -10,6 +8,43 @@
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//config:config CROND
+//config: bool "crond"
+//config: default y
+//config: select FEATURE_SYSLOG
+//config: help
+//config: Crond is a background daemon that parses individual crontab
+//config: files and executes commands on behalf of the users in question.
+//config: This is a port of dcron from slackware. It uses files of the
+//config: format /var/spool/cron/crontabs/<username> files, for example:
+//config: $ cat /var/spool/cron/crontabs/root
+//config: # Run daily cron jobs at 4:40 every day:
+//config: 40 4 * * * /etc/cron/daily > /dev/null 2>&1
+//config:
+//config:config FEATURE_CROND_D
+//config: bool "Support option -d to redirect output to stderr"
+//config: depends on CROND
+//config: default y
+//config: help
+//config: -d N sets loglevel (0:most verbose) and directs all output to stderr.
+//config:
+//config:config FEATURE_CROND_CALL_SENDMAIL
+//config: bool "Report command output via email (using sendmail)"
+//config: default y
+//config: depends on CROND
+//config: help
+//config: Command output will be sent to corresponding user via email.
+//config:
+//config:config FEATURE_CROND_DIR
+//config: string "crond spool directory"
+//config: default "/var/spool/cron"
+//config: depends on CROND || CRONTAB
+//config: help
+//config: Location of crond spool.
+
+//applet:IF_CROND(APPLET(crond, BB_DIR_USR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_CROND) += crond.o
//usage:#define crond_trivial_usage
//usage: "-fbS -l N " IF_FEATURE_CROND_D("-d N ") "-L LOGFILE -c DIR"
@@ -17,14 +52,15 @@
//usage: " -f Foreground"
//usage: "\n -b Background (default)"
//usage: "\n -S Log to syslog (default)"
-//usage: "\n -l Set log level. 0 is the most verbose, default 8"
+//usage: "\n -l N Set log level. Most verbose:0, default:8"
//usage: IF_FEATURE_CROND_D(
-//usage: "\n -d Set log level, log to stderr"
+//usage: "\n -d N Set log level, log to stderr"
//usage: )
-//usage: "\n -L Log to file"
-//usage: "\n -c Working dir"
+//usage: "\n -L FILE Log to FILE"
+//usage: "\n -c DIR Cron dir. Default:"CONFIG_FEATURE_CROND_DIR"/crontabs"
#include "libbb.h"
+#include "common_bufsiz.h"
#include <syslog.h>
/* glibc frees previous setenv'ed value when we do next setenv()
@@ -36,7 +72,7 @@
#endif
-#define TMPDIR CONFIG_FEATURE_CROND_DIR
+#define CRON_DIR CONFIG_FEATURE_CROND_DIR
#define CRONTABS CONFIG_FEATURE_CROND_DIR "/crontabs"
#ifndef SENDMAIL
# define SENDMAIL "sendmail"
@@ -69,6 +105,7 @@ typedef struct CronLine {
int cl_empty_mail_size; /* size of mail header only, 0 if no mailfile */
char *cl_mailto; /* whom to mail results, may be NULL */
#endif
+ char *cl_shell;
/* ordered by size, not in natural order. makes code smaller: */
char cl_Dow[7]; /* 0-6, beginning sunday */
char cl_Mons[12]; /* 0-11 */
@@ -90,12 +127,6 @@ enum {
OPT_c = (1 << 5),
OPT_d = (1 << 6) * ENABLE_FEATURE_CROND_D,
};
-#if ENABLE_FEATURE_CROND_D
-# define DebugOpt (option_mask32 & OPT_d)
-#else
-# define DebugOpt 0
-#endif
-
struct globals {
unsigned log_level; /* = 8; */
@@ -106,64 +137,67 @@ struct globals {
#if SETENV_LEAKS
char *env_var_user;
char *env_var_home;
+ char *env_var_shell;
+ char *env_var_logname;
#endif
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define INIT_G() do { \
+ setup_common_bufsiz(); \
G.log_level = 8; \
G.crontab_dir_name = CRONTABS; \
} while (0)
+/* Log levels:
+ * 0 is the most verbose, default 8.
+ * For some reason, in fact only 5, 7 and 8 are used.
+ */
+static void crondlog(unsigned level, const char *msg, va_list va)
+{
+ if (level >= G.log_level) {
+ /*
+ * We are called only for info meesages.
+ * Warnings/errors use plain bb_[p]error_msg's, which
+ * need not touch syslog_level
+ * (they are ok with LOG_ERR default).
+ */
+ syslog_level = LOG_INFO;
+ bb_verror_msg(msg, va, /* strerr: */ NULL);
+ syslog_level = LOG_ERR;
+ }
+}
-/* 0 is the most verbose, default 8 */
-#define LVL5 "\x05"
-#define LVL7 "\x07"
-#define LVL8 "\x08"
-#define WARN9 "\x49"
-#define DIE9 "\xc9"
-/* level >= 20 is "error" */
-#define ERR20 "\x14"
+static void log5(const char *msg, ...)
+{
+ va_list va;
+ va_start(va, msg);
+ crondlog(4, msg, va);
+ va_end(va);
+}
-static void crondlog(const char *ctl, ...) __attribute__ ((format (printf, 1, 2)));
-static void crondlog(const char *ctl, ...)
+static void log7(const char *msg, ...)
{
va_list va;
- int level = (ctl[0] & 0x1f);
-
- va_start(va, ctl);
- if (level >= (int)G.log_level) {
- /* Debug mode: all to (non-redirected) stderr, */
- /* Syslog mode: all to syslog (logmode = LOGMODE_SYSLOG), */
- if (!DebugOpt && G.log_filename) {
- /* Otherwise (log to file): we reopen log file at every write: */
- int logfd = open_or_warn(G.log_filename, O_WRONLY | O_CREAT | O_APPEND);
- if (logfd >= 0)
- xmove_fd(logfd, STDERR_FILENO);
- }
- /* When we log to syslog, level > 8 is logged at LOG_ERR
- * syslog level, level <= 8 is logged at LOG_INFO. */
- if (level > 8) {
- bb_verror_msg(ctl + 1, va, /* strerr: */ NULL);
- } else {
- char *msg = NULL;
- vasprintf(&msg, ctl + 1, va);
- bb_info_msg("%s: %s", applet_name, msg);
- free(msg);
- }
- }
+ va_start(va, msg);
+ crondlog(7, msg, va);
+ va_end(va);
+}
+
+static void log8(const char *msg, ...)
+{
+ va_list va;
+ va_start(va, msg);
+ crondlog(8, msg, va);
va_end(va);
- if (ctl[0] & 0x80)
- exit(20);
}
+
static const char DowAry[] ALIGN1 =
"sun""mon""tue""wed""thu""fri""sat"
- /* "Sun""Mon""Tue""Wed""Thu""Fri""Sat" */
;
static const char MonAry[] ALIGN1 =
"jan""feb""mar""apr""may""jun""jul""aug""sep""oct""nov""dec"
- /* "Jan""Feb""Mar""Apr""May""Jun""Jul""Aug""Sep""Oct""Nov""Dec" */
;
static void ParseField(char *user, char *ary, int modvalue, int off,
@@ -267,12 +301,12 @@ static void ParseField(char *user, char *ary, int modvalue, int off,
if (*ptr) {
err:
- crondlog(WARN9 "user %s: parse error at %s", user, base);
+ bb_error_msg("user %s: parse error at %s", user, base);
return;
}
- if (DebugOpt && (G.log_level <= 5)) { /* like LVL5 */
- /* can't use crondlog, it inserts '\n' */
+ /* can't use log5 (it inserts newlines), open-coding it */
+ if (G.log_level <= 5 && logmode != LOGMODE_SYSLOG) {
int i;
for (i = 0; i < modvalue; ++i)
fprintf(stderr, "%d", (unsigned char)ary[i]);
@@ -368,11 +402,12 @@ static void load_crontab(const char *fileName)
#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
char *mailTo = NULL;
#endif
+ char *shell = NULL;
delete_cronfile(fileName);
if (!getpwnam(fileName)) {
- crondlog(LVL7 "ignoring file '%s' (no such user)", fileName);
+ log7("ignoring file '%s' (no such user)", fileName);
return;
}
@@ -393,23 +428,43 @@ static void load_crontab(const char *fileName)
while (1) {
CronLine *line;
- if (!--maxLines)
+ if (!--maxLines) {
+ bb_error_msg("user %s: too many lines", fileName);
break;
+ }
+
n = config_read(parser, tokens, 6, 1, "# \t", PARSE_NORMAL | PARSE_KEEP_COPY);
if (!n)
break;
- if (DebugOpt)
- crondlog(LVL5 "user:%s entry:%s", fileName, parser->data);
+ log5("user:%s entry:%s", fileName, parser->data);
/* check if line is setting MAILTO= */
- if (0 == strncmp(tokens[0], "MAILTO=", 7)) {
+ if (is_prefixed_with(tokens[0], "MAILTO=")) {
#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
free(mailTo);
mailTo = (tokens[0][7]) ? xstrdup(&tokens[0][7]) : NULL;
#endif /* otherwise just ignore such lines */
continue;
}
+ if (is_prefixed_with(tokens[0], "SHELL=")) {
+ free(shell);
+ shell = xstrdup(&tokens[0][6]);
+ continue;
+ }
+//TODO: handle HOME= too? "man crontab" says:
+//name = value
+//
+//where the spaces around the equal-sign (=) are optional, and any subsequent
+//non-leading spaces in value will be part of the value assigned to name.
+//The value string may be placed in quotes (single or double, but matching)
+//to preserve leading or trailing blanks.
+//
+//Several environment variables are set up automatically by the cron(8) daemon.
+//SHELL is set to /bin/sh, and LOGNAME and HOME are set from the /etc/passwd
+//line of the crontab's owner. HOME and SHELL may be overridden by settings
+//in the crontab; LOGNAME may not.
+
/* check if a minimum of tokens is specified */
if (n < 6)
continue;
@@ -429,11 +484,9 @@ static void load_crontab(const char *fileName)
/* copy mailto (can be NULL) */
line->cl_mailto = xstrdup(mailTo);
#endif
+ line->cl_shell = xstrdup(shell);
/* copy command */
line->cl_cmd = xstrdup(tokens[5]);
- if (DebugOpt) {
- crondlog(LVL5 " command:%s", tokens[5]);
- }
pline = &line->cl_next;
//bb_error_msg("M[%s]F[%s][%s][%s][%s][%s][%s]", mailTo, tokens[0], tokens[1], tokens[2], tokens[3], tokens[4], tokens[5]);
}
@@ -441,12 +494,12 @@ static void load_crontab(const char *fileName)
file->cf_next = G.cron_files;
G.cron_files = file;
-
- if (maxLines == 0) {
- crondlog(WARN9 "user %s: too many lines", fileName);
- }
}
config_close(parser);
+#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
+ free(mailTo);
+#endif
+ free(shell);
}
static void process_cron_update_file(void)
@@ -482,17 +535,16 @@ static void rescan_crontab_dir(void)
/* Remove cron update file */
unlink(CRONUPDATE);
/* Re-chdir, in case directory was renamed & deleted */
- if (chdir(G.crontab_dir_name) < 0) {
- crondlog(DIE9 "chdir(%s)", G.crontab_dir_name);
- }
+ xchdir(G.crontab_dir_name);
/* Scan directory and add associated users */
{
DIR *dir = opendir(".");
struct dirent *den;
+ /* xopendir exists, but "can't open '.'" is not informative */
if (!dir)
- crondlog(DIE9 "chdir(%s)", "."); /* exits */
+ bb_error_msg_and_die("can't open '%s'", G.crontab_dir_name);
while ((den = readdir(dir)) != NULL) {
if (strchr(den->d_name, '.') != NULL) {
continue;
@@ -519,19 +571,22 @@ static void safe_setenv(char **pvar_val, const char *var, const char *val)
}
#endif
-static void set_env_vars(struct passwd *pas)
+static void set_env_vars(struct passwd *pas, const char *shell)
{
+ /* POSIX requires crond to set up at least HOME, LOGNAME, PATH, SHELL.
+ * We assume crond inherited suitable PATH.
+ */
#if SETENV_LEAKS
+ safe_setenv(&G.env_var_logname, "LOGNAME", pas->pw_name);
safe_setenv(&G.env_var_user, "USER", pas->pw_name);
safe_setenv(&G.env_var_home, "HOME", pas->pw_dir);
- /* if we want to set user's shell instead: */
- /*safe_setenv(G.env_var_shell, "SHELL", pas->pw_shell);*/
+ safe_setenv(&G.env_var_shell, "SHELL", shell);
#else
+ xsetenv("LOGNAME", pas->pw_name);
xsetenv("USER", pas->pw_name);
xsetenv("HOME", pas->pw_dir);
+ xsetenv("SHELL", shell);
#endif
- /* currently, we use constant one: */
- /*setenv("SHELL", DEFAULT_SHELL, 1); - done earlier */
}
static void change_user(struct passwd *pas)
@@ -539,10 +594,8 @@ static void change_user(struct passwd *pas)
/* careful: we're after vfork! */
change_identity(pas); /* - initgroups, setgid, setuid */
if (chdir(pas->pw_dir) < 0) {
- crondlog(WARN9 "chdir(%s)", pas->pw_dir);
- if (chdir(TMPDIR) < 0) {
- crondlog(DIE9 "chdir(%s)", TMPDIR); /* exits */
- }
+ bb_error_msg("can't change directory to '%s'", pas->pw_dir);
+ xchdir(CRON_DIR);
}
}
@@ -550,46 +603,53 @@ static void change_user(struct passwd *pas)
#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
static pid_t
-fork_job(const char *user, int mailFd,
- const char *prog,
- const char *shell_cmd /* if NULL, we run sendmail */
-) {
+fork_job(const char *user, int mailFd, CronLine *line, bool run_sendmail)
+{
struct passwd *pas;
+ const char *shell, *prog;
+ smallint sv_logmode;
pid_t pid;
/* prepare things before vfork */
pas = getpwnam(user);
if (!pas) {
- crondlog(WARN9 "can't get uid for %s", user);
+ bb_error_msg("can't get uid for %s", user);
goto err;
}
- set_env_vars(pas);
+ shell = line->cl_shell ? line->cl_shell : DEFAULT_SHELL;
+ prog = run_sendmail ? SENDMAIL : shell;
+
+ set_env_vars(pas, shell);
+
+ sv_logmode = logmode;
pid = vfork();
if (pid == 0) {
/* CHILD */
- /* initgroups, setgid, setuid, and chdir to home or TMPDIR */
+ /* initgroups, setgid, setuid, and chdir to home or CRON_DIR */
change_user(pas);
- if (DebugOpt) {
- crondlog(LVL5 "child running %s", prog);
- }
+ log5("child running %s", prog);
if (mailFd >= 0) {
- xmove_fd(mailFd, shell_cmd ? 1 : 0);
+ xmove_fd(mailFd, run_sendmail ? 0 : 1);
dup2(1, 2);
}
/* crond 3.0pl1-100 puts tasks in separate process groups */
bb_setpgrp();
- execlp(prog, prog, (shell_cmd ? "-c" : SENDMAIL_ARGS), shell_cmd, (char *) NULL);
- crondlog(ERR20 "can't execute '%s' for user %s", prog, user);
- if (shell_cmd) {
- fdprintf(1, "Exec failed: %s -c %s\n", prog, shell_cmd);
- }
- _exit(EXIT_SUCCESS);
+ if (!run_sendmail)
+ execlp(prog, prog, "-c", line->cl_cmd, (char *) NULL);
+ else
+ execlp(prog, prog, SENDMAIL_ARGS, (char *) NULL);
+ /*
+ * I want this error message on stderr too,
+ * even if other messages go only to syslog:
+ */
+ logmode |= LOGMODE_STDIO;
+ bb_error_msg_and_die("can't execute '%s' for user %s", prog, user);
}
+ logmode = sv_logmode;
if (pid < 0) {
- /* FORK FAILED */
- crondlog(ERR20 "can't vfork");
+ bb_perror_msg("vfork");
err:
pid = 0;
} /* else: PARENT, FORK SUCCESS */
@@ -614,7 +674,7 @@ static void start_one_job(const char *user, CronLine *line)
if (line->cl_mailto) {
/* Open mail file (owner is root so nobody can screw with it) */
- snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", TMPDIR, user, getpid());
+ snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", CRON_DIR, user, getpid());
mailFd = open(mailFile, O_CREAT | O_TRUNC | O_WRONLY | O_EXCL | O_APPEND, 0600);
if (mailFd >= 0) {
@@ -622,18 +682,18 @@ static void start_one_job(const char *user, CronLine *line)
line->cl_cmd);
line->cl_empty_mail_size = lseek(mailFd, 0, SEEK_CUR);
} else {
- crondlog(ERR20 "can't create mail file %s for user %s, "
+ bb_error_msg("can't create mail file %s for user %s, "
"discarding output", mailFile, user);
}
}
- line->cl_pid = fork_job(user, mailFd, DEFAULT_SHELL, line->cl_cmd);
+ line->cl_pid = fork_job(user, mailFd, line, /*sendmail?*/ 0);
if (mailFd >= 0) {
if (line->cl_pid <= 0) {
unlink(mailFile);
} else {
/* rename mail-file based on pid of process */
- char *mailFile2 = xasprintf("%s/cron.%s.%d", TMPDIR, user, (int)line->cl_pid);
+ char *mailFile2 = xasprintf("%s/cron.%s.%d", CRON_DIR, user, (int)line->cl_pid);
rename(mailFile, mailFile2); // TODO: xrename?
free(mailFile2);
}
@@ -665,7 +725,7 @@ static void process_finished_job(const char *user, CronLine *line)
* End of primary job - check for mail file.
* If size has changed and the file is still valid, we send it.
*/
- snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", TMPDIR, user, (int)pid);
+ snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", CRON_DIR, user, (int)pid);
mailFd = open(mailFile, O_RDONLY);
unlink(mailFile);
if (mailFd < 0) {
@@ -683,43 +743,41 @@ static void process_finished_job(const char *user, CronLine *line)
}
line->cl_empty_mail_size = 0;
/* if (line->cl_mailto) - always true if cl_empty_mail_size was nonzero */
- line->cl_pid = fork_job(user, mailFd, SENDMAIL, NULL);
+ line->cl_pid = fork_job(user, mailFd, line, /*sendmail?*/ 1);
}
#else /* !ENABLE_FEATURE_CROND_CALL_SENDMAIL */
static void start_one_job(const char *user, CronLine *line)
{
+ const char *shell;
struct passwd *pas;
pid_t pid;
pas = getpwnam(user);
if (!pas) {
- crondlog(WARN9 "can't get uid for %s", user);
+ bb_error_msg("can't get uid for %s", user);
goto err;
}
/* Prepare things before vfork */
- set_env_vars(pas);
+ shell = line->cl_shell ? line->cl_shell : DEFAULT_SHELL;
+ set_env_vars(pas, shell);
/* Fork as the user in question and run program */
pid = vfork();
if (pid == 0) {
/* CHILD */
- /* initgroups, setgid, setuid, and chdir to home or TMPDIR */
+ /* initgroups, setgid, setuid, and chdir to home or CRON_DIR */
change_user(pas);
- if (DebugOpt) {
- crondlog(LVL5 "child running %s", DEFAULT_SHELL);
- }
+ log5("child running %s", shell);
/* crond 3.0pl1-100 puts tasks in separate process groups */
bb_setpgrp();
- execl(DEFAULT_SHELL, DEFAULT_SHELL, "-c", line->cl_cmd, (char *) NULL);
- crondlog(ERR20 "can't execute '%s' for user %s", DEFAULT_SHELL, user);
- _exit(EXIT_SUCCESS);
+ execl(shell, shell, "-c", line->cl_cmd, (char *) NULL);
+ bb_error_msg_and_die("can't execute '%s' for user %s", shell, user);
}
if (pid < 0) {
- /* FORK FAILED */
- crondlog(ERR20 "can't vfork");
+ bb_perror_msg("vfork");
err:
pid = 0;
}
@@ -751,24 +809,20 @@ static void flag_starting_jobs(time_t t1, time_t t2)
ptm = localtime(&t);
for (file = G.cron_files; file; file = file->cf_next) {
- if (DebugOpt)
- crondlog(LVL5 "file %s:", file->cf_username);
+ log5("file %s:", file->cf_username);
if (file->cf_deleted)
continue;
for (line = file->cf_lines; line; line = line->cl_next) {
- if (DebugOpt)
- crondlog(LVL5 " line %s", line->cl_cmd);
+ log5(" line %s", line->cl_cmd);
if (line->cl_Mins[ptm->tm_min]
&& line->cl_Hrs[ptm->tm_hour]
&& (line->cl_Days[ptm->tm_mday] || line->cl_Dow[ptm->tm_wday])
&& line->cl_Mons[ptm->tm_mon]
) {
- if (DebugOpt) {
- crondlog(LVL5 " job: %d %s",
+ log5(" job: %d %s",
(int)line->cl_pid, line->cl_cmd);
- }
if (line->cl_pid > 0) {
- crondlog(LVL8 "user %s: process already running: %s",
+ log8("user %s: process already running: %s",
file->cf_username, line->cl_cmd);
} else if (line->cl_pid == 0) {
line->cl_pid = -1;
@@ -797,7 +851,7 @@ static void start_jobs(void)
start_one_job(file->cf_username, line);
pid = line->cl_pid;
- crondlog(LVL8 "USER %s pid %3d cmd %s",
+ log8("USER %s pid %3d cmd %s",
file->cf_username, (int)pid, line->cl_cmd);
if (pid < 0) {
file->cf_wants_starting = 1;
@@ -849,12 +903,21 @@ static int check_completions(void)
return num_still_running;
}
+static void reopen_logfile_to_stderr(void)
+{
+ if (G.log_filename) {
+ int logfd = open_or_warn(G.log_filename, O_WRONLY | O_CREAT | O_APPEND);
+ if (logfd >= 0)
+ xmove_fd(logfd, STDERR_FILENO);
+ }
+}
+
int crond_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int crond_main(int argc UNUSED_PARAM, char **argv)
{
time_t t2;
- int rescan;
- int sleep_time;
+ unsigned rescan;
+ unsigned sleep_time;
unsigned opts;
INIT_G();
@@ -880,12 +943,13 @@ int crond_main(int argc UNUSED_PARAM, char **argv)
logmode = LOGMODE_SYSLOG;
}
- xchdir(G.crontab_dir_name);
//signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */
- xsetenv("SHELL", DEFAULT_SHELL); /* once, for all future children */
- crondlog(LVL8 "crond (busybox "BB_VER") started, log level %d", G.log_level);
+
+ reopen_logfile_to_stderr();
+ xchdir(G.crontab_dir_name);
+ log8("crond (busybox "BB_VER") started, log level %d", G.log_level);
rescan_crontab_dir();
- write_pidfile("/var/run/crond.pid");
+ write_pidfile(CONFIG_PID_FILE_PATH "/crond.pid");
/* Main loop */
t2 = time(NULL);
@@ -896,14 +960,14 @@ int crond_main(int argc UNUSED_PARAM, char **argv)
time_t t1;
long dt;
- t1 = t2;
-
/* Synchronize to 1 minute, minimum 1 second */
- sleep(sleep_time - (time(NULL) % sleep_time) + 1);
-
+ t1 = t2;
+ sleep(sleep_time - (time(NULL) % sleep_time));
t2 = time(NULL);
dt = (long)t2 - (long)t1;
+ reopen_logfile_to_stderr();
+
/*
* The file 'cron.update' is checked to determine new cron
* jobs. The directory is rescanned once an hour to deal
@@ -931,20 +995,18 @@ int crond_main(int argc UNUSED_PARAM, char **argv)
rescan_crontab_dir();
}
process_cron_update_file();
- if (DebugOpt)
- crondlog(LVL5 "wakeup dt=%ld", dt);
+ log5("wakeup dt=%ld", dt);
if (dt < -60 * 60 || dt > 60 * 60) {
- crondlog(WARN9 "time disparity of %ld minutes detected", dt / 60);
+ bb_error_msg("time disparity of %ld minutes detected", dt / 60);
/* and we do not run any jobs in this case */
} else if (dt > 0) {
/* Usual case: time advances forward, as expected */
flag_starting_jobs(t1, t2);
start_jobs();
+ sleep_time = 60;
if (check_completions() > 0) {
/* some jobs are still running */
sleep_time = 10;
- } else {
- sleep_time = 60;
}
}
/* else: time jumped back, do not run any jobs */
diff --git a/release/src/router/busybox/miscutils/crontab.c b/release/src/router/busybox/miscutils/crontab.c
index 4731d8da60..85c6623b26 100644
--- a/release/src/router/busybox/miscutils/crontab.c
+++ b/release/src/router/busybox/miscutils/crontab.c
@@ -55,28 +55,6 @@ static void edit_file(const struct passwd *pas, const char *file)
bb_perror_msg_and_die("can't execute '%s'", ptr);
}
-static int open_as_user(const struct passwd *pas, const char *file)
-{
- pid_t pid;
- char c;
-
- pid = xvfork();
- if (pid) { /* PARENT */
- if (wait4pid(pid) == 0) {
- /* exitcode 0: child says it can read */
- return open(file, O_RDONLY);
- }
- return -1;
- }
-
- /* CHILD */
- /* initgroups, setgid, setuid */
- change_identity(pas);
- /* We just try to read one byte. If it works, file is readable
- * under this user. We signal that by exiting with 0. */
- _exit(safe_read(xopen(file, O_RDONLY), &c, 1) < 0);
-}
-
int crontab_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int crontab_main(int argc UNUSED_PARAM, char **argv)
{
@@ -137,10 +115,7 @@ int crontab_main(int argc UNUSED_PARAM, char **argv)
if (!argv[0])
bb_show_usage();
if (NOT_LONE_DASH(argv[0])) {
- src_fd = open_as_user(pas, argv[0]);
- if (src_fd < 0)
- bb_error_msg_and_die("user %s cannot read %s",
- pas->pw_name, argv[0]);
+ src_fd = xopen_as_uid_gid(argv[0], O_RDONLY, pas->pw_uid, pas->pw_gid);
}
}
@@ -195,7 +170,6 @@ int crontab_main(int argc UNUSED_PARAM, char **argv)
unlink(tmp_fname);
/*free(tmp_fname);*/
/*free(new_fname);*/
-
} /* switch */
/* Bump notification file. Handle window where crond picks file up
diff --git a/release/src/router/busybox/miscutils/dc.c b/release/src/router/busybox/miscutils/dc.c
index 6903761e4f..4d92bc3d04 100644
--- a/release/src/router/busybox/miscutils/dc.c
+++ b/release/src/router/busybox/miscutils/dc.c
@@ -4,6 +4,7 @@
*/
#include "libbb.h"
+#include "common_bufsiz.h"
#include <math.h>
//usage:#define dc_trivial_usage
@@ -11,11 +12,11 @@
//usage:
//usage:#define dc_full_usage "\n\n"
//usage: "Tiny RPN calculator. Operations:\n"
-//usage: "+, add, -, sub, *, mul, /, div, %, mod, "IF_FEATURE_DC_LIBM("**, exp, ")"and, or, not, eor,\n"
+//usage: "+, add, -, sub, *, mul, /, div, %, mod, "IF_FEATURE_DC_LIBM("**, exp, ")"and, or, not, xor,\n"
//usage: "p - print top of the stack (without popping),\n"
//usage: "f - print entire stack,\n"
//usage: "o - pop the value and set output radix (must be 10, 16, 8 or 2).\n"
-//usage: "Examples: 'dc 2 2 add p' -> 4, 'dc 8 8 * 2 2 + / p' -> 16"
+//usage: "Examples: 'dc 2 2 add p' -> 4, 'dc 8 8 mul 2 2 + / p' -> 16"
//usage:
//usage:#define dc_example_usage
//usage: "$ dc 2 2 + p\n"
@@ -47,15 +48,22 @@ struct globals {
double stack[1];
} FIX_ALIASING;
enum { STACK_SIZE = (COMMON_BUFSIZE - offsetof(struct globals, stack)) / sizeof(double) };
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define pointer (G.pointer )
#define base (G.base )
#define stack (G.stack )
#define INIT_G() do { \
+ setup_common_bufsiz(); \
base = 10; \
} while (0)
+static void check_under(void)
+{
+ if (pointer == 0)
+ bb_error_msg_and_die("stack underflow");
+}
+
static void push(double a)
{
if (pointer >= STACK_SIZE)
@@ -65,8 +73,7 @@ static void push(double a)
static double pop(void)
{
- if (pointer == 0)
- bb_error_msg_and_die("stack underflow");
+ check_under();
return stack[--pointer];
}
@@ -187,6 +194,7 @@ static void print_stack_no_pop(void)
static void print_no_pop(void)
{
+ check_under();
print_base(stack[pointer-1]);
}
@@ -196,14 +204,6 @@ struct op {
};
static const struct op operators[] = {
- {"+", add},
- {"add", add},
- {"-", sub},
- {"sub", sub},
- {"*", mul},
- {"mul", mul},
- {"/", divide},
- {"div", divide},
#if ENABLE_FEATURE_DC_LIBM
{"**", power},
{"exp", power},
@@ -216,32 +216,51 @@ static const struct op operators[] = {
{"not", not},
{"eor", eor},
{"xor", eor},
+ {"+", add},
+ {"add", add},
+ {"-", sub},
+ {"sub", sub},
+ {"*", mul},
+ {"mul", mul},
+ {"/", divide},
+ {"div", divide},
{"p", print_no_pop},
{"f", print_stack_no_pop},
{"o", set_output_base},
- { "", NULL }
};
+/* Feed the stack machine */
static void stack_machine(const char *argument)
{
- char *endPointer;
- double d;
- const struct op *o = operators;
+ char *end;
+ double number;
+ const struct op *o;
+
+ next:
+ number = strtod(argument, &end);
+ if (end != argument) {
+ argument = end;
+ push(number);
+ goto next;
+ }
- d = strtod(argument, &endPointer);
+ /* We might have matched a digit, eventually advance the argument */
+ argument = skip_whitespace(argument);
- if (endPointer != argument && *endPointer == '\0') {
- push(d);
+ if (*argument == '\0')
return;
- }
- while (o->function) {
- if (strcmp(o->name, argument) == 0) {
+ o = operators;
+ do {
+ char *after_name = is_prefixed_with(argument, o->name);
+ if (after_name) {
+ argument = after_name;
o->function();
- return;
+ goto next;
}
o++;
- }
+ } while (o != operators + ARRAY_SIZE(operators));
+
bb_error_msg_and_die("syntax error at '%s'", argument);
}
@@ -254,25 +273,11 @@ int dc_main(int argc UNUSED_PARAM, char **argv)
if (!argv[0]) {
/* take stuff from stdin if no args are given */
char *line;
- char *cursor;
- char *token;
while ((line = xmalloc_fgetline(stdin)) != NULL) {
- cursor = line;
- while (1) {
- token = skip_whitespace(cursor);
- if (*token == '\0')
- break;
- cursor = skip_non_whitespace(token);
- if (*cursor != '\0')
- *cursor++ = '\0';
- stack_machine(token);
- }
+ stack_machine(line);
free(line);
}
} else {
- // why? it breaks "dc -2 2 + p"
- //if (argv[0][0] == '-')
- // bb_show_usage();
do {
stack_machine(*argv);
} while (*++argv);
diff --git a/release/src/router/busybox/miscutils/devfsd.c b/release/src/router/busybox/miscutils/devfsd.c
index 6493fe4f1c..6217918da7 100644
--- a/release/src/router/busybox/miscutils/devfsd.c
+++ b/release/src/router/busybox/miscutils/devfsd.c
@@ -219,7 +219,7 @@ static void action_execute(const struct devfsd_notify_struct *, const struct con
const regmatch_t *, unsigned);
static void action_modload(const struct devfsd_notify_struct *info, const struct config_entry_struct *entry);
static void action_copy(const struct devfsd_notify_struct *, const struct config_entry_struct *,
- const regmatch_t *, unsigned);
+ const regmatch_t *, unsigned);
static void action_compat(const struct devfsd_notify_struct *, unsigned);
static void free_config(void);
static void restore(char *spath, struct stat source_stat, int rootlen);
@@ -229,12 +229,12 @@ static void signal_handler(int);
static const char *get_variable(const char *, void *);
static int make_dir_tree(const char *);
static int expand_expression(char *, unsigned, const char *, const char *(*)(const char *, void *), void *,
- const char *, const regmatch_t *, unsigned);
+ const char *, const regmatch_t *, unsigned);
static void expand_regexp(char *, size_t, const char *, const char *, const regmatch_t *, unsigned);
static const char *expand_variable( char *, unsigned, unsigned *, const char *,
const char *(*)(const char *, void *), void *);
static const char *get_variable_v2(const char *, const char *(*)(const char *, void *), void *);
-static char get_old_ide_name(unsigned , unsigned);
+static char get_old_ide_name(unsigned, unsigned);
static char *write_old_sd_name(char *, unsigned, unsigned, const char *);
/* busybox functions */
@@ -284,7 +284,7 @@ static const char bb_msg_variable_not_found[] ALIGN1 = "variable: %s not found";
/* Busybox stuff */
#if ENABLE_DEVFSD_VERBOSE || ENABLE_DEBUG
-#define info_logger(p, fmt, args...) bb_info_msg(fmt, ## args)
+#define info_logger(p, fmt, args...) bb_error_msg(fmt, ## args)
#define msg_logger(p, fmt, args...) bb_error_msg(fmt, ## args)
#define msg_logger_and_die(p, fmt, args...) bb_error_msg_and_die(fmt, ## args)
#define error_logger(p, fmt, args...) bb_perror_msg(fmt, ## args)
@@ -580,9 +580,9 @@ static void process_config_line(const char *line, unsigned long *event_mask)
/*This action will pass "/dev/$devname"(i.e. "/dev/" prefixed to
the device name) to the module loading facility. In addition,
the /etc/modules.devfs configuration file is used.*/
- if (ENABLE_DEVFSD_MODLOAD)
+ if (ENABLE_DEVFSD_MODLOAD)
new->action.what = AC_MODLOAD;
- break;
+ break;
case 6: /* EXECUTE */
new->action.what = AC_EXECUTE;
num_args -= 3;
@@ -750,7 +750,7 @@ static void action_permissions(const struct devfsd_notify_struct *info,
} /* End Function action_permissions */
static void action_modload(const struct devfsd_notify_struct *info,
- const struct config_entry_struct *entry UNUSED_PARAM)
+ const struct config_entry_struct *entry UNUSED_PARAM)
/* [SUMMARY] Load a module.
<info> The devfs change.
<entry> The config file entry.
@@ -771,8 +771,8 @@ static void action_modload(const struct devfsd_notify_struct *info,
} /* End Function action_modload */
static void action_execute(const struct devfsd_notify_struct *info,
- const struct config_entry_struct *entry,
- const regmatch_t *regexpr, unsigned int numexpr)
+ const struct config_entry_struct *entry,
+ const regmatch_t *regexpr, unsigned int numexpr)
/* [SUMMARY] Execute a programme.
<info> The devfs change.
<entry> The config file entry.
@@ -803,8 +803,8 @@ static void action_execute(const struct devfsd_notify_struct *info,
static void action_copy(const struct devfsd_notify_struct *info,
- const struct config_entry_struct *entry,
- const regmatch_t *regexpr, unsigned int numexpr)
+ const struct config_entry_struct *entry,
+ const regmatch_t *regexpr, unsigned int numexpr)
/* [SUMMARY] Copy permissions.
<info> The devfs change.
<entry> The config file entry.
@@ -1083,21 +1083,23 @@ static int get_uid_gid(int flag, const char *string)
{
struct passwd *pw_ent;
struct group *grp_ent;
- static const char *msg;
+ const char *msg;
- if (ENABLE_DEVFSD_VERBOSE)
- msg = "user";
-
- if (isdigit(string[0]) ||((string[0] == '-') && isdigit(string[1])))
+ if (isdigit(string[0]) || ((string[0] == '-') && isdigit(string[1])))
return atoi(string);
if (flag == UID && (pw_ent = getpwnam(string)) != NULL)
return pw_ent->pw_uid;
- if (flag == GID && (grp_ent = getgrnam(string)) != NULL)
- return grp_ent->gr_gid;
- else if (ENABLE_DEVFSD_VERBOSE)
- msg = "group";
+ if (ENABLE_DEVFSD_VERBOSE)
+ msg = "user";
+
+ if (flag == GID) {
+ if ((grp_ent = getgrnam(string)) != NULL)
+ return grp_ent->gr_gid;
+ if (ENABLE_DEVFSD_VERBOSE)
+ msg = "group";
+ }
if (ENABLE_DEVFSD_VERBOSE)
msg_logger(LOG_ERR, "unknown %s: %s, defaulting to %cid=0", msg, string, msg[0]);
@@ -1140,19 +1142,19 @@ static void signal_handler(int sig)
static const char *get_variable(const char *variable, void *info)
{
- static char sbuf[sizeof(int)*3 + 2]; /* sign and NUL */
static char *hostname;
struct get_variable_info *gv_info = info;
const char *field_names[] = {
- "hostname", "mntpt", "devpath", "devname",
- "uid", "gid", "mode", hostname, mount_point,
- gv_info->devpath, gv_info->devname, NULL
+ "hostname", "mntpt", "devpath", "devname", "uid", "gid", "mode",
+ NULL, mount_point, gv_info->devpath, gv_info->devname, NULL
};
int i;
if (!hostname)
hostname = safe_gethostname();
+ field_names[7] = hostname;
+
/* index_in_str_array returns i>=0 */
i = index_in_str_array(field_names, variable);
@@ -1162,12 +1164,11 @@ static const char *get_variable(const char *variable, void *info)
return field_names[i + 7];
if (i == 4)
- sprintf(sbuf, "%u", gv_info->info->uid);
- else if (i == 5)
- sprintf(sbuf, "%u", gv_info->info->gid);
- else if (i == 6)
- sprintf(sbuf, "%o", gv_info->info->mode);
- return sbuf;
+ return auto_string(xasprintf("%u", gv_info->info->uid));
+ if (i == 5)
+ return auto_string(xasprintf("%u", gv_info->info->gid));
+ /* i == 6 */
+ return auto_string(xasprintf("%o", gv_info->info->mode));
} /* End Function get_variable */
static void service(struct stat statbuf, char *path)
@@ -1259,11 +1260,11 @@ static int make_dir_tree(const char *path)
} /* End Function make_dir_tree */
static int expand_expression(char *output, unsigned int outsize,
- const char *input,
- const char *(*get_variable_func)(const char *variable, void *info),
- void *info,
- const char *devname,
- const regmatch_t *ex, unsigned int numexp)
+ const char *input,
+ const char *(*get_variable_func)(const char *variable, void *info),
+ void *info,
+ const char *devname,
+ const regmatch_t *ex, unsigned int numexp)
/* [SUMMARY] Expand environment variables and regular subexpressions in string.
<output> The output expanded expression is written here.
<length> The size of the output buffer.
@@ -1288,8 +1289,8 @@ static int expand_expression(char *output, unsigned int outsize,
} /* End Function expand_expression */
static void expand_regexp(char *output, size_t outsize, const char *input,
- const char *devname,
- const regmatch_t *ex, unsigned int numex)
+ const char *devname,
+ const regmatch_t *ex, unsigned int numex)
/* [SUMMARY] Expand all occurrences of the regular subexpressions \0 to \9.
<output> The output expanded expression is written here.
<outsize> The size of the output buffer.
@@ -1385,7 +1386,7 @@ static struct translate_struct translate_table[] =
};
const char *get_old_name(const char *devname, unsigned int namelen,
- char *buffer, unsigned int major, unsigned int minor)
+ char *buffer, unsigned int major, unsigned int minor)
/* [SUMMARY] Translate a kernel-supplied name into an old name.
<devname> The device name provided by the kernel.
<namelen> The length of the name.
@@ -1403,7 +1404,6 @@ const char *get_old_name(const char *devname, unsigned int namelen,
int indexx;
const char *pty1;
const char *pty2;
- size_t len;
/* 1 to 5 "scsi/" , 6 to 9 "ide/host", 10 sbp/, 11 vcc/, 12 pty/ */
static const char *const fmt[] = {
NULL ,
@@ -1423,12 +1423,11 @@ const char *get_old_name(const char *devname, unsigned int namelen,
};
for (trans = translate_table; trans->match != NULL; ++trans) {
- len = strlen(trans->match);
-
- if (strncmp(devname, trans->match, len) == 0) {
+ char *after_match = is_prefixed_with(devname, trans->match);
+ if (after_match) {
if (trans->format == NULL)
- return devname + len;
- sprintf(buffer, trans->format, devname + len);
+ return after_match;
+ sprintf(buffer, trans->format, after_match);
return buffer;
}
}
@@ -1549,9 +1548,9 @@ static char *write_old_sd_name(char *buffer,
/*EXPERIMENTAL_FUNCTION*/
int st_expr_expand(char *output, unsigned int length, const char *input,
- const char *(*get_variable_func)(const char *variable,
- void *info),
- void *info)
+ const char *(*get_variable_func)(const char *variable,
+ void *info),
+ void *info)
/* [SUMMARY] Expand an expression using Borne Shell-like unquoted rules.
<output> The output expanded expression is written here.
<length> The size of the output buffer.
@@ -1641,10 +1640,10 @@ st_expr_expand_out:
/* Private functions follow */
static const char *expand_variable(char *buffer, unsigned int length,
- unsigned int *out_pos, const char *input,
- const char *(*func)(const char *variable,
- void *info),
- void *info)
+ unsigned int *out_pos, const char *input,
+ const char *(*func)(const char *variable,
+ void *info),
+ void *info)
/* [SUMMARY] Expand a variable.
<buffer> The buffer to write to.
<length> The length of the output buffer.
@@ -1786,8 +1785,8 @@ expand_variable_out:
static const char *get_variable_v2(const char *variable,
- const char *(*func)(const char *variable, void *info),
- void *info)
+ const char *(*func)(const char *variable, void *info),
+ void *info)
/* [SUMMARY] Get a variable from the environment or .
<variable> The variable name.
<func> A function which will be used to get the variable. If this returns
diff --git a/release/src/router/busybox/miscutils/eject.c b/release/src/router/busybox/miscutils/eject.c
index a20e04b7f4..16ae250ff6 100644
--- a/release/src/router/busybox/miscutils/eject.c
+++ b/release/src/router/busybox/miscutils/eject.c
@@ -25,26 +25,22 @@
#include <sys/mount.h>
#include "libbb.h"
+#if ENABLE_FEATURE_EJECT_SCSI
/* Must be after libbb.h: they need size_t */
-#include "fix_u32.h"
-#include <scsi/sg.h>
-#include <scsi/scsi.h>
-
-/* various defines swiped from linux/cdrom.h */
-#define CDROMCLOSETRAY 0x5319 /* pendant of CDROMEJECT */
-#define CDROMEJECT 0x5309 /* Ejects the cdrom media */
-#define CDROM_DRIVE_STATUS 0x5326 /* Get tray position, etc. */
-/* drive status possibilities returned by CDROM_DRIVE_STATUS ioctl */
-#define CDS_TRAY_OPEN 2
+# include "fix_u32.h"
+# include <scsi/sg.h>
+# include <scsi/scsi.h>
+#endif
#define dev_fd 3
/* Code taken from the original eject (http://eject.sourceforge.net/),
* refactored it a bit for busybox (ne-bb@nicoerfurth.de) */
+#if ENABLE_FEATURE_EJECT_SCSI
static void eject_scsi(const char *dev)
{
- static const char sg_commands[3][6] = {
+ static const char sg_commands[3][6] ALIGN1 = {
{ ALLOW_MEDIUM_REMOVAL, 0, 0, 0, 0, 0 },
{ START_STOP, 0, 0, 0, 1, 0 },
{ START_STOP, 0, 0, 0, 2, 0 }
@@ -76,6 +72,16 @@ static void eject_scsi(const char *dev)
/* force kernel to reread partition table when new disc is inserted */
ioctl(dev_fd, BLKRRPART);
}
+#else
+# define eject_scsi(dev) ((void)0)
+#endif
+
+/* various defines swiped from linux/cdrom.h */
+#define CDROMCLOSETRAY 0x5319 /* pendant of CDROMEJECT */
+#define CDROMEJECT 0x5309 /* Ejects the cdrom media */
+#define CDROM_DRIVE_STATUS 0x5326 /* Get tray position, etc. */
+/* drive status possibilities returned by CDROM_DRIVE_STATUS ioctl */
+#define CDS_TRAY_OPEN 2
#define FLAG_CLOSE 1
#define FLAG_SMART 2
diff --git a/release/src/router/busybox/miscutils/ethreg.c b/release/src/router/busybox/miscutils/ethreg.c
index 32d8395f0e..c458341298 100644
--- a/release/src/router/busybox/miscutils/ethreg.c
+++ b/release/src/router/busybox/miscutils/ethreg.c
@@ -17,6 +17,23 @@
*
*/
+//config:config ETHREG
+//config: bool "Ethreg Utility"
+//config: default n
+//config: help
+//config: The ethreg utility can be used to read/write MAC and PHY registers
+//config: to change the duplex and speed setting for individual PHYS.
+
+//kbuild:lib-$(CONFIG_ETHREG) += ethreg.o
+
+//applet:IF_ETHREG(APPLET(ethreg, BB_DIR_USR_SBIN, BB_SUID_DROP))
+
+//usage:#define ethreg_trivial_usage
+//usage: "......"
+//usage:#define ethreg_full_usage "\n"
+
+#include "libbb.h"
+
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -29,7 +46,7 @@
#include <string.h>
#include <net/if.h>
#include <fcntl.h>
-#include "busybox.h"
+
#include "athrs_ctrl.h"
#define MAX_SIZ 10
@@ -51,10 +68,10 @@ struct eth_cfg_params {
};
-struct ifreq ifr;
-struct eth_cfg_params etd;
-int s,opt_force = 0,duplex = 1;
-const char *progname;
+static struct ifreq ifr;
+static struct eth_cfg_params etd;
+static int s,opt_force = 0,duplex = 1;
+static const char *progname;
static void rx_stats(void)
{
//printf ("\n\n%s\n", __func__);
@@ -158,10 +175,7 @@ static void rx_mac_stats (void)
printf ("\t%u\t: Rx overfl cntr\n",etd.rxmac.rxoverfl);
}
-
-
-
-u_int32_t
+static u_int32_t
regread(u_int32_t phy_reg,u_int16_t portno)
{
@@ -445,8 +459,8 @@ static void usage(void)
}
-int
-ethreg_main(int argc, char *argv[])
+int ethreg_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int ethreg_main(int argc, char *argv[])
{
const char *ifname = "eth0";
int c,portnum = 0x3f,cmd = 0,value = -1;
@@ -454,17 +468,8 @@ ethreg_main(int argc, char *argv[])
int vlanid = 0;
char *mac = NULL;
int tos = -1;
- char *opt = "xfhci:d:s:j:v:t:p:m:l:";
-
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0)
- err(1, "socket");
-
- opt_force = 0;
- progname = argv[0];
-
-
- struct option long_options[] =
+ const char *opt = "xfhci:d:s:j:v:t:p:m:l:";
+ const struct option long_options[] =
{
{ "f_link", no_argument, 0, ATHR_FLOW_LINK_EN},
{ "txfctl", no_argument, 0, ATHR_PHY_TXFCTL},
@@ -483,9 +488,15 @@ ethreg_main(int argc, char *argv[])
{ "macfl" , no_argument, 0, ATHR_GMAC_FLOW_CTRL},
{ "swfl" , no_argument, 0, ATHR_PHY_FLOW_CTRL},
{ 0,0,0,0}
- };
-
-
+ };
+
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0)
+ err(1, "socket");
+
+ opt_force = 0;
+ progname = argv[0];
+
while ((c = getopt_long(argc, argv,
opt, long_options, &optionindex)) != -1) {
switch (c) {
@@ -792,4 +803,3 @@ ethreg_main(int argc, char *argv[])
}
return 0;
}
-
diff --git a/release/src/router/busybox/miscutils/fbsplash.c b/release/src/router/busybox/miscutils/fbsplash.c
index 988439b25a..3ddf8a2427 100644
--- a/release/src/router/busybox/miscutils/fbsplash.c
+++ b/release/src/router/busybox/miscutils/fbsplash.c
@@ -34,6 +34,7 @@
//usage: "\n commands: 'NN' (% for progress bar) or 'exit'"
#include "libbb.h"
+#include "common_bufsiz.h"
#include <linux/fb.h>
/* If you want logging messages on /tmp/fbsplash.log... */
@@ -50,6 +51,10 @@ struct globals {
struct fb_var_screeninfo scr_var;
struct fb_fix_screeninfo scr_fix;
unsigned bytes_per_pixel;
+ // cached (8 - scr_var.COLOR.length):
+ unsigned red_shift;
+ unsigned green_shift;
+ unsigned blue_shift;
};
#define G (*ptr_to_globals)
#define INIT_G() do { \
@@ -139,11 +144,14 @@ static void fb_open(const char *strfb_device)
break;
}
+ G.red_shift = 8 - G.scr_var.red.length;
+ G.green_shift = 8 - G.scr_var.green.length;
+ G.blue_shift = 8 - G.scr_var.blue.length;
G.bytes_per_pixel = (G.scr_var.bits_per_pixel + 7) >> 3;
// map the device in memory
G.addr = mmap(NULL,
- G.scr_var.yres * G.scr_fix.line_length,
+ (G.scr_var.yres_virtual ?: G.scr_var.yres) * G.scr_fix.line_length,
PROT_WRITE, MAP_SHARED, fbfd, 0);
if (G.addr == MAP_FAILED)
bb_perror_msg_and_die("mmap");
@@ -155,10 +163,13 @@ static void fb_open(const char *strfb_device)
/**
- * Return pixel value of the passed RGB color
+ * Return pixel value of the passed RGB color.
+ * This is performance critical fn.
*/
static unsigned fb_pixel_value(unsigned r, unsigned g, unsigned b)
{
+ /* We assume that the r,g,b values are <= 255 */
+
if (G.bytes_per_pixel == 1) {
r = r & 0xe0; // 3-bit red
g = (g >> 3) & 0x1c; // 3-bit green
@@ -166,10 +177,17 @@ static unsigned fb_pixel_value(unsigned r, unsigned g, unsigned b)
return r + g + b;
}
if (G.bytes_per_pixel == 2) {
- r = (r & 0xf8) << 8; // 5-bit red
- g = (g & 0xfc) << 3; // 6-bit green
- b = b >> 3; // 5-bit blue
- return r + g + b;
+ // ARM PL110 on Integrator/CP has RGBA5551 bit arrangement.
+ // We want to support bit locations like that.
+ //
+ // First shift out unused bits
+ r = r >> G.red_shift;
+ g = g >> G.green_shift;
+ b = b >> G.blue_shift;
+ // Then shift the remaining bits to their offset
+ return (r << G.scr_var.red.offset) +
+ (g << G.scr_var.green.offset) +
+ (b << G.scr_var.blue.offset);
}
// RGB 888
return b + (g << 8) + (r << 16);
@@ -295,8 +313,7 @@ static void fb_drawprogressbar(unsigned percent)
pos_x = left_x;
if (percent > 0) {
- int y;
- unsigned i;
+ int i, y;
// actual progress bar
pos_x += (unsigned)(width * percent) / 100;
@@ -308,7 +325,7 @@ static void fb_drawprogressbar(unsigned percent)
while (i >= 0) {
// draw one-line thick "rectangle"
// top line will have gray lvl 200, bottom one 100
- unsigned gray_level = 100 + i*100 / height;
+ unsigned gray_level = 100 + (unsigned)i*100 / height;
fb_drawfullrectangle(
left_x, y, pos_x, y,
gray_level, gray_level, gray_level);
@@ -337,7 +354,7 @@ static void fb_drawimage(void)
if (LONE_DASH(G.image_filename)) {
theme_file = stdin;
} else {
- int fd = open_zipped(G.image_filename);
+ int fd = open_zipped(G.image_filename, /*fail_if_not_compressed:*/ 0);
if (fd < 0)
bb_simple_perror_msg_and_die(G.image_filename);
theme_file = xfdopen_for_read(fd);
@@ -357,10 +374,12 @@ static void fb_drawimage(void)
* in pure binary by 1 or 2 bytes. (we support only 1 byte)
*/
#define concat_buf bb_common_bufsiz1
+ setup_common_bufsiz();
+
read_ptr = concat_buf;
while (1) {
int w, h, max_color_val;
- int rem = concat_buf + sizeof(concat_buf) - read_ptr;
+ int rem = concat_buf + COMMON_BUFSIZE - read_ptr;
if (rem < 2
|| fgets(read_ptr, rem, theme_file) == NULL
) {
@@ -500,7 +519,7 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv)
// handle a case when we have many buffered lines
// already in the pipe
while ((num_buf = xmalloc_fgetline(fp)) != NULL) {
- if (strncmp(num_buf, "exit", 4) == 0) {
+ if (is_prefixed_with(num_buf, "exit")) {
DEBUG_MESSAGE("exit");
break;
}
diff --git a/release/src/router/busybox/miscutils/flash_eraseall.c b/release/src/router/busybox/miscutils/flash_eraseall.c
index 0598371d55..d95d214d91 100644
--- a/release/src/router/busybox/miscutils/flash_eraseall.c
+++ b/release/src/router/busybox/miscutils/flash_eraseall.c
@@ -11,10 +11,11 @@
*/
//usage:#define flash_eraseall_trivial_usage
-//usage: "[-jq] MTD_DEVICE"
+//usage: "[-jNq] MTD_DEVICE"
//usage:#define flash_eraseall_full_usage "\n\n"
//usage: "Erase an MTD device\n"
//usage: "\n -j Format the device for jffs2"
+//usage: "\n -N Don't skip bad blocks"
//usage: "\n -q Don't display progress messages"
#include "libbb.h"
@@ -22,9 +23,9 @@
#include <linux/jffs2.h>
#define OPTION_J (1 << 0)
-#define OPTION_Q (1 << 1)
-#define IS_NAND (1 << 2)
-#define BBTEST (1 << 3)
+#define OPTION_N (1 << 1)
+#define OPTION_Q (1 << 2)
+#define IS_NAND (1 << 3)
/* mtd/jffs2-user.h used to have this atrocity:
extern int target_endian;
@@ -71,7 +72,7 @@ int flash_eraseall_main(int argc UNUSED_PARAM, char **argv)
char *mtd_name;
opt_complementary = "=1";
- flags = BBTEST | getopt32(argv, "jq");
+ flags = getopt32(argv, "jNq");
mtd_name = argv[optind];
fd = xopen(mtd_name, O_RDWR);
@@ -139,14 +140,14 @@ int flash_eraseall_main(int argc UNUSED_PARAM, char **argv)
for (erase.start = 0; erase.start < meminfo.size;
erase.start += meminfo.erasesize) {
- if (flags & BBTEST) {
+ if (!(flags & OPTION_N)) {
int ret;
loff_t offset = erase.start;
ret = ioctl(fd, MEMGETBADBLOCK, &offset);
if (ret > 0) {
if (!(flags & OPTION_Q))
- bb_info_msg("\nSkipping bad block at 0x%08x", erase.start);
+ printf("\nSkipping bad block at 0x%08x\n", erase.start);
continue;
}
if (ret < 0) {
@@ -154,7 +155,7 @@ int flash_eraseall_main(int argc UNUSED_PARAM, char **argv)
* types e.g. NOR
*/
if (errno == EOPNOTSUPP) {
- flags &= ~BBTEST;
+ flags |= OPTION_N;
if (flags & IS_NAND)
bb_error_msg_and_die("bad block check not available");
} else {
diff --git a/release/src/router/busybox/miscutils/flashcp.c b/release/src/router/busybox/miscutils/flashcp.c
index 790f9c01f8..9bc588d14b 100644
--- a/release/src/router/busybox/miscutils/flashcp.c
+++ b/release/src/router/busybox/miscutils/flashcp.c
@@ -16,11 +16,12 @@
#include "libbb.h"
#include <mtd/mtd-user.h>
+/* If 1, simulates "flashing" by writing to existing regular file */
#define MTD_DEBUG 0
#define OPT_v (1 << 0)
-#define BUFSIZE (8 * 1024)
+#define BUFSIZE (4 * 1024)
static void progress(int mode, uoff_t count, uoff_t total)
{
@@ -32,7 +33,7 @@ static void progress(int mode, uoff_t count, uoff_t total)
if (total)
percent = (unsigned) (percent / total);
printf("\r%s: %"OFF_FMT"u/%"OFF_FMT"u (%u%%) ",
- (mode == 0) ? "Erasing block" : ((mode == 1) ? "Writing kb" : "Verifying kb"),
+ (mode < 0) ? "Erasing block" : ((mode == 0) ? "Writing kb" : "Verifying kb"),
count, total, (unsigned)percent);
fflush_all();
}
@@ -50,7 +51,6 @@ int flashcp_main(int argc UNUSED_PARAM, char **argv)
int fd_f, fd_d; /* input file and mtd device file descriptors */
int i;
uoff_t erase_count;
- unsigned opts;
struct mtd_info_user mtd;
struct erase_info_user e;
struct stat statb;
@@ -59,7 +59,7 @@ int flashcp_main(int argc UNUSED_PARAM, char **argv)
RESERVE_CONFIG_UBUFFER(buf2, BUFSIZE);
opt_complementary = "=2"; /* exactly 2 non-option args: file, dev */
- opts = getopt32(argv, "v");
+ /*opts =*/ getopt32(argv, "v");
argv += optind;
// filename = *argv++;
// devicename = *argv;
@@ -98,8 +98,7 @@ int flashcp_main(int argc UNUSED_PARAM, char **argv)
#endif
e.start = 0;
for (i = 1; i <= erase_count; i++) {
- progress(0, i, erase_count);
- errno = 0;
+ progress(-1, i, erase_count);
#if !MTD_DEBUG
if (ioctl(fd_d, MEMERASE, &e) < 0) {
bb_perror_msg_and_die("erase error at 0x%llx on %s",
@@ -114,7 +113,7 @@ int flashcp_main(int argc UNUSED_PARAM, char **argv)
/* doing this outer loop gives significantly smaller code
* than doing two separate loops for writing and verifying */
- for (i = 1; i <= 2; i++) {
+ for (i = 0; i <= 1; i++) {
uoff_t done;
unsigned count;
@@ -123,25 +122,29 @@ int flashcp_main(int argc UNUSED_PARAM, char **argv)
done = 0;
count = BUFSIZE;
while (1) {
- uoff_t rem = statb.st_size - done;
+ uoff_t rem;
+
+ progress(i, done / 1024, (uoff_t)statb.st_size / 1024);
+ rem = statb.st_size - done;
if (rem == 0)
break;
if (rem < BUFSIZE)
count = rem;
- progress(i, done / 1024, (uoff_t)statb.st_size / 1024);
xread(fd_f, buf, count);
- if (i == 1) {
+ if (i == 0) {
int ret;
+ if (count < BUFSIZE)
+ memset((char*)buf + count, 0, BUFSIZE - count);
errno = 0;
- ret = full_write(fd_d, buf, count);
- if (ret != count) {
+ ret = full_write(fd_d, buf, BUFSIZE);
+ if (ret != BUFSIZE) {
bb_perror_msg_and_die("write error at 0x%"OFF_FMT"x on %s, "
"write returned %d",
done, devicename, ret);
}
- } else { /* i == 2 */
+ } else { /* i == 1 */
xread(fd_d, buf2, count);
- if (memcmp(buf, buf2, count)) {
+ if (memcmp(buf, buf2, count) != 0) {
bb_error_msg_and_die("verification mismatch at 0x%"OFF_FMT"x", done);
}
}
diff --git a/release/src/router/busybox/miscutils/hdparm.c b/release/src/router/busybox/miscutils/hdparm.c
index a97f3e7b59..b4c5876d46 100644
--- a/release/src/router/busybox/miscutils/hdparm.c
+++ b/release/src/router/busybox/miscutils/hdparm.c
@@ -63,6 +63,7 @@
//usage: "\n -z Reread partition table"
#include "libbb.h"
+#include "common_bufsiz.h"
/* must be _after_ libbb.h: */
#include <linux/hdreg.h>
#include <sys/mount.h>
@@ -367,10 +368,7 @@ struct globals {
unsigned char flushcache[4] = { WIN_FLUSHCACHE, 0, 0, 0 };
#endif
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
-struct BUG_G_too_big {
- char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
-};
+#define G (*(struct globals*)bb_common_bufsiz1)
#define get_identity (G.get_identity )
#define get_geom (G.get_geom )
#define do_flush (G.do_flush )
@@ -433,7 +431,10 @@ struct BUG_G_too_big {
#define hwif_data (G.hwif_data )
#define hwif_ctrl (G.hwif_ctrl )
#define hwif_irq (G.hwif_irq )
-#define INIT_G() do { } while (0)
+#define INIT_G() do { \
+ setup_common_bufsiz(); \
+ BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
+} while (0)
/* Busybox messages and functions */
@@ -465,14 +466,14 @@ static void on_off(int value)
static void print_flag_on_off(int get_arg, const char *s, unsigned long arg)
{
if (get_arg) {
- printf(" setting %s to %ld", s, arg);
+ printf(" setting %s to %lu", s, arg);
on_off(arg);
}
}
static void print_value_on_off(const char *str, unsigned long argp)
{
- printf(" %s\t= %2ld", str, argp);
+ printf(" %s\t= %2lu", str, argp);
on_off(argp != 0);
}
@@ -763,9 +764,9 @@ static void identify(uint16_t *val)
) {
like_std = 5;
if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL))
- printf("powers-up in standby; SET FEATURES subcmd spins-up.\n");
+ puts("powers-up in standby; SET FEATURES subcmd spins-up.");
if (((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==PWRD_NID_VAL)) && (val[GEN_CONFIG] & INCOMPLETE))
- printf("\n\tWARNING: ID response incomplete.\n\tFollowing data may be incorrect.\n\n");
+ puts("\n\tWARNING: ID response incomplete.\n\tFollowing data may be incorrect.\n");
}
/* output the model and serial numbers and the fw revision */
@@ -875,7 +876,7 @@ static void identify(uint16_t *val)
if (min_std == 0xffff)
min_std = like_std > 4 ? like_std - 3 : 1;
- printf("Configuration:\n");
+ puts("Configuration:");
/* more info from the general configuration word */
if ((eqpt != CDROM) && (like_std == 1)) {
jj = val[GEN_CONFIG] >> 1;
@@ -909,7 +910,7 @@ static void identify(uint16_t *val)
mm = 0;
bbbig = 0;
if ((ll > 0x00FBFC10) && (!val[LCYLS]))
- printf("\tCHS addressing not supported\n");
+ puts("\tCHS addressing not supported");
else {
jj = val[WHATS_VALID] & OK_W54_58;
printf("\tLogical\t\tmax\tcurrent\n"
@@ -980,7 +981,7 @@ static void identify(uint16_t *val)
!(val[CAPAB_0] & IORDY_SUP) ? "(may be)" : "",
(val[CAPAB_0] & IORDY_OFF) ? "" :"not");
} else
- printf("no IORDY\n");
+ puts("no IORDY");
if ((like_std == 1) && val[BUF_TYPE]) {
printf("\tBuffer type: %04x: %s%s\n", val[BUF_TYPE],
@@ -1012,18 +1013,18 @@ static void identify(uint16_t *val)
}
printf("\tR/W multiple sector transfer: ");
if ((like_std < 3) && !(val[SECTOR_XFER_MAX] & SECTOR_XFER))
- printf("not supported\n");
+ puts("not supported");
else {
printf("Max = %u\tCurrent = ", val[SECTOR_XFER_MAX] & SECTOR_XFER);
if (val[SECTOR_XFER_CUR] & MULTIPLE_SETTING_VALID)
printf("%u\n", val[SECTOR_XFER_CUR] & SECTOR_XFER);
else
- printf("?\n");
+ puts("?");
}
if ((like_std > 3) && (val[CMDS_SUPP_1] & 0x0008)) {
/* We print out elsewhere whether the APM feature is enabled or
- not. If it's not enabled, let's not repeat the info; just print
- nothing here. */
+ * not. If it's not enabled, let's not repeat the info; just print
+ * nothing here. */
printf("\tAdvancedPM level: ");
if ((val[ADV_PWR] & 0xFF00) == 0x4000) {
uint8_t apm_level = val[ADV_PWR] & 0x00FF;
@@ -1038,9 +1039,9 @@ static void identify(uint16_t *val)
val[ACOUSTIC] & 0x00ff);
}
} else {
- /* ATAPI */
+ /* ATAPI */
if (eqpt != CDROM && (val[CAPAB_0] & SWRST_REQ))
- printf("\tATA sw reset required\n");
+ puts("\tATA sw reset required");
if (val[PKT_REL] || val[SVC_NBSY]) {
printf("\tOverlap support:");
@@ -1056,7 +1057,7 @@ static void identify(uint16_t *val)
/* DMA stuff. Check that only one DMA mode is selected. */
printf("\tDMA: ");
if (!(val[CAPAB_0] & DMA_SUP))
- printf("not supported\n");
+ puts("not supported");
else {
if (val[DMA_MODE] && !val[SINGLE_DMA] && !val[MULTI_DMA])
printf(" sdma%u\n", (val[DMA_MODE] & MODE) >> 8);
@@ -1079,7 +1080,7 @@ static void identify(uint16_t *val)
bb_putchar('\n');
if ((dev == ATAPI_DEV) && (eqpt != CDROM) && (val[CAPAB_0] & DMA_IL_SUP))
- printf("\t\tInterleaved DMA support\n");
+ puts("\t\tInterleaved DMA support");
if ((val[WHATS_VALID] & OK_W64_70)
&& (val[DMA_TIME_MIN] || val[DMA_TIME_NORM])
@@ -1121,8 +1122,8 @@ static void identify(uint16_t *val)
}
if ((val[CMDS_SUPP_1] & VALID) == VALID_VAL) {
- printf("Commands/features:\n"
- "\tEnabled\tSupported:\n");
+ puts("Commands/features:\n"
+ "\tEnabled\tSupported:");
jj = val[CMDS_SUPP_0];
kk = val[CMDS_EN_0];
for (ii = 0; ii < NUM_CMD_FEAT_STR; ii++) {
@@ -1150,7 +1151,7 @@ static void identify(uint16_t *val)
if ((eqpt != CDROM) && (like_std > 3)
&& (val[SECU_STATUS] || val[ERASE_TIME] || val[ENH_ERASE_TIME])
) {
- printf("Security:\n");
+ puts("Security:");
if (val[PSWD_CODE] && (val[PSWD_CODE] != NOVAL_1))
printf("\tMaster password revision code = %u\n", val[PSWD_CODE]);
jj = val[SECU_STATUS];
@@ -1366,7 +1367,7 @@ static NOINLINE void dump_identity(const struct hd_driveid *id)
}
}
#endif /* __NEW_HD_DRIVE_ID */
- printf("\n\n * current active mode\n\n");
+ puts("\n\n * current active mode\n");
}
#endif
@@ -1507,9 +1508,9 @@ static void bus_state_value(unsigned value)
else if (value == BUSSTATE_OFF)
on_off(0);
else if (value == BUSSTATE_TRISTATE)
- printf(" (tristate)\n");
+ puts(" (tristate)");
else
- printf(" (unknown: %d)\n", value);
+ printf(" (unknown: %u)\n", value);
}
#endif
@@ -1531,7 +1532,7 @@ static void interpret_standby(uint8_t standby)
printf("vendor-specific");
if (standby == 254)
printf("reserved");
- printf(")\n");
+ puts(")");
}
static const uint8_t xfermode_val[] ALIGN1 = {
@@ -1582,14 +1583,14 @@ static void interpret_xfermode(unsigned xfermode)
printf("UltraDMA mode%u", xfermode - 64);
else
printf("unknown");
- printf(")\n");
+ puts(")");
}
#endif /* HDIO_DRIVE_CMD */
static void print_flag(int flag, const char *s, unsigned long value)
{
if (flag)
- printf(" setting %s to %ld\n", s, value);
+ printf(" setting %s to %lu\n", s, value);
}
static void process_dev(char *devname)
@@ -1633,7 +1634,7 @@ static void process_dev(char *devname)
if (noisy_piomode) {
printf(" attempting to ");
if (piomode == 255)
- printf("auto-tune PIO mode\n");
+ puts("auto-tune PIO mode");
else if (piomode < 100)
printf("set PIO mode to %d\n", piomode);
else if (piomode < 200)
@@ -1762,7 +1763,7 @@ static void process_dev(char *devname)
#ifndef WIN_STANDBYNOW2
#define WIN_STANDBYNOW2 0x94
#endif
- printf(" issuing standby command\n");
+ puts(" issuing standby command");
args[0] = WIN_STANDBYNOW1;
ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_STANDBYNOW2);
}
@@ -1773,13 +1774,13 @@ static void process_dev(char *devname)
#ifndef WIN_SLEEPNOW2
#define WIN_SLEEPNOW2 0x99
#endif
- printf(" issuing sleep command\n");
+ puts(" issuing sleep command");
args[0] = WIN_SLEEPNOW1;
ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_SLEEPNOW2);
}
if (set_seagate) {
args[0] = 0xfb;
- printf(" disabling Seagate auto powersaving mode\n");
+ puts(" disabling Seagate auto powersaving mode");
ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
}
if (getset_standby == IS_SET) {
@@ -1815,17 +1816,17 @@ static void process_dev(char *devname)
if (!ioctl_or_warn(fd, HDIO_GET_32BIT, &parm)) {
printf(" IO_support\t=%3ld (", parm);
if (parm == 0)
- printf("default 16-bit)\n");
+ puts("default 16-bit)");
else if (parm == 2)
- printf("16-bit)\n");
+ puts("16-bit)");
else if (parm == 1)
- printf("32-bit)\n");
+ puts("32-bit)");
else if (parm == 3)
- printf("32-bit w/sync)\n");
+ puts("32-bit w/sync)");
else if (parm == 8)
- printf("Request-Queue-Bypass)\n");
+ puts("Request-Queue-Bypass)");
else
- printf("\?\?\?)\n");
+ puts("\?\?\?)");
}
}
if (getset_unmask) {
@@ -1837,7 +1838,7 @@ static void process_dev(char *devname)
if (!ioctl_or_warn(fd, HDIO_GET_DMA, &parm)) {
printf(fmt, "using_dma", parm);
if (parm == 8)
- printf(" (DMA-Assisted-PIO)\n");
+ puts(" (DMA-Assisted-PIO)");
else
on_off(parm != 0);
}
@@ -1921,7 +1922,7 @@ static void process_dev(char *devname)
id.multsect_valid &= ~1;
dump_identity(&id);
} else if (errno == -ENOMSG)
- printf(" no identification info available\n");
+ puts(" no identification info available");
else if (ENABLE_IOCTL_HEX2STR_ERROR) /* To be coherent with ioctl_or_warn */
bb_perror_msg("HDIO_GET_IDENTITY");
else
diff --git a/release/src/router/busybox/miscutils/i2c_tools.c b/release/src/router/busybox/miscutils/i2c_tools.c
new file mode 100644
index 0000000000..57bb72ae7e
--- /dev/null
+++ b/release/src/router/busybox/miscutils/i2c_tools.c
@@ -0,0 +1,1343 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Minimal i2c-tools implementation for busybox.
+ * Parts of code ported from i2c-tools:
+ * http://www.lm-sensors.org/wiki/I2CTools.
+ *
+ * Copyright (C) 2014 by Bartosz Golaszewski <bartekgola@gmail.com>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+//config:config I2CGET
+//config: bool "i2cget"
+//config: default y
+//config: select PLATFORM_LINUX
+//config: help
+//config: Read from I2C/SMBus chip registers.
+//config:
+//config:config I2CSET
+//config: bool "i2cset"
+//config: default y
+//config: select PLATFORM_LINUX
+//config: help
+//config: Set I2C registers.
+//config:
+//config:config I2CDUMP
+//config: bool "i2cdump"
+//config: default y
+//config: select PLATFORM_LINUX
+//config: help
+//config: Examine I2C registers.
+//config:
+//config:config I2CDETECT
+//config: bool "i2cdetect"
+//config: default y
+//config: select PLATFORM_LINUX
+//config: help
+//config: Detect I2C chips.
+//config:
+
+//applet:IF_I2CGET(APPLET(i2cget, BB_DIR_USR_SBIN, BB_SUID_DROP))
+//applet:IF_I2CSET(APPLET(i2cset, BB_DIR_USR_SBIN, BB_SUID_DROP))
+//applet:IF_I2CDUMP(APPLET(i2cdump, BB_DIR_USR_SBIN, BB_SUID_DROP))
+//applet:IF_I2CDETECT(APPLET(i2cdetect, BB_DIR_USR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_I2CGET) += i2c_tools.o
+//kbuild:lib-$(CONFIG_I2CSET) += i2c_tools.o
+//kbuild:lib-$(CONFIG_I2CDUMP) += i2c_tools.o
+//kbuild:lib-$(CONFIG_I2CDETECT) += i2c_tools.o
+
+/*
+ * Unsupported stuff:
+ *
+ * - upstream i2c-tools can also look-up i2c busses by name, we only accept
+ * numbers,
+ * - bank and bankreg parameters for i2cdump are not supported because of
+ * their limited usefulness (see i2cdump manual entry for more info),
+ * - i2cdetect doesn't look for bus info in /proc as it does in upstream, but
+ * it shouldn't be a problem in modern kernels.
+ */
+
+#include "libbb.h"
+#include "common_bufsiz.h"
+
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+
+#define I2CDUMP_NUM_REGS 256
+
+#define I2CDETECT_MODE_AUTO 0
+#define I2CDETECT_MODE_QUICK 1
+#define I2CDETECT_MODE_READ 2
+
+/*
+ * This is needed for ioctl_or_perror_and_die() since it only accepts pointers.
+ */
+static ALWAYS_INLINE void *itoptr(int i)
+{
+ return (void*)(intptr_t)i;
+}
+
+static int32_t i2c_smbus_access(int fd, char read_write, uint8_t cmd,
+ int size, union i2c_smbus_data *data)
+{
+ struct i2c_smbus_ioctl_data args;
+
+ args.read_write = read_write;
+ args.command = cmd;
+ args.size = size;
+ args.data = data;
+
+ return ioctl(fd, I2C_SMBUS, &args);
+}
+
+static int32_t i2c_smbus_read_byte(int fd)
+{
+ union i2c_smbus_data data;
+ int err;
+
+ err = i2c_smbus_access(fd, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &data);
+ if (err < 0)
+ return err;
+
+ return data.byte;
+}
+
+#if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP
+static int32_t i2c_smbus_write_byte(int fd, uint8_t val)
+{
+ return i2c_smbus_access(fd, I2C_SMBUS_WRITE,
+ val, I2C_SMBUS_BYTE, NULL);
+}
+
+static int32_t i2c_smbus_read_byte_data(int fd, uint8_t cmd)
+{
+ union i2c_smbus_data data;
+ int err;
+
+ err = i2c_smbus_access(fd, I2C_SMBUS_READ, cmd,
+ I2C_SMBUS_BYTE_DATA, &data);
+ if (err < 0)
+ return err;
+
+ return data.byte;
+}
+
+static int32_t i2c_smbus_read_word_data(int fd, uint8_t cmd)
+{
+ union i2c_smbus_data data;
+ int err;
+
+ err = i2c_smbus_access(fd, I2C_SMBUS_READ, cmd,
+ I2C_SMBUS_WORD_DATA, &data);
+ if (err < 0)
+ return err;
+
+ return data.word;
+}
+#endif /* ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP */
+
+#if ENABLE_I2CSET
+static int32_t i2c_smbus_write_byte_data(int file,
+ uint8_t cmd, uint8_t value)
+{
+ union i2c_smbus_data data;
+
+ data.byte = value;
+
+ return i2c_smbus_access(file, I2C_SMBUS_WRITE, cmd,
+ I2C_SMBUS_BYTE_DATA, &data);
+}
+
+static int32_t i2c_smbus_write_word_data(int file, uint8_t cmd, uint16_t value)
+{
+ union i2c_smbus_data data;
+
+ data.word = value;
+
+ return i2c_smbus_access(file, I2C_SMBUS_WRITE, cmd,
+ I2C_SMBUS_WORD_DATA, &data);
+}
+
+static int32_t i2c_smbus_write_block_data(int file, uint8_t cmd,
+ uint8_t length, const uint8_t *values)
+{
+ union i2c_smbus_data data;
+
+ if (length > I2C_SMBUS_BLOCK_MAX)
+ length = I2C_SMBUS_BLOCK_MAX;
+
+ memcpy(data.block+1, values, length);
+ data.block[0] = length;
+
+ return i2c_smbus_access(file, I2C_SMBUS_WRITE, cmd,
+ I2C_SMBUS_BLOCK_DATA, &data);
+}
+
+static int32_t i2c_smbus_write_i2c_block_data(int file, uint8_t cmd,
+ uint8_t length, const uint8_t *values)
+{
+ union i2c_smbus_data data;
+
+ if (length > I2C_SMBUS_BLOCK_MAX)
+ length = I2C_SMBUS_BLOCK_MAX;
+
+ memcpy(data.block+1, values, length);
+ data.block[0] = length;
+
+ return i2c_smbus_access(file, I2C_SMBUS_WRITE, cmd,
+ I2C_SMBUS_I2C_BLOCK_BROKEN, &data);
+}
+#endif /* ENABLE_I2CSET */
+
+#if ENABLE_I2CDUMP
+/*
+ * Returns the number of bytes read, vals must hold at
+ * least I2C_SMBUS_BLOCK_MAX bytes.
+ */
+static int32_t i2c_smbus_read_block_data(int fd, uint8_t cmd, uint8_t *vals)
+{
+ union i2c_smbus_data data;
+ int i, err;
+
+ err = i2c_smbus_access(fd, I2C_SMBUS_READ, cmd,
+ I2C_SMBUS_BLOCK_DATA, &data);
+ if (err < 0)
+ return err;
+
+ for (i = 1; i <= data.block[0]; i++)
+ *vals++ = data.block[i];
+ return data.block[0];
+}
+
+static int32_t i2c_smbus_read_i2c_block_data(int fd, uint8_t cmd,
+ uint8_t len, uint8_t *vals)
+{
+ union i2c_smbus_data data;
+ int i, err;
+
+ if (len > I2C_SMBUS_BLOCK_MAX)
+ len = I2C_SMBUS_BLOCK_MAX;
+ data.block[0] = len;
+
+ err = i2c_smbus_access(fd, I2C_SMBUS_READ, cmd,
+ len == 32 ? I2C_SMBUS_I2C_BLOCK_BROKEN :
+ I2C_SMBUS_I2C_BLOCK_DATA, &data);
+ if (err < 0)
+ return err;
+
+ for (i = 1; i <= data.block[0]; i++)
+ *vals++ = data.block[i];
+ return data.block[0];
+}
+#endif /* ENABLE_I2CDUMP */
+
+#if ENABLE_I2CDETECT
+static int32_t i2c_smbus_write_quick(int fd, uint8_t val)
+{
+ return i2c_smbus_access(fd, val, 0, I2C_SMBUS_QUICK, NULL);
+}
+#endif /* ENABLE_I2CDETECT */
+
+static int i2c_bus_lookup(const char *bus_str)
+{
+ return xstrtou_range(bus_str, 10, 0, 0xfffff);
+}
+
+#if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP
+static int i2c_parse_bus_addr(const char *addr_str)
+{
+ /* Slave address must be in range 0x03 - 0x77. */
+ return xstrtou_range(addr_str, 16, 0x03, 0x77);
+}
+
+static void i2c_set_pec(int fd, int pec)
+{
+ ioctl_or_perror_and_die(fd, I2C_PEC,
+ itoptr(pec ? 1 : 0),
+ "can't set PEC");
+}
+
+static void i2c_set_slave_addr(int fd, int addr, int force)
+{
+ ioctl_or_perror_and_die(fd, force ? I2C_SLAVE_FORCE : I2C_SLAVE,
+ itoptr(addr),
+ "can't set address to 0x%02x", addr);
+}
+#endif /* ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP */
+
+#if ENABLE_I2CGET || ENABLE_I2CSET
+static int i2c_parse_data_addr(const char *data_addr)
+{
+ /* Data address must be an 8 bit integer. */
+ return xstrtou_range(data_addr, 16, 0, 0xff);
+}
+#endif /* ENABLE_I2CGET || ENABLE_I2CSET */
+
+/*
+ * Opens the device file associated with given i2c bus.
+ *
+ * Upstream i2c-tools also support opening devices by i2c bus name
+ * but we drop it here for size reduction.
+ */
+static int i2c_dev_open(int i2cbus)
+{
+ char filename[sizeof("/dev/i2c-%d") + sizeof(int)*3];
+ int fd;
+
+ sprintf(filename, "/dev/i2c-%d", i2cbus);
+ fd = open(filename, O_RDWR);
+ if (fd < 0) {
+ if (errno == ENOENT) {
+ filename[8] = '/'; /* change to "/dev/i2c/%d" */
+ fd = xopen(filename, O_RDWR);
+ } else {
+ bb_perror_msg_and_die("can't open '%s'", filename);
+ }
+ }
+
+ return fd;
+}
+
+/* Size reducing helpers for xxx_check_funcs(). */
+static void get_funcs_matrix(int fd, unsigned long *funcs)
+{
+ ioctl_or_perror_and_die(fd, I2C_FUNCS, funcs,
+ "can't get adapter functionality matrix");
+}
+
+#if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP
+static void check_funcs_test_end(int funcs, int pec, const char *err)
+{
+ if (pec && !(funcs & (I2C_FUNC_SMBUS_PEC | I2C_FUNC_I2C)))
+ bb_error_msg("warning: adapter does not support PEC");
+
+ if (err)
+ bb_error_msg_and_die(
+ "adapter has no %s capability", err);
+}
+#endif /* ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP */
+
+/*
+ * The below functions emit an error message and exit if the adapter doesn't
+ * support desired functionalities.
+ */
+#if ENABLE_I2CGET || ENABLE_I2CDUMP
+static void check_read_funcs(int fd, int mode, int data_addr, int pec)
+{
+ unsigned long funcs;
+ const char *err = NULL;
+
+ get_funcs_matrix(fd, &funcs);
+ switch (mode) {
+ case I2C_SMBUS_BYTE:
+ if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE)) {
+ err = "SMBus receive byte";
+ break;
+ }
+ if (data_addr >= 0 && !(funcs & I2C_FUNC_SMBUS_WRITE_BYTE))
+ err = "SMBus send byte";
+ break;
+ case I2C_SMBUS_BYTE_DATA:
+ if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE_DATA))
+ err = "SMBus read byte";
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ if (!(funcs & I2C_FUNC_SMBUS_READ_WORD_DATA))
+ err = "SMBus read word";
+ break;
+#if ENABLE_I2CDUMP
+ case I2C_SMBUS_BLOCK_DATA:
+ if (!(funcs & I2C_FUNC_SMBUS_READ_BLOCK_DATA))
+ err = "SMBus block read";
+ break;
+
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ if (!(funcs & I2C_FUNC_SMBUS_READ_I2C_BLOCK))
+ err = "I2C block read";
+ break;
+#endif /* ENABLE_I2CDUMP */
+ default:
+ bb_error_msg_and_die("internal error");
+ }
+ check_funcs_test_end(funcs, pec, err);
+}
+#endif /* ENABLE_I2CGET || ENABLE_I2CDUMP */
+
+#if ENABLE_I2CSET
+static void check_write_funcs(int fd, int mode, int pec)
+{
+ unsigned long funcs;
+ const char *err = NULL;
+
+ get_funcs_matrix(fd, &funcs);
+ switch (mode) {
+ case I2C_SMBUS_BYTE:
+ if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE))
+ err = "SMBus send byte";
+ break;
+
+ case I2C_SMBUS_BYTE_DATA:
+ if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+ err = "SMBus write byte";
+ break;
+
+ case I2C_SMBUS_WORD_DATA:
+ if (!(funcs & I2C_FUNC_SMBUS_WRITE_WORD_DATA))
+ err = "SMBus write word";
+ break;
+
+ case I2C_SMBUS_BLOCK_DATA:
+ if (!(funcs & I2C_FUNC_SMBUS_WRITE_BLOCK_DATA))
+ err = "SMBus block write";
+ break;
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ if (!(funcs & I2C_FUNC_SMBUS_WRITE_I2C_BLOCK))
+ err = "I2C block write";
+ break;
+ }
+ check_funcs_test_end(funcs, pec, err);
+}
+#endif /* ENABLE_I2CSET */
+
+static void confirm_or_abort(void)
+{
+ fprintf(stderr, "Continue? [y/N] ");
+ fflush_all();
+ if (!bb_ask_confirmation())
+ bb_error_msg_and_die("aborting");
+}
+
+/*
+ * Return only if user confirms the action, abort otherwise.
+ *
+ * The messages displayed here are much less elaborate than their i2c-tools
+ * counterparts - this is done for size reduction.
+ */
+static void confirm_action(int bus_addr, int mode, int data_addr, int pec)
+{
+ bb_error_msg("WARNING! This program can confuse your I2C bus");
+
+ /* Don't let the user break his/her EEPROMs */
+ if (bus_addr >= 0x50 && bus_addr <= 0x57 && pec) {
+ bb_error_msg_and_die("this is I2C not smbus - using PEC on I2C "
+ "devices may result in data loss, aborting");
+ }
+
+ if (mode == I2C_SMBUS_BYTE && data_addr >= 0 && pec)
+ bb_error_msg("WARNING! May interpret a write byte command "
+ "with PEC as a write byte data command");
+
+ if (pec)
+ bb_error_msg("PEC checking enabled");
+
+ confirm_or_abort();
+}
+
+#if ENABLE_I2CGET
+//usage:#define i2cget_trivial_usage
+//usage: "[-f] [-y] BUS CHIP-ADDRESS [DATA-ADDRESS [MODE]]"
+//usage:#define i2cget_full_usage "\n\n"
+//usage: "Read from I2C/SMBus chip registers\n"
+//usage: "\n I2CBUS i2c bus number"
+//usage: "\n ADDRESS 0x03 - 0x77"
+//usage: "\nMODE is:"
+//usage: "\n b read byte data (default)"
+//usage: "\n w read word data"
+//usage: "\n c write byte/read byte"
+//usage: "\n Append p for SMBus PEC"
+//usage: "\n"
+//usage: "\n -f force access"
+//usage: "\n -y disable interactive mode"
+int i2cget_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int i2cget_main(int argc UNUSED_PARAM, char **argv)
+{
+ const unsigned opt_f = (1 << 0), opt_y = (1 << 1);
+ const char *const optstr = "fy";
+
+ int bus_num, bus_addr, data_addr = -1, status;
+ int mode = I2C_SMBUS_BYTE, pec = 0, fd;
+ unsigned opts;
+
+ opt_complementary = "-2:?4"; /* from 2 to 4 args */
+ opts = getopt32(argv, optstr);
+ argv += optind;
+
+ bus_num = i2c_bus_lookup(argv[0]);
+ bus_addr = i2c_parse_bus_addr(argv[1]);
+
+ if (argv[2]) {
+ data_addr = i2c_parse_data_addr(argv[2]);
+ mode = I2C_SMBUS_BYTE_DATA;
+ if (argv[3]) {
+ switch (argv[3][0]) {
+ case 'b': /* Already set */ break;
+ case 'w': mode = I2C_SMBUS_WORD_DATA; break;
+ case 'c': mode = I2C_SMBUS_BYTE; break;
+ default:
+ bb_error_msg("invalid mode");
+ bb_show_usage();
+ }
+ pec = argv[3][1] == 'p';
+ }
+ }
+
+ fd = i2c_dev_open(bus_num);
+ check_read_funcs(fd, mode, data_addr, pec);
+ i2c_set_slave_addr(fd, bus_addr, opts & opt_f);
+
+ if (!(opts & opt_y))
+ confirm_action(bus_addr, mode, data_addr, pec);
+
+ if (pec)
+ i2c_set_pec(fd, 1);
+
+ switch (mode) {
+ case I2C_SMBUS_BYTE:
+ if (data_addr >= 0) {
+ status = i2c_smbus_write_byte(fd, data_addr);
+ if (status < 0)
+ bb_error_msg("warning - write failed");
+ }
+ status = i2c_smbus_read_byte(fd);
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ status = i2c_smbus_read_word_data(fd, data_addr);
+ break;
+ default: /* I2C_SMBUS_BYTE_DATA */
+ status = i2c_smbus_read_byte_data(fd, data_addr);
+ }
+ close(fd);
+
+ if (status < 0)
+ bb_perror_msg_and_die("read failed");
+
+ printf("0x%0*x\n", mode == I2C_SMBUS_WORD_DATA ? 4 : 2, status);
+
+ return 0;
+}
+#endif /* ENABLE_I2CGET */
+
+#if ENABLE_I2CSET
+//usage:#define i2cset_trivial_usage
+//usage: "[-f] [-y] [-m MASK] BUS CHIP-ADDR DATA-ADDR [VALUE] ... [MODE]"
+//usage:#define i2cset_full_usage "\n\n"
+//usage: "Set I2C registers\n"
+//usage: "\n I2CBUS i2c bus number"
+//usage: "\n ADDRESS 0x03 - 0x77"
+//usage: "\nMODE is:"
+//usage: "\n c byte, no value"
+//usage: "\n b byte data (default)"
+//usage: "\n w word data"
+//usage: "\n i I2C block data"
+//usage: "\n s SMBus block data"
+//usage: "\n Append p for SMBus PEC"
+//usage: "\n"
+//usage: "\n -f force access"
+//usage: "\n -y disable interactive mode"
+//usage: "\n -r read back and compare the result"
+//usage: "\n -m MASK mask specifying which bits to write"
+int i2cset_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int i2cset_main(int argc, char **argv)
+{
+ const unsigned opt_f = (1 << 0), opt_y = (1 << 1),
+ opt_m = (1 << 2), opt_r = (1 << 3);
+ const char *const optstr = "fym:r";
+
+ int bus_num, bus_addr, data_addr, mode = I2C_SMBUS_BYTE, pec = 0;
+ int val, blen = 0, mask = 0, fd, status;
+ unsigned char block[I2C_SMBUS_BLOCK_MAX];
+ char *opt_m_arg = NULL;
+ unsigned opts;
+
+ opt_complementary = "-3"; /* from 3 to ? args */
+ opts = getopt32(argv, optstr, &opt_m_arg);
+ argv += optind;
+ argc -= optind;
+
+ bus_num = i2c_bus_lookup(argv[0]);
+ bus_addr = i2c_parse_bus_addr(argv[1]);
+ data_addr = i2c_parse_data_addr(argv[2]);
+
+ if (argv[3]) {
+ if (!argv[4] && argv[3][0] != 'c') {
+ mode = I2C_SMBUS_BYTE_DATA; /* Implicit b */
+ } else {
+ switch (argv[argc-1][0]) {
+ case 'c': /* Already set */ break;
+ case 'b': mode = I2C_SMBUS_BYTE_DATA; break;
+ case 'w': mode = I2C_SMBUS_WORD_DATA; break;
+ case 's': mode = I2C_SMBUS_BLOCK_DATA; break;
+ case 'i': mode = I2C_SMBUS_I2C_BLOCK_DATA; break;
+ default:
+ bb_error_msg("invalid mode");
+ bb_show_usage();
+ }
+
+ pec = argv[argc-1][1] == 'p';
+ if (mode == I2C_SMBUS_BLOCK_DATA ||
+ mode == I2C_SMBUS_I2C_BLOCK_DATA) {
+ if (pec && mode == I2C_SMBUS_I2C_BLOCK_DATA)
+ bb_error_msg_and_die(
+ "PEC not supported for I2C "
+ "block writes");
+ if (opts & opt_m)
+ bb_error_msg_and_die(
+ "mask not supported for block "
+ "writes");
+ }
+ }
+ }
+
+ /* Prepare the value(s) to be written according to current mode. */
+ switch (mode) {
+ case I2C_SMBUS_BYTE_DATA:
+ val = xstrtou_range(argv[3], 0, 0, 0xff);
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ val = xstrtou_range(argv[3], 0, 0, 0xffff);
+ break;
+ case I2C_SMBUS_BLOCK_DATA:
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ for (blen = 3; blen < (argc - 1); blen++)
+ block[blen] = xstrtou_range(argv[blen], 0, 0, 0xff);
+ val = -1;
+ break;
+ default:
+ val = -1;
+ break;
+ }
+
+ if (opts & opt_m) {
+ mask = xstrtou_range(opt_m_arg, 0, 0,
+ (mode == I2C_SMBUS_BYTE ||
+ mode == I2C_SMBUS_BYTE_DATA) ? 0xff : 0xffff);
+ }
+
+ fd = i2c_dev_open(bus_num);
+ check_write_funcs(fd, mode, pec);
+ i2c_set_slave_addr(fd, bus_addr, opts & opt_f);
+
+ if (!(opts & opt_y))
+ confirm_action(bus_addr, mode, data_addr, pec);
+
+ /*
+ * If we're using mask - read the current value here and adjust the
+ * value to be written.
+ */
+ if (opts & opt_m) {
+ int tmpval;
+
+ switch (mode) {
+ case I2C_SMBUS_BYTE:
+ tmpval = i2c_smbus_read_byte(fd);
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ tmpval = i2c_smbus_read_word_data(fd, data_addr);
+ break;
+ default:
+ tmpval = i2c_smbus_read_byte_data(fd, data_addr);
+ }
+
+ if (tmpval < 0)
+ bb_perror_msg_and_die("can't read old value");
+
+ val = (val & mask) | (tmpval & ~mask);
+
+ if (!(opts & opt_y)) {
+ bb_error_msg("old value 0x%0*x, write mask "
+ "0x%0*x, will write 0x%0*x to register "
+ "0x%02x",
+ mode == I2C_SMBUS_WORD_DATA ? 4 : 2, tmpval,
+ mode == I2C_SMBUS_WORD_DATA ? 4 : 2, mask,
+ mode == I2C_SMBUS_WORD_DATA ? 4 : 2, val,
+ data_addr);
+ confirm_or_abort();
+ }
+ }
+
+ if (pec)
+ i2c_set_pec(fd, 1);
+
+ switch (mode) {
+ case I2C_SMBUS_BYTE:
+ status = i2c_smbus_write_byte(fd, data_addr);
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ status = i2c_smbus_write_word_data(fd, data_addr, val);
+ break;
+ case I2C_SMBUS_BLOCK_DATA:
+ status = i2c_smbus_write_block_data(fd, data_addr,
+ blen, block);
+ break;
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ status = i2c_smbus_write_i2c_block_data(fd, data_addr,
+ blen, block);
+ break;
+ default: /* I2C_SMBUS_BYTE_DATA */
+ status = i2c_smbus_write_byte_data(fd, data_addr, val);
+ break;
+ }
+ if (status < 0)
+ bb_perror_msg_and_die("write failed");
+
+ if (pec)
+ i2c_set_pec(fd, 0); /* Clear PEC. */
+
+ /* No readback required - we're done. */
+ if (!(opts & opt_r))
+ return 0;
+
+ switch (mode) {
+ case I2C_SMBUS_BYTE:
+ status = i2c_smbus_read_byte(fd);
+ val = data_addr;
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ status = i2c_smbus_read_word_data(fd, data_addr);
+ break;
+ default: /* I2C_SMBUS_BYTE_DATA */
+ status = i2c_smbus_read_byte_data(fd, data_addr);
+ }
+
+ if (status < 0) {
+ puts("Warning - readback failed");
+ } else
+ if (status != val) {
+ printf("Warning - data mismatch - wrote "
+ "0x%0*x, read back 0x%0*x\n",
+ mode == I2C_SMBUS_WORD_DATA ? 4 : 2, val,
+ mode == I2C_SMBUS_WORD_DATA ? 4 : 2, status);
+ } else {
+ printf("Value 0x%0*x written, readback matched\n",
+ mode == I2C_SMBUS_WORD_DATA ? 4 : 2, val);
+ }
+
+ return 0;
+}
+#endif /* ENABLE_I2CSET */
+
+#if ENABLE_I2CDUMP
+static int read_block_data(int buf_fd, int mode, int *block)
+{
+ uint8_t cblock[I2C_SMBUS_BLOCK_MAX + I2CDUMP_NUM_REGS];
+ int res, blen = 0, tmp, i;
+
+ if (mode == I2C_SMBUS_BLOCK_DATA) {
+ blen = i2c_smbus_read_block_data(buf_fd, 0, cblock);
+ if (blen <= 0)
+ goto fail;
+ } else {
+ for (res = 0; res < I2CDUMP_NUM_REGS; res += tmp) {
+ tmp = i2c_smbus_read_i2c_block_data(
+ buf_fd, res, I2C_SMBUS_BLOCK_MAX,
+ cblock + res);
+ if (tmp <= 0) {
+ blen = tmp;
+ goto fail;
+ }
+ }
+
+ if (res >= I2CDUMP_NUM_REGS)
+ res = I2CDUMP_NUM_REGS;
+
+ for (i = 0; i < res; i++)
+ block[i] = cblock[i];
+
+ if (mode != I2C_SMBUS_BLOCK_DATA)
+ for (i = res; i < I2CDUMP_NUM_REGS; i++)
+ block[i] = -1;
+ }
+
+ return blen;
+
+ fail:
+ bb_error_msg_and_die("block read failed: %d", blen);
+}
+
+/* Dump all but word data. */
+static void dump_data(int bus_fd, int mode, unsigned first,
+ unsigned last, int *block, int blen)
+{
+ int i, j, res;
+
+ puts(" 0 1 2 3 4 5 6 7 8 9 a b c d e f"
+ " 0123456789abcdef");
+
+ for (i = 0; i < I2CDUMP_NUM_REGS; i += 0x10) {
+ if (mode == I2C_SMBUS_BLOCK_DATA && i >= blen)
+ break;
+ if (i/16 < first/16)
+ continue;
+ if (i/16 > last/16)
+ break;
+
+ printf("%02x: ", i);
+ for (j = 0; j < 16; j++) {
+ fflush_all();
+ /* Skip unwanted registers */
+ if (i+j < first || i+j > last) {
+ printf(" ");
+ if (mode == I2C_SMBUS_WORD_DATA) {
+ printf(" ");
+ j++;
+ }
+ continue;
+ }
+
+ switch (mode) {
+ case I2C_SMBUS_BYTE_DATA:
+ res = i2c_smbus_read_byte_data(bus_fd, i+j);
+ block[i+j] = res;
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ res = i2c_smbus_read_word_data(bus_fd, i+j);
+ if (res < 0) {
+ block[i+j] = res;
+ block[i+j+1] = res;
+ } else {
+ block[i+j] = res & 0xff;
+ block[i+j+1] = res >> 8;
+ }
+ break;
+ case I2C_SMBUS_BYTE:
+ res = i2c_smbus_read_byte(bus_fd);
+ block[i+j] = res;
+ break;
+ default:
+ res = block[i+j];
+ }
+
+ if (mode == I2C_SMBUS_BLOCK_DATA &&
+ i+j >= blen) {
+ printf(" ");
+ } else if (res < 0) {
+ printf("XX ");
+ if (mode == I2C_SMBUS_WORD_DATA)
+ printf("XX ");
+ } else {
+ printf("%02x ", block[i+j]);
+ if (mode == I2C_SMBUS_WORD_DATA)
+ printf("%02x ", block[i+j+1]);
+ }
+
+ if (mode == I2C_SMBUS_WORD_DATA)
+ j++;
+ }
+ printf(" ");
+
+ for (j = 0; j < 16; j++) {
+ if (mode == I2C_SMBUS_BLOCK_DATA && i+j >= blen)
+ break;
+ /* Skip unwanted registers */
+ if (i+j < first || i+j > last) {
+ bb_putchar(' ');
+ continue;
+ }
+
+ res = block[i+j];
+ if (res < 0) {
+ bb_putchar('X');
+ } else if (res == 0x00 || res == 0xff) {
+ bb_putchar('.');
+ } else if (res < 32 || res >= 127) {
+ bb_putchar('?');
+ } else {
+ bb_putchar(res);
+ }
+ }
+ bb_putchar('\n');
+ }
+}
+
+static void dump_word_data(int bus_fd, unsigned first, unsigned last)
+{
+ int i, j, rv;
+
+ /* Word data. */
+ puts(" 0,8 1,9 2,a 3,b 4,c 5,d 6,e 7,f");
+ for (i = 0; i < 256; i += 8) {
+ if (i/8 < first/8)
+ continue;
+ if (i/8 > last/8)
+ break;
+
+ printf("%02x: ", i);
+ for (j = 0; j < 8; j++) {
+ /* Skip unwanted registers. */
+ if (i+j < first || i+j > last) {
+ printf(" ");
+ continue;
+ }
+
+ rv = i2c_smbus_read_word_data(bus_fd, i+j);
+ if (rv < 0)
+ printf("XXXX ");
+ else
+ printf("%04x ", rv & 0xffff);
+ }
+ bb_putchar('\n');
+ }
+}
+
+//usage:#define i2cdump_trivial_usage
+//usage: "[-f] [-r FIRST-LAST] [-y] BUS ADDR [MODE]"
+//usage:#define i2cdump_full_usage "\n\n"
+//usage: "Examine I2C registers\n"
+//usage: "\n I2CBUS i2c bus number"
+//usage: "\n ADDRESS 0x03 - 0x77"
+//usage: "\nMODE is:"
+//usage: "\n b byte (default)"
+//usage: "\n w word"
+//usage: "\n W word on even register addresses"
+//usage: "\n i I2C block"
+//usage: "\n s SMBus block"
+//usage: "\n c consecutive byte"
+//usage: "\n Append p for SMBus PEC"
+//usage: "\n"
+//usage: "\n -f force access"
+//usage: "\n -y disable interactive mode"
+//usage: "\n -r limit the number of registers being accessed"
+int i2cdump_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int i2cdump_main(int argc UNUSED_PARAM, char **argv)
+{
+ const unsigned opt_f = (1 << 0), opt_y = (1 << 1),
+ opt_r = (1 << 2);
+ const char *const optstr = "fyr:";
+
+ int bus_num, bus_addr, mode = I2C_SMBUS_BYTE_DATA, even = 0, pec = 0;
+ unsigned first = 0x00, last = 0xff, opts;
+ int *block = (int *)bb_common_bufsiz1;
+ char *opt_r_str, *dash;
+ int fd, res;
+
+ opt_complementary = "-2:?3"; /* from 2 to 3 args */
+ opts = getopt32(argv, optstr, &opt_r_str);
+ argv += optind;
+
+ bus_num = i2c_bus_lookup(argv[0]);
+ bus_addr = i2c_parse_bus_addr(argv[1]);
+
+ if (argv[2]) {
+ switch (argv[2][0]) {
+ case 'b': /* Already set. */ break;
+ case 'c': mode = I2C_SMBUS_BYTE; break;
+ case 'w': mode = I2C_SMBUS_WORD_DATA; break;
+ case 'W':
+ mode = I2C_SMBUS_WORD_DATA;
+ even = 1;
+ break;
+ case 's': mode = I2C_SMBUS_BLOCK_DATA; break;
+ case 'i': mode = I2C_SMBUS_I2C_BLOCK_DATA; break;
+ default:
+ bb_error_msg_and_die("invalid mode");
+ }
+
+ if (argv[2][1] == 'p') {
+ if (argv[2][0] == 'W' || argv[2][0] == 'i') {
+ bb_error_msg_and_die(
+ "pec not supported for -W and -i");
+ } else {
+ pec = 1;
+ }
+ }
+ }
+
+ if (opts & opt_r) {
+ first = strtol(opt_r_str, &dash, 0);
+ if (dash == opt_r_str || *dash != '-' || first > 0xff)
+ bb_error_msg_and_die("invalid range");
+ last = xstrtou_range(++dash, 0, first, 0xff);
+
+ /* Range is not available for every mode. */
+ switch (mode) {
+ case I2C_SMBUS_BYTE:
+ case I2C_SMBUS_BYTE_DATA:
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ if (!even || (!(first % 2) && last % 2))
+ break;
+ /* Fall through */
+ default:
+ bb_error_msg_and_die(
+ "range not compatible with selected mode");
+ }
+ }
+
+ fd = i2c_dev_open(bus_num);
+ check_read_funcs(fd, mode, -1 /* data_addr */, pec);
+ i2c_set_slave_addr(fd, bus_addr, opts & opt_f);
+
+ if (pec)
+ i2c_set_pec(fd, 1);
+
+ if (!(opts & opt_y))
+ confirm_action(bus_addr, mode, -1 /* data_addr */, pec);
+
+ /* All but word data. */
+ if (mode != I2C_SMBUS_WORD_DATA || even) {
+ int blen = 0;
+
+ if (mode == I2C_SMBUS_BLOCK_DATA || mode == I2C_SMBUS_I2C_BLOCK_DATA)
+ blen = read_block_data(fd, mode, block);
+
+ if (mode == I2C_SMBUS_BYTE) {
+ res = i2c_smbus_write_byte(fd, first);
+ if (res < 0)
+ bb_perror_msg_and_die("write start address");
+ }
+
+ dump_data(fd, mode, first, last, block, blen);
+ } else {
+ dump_word_data(fd, first, last);
+ }
+
+ return 0;
+}
+#endif /* ENABLE_I2CDUMP */
+
+#if ENABLE_I2CDETECT
+enum adapter_type {
+ ADT_DUMMY = 0,
+ ADT_ISA,
+ ADT_I2C,
+ ADT_SMBUS,
+};
+
+struct adap_desc {
+ const char *funcs;
+ const char *algo;
+};
+
+static const struct adap_desc adap_descs[] = {
+ { .funcs = "dummy",
+ .algo = "Dummy bus", },
+ { .funcs = "isa",
+ .algo = "ISA bus", },
+ { .funcs = "i2c",
+ .algo = "I2C adapter", },
+ { .funcs = "smbus",
+ .algo = "SMBus adapter", },
+};
+
+struct i2c_func
+{
+ long value;
+ const char* name;
+};
+
+static const struct i2c_func i2c_funcs_tab[] = {
+ { .value = I2C_FUNC_I2C,
+ .name = "I2C" },
+ { .value = I2C_FUNC_SMBUS_QUICK,
+ .name = "SMBus quick command" },
+ { .value = I2C_FUNC_SMBUS_WRITE_BYTE,
+ .name = "SMBus send byte" },
+ { .value = I2C_FUNC_SMBUS_READ_BYTE,
+ .name = "SMBus receive byte" },
+ { .value = I2C_FUNC_SMBUS_WRITE_BYTE_DATA,
+ .name = "SMBus write byte" },
+ { .value = I2C_FUNC_SMBUS_READ_BYTE_DATA,
+ .name = "SMBus read byte" },
+ { .value = I2C_FUNC_SMBUS_WRITE_WORD_DATA,
+ .name = "SMBus write word" },
+ { .value = I2C_FUNC_SMBUS_READ_WORD_DATA,
+ .name = "SMBus read word" },
+ { .value = I2C_FUNC_SMBUS_PROC_CALL,
+ .name = "SMBus process call" },
+ { .value = I2C_FUNC_SMBUS_WRITE_BLOCK_DATA,
+ .name = "SMBus block write" },
+ { .value = I2C_FUNC_SMBUS_READ_BLOCK_DATA,
+ .name = "SMBus block read" },
+ { .value = I2C_FUNC_SMBUS_BLOCK_PROC_CALL,
+ .name = "SMBus block process call" },
+ { .value = I2C_FUNC_SMBUS_PEC,
+ .name = "SMBus PEC" },
+ { .value = I2C_FUNC_SMBUS_WRITE_I2C_BLOCK,
+ .name = "I2C block write" },
+ { .value = I2C_FUNC_SMBUS_READ_I2C_BLOCK,
+ .name = "I2C block read" },
+ { .value = 0, .name = NULL }
+};
+
+static enum adapter_type i2cdetect_get_funcs(int bus)
+{
+ enum adapter_type ret;
+ unsigned long funcs;
+ int fd;
+
+ fd = i2c_dev_open(bus);
+
+ get_funcs_matrix(fd, &funcs);
+ if (funcs & I2C_FUNC_I2C)
+ ret = ADT_I2C;
+ else if (funcs & (I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_WORD_DATA))
+ ret = ADT_SMBUS;
+ else
+ ret = ADT_DUMMY;
+
+ close(fd);
+
+ return ret;
+}
+
+static void NORETURN list_i2c_busses_and_exit(void)
+{
+ const char *const i2cdev_path = "/sys/class/i2c-dev";
+
+ char path[NAME_MAX], name[128];
+ struct dirent *de, *subde;
+ enum adapter_type adt;
+ DIR *dir, *subdir;
+ int rv, bus;
+ char *pos;
+ FILE *fp;
+
+ /*
+ * XXX Upstream i2cdetect also looks for i2c bus info in /proc/bus/i2c,
+ * but we won't bother since it's only useful on older kernels (before
+ * 2.6.5). We expect sysfs to be present and mounted at /sys/.
+ */
+
+ dir = xopendir(i2cdev_path);
+ while ((de = readdir(dir))) {
+ if (de->d_name[0] == '.')
+ continue;
+
+ /* Simple version for ISA chips. */
+ snprintf(path, NAME_MAX, "%s/%s/name",
+ i2cdev_path, de->d_name);
+ fp = fopen(path, "r");
+ if (fp == NULL) {
+ snprintf(path, NAME_MAX,
+ "%s/%s/device/name",
+ i2cdev_path, de->d_name);
+ fp = fopen(path, "r");
+ }
+
+ /* Non-ISA chips require the hard-way. */
+ if (fp == NULL) {
+ snprintf(path, NAME_MAX,
+ "%s/%s/device/name",
+ i2cdev_path, de->d_name);
+ subdir = opendir(path);
+ if (subdir == NULL)
+ continue;
+
+ while ((subde = readdir(subdir))) {
+ if (subde->d_name[0] == '.')
+ continue;
+
+ if (is_prefixed_with(subde->d_name, "i2c-")) {
+ snprintf(path, NAME_MAX,
+ "%s/%s/device/%s/name",
+ i2cdev_path, de->d_name,
+ subde->d_name);
+ fp = fopen(path, "r");
+ break;
+ }
+ }
+ }
+
+ if (fp != NULL) {
+ /*
+ * Get the rest of the info and display a line
+ * for a single bus.
+ */
+ memset(name, 0, sizeof(name));
+ pos = fgets(name, sizeof(name), fp);
+ fclose(fp);
+ if (pos == NULL)
+ continue;
+
+ pos = strchr(name, '\n');
+ if (pos != NULL)
+ *pos = '\0';
+
+ rv = sscanf(de->d_name, "i2c-%d", &bus);
+ if (rv != 1)
+ continue;
+
+ if (is_prefixed_with(name, "ISA"))
+ adt = ADT_ISA;
+ else
+ adt = i2cdetect_get_funcs(bus);
+
+ printf(
+ "i2c-%d\t%-10s\t%-32s\t%s\n",
+ bus, adap_descs[adt].funcs,
+ name, adap_descs[adt].algo);
+ }
+ }
+
+ exit(EXIT_SUCCESS);
+}
+
+static void NORETURN no_support(const char *cmd)
+{
+ bb_error_msg_and_die("bus doesn't support %s", cmd);
+}
+
+static void will_skip(const char *cmd)
+{
+ bb_error_msg(
+ "warning: can't use %s command, "
+ "will skip some addresses", cmd);
+}
+
+//usage:#define i2cdetect_trivial_usage
+//usage: "[-F I2CBUS] [-l] [-y] [-a] [-q|-r] I2CBUS [FIRST LAST]"
+//usage:#define i2cdetect_full_usage "\n\n"
+//usage: "Detect I2C chips.\n"
+//usage: "\n I2CBUS i2c bus number"
+//usage: "\n FIRST and LAST limit the probing range"
+//usage: "\n"
+//usage: "\n -l output list of installed busses"
+//usage: "\n -y disable interactive mode"
+//usage: "\n -a force scanning of non-regular addresses"
+//usage: "\n -q use smbus quick write commands for probing (default)"
+//usage: "\n -r use smbus read byte commands for probing"
+//usage: "\n -F display list of functionalities"
+int i2cdetect_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int i2cdetect_main(int argc UNUSED_PARAM, char **argv)
+{
+ const unsigned opt_y = (1 << 0), opt_a = (1 << 1),
+ opt_q = (1 << 2), opt_r = (1 << 3),
+ opt_F = (1 << 4), opt_l = (1 << 5);
+ const char *const optstr = "yaqrFl";
+
+ int fd, bus_num, i, j, mode = I2CDETECT_MODE_AUTO, status, cmd;
+ unsigned first = 0x03, last = 0x77, opts;
+ unsigned long funcs;
+
+ opt_complementary = "q--r:r--q:" /* mutually exclusive */
+ "?3"; /* up to 3 args */
+ opts = getopt32(argv, optstr);
+ argv += optind;
+
+ if (opts & opt_l)
+ list_i2c_busses_and_exit();
+
+ if (!argv[0])
+ bb_show_usage();
+
+ bus_num = i2c_bus_lookup(argv[0]);
+ fd = i2c_dev_open(bus_num);
+ get_funcs_matrix(fd, &funcs);
+
+ if (opts & opt_F) {
+ /* Only list the functionalities. */
+ printf("Functionalities implemented by bus #%d\n", bus_num);
+ for (i = 0; i2c_funcs_tab[i].value; i++) {
+ printf("%-32s %s\n", i2c_funcs_tab[i].name,
+ funcs & i2c_funcs_tab[i].value ? "yes" : "no");
+ }
+
+ return EXIT_SUCCESS;
+ }
+
+ if (opts & opt_r)
+ mode = I2CDETECT_MODE_READ;
+ else if (opts & opt_q)
+ mode = I2CDETECT_MODE_QUICK;
+
+ if (opts & opt_a) {
+ first = 0x00;
+ last = 0x7f;
+ }
+
+ /* Read address range. */
+ if (argv[1]) {
+ first = xstrtou_range(argv[1], 16, first, last);
+ if (argv[2])
+ last = xstrtou_range(argv[2], 16, first, last);
+ }
+
+ if (!(funcs & (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_READ_BYTE))) {
+ no_support("detection commands");
+ } else
+ if (mode == I2CDETECT_MODE_QUICK && !(funcs & I2C_FUNC_SMBUS_QUICK)) {
+ no_support("SMBus quick write");
+ } else
+ if (mode == I2CDETECT_MODE_READ && !(funcs & I2C_FUNC_SMBUS_READ_BYTE)) {
+ no_support("SMBus receive byte");
+ }
+
+ if (mode == I2CDETECT_MODE_AUTO) {
+ if (!(funcs & I2C_FUNC_SMBUS_QUICK))
+ will_skip("SMBus quick write");
+ if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE))
+ will_skip("SMBus receive byte");
+ }
+
+ if (!(opts & opt_y))
+ confirm_action(-1, -1, -1, 0);
+
+ puts(" 0 1 2 3 4 5 6 7 8 9 a b c d e f");
+ for (i = 0; i < 128; i += 16) {
+ printf("%02x: ", i);
+ for (j = 0; j < 16; j++) {
+ fflush_all();
+
+ cmd = mode;
+ if (mode == I2CDETECT_MODE_AUTO) {
+ if ((i+j >= 0x30 && i+j <= 0x37) ||
+ (i+j >= 0x50 && i+j <= 0x5F))
+ cmd = I2CDETECT_MODE_READ;
+ else
+ cmd = I2CDETECT_MODE_QUICK;
+ }
+
+ /* Skip unwanted addresses. */
+ if (i+j < first
+ || i+j > last
+ || (cmd == I2CDETECT_MODE_READ && !(funcs & I2C_FUNC_SMBUS_READ_BYTE))
+ || (cmd == I2CDETECT_MODE_QUICK && !(funcs & I2C_FUNC_SMBUS_QUICK)))
+ {
+ printf(" ");
+ continue;
+ }
+
+ status = ioctl(fd, I2C_SLAVE, itoptr(i + j));
+ if (status < 0) {
+ if (errno == EBUSY) {
+ printf("UU ");
+ continue;
+ }
+
+ bb_perror_msg_and_die(
+ "can't set address to 0x%02x", i + j);
+ }
+
+ switch (cmd) {
+ case I2CDETECT_MODE_READ:
+ /*
+ * This is known to lock SMBus on various
+ * write-only chips (mainly clock chips).
+ */
+ status = i2c_smbus_read_byte(fd);
+ break;
+ default: /* I2CDETECT_MODE_QUICK: */
+ /*
+ * This is known to corrupt the Atmel
+ * AT24RF08 EEPROM.
+ */
+ status = i2c_smbus_write_quick(fd,
+ I2C_SMBUS_WRITE);
+ break;
+ }
+
+ if (status < 0)
+ printf("-- ");
+ else
+ printf("%02x ", i+j);
+ }
+ bb_putchar('\n');
+ }
+
+ return 0;
+}
+#endif /* ENABLE_I2CDETECT */
diff --git a/release/src/router/busybox/miscutils/inotifyd.c b/release/src/router/busybox/miscutils/inotifyd.c
index 7a1a6a2e53..52db08adac 100644
--- a/release/src/router/busybox/miscutils/inotifyd.c
+++ b/release/src/router/busybox/miscutils/inotifyd.c
@@ -47,8 +47,8 @@
//usage: "\n o Event queue overflowed"
//usage: "\n x File can't be watched anymore"
//usage: "\nIf watching a directory:"
-//usage: "\n m Subfile is moved into dir"
-//usage: "\n y Subfile is moved out of dir"
+//usage: "\n y Subfile is moved into dir"
+//usage: "\n m Subfile is moved out of dir"
//usage: "\n n Subfile is created"
//usage: "\n d Subfile is deleted"
//usage: "\n"
@@ -56,6 +56,7 @@
//usage: "\nWhen x event happens for all FILEs, inotifyd exits."
#include "libbb.h"
+#include "common_bufsiz.h"
#include <sys/inotify.h>
static const char mask_names[] ALIGN1 =
@@ -161,9 +162,10 @@ int inotifyd_main(int argc, char **argv)
// read out all pending events
// (NB: len must be int, not ssize_t or long!)
- xioctl(pfd.fd, FIONREAD, &len);
#define eventbuf bb_common_bufsiz1
- ie = buf = (len <= sizeof(eventbuf)) ? eventbuf : xmalloc(len);
+ setup_common_bufsiz();
+ xioctl(pfd.fd, FIONREAD, &len);
+ ie = buf = (len <= COMMON_BUFSIZE) ? eventbuf : xmalloc(len);
len = full_read(pfd.fd, buf, len);
// process events. N.B. events may vary in length
while (len > 0) {
diff --git a/release/src/router/busybox/miscutils/ionice.c b/release/src/router/busybox/miscutils/ionice.c
index bd300605fd..0c14256ab9 100644
--- a/release/src/router/busybox/miscutils/ionice.c
+++ b/release/src/router/busybox/miscutils/ionice.c
@@ -41,7 +41,7 @@ enum {
IOPRIO_CLASS_IDLE
};
-static const char to_prio[] = "none\0realtime\0best-effort\0idle";
+static const char to_prio[] ALIGN1 = "none\0realtime\0best-effort\0idle";
#define IOPRIO_CLASS_SHIFT 13
diff --git a/release/src/router/busybox/miscutils/last.c b/release/src/router/busybox/miscutils/last.c
index d527803743..f8f34371ac 100644
--- a/release/src/router/busybox/miscutils/last.c
+++ b/release/src/router/busybox/miscutils/last.c
@@ -32,21 +32,22 @@
#if defined UT_LINESIZE \
&& ((UT_LINESIZE != 32) || (UT_NAMESIZE != 32) || (UT_HOSTSIZE != 256))
-#error struct utmp member char[] size(s) have changed!
+#error struct utmpx member char[] size(s) have changed!
#elif defined __UT_LINESIZE \
- && ((__UT_LINESIZE != 32) || (__UT_NAMESIZE != 64) || (__UT_HOSTSIZE != 256))
-#error struct utmp member char[] size(s) have changed!
+ && ((__UT_LINESIZE != 32) || (__UT_NAMESIZE != 32) || (__UT_HOSTSIZE != 256))
+/* __UT_NAMESIZE was checked with 64 above, but glibc-2.11 definitely uses 32! */
+#error struct utmpx member char[] size(s) have changed!
#endif
#if EMPTY != 0 || RUN_LVL != 1 || BOOT_TIME != 2 || NEW_TIME != 3 || \
OLD_TIME != 4
-#error Values for the ut_type field of struct utmp changed
+#error Values for the ut_type field of struct utmpx changed
#endif
int last_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int last_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
{
- struct utmp ut;
+ struct utmpx ut;
int n, file = STDIN_FILENO;
time_t t_tmp;
off_t pos;
@@ -71,7 +72,7 @@ int last_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
file = xopen(bb_path_wtmp_file, O_RDONLY);
printf("%-10s %-14s %-18s %-12.12s %s\n",
- "USER", "TTY", "HOST", "LOGIN", "TIME");
+ "USER", "TTY", "HOST", "LOGIN", "TIME");
/* yikes. We reverse over the file and that is a not too elegant way */
pos = xlseek(file, 0, SEEK_END);
pos = lseek(file, pos - sizeof(ut), SEEK_SET);
@@ -87,11 +88,11 @@ int last_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
if (++n > 0)
ut.ut_type = n != 3 ? n : SHUTDOWN_TIME;
#else
- if (strncmp(ut.ut_user, "shutdown", 8) == 0)
+ if (is_prefixed_with(ut.ut_user, "shutdown"))
ut.ut_type = SHUTDOWN_TIME;
- else if (strncmp(ut.ut_user, "reboot", 6) == 0)
+ else if (is_prefixed_with(ut.ut_user, "reboot"))
ut.ut_type = BOOT_TIME;
- else if (strncmp(ut.ut_user, "runlevel", 8) == 0)
+ else if (is_prefixed_with(ut.ut_user, "runlevel"))
ut.ut_type = RUN_LVL;
#endif
} else {
@@ -131,7 +132,7 @@ int last_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
* but some systems have it wrong */
t_tmp = (time_t)ut.ut_tv.tv_sec;
printf("%-10s %-14s %-18s %-12.12s\n",
- ut.ut_user, ut.ut_line, ut.ut_host, ctime(&t_tmp) + 4);
+ ut.ut_user, ut.ut_line, ut.ut_host, ctime(&t_tmp) + 4);
next:
pos -= sizeof(ut);
if (pos <= 0)
diff --git a/release/src/router/busybox/miscutils/last_fancy.c b/release/src/router/busybox/miscutils/last_fancy.c
index dc09b65fb6..e56e0ba859 100644
--- a/release/src/router/busybox/miscutils/last_fancy.c
+++ b/release/src/router/busybox/miscutils/last_fancy.c
@@ -22,6 +22,10 @@
#define HEADER_LINE_WIDE "USER", "TTY", \
INET6_ADDRSTRLEN, INET6_ADDRSTRLEN, "HOST", "LOGIN", " TIME", ""
+#if !defined __UT_LINESIZE && defined UT_LINESIZE
+# define __UT_LINESIZE UT_LINESIZE
+#endif
+
enum {
NORMAL,
LOGGED,
@@ -39,10 +43,10 @@ enum {
#define show_wide (option_mask32 & LAST_OPT_W)
-static void show_entry(struct utmp *ut, int state, time_t dur_secs)
+static void show_entry(struct utmpx *ut, int state, time_t dur_secs)
{
unsigned days, hours, mins;
- char duration[32];
+ char duration[sizeof("(%u+02:02)") + sizeof(int)*3];
char login_time[17];
char logout_time[8];
const char *logout_str;
@@ -53,7 +57,8 @@ static void show_entry(struct utmp *ut, int state, time_t dur_secs)
* but some systems have it wrong */
tmp = ut->ut_tv.tv_sec;
safe_strncpy(login_time, ctime(&tmp), 17);
- snprintf(logout_time, 8, "- %s", ctime(&dur_secs) + 11);
+ tmp = dur_secs;
+ snprintf(logout_time, 8, "- %s", ctime(&tmp) + 11);
dur_secs = MAX(dur_secs - (time_t)ut->ut_tv.tv_sec, (time_t)0);
/* unsigned int is easier to divide than time_t (which may be signed long) */
@@ -93,17 +98,17 @@ static void show_entry(struct utmp *ut, int state, time_t dur_secs)
}
printf(HEADER_FORMAT,
- ut->ut_user,
- ut->ut_line,
- show_wide ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN,
- show_wide ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN,
- ut->ut_host,
- login_time,
- logout_str,
- duration_str);
+ ut->ut_user,
+ ut->ut_line,
+ show_wide ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN,
+ show_wide ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN,
+ ut->ut_host,
+ login_time,
+ logout_str,
+ duration_str);
}
-static int get_ut_type(struct utmp *ut)
+static int get_ut_type(struct utmpx *ut)
{
if (ut->ut_line[0] == '~') {
if (strcmp(ut->ut_user, "shutdown") == 0) {
@@ -141,7 +146,7 @@ static int get_ut_type(struct utmp *ut)
return ut->ut_type;
}
-static int is_runlevel_shutdown(struct utmp *ut)
+static int is_runlevel_shutdown(struct utmpx *ut)
{
if (((ut->ut_pid & 255) == '0') || ((ut->ut_pid & 255) == '6')) {
return 1;
@@ -153,7 +158,7 @@ static int is_runlevel_shutdown(struct utmp *ut)
int last_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int last_main(int argc UNUSED_PARAM, char **argv)
{
- struct utmp ut;
+ struct utmpx ut;
const char *filename = _PATH_WTMP;
llist_t *zlist;
off_t pos;
@@ -228,7 +233,7 @@ int last_main(int argc UNUSED_PARAM, char **argv)
break;
}
/* add_entry */
- llist_add_to(&zlist, memcpy(xmalloc(sizeof(ut)), &ut, sizeof(ut)));
+ llist_add_to(&zlist, xmemdup(&ut, sizeof(ut)));
break;
case USER_PROCESS: {
int show;
@@ -241,9 +246,9 @@ int last_main(int argc UNUSED_PARAM, char **argv)
{
llist_t *el, *next;
for (el = zlist; el; el = next) {
- struct utmp *up = (struct utmp *)el->data;
+ struct utmpx *up = (struct utmpx *)el->data;
next = el->link;
- if (strncmp(up->ut_line, ut.ut_line, UT_LINESIZE) == 0) {
+ if (strncmp(up->ut_line, ut.ut_line, __UT_LINESIZE) == 0) {
if (show) {
show_entry(&ut, NORMAL, up->ut_tv.tv_sec);
show = 0;
@@ -270,7 +275,7 @@ int last_main(int argc UNUSED_PARAM, char **argv)
show_entry(&ut, state, boot_time);
}
/* add_entry */
- llist_add_to(&zlist, memcpy(xmalloc(sizeof(ut)), &ut, sizeof(ut)));
+ llist_add_to(&zlist, xmemdup(&ut, sizeof(ut)));
break;
}
}
diff --git a/release/src/router/busybox/miscutils/less.c b/release/src/router/busybox/miscutils/less.c
index f0187bf8ae..d7076dbbc7 100644
--- a/release/src/router/busybox/miscutils/less.c
+++ b/release/src/router/busybox/miscutils/less.c
@@ -48,6 +48,14 @@
//config: help
//config: The -M/-m flag enables a more sophisticated status line.
//config:
+//config:config FEATURE_LESS_TRUNCATE
+//config: bool "Enable -S"
+//config: default y
+//config: depends on LESS
+//config: help
+//config: The -S flag causes long lines to be truncated rather than
+//config: wrapped.
+//config:
//config:config FEATURE_LESS_MARKS
//config: bool "Enable marks"
//config: default y
@@ -98,21 +106,28 @@
//config: Enables "-N" command.
//usage:#define less_trivial_usage
-//usage: "[-E" IF_FEATURE_LESS_FLAGS("Mm") "Nh~I?] [FILE]..."
+//usage: "[-E" IF_FEATURE_LESS_REGEXP("I")IF_FEATURE_LESS_FLAGS("Mm")
+//usage: "N" IF_FEATURE_LESS_TRUNCATE("S") "h~] [FILE]..."
//usage:#define less_full_usage "\n\n"
//usage: "View FILE (or stdin) one screenful at a time\n"
//usage: "\n -E Quit once the end of a file is reached"
+//usage: IF_FEATURE_LESS_REGEXP(
+//usage: "\n -I Ignore case in all searches"
+//usage: )
//usage: IF_FEATURE_LESS_FLAGS(
//usage: "\n -M,-m Display status line with line numbers"
//usage: "\n and percentage through the file"
//usage: )
//usage: "\n -N Prefix line number to each line"
-//usage: "\n -I Ignore case in all searches"
+//usage: IF_FEATURE_LESS_TRUNCATE(
+//usage: "\n -S Truncate long lines"
+//usage: )
//usage: "\n -~ Suppress ~s displayed past EOF"
#include <sched.h> /* sched_yield() */
#include "libbb.h"
+#include "common_bufsiz.h"
#if ENABLE_FEATURE_LESS_REGEXP
#include "xregex.h"
#endif
@@ -142,7 +157,7 @@ enum {
FLAG_N = 1 << 3,
FLAG_TILDE = 1 << 4,
FLAG_I = 1 << 5,
- FLAG_S = (1 << 6) * ENABLE_FEATURE_LESS_DASHCMD,
+ FLAG_S = (1 << 6) * ENABLE_FEATURE_LESS_TRUNCATE,
/* hijack command line options variable for internal state vars */
LESS_STATE_MATCH_BACKWARDS = 1 << 15,
};
@@ -174,6 +189,12 @@ struct globals {
unsigned current_file;
char *filename;
char **files;
+#if ENABLE_FEATURE_LESS_FLAGS
+ int num_lines; /* a flag if < 0, line count if >= 0 */
+# define REOPEN_AND_COUNT (-1)
+# define REOPEN_STDIN (-2)
+# define NOT_REGULAR_FILE (-3)
+#endif
#if ENABLE_FEATURE_LESS_MARKS
unsigned num_marks;
unsigned mark_lines[15][2];
@@ -215,6 +236,7 @@ struct globals {
#define current_file (G.current_file )
#define filename (G.filename )
#define files (G.files )
+#define num_lines (G.num_lines )
#define num_marks (G.num_marks )
#define mark_lines (G.mark_lines )
#if ENABLE_FEATURE_LESS_REGEXP
@@ -317,8 +339,10 @@ static void re_wrap(void)
*d = *s;
if (*d != '\0') {
new_line_pos++;
- if (*d == '\t') /* tab */
+ if (*d == '\t') { /* tab */
new_line_pos += 7;
+ new_line_pos &= (~7);
+ }
s++;
d++;
if (new_line_pos >= w) {
@@ -380,6 +404,14 @@ static void fill_match_lines(unsigned pos);
#define fill_match_lines(pos) ((void)0)
#endif
+static int at_end(void)
+{
+ return (option_mask32 & FLAG_S)
+ ? !(cur_fline <= max_fline &&
+ max_lineno > LINENO(flines[cur_fline]) + max_displayed_line)
+ : !(max_fline > cur_fline + max_displayed_line);
+}
+
/* Devilishly complex routine.
*
* Has to deal with EOF and EPIPE on input,
@@ -402,33 +434,39 @@ static void fill_match_lines(unsigned pos);
* last_line_pos - screen line position of next char to be read
* (takes into account tabs and backspaces)
* eof_error - < 0 error, == 0 EOF, > 0 not EOF/error
+ *
+ * "git log -p | less -m" on the kernel git tree is a good test for EAGAINs,
+ * "/search on very long input" and "reaching max line count" corner cases.
*/
static void read_lines(void)
{
-#define readbuf bb_common_bufsiz1
char *current_line, *p;
int w = width;
char last_terminated = terminated;
+ time_t last_time = 0;
+ int retry_EAGAIN = 2;
#if ENABLE_FEATURE_LESS_REGEXP
unsigned old_max_fline = max_fline;
- time_t last_time = 0;
- unsigned seconds_p1 = 3; /* seconds_to_loop + 1 */
#endif
+#define readbuf bb_common_bufsiz1
+ setup_common_bufsiz();
+
+ /* (careful: max_fline can be -1) */
+ if (max_fline + 1 > MAXLINES)
+ return;
+
if (option_mask32 & FLAG_N)
w -= 8;
- IF_FEATURE_LESS_REGEXP(again0:)
-
- p = current_line = ((char*)xmalloc(w + 4)) + 4;
- max_fline += last_terminated;
+ p = current_line = ((char*)xmalloc(w + 5)) + 4;
if (!last_terminated) {
const char *cp = flines[max_fline];
- strcpy(p, cp);
- p += strlen(current_line);
- free(MEMPTR(flines[max_fline]));
+ p = stpcpy(p, cp);
+ free(MEMPTR(cp));
/* last_line_pos is still valid from previous read_lines() */
} else {
+ max_fline++;
last_line_pos = 0;
}
@@ -439,13 +477,29 @@ static void read_lines(void)
char c;
/* if no unprocessed chars left, eat more */
if (readpos >= readeof) {
- ndelay_on(0);
- eof_error = safe_read(STDIN_FILENO, readbuf, sizeof(readbuf));
- ndelay_off(0);
+ int flags = ndelay_on(0);
+
+ while (1) {
+ time_t t;
+
+ errno = 0;
+ eof_error = safe_read(STDIN_FILENO, readbuf, COMMON_BUFSIZE);
+ if (errno != EAGAIN)
+ break;
+ t = time(NULL);
+ if (t != last_time) {
+ last_time = t;
+ if (--retry_EAGAIN < 0)
+ break;
+ }
+ sched_yield();
+ }
+ fcntl(0, F_SETFL, flags); /* ndelay_off(0) */
readpos = 0;
readeof = eof_error;
if (eof_error <= 0)
goto reached_eof;
+ retry_EAGAIN = 1;
}
c = readbuf[readpos];
/* backspace? [needed for manpages] */
@@ -464,7 +518,7 @@ static void read_lines(void)
new_last_line_pos += 7;
new_last_line_pos &= (~7);
}
- if ((int)new_last_line_pos >= w)
+ if ((int)new_last_line_pos > w)
break;
last_line_pos = new_last_line_pos;
}
@@ -480,6 +534,11 @@ static void read_lines(void)
*p++ = c;
*p = '\0';
} /* end of "read chars until we have a line" loop */
+#if 0
+//BUG: also triggers on this:
+// { printf "\nfoo\n"; sleep 1; printf "\nbar\n"; } | less
+// (resulting in lost empty line between "foo" and "bar" lines)
+// the "terminated" logic needs fixing (or explaining)
/* Corner case: linewrap with only "" wrapping to next line */
/* Looks ugly on screen, so we do not store this empty line */
if (!last_terminated && !current_line[0]) {
@@ -487,6 +546,7 @@ static void read_lines(void)
max_lineno++;
continue;
}
+#endif
reached_eof:
last_terminated = terminated;
flines = xrealloc_vector(flines, 8, max_fline);
@@ -500,11 +560,7 @@ static void read_lines(void)
eof_error = 0; /* Pretend we saw EOF */
break;
}
- if (!(option_mask32 & FLAG_S)
- ? (max_fline > cur_fline + max_displayed_line)
- : (max_fline >= cur_fline
- && max_lineno > LINENO(flines[cur_fline]) + max_displayed_line)
- ) {
+ if (!at_end()) {
#if !ENABLE_FEATURE_LESS_REGEXP
break;
#else
@@ -517,38 +573,26 @@ static void read_lines(void)
#endif
}
if (eof_error <= 0) {
- if (eof_error < 0) {
- if (errno == EAGAIN) {
- /* not yet eof or error, reset flag (or else
- * we will hog CPU - select() will return
- * immediately */
- eof_error = 1;
- } else {
- print_statusline(bb_msg_read_error);
- }
- }
-#if !ENABLE_FEATURE_LESS_REGEXP
break;
-#else
- if (wanted_match < num_matches) {
- break;
- } else { /* goto_match called us */
- time_t t = time(NULL);
- if (t != last_time) {
- last_time = t;
- if (--seconds_p1 == 0)
- break;
- }
- sched_yield();
- goto again0; /* go loop again (max 2 seconds) */
- }
-#endif
}
max_fline++;
- current_line = ((char*)xmalloc(w + 4)) + 4;
+ current_line = ((char*)xmalloc(w + 5)) + 4;
p = current_line;
last_line_pos = 0;
} /* end of "read lines until we reach cur_fline" loop */
+
+ if (eof_error < 0) {
+ if (errno == EAGAIN) {
+ eof_error = 1;
+ } else {
+ print_statusline(bb_msg_read_error);
+ }
+ }
+#if ENABLE_FEATURE_LESS_FLAGS
+ else if (eof_error == 0)
+ num_lines = max_lineno;
+#endif
+
fill_match_lines(old_max_fline);
#if ENABLE_FEATURE_LESS_REGEXP
/* prevent us from being stuck in search for a match */
@@ -558,18 +602,61 @@ static void read_lines(void)
}
#if ENABLE_FEATURE_LESS_FLAGS
-/* Interestingly, writing calc_percent as a function saves around 32 bytes
- * on my build. */
-static int calc_percent(void)
+static int safe_lineno(int fline)
+{
+ if (fline >= max_fline)
+ fline = max_fline - 1;
+
+ /* also catches empty file (max_fline == 0) */
+ if (fline < 0)
+ return 0;
+
+ return LINENO(flines[fline]) + 1;
+}
+
+/* count number of lines in file */
+static void update_num_lines(void)
{
- unsigned p = (100 * (cur_fline+max_displayed_line+1) + max_fline/2) / (max_fline+1);
- return p <= 100 ? p : 100;
+ int count, fd;
+ struct stat stbuf;
+ ssize_t len, i;
+ char buf[4096];
+
+ /* only do this for regular files */
+ if (num_lines == REOPEN_AND_COUNT || num_lines == REOPEN_STDIN) {
+ count = 0;
+ fd = open("/proc/self/fd/0", O_RDONLY);
+ if (fd < 0 && num_lines == REOPEN_AND_COUNT) {
+ /* "filename" is valid only if REOPEN_AND_COUNT */
+ fd = open(filename, O_RDONLY);
+ }
+ if (fd < 0) {
+ /* somebody stole my file! */
+ num_lines = NOT_REGULAR_FILE;
+ return;
+ }
+ if (fstat(fd, &stbuf) != 0 || !S_ISREG(stbuf.st_mode)) {
+ num_lines = NOT_REGULAR_FILE;
+ goto do_close;
+ }
+ while ((len = safe_read(fd, buf, sizeof(buf))) > 0) {
+ for (i = 0; i < len; ++i) {
+ if (buf[i] == '\n' && ++count == MAXLINES)
+ goto done;
+ }
+ }
+ done:
+ num_lines = count;
+ do_close:
+ close(fd);
+ }
}
/* Print a status line if -M was specified */
static void m_status_print(void)
{
- int percentage;
+ int first, last;
+ unsigned percent;
if (less_gets_pos >= 0) /* don't touch statusline while input is done! */
return;
@@ -578,17 +665,26 @@ static void m_status_print(void)
printf(HIGHLIGHT"%s", filename);
if (num_files > 1)
printf(" (file %i of %i)", current_file, num_files);
- printf(" lines %i-%i/%i ",
- cur_fline + 1, cur_fline + max_displayed_line + 1,
- max_fline + 1);
- if (cur_fline >= (int)(max_fline - max_displayed_line)) {
- printf("(END)"NORMAL);
+
+ first = safe_lineno(cur_fline);
+ last = (option_mask32 & FLAG_S)
+ ? MIN(first + max_displayed_line, max_lineno)
+ : safe_lineno(cur_fline + max_displayed_line);
+ printf(" lines %i-%i", first, last);
+
+ update_num_lines();
+ if (num_lines >= 0)
+ printf("/%i", num_lines);
+
+ if (at_end()) {
+ printf(" (END)");
if (num_files > 1 && current_file != num_files)
- printf(HIGHLIGHT" - next: %s"NORMAL, files[current_file]);
- return;
+ printf(" - next: %s", files[current_file]);
+ } else if (num_lines > 0) {
+ percent = (100 * last + num_lines/2) / num_lines;
+ printf(" %i%%", percent <= 100 ? percent : 100);
}
- percentage = calc_percent();
- printf("%i%%"NORMAL, percentage);
+ printf(NORMAL);
}
#endif
@@ -610,7 +706,7 @@ static void status_print(void)
#endif
clear_line();
- if (cur_fline && cur_fline < (int)(max_fline - max_displayed_line)) {
+ if (cur_fline && !at_end()) {
bb_putchar(':');
return;
}
@@ -625,23 +721,6 @@ static void status_print(void)
print_hilite(p);
}
-static void cap_cur_fline(int nlines)
-{
- int diff;
- if (cur_fline < 0)
- cur_fline = 0;
- if (cur_fline + max_displayed_line > max_fline + TILDES) {
- cur_fline -= nlines;
- if (cur_fline < 0)
- cur_fline = 0;
- diff = max_fline - (cur_fline + max_displayed_line) + TILDES;
- /* As the number of lines requested was too large, we just move
- * to the end of the file */
- if (diff > 0)
- cur_fline += diff;
- }
-}
-
static const char controls[] ALIGN1 =
/* NUL: never encountered; TAB: not converted */
/**/"\x01\x02\x03\x04\x05\x06\x07\x08" "\x0a\x0b\x0c\x0d\x0e\x0f"
@@ -653,27 +732,21 @@ static const char ctrlconv[] ALIGN1 =
"\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x40\x4b\x4c\x4d\x4e\x4f"
"\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f";
-static void lineno_str(char *nbuf9, const char *line)
+static void print_lineno(const char *line)
{
- nbuf9[0] = '\0';
- if (option_mask32 & FLAG_N) {
- const char *fmt;
- unsigned n;
-
- if (line == empty_line_marker) {
- memset(nbuf9, ' ', 8);
- nbuf9[8] = '\0';
- return;
- }
+ const char *fmt = " ";
+ unsigned n = n; /* for compiler */
+
+ if (line != empty_line_marker) {
/* Width of 7 preserves tab spacing in the text */
fmt = "%7u ";
n = LINENO(line) + 1;
- if (n > 9999999) {
+ if (n > 9999999 && MAXLINES > 9999999) {
n %= 10000000;
fmt = "%07u ";
}
- sprintf(nbuf9, fmt, n);
}
+ printf(fmt, n);
}
@@ -685,8 +758,7 @@ static void print_found(const char *line)
char *growline;
regmatch_t match_structs;
- char buf[width];
- char nbuf9[9];
+ char buf[width+1];
const char *str = line;
char *p = buf;
size_t n;
@@ -709,9 +781,9 @@ static void print_found(const char *line)
/* buf[] holds quarantined version of str */
/* Each part of the line that matches has the HIGHLIGHT
- and NORMAL escape sequences placed around it.
- NB: we regex against line, but insert text
- from quarantined copy (buf[]) */
+ * and NORMAL escape sequences placed around it.
+ * NB: we regex against line, but insert text
+ * from quarantined copy (buf[]) */
str = buf;
growline = NULL;
eflags = 0;
@@ -736,12 +808,7 @@ static void print_found(const char *line)
match_status = 1;
}
- lineno_str(nbuf9, line);
- if (!growline) {
- printf(CLEAR_2_EOL"%s%s\n", nbuf9, str);
- return;
- }
- printf(CLEAR_2_EOL"%s%s%s\n", nbuf9, growline, str);
+ printf("%s%s\n", growline ? growline : "", str);
free(growline);
}
#else
@@ -750,14 +817,10 @@ void print_found(const char *line);
static void print_ascii(const char *str)
{
- char buf[width];
- char nbuf9[9];
+ char buf[width+1];
char *p;
size_t n;
- lineno_str(nbuf9, str);
- printf(CLEAR_2_EOL"%s", nbuf9);
-
while (*str) {
n = strcspn(str, controls);
if (n) {
@@ -790,18 +853,28 @@ static void buffer_print(void)
unsigned i;
move_cursor(0, 0);
- for (i = 0; i <= max_displayed_line; i++)
+ for (i = 0; i <= max_displayed_line; i++) {
+ printf(CLEAR_2_EOL);
+ if (option_mask32 & FLAG_N)
+ print_lineno(buffer[i]);
if (pattern_valid)
print_found(buffer[i]);
else
print_ascii(buffer[i]);
+ }
+ if ((option_mask32 & FLAG_E)
+ && eof_error <= 0
+ && (max_fline - cur_fline) <= max_displayed_line
+ ) {
+ less_exit(EXIT_SUCCESS);
+ }
status_print();
}
static void buffer_fill_and_print(void)
{
unsigned i;
-#if ENABLE_FEATURE_LESS_DASHCMD
+#if ENABLE_FEATURE_LESS_TRUNCATE
int fpos = cur_fline;
if (option_mask32 & FLAG_S) {
@@ -833,45 +906,112 @@ static void buffer_fill_and_print(void)
buffer_print();
}
+/* move cur_fline to a given line number, reading lines if necessary */
+static void goto_lineno(int target)
+{
+ if (target <= 0 ) {
+ cur_fline = 0;
+ }
+ else if (target > LINENO(flines[cur_fline])) {
+ retry:
+ while (LINENO(flines[cur_fline]) != target && cur_fline < max_fline)
+ ++cur_fline;
+ /* target not reached but more input is available */
+ if (LINENO(flines[cur_fline]) != target && eof_error > 0) {
+ read_lines();
+ goto retry;
+ }
+ }
+ else {
+ /* search backwards through already-read lines */
+ while (LINENO(flines[cur_fline]) != target && cur_fline > 0)
+ --cur_fline;
+ }
+}
+
+static void cap_cur_fline(void)
+{
+ if ((option_mask32 & FLAG_S)) {
+ if (cur_fline > max_fline)
+ cur_fline = max_fline;
+ if (LINENO(flines[cur_fline]) + max_displayed_line > max_lineno + TILDES) {
+ goto_lineno(max_lineno - max_displayed_line + TILDES);
+ read_lines();
+ }
+ }
+ else {
+ if (cur_fline + max_displayed_line > max_fline + TILDES)
+ cur_fline = max_fline - max_displayed_line + TILDES;
+ if (cur_fline < 0)
+ cur_fline = 0;
+ }
+}
+
/* Move the buffer up and down in the file in order to scroll */
static void buffer_down(int nlines)
{
- cur_fline += nlines;
+ if ((option_mask32 & FLAG_S))
+ goto_lineno(LINENO(flines[cur_fline]) + nlines);
+ else
+ cur_fline += nlines;
read_lines();
- cap_cur_fline(nlines);
+ cap_cur_fline();
buffer_fill_and_print();
}
static void buffer_up(int nlines)
{
- cur_fline -= nlines;
- if (cur_fline < 0) cur_fline = 0;
+ if ((option_mask32 & FLAG_S)) {
+ goto_lineno(LINENO(flines[cur_fline]) - nlines);
+ }
+ else {
+ cur_fline -= nlines;
+ if (cur_fline < 0)
+ cur_fline = 0;
+ }
read_lines();
buffer_fill_and_print();
}
-static void buffer_line(int linenum)
+/* display a given line where the argument can be either an index into
+ * the flines array or a line number */
+static void buffer_to_line(int linenum, int is_lineno)
{
- if (linenum < 0)
- linenum = 0;
- cur_fline = linenum;
+ if (linenum <= 0)
+ cur_fline = 0;
+ else if (is_lineno)
+ goto_lineno(linenum);
+ else
+ cur_fline = linenum;
read_lines();
- if (linenum + max_displayed_line > max_fline)
- linenum = max_fline - max_displayed_line + TILDES;
- if (linenum < 0)
- linenum = 0;
- cur_fline = linenum;
+ cap_cur_fline();
buffer_fill_and_print();
}
+static void buffer_line(int linenum)
+{
+ buffer_to_line(linenum, FALSE);
+}
+
+static void buffer_lineno(int lineno)
+{
+ buffer_to_line(lineno, TRUE);
+}
+
static void open_file_and_read_lines(void)
{
if (filename) {
xmove_fd(xopen(filename, O_RDONLY), STDIN_FILENO);
+#if ENABLE_FEATURE_LESS_FLAGS
+ num_lines = REOPEN_AND_COUNT;
+#endif
} else {
/* "less" with no arguments in argv[] */
/* For status line only */
filename = xstrdup(bb_msg_standard_input);
+#if ENABLE_FEATURE_LESS_FLAGS
+ num_lines = REOPEN_STDIN;
+#endif
}
readpos = 0;
readeof = 0;
@@ -923,12 +1063,7 @@ static int64_t getch_nowait(void)
*/
rd = 1;
/* Are we interested in stdin? */
-//TODO: reuse code for determining this
- if (!(option_mask32 & FLAG_S)
- ? !(max_fline > cur_fline + max_displayed_line)
- : !(max_fline >= cur_fline
- && max_lineno > LINENO(flines[cur_fline]) + max_displayed_line)
- ) {
+ if (at_end()) {
if (eof_error > 0) /* did NOT reach eof yet */
rd = 0; /* yes, we are interested in stdin */
}
@@ -1239,7 +1374,7 @@ static void number_process(int first_digit)
i = 1;
while (i < sizeof(num_input)-1) {
keypress = less_getch(i + 1);
- if ((unsigned)keypress > 255 || !isdigit(num_input[i]))
+ if ((unsigned)keypress > 255 || !isdigit(keypress))
break;
num_input[i] = keypress;
bb_putchar(keypress);
@@ -1263,15 +1398,16 @@ static void number_process(int first_digit)
buffer_up(num);
break;
case 'g': case '<': case 'G': case '>':
- cur_fline = num + max_displayed_line;
- read_lines();
- buffer_line(num - 1);
+ buffer_lineno(num - 1);
break;
case 'p': case '%':
- num = num * (max_fline / 100); /* + max_fline / 2; */
- cur_fline = num + max_displayed_line;
- read_lines();
- buffer_line(num);
+#if ENABLE_FEATURE_LESS_FLAGS
+ update_num_lines();
+ num = num * (num_lines > 0 ? num_lines : max_lineno) / 100;
+#else
+ num = num * max_lineno / 100;
+#endif
+ buffer_lineno(num);
break;
#if ENABLE_FEATURE_LESS_REGEXP
case 'n':
@@ -1311,10 +1447,12 @@ static void flag_change(void)
case '~':
option_mask32 ^= FLAG_TILDE;
break;
+#if ENABLE_FEATURE_LESS_TRUNCATE
case 'S':
option_mask32 ^= FLAG_S;
buffer_fill_and_print();
break;
+#endif
#if ENABLE_FEATURE_LESS_LINENUMS
case 'N':
option_mask32 ^= FLAG_N;
@@ -1608,12 +1746,18 @@ static void sigwinch_handler(int sig UNUSED_PARAM)
int less_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int less_main(int argc, char **argv)
{
+ char *tty_name;
+ int tty_fd;
+
INIT_G();
- /* TODO: -x: do not interpret backspace, -xx: tab also */
- /* -xxx: newline also */
- /* -w N: assume width N (-xxx -w 32: hex viewer of sorts) */
- getopt32(argv, "EMmN~I" IF_FEATURE_LESS_DASHCMD("S"));
+ /* TODO: -x: do not interpret backspace, -xx: tab also
+ * -xxx: newline also
+ * -w N: assume width N (-xxx -w 32: hex viewer of sorts)
+ * -s: condense many empty lines to one
+ * (used by some setups for manpage display)
+ */
+ getopt32(argv, "EMmN~I" IF_FEATURE_LESS_TRUNCATE("S") /*ignored:*/"s");
argc -= optind;
argv += optind;
num_files = argc;
@@ -1637,10 +1781,28 @@ int less_main(int argc, char **argv)
if (option_mask32 & FLAG_TILDE)
empty_line_marker = "";
- kbd_fd = open(CURRENT_TTY, O_RDONLY);
- if (kbd_fd < 0)
- return bb_cat(argv);
- ndelay_on(kbd_fd);
+ /* Some versions of less can survive w/o controlling tty,
+ * try to do the same. This also allows to specify an alternative
+ * tty via "less 1<>TTY".
+ * We don't try to use STDOUT_FILENO directly,
+ * since we want to set this fd to non-blocking mode,
+ * and not bother with restoring it on exit.
+ */
+ tty_name = xmalloc_ttyname(STDOUT_FILENO);
+ if (tty_name) {
+ tty_fd = open(tty_name, O_RDONLY);
+ free(tty_name);
+ if (tty_fd < 0)
+ goto try_ctty;
+ } else {
+ /* Try controlling tty */
+ try_ctty:
+ tty_fd = open(CURRENT_TTY, O_RDONLY);
+ if (tty_fd < 0)
+ return bb_cat(argv);
+ }
+ ndelay_on(tty_fd);
+ kbd_fd = tty_fd; /* save in a global */
tcgetattr(kbd_fd, &term_orig);
term_less = term_orig;
@@ -1805,7 +1967,7 @@ key and/or command line switch compatibility is a good idea:
Most options may be changed either on the command line,
or from within less by using the - or -- command.
Options may be given in one of two forms: either a single
- character preceded by a -, or a name preceeded by --.
+ character preceded by a -, or a name preceded by --.
-? ........ --help
Display help (from command line).
-a ........ --search-skip-screen
diff --git a/release/src/router/busybox/miscutils/man.c b/release/src/router/busybox/miscutils/man.c
index e380fdabaf..58ed81955b 100644
--- a/release/src/router/busybox/miscutils/man.c
+++ b/release/src/router/busybox/miscutils/man.c
@@ -66,7 +66,7 @@ static int run_pipe(const char *pager, char *man_filename, int man, int level)
goto ordinary_manpage;
line = xmalloc_open_zipped_read_close(man_filename, NULL);
- if (!line || strncmp(line, ".so ", 4) != 0) {
+ if (!line || !is_prefixed_with(line, ".so ")) {
free(line);
goto ordinary_manpage;
}
@@ -102,11 +102,12 @@ static int run_pipe(const char *pager, char *man_filename, int man, int level)
ordinary_manpage:
close(STDIN_FILENO);
- open_zipped(man_filename); /* guaranteed to use fd 0 (STDIN_FILENO) */
+ open_zipped(man_filename, /*fail_if_not_compressed:*/ 0); /* guaranteed to use fd 0 (STDIN_FILENO) */
/* "2>&1" is added so that nroff errors are shown in pager too.
* Otherwise it may show just empty screen */
cmd = xasprintf(
- man ? "gtbl | nroff -Tlatin1 -mandoc 2>&1 | %s"
+ /* replaced -Tlatin1 with -Tascii for non-UTF8 displays */
+ man ? "gtbl | nroff -Tascii -mandoc 2>&1 | %s"
: "%s",
pager);
system(cmd);
@@ -146,15 +147,51 @@ static int show_manpage(const char *pager, char *man_filename, int man, int leve
return run_pipe(pager, man_filename, man, level);
}
+static char **add_MANPATH(char **man_path_list, int *count_mp, char *path)
+{
+ if (path) while (*path) {
+ char *next_path;
+ char **path_element;
+
+ next_path = strchr(path, ':');
+ if (next_path) {
+ if (next_path == path) /* "::"? */
+ goto next;
+ *next_path = '\0';
+ }
+ /* Do we already have path? */
+ path_element = man_path_list;
+ if (path_element) while (*path_element) {
+ if (strcmp(*path_element, path) == 0)
+ goto skip;
+ path_element++;
+ }
+ man_path_list = xrealloc_vector(man_path_list, 4, *count_mp);
+ man_path_list[*count_mp] = xstrdup(path);
+ (*count_mp)++;
+ /* man_path_list is NULL terminated */
+ /* man_path_list[*count_mp] = NULL; - xrealloc_vector did it */
+ skip:
+ if (!next_path)
+ break;
+ /* "path" may be a result of getenv(), be nice and don't mangle it */
+ *next_path = ':';
+ next:
+ path = next_path + 1;
+ }
+ return man_path_list;
+}
+
int man_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int man_main(int argc UNUSED_PARAM, char **argv)
{
parser_t *parser;
- const char *pager;
- char **man_path_list;
+ const char *pager = ENABLE_LESS ? "less" : "more";
char *sec_list;
char *cur_path, *cur_sect;
- int count_mp, cur_mp;
+ char **man_path_list;
+ int count_mp;
+ int cur_mp;
int opt, not_found;
char *token[2];
@@ -162,20 +199,20 @@ int man_main(int argc UNUSED_PARAM, char **argv)
opt = getopt32(argv, "+aw");
argv += optind;
- sec_list = xstrdup("1:2:3:4:5:6:7:8:9");
- /* Last valid man_path_list[] is [0x10] */
+ sec_list = xstrdup("0p:1:1p:2:3:3p:4:5:6:7:8:9");
+
count_mp = 0;
- man_path_list = xzalloc(0x11 * sizeof(man_path_list[0]));
- man_path_list[0] = getenv("MANPATH");
- if (!man_path_list[0]) /* default, may be overridden by /etc/man.conf */
+ man_path_list = add_MANPATH(NULL, &count_mp,
+ getenv("MANDATORY_MANPATH"+10) /* "MANPATH" */
+ );
+ if (!man_path_list) {
+ /* default, may be overridden by /etc/man.conf */
+ man_path_list = xzalloc(2 * sizeof(man_path_list[0]));
man_path_list[0] = (char*)"/usr/man";
- else
- count_mp++;
- pager = getenv("MANPAGER");
- if (!pager) {
- pager = getenv("PAGER");
- if (!pager)
- pager = "more";
+ /* count_mp stays 0.
+ * Thus, man.conf will overwrite man_path_list[0]
+ * if a path is defined there.
+ */
}
/* Parse man.conf[ig] or man_db.conf */
@@ -190,38 +227,15 @@ int man_main(int argc UNUSED_PARAM, char **argv)
while (config_read(parser, token, 2, 0, "# \t", PARSE_NORMAL)) {
if (!token[1])
continue;
+ if (strcmp("DEFINE", token[0]) == 0) {
+ if (is_prefixed_with("pager", token[1])) {
+ pager = xstrdup(skip_whitespace(token[1]) + 5);
+ }
+ } else
if (strcmp("MANDATORY_MANPATH"+10, token[0]) == 0 /* "MANPATH"? */
|| strcmp("MANDATORY_MANPATH", token[0]) == 0
) {
- char *path = token[1];
- while (*path) {
- char *next_path;
- char **path_element;
-
- next_path = strchr(path, ':');
- if (next_path) {
- *next_path = '\0';
- if (next_path++ == path) /* "::"? */
- goto next;
- }
- /* Do we already have path? */
- path_element = man_path_list;
- while (*path_element) {
- if (strcmp(*path_element, path) == 0)
- goto skip;
- path_element++;
- }
- man_path_list = xrealloc_vector(man_path_list, 4, count_mp);
- man_path_list[count_mp] = xstrdup(path);
- count_mp++;
- /* man_path_list is NULL terminated */
- /*man_path_list[count_mp] = NULL; - xrealloc_vector did it */
- skip:
- if (!next_path)
- break;
- next:
- path = next_path;
- }
+ man_path_list = add_MANPATH(man_path_list, &count_mp, token[1]);
}
if (strcmp("MANSECT", token[0]) == 0) {
free(sec_list);
@@ -230,6 +244,15 @@ int man_main(int argc UNUSED_PARAM, char **argv)
}
config_close(parser);
+ {
+ /* environment overrides setting from man.config */
+ char *env_pager = getenv("MANPAGER");
+ if (!env_pager)
+ env_pager = getenv("PAGER");
+ if (env_pager)
+ pager = env_pager;
+ }
+
not_found = 0;
do { /* for each argv[] */
int found = 0;
diff --git a/release/src/router/busybox/miscutils/mdmm.c b/release/src/router/busybox/miscutils/mdmm.c
index 584a37f1be..d9763ffbf8 100644
--- a/release/src/router/busybox/miscutils/mdmm.c
+++ b/release/src/router/busybox/miscutils/mdmm.c
@@ -17,6 +17,27 @@
*
*/
+//config:config MDMM
+//config: bool "MDMM Utility"
+//config: default n
+//config: help
+//config: The md/mm utility can be used to read/write memory and memory
+//config: mapped registers.
+
+//kbuild:lib-$(CONFIG_MDMM) += mdmm.o
+
+//applet:IF_MDMM(APPLET(md, BB_DIR_USR_SBIN, BB_SUID_DROP))
+//applet:IF_MDMM(APPLET(mm, BB_DIR_USR_SBIN, BB_SUID_DROP))
+
+//usage:#define md_trivial_usage
+//usage: "address [count]"
+//usage:#define md_full_usage "\n"
+//usage:#define mm_trivial_usage
+//usage: "address value"
+//usage:#define mm_full_usage "\n"
+
+#include "libbb.h"
+
/*
* Simple Atheros-specific tool to inspect and monitor network traffic
* statistics.
@@ -43,13 +64,12 @@
#include <errno.h>
#include <unistd.h>
-void usage(void);
-int opendev(int);
+static void usage(void);
+static int opendev(int);
int md_main(int, char *[]);
int mm_main(int, char *[]);
-int main(int, char *[]);
-void
+static void
usage(void)
{
fprintf(stderr, "Usage:\n"
@@ -58,11 +78,10 @@ usage(void)
exit(1);
}
-int
+static int
opendev(int mode)
{
int fd;
- extern int errno;
#define AR_MEM_DEV_NAME "/dev/armem"
fd = open(AR_MEM_DEV_NAME, mode);
@@ -74,19 +93,18 @@ opendev(int mode)
return fd;
}
-int
+static int
closedev(int fd)
{
return close(fd);
}
-int
-md_main(int argc, char *argv[])
+int md_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int md_main(int argc, char *argv[])
{
int i, fd, count;
unsigned val;
loff_t addr;
- off_t ret;
if (argc < 2 || argc > 3) {
usage();
@@ -119,8 +137,8 @@ md_main(int argc, char *argv[])
return 0;
}
-int
-mm_main(int argc, char *argv[])
+int mm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int mm_main(int argc, char *argv[])
{
int fd;
unsigned new;
@@ -148,4 +166,3 @@ mm_main(int argc, char *argv[])
closedev(fd);
return 0;
}
-
diff --git a/release/src/router/busybox/miscutils/microcom.c b/release/src/router/busybox/miscutils/microcom.c
index 5e29a1acdd..d9e8f91879 100644
--- a/release/src/router/busybox/miscutils/microcom.c
+++ b/release/src/router/busybox/miscutils/microcom.c
@@ -19,6 +19,7 @@
//usage: "\n -X Disable special meaning of NUL and Ctrl-X from stdin"
#include "libbb.h"
+#include "common_bufsiz.h"
// set raw tty mode
static void xget1(int fd, struct termios *t, struct termios *oldt)
@@ -155,10 +156,11 @@ int microcom_main(int argc UNUSED_PARAM, char **argv)
skip_write: ;
}
if (pfd[0].revents) {
-#define iobuf bb_common_bufsiz1
ssize_t len;
+#define iobuf bb_common_bufsiz1
+ setup_common_bufsiz();
// read from device -> write to stdout
- len = safe_read(sfd, iobuf, sizeof(iobuf));
+ len = safe_read(sfd, iobuf, COMMON_BUFSIZE);
if (len > 0)
full_write(STDOUT_FILENO, iobuf, len);
else {
diff --git a/release/src/router/busybox/miscutils/nandwrite.c b/release/src/router/busybox/miscutils/nandwrite.c
index 2ba6e3fe55..c95cbb21e6 100644
--- a/release/src/router/busybox/miscutils/nandwrite.c
+++ b/release/src/router/busybox/miscutils/nandwrite.c
@@ -23,27 +23,33 @@
//config: Dump the content of raw NAND chip
//applet:IF_NANDWRITE(APPLET(nandwrite, BB_DIR_USR_SBIN, BB_SUID_DROP))
-//applet:IF_NANDWRITE(APPLET_ODDNAME(nanddump, nandwrite, BB_DIR_USR_SBIN, BB_SUID_DROP, nanddump))
+//applet:IF_NANDDUMP(APPLET_ODDNAME(nanddump, nandwrite, BB_DIR_USR_SBIN, BB_SUID_DROP, nanddump))
//kbuild:lib-$(CONFIG_NANDWRITE) += nandwrite.o
//kbuild:lib-$(CONFIG_NANDDUMP) += nandwrite.o
//usage:#define nandwrite_trivial_usage
-//usage: "[-p] [-s ADDR] MTD_DEVICE [FILE]"
+//usage: "[-np] [-s ADDR] MTD_DEVICE [FILE]"
//usage:#define nandwrite_full_usage "\n\n"
-//usage: "Write to the specified MTD device\n"
+//usage: "Write to MTD_DEVICE\n"
+//usage: "\n -n Write without ecc"
//usage: "\n -p Pad to page size"
//usage: "\n -s ADDR Start address"
//usage:#define nanddump_trivial_usage
-//usage: "[-o] [-b] [-s ADDR] [-f FILE] MTD_DEVICE"
+//usage: "[-no]" IF_LONG_OPTS(" [--bb=padbad|skipbad]") " [-s ADDR] [-l LEN] [-f FILE] MTD_DEVICE"
//usage:#define nanddump_full_usage "\n\n"
-//usage: "Dump the specified MTD device\n"
-//usage: "\n -o Omit oob data"
-//usage: "\n -b Omit bad block from the dump"
+//usage: "Dump MTD_DEVICE\n"
+//usage: "\n -n Read without ecc"
+//usage: "\n -o Dump oob data"
//usage: "\n -s ADDR Start address"
//usage: "\n -l LEN Length"
//usage: "\n -f FILE Dump to file ('-' for stdout)"
+//usage: IF_LONG_OPTS(
+//usage: "\n --bb=METHOD:"
+//usage: "\n skipbad: skip bad blocks"
+//usage: "\n padbad: substitute bad blocks by 0xff (default)"
+//usage: )
#include "libbb.h"
#include <mtd/mtd-user.h>
@@ -53,10 +59,14 @@
#define OPT_p (1 << 0) /* nandwrite only */
#define OPT_o (1 << 0) /* nanddump only */
-#define OPT_s (1 << 1)
-#define OPT_b (1 << 2)
+#define OPT_n (1 << 1)
+#define OPT_s (1 << 2)
#define OPT_f (1 << 3)
#define OPT_l (1 << 4)
+#define OPT_bb (1 << 5) /* must be the last one in the list */
+
+#define BB_PADBAD (1 << 0)
+#define BB_SKIPBAD (1 << 1)
/* helper for writing out 0xff for bad blocks pad */
static void dump_bad(struct mtd_info_user *meminfo, unsigned len, int oob)
@@ -64,8 +74,8 @@ static void dump_bad(struct mtd_info_user *meminfo, unsigned len, int oob)
unsigned char buf[meminfo->writesize];
unsigned count;
- /* round len to the next page */
- len = (len | ~(meminfo->writesize - 1)) + 1;
+ /* round len to the next page only if len is not already on a page */
+ len = ((len - 1) | (meminfo->writesize - 1)) + 1;
memset(buf, 0xff, sizeof(buf));
for (count = 0; count < len; count += meminfo->writesize) {
@@ -102,6 +112,7 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv)
/* Buffer for OOB data */
unsigned char *oobbuf;
unsigned opts;
+ unsigned bb_method = BB_SKIPBAD;
int fd;
ssize_t cnt;
unsigned mtdoffset, meminfo_writesize, blockstart, limit;
@@ -109,14 +120,18 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv)
struct mtd_info_user meminfo;
struct mtd_oob_buf oob;
unsigned char *filebuf;
- const char *opt_s = "0", *opt_f = "-", *opt_l;
+ const char *opt_s = "0", *opt_f = "-", *opt_l, *opt_bb;
if (IS_NANDDUMP) {
opt_complementary = "=1";
- opts = getopt32(argv, "os:bf:l:", &opt_s, &opt_f, &opt_l);
+#if ENABLE_LONG_OPTS
+ applet_long_options =
+ "bb\0" Required_argument "\xff"; /* no short equivalent */
+#endif
+ opts = getopt32(argv, "ons:f:l:", &opt_s, &opt_f, &opt_l, &opt_bb);
} else { /* nandwrite */
opt_complementary = "-1:?2";
- opts = getopt32(argv, "ps:", &opt_s);
+ opts = getopt32(argv, "pns:", &opt_s);
}
argv += optind;
@@ -129,15 +144,26 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv)
xmove_fd(tmp_fd, IS_NANDDUMP ? STDOUT_FILENO : STDIN_FILENO);
}
- fd = xopen(argv[0], O_RDWR);
+ fd = xopen(argv[0], IS_NANDWRITE ? O_RDWR : O_RDONLY);
xioctl(fd, MEMGETINFO, &meminfo);
+ if (opts & OPT_n)
+ xioctl(fd, MTDFILEMODE, (void *)MTD_FILE_MODE_RAW);
+
mtdoffset = xstrtou(opt_s, 0);
if (IS_NANDDUMP && (opts & OPT_l)) {
unsigned length = xstrtou(opt_l, 0);
if (length < meminfo.size - mtdoffset)
end_addr = mtdoffset + length;
}
+ if (IS_NANDDUMP && (opts & OPT_bb)) {
+ if (strcmp("skipbad", opt_bb) == 0)
+ bb_method = BB_SKIPBAD;
+ else if (strcmp("padbad", opt_bb) == 0)
+ bb_method = BB_PADBAD;
+ else
+ bb_show_usage();
+ }
/* Pull it into a CPU register (hopefully) - smaller code that way */
meminfo_writesize = meminfo.writesize;
@@ -162,9 +188,15 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv)
tmp = next_good_eraseblock(fd, &meminfo, blockstart);
if (tmp != blockstart) {
/* bad block(s), advance mtdoffset */
- if (IS_NANDDUMP & !(opts & OPT_b)) {
- int bad_len = MIN(tmp, end_addr) - mtdoffset;
- dump_bad(&meminfo, bad_len, !(opts & OPT_o));
+ if (IS_NANDDUMP) {
+ if (bb_method == BB_PADBAD) {
+ int bad_len = MIN(tmp, end_addr) - mtdoffset;
+ dump_bad(&meminfo, bad_len, opts & OPT_o);
+ }
+ /* with option skipbad, increase the total length */
+ if (bb_method == BB_SKIPBAD) {
+ end_addr += (tmp - blockstart);
+ }
}
mtdoffset = tmp;
}
@@ -183,8 +215,18 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv)
if (IS_NANDWRITE)
printf("Writing at 0x%08x\n", mtdoffset);
else if (mtdoffset > blockstart) {
- int bad_len = MIN(mtdoffset, limit) - blockstart;
- dump_bad(&meminfo, bad_len, !(opts & OPT_o));
+ if (bb_method == BB_PADBAD) {
+ /* dump FF padded bad block */
+ int bad_len = MIN(mtdoffset, limit) - blockstart;
+ dump_bad(&meminfo, bad_len, opts & OPT_o);
+ } else if (bb_method == BB_SKIPBAD) {
+ /* for skipbad, increase the length */
+ if ((end_addr + mtdoffset - blockstart) > end_addr)
+ end_addr += (mtdoffset - blockstart);
+ else
+ end_addr = ~0;
+ limit = MIN(meminfo.size, end_addr);
+ }
}
if (mtdoffset >= limit)
break;
@@ -210,7 +252,7 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv)
}
xwrite(output_fd, filebuf, meminfo_writesize);
- if (IS_NANDDUMP && !(opts & OPT_o)) {
+ if (IS_NANDDUMP && (opts & OPT_o)) {
/* Dump OOB data */
oob.start = mtdoffset;
xioctl(fd, MEMREADOOB, &oob);
diff --git a/release/src/router/busybox/miscutils/rfkill.c b/release/src/router/busybox/miscutils/rfkill.c
index 4671973713..7411b6fc39 100644
--- a/release/src/router/busybox/miscutils/rfkill.c
+++ b/release/src/router/busybox/miscutils/rfkill.c
@@ -7,6 +7,23 @@
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//config:config RFKILL
+//config: bool "rfkill"
+//config: default n # doesn't build on Ubuntu 9.04
+//config: select PLATFORM_LINUX
+//config: help
+//config: Enable/disable wireless devices.
+//config:
+//config: rfkill list : list all wireless devices
+//config: rfkill list bluetooth : list all bluetooth devices
+//config: rfkill list 1 : list device corresponding to the given index
+//config: rfkill block|unblock wlan : block/unblock all wlan(wifi) devices
+//config:
+
+//applet:IF_RFKILL(APPLET(rfkill, BB_DIR_USR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_RFKILL) += rfkill.o
+
//usage:#define rfkill_trivial_usage
//usage: "COMMAND [INDEX|TYPE]"
//usage:#define rfkill_full_usage "\n\n"
diff --git a/release/src/router/busybox/miscutils/runlevel.c b/release/src/router/busybox/miscutils/runlevel.c
index 76231df228..8558db8625 100644
--- a/release/src/router/busybox/miscutils/runlevel.c
+++ b/release/src/router/busybox/miscutils/runlevel.c
@@ -29,19 +29,19 @@
int runlevel_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int runlevel_main(int argc UNUSED_PARAM, char **argv)
{
- struct utmp *ut;
+ struct utmpx *ut;
char prev;
- if (argv[1]) utmpname(argv[1]);
+ if (argv[1]) utmpxname(argv[1]);
- setutent();
- while ((ut = getutent()) != NULL) {
+ setutxent();
+ while ((ut = getutxent()) != NULL) {
if (ut->ut_type == RUN_LVL) {
prev = ut->ut_pid / 256;
if (prev == 0) prev = 'N';
printf("%c %c\n", prev, ut->ut_pid % 256);
if (ENABLE_FEATURE_CLEAN_UP)
- endutent();
+ endutxent();
return 0;
}
}
@@ -49,6 +49,6 @@ int runlevel_main(int argc UNUSED_PARAM, char **argv)
puts("unknown");
if (ENABLE_FEATURE_CLEAN_UP)
- endutent();
+ endutxent();
return 1;
}
diff --git a/release/src/router/busybox/miscutils/rx.c b/release/src/router/busybox/miscutils/rx.c
index af597320ce..1dffb593af 100644
--- a/release/src/router/busybox/miscutils/rx.c
+++ b/release/src/router/busybox/miscutils/rx.c
@@ -193,8 +193,8 @@ static int receive(/*int read_fd, */int file_fd)
}
if (cksum_or_crc != expected) {
bb_error_msg(do_crc ? "crc error, expected 0x%04x, got 0x%04x"
- : "checksum error, expected 0x%02x, got 0x%02x",
- expected, cksum_or_crc);
+ : "checksum error, expected 0x%02x, got 0x%02x",
+ expected, cksum_or_crc);
goto error;
}
diff --git a/release/src/router/busybox/miscutils/setserial.c b/release/src/router/busybox/miscutils/setserial.c
index 2a034e32c0..8b5c4a9c76 100644
--- a/release/src/router/busybox/miscutils/setserial.c
+++ b/release/src/router/busybox/miscutils/setserial.c
@@ -223,7 +223,7 @@ struct serial_struct {
//usage: " -v Verbose\n"
//usage: "\n"
//usage: "Parameters: (* = takes an argument, ^ = can be turned off by preceding ^)\n"
-//usage: " *port, *irq, *divisor, *uart, *baund_base, *close_delay, *closing_wait,\n"
+//usage: " *port, *irq, *divisor, *uart, *baud_base, *close_delay, *closing_wait,\n"
//usage: " ^fourport, ^auto_irq, ^skip_test, ^sak, ^session_lockout, ^pgrp_lockout,\n"
//usage: " ^callout_nohup, ^split_termios, ^hup_notify, ^low_latency, autoconfig,\n"
//usage: " spd_normal, spd_hi, spd_vhi, spd_shi, spd_warp, spd_cust\n"
@@ -257,7 +257,7 @@ enum print_mode
#define CTL_CLOSE (1 << 3)
#define CTL_NODIE (1 << 4)
-static const char serial_types[] =
+static const char serial_types[] ALIGN1 =
"unknown\0" /* 0 */
"8250\0" /* 1 */
"16450\0" /* 2 */
@@ -288,7 +288,7 @@ static const char serial_types[] =
# define MAX_SERIAL_TYPE 13
#endif
-static const char commands[] =
+static const char commands[] ALIGN1 =
"spd_normal\0"
"spd_hi\0"
"spd_vhi\0"
@@ -311,7 +311,7 @@ static const char commands[] =
"irq\0"
"divisor\0"
"uart\0"
- "baund_base\0"
+ "baud_base\0"
"close_delay\0"
"closing_wait\0"
@@ -404,8 +404,8 @@ static const uint16_t setbits[CMD_FLAG_LAST + 1] =
ASYNC_LOW_LATENCY
};
-static const char STR_INFINITE[] = "infinite";
-static const char STR_NONE[] = "none";
+#define STR_INFINITE "infinite"
+#define STR_NONE "none"
static const char *uart_type(int type)
{
diff --git a/release/src/router/busybox/miscutils/setsid.c b/release/src/router/busybox/miscutils/setsid.c
index ad2c8a4de5..9bddc2fcf0 100644
--- a/release/src/router/busybox/miscutils/setsid.c
+++ b/release/src/router/busybox/miscutils/setsid.c
@@ -15,23 +15,36 @@
*/
//usage:#define setsid_trivial_usage
-//usage: "PROG ARGS"
+//usage: "[-c] PROG ARGS"
//usage:#define setsid_full_usage "\n\n"
//usage: "Run PROG in a new session. PROG will have no controlling terminal\n"
-//usage: "and will not be affected by keyboard signals (Ctrl-C etc).\n"
-//usage: "See setsid(2) for details."
+//usage: "and will not be affected by keyboard signals (^C etc).\n"
+//usage: "\n -c Set controlling terminal to stdin"
#include "libbb.h"
int setsid_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int setsid_main(int argc UNUSED_PARAM, char **argv)
{
- if (!argv[1])
- bb_show_usage();
+ unsigned opt;
+
+ opt_complementary = "-1"; /* at least one arg */
+ opt = getopt32(argv, "+c"); /* +: stop on first non-opt */
+ argv += optind;
/* setsid() is allowed only when we are not a process group leader.
* Otherwise our PID serves as PGID of some existing process group
- * and cannot be used as PGID of a new process group. */
+ * and cannot be used as PGID of a new process group.
+ *
+ * Example: setsid() below fails when run alone in interactive shell:
+ * $ setsid PROG
+ * because shell's child (setsid) is put in a new process group.
+ * But doesn't fail if shell is not interactive
+ * (and therefore doesn't create process groups for pipes),
+ * or if setsid is not the first process in the process group:
+ * $ true | setsid PROG
+ * or if setsid is executed in backquotes (`setsid PROG`)...
+ */
if (setsid() < 0) {
pid_t pid = fork_or_rexec(argv);
if (pid != 0) {
@@ -43,7 +56,7 @@ int setsid_main(int argc UNUSED_PARAM, char **argv)
* However, the code is larger and upstream
* does not do such trick.
*/
- exit(EXIT_SUCCESS);
+ return EXIT_SUCCESS;
}
/* child */
@@ -51,6 +64,10 @@ int setsid_main(int argc UNUSED_PARAM, char **argv)
setsid();
}
- argv++;
+ if (opt) {
+ /* -c: set (with stealing) controlling tty */
+ ioctl(0, TIOCSCTTY, 1);
+ }
+
BB_EXECVP_or_die(argv);
}
diff --git a/release/src/router/busybox/miscutils/taskset.c b/release/src/router/busybox/miscutils/taskset.c
index 4a9e3230d3..fb352ab8dc 100644
--- a/release/src/router/busybox/miscutils/taskset.c
+++ b/release/src/router/busybox/miscutils/taskset.c
@@ -6,6 +6,25 @@
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//config:config TASKSET
+//config: bool "taskset"
+//config: default n # doesn't build on some non-x86 targets (m68k)
+//config: help
+//config: Retrieve or set a processes's CPU affinity.
+//config: This requires sched_{g,s}etaffinity support in your libc.
+//config:
+//config:config FEATURE_TASKSET_FANCY
+//config: bool "Fancy output"
+//config: default y
+//config: depends on TASKSET
+//config: help
+//config: Add code for fancy output. This merely silences a compiler-warning
+//config: and adds about 135 Bytes. May be needed for machines with alot
+//config: of CPUs.
+
+//applet:IF_TASKSET(APPLET(taskset, BB_DIR_USR_BIN, BB_SUID_DROP))
+//kbuild:lib-$(CONFIG_TASKSET) += taskset.o
+
//usage:#define taskset_trivial_usage
//usage: "[-p] [MASK] [PID | PROG ARGS]"
//usage:#define taskset_full_usage "\n\n"
@@ -22,6 +41,11 @@
//usage: "pid 6671's new affinity mask: 1\n"
//usage: "$ taskset -p 1\n"
//usage: "pid 1's current affinity mask: 3\n"
+/*
+ Not yet implemented:
+ * -a/--all-tasks (affect all threads)
+ * -c/--cpu-list (specify CPUs via "1,3,5-7")
+ */
#include <sched.h>
#include "libbb.h"
@@ -51,29 +75,26 @@ static char *from_cpuset(cpu_set_t *mask)
#define TASKSET_PRINTF_MASK "%llx"
static unsigned long long from_cpuset(cpu_set_t *mask)
{
- struct BUG_CPU_SETSIZE_is_too_small {
- char BUG_CPU_SETSIZE_is_too_small[
- CPU_SETSIZE < sizeof(int) ? -1 : 1];
- };
- char *p = (void*)mask;
-
- /* Take the least significant bits. Careful!
- * Consider both CPU_SETSIZE=4 and CPU_SETSIZE=1024 cases
+ BUILD_BUG_ON(CPU_SETSIZE < 8*sizeof(int));
+
+ /* Take the least significant bits. Assume cpu_set_t is
+ * implemented as an array of unsigned long or unsigned
+ * int.
*/
-#if BB_BIG_ENDIAN
- /* For big endian, it means LAST bits */
- if (CPU_SETSIZE < sizeof(long))
- p += CPU_SETSIZE - sizeof(int);
- else if (CPU_SETSIZE < sizeof(long long))
- p += CPU_SETSIZE - sizeof(long);
- else
- p += CPU_SETSIZE - sizeof(long long);
-#endif
- if (CPU_SETSIZE < sizeof(long))
- return *(unsigned*)p;
- if (CPU_SETSIZE < sizeof(long long))
- return *(unsigned long*)p;
- return *(unsigned long long*)p;
+ if (CPU_SETSIZE < 8*sizeof(long))
+ return *(unsigned*)mask;
+ if (CPU_SETSIZE < 8*sizeof(long long))
+ return *(unsigned long*)mask;
+# if BB_BIG_ENDIAN
+ if (sizeof(long long) > sizeof(long)) {
+ /* We can put two long in the long long, but they have to
+ * be swapped: the least significant word comes first in the
+ * array */
+ unsigned long *p = (void*)mask;
+ return p[0] + ((unsigned long long)p[1] << (8*sizeof(long)));
+ }
+# endif
+ return *(unsigned long long*)mask;
}
#endif
@@ -128,17 +149,65 @@ int taskset_main(int argc UNUSED_PARAM, char **argv)
current_new += 8; /* "new" */
}
- { /* Affinity was specified, translate it into cpu_set_t */
+ /* Affinity was specified, translate it into cpu_set_t */
+ CPU_ZERO(&mask);
+ if (!ENABLE_FEATURE_TASKSET_FANCY) {
unsigned i;
+ unsigned long long m;
+
/* Do not allow zero mask: */
- unsigned long long m = xstrtoull_range(aff, 0, 1, ULLONG_MAX);
- enum { CNT_BIT = CPU_SETSIZE < sizeof(m)*8 ? CPU_SETSIZE : sizeof(m)*8 };
+ m = xstrtoull_range(aff, 0, 1, ULLONG_MAX);
+ i = 0;
+ do {
+ if (m & 1)
+ CPU_SET(i, &mask);
+ i++;
+ m >>= 1;
+ } while (m != 0);
+ } else {
+ unsigned i;
+ char *last_byte;
+ char *bin;
+ uint8_t bit_in_byte;
+
+ /* Cheap way to get "long enough" buffer */
+ bin = xstrdup(aff);
+
+ if (aff[0] != '0' || (aff[1]|0x20) != 'x') {
+/* TODO: decimal/octal masks are still limited to 2^64 */
+ unsigned long long m = xstrtoull_range(aff, 0, 1, ULLONG_MAX);
+ bin += strlen(bin);
+ last_byte = bin - 1;
+ while (m) {
+ *--bin = m & 0xff;
+ m >>= 8;
+ }
+ } else {
+ /* aff is "0x.....", we accept very long masks in this form */
+ last_byte = hex2bin(bin, aff + 2, INT_MAX);
+ if (!last_byte) {
+ bad_aff:
+ bb_error_msg_and_die("bad affinity '%s'", aff);
+ }
+ last_byte--; /* now points to the last byte */
+ }
- CPU_ZERO(&mask);
- for (i = 0; i < CNT_BIT; i++) {
- unsigned long long bit = (1ULL << i);
- if (bit & m)
+ i = 0;
+ bit_in_byte = 1;
+ while (last_byte >= bin) {
+ if (bit_in_byte & *last_byte) {
+ if (i >= CPU_SETSIZE)
+ goto bad_aff;
CPU_SET(i, &mask);
+ //bb_error_msg("bit %d set", i);
+ }
+ i++;
+ /* bit_in_byte is uint8_t! & 0xff is implied */
+ bit_in_byte = (bit_in_byte << 1);
+ if (!bit_in_byte) {
+ bit_in_byte = 1;
+ last_byte--;
+ }
}
}
diff --git a/release/src/router/busybox/miscutils/time.c b/release/src/router/busybox/miscutils/time.c
index 945f15f0d5..19b0b44c91 100644
--- a/release/src/router/busybox/miscutils/time.c
+++ b/release/src/router/busybox/miscutils/time.c
@@ -16,6 +16,7 @@
//usage: "\n -v Verbose"
#include "libbb.h"
+#include <sys/resource.h> /* getrusage */
/* Information on the resources used by a child process. */
typedef struct {
@@ -69,7 +70,7 @@ static void resuse_end(pid_t pid, resource_t *resp)
pid_t caught;
/* Ignore signals, but don't ignore the children. When wait3
- returns the child process, set the time the command finished. */
+ * returns the child process, set the time the command finished. */
while ((caught = wait3(&resp->waitstatus, 0, &resp->ru)) != pid) {
if (caught == -1 && errno != EINTR) {
bb_perror_msg("wait");
diff --git a/release/src/router/busybox/miscutils/ubi_tools.c b/release/src/router/busybox/miscutils/ubi_tools.c
index dd99a44f4e..4364bc807f 100644
--- a/release/src/router/busybox/miscutils/ubi_tools.c
+++ b/release/src/router/busybox/miscutils/ubi_tools.c
@@ -66,14 +66,6 @@
#endif
#include <mtd/ubi-user.h>
-#define OPTION_M (1 << 0)
-#define OPTION_D (1 << 1)
-#define OPTION_n (1 << 2)
-#define OPTION_N (1 << 3)
-#define OPTION_s (1 << 4)
-#define OPTION_a (1 << 5)
-#define OPTION_t (1 << 6)
-
#define do_attach (ENABLE_UBIATTACH && applet_name[3] == 'a')
#define do_detach (ENABLE_UBIDETACH && applet_name[3] == 'd')
#define do_mkvol (ENABLE_UBIMKVOL && applet_name[3] == 'm')
@@ -81,191 +73,268 @@
#define do_rsvol (ENABLE_UBIRSVOL && applet_name[4] == 's')
#define do_update (ENABLE_UBIUPDATEVOL && applet_name[3] == 'u')
-//usage:#define ubiattach_trivial_usage
-//usage: "-m MTD_NUM [-d UBI_NUM] UBI_CTRL_DEV"
-//usage:#define ubiattach_full_usage "\n\n"
-//usage: "Attach MTD device to UBI\n"
-//usage: "\n -m MTD_NUM MTD device number to attach"
-//usage: "\n -d UBI_NUM UBI device number to assign"
-//usage:
-//usage:#define ubidetach_trivial_usage
-//usage: "-d UBI_NUM UBI_CTRL_DEV"
-//usage:#define ubidetach_full_usage "\n\n"
-//usage: "Detach MTD device from UBI\n"
-//usage: "\n -d UBI_NUM UBI device number"
-//usage:
-//usage:#define ubimkvol_trivial_usage
-//usage: "UBI_DEVICE -N NAME -s SIZE"
-//usage:#define ubimkvol_full_usage "\n\n"
-//usage: "Create UBI volume\n"
-//usage: "\n -a ALIGNMENT Volume alignment (default 1)"
-//usage: "\n -n VOLID Volume ID, if not specified, it"
-//usage: "\n will be assigned automatically"
-//usage: "\n -N NAME Volume name"
-//usage: "\n -s SIZE Size in bytes"
-//usage: "\n -t TYPE Volume type (static|dynamic)"
-//usage:
-//usage:#define ubirmvol_trivial_usage
-//usage: "UBI_DEVICE -n VOLID"
-//usage:#define ubirmvol_full_usage "\n\n"
-//usage: "Remove UBI volume\n"
-//usage: "\n -n VOLID Volume ID"
-//usage:
-//usage:#define ubirsvol_trivial_usage
-//usage: "UBI_DEVICE -n VOLID -s SIZE"
-//usage:#define ubirsvol_full_usage "\n\n"
-//usage: "Resize UBI volume\n"
-//usage: "\n -n VOLID Volume ID to resize"
-//usage: "\n -s SIZE Size in bytes"
-//usage:
-//usage:#define ubiupdatevol_trivial_usage
-//usage: "UBI_DEVICE [IMG_FILE]"
-//usage:#define ubiupdatevol_full_usage "\n\n"
-//usage: "Update UBI volume\n"
-//usage: "\n -t Truncate UBI volume"
-//usage: "\n -s SIZE Bytes in input (if reading stdin)"
+static unsigned get_num_from_file(const char *path, unsigned max, const char *errmsg)
+{
+ char buf[sizeof(long long)*3];
+ unsigned long long num;
+ if (open_read_close(path, buf, sizeof(buf)) < 0)
+ bb_perror_msg_and_die(errmsg, path);
+ /* It can be \n terminated, xatoull won't work well */
+ if (sscanf(buf, "%llu", &num) != 1 || num > max)
+ bb_error_msg_and_die(errmsg, path);
+ return num;
+}
+
+/* To prevent malloc(1G) accidents */
+#define MAX_SANE_ERASEBLOCK (16*1024*1024)
int ubi_tools_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int ubi_tools_main(int argc UNUSED_PARAM, char **argv)
{
+ static const struct suffix_mult size_suffixes[] = {
+ { "KiB", 1024 },
+ { "MiB", 1024*1024 },
+ { "GiB", 1024*1024*1024 },
+ { "", 0 }
+ };
+
unsigned opts;
char *ubi_ctrl;
- //struct stat st;
int fd;
int mtd_num;
int dev_num = UBI_DEV_NUM_AUTO;
int vol_id = UBI_VOL_NUM_AUTO;
- char *vol_name = NULL;
- int size_bytes;
+ int vid_hdr_offset = 0;
+ char *vol_name;
+ unsigned long long size_bytes = size_bytes; /* for compiler */
+ char *size_bytes_str;
int alignment = 1;
- char *type = NULL;
+ char *type;
+ union {
+ struct ubi_attach_req attach_req;
+ struct ubi_mkvol_req mkvol_req;
+ struct ubi_rsvol_req rsvol_req;
+ } req_structs;
+#define attach_req req_structs.attach_req
+#define mkvol_req req_structs.mkvol_req
+#define rsvol_req req_structs.rsvol_req
+ char path[sizeof("/sys/class/ubi/ubi%d_%d/usable_eb_size")
+ + 2 * sizeof(int)*3 + /*just in case:*/ 16];
+#define path_sys_class_ubi_ubi (path + sizeof("/sys/class/ubi/ubi")-1)
- opt_complementary = "-1:m+:d+:n+:s+:a+";
- opts = getopt32(argv, "m:d:n:N:s:a:t::",
- &mtd_num, &dev_num, &vol_id,
- &vol_name, &size_bytes, &alignment, &type
- );
- ubi_ctrl = argv[optind];
+ strcpy(path, "/sys/class/ubi/ubi");
+ memset(&req_structs, 0, sizeof(req_structs));
+
+#define OPTION_m (1 << 0)
+#define OPTION_d (1 << 1)
+#define OPTION_n (1 << 2)
+#define OPTION_N (1 << 3)
+#define OPTION_s (1 << 4)
+#define OPTION_a (1 << 5)
+#define OPTION_t (1 << 6)
+ if (do_mkvol) {
+ opt_complementary = "-1:d+:n+:a+:O+";
+ opts = getopt32(argv, "md:n:N:s:a:t:O:",
+ &dev_num, &vol_id,
+ &vol_name, &size_bytes_str, &alignment, &type,
+ &vid_hdr_offset
+ );
+ } else
+ if (do_update) {
+ opt_complementary = "-1";
+ opts = getopt32(argv, "s:at", &size_bytes_str);
+ opts *= OPTION_s;
+ } else {
+ opt_complementary = "-1:m+:d+:n+:a+";
+ opts = getopt32(argv, "m:d:n:N:s:a:t:",
+ &mtd_num, &dev_num, &vol_id,
+ &vol_name, &size_bytes_str, &alignment, &type
+ );
+ }
+
+ if (opts & OPTION_s)
+ size_bytes = xatoull_sfx(size_bytes_str, size_suffixes);
+ argv += optind;
+ ubi_ctrl = *argv++;
fd = xopen(ubi_ctrl, O_RDWR);
//xfstat(fd, &st, ubi_ctrl);
//if (!S_ISCHR(st.st_mode))
// bb_error_msg_and_die("%s: not a char device", ubi_ctrl);
+//usage:#define ubiattach_trivial_usage
+//usage: "-m MTD_NUM [-d UBI_NUM] [-O VID_HDR_OFF] UBI_CTRL_DEV"
+//usage:#define ubiattach_full_usage "\n\n"
+//usage: "Attach MTD device to UBI\n"
+//usage: "\n -m MTD_NUM MTD device number to attach"
+//usage: "\n -d UBI_NUM UBI device number to assign"
+//usage: "\n -O VID_HDR_OFF VID header offset"
if (do_attach) {
- struct ubi_attach_req req;
- if (!(opts & OPTION_M))
+ if (!(opts & OPTION_m))
bb_error_msg_and_die("%s device not specified", "MTD");
- memset(&req, 0, sizeof(req));
- req.mtd_num = mtd_num;
- req.ubi_num = dev_num;
+ attach_req.mtd_num = mtd_num;
+ attach_req.ubi_num = dev_num;
+ attach_req.vid_hdr_offset = vid_hdr_offset;
- xioctl(fd, UBI_IOCATT, &req);
+ xioctl(fd, UBI_IOCATT, &attach_req);
} else
+
+//usage:#define ubidetach_trivial_usage
+//usage: "-d UBI_NUM UBI_CTRL_DEV"
+//usage:#define ubidetach_full_usage "\n\n"
+//usage: "Detach MTD device from UBI\n"
+//usage: "\n -d UBI_NUM UBI device number"
if (do_detach) {
- if (!(opts & OPTION_D))
+ if (!(opts & OPTION_d))
bb_error_msg_and_die("%s device not specified", "UBI");
+ /* FIXME? kernel expects int32_t* here: */
xioctl(fd, UBI_IOCDET, &dev_num);
} else
+
+//usage:#define ubimkvol_trivial_usage
+//usage: "-N NAME [-s SIZE | -m] UBI_DEVICE"
+//usage:#define ubimkvol_full_usage "\n\n"
+//usage: "Create UBI volume\n"
+//usage: "\n -a ALIGNMENT Volume alignment (default 1)"
+//usage: "\n -m Set volume size to maximum available"
+//usage: "\n -n VOLID Volume ID. If not specified,"
+//usage: "\n assigned automatically"
+//usage: "\n -N NAME Volume name"
+//usage: "\n -s SIZE Size in bytes"
+//usage: "\n -t TYPE Volume type (static|dynamic)"
if (do_mkvol) {
- struct ubi_mkvol_req req;
- int vol_name_len;
+ if (opts & OPTION_m) {
+ unsigned leb_avail;
+ unsigned leb_size;
+ unsigned num;
+ char *p;
+
+ num = ubi_devnum_from_devname(ubi_ctrl);
+ p = path_sys_class_ubi_ubi + sprintf(path_sys_class_ubi_ubi, "%u/", num);
+
+ strcpy(p, "avail_eraseblocks");
+ leb_avail = get_num_from_file(path, UINT_MAX, "Can't get available eraseblocks from '%s'");
+
+ strcpy(p, "eraseblock_size");
+ leb_size = get_num_from_file(path, MAX_SANE_ERASEBLOCK, "Can't get eraseblock size from '%s'");
+
+ size_bytes = leb_avail * (unsigned long long)leb_size;
+ //if (size_bytes <= 0)
+ // bb_error_msg_and_die("%s invalid maximum size calculated", "UBI");
+ } else
if (!(opts & OPTION_s))
- bb_error_msg_and_die("%s size not specified", "UBI");
+ bb_error_msg_and_die("size not specified");
+
if (!(opts & OPTION_N))
- bb_error_msg_and_die("%s name not specified", "UBI");
- vol_name_len = strlen(vol_name);
- if (vol_name_len > UBI_MAX_VOLUME_NAME)
- bb_error_msg_and_die("%s volume name too long", "UBI");
-
- memset(&req, 0, sizeof(req));
- req.vol_id = vol_id;
- if ((opts & OPTION_t) && type) {
- if (type[0] == 's')
- req.vol_type = UBI_STATIC_VOLUME;
- else
- req.vol_type = UBI_DYNAMIC_VOLUME;
- } else {
- req.vol_type = UBI_DYNAMIC_VOLUME;
- }
- req.alignment = alignment;
- req.bytes = size_bytes;
- strncpy(req.name, vol_name, UBI_MAX_VOLUME_NAME);
- req.name_len = vol_name_len;
+ bb_error_msg_and_die("name not specified");
+
+ mkvol_req.vol_id = vol_id;
+ mkvol_req.vol_type = UBI_DYNAMIC_VOLUME;
+ if ((opts & OPTION_t) && type[0] == 's')
+ mkvol_req.vol_type = UBI_STATIC_VOLUME;
+ mkvol_req.alignment = alignment;
+ mkvol_req.bytes = size_bytes; /* signed int64_t */
+ strncpy(mkvol_req.name, vol_name, UBI_MAX_VOLUME_NAME);
+ mkvol_req.name_len = strlen(vol_name);
+ if (mkvol_req.name_len > UBI_MAX_VOLUME_NAME)
+ bb_error_msg_and_die("volume name too long: '%s'", vol_name);
- xioctl(fd, UBI_IOCMKVOL, &req);
+ xioctl(fd, UBI_IOCMKVOL, &mkvol_req);
} else
+
+//usage:#define ubirmvol_trivial_usage
+//usage: "-n VOLID / -N VOLNAME UBI_DEVICE"
+//usage:#define ubirmvol_full_usage "\n\n"
+//usage: "Remove UBI volume\n"
+//usage: "\n -n VOLID Volume ID"
+//usage: "\n -N VOLNAME Volume name"
if (do_rmvol) {
- if (!(opts & OPTION_n))
- bb_error_msg_and_die("%s volume id not specified", "UBI");
+ if (!(opts & (OPTION_n|OPTION_N)))
+ bb_error_msg_and_die("volume id not specified");
+
+ if (opts & OPTION_N) {
+ unsigned num = ubi_devnum_from_devname(ubi_ctrl);
+ vol_id = ubi_get_volid_by_name(num, vol_name);
+ }
- xioctl(fd, UBI_IOCRMVOL, &vol_id);
+ if (sizeof(vol_id) != 4) {
+ /* kernel expects int32_t* in this ioctl */
+ int32_t t = vol_id;
+ xioctl(fd, UBI_IOCRMVOL, &t);
+ } else {
+ xioctl(fd, UBI_IOCRMVOL, &vol_id);
+ }
} else
+
+//usage:#define ubirsvol_trivial_usage
+//usage: "-n VOLID -s SIZE UBI_DEVICE"
+//usage:#define ubirsvol_full_usage "\n\n"
+//usage: "Resize UBI volume\n"
+//usage: "\n -n VOLID Volume ID"
+//usage: "\n -s SIZE Size in bytes"
if (do_rsvol) {
- struct ubi_rsvol_req req;
if (!(opts & OPTION_s))
- bb_error_msg_and_die("%s size not specified", "UBI");
+ bb_error_msg_and_die("size not specified");
if (!(opts & OPTION_n))
- bb_error_msg_and_die("%s volume id not specified", "UBI");
+ bb_error_msg_and_die("volume id not specified");
- memset(&req, 0, sizeof(req));
- req.bytes = size_bytes;
- req.vol_id = vol_id;
+ rsvol_req.bytes = size_bytes; /* signed int64_t */
+ rsvol_req.vol_id = vol_id;
- xioctl(fd, UBI_IOCRSVOL, &req);
+ xioctl(fd, UBI_IOCRSVOL, &rsvol_req);
} else
+
+//usage:#define ubiupdatevol_trivial_usage
+//usage: "[-t | [-s SIZE] IMG_FILE] UBI_DEVICE"
+//usage:#define ubiupdatevol_full_usage "\n\n"
+//usage: "Update UBI volume\n"
+//usage: "\n -t Truncate to zero size"
+//usage: "\n -s SIZE Size in bytes to resize to"
if (do_update) {
- long long bytes;
+ int64_t bytes64;
if (opts & OPTION_t) {
- // truncate the volume by starting an update for size 0
- bytes = 0;
- xioctl(fd, UBI_IOCVOLUP, &bytes);
+ /* truncate the volume by starting an update for size 0 */
+ bytes64 = 0;
+ /* this ioctl expects int64_t* parameter */
+ xioctl(fd, UBI_IOCVOLUP, &bytes64);
}
else {
struct stat st;
- char buf[sizeof("/sys/class/ubi/ubi%d_%d/usable_eb_size") + 2 * sizeof(int)*3];
- int input_fd;
unsigned ubinum, volnum;
unsigned leb_size;
ssize_t len;
char *input_data;
- // Make assumption that device not is in normal format.
- // Removes need for scanning sysfs tree as full libubi does
+ /* Assume that device is in normal format. */
+ /* Removes need for scanning sysfs tree as full libubi does. */
if (sscanf(ubi_ctrl, "/dev/ubi%u_%u", &ubinum, &volnum) != 2)
- bb_error_msg_and_die("%s volume node not in correct format", "UBI");
-
- sprintf(buf, "/sys/class/ubi/ubi%u_%u/usable_eb_size", ubinum, volnum);
- if (open_read_close(buf, buf, sizeof(buf)) <= 0)
- bb_error_msg_and_die("%s could not get LEB size", "UBI");
- if (sscanf(buf, "%u", &leb_size) != 1)
- bb_error_msg_and_die("%s could not get LEB size", "UBI");
-
- if (opts & OPTION_s) {
- input_fd = 0;
- } else {
- if (!argv[optind+1])
+ bb_error_msg_and_die("wrong format of UBI device name");
+
+ sprintf(path_sys_class_ubi_ubi, "%u_%u/usable_eb_size", ubinum, volnum);
+ leb_size = get_num_from_file(path, MAX_SANE_ERASEBLOCK, "Can't get usable eraseblock size from '%s'");
+
+ if (!(opts & OPTION_s)) {
+ if (!*argv)
bb_show_usage();
- xstat(argv[optind+1], &st);
+ xmove_fd(xopen(*argv, O_RDONLY), STDIN_FILENO);
+ xfstat(STDIN_FILENO, &st, *argv);
size_bytes = st.st_size;
- input_fd = xopen(argv[optind+1], O_RDONLY);
}
- bytes = size_bytes;
- xioctl(fd, UBI_IOCVOLUP, &bytes);
+ bytes64 = size_bytes;
+ /* this ioctl expects signed int64_t* parameter */
+ xioctl(fd, UBI_IOCVOLUP, &bytes64);
input_data = xmalloc(leb_size);
- while ((len = full_read(input_fd, input_data, leb_size)) > 0) {
+ while ((len = full_read(STDIN_FILENO, input_data, leb_size)) > 0) {
xwrite(fd, input_data, len);
}
if (len < 0)
- bb_error_msg_and_die("%s volume update failed", "UBI");
- if (ENABLE_FEATURE_CLEAN_UP)
- close(input_fd);
+ bb_perror_msg_and_die("UBI volume update failed");
}
}
diff --git a/release/src/router/busybox/miscutils/ubirename.c b/release/src/router/busybox/miscutils/ubirename.c
new file mode 100644
index 0000000000..8b1c3785ac
--- /dev/null
+++ b/release/src/router/busybox/miscutils/ubirename.c
@@ -0,0 +1,94 @@
+/* ubirename - port of the ubirename from the mtd-utils package
+ *
+ * A utility to rename one UBI volume.
+ *
+ * 2016-03-01 Sven Eisenberg <sven.eisenberg@novero.com>
+ *
+ * Licensed under GPLv2, see file LICENSE in this source tree.
+ */
+//config:config UBIRENAME
+//config: bool "ubirename"
+//config: default y
+//config: select PLATFORM_LINUX
+//config: help
+//config: Utility to rename UBI volumes
+
+//applet:IF_UBIRENAME(APPLET(ubirename, BB_DIR_USR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_UBIRENAME) += ubirename.o
+
+//usage:#define ubirename_trivial_usage
+//usage: "UBI_DEVICE OLD_VOLNAME NEW_VOLNAME [OLD2 NEW2]..."
+//usage:#define ubirename_full_usage "\n\n"
+//usage: "Rename UBI volumes on UBI_DEVICE"
+
+#include "libbb.h"
+#include <mtd/mtd-user.h>
+
+#ifndef __packed
+# define __packed __attribute__((packed))
+#endif
+
+// from ubi-media.h
+#define UBI_MAX_VOLUME_NAME 127
+#define UBI_MAX_VOLUMES 128
+// end ubi-media.h
+
+// from ubi-user.h
+/* ioctl commands of UBI character devices */
+#define UBI_IOC_MAGIC 'o'
+
+/* Re-name volumes */
+#define UBI_IOCRNVOL _IOW(UBI_IOC_MAGIC, 3, struct ubi_rnvol_req)
+
+/* Maximum amount of UBI volumes that can be re-named at one go */
+#define UBI_MAX_RNVOL 32
+
+struct ubi_rnvol_req {
+ int32_t count;
+ int8_t padding1[12];
+ struct {
+ int32_t vol_id;
+ int16_t name_len;
+ int8_t padding2[2];
+ char name[UBI_MAX_VOLUME_NAME + 1];
+ } ents[UBI_MAX_RNVOL];
+} __packed;
+// end ubi-user.h
+
+int ubirename_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int ubirename_main(int argc, char **argv)
+{
+ struct ubi_rnvol_req *rnvol;
+ const char *ubi_devname;
+ unsigned ubi_devnum;
+ unsigned n;
+
+ /* argc can be 4, 6, 8, ... */
+ if ((argc & 1) || (argc >>= 1) < 2)
+ bb_show_usage();
+
+ rnvol = xzalloc(sizeof(*rnvol));
+ rnvol->count = --argc;
+ if (argc > ARRAY_SIZE(rnvol->ents))
+ bb_error_msg_and_die("too many renames requested");
+
+ ubi_devname = argv[1];
+ ubi_devnum = ubi_devnum_from_devname(ubi_devname);
+
+ n = 0;
+ argv += 2;
+ while (argv[0]) {
+ rnvol->ents[n].vol_id = ubi_get_volid_by_name(ubi_devnum, argv[0]);
+ rnvol->ents[n].name_len = strlen(argv[1]);
+ if (rnvol->ents[n].name_len >= sizeof(rnvol->ents[n].name))
+ bb_error_msg_and_die("new name '%s' is too long", argv[1]);
+ strcpy(rnvol->ents[n].name, argv[1]);
+ n++;
+ argv += 2;
+ }
+
+ xioctl(xopen(ubi_devname, O_RDONLY), UBI_IOCRNVOL, rnvol);
+
+ return 0;
+}
diff --git a/release/src/router/busybox/miscutils/wall.c b/release/src/router/busybox/miscutils/wall.c
index 762f53b728..50658f457d 100644
--- a/release/src/router/busybox/miscutils/wall.c
+++ b/release/src/router/busybox/miscutils/wall.c
@@ -6,6 +6,18 @@
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//config:config WALL
+//config: bool "wall"
+//config: default y
+//config: depends on FEATURE_UTMP
+//config: help
+//config: Write a message to all users that are logged in.
+
+/* Needs to be run by root or be suid root - needs to write to /dev/TTY: */
+//applet:IF_WALL(APPLET(wall, BB_DIR_USR_BIN, BB_SUID_REQUIRE))
+
+//kbuild:lib-$(CONFIG_WALL) += wall.o
+
//usage:#define wall_trivial_usage
//usage: "[FILE]"
//usage:#define wall_full_usage "\n\n"
@@ -20,15 +32,22 @@
int wall_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int wall_main(int argc UNUSED_PARAM, char **argv)
{
- struct utmp *ut;
+ struct utmpx *ut;
char *msg;
- int fd = argv[1] ? xopen(argv[1], O_RDONLY) : STDIN_FILENO;
+ int fd;
+ fd = STDIN_FILENO;
+ if (argv[1]) {
+ /* The applet is setuid.
+ * Access to the file must be under user's uid/gid.
+ */
+ fd = xopen_as_uid_gid(argv[1], O_RDONLY, getuid(), getgid());
+ }
msg = xmalloc_read(fd, NULL);
if (ENABLE_FEATURE_CLEAN_UP && argv[1])
close(fd);
- setutent();
- while ((ut = getutent()) != NULL) {
+ setutxent();
+ while ((ut = getutxent()) != NULL) {
char *line;
if (ut->ut_type != USER_PROCESS)
continue;
@@ -37,7 +56,7 @@ int wall_main(int argc UNUSED_PARAM, char **argv)
free(line);
}
if (ENABLE_FEATURE_CLEAN_UP) {
- endutent();
+ endutxent();
free(msg);
}
return EXIT_SUCCESS;
diff --git a/release/src/router/busybox/miscutils/watchdog.c b/release/src/router/busybox/miscutils/watchdog.c
index ee28dc30d3..d3a76edf07 100644
--- a/release/src/router/busybox/miscutils/watchdog.c
+++ b/release/src/router/busybox/miscutils/watchdog.c
@@ -31,6 +31,7 @@ static void watchdog_shutdown(int sig UNUSED_PARAM)
{
static const char V = 'V';
+ remove_pidfile(CONFIG_PID_FILE_PATH "/watchdog.pid");
write(3, &V, 1); /* Magic, see watchdog-api.txt in kernel */
if (ENABLE_FEATURE_CLEAN_UP)
close(3);
@@ -95,6 +96,8 @@ int watchdog_main(int argc, char **argv)
stimer_duration, htimer_duration * 1000);
#endif
+ write_pidfile(CONFIG_PID_FILE_PATH "/watchdog.pid");
+
while (1) {
/*
* Make sure we clear the counter before sleeping,
diff --git a/release/src/router/busybox/modutils/Config.src b/release/src/router/busybox/modutils/Config.src
index 449ac65afb..0b11832bca 100644
--- a/release/src/router/busybox/modutils/Config.src
+++ b/release/src/router/busybox/modutils/Config.src
@@ -38,9 +38,6 @@ config MODPROBE_SMALL
- rmmod is an alias to modprobe -r
- depmod generates modules.dep.bb
- As of 2008-07, this code is experimental. It is 14kb smaller
- than "non-small" modutils.
-
config FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE
bool "Accept module options on modprobe command line"
default y
diff --git a/release/src/router/busybox/modutils/depmod.c b/release/src/router/busybox/modutils/depmod.c
index 7752361261..e5f0e3d2b4 100644
--- a/release/src/router/busybox/modutils/depmod.c
+++ b/release/src/router/busybox/modutils/depmod.c
@@ -21,22 +21,13 @@
* for each depends, look through our list of full paths and emit if found
*/
-typedef struct module_info {
- struct module_info *next;
- char *name, *modname;
- llist_t *dependencies;
- llist_t *aliases;
- llist_t *symbols;
- struct module_info *dnext, *dprev;
-} module_info;
-
static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARAM,
- void *data, int depth UNUSED_PARAM)
+ void *data, int depth UNUSED_PARAM)
{
- char modname[MODULE_NAME_LEN];
- module_info **first = (module_info **) data;
+ module_db *modules = data;
char *image, *ptr;
- module_info *info;
+ module_entry *e;
+
/* Arbitrary. Was sb->st_size, but that breaks .gz etc */
size_t len = (64*1024*1024 - 4096);
@@ -44,38 +35,34 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA
return TRUE;
image = xmalloc_open_zipped_read_close(fname, &len);
- info = xzalloc(sizeof(*info));
- info->next = *first;
- *first = info;
+ e = moddb_get_or_create(modules, bb_get_last_path_component_nostrip(fname));
+ e->name = xstrdup(fname + 2); /* skip "./" */
- info->dnext = info->dprev = info;
- info->name = xstrdup(fname + 2); /* skip "./" */
- info->modname = xstrdup(filename2modname(fname, modname));
for (ptr = image; ptr < image + len - 10; ptr++) {
- if (strncmp(ptr, "depends=", 8) == 0) {
+ if (is_prefixed_with(ptr, "depends=")) {
char *u;
ptr += 8;
for (u = ptr; *u; u++)
if (*u == '-')
*u = '_';
- ptr += string_to_llist(ptr, &info->dependencies, ",");
+ ptr += string_to_llist(ptr, &e->deps, ",");
} else if (ENABLE_FEATURE_MODUTILS_ALIAS
- && strncmp(ptr, "alias=", 6) == 0
+ && is_prefixed_with(ptr, "alias=")
) {
- llist_add_to(&info->aliases, xstrdup(ptr + 6));
+ llist_add_to(&e->aliases, xstrdup(ptr + 6));
ptr += strlen(ptr);
} else if (ENABLE_FEATURE_MODUTILS_SYMBOLS
- && strncmp(ptr, "__ksymtab_", 10) == 0
+ && is_prefixed_with(ptr, "__ksymtab_")
) {
ptr += 10;
- if (strncmp(ptr, "gpl", 3) == 0
+ if (is_prefixed_with(ptr, "gpl")
|| strcmp(ptr, "strings") == 0
) {
continue;
}
- llist_add_to(&info->symbols, xstrdup(ptr));
+ llist_add_to(&e->symbols, xstrdup(ptr));
ptr += strlen(ptr);
}
}
@@ -84,24 +71,13 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA
return TRUE;
}
-static module_info *find_module(module_info *modules, const char *modname)
-{
- module_info *m;
-
- for (m = modules; m != NULL; m = m->next)
- if (strcmp(m->modname, modname) == 0)
- return m;
- return NULL;
-}
-
-static void order_dep_list(module_info *modules, module_info *start,
- llist_t *add)
+static void order_dep_list(module_db *modules, module_entry *start, llist_t *add)
{
- module_info *m;
+ module_entry *m;
llist_t *n;
for (n = add; n != NULL; n = n->link) {
- m = find_module(modules, n->data);
+ m = moddb_get(modules, n->data);
if (m == NULL)
continue;
@@ -116,7 +92,7 @@ static void order_dep_list(module_info *modules, module_info *start,
start->dprev = m;
/* recurse */
- order_dep_list(modules, start, m->dependencies);
+ order_dep_list(modules, start, m->deps);
}
}
@@ -182,10 +158,12 @@ enum {
int depmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int depmod_main(int argc UNUSED_PARAM, char **argv)
{
- module_info *modules, *m, *dep;
+ module_db modules;
+ module_entry *m, *dep;
const char *moddir_base = "/";
char *moddir, *version;
struct utsname uts;
+ unsigned i;
int tmp;
getopt32(argv, "aAb:eF:nruqC:", &moddir_base, NULL, NULL);
@@ -209,23 +187,24 @@ int depmod_main(int argc UNUSED_PARAM, char **argv)
free(moddir);
/* Scan modules */
- modules = NULL;
+ memset(&modules, 0, sizeof(modules));
if (*argv) {
do {
parse_module(*argv, /*sb (unused):*/ NULL, &modules, 0);
} while (*++argv);
} else {
recursive_action(".", ACTION_RECURSE,
- parse_module, NULL, &modules, 0);
+ parse_module, NULL, &modules, 0);
}
/* Generate dependency and alias files */
if (!(option_mask32 & OPT_n))
xfreopen_write(CONFIG_DEFAULT_DEPMOD_FILE, stdout);
- for (m = modules; m != NULL; m = m->next) {
+
+ moddb_foreach_module(&modules, m, i) {
printf("%s:", m->name);
- order_dep_list(modules, m, m->dependencies);
+ order_dep_list(&modules, m, m->deps);
while (m->dnext != m) {
dep = m->dnext;
printf(" %s", dep->name);
@@ -241,44 +220,34 @@ int depmod_main(int argc UNUSED_PARAM, char **argv)
#if ENABLE_FEATURE_MODUTILS_ALIAS
if (!(option_mask32 & OPT_n))
xfreopen_write("modules.alias", stdout);
- for (m = modules; m != NULL; m = m->next) {
- const char *fname = bb_basename(m->name);
- int fnlen = strchrnul(fname, '.') - fname;
+ moddb_foreach_module(&modules, m, i) {
while (m->aliases) {
- /* Last word can well be m->modname instead,
- * but depmod from module-init-tools 3.4
- * uses module basename, i.e., no s/-/_/g.
- * (pathname and .ko.* are still stripped)
- * Mimicking that... */
- printf("alias %s %.*s\n",
+ /*
+ * Last word used to be a basename
+ * (filename with path and .ko.* stripped)
+ * at the time of module-init-tools 3.4.
+ * kmod v.12 uses module name, i.e., s/-/_/g.
+ */
+ printf("alias %s %s\n",
(char*)llist_pop(&m->aliases),
- fnlen, fname);
+ m->modname);
}
}
#endif
#if ENABLE_FEATURE_MODUTILS_SYMBOLS
if (!(option_mask32 & OPT_n))
xfreopen_write("modules.symbols", stdout);
- for (m = modules; m != NULL; m = m->next) {
- const char *fname = bb_basename(m->name);
- int fnlen = strchrnul(fname, '.') - fname;
+ moddb_foreach_module(&modules, m, i) {
while (m->symbols) {
- printf("alias symbol:%s %.*s\n",
+ printf("alias symbol:%s %s\n",
(char*)llist_pop(&m->symbols),
- fnlen, fname);
+ m->modname);
}
}
#endif
- if (ENABLE_FEATURE_CLEAN_UP) {
- while (modules) {
- module_info *old = modules;
- modules = modules->next;
- free(old->name);
- free(old->modname);
- free(old);
- }
- }
+ if (ENABLE_FEATURE_CLEAN_UP)
+ moddb_free(&modules);
return EXIT_SUCCESS;
}
diff --git a/release/src/router/busybox/modutils/insmod.c b/release/src/router/busybox/modutils/insmod.c
index c57d2a7756..2cd54799f7 100644
--- a/release/src/router/busybox/modutils/insmod.c
+++ b/release/src/router/busybox/modutils/insmod.c
@@ -10,9 +10,8 @@
//applet:IF_INSMOD(APPLET(insmod, BB_DIR_SBIN, BB_SUID_DROP))
#include "libbb.h"
+#include "common_bufsiz.h"
#include "modutils.h"
-#include <sys/utsname.h>
-#include <fnmatch.h>
/* 2.6 style insmod has no options and required filename
* (not module name - .ko can't be omitted) */
@@ -23,7 +22,7 @@
//usage: IF_NOT_FEATURE_2_4_MODULES("FILE ")
//usage: "[SYMBOL=VALUE]..."
//usage:#define insmod_full_usage "\n\n"
-//usage: "Load the specified kernel modules into the kernel"
+//usage: "Load kernel module"
//usage: IF_FEATURE_2_4_MODULES( "\n"
//usage: "\n -f Force module to load into the wrong kernel version"
//usage: "\n -k Make module autoclean-able"
@@ -37,7 +36,13 @@
//usage: )
//usage:#endif
-static char *m_filename;
+struct globals {
+ char *filename;
+} FIX_ALIASING;
+#define G (*(struct globals*)bb_common_bufsiz1)
+#define INIT_G() do { \
+ setup_common_bufsiz(); \
+} while (0)
static int FAST_FUNC check_module_name_match(const char *filename,
struct stat *statbuf UNUSED_PARAM,
@@ -52,22 +57,20 @@ static int FAST_FUNC check_module_name_match(const char *filename,
tmp = bb_get_last_path_component_nostrip(filename);
if (strcmp(tmp, fullname) == 0) {
/* Stop searching if we find a match */
- m_filename = xstrdup(filename);
+ G.filename = xstrdup(filename);
return FALSE;
}
return TRUE;
}
-
int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int insmod_main(int argc UNUSED_PARAM, char **argv)
{
- struct stat st;
- char *filename;
- FILE *fp = NULL;
- int pos;
+ char *filename, *dot;
int rc;
+ INIT_G();
+
/* Compat note:
* 2.6 style insmod has no options and required filename
* (not module name - .ko can't be omitted).
@@ -85,45 +88,36 @@ int insmod_main(int argc UNUSED_PARAM, char **argv)
if (!filename)
bb_show_usage();
- m_filename = NULL;
-
- pos = strlen(filename) - 2;
- if (get_linux_version_code() < KERNEL_VERSION(2,6,0)) {
- if (pos < 0) pos = 0;
- if (strncmp(&filename[pos], ".o", 2) !=0)
+ /* Check if we have a complete module name */
+ dot = strrchr(filename, '.');
+ if (ENABLE_FEATURE_2_4_MODULES
+ && get_linux_version_code() < KERNEL_VERSION(2,6,0)) {
+ if (!dot || strcmp(dot, ".o") != 0)
filename = xasprintf("%s.o", filename);
} else {
- if (--pos < 0) pos = 0;
- if (strncmp(&filename[pos], ".ko", 3) !=0)
+ if (!dot || strcmp(dot, ".ko") != 0)
filename = xasprintf("%s.ko", filename);
}
- /* Get a filedesc for the module. Check if we have a complete path */
- if (stat(filename, &st) < 0 || !S_ISREG(st.st_mode) ||
- (fp = fopen_for_read(filename)) == NULL) {
+ /* Check if we have a complete path */
+ if (access(filename, R_OK) != 0) {
/* Hmm. Could not open it. Search /lib/modules/ */
- int r;
- char *module_dir;
-
- module_dir = xmalloc_readlink(CONFIG_DEFAULT_MODULES_DIR);
+ char *module_dir = xmalloc_readlink(CONFIG_DEFAULT_MODULES_DIR);
if (!module_dir)
module_dir = xstrdup(CONFIG_DEFAULT_MODULES_DIR);
- r = recursive_action(module_dir, ACTION_RECURSE,
- check_module_name_match, NULL, filename, 0);
+ rc = recursive_action(module_dir, ACTION_RECURSE,
+ check_module_name_match, NULL, filename, 0);
+ if (!rc && G.filename && access(G.filename, R_OK) == 0)
+ filename = G.filename;
free(module_dir);
- if (r)
- bb_error_msg_and_die("'%s': module not found", filename);
- if (m_filename == NULL || ((fp = fopen_for_read(m_filename)) == NULL))
- bb_error_msg_and_die("'%s': module not found", filename);
- filename = m_filename;
}
- if (fp != NULL)
- fclose(fp);
rc = bb_init_module(filename, parse_cmdline_module_options(argv, /*quote_spaces:*/ 0));
if (rc)
bb_error_msg("can't insert '%s': %s", filename, moderror(rc));
- free(m_filename);
+ if (ENABLE_FEATURE_CLEAN_UP)
+ free(G.filename);
+
return rc;
}
diff --git a/release/src/router/busybox/modutils/modinfo.c b/release/src/router/busybox/modutils/modinfo.c
index c0910ffedf..aa641ad54c 100644
--- a/release/src/router/busybox/modutils/modinfo.c
+++ b/release/src/router/busybox/modutils/modinfo.c
@@ -5,11 +5,6 @@
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
-
-//applet:IF_MODINFO(APPLET(modinfo, BB_DIR_SBIN, BB_SUID_DROP))
-
-//kbuild:lib-$(CONFIG_MODINFO) += modinfo.o modutils.o
-
//config:config MODINFO
//config: bool "modinfo"
//config: default y
@@ -17,102 +12,125 @@
//config: help
//config: Show information about a Linux Kernel module
+//applet:IF_MODINFO(APPLET(modinfo, BB_DIR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_MODINFO) += modinfo.o modutils.o
+
#include <fnmatch.h>
#include <sys/utsname.h> /* uname() */
#include "libbb.h"
#include "modutils.h"
-
-enum {
- OPT_TAGS = (1 << 8) - 1,
- OPT_F = (1 << 8), /* field name */
- OPT_0 = (1 << 9), /* \0 as separator */
+static const char *const shortcuts[] = {
+ "filename", // -n
+ "author", // -a
+ "description", // -d
+ "license", // -l
+ "parm", // -p
+ "version", // the rest has no shortcut options
+ "alias",
+ "srcversion",
+ "depends",
+ "uts_release",
+ "intree",
+ "vermagic",
+ "firmware",
};
-struct modinfo_env {
- char *field;
- int tags;
+enum {
+ OPT_0 = (1 << 0), /* \0 as separator */
+ OPT_F = (1 << 1), /* field name */
+ /* first bits are for -nadlp options, the rest are for
+ * fields not selectable with "shortcut" options
+ */
+ OPT_n = (1 << 2),
+ OPT_TAGS = ((1 << ARRAY_SIZE(shortcuts)) - 1) << 2,
};
-static int display(const char *data, const char *pattern, int flag)
+static void display(const char *data, const char *pattern)
{
- if (flag) {
+ int flag = option_mask32 >> 1; /* shift out -0 bit */
+ if (flag & (flag-1)) {
+ /* more than one field to show: print "FIELD:" pfx */
int n = printf("%s:", pattern);
while (n++ < 16)
bb_putchar(' ');
}
- return printf("%s%c", data, (option_mask32 & OPT_0) ? '\0' : '\n');
+ printf("%s%c", data, (option_mask32 & OPT_0) ? '\0' : '\n');
}
static void modinfo(const char *path, const char *version,
- const struct modinfo_env *env)
+ const char *field)
{
- static const char *const shortcuts[] = {
- "filename",
- "description",
- "author",
- "license",
- "vermagic",
- "parm",
- "firmware",
- "depends",
- };
size_t len;
- int j, length;
+ int j;
char *ptr, *the_module;
- const char *field = env->field;
- int tags = env->tags;
-
- if (tags & 1) { /* filename */
- display(path, shortcuts[0], 1 != tags);
- }
+ char *allocated;
+ int tags = option_mask32;
+ allocated = NULL;
len = MAXINT(ssize_t);
the_module = xmalloc_open_zipped_read_close(path, &len);
if (!the_module) {
if (path[0] == '/')
return;
/* Newer depmod puts relative paths in modules.dep */
- path = xasprintf("%s/%s/%s", CONFIG_DEFAULT_MODULES_DIR, version, path);
+ path = allocated = xasprintf("%s/%s/%s", CONFIG_DEFAULT_MODULES_DIR, version, path);
the_module = xmalloc_open_zipped_read_close(path, &len);
- free((char*)path);
- if (!the_module)
- return;
+ if (!the_module) {
+ bb_error_msg("module '%s' not found", path);
+ goto ret;
+ }
}
- if (field)
- tags |= OPT_F;
- for (j = 1; (1<<j) & (OPT_TAGS + OPT_F); j++) {
+ for (j = 1; (1<<j) & (OPT_TAGS|OPT_F); j++) {
const char *pattern;
if (!((1<<j) & tags))
continue;
+
pattern = field;
if ((1<<j) & OPT_TAGS)
- pattern = shortcuts[j];
- length = strlen(pattern);
+ pattern = shortcuts[j-2];
+
+ if (strcmp(pattern, shortcuts[0]) == 0) {
+ /* "-n" or "-F filename" */
+ display(path, shortcuts[0]);
+ continue;
+ }
+
ptr = the_module;
while (1) {
+ char *after_pattern;
+
ptr = memchr(ptr, *pattern, len - (ptr - (char*)the_module));
if (ptr == NULL) /* no occurance left, done */
break;
- if (strncmp(ptr, pattern, length) == 0 && ptr[length] == '=') {
- ptr += length + 1;
- ptr += display(ptr, pattern, (1<<j) != tags);
+ after_pattern = is_prefixed_with(ptr, pattern);
+ if (after_pattern && *after_pattern == '=') {
+ /* field prefixes are 0x80 or 0x00 */
+ if ((ptr[-1] & 0x7F) == 0x00) {
+ ptr = after_pattern + 1;
+ display(ptr, pattern);
+ ptr += strlen(ptr);
+ }
}
++ptr;
}
}
free(the_module);
+ ret:
+ free(allocated);
}
//usage:#define modinfo_trivial_usage
-//usage: "[-adlp0] [-F keyword] MODULE"
+//usage: "[-adlpn0] [-F keyword] MODULE"
//usage:#define modinfo_full_usage "\n\n"
//usage: " -a Shortcut for '-F author'"
//usage: "\n -d Shortcut for '-F description'"
//usage: "\n -l Shortcut for '-F license'"
//usage: "\n -p Shortcut for '-F parm'"
+////usage: "\n -n Shortcut for '-F filename'"
//usage: "\n -F keyword Keyword to look for"
//usage: "\n -0 Separate output with NULs"
//usage:#define modinfo_example_usage
@@ -121,7 +139,7 @@ static void modinfo(const char *path, const char *version,
int modinfo_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int modinfo_main(int argc UNUSED_PARAM, char **argv)
{
- struct modinfo_env env;
+ const char *field;
char name[MODULE_NAME_LEN];
struct utsname uts;
parser_t *parser;
@@ -129,10 +147,12 @@ int modinfo_main(int argc UNUSED_PARAM, char **argv)
unsigned opts;
unsigned i;
- env.field = NULL;
+ field = NULL;
opt_complementary = "-1"; /* minimum one param */
- opts = getopt32(argv, "fdalvpF:0", &env.field);
- env.tags = opts & OPT_TAGS ? opts & OPT_TAGS : OPT_TAGS;
+ opts = getopt32(argv, "0F:nadlp", &field);
+ /* If no field selected, show all */
+ if (!(opts & (OPT_TAGS|OPT_F)))
+ option_mask32 |= OPT_TAGS;
argv += optind;
uname(&uts);
@@ -146,10 +166,10 @@ int modinfo_main(int argc UNUSED_PARAM, char **argv)
if (colon == NULL)
continue;
*colon = '\0';
- filename2modname(tokens[0], name);
+ filename2modname(bb_basename(tokens[0]), name);
for (i = 0; argv[i]; i++) {
if (fnmatch(argv[i], name, 0) == 0) {
- modinfo(tokens[0], uts.release, &env);
+ modinfo(tokens[0], uts.release, field);
argv[i] = (char *) "";
}
}
@@ -159,7 +179,7 @@ int modinfo_main(int argc UNUSED_PARAM, char **argv)
for (i = 0; argv[i]; i++) {
if (argv[i][0]) {
- modinfo(argv[i], uts.release, &env);
+ modinfo(argv[i], uts.release, field);
}
}
diff --git a/release/src/router/busybox/modutils/modprobe-small.c b/release/src/router/busybox/modutils/modprobe-small.c
index bd855f628c..5936e48cff 100644
--- a/release/src/router/busybox/modutils/modprobe-small.c
+++ b/release/src/router/busybox/modutils/modprobe-small.c
@@ -9,10 +9,10 @@
*/
//applet:IF_MODPROBE_SMALL(APPLET(modprobe, BB_DIR_SBIN, BB_SUID_DROP))
-//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, modprobe))
-//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(insmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, modprobe))
-//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, modprobe))
-//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(rmmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, modprobe))
+//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, depmod))
+//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(insmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, insmod))
+//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, lsmod))
+//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(rmmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, rmmod))
#include "libbb.h"
/* After libbb.h, since it needs sys/types.h on some systems */
@@ -21,7 +21,9 @@
extern int init_module(void *module, unsigned long len, const char *options);
extern int delete_module(const char *module, unsigned flags);
-extern int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret);
+/* linux/include/linux/module.h has limit of 64 chars on module names */
+#undef MODULE_NAME_LEN
+#define MODULE_NAME_LEN 64
#if 1
@@ -43,6 +45,7 @@ typedef struct module_info {
char *pathname;
char *aliases;
char *deps;
+ smallint open_read_failed;
} module_info;
/*
@@ -113,21 +116,21 @@ static char* copy_stringbuf(void)
static char* find_keyword(char *ptr, size_t len, const char *word)
{
- int wlen;
-
if (!ptr) /* happens if xmalloc_open_zipped_read_close cannot read it */
return NULL;
- wlen = strlen(word);
- len -= wlen - 1;
+ len -= strlen(word) - 1;
while ((ssize_t)len > 0) {
char *old = ptr;
+ char *after_word;
+
/* search for the first char in word */
- ptr = memchr(ptr, *word, len);
+ ptr = memchr(ptr, word[0], len);
if (ptr == NULL) /* no occurance left, done */
break;
- if (strncmp(ptr, word, wlen) == 0)
- return ptr + wlen; /* found, return ptr past it */
+ after_word = is_prefixed_with(ptr, word);
+ if (after_word)
+ return after_word; /* found, return ptr past it */
++ptr;
len -= (ptr - old);
}
@@ -143,6 +146,32 @@ static void replace(char *s, char what, char with)
}
}
+static char *filename2modname(const char *filename, char *modname)
+{
+ int i;
+ const char *from;
+
+ // Disabled since otherwise "modprobe dir/name" would work
+ // as if it is "modprobe name". It is unclear why
+ // 'basenamization' was here in the first place.
+ //from = bb_get_last_path_component_nostrip(filename);
+ from = filename;
+ for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++)
+ modname[i] = (from[i] == '-') ? '_' : from[i];
+ modname[i] = '\0';
+
+ return modname;
+}
+
+static int pathname_matches_modname(const char *pathname, const char *modname)
+{
+ int r;
+ char name[MODULE_NAME_LEN];
+ filename2modname(bb_get_last_path_component_nostrip(pathname), name);
+ r = (strcmp(name, modname) == 0);
+ return r;
+}
+
/* Take "word word", return malloced "word",NUL,"word",NUL,NUL */
static char* str_2_list(const char *str)
{
@@ -194,7 +223,8 @@ static int load_module(const char *fname, const char *options)
#endif
}
-static void parse_module(module_info *info, const char *pathname)
+/* Returns !0 if open/read was unsuccessful */
+static int parse_module(module_info *info, const char *pathname)
{
char *module_image;
char *ptr;
@@ -203,6 +233,7 @@ static void parse_module(module_info *info, const char *pathname)
dbg1_error_msg("parse_module('%s')", pathname);
/* Read (possibly compressed) module */
+ errno = 0;
len = 64 * 1024 * 1024; /* 64 Mb at most */
module_image = xmalloc_open_zipped_read_close(pathname, &len);
/* module_image == NULL is ok here, find_keyword handles it */
@@ -212,6 +243,7 @@ static void parse_module(module_info *info, const char *pathname)
reset_stringbuf();
pos = 0;
while (1) {
+ unsigned start = stringbuf_idx;
ptr = find_keyword(module_image + pos, len - pos, "alias=");
if (!ptr) {
ptr = find_keyword(module_image + pos, len - pos, "__ksymtab_");
@@ -228,6 +260,31 @@ static void parse_module(module_info *info, const char *pathname)
}
append(ptr);
appendc(' ');
+ /*
+ * Don't add redundant aliases, such as:
+ * libcrc32c.ko symbol:crc32c symbol:crc32c
+ */
+ if (start) { /* "if we aren't the first alias" */
+ char *found, *last;
+ stringbuf[stringbuf_idx] = '\0';
+ last = stringbuf + start;
+ /*
+ * String at last-1 is " symbol:crc32c "
+ * (with both leading and trailing spaces).
+ */
+ if (strncmp(stringbuf, last, stringbuf_idx - start) == 0)
+ /* First alias matches us */
+ found = stringbuf;
+ else
+ /* Does any other alias match? */
+ found = strstr(stringbuf, last-1);
+ if (found < last-1) {
+ /* There is absolutely the same string before us */
+ dbg2_error_msg("redundant:'%s'", last);
+ stringbuf_idx = start;
+ goto skip;
+ }
+ }
skip:
pos = (ptr - module_image);
}
@@ -244,22 +301,11 @@ static void parse_module(module_info *info, const char *pathname)
dbg2_error_msg("dep:'%s'", ptr);
append(ptr);
}
- info->deps = copy_stringbuf();
-
free(module_image);
-}
+ info->deps = copy_stringbuf();
-static int pathname_matches_modname(const char *pathname, const char *modname)
-{
- const char *fname = bb_get_last_path_component_nostrip(pathname);
- const char *suffix = strrstr(fname, ".ko");
-//TODO: can do without malloc?
- char *name = xstrndup(fname, suffix - fname);
- int r;
- replace(name, '-', '_');
- r = (strcmp(name, modname) == 0);
- free(name);
- return r;
+ info->open_read_failed = (module_image == NULL);
+ return info->open_read_failed;
}
static FAST_FUNC int fileAction(const char *pathname,
@@ -290,7 +336,8 @@ static FAST_FUNC int fileAction(const char *pathname,
dbg1_error_msg("'%s' module name matches", pathname);
module_found_idx = cur;
- parse_module(&modinfo[cur], pathname);
+ if (parse_module(&modinfo[cur], pathname) != 0)
+ return TRUE; /* failed to open/read it, no point in trying loading */
if (!(option_mask32 & OPT_r)) {
if (load_module(pathname, module_load_options) == 0) {
@@ -421,11 +468,12 @@ static void write_out_dep_bb(int fd)
}
}
-static module_info* find_alias(const char *alias)
+static module_info** find_alias(const char *alias)
{
int i;
int dep_bb_fd;
- module_info *result;
+ int infoidx;
+ module_info **infovec;
dbg1_error_msg("find_alias('%s')", alias);
try_again:
@@ -438,7 +486,9 @@ static module_info* find_alias(const char *alias)
if (!modinfo[i].aliases) {
parse_module(&modinfo[i], modinfo[i].pathname);
}
- return &modinfo[i];
+ infovec = xzalloc(2 * sizeof(infovec[0]));
+ infovec[0] = &modinfo[i];
+ return infovec;
}
i++;
}
@@ -451,16 +501,13 @@ static module_info* find_alias(const char *alias)
/* Scan all module bodies, extract modinfo (it contains aliases) */
i = 0;
- result = NULL;
+ infoidx = 0;
+ infovec = NULL;
while (modinfo[i].pathname) {
char *desc, *s;
if (!modinfo[i].aliases) {
parse_module(&modinfo[i], modinfo[i].pathname);
}
- if (result) {
- i++;
- continue;
- }
/* "alias1 symbol:sym1 alias2 symbol:sym2" */
desc = str_2_list(modinfo[i].aliases);
/* Does matching substring exist? */
@@ -472,13 +519,12 @@ static module_info* find_alias(const char *alias)
if (fnmatch(s, alias, 0) == 0) {
dbg1_error_msg("found alias '%s' in module '%s'",
alias, modinfo[i].pathname);
- result = &modinfo[i];
+ infovec = xrealloc_vector(infovec, 1, infoidx);
+ infovec[infoidx++] = &modinfo[i];
break;
}
}
free(desc);
- if (result && dep_bb_fd < 0)
- return result;
i++;
}
@@ -487,30 +533,77 @@ static module_info* find_alias(const char *alias)
write_out_dep_bb(dep_bb_fd);
}
- dbg1_error_msg("find_alias '%s' returns %p", alias, result);
- return result;
+ dbg1_error_msg("find_alias '%s' returns %d results", alias, infoidx);
+ return infovec;
}
#if ENABLE_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED
// TODO: open only once, invent config_rewind()
static int already_loaded(const char *name)
{
- int ret = 0;
- char *s;
- parser_t *parser = config_open2("/proc/modules", xfopen_for_read);
- while (config_read(parser, &s, 1, 1, "# \t", PARSE_NORMAL & ~PARSE_GREEDY)) {
- if (strcmp(s, name) == 0) {
- ret = 1;
- break;
+ int ret;
+ char *line;
+ FILE *fp;
+
+ ret = 5 * 2;
+ again:
+ fp = fopen_for_read("/proc/modules");
+ if (!fp)
+ return 0;
+ while ((line = xmalloc_fgetline(fp)) != NULL) {
+ char *live;
+ char *after_name;
+
+ // Examples from kernel 3.14.6:
+ //pcspkr 12718 0 - Live 0xffffffffa017e000
+ //snd_timer 28690 2 snd_seq,snd_pcm, Live 0xffffffffa025e000
+ //i915 801405 2 - Live 0xffffffffa0096000
+ after_name = is_prefixed_with(line, name);
+ if (!after_name || *after_name != ' ') {
+ free(line);
+ continue;
+ }
+ live = strstr(line, " Live");
+ free(line);
+ if (!live) {
+ /* State can be Unloading, Loading, or Live.
+ * modprobe must not return prematurely if we see "Loading":
+ * it can cause further programs to assume load completed,
+ * but it did not (yet)!
+ * Wait up to 5*20 ms for it to resolve.
+ */
+ ret -= 2;
+ if (ret == 0)
+ break; /* huh? report as "not loaded" */
+ fclose(fp);
+ usleep(20*1000);
+ goto again;
}
+ ret = 1;
+ break;
}
- config_close(parser);
- return ret;
+ fclose(fp);
+
+ return ret & 1;
}
#else
-#define already_loaded(name) is_rmmod
+#define already_loaded(name) 0
#endif
+static int rmmod(const char *filename)
+{
+ int r;
+ char modname[MODULE_NAME_LEN];
+
+ filename2modname(filename, modname);
+ r = delete_module(modname, O_NONBLOCK | O_EXCL);
+ dbg1_error_msg("delete_module('%s', O_NONBLOCK | O_EXCL):%d", modname, r);
+ if (r != 0 && !(option_mask32 & OPT_q)) {
+ bb_perror_msg("remove '%s'", modname);
+ }
+ return r;
+}
+
/*
* Given modules definition and module name (or alias, or symbol)
* load/remove the module respecting dependencies.
@@ -521,23 +614,43 @@ static int already_loaded(const char *name)
#define process_module(a,b) process_module(a)
#define cmdline_options ""
#endif
-static void process_module(char *name, const char *cmdline_options)
+static int process_module(char *name, const char *cmdline_options)
{
char *s, *deps, *options;
+ module_info **infovec;
module_info *info;
- int is_rmmod = (option_mask32 & OPT_r) != 0;
+ int infoidx;
+ int is_remove = (option_mask32 & OPT_r) != 0;
+ int exitcode = EXIT_SUCCESS;
+
dbg1_error_msg("process_module('%s','%s')", name, cmdline_options);
replace(name, '-', '_');
- dbg1_error_msg("already_loaded:%d is_rmmod:%d", already_loaded(name), is_rmmod);
- if (already_loaded(name) != is_rmmod) {
+ dbg1_error_msg("already_loaded:%d is_remove:%d", already_loaded(name), is_remove);
+
+ if (applet_name[0] == 'r') {
+ /* rmmod.
+ * Does not remove dependencies, no need to scan, just remove.
+ * (compat note: this allows and strips .ko suffix)
+ */
+ rmmod(name);
+ return EXIT_SUCCESS;
+ }
+
+ /*
+ * We used to have "is_remove != already_loaded(name)" check here, but
+ * modprobe -r pci:v00008086d00007010sv00000000sd00000000bc01sc01i80
+ * won't unload modules (there are more than one)
+ * which have this alias.
+ */
+ if (!is_remove && already_loaded(name)) {
dbg1_error_msg("nothing to do for '%s'", name);
- return;
+ return EXIT_SUCCESS;
}
options = NULL;
- if (!is_rmmod) {
+ if (!is_remove) {
char *opt_filename = xasprintf("/etc/modules/%s", name);
options = xmalloc_open_read_close(opt_filename, NULL);
if (options)
@@ -560,88 +673,105 @@ static void process_module(char *name, const char *cmdline_options)
if (!module_count) {
/* Scan module directory. This is done only once.
* It will attempt module load, and will exit(EXIT_SUCCESS)
- * on success. */
+ * on success.
+ */
module_found_idx = -1;
recursive_action(".",
ACTION_RECURSE, /* flags */
fileAction, /* file action */
NULL, /* dir action */
name, /* user data */
- 0); /* depth */
+ 0 /* depth */
+ );
dbg1_error_msg("dirscan complete");
- /* Module was not found, or load failed, or is_rmmod */
+ /* Module was not found, or load failed, or is_remove */
if (module_found_idx >= 0) { /* module was found */
- info = &modinfo[module_found_idx];
+ infovec = xzalloc(2 * sizeof(infovec[0]));
+ infovec[0] = &modinfo[module_found_idx];
} else { /* search for alias, not a plain module name */
- info = find_alias(name);
+ infovec = find_alias(name);
}
} else {
- info = find_alias(name);
- }
-
-// Problem here: there can be more than one module
-// for the given alias. For example,
-// "pci:v00008086d00007010sv00000000sd00000000bc01sc01i80" matches
-// ata_piix because it has an alias "pci:v00008086d00007010sv*sd*bc*sc*i*"
-// and ata_generic, it has an alias "alias=pci:v*d*sv*sd*bc01sc01i*"
-// Standard modprobe would load them both.
-// In this code, find_alias() returns only the first matching module.
-
- /* rmmod? unload it by name */
- if (is_rmmod) {
- if (delete_module(name, O_NONBLOCK | O_EXCL) != 0) {
- if (!(option_mask32 & OPT_q))
- bb_perror_msg("remove '%s'", name);
- goto ret;
- }
- /* N.B. we do not stop here -
- * continue to unload modules on which the module depends:
- * "-r --remove: option causes modprobe to remove a module.
- * If the modules it depends on are also unused, modprobe
- * will try to remove them, too." */
+ infovec = find_alias(name);
}
- if (!info) {
+ if (!infovec) {
/* both dirscan and find_alias found nothing */
- if (!is_rmmod && applet_name[0] != 'd') /* it wasn't rmmod or depmod */
+ if (!is_remove && applet_name[0] != 'd') /* it wasn't rmmod or depmod */
bb_error_msg("module '%s' not found", name);
//TODO: _and_die()? or should we continue (un)loading modules listed on cmdline?
goto ret;
}
- /* Iterate thru dependencies, trying to (un)load them */
- deps = str_2_list(info->deps);
- for (s = deps; *s; s += strlen(s) + 1) {
- //if (strcmp(name, s) != 0) // N.B. do loops exist?
- dbg1_error_msg("recurse on dep '%s'", s);
- process_module(s, NULL);
- dbg1_error_msg("recurse on dep '%s' done", s);
- }
- free(deps);
-
- /* modprobe -> load it */
- if (!is_rmmod) {
- if (!options || strstr(options, "blacklist") == NULL) {
- errno = 0;
- if (load_module(info->pathname, options) != 0) {
- if (EEXIST != errno) {
- bb_error_msg("'%s': %s",
- info->pathname,
- moderror(errno));
- } else {
- dbg1_error_msg("'%s': %s",
- info->pathname,
- moderror(errno));
- }
+ /* There can be more than one module for the given alias. For example,
+ * "pci:v00008086d00007010sv00000000sd00000000bc01sc01i80" matches
+ * ata_piix because it has alias "pci:v00008086d00007010sv*sd*bc*sc*i*"
+ * and ata_generic, it has alias "pci:v*d*sv*sd*bc01sc01i*"
+ * Standard modprobe loads them both. We achieve it by returning
+ * a *list* of modinfo pointers from find_alias().
+ */
+
+ /* modprobe -r? unload module(s) */
+ if (is_remove) {
+ infoidx = 0;
+ while ((info = infovec[infoidx++]) != NULL) {
+ int r = rmmod(bb_get_last_path_component_nostrip(info->pathname));
+ if (r != 0) {
+ goto ret; /* error */
}
- } else {
+ }
+ /* modprobe -r: we do not stop here -
+ * continue to unload modules on which the module depends:
+ * "-r --remove: option causes modprobe to remove a module.
+ * If the modules it depends on are also unused, modprobe
+ * will try to remove them, too."
+ */
+ }
+
+ infoidx = 0;
+ while ((info = infovec[infoidx++]) != NULL) {
+ /* Iterate thru dependencies, trying to (un)load them */
+ deps = str_2_list(info->deps);
+ for (s = deps; *s; s += strlen(s) + 1) {
+ //if (strcmp(name, s) != 0) // N.B. do loops exist?
+ dbg1_error_msg("recurse on dep '%s'", s);
+ process_module(s, NULL);
+ dbg1_error_msg("recurse on dep '%s' done", s);
+ }
+ free(deps);
+
+ if (is_remove)
+ continue;
+
+ /* We are modprobe: load it */
+ if (options && strstr(options, "blacklist")) {
dbg1_error_msg("'%s': blacklisted", info->pathname);
+ continue;
+ }
+ if (info->open_read_failed) {
+ /* We already tried it, didn't work. Don't try load again */
+ exitcode = EXIT_FAILURE;
+ continue;
+ }
+ errno = 0;
+ if (load_module(info->pathname, options) != 0) {
+ if (EEXIST != errno) {
+ bb_error_msg("'%s': %s",
+ info->pathname,
+ moderror(errno));
+ } else {
+ dbg1_error_msg("'%s': %s",
+ info->pathname,
+ moderror(errno));
+ }
+ exitcode = EXIT_FAILURE;
}
}
ret:
+ free(infovec);
free(options);
-//TODO: return load attempt result from process_module.
-//If dep didn't load ok, continuing makes little sense.
+
+ return exitcode;
}
#undef cmdline_options
@@ -696,10 +826,6 @@ The following options are useful for people managing distributions:
//usage:#if ENABLE_MODPROBE_SMALL
-//// Note: currently, help system shows modprobe --help text for all aliased cmds
-//// (see APPLET_ODDNAME macro definition).
-//// All other help texts defined below are not used. FIXME?
-
//usage:#define depmod_trivial_usage NOUSAGE_STR
//usage:#define depmod_full_usage ""
@@ -713,7 +839,7 @@ The following options are useful for people managing distributions:
//usage: IF_NOT_FEATURE_2_4_MODULES("FILE ")
//usage: "[SYMBOL=VALUE]..."
//usage:#define insmod_full_usage "\n\n"
-//usage: "Load the specified kernel modules into the kernel"
+//usage: "Load kernel module"
//usage: IF_FEATURE_2_4_MODULES( "\n"
//usage: "\n -f Force module to load into the wrong kernel version"
//usage: "\n -k Make module autoclean-able"
@@ -738,7 +864,7 @@ The following options are useful for people managing distributions:
//usage: "$ rmmod tulip\n"
//usage:#define modprobe_trivial_usage
-//usage: "[-qfwrsv] MODULE [symbol=value]..."
+//usage: "[-qfwrsv] MODULE [SYMBOL=VALUE]..."
//usage:#define modprobe_full_usage "\n\n"
//usage: " -r Remove MODULE (stacks) or do autoclean"
//usage: "\n -q Quiet"
@@ -752,6 +878,7 @@ The following options are useful for people managing distributions:
int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int modprobe_main(int argc UNUSED_PARAM, char **argv)
{
+ int exitcode;
struct utsname uts;
char applet0 = applet_name[0];
IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(char *options;)
@@ -823,10 +950,10 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
}
#if ENABLE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE
- /* If not rmmod, parse possible module options given on command line.
+ /* If not rmmod/-r, parse possible module options given on command line.
* insmod/modprobe takes one module name, the rest are parameters. */
options = NULL;
- if ('r' != applet0) {
+ if (!(option_mask32 & OPT_r)) {
char **arg = argv;
while (*++arg) {
/* Enclose options in quotes */
@@ -837,7 +964,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
}
}
#else
- if ('r' != applet0)
+ if (!(option_mask32 & OPT_r))
argv[1] = NULL;
#endif
@@ -857,20 +984,23 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
bb_error_msg_and_die("can't insert '%s': %s",
*argv, moderror(errno));
}
- return 0;
+ return EXIT_SUCCESS;
}
/* Try to load modprobe.dep.bb */
- load_dep_bb();
+ if ('r' != applet0) { /* not rmmod */
+ load_dep_bb();
+ }
/* Load/remove modules.
- * Only rmmod loops here, modprobe has only argv[0] */
+ * Only rmmod/modprobe -r loops here, insmod/modprobe has only argv[0] */
+ exitcode = EXIT_SUCCESS;
do {
- process_module(*argv, options);
+ exitcode |= process_module(*argv, options);
} while (*++argv);
if (ENABLE_FEATURE_CLEAN_UP) {
IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(free(options);)
}
- return EXIT_SUCCESS;
+ return exitcode;
}
diff --git a/release/src/router/busybox/modutils/modprobe.c b/release/src/router/busybox/modutils/modprobe.c
index 3232013df5..e4dd37e3a7 100644
--- a/release/src/router/busybox/modutils/modprobe.c
+++ b/release/src/router/busybox/modutils/modprobe.c
@@ -15,8 +15,11 @@
#include <sys/utsname.h>
#include <fnmatch.h>
-//#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__)
+#if 1
#define DBG(...) ((void)0)
+#else
+#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__)
+#endif
/* Note that unlike older versions of modules.dep/depmod (busybox and m-i-t),
* we expect the full dependency list to be specified in modules.dep.
@@ -87,7 +90,7 @@
//usage:
//usage:#define modprobe_trivial_usage
//usage: "[-alrqvsD" IF_FEATURE_MODPROBE_BLACKLIST("b") "]"
-//usage: " MODULE [symbol=value]..."
+//usage: " MODULE [SYMBOL=VALUE]..."
//usage:#define modprobe_full_usage "\n\n"
//usage: " -a Load multiple MODULEs"
//usage: "\n -l List (MODULE is a pattern)"
@@ -147,19 +150,6 @@ static const char modprobe_longopts[] ALIGN1 =
#define MODULE_FLAG_FOUND_IN_MODDEP 0x0004
#define MODULE_FLAG_BLACKLISTED 0x0008
-struct module_entry { /* I'll call it ME. */
- unsigned flags;
- char *modname; /* stripped of /path/, .ext and s/-/_/g */
- const char *probed_name; /* verbatim as seen on cmdline */
- char *options; /* options from config files */
- llist_t *realnames; /* strings. if this module is an alias, */
- /* real module name is one of these. */
-//Can there really be more than one? Example from real kernel?
- llist_t *deps; /* strings. modules we depend on */
-};
-
-#define DB_HASH_SIZE 256
-
struct globals {
llist_t *probes; /* MEs of module(s) requested on cmdline */
char *cmdline_mopts; /* module options from cmdline */
@@ -167,11 +157,11 @@ struct globals {
/* bool. "Did we have 'symbol:FOO' requested on cmdline?" */
smallint need_symbols;
struct utsname uts;
- llist_t *db[DB_HASH_SIZE]; /* MEs of all modules ever seen (caching for speed) */
+ module_db db;
} FIX_ALIASING;
#define G (*ptr_to_globals)
#define INIT_G() do { \
- SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
+ SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
} while (0)
@@ -192,46 +182,9 @@ static char *gather_options_str(char *opts, const char *append)
return opts;
}
-/* These three functions called many times, optimizing for speed.
- * Users reported minute-long delays when they runn iptables repeatedly
- * (iptables use modprobe to install needed kernel modules).
- */
-static struct module_entry *helper_get_module(const char *module, int create)
-{
- char modname[MODULE_NAME_LEN];
- struct module_entry *e;
- llist_t *l;
- unsigned i;
- unsigned hash;
-
- filename2modname(module, modname);
-
- hash = 0;
- for (i = 0; modname[i]; i++)
- hash = ((hash << 5) + hash) + modname[i];
- hash %= DB_HASH_SIZE;
-
- for (l = G.db[hash]; l; l = l->link) {
- e = (struct module_entry *) l->data;
- if (strcmp(e->modname, modname) == 0)
- return e;
- }
- if (!create)
- return NULL;
-
- e = xzalloc(sizeof(*e));
- e->modname = xstrdup(modname);
- llist_add_to(&G.db[hash], e);
-
- return e;
-}
-static ALWAYS_INLINE struct module_entry *get_or_add_modentry(const char *module)
+static struct module_entry *get_or_add_modentry(const char *module)
{
- return helper_get_module(module, 1);
-}
-static ALWAYS_INLINE struct module_entry *get_modentry(const char *module)
-{
- return helper_get_module(module, 0);
+ return moddb_get_or_create(&G.db, module);
}
static void add_probe(const char *name)
@@ -252,7 +205,7 @@ static void add_probe(const char *name)
llist_add_to_end(&G.probes, m);
G.num_unresolved_deps++;
if (ENABLE_FEATURE_MODUTILS_SYMBOLS
- && strncmp(m->modname, "symbol:", 7) == 0
+ && is_prefixed_with(m->modname, "symbol:")
) {
G.need_symbols = 1;
}
@@ -261,16 +214,29 @@ static void add_probe(const char *name)
static int FAST_FUNC config_file_action(const char *filename,
struct stat *statbuf UNUSED_PARAM,
void *userdata UNUSED_PARAM,
- int depth UNUSED_PARAM)
+ int depth)
{
char *tokens[3];
parser_t *p;
struct module_entry *m;
int rc = TRUE;
+ const char *base, *ext;
- if (bb_basename(filename)[0] == '.')
+ /* Skip files that begin with a "." */
+ base = bb_basename(filename);
+ if (base[0] == '.')
goto error;
+ /* In dir recursion, skip files that do not end with a ".conf"
+ * depth==0: read_config("modules.{symbols,alias}") must work,
+ * "include FILE_NOT_ENDING_IN_CONF" must work too.
+ */
+ if (depth != 0) {
+ ext = strrchr(base, '.');
+ if (ext == NULL || strcmp(ext + 1, "conf"))
+ goto error;
+ }
+
p = config_open2(filename, fopen_for_read);
if (p == NULL) {
rc = FALSE;
@@ -314,7 +280,7 @@ static int FAST_FUNC config_file_action(const char *filename,
m = get_or_add_modentry(tokens[1]);
m->options = gather_options_str(m->options, tokens[2]);
} else if (strcmp(tokens[0], "include") == 0) {
- /* include <filename> */
+ /* include <filename>/<dirname> (yes, directories also must work) */
read_config(tokens[1]);
} else if (ENABLE_FEATURE_MODPROBE_BLACKLIST
&& strcmp(tokens[0], "blacklist") == 0
@@ -331,7 +297,8 @@ static int FAST_FUNC config_file_action(const char *filename,
static int read_config(const char *path)
{
return recursive_action(path, ACTION_RECURSE | ACTION_QUIET,
- config_file_action, NULL, NULL, 1);
+ config_file_action, NULL, NULL,
+ /*depth:*/ 0);
}
static const char *humanly_readable_name(struct module_entry *m)
@@ -340,27 +307,55 @@ static const char *humanly_readable_name(struct module_entry *m)
return m->probed_name ? m->probed_name : m->modname;
}
+/* Like strsep(&stringp, "\n\t ") but quoted text goes to single token
+ * even if it contains whitespace.
+ */
+static char *strsep_quotes(char **stringp)
+{
+ char *s, *start = *stringp;
+
+ if (!start)
+ return NULL;
+
+ for (s = start; ; s++) {
+ switch (*s) {
+ case '"':
+ s = strchrnul(s + 1, '"'); /* find trailing quote */
+ if (*s != '\0')
+ s++; /* skip trailing quote */
+ /* fall through */
+ case '\0':
+ case '\n':
+ case '\t':
+ case ' ':
+ if (*s != '\0') {
+ *s = '\0';
+ *stringp = s + 1;
+ } else {
+ *stringp = NULL;
+ }
+ return start;
+ }
+ }
+}
+
static char *parse_and_add_kcmdline_module_options(char *options, const char *modulename)
{
char *kcmdline_buf;
char *kcmdline;
char *kptr;
- int len;
kcmdline_buf = xmalloc_open_read_close("/proc/cmdline", NULL);
if (!kcmdline_buf)
return options;
kcmdline = kcmdline_buf;
- len = strlen(modulename);
- while ((kptr = strsep(&kcmdline, "\n\t ")) != NULL) {
- if (strncmp(modulename, kptr, len) != 0)
- continue;
- kptr += len;
- if (*kptr != '.')
+ while ((kptr = strsep_quotes(&kcmdline)) != NULL) {
+ char *after_modulename = is_prefixed_with(kptr, modulename);
+ if (!after_modulename || *after_modulename != '.')
continue;
/* It is "modulename.xxxx" */
- kptr++;
+ kptr = after_modulename + 1;
if (strchr(kptr, '=') != NULL) {
/* It is "modulename.opt=[val]" */
options = gather_options_str(options, kptr);
@@ -417,7 +412,7 @@ static int do_modprobe(struct module_entry *m)
rc = 0;
fn = llist_pop(&m->deps); /* we leak it */
- m2 = get_or_add_modentry(fn);
+ m2 = get_or_add_modentry(bb_get_last_path_component_nostrip(fn));
if (option_mask32 & OPT_REMOVE) {
/* modprobe -r */
@@ -425,9 +420,8 @@ static int do_modprobe(struct module_entry *m)
rc = bb_delete_module(m2->modname, O_NONBLOCK | O_EXCL);
if (rc) {
if (first) {
- bb_error_msg("can't unload module %s: %s",
- humanly_readable_name(m2),
- moderror(rc));
+ bb_perror_msg("can't unload module '%s'",
+ humanly_readable_name(m2));
break;
}
} else {
@@ -499,9 +493,9 @@ static void load_modules_dep(void)
colon = last_char_is(tokens[0], ':');
if (colon == NULL)
continue;
- *colon = 0;
+ *colon = '\0';
- m = get_modentry(tokens[0]);
+ m = moddb_get(&G.db, bb_get_last_path_component_nostrip(tokens[0]));
if (m == NULL)
continue;
@@ -546,7 +540,6 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
if (opt & OPT_LIST_ONLY) {
int i;
- char name[MODULE_NAME_LEN];
char *colon, *tokens[2];
parser_t *p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, xfopen_for_read);
@@ -558,10 +551,14 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
if (!colon)
continue;
*colon = '\0';
- filename2modname(tokens[0], name);
if (!argv[0])
puts(tokens[0]);
else {
+ char name[MODULE_NAME_LEN];
+ filename2modname(
+ bb_get_last_path_component_nostrip(tokens[0]),
+ name
+ );
for (i = 0; argv[i]; i++) {
if (fnmatch(argv[i], name, 0) == 0) {
puts(tokens[0]);
@@ -583,7 +580,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
* autoclean will be removed".
*/
if (bb_delete_module(NULL, O_NONBLOCK | O_EXCL) != 0)
- bb_perror_msg_and_die("rmmod");
+ bb_perror_nomsg_and_die();
}
return EXIT_SUCCESS;
}
@@ -659,5 +656,8 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
} while (me->realnames != NULL);
}
+ if (ENABLE_FEATURE_CLEAN_UP)
+ moddb_free(&G.db);
+
return (rc != 0);
}
diff --git a/release/src/router/busybox/modutils/modutils-24.c b/release/src/router/busybox/modutils/modutils-24.c
index 5e99839192..fe46fc3fdf 100644
--- a/release/src/router/busybox/modutils/modutils-24.c
+++ b/release/src/router/busybox/modutils/modutils-24.c
@@ -793,7 +793,7 @@ static enum obj_reloc
arch_apply_relocation(struct obj_file *f,
struct obj_section *targsec,
/*struct obj_section *symsec,*/
- struct obj_symbol *sym PLTGOT_UNUSED_PARAM,
+ struct obj_symbol *sym,
ElfW(RelM) *rel, ElfW(Addr) v)
{
#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) \
@@ -1762,7 +1762,7 @@ static struct obj_section *arch_xsect_init(struct obj_file *f, const char *name,
#endif
-static void arch_create_got(struct obj_file *f PLTGOT_UNUSED_PARAM)
+static void arch_create_got(struct obj_file *f)
{
#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
struct arch_file *ifile = (struct arch_file *) f;
@@ -2255,7 +2255,7 @@ static int add_symbols_from(struct obj_file *f,
* symbols so they cannot fudge it by adding the prefix on
* their references.
*/
- if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
+ if (is_prefixed_with((char *)s->name, "GPLONLY_")) {
#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
if (gpl)
s->name += 8;
@@ -3824,7 +3824,7 @@ int FAST_FUNC bb_init_module_24(const char *m_filename, const char *options)
/* Load module into memory and unzip if compressed */
image = xmalloc_open_zipped_read_close(m_filename, &image_size);
if (!image)
- return (-errno);
+ return EXIT_FAILURE;
}
m_name = xstrdup(bb_basename(m_filename));
@@ -3855,10 +3855,8 @@ int FAST_FUNC bb_init_module_24(const char *m_filename, const char *options)
"\twhile this kernel is version %s",
flag_force_load ? "warning: " : "",
m_name, m_strversion, uts.release);
- if (!flag_force_load) {
- exit_status = ESRCH;
+ if (!flag_force_load)
goto out;
- }
}
}
#endif
diff --git a/release/src/router/busybox/modutils/modutils.c b/release/src/router/busybox/modutils/modutils.c
index 6187ca72fd..0a056731d2 100644
--- a/release/src/router/busybox/modutils/modutils.c
+++ b/release/src/router/busybox/modutils/modutils.c
@@ -16,6 +16,57 @@ extern int delete_module(const char *module, unsigned int flags);
# define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags)
#endif
+static module_entry *helper_get_module(module_db *db, const char *module, int create)
+{
+ char modname[MODULE_NAME_LEN];
+ struct module_entry *e;
+ unsigned i, hash;
+
+ filename2modname(module, modname);
+
+ hash = 0;
+ for (i = 0; modname[i]; i++)
+ hash = ((hash << 5) + hash) + modname[i];
+ hash %= MODULE_HASH_SIZE;
+
+ for (e = db->buckets[hash]; e; e = e->next)
+ if (strcmp(e->modname, modname) == 0)
+ return e;
+ if (!create)
+ return NULL;
+
+ e = xzalloc(sizeof(*e));
+ e->modname = xstrdup(modname);
+ e->next = db->buckets[hash];
+ db->buckets[hash] = e;
+ IF_DEPMOD(e->dnext = e->dprev = e;)
+
+ return e;
+}
+module_entry* FAST_FUNC moddb_get(module_db *db, const char *module)
+{
+ return helper_get_module(db, module, 0);
+}
+module_entry* FAST_FUNC moddb_get_or_create(module_db *db, const char *module)
+{
+ return helper_get_module(db, module, 1);
+}
+
+void FAST_FUNC moddb_free(module_db *db)
+{
+ module_entry *e, *n;
+ unsigned i;
+
+ for (i = 0; i < MODULE_HASH_SIZE; i++) {
+ for (e = db->buckets[i]; e; e = n) {
+ n = e->next;
+ free(e->name);
+ free(e->modname);
+ free(e);
+ }
+ }
+}
+
void FAST_FUNC replace(char *s, char what, char with)
{
while (*s) {
@@ -47,18 +98,26 @@ int FAST_FUNC string_to_llist(char *string, llist_t **llist, const char *delim)
char* FAST_FUNC filename2modname(const char *filename, char *modname)
{
+ char local_modname[MODULE_NAME_LEN];
int i;
- char *from;
+ const char *from;
if (filename == NULL)
return NULL;
if (modname == NULL)
- modname = xmalloc(MODULE_NAME_LEN);
- from = bb_get_last_path_component_nostrip(filename);
+ modname = local_modname;
+ // Disabled since otherwise "modprobe dir/name" would work
+ // as if it is "modprobe name". It is unclear why
+ // 'basenamization' was here in the first place.
+ //from = bb_get_last_path_component_nostrip(filename);
+ from = filename;
for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++)
modname[i] = (from[i] == '-') ? '_' : from[i];
modname[i] = '\0';
+ if (modname == local_modname)
+ return xstrdup(modname);
+
return modname;
}
@@ -182,6 +241,11 @@ int FAST_FUNC bb_delete_module(const char *module, unsigned int flags)
return errno;
}
+/* Note: not suitable for delete_module() errnos.
+ * For them, probably only EWOULDBLOCK needs explaining:
+ * "Other modules depend on us". So far we don't do such
+ * translation and don't use moderror() for removal errors.
+ */
const char* FAST_FUNC moderror(int err)
{
switch (err) {
diff --git a/release/src/router/busybox/modutils/modutils.h b/release/src/router/busybox/modutils/modutils.h
index c199ebb274..2cbd1448a0 100644
--- a/release/src/router/busybox/modutils/modutils.h
+++ b/release/src/router/busybox/modutils/modutils.h
@@ -16,6 +16,36 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
/* linux/include/linux/module.h has 64, but this is also used
* internally for the maximum alias name length, which can be quite long */
#define MODULE_NAME_LEN 256
+#define MODULE_HASH_SIZE 256
+
+typedef struct module_entry {
+ struct module_entry *next;
+ char *name, *modname;
+ llist_t *deps;
+ IF_MODPROBE(
+ llist_t *realnames;
+ unsigned flags;
+ const char *probed_name; /* verbatim as seen on cmdline */
+ char *options; /* options from config files */
+ )
+ IF_DEPMOD(
+ llist_t *aliases;
+ llist_t *symbols;
+ struct module_entry *dnext, *dprev;
+ )
+} module_entry;
+
+typedef struct module_db {
+ module_entry *buckets[MODULE_HASH_SIZE];
+} module_db;
+
+#define moddb_foreach_module(db, module, index) \
+ for ((index) = 0; (index) < MODULE_HASH_SIZE; (index)++) \
+ for (module = (db)->buckets[index]; module; module = module->next)
+
+module_entry *moddb_get(module_db *db, const char *s) FAST_FUNC;
+module_entry *moddb_get_or_create(module_db *db, const char *s) FAST_FUNC;
+void moddb_free(module_db *db) FAST_FUNC;
void replace(char *s, char what, char with) FAST_FUNC;
char *replace_underscores(char *s) FAST_FUNC;
@@ -68,11 +98,6 @@ const char *moderror(int err) FAST_FUNC;
#if ENABLE_FEATURE_2_4_MODULES
int FAST_FUNC bb_init_module_24(const char *module, const char *options);
-# if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
-# define PLTGOT_UNUSED_PARAM
-# else
-# define PLTGOT_UNUSED_PARAM UNUSED_PARAM
-# endif
#endif
POP_SAVED_FUNCTION_VISIBILITY
diff --git a/release/src/router/busybox/modutils/rmmod.c b/release/src/router/busybox/modutils/rmmod.c
index 4a4a91982c..5c353ef95f 100644
--- a/release/src/router/busybox/modutils/rmmod.c
+++ b/release/src/router/busybox/modutils/rmmod.c
@@ -28,7 +28,7 @@
int rmmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int rmmod_main(int argc UNUSED_PARAM, char **argv)
{
- int n;
+ int n, err;
unsigned flags = O_NONBLOCK | O_EXCL;
/* Parse command line. */
@@ -40,7 +40,8 @@ int rmmod_main(int argc UNUSED_PARAM, char **argv)
flags |= O_TRUNC;
if (n & 4) {
/* Unload _all_ unused modules via NULL delete_module() call */
- if (bb_delete_module(NULL, flags) != 0 && errno != EFAULT)
+ err = bb_delete_module(NULL, flags);
+ if (err && err != EFAULT)
bb_perror_msg_and_die("rmmod");
return EXIT_SUCCESS;
}
@@ -58,9 +59,10 @@ int rmmod_main(int argc UNUSED_PARAM, char **argv)
safe_strncpy(modname, bname, MODULE_NAME_LEN);
else
filename2modname(bname, modname);
- if (bb_delete_module(modname, flags))
- bb_error_msg_and_die("can't unload '%s': %s",
- modname, moderror(errno));
+ err = bb_delete_module(modname, flags);
+ if (err)
+ bb_perror_msg_and_die("can't unload module '%s'",
+ modname);
}
return EXIT_SUCCESS;
diff --git a/release/src/router/busybox/networking/Config.src b/release/src/router/busybox/networking/Config.src
index fb7dca7d49..27c604a316 100644
--- a/release/src/router/busybox/networking/Config.src
+++ b/release/src/router/busybox/networking/Config.src
@@ -82,12 +82,12 @@ config FEATURE_BRCTL_FANCY
This adds about 600 bytes.
config FEATURE_BRCTL_SHOW
- bool "Support show, showmac and showstp"
+ bool "Support show"
default y
depends on BRCTL && FEATURE_BRCTL_FANCY
help
Add support for option which prints the current config:
- showmacs, showstp, show
+ show
config DNSD
bool "dnsd"
@@ -134,6 +134,13 @@ config FEATURE_FTPD_ACCEPT_BROKEN_LIST
it increases the code size by ~40 bytes.
Most other ftp servers seem to behave similar to this.
+config FEATURE_FTP_AUTHENTICATION
+ bool "Enable authentication"
+ default y
+ depends on FTPD
+ help
+ Enable basic system login as seen in telnet etc.
+
config FTPGET
bool "ftpget"
default y
@@ -174,14 +181,6 @@ config FEATURE_HTTPD_RANGES
"Range: bytes=NNN-[MMM]" header. Allows for resuming interrupted
downloads, seeking in multimedia players etc.
-config FEATURE_HTTPD_USE_SENDFILE
- bool "Use sendfile system call"
- default y
- depends on HTTPD
- help
- When enabled, httpd will use the kernel sendfile() function
- instead of read/write loop.
-
config FEATURE_HTTPD_SETUID
bool "Enable -u <user> option"
default y
@@ -498,7 +497,7 @@ config FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
config FEATURE_INETD_RPC
bool "Support RPC services"
- default y
+ default n # very rarely used, and needs Sun RPC support in libc
depends on INETD
select FEATURE_HAVE_RPC
help
@@ -534,6 +533,13 @@ config FEATURE_IP_ROUTE
help
Add support for routing table management to "ip".
+config FEATURE_IP_ROUTE_DIR
+ string "ip route configuration directory"
+ default "/etc/iproute2"
+ depends on FEATURE_IP_ROUTE
+ help
+ Location of the "ip" applet routing configuration.
+
config FEATURE_IP_TUNNEL
bool "ip tunnel"
default y
@@ -548,6 +554,13 @@ config FEATURE_IP_RULE
help
Add support for rule commands to "ip".
+config FEATURE_IP_NEIGH
+ bool "ip neighbor"
+ default y
+ depends on IP
+ help
+ Add support for neighbor commands to "ip".
+
config FEATURE_IP_SHORT_FORMS
bool "Support short forms of ip commands"
default y
@@ -559,6 +572,7 @@ config FEATURE_IP_SHORT_FORMS
ip route -> iproute
ip tunnel -> iptunnel
ip rule -> iprule
+ ip neigh -> ipneigh
Say N unless you desparately need the short form of the ip
object commands.
@@ -598,6 +612,11 @@ config IPRULE
default y
depends on FEATURE_IP_SHORT_FORMS && FEATURE_IP_RULE
+config IPNEIGH
+ bool
+ default y
+ depends on FEATURE_IP_SHORT_FORMS && FEATURE_IP_NEIGH
+
config IPCALC
bool "ipcalc"
default y
@@ -664,6 +683,14 @@ config FEATURE_NTPD_SERVER
Make ntpd usable as a NTP server. If you disable this option
ntpd will be usable only as a NTP client.
+config FEATURE_NTPD_CONF
+ bool "Make ntpd understand /etc/ntp.conf"
+ default y
+ depends on NTPD
+ help
+ Make ntpd look in /etc/ntp.conf for peers. Only "server address"
+ is supported.
+
config PSCAN
bool "pscan"
default y
@@ -743,8 +770,7 @@ config TELNETD
Note that for busybox telnetd to work you need several things:
First of all, your kernel needs:
- UNIX98_PTYS=y
- DEVPTS_FS=y
+ CONFIG_UNIX98_PTYS=y
Next, you need a /dev/pts directory on your root filesystem:
@@ -941,46 +967,6 @@ config VCONFIG
help
Creates, removes, and configures VLAN interfaces
-config WGET
- bool "wget"
- default y
- help
- wget is a utility for non-interactive download of files from HTTP,
- HTTPS, and FTP servers.
-
-config FEATURE_WGET_STATUSBAR
- bool "Enable a nifty process meter (+2k)"
- default y
- depends on WGET
- help
- Enable the transfer progress bar for wget transfers.
-
-config FEATURE_WGET_AUTHENTICATION
- bool "Enable HTTP authentication"
- default y
- depends on WGET
- help
- Support authenticated HTTP transfers.
-
-config FEATURE_WGET_LONG_OPTIONS
- bool "Enable long options"
- default y
- depends on WGET && LONG_OPTS
- help
- Support long options for the wget applet.
-
-config FEATURE_WGET_TIMEOUT
- bool "Enable read timeout option -T SEC"
- default y
- depends on WGET
- help
- Supports network read timeout for wget, so that wget will give
- up and timeout when reading network data, through the -T command
- line option. Currently only network data read timeout is
- supported (i.e., timeout is not applied to the DNS nor TCP
- connection initialization). When FEATURE_WGET_LONG_OPTIONS is
- also enabled, the --timeout option will work in addition to -T.
-
config ZCIP
bool "zcip"
default y
diff --git a/release/src/router/busybox/networking/Kbuild.src b/release/src/router/busybox/networking/Kbuild.src
index 944f27be10..79f54824b3 100644
--- a/release/src/router/busybox/networking/Kbuild.src
+++ b/release/src/router/busybox/networking/Kbuild.src
@@ -41,7 +41,6 @@ lib-$(CONFIG_TFTPD) += tftp.o
lib-$(CONFIG_TRACEROUTE) += traceroute.o
lib-$(CONFIG_TUNCTL) += tunctl.o
lib-$(CONFIG_VCONFIG) += vconfig.o
-lib-$(CONFIG_WGET) += wget.o
lib-$(CONFIG_ZCIP) += zcip.o
lib-$(CONFIG_TCPSVD) += tcpudp.o tcpudp_perhost.o
diff --git a/release/src/router/busybox/networking/arp.c b/release/src/router/busybox/networking/arp.c
index 696c402e01..9381eb53a6 100644
--- a/release/src/router/busybox/networking/arp.c
+++ b/release/src/router/busybox/networking/arp.c
@@ -22,16 +22,17 @@
//usage:#define arp_full_usage "\n\n"
//usage: "Manipulate ARP cache\n"
//usage: "\n -a Display (all) hosts"
-//usage: "\n -s Set new ARP entry"
-//usage: "\n -d Delete a specified entry"
+//usage: "\n -d Delete ARP entry"
+//usage: "\n -s Set new entry"
//usage: "\n -v Verbose"
//usage: "\n -n Don't resolve names"
//usage: "\n -i IF Network interface"
-//usage: "\n -D Read <hwaddr> from given device"
+//usage: "\n -D Read HWADDR from IFACE"
//usage: "\n -A,-p AF Protocol family"
//usage: "\n -H HWTYPE Hardware address type"
#include "libbb.h"
+#include "common_bufsiz.h"
#include "inet_common.h"
#include <arpa/inet.h>
@@ -68,14 +69,14 @@ struct globals {
const struct hwtype *hw; /* current hardware type */
const char *device; /* current device */
smallint hw_set; /* flag if hw-type was set (-H) */
-
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define ap (G.ap )
#define hw (G.hw )
#define device (G.device )
#define hw_set (G.hw_set )
#define INIT_G() do { \
+ setup_common_bufsiz(); \
device = ""; \
} while (0)
@@ -213,16 +214,15 @@ static int arp_del(char **args)
}
/* Get the hardware address to a specified interface name */
-static void arp_getdevhw(char *ifname, struct sockaddr *sa,
- const struct hwtype *hwt)
+static void arp_getdevhw(char *ifname, struct sockaddr *sa)
{
struct ifreq ifr;
const struct hwtype *xhw;
strcpy(ifr.ifr_name, ifname);
ioctl_or_perror_and_die(sockfd, SIOCGIFHWADDR, &ifr,
- "cant get HW-Address for '%s'", ifname);
- if (hwt && (ifr.ifr_hwaddr.sa_family != hw->type)) {
+ "can't get HW-Address for '%s'", ifname);
+ if (hw_set && (ifr.ifr_hwaddr.sa_family != hw->type)) {
bb_error_msg_and_die("protocol type mismatch");
}
memcpy(sa, &(ifr.ifr_hwaddr), sizeof(struct sockaddr));
@@ -233,8 +233,8 @@ static void arp_getdevhw(char *ifname, struct sockaddr *sa,
xhw = get_hwntype(-1);
}
bb_error_msg("device '%s' has HW address %s '%s'",
- ifname, xhw->name,
- xhw->print((unsigned char *) &ifr.ifr_hwaddr.sa_data));
+ ifname, xhw->name,
+ xhw->print((unsigned char *) &ifr.ifr_hwaddr.sa_data));
}
}
@@ -261,7 +261,7 @@ static int arp_set(char **args)
bb_error_msg_and_die("need hardware address");
}
if (option_mask32 & ARP_OPT_D) {
- arp_getdevhw(*args++, &req.arp_ha, hw_set ? hw : NULL);
+ arp_getdevhw(*args++, &req.arp_ha);
} else {
if (hw->input(*args++, &req.arp_ha) < 0) {
bb_error_msg_and_die("invalid hardware address");
@@ -345,7 +345,7 @@ static int arp_set(char **args)
/* Print the contents of an ARP request block. */
static void
arp_disp(const char *name, char *ip, int type, int arp_flags,
- char *hwa, char *mask, char *dev)
+ char *hwa, char *mask, char *dev)
{
static const int arp_masks[] = {
ATF_PERM, ATF_PUBL,
@@ -428,7 +428,7 @@ static int arp_show(char *name)
/* All these strings can't overflow
* because fgets above reads limited amount of data */
num = sscanf(line, "%s 0x%x 0x%x %s %s %s\n",
- ip, &type, &flags, hwa, mask, dev);
+ ip, &type, &flags, hwa, mask, dev);
if (num < 4)
break;
@@ -460,12 +460,12 @@ static int arp_show(char *name)
arp_disp(hostname, ip, type, flags, hwa, mask, dev);
}
if (option_mask32 & ARP_OPT_v)
- printf("Entries: %d\tSkipped: %d\tFound: %d\n",
- entries, entries - shown, shown);
+ printf("Entries: %u\tSkipped: %u\tFound: %u\n",
+ entries, entries - shown, shown);
if (!shown) {
if (hw_set || host || device[0])
- printf("No match found in %d entries\n", entries);
+ printf("No match found in %u entries\n", entries);
}
if (ENABLE_FEATURE_CLEAN_UP) {
free((char*)host);
@@ -477,28 +477,33 @@ static int arp_show(char *name)
int arp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int arp_main(int argc UNUSED_PARAM, char **argv)
{
- const char *hw_type = "ether";
+ const char *hw_type;
const char *protocol;
unsigned opts;
INIT_G();
xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), sockfd);
+
ap = get_aftype(DFLT_AF);
- if (!ap)
- bb_error_msg_and_die("%s: %s not supported", DFLT_AF, "address family");
+ /* Defaults are always supported */
+ //if (!ap)
+ // bb_error_msg_and_die("%s: %s not supported", DFLT_AF, "address family");
+ hw = get_hwtype(DFLT_HW);
+ //if (!hw)
+ // bb_error_msg_and_die("%s: %s not supported", DFLT_HW, "hardware type");
opts = getopt32(argv, "A:p:H:t:i:adnDsv", &protocol, &protocol,
&hw_type, &hw_type, &device);
argv += optind;
if (opts & (ARP_OPT_A | ARP_OPT_p)) {
ap = get_aftype(protocol);
- if (ap == NULL)
+ if (!ap)
bb_error_msg_and_die("%s: unknown %s", protocol, "address family");
}
- if (opts & (ARP_OPT_A | ARP_OPT_p)) {
+ if (opts & (ARP_OPT_H | ARP_OPT_t)) {
hw = get_hwtype(hw_type);
- if (hw == NULL)
+ if (!hw)
bb_error_msg_and_die("%s: unknown %s", hw_type, "hardware type");
hw_set = 1;
}
@@ -507,17 +512,9 @@ int arp_main(int argc UNUSED_PARAM, char **argv)
if (ap->af != AF_INET) {
bb_error_msg_and_die("%s: kernel only supports 'inet'", ap->name);
}
-
- /* If no hw type specified get default */
- if (!hw) {
- hw = get_hwtype(DFLT_HW);
- if (!hw)
- bb_error_msg_and_die("%s: %s not supported", DFLT_HW, "hardware type");
- }
-
if (hw->alen <= 0) {
bb_error_msg_and_die("%s: %s without ARP support",
- hw->name, "hardware type");
+ hw->name, "hardware type");
}
/* Now see what we have to do here... */
@@ -528,6 +525,7 @@ int arp_main(int argc UNUSED_PARAM, char **argv)
return arp_set(argv);
return arp_del(argv);
}
+
//if (opts & ARP_OPT_a) - default
return arp_show(argv[0]);
}
diff --git a/release/src/router/busybox/networking/arping.c b/release/src/router/busybox/networking/arping.c
index a4421edcba..4f207eaa51 100644
--- a/release/src/router/busybox/networking/arping.c
+++ b/release/src/router/busybox/networking/arping.c
@@ -13,11 +13,11 @@
//usage: "\n -f Quit on first ARP reply"
//usage: "\n -q Quiet"
//usage: "\n -b Keep broadcasting, don't go unicast"
-//usage: "\n -D Duplicated address detection mode"
+//usage: "\n -D Exit with 1 if DST_IP replies"
//usage: "\n -U Unsolicited ARP mode, update your neighbors"
//usage: "\n -A ARP answer mode, update your neighbors"
//usage: "\n -c N Stop after sending N ARP requests"
-//usage: "\n -w TIMEOUT Time to wait for ARP reply, seconds"
+//usage: "\n -w TIMEOUT Seconds to wait for ARP reply"
//usage: "\n -I IFACE Interface to use (default eth0)"
//usage: "\n -s SRC_IP Sender IP address"
//usage: "\n DST_IP Target IP address"
@@ -28,6 +28,7 @@
#include <netpacket/packet.h>
#include "libbb.h"
+#include "common_bufsiz.h"
/* We don't expect to see 1000+ seconds delay, unsigned is enough */
#define MONOTONIC_US() ((unsigned)monotonic_us())
@@ -60,7 +61,7 @@ struct globals {
unsigned brd_recv;
unsigned req_recv;
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define src (G.src )
#define dst (G.dst )
#define me (G.me )
@@ -76,6 +77,7 @@ struct globals {
#define brd_recv (G.brd_recv )
#define req_recv (G.req_recv )
#define INIT_G() do { \
+ setup_common_bufsiz(); \
count = -1; \
} while (0)
@@ -162,7 +164,7 @@ static void catcher(void)
alarm(1);
}
-static bool recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
+static void recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
{
struct arphdr *ah = (struct arphdr *) buf;
unsigned char *p = (unsigned char *) (ah + 1);
@@ -181,33 +183,33 @@ static bool recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
if (FROM->sll_pkttype != PACKET_HOST
&& FROM->sll_pkttype != PACKET_BROADCAST
&& FROM->sll_pkttype != PACKET_MULTICAST)
- return false;
+ return;
/* Only these types are recognized */
if (ah->ar_op != htons(ARPOP_REQUEST) && ah->ar_op != htons(ARPOP_REPLY))
- return false;
+ return;
/* ARPHRD check and this darned FDDI hack here :-( */
if (ah->ar_hrd != htons(FROM->sll_hatype)
&& (FROM->sll_hatype != ARPHRD_FDDI || ah->ar_hrd != htons(ARPHRD_ETHER)))
- return false;
+ return;
/* Protocol must be IP. */
if (ah->ar_pro != htons(ETH_P_IP)
|| (ah->ar_pln != 4)
|| (ah->ar_hln != me.sll_halen)
|| (len < (int)(sizeof(*ah) + 2 * (4 + ah->ar_hln))))
- return false;
+ return;
move_from_unaligned32(src_ip.s_addr, p + ah->ar_hln);
move_from_unaligned32(dst_ip.s_addr, p + ah->ar_hln + 4 + ah->ar_hln);
if (dst.s_addr != src_ip.s_addr)
- return false;
+ return;
if (!(option_mask32 & DAD)) {
if ((src.s_addr != dst_ip.s_addr)
- || (memcmp(p + ah->ar_hln + 4, &me.sll_addr, ah->ar_hln)))
- return false;
+ || (memcmp(p + ah->ar_hln + 4, &me.sll_addr, ah->ar_hln)))
+ return;
} else {
/* DAD packet was:
src_ip = 0 (or some src)
@@ -224,32 +226,35 @@ static bool recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
*/
if ((memcmp(p, &me.sll_addr, me.sll_halen) == 0)
|| (src.s_addr && src.s_addr != dst_ip.s_addr))
- return false;
+ return;
}
if (!(option_mask32 & QUIET)) {
int s_printed = 0;
- printf("%scast re%s from %s [%s]",
+ printf("%scast re%s from %s [%02x:%02x:%02x:%02x:%02x:%02x]",
FROM->sll_pkttype == PACKET_HOST ? "Uni" : "Broad",
ah->ar_op == htons(ARPOP_REPLY) ? "ply" : "quest",
inet_ntoa(src_ip),
- ether_ntoa((struct ether_addr *) p));
+ p[0], p[1], p[2], p[3], p[4], p[5]
+ );
if (dst_ip.s_addr != src.s_addr) {
printf("for %s ", inet_ntoa(dst_ip));
s_printed = 1;
}
if (memcmp(p + ah->ar_hln + 4, me.sll_addr, ah->ar_hln)) {
+ unsigned char *pp = p + ah->ar_hln + 4;
if (!s_printed)
printf("for ");
- printf("[%s]",
- ether_ntoa((struct ether_addr *) p + ah->ar_hln + 4));
+ printf("[%02x:%02x:%02x:%02x:%02x:%02x]",
+ pp[0], pp[1], pp[2], pp[3], pp[4], pp[5]
+ );
}
if (last) {
unsigned diff = MONOTONIC_US() - last;
printf(" %u.%03ums\n", diff / 1000, diff % 1000);
} else {
- printf(" UNSOLICITED?\n");
+ puts(" UNSOLICITED?");
}
fflush_all();
}
@@ -264,7 +269,6 @@ static bool recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
memcpy(he.sll_addr, p, me.sll_halen);
option_mask32 |= UNICASTING;
}
- return true;
}
int arping_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -284,7 +288,6 @@ int arping_main(int argc UNUSED_PARAM, char **argv)
// Need to remove SUID_NEVER from applets.h for this to work
//xsetuid(getuid());
- err_str = xasprintf("interface %s %%s", device);
{
unsigned opt;
char *str_timeout;
@@ -302,7 +305,7 @@ int arping_main(int argc UNUSED_PARAM, char **argv)
}
target = argv[optind];
-
+ err_str = xasprintf("interface %s %%s", device);
xfunc_error_retval = 2;
{
@@ -359,8 +362,8 @@ int arping_main(int argc UNUSED_PARAM, char **argv)
saddr.sin_port = htons(1025);
saddr.sin_addr = dst;
- if (setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, &const_int_1, sizeof(const_int_1)) == -1)
- bb_perror_msg("setsockopt(SO_DONTROUTE)");
+ if (setsockopt_SOL_SOCKET_1(probe_fd, SO_DONTROUTE) != 0)
+ bb_perror_msg("setsockopt(%s)", "SO_DONTROUTE");
xconnect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr));
getsockname(probe_fd, (struct sockaddr *) &saddr, &alen);
//never happens:
diff --git a/release/src/router/busybox/networking/brctl.c b/release/src/router/busybox/networking/brctl.c
index 19f474fce3..b7320966a8 100644
--- a/release/src/router/busybox/networking/brctl.c
+++ b/release/src/router/busybox/networking/brctl.c
@@ -64,10 +64,60 @@
#define BRCTL_USE_INTERNAL 1
#if ENABLE_FEATURE_BRCTL_FANCY
-# include <linux/if_bridge.h>
+/* #include <linux/if_bridge.h>
+ * breaks on musl: we already included netinet/in.h in libbb.h,
+ * if we include <linux/if_bridge.h> here, we get this:
+ * In file included from /usr/include/linux/if_bridge.h:18,
+ * from networking/brctl.c:67:
+ * /usr/include/linux/in6.h:32: error: redefinition of 'struct in6_addr'
+ * /usr/include/linux/in6.h:49: error: redefinition of 'struct sockaddr_in6'
+ * /usr/include/linux/in6.h:59: error: redefinition of 'struct ipv6_mreq'
+ */
+/* From <linux/if_bridge.h> */
+#define BRCTL_GET_VERSION 0
+#define BRCTL_GET_BRIDGES 1
+#define BRCTL_ADD_BRIDGE 2
+#define BRCTL_DEL_BRIDGE 3
+#define BRCTL_ADD_IF 4
+#define BRCTL_DEL_IF 5
+#define BRCTL_GET_BRIDGE_INFO 6
+#define BRCTL_GET_PORT_LIST 7
+#define BRCTL_SET_BRIDGE_FORWARD_DELAY 8
+#define BRCTL_SET_BRIDGE_HELLO_TIME 9
+#define BRCTL_SET_BRIDGE_MAX_AGE 10
+#define BRCTL_SET_AGEING_TIME 11
+#define BRCTL_SET_GC_INTERVAL 12
+#define BRCTL_GET_PORT_INFO 13
+#define BRCTL_SET_BRIDGE_STP_STATE 14
+#define BRCTL_SET_BRIDGE_PRIORITY 15
+#define BRCTL_SET_PORT_PRIORITY 16
+#define BRCTL_SET_PATH_COST 17
+#define BRCTL_GET_FDB_ENTRIES 18
+struct __bridge_info {
+ uint64_t designated_root;
+ uint64_t bridge_id;
+ uint32_t root_path_cost;
+ uint32_t max_age;
+ uint32_t hello_time;
+ uint32_t forward_delay;
+ uint32_t bridge_max_age;
+ uint32_t bridge_hello_time;
+ uint32_t bridge_forward_delay;
+ uint8_t topology_change;
+ uint8_t topology_change_detected;
+ uint8_t root_port;
+ uint8_t stp_enabled;
+ uint32_t ageing_time;
+ uint32_t gc_interval;
+ uint32_t hello_timer_value;
+ uint32_t tcn_timer_value;
+ uint32_t topology_change_timer_value;
+ uint32_t gc_timer_value;
+};
+/* end <linux/if_bridge.h> */
/* FIXME: These 4 funcs are not really clean and could be improved */
-static ALWAYS_INLINE void strtotimeval(struct timeval *tv,
+static ALWAYS_INLINE void bb_strtotimeval(struct timeval *tv,
const char *time_str)
{
double secs;
@@ -78,7 +128,7 @@ static ALWAYS_INLINE void strtotimeval(struct timeval *tv,
# else
if (sscanf(time_str, "%lf", &secs) != 1)
# endif
- bb_error_msg_and_die(bb_msg_invalid_arg, time_str, "timespec");
+ bb_error_msg_and_die(bb_msg_invalid_arg_to, time_str, "timespec");
tv->tv_sec = secs;
tv->tv_usec = 1000000 * (secs - tv->tv_sec);
}
@@ -104,7 +154,7 @@ static void jiffies_to_tv(struct timeval *tv, unsigned long jiffies)
static unsigned long str_to_jiffies(const char *time_str)
{
struct timeval tv;
- strtotimeval(&tv, time_str);
+ bb_strtotimeval(&tv, time_str);
return tv_to_jiffies(&tv);
}
@@ -129,15 +179,15 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
"setageing\0" "setfd\0" "sethello\0" "setmaxage\0"
"setpathcost\0" "setportprio\0" "setbridgeprio\0"
)
- IF_FEATURE_BRCTL_SHOW("showmacs\0" "show\0");
+ IF_FEATURE_BRCTL_SHOW("show\0");
enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif
IF_FEATURE_BRCTL_FANCY(,
- ARG_stp,
- ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage,
- ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio
+ ARG_stp,
+ ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage,
+ ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio
)
- IF_FEATURE_BRCTL_SHOW(, ARG_showmacs, ARG_show)
+ IF_FEATURE_BRCTL_SHOW(, ARG_show)
};
int fd;
@@ -155,7 +205,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
key = index_in_strings(keywords, *argv);
if (key == -1) /* no match found in keywords array, bail out. */
- bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
+ bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name);
argv++;
fd = xsocket(AF_INET, SOCK_STREAM, 0);
@@ -167,7 +217,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
arm_ioctl(args, BRCTL_GET_BRIDGES,
(unsigned long) bridx, MAX_PORTS);
num = xioctl(fd, SIOCGIFBR, args);
- printf("bridge name\tbridge id\t\tSTP enabled\tinterfaces\n");
+ puts("bridge name\tbridge id\t\tSTP enabled\tinterfaces");
for (i = 0; i < num; i++) {
char ifname[IFNAMSIZ];
int j, tabs;
@@ -186,7 +236,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
/* print bridge id */
x = (unsigned char *) &bi.bridge_id;
for (j = 0; j < 8; j++) {
- printf("%.2x", x[j]);
+ printf("%02x", x[j]);
if (j == 1)
bb_putchar('.');
}
@@ -249,7 +299,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
"1\0" "on\0" "y\0" "yes\0"; /* 4 .. 7 */
int onoff = index_in_strings(no_yes, *argv);
if (onoff < 0)
- bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
+ bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name);
onoff = (unsigned)onoff / 4;
arm_ioctl(args, BRCTL_SET_BRIDGE_STP_STATE, onoff, 0);
goto fire;
@@ -282,10 +332,10 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
port = if_nametoindex(*argv++);
if (!port)
- bb_error_msg_and_die(bb_msg_invalid_arg, *argv, "port");
+ bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, "port");
memset(ifidx, 0, sizeof ifidx);
arm_ioctl(args, BRCTL_GET_PORT_LIST, (unsigned long)ifidx,
- MAX_PORTS);
+ MAX_PORTS);
xioctl(fd, SIOCDEVPRIVATE, &ifr);
for (i = 0; i < MAX_PORTS; i++) {
if (ifidx[i] == port) {
diff --git a/release/src/router/busybox/networking/dnsd.c b/release/src/router/busybox/networking/dnsd.c
index fe98400f7d..923ad6bc6b 100644
--- a/release/src/router/busybox/networking/dnsd.c
+++ b/release/src/router/busybox/networking/dnsd.c
@@ -194,7 +194,7 @@ static char *table_lookup(struct dns_entry *d,
if ((len != 1 || d->name[1] != '*')
/* we assume (do not check) that query_string
* ends in ".in-addr.arpa" */
- && strncmp(d->rip, query_string, strlen(d->rip)) == 0
+ && is_prefixed_with(query_string, d->rip)
) {
#if DEBUG
fprintf(stderr, "Found name:%s\n", d->name);
diff --git a/release/src/router/busybox/networking/ether-wake.c b/release/src/router/busybox/networking/ether-wake.c
index 6a88279f4e..c38547dda4 100644
--- a/release/src/router/busybox/networking/ether-wake.c
+++ b/release/src/router/busybox/networking/ether-wake.c
@@ -49,9 +49,9 @@
* Copyright 1999-2003 Donald Becker and Scyld Computing Corporation.
*
* The author may be reached as becker@scyld, or C/O
- * Scyld Computing Corporation
- * 914 Bay Ridge Road, Suite 220
- * Annapolis MD 21403
+ * Scyld Computing Corporation
+ * 914 Bay Ridge Road, Suite 220
+ * Annapolis MD 21403
*
* Notes:
* On some systems dropping root capability allows the process to be
@@ -62,17 +62,17 @@
* An alternative to needing 'root' is using a UDP broadcast socket, however
* doing so only works with adapters configured for unicast+broadcast Rx
* filter. That configuration consumes more power.
-*/
+ */
//usage:#define ether_wake_trivial_usage
-//usage: "[-b] [-i iface] [-p aa:bb:cc:dd[:ee:ff]] MAC"
+//usage: "[-b] [-i IFACE] [-p aa:bb:cc:dd[:ee:ff]/a.b.c.d] MAC"
//usage:#define ether_wake_full_usage "\n\n"
//usage: "Send a magic packet to wake up sleeping machines.\n"
//usage: "MAC must be a station address (00:11:22:33:44:55) or\n"
//usage: "a hostname with a known 'ethers' entry.\n"
-//usage: "\n -b Send wake-up packet to the broadcast address"
-//usage: "\n -i iface Interface to use (default eth0)"
-//usage: "\n -p pass Append four or six byte password PW to the packet"
+//usage: "\n -b Broadcast the packet"
+//usage: "\n -i IFACE Interface to use (default eth0)"
+//usage: "\n -p PASSWORD Append four or six byte PASSWORD to the packet"
#include "libbb.h"
#include <netpacket/packet.h>
@@ -113,7 +113,7 @@ void bb_debug_dump_packet(unsigned char *outpack, int pktsize)
* Host name
* IP address string
* MAC address string
-*/
+ */
static void get_dest_addr(const char *hostid, struct ether_addr *eaddr)
{
struct ether_addr *eap;
@@ -121,10 +121,7 @@ static void get_dest_addr(const char *hostid, struct ether_addr *eaddr)
eap = ether_aton_r(hostid, eaddr);
if (eap) {
bb_debug_msg("The target station address is %s\n\n", ether_ntoa(eap));
-#if !defined(__UCLIBC_MAJOR__) \
- || __UCLIBC_MAJOR__ > 0 \
- || __UCLIBC_MINOR__ > 9 \
- || (__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ >= 30)
+#if !defined(__UCLIBC__) || UCLIBC_VERSION >= KERNEL_VERSION(0, 9, 30)
} else if (ether_hostton(hostid, eaddr) == 0) {
bb_debug_msg("Station address for hostname %s is %s\n\n", hostid, ether_ntoa(eaddr));
#endif
@@ -133,7 +130,8 @@ static void get_dest_addr(const char *hostid, struct ether_addr *eaddr)
}
}
-static int get_fill(unsigned char *pkt, struct ether_addr *eaddr, int broadcast)
+#define PKT_HEADER_SIZE (20 + 16*6)
+static int fill_pkt_header(unsigned char *pkt, struct ether_addr *eaddr, int broadcast)
{
int i;
unsigned char *station_addr = eaddr->ether_addr_octet;
@@ -156,7 +154,7 @@ static int get_fill(unsigned char *pkt, struct ether_addr *eaddr, int broadcast)
memcpy(pkt, station_addr, 6); /* 20,26,32,... */
}
- return 20 + 16*6; /* length of packet */
+ return PKT_HEADER_SIZE; /* length of packet */
}
static int get_wol_pw(const char *ethoptarg, unsigned char *wol_passwd)
@@ -198,7 +196,7 @@ int ether_wake_main(int argc UNUSED_PARAM, char **argv)
int wol_passwd_sz = 0;
int s; /* Raw socket */
int pktsize;
- unsigned char outpack[1000];
+ unsigned char outpack[PKT_HEADER_SIZE + 6 /* max passwd size */ + 16 /* paranoia */];
struct ether_addr eaddr;
struct whereto_t whereto; /* who to wake up */
@@ -220,7 +218,7 @@ int ether_wake_main(int argc UNUSED_PARAM, char **argv)
get_dest_addr(argv[optind], &eaddr);
/* fill out the header of the packet */
- pktsize = get_fill(outpack, &eaddr, flags /* & 1 OPT_BROADCAST */);
+ pktsize = fill_pkt_header(outpack, &eaddr, flags /* & 1 OPT_BROADCAST */);
bb_debug_dump_packet(outpack, pktsize);
@@ -238,9 +236,9 @@ int ether_wake_main(int argc UNUSED_PARAM, char **argv)
{
unsigned char *hwaddr = if_hwaddr.ifr_hwaddr.sa_data;
printf("The hardware address (SIOCGIFHWADDR) of %s is type %d "
- "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n\n", ifname,
- if_hwaddr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1],
- hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
+ "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n\n", ifname,
+ if_hwaddr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1],
+ hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
}
# endif
}
diff --git a/release/src/router/busybox/networking/ftpd.c b/release/src/router/busybox/networking/ftpd.c
index 1c97df564f..360d1e6be6 100644
--- a/release/src/router/busybox/networking/ftpd.c
+++ b/release/src/router/busybox/networking/ftpd.c
@@ -29,6 +29,7 @@
//usage: "\n DIR Change root to this directory"
#include "libbb.h"
+#include "common_bufsiz.h"
#include <syslog.h>
#include <netinet/tcp.h>
@@ -123,8 +124,9 @@ struct globals {
char msg_ok [(sizeof("NNN " MSG_OK ) + 3) & 0xfffc];
char msg_err[(sizeof("NNN " MSG_ERR) + 3) & 0xfffc];
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define INIT_G() do { \
+ setup_common_bufsiz(); \
/* Moved to main */ \
/*strcpy(G.msg_ok + 4, MSG_OK );*/ \
/*strcpy(G.msg_err + 4, MSG_ERR);*/ \
@@ -377,7 +379,7 @@ ftpdataio_get_pasv_fd(void)
return remote_fd;
}
- setsockopt(remote_fd, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));
+ setsockopt_keepalive(remote_fd);
return remote_fd;
}
@@ -622,14 +624,8 @@ popen_ls(const char *opt)
pid_t pid;
argv[0] = "ftpd";
- argv[1] = opt; /* "-l" or "-1" */
-#if BB_MMU
+ argv[1] = opt; /* "-lA" or "-1A" */
argv[2] = "--";
-#else
- /* NOMMU ftpd ls helper chdirs to argv[2],
- * preventing peer from seeing real root. */
- argv[2] = xrealloc_getcwd_or_warn(NULL);
-#endif
argv[3] = G.ftp_arg;
argv[4] = NULL;
@@ -650,17 +646,10 @@ popen_ls(const char *opt)
/*fflush_all(); - so far we dont use stdio on output */
pid = BB_MMU ? xfork() : xvfork();
if (pid == 0) {
- /* child */
#if !BB_MMU
- /* On NOMMU, we want to execute a child - copy of ourself.
- * In chroot we usually can't do it. Thus we chdir
- * out of the chroot back to original root,
- * and (see later below) execute bb_busybox_exec_path
- * relative to current directory */
- if (fchdir(G.root_fd) != 0)
- _exit(127);
- /*close(G.root_fd); - close_on_exec_on() took care of this */
+ int cur_fd;
#endif
+ /* child */
/* NB: close _first_, then move fd! */
close(outfd.rd);
xmove_fd(outfd.wr, STDOUT_FILENO);
@@ -674,19 +663,26 @@ popen_ls(const char *opt)
/* memset(&G, 0, sizeof(G)); - ls_main does it */
exit(ls_main(ARRAY_SIZE(argv) - 1, (char**) argv));
#else
- /* + 1: we must use relative path here if in chroot.
- * For example, execv("/proc/self/exe") will fail, since
- * it looks for "/proc/self/exe" _relative to chroot!_ */
- execv(bb_busybox_exec_path + 1, (char**) argv);
+ cur_fd = xopen(".", O_RDONLY | O_DIRECTORY);
+ /* On NOMMU, we want to execute a child - copy of ourself
+ * in order to unblock parent after vfork.
+ * In chroot we usually can't re-exec. Thus we escape
+ * out of the chroot back to original root.
+ */
+ if (G.root_fd >= 0) {
+ if (fchdir(G.root_fd) != 0 || chroot(".") != 0)
+ _exit(127);
+ /*close(G.root_fd); - close_on_exec_on() took care of this */
+ }
+ /* Child expects directory to list on fd #3 */
+ xmove_fd(cur_fd, 3);
+ execv(bb_busybox_exec_path, (char**) argv);
_exit(127);
#endif
}
/* parent */
close(outfd.wr);
-#if !BB_MMU
- free((char*)argv[2]);
-#endif
return outfd.rd;
}
@@ -705,10 +701,9 @@ handle_dir_common(int opts)
if (!(opts & USE_CTRL_CONN) && !port_or_pasv_was_seen())
return; /* port_or_pasv_was_seen emitted error response */
- /* -n prevents user/groupname display,
- * which can be problematic in chroot */
- ls_fd = popen_ls((opts & LONG_LISTING) ? "-l" : "-1");
+ ls_fd = popen_ls((opts & LONG_LISTING) ? "-lA" : "-1A");
ls_fp = xfdopen_for_read(ls_fd);
+/* FIXME: filenames with embedded newlines are mishandled */
if (opts & USE_CTRL_CONN) {
/* STAT <filename> */
@@ -729,16 +724,20 @@ handle_dir_common(int opts)
int remote_fd = get_remote_transfer_fd(" Directory listing");
if (remote_fd >= 0) {
while (1) {
- line = xmalloc_fgetline(ls_fp);
+ unsigned len;
+
+ line = xmalloc_fgets(ls_fp);
if (!line)
break;
/* I've seen clients complaining when they
* are fed with ls output with bare '\n'.
- * Pity... that would be much simpler.
+ * Replace trailing "\n\0" with "\r\n".
*/
-/* TODO: need to s/LF/NUL/g here */
- xwrite_str(remote_fd, line);
- xwrite(remote_fd, "\r\n", 2);
+ len = strlen(line);
+ if (len != 0) /* paranoia check */
+ line[len - 1] = '\r';
+ line[len] = '\n';
+ xwrite(remote_fd, line, len + 1);
free(line);
}
}
@@ -821,7 +820,7 @@ handle_size_or_mdtm(int need_size)
gmtime_r(&statbuf.st_mtime, &broken_out);
sprintf(buf, STR(FTP_STATFILE_OK)" %04u%02u%02u%02u%02u%02u\r\n",
broken_out.tm_year + 1900,
- broken_out.tm_mon,
+ broken_out.tm_mon + 1,
broken_out.tm_mday,
broken_out.tm_hour,
broken_out.tm_min,
@@ -927,6 +926,7 @@ handle_upload_common(int is_append, int is_unique)
|| fstat(local_file_fd, &statbuf) != 0
|| !S_ISREG(statbuf.st_mode)
) {
+ free(tempname);
WRITE_ERR(FTP_UPLOADFAIL);
if (local_file_fd >= 0)
goto close_local_and_bail;
@@ -1084,6 +1084,8 @@ enum {
const_PASV = mk_const4('P', 'A', 'S', 'V'),
const_PORT = mk_const4('P', 'O', 'R', 'T'),
const_PWD = mk_const3('P', 'W', 'D'),
+ /* Same as PWD. Reportedly used by windows ftp client */
+ const_XPWD = mk_const4('X', 'P', 'W', 'D'),
const_QUIT = mk_const4('Q', 'U', 'I', 'T'),
const_REST = mk_const4('R', 'E', 'S', 'T'),
const_RETR = mk_const4('R', 'E', 'T', 'R'),
@@ -1102,10 +1104,11 @@ enum {
#if !BB_MMU
OPT_l = (1 << 0),
OPT_1 = (1 << 1),
+ OPT_A = (1 << 2),
#endif
- OPT_v = (1 << ((!BB_MMU) * 2 + 0)),
- OPT_S = (1 << ((!BB_MMU) * 2 + 1)),
- OPT_w = (1 << ((!BB_MMU) * 2 + 2)) * ENABLE_FEATURE_FTP_WRITE,
+ OPT_v = (1 << ((!BB_MMU) * 3 + 0)),
+ OPT_S = (1 << ((!BB_MMU) * 3 + 1)),
+ OPT_w = (1 << ((!BB_MMU) * 3 + 2)) * ENABLE_FEATURE_FTP_WRITE,
};
int ftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -1115,6 +1118,9 @@ int ftpd_main(int argc, char **argv)
int ftpd_main(int argc UNUSED_PARAM, char **argv)
#endif
{
+#if ENABLE_FEATURE_FTP_AUTHENTICATION
+ struct passwd *pw = NULL;
+#endif
unsigned abs_timeout;
unsigned verbose_S;
smallint opts;
@@ -1126,16 +1132,14 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv)
G.timeout = 2 * 60;
opt_complementary = "t+:T+:vv:SS";
#if BB_MMU
- opts = getopt32(argv, "vS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S);
+ opts = getopt32(argv, "vS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S);
#else
- opts = getopt32(argv, "l1vS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S);
+ opts = getopt32(argv, "l1AvS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S);
if (opts & (OPT_l|OPT_1)) {
/* Our secret backdoor to ls */
-/* TODO: pass -n? It prevents user/group resolution, which may not work in chroot anyway */
-/* TODO: pass -A? It shows dot files */
/* TODO: pass --group-directories-first? would be nice, but ls doesn't do that yet */
- xchdir(argv[2]);
- argv[2] = (char*)"--";
+ if (fchdir(3) != 0)
+ _exit(127);
/* memset(&G, 0, sizeof(G)); - ls_main does it */
return ls_main(argc, argv);
}
@@ -1173,58 +1177,80 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv)
if (logmode)
applet_name = xasprintf("%s[%u]", applet_name, (int)getpid());
-#if !BB_MMU
- G.root_fd = xopen("/", O_RDONLY | O_DIRECTORY);
- close_on_exec_on(G.root_fd);
-#endif
-
- if (argv[optind]) {
- xchroot(argv[optind]);
- }
-
//umask(077); - admin can set umask before starting us
- /* Signals. We'll always take -EPIPE rather than a rude signal, thanks */
- signal(SIGPIPE, SIG_IGN);
+ /* Signals */
+ bb_signals(0
+ /* We'll always take EPIPE rather than a rude signal, thanks */
+ + (1 << SIGPIPE)
+ /* LIST command spawns chilren. Prevent zombies */
+ + (1 << SIGCHLD)
+ , SIG_IGN);
/* Set up options on the command socket (do we need these all? why?) */
- setsockopt(STDIN_FILENO, IPPROTO_TCP, TCP_NODELAY, &const_int_1, sizeof(const_int_1));
- setsockopt(STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));
+ setsockopt_1(STDIN_FILENO, IPPROTO_TCP, TCP_NODELAY);
+ setsockopt_keepalive(STDIN_FILENO);
/* Telnet protocol over command link may send "urgent" data,
* we prefer it to be received in the "normal" data stream: */
- setsockopt(STDIN_FILENO, SOL_SOCKET, SO_OOBINLINE, &const_int_1, sizeof(const_int_1));
+ setsockopt_1(STDIN_FILENO, SOL_SOCKET, SO_OOBINLINE);
WRITE_OK(FTP_GREET);
signal(SIGALRM, timeout_handler);
-#ifdef IF_WE_WANT_TO_REQUIRE_LOGIN
- {
- smallint user_was_specified = 0;
- while (1) {
- uint32_t cmdval = cmdio_get_cmd_and_arg();
-
+#if ENABLE_FEATURE_FTP_AUTHENTICATION
+ while (1) {
+ uint32_t cmdval = cmdio_get_cmd_and_arg();
if (cmdval == const_USER) {
- if (G.ftp_arg == NULL || strcasecmp(G.ftp_arg, "anonymous") != 0)
- cmdio_write_raw(STR(FTP_LOGINERR)" Server is anonymous only\r\n");
- else {
- user_was_specified = 1;
- cmdio_write_raw(STR(FTP_GIVEPWORD)" Please specify the password\r\n");
- }
- } else if (cmdval == const_PASS) {
- if (user_was_specified)
- break;
- cmdio_write_raw(STR(FTP_NEEDUSER)" Login with USER\r\n");
- } else if (cmdval == const_QUIT) {
- WRITE_OK(FTP_GOODBYE);
- return 0;
- } else {
- cmdio_write_raw(STR(FTP_LOGINERR)" Login with USER and PASS\r\n");
+ pw = getpwnam(G.ftp_arg);
+ cmdio_write_raw(STR(FTP_GIVEPWORD)" Please specify password\r\n");
+ } else if (cmdval == const_PASS) {
+ if (check_password(pw, G.ftp_arg) > 0) {
+ break; /* login success */
}
+ cmdio_write_raw(STR(FTP_LOGINERR)" Login failed\r\n");
+ pw = NULL;
+ } else if (cmdval == const_QUIT) {
+ WRITE_OK(FTP_GOODBYE);
+ return 0;
+ } else {
+ cmdio_write_raw(STR(FTP_LOGINERR)" Login with USER and PASS\r\n");
}
}
WRITE_OK(FTP_LOGINOK);
#endif
+ /* Do this after auth, else /etc/passwd is not accessible */
+#if !BB_MMU
+ G.root_fd = -1;
+#endif
+ argv += optind;
+ if (argv[0]) {
+ const char *basedir = argv[0];
+#if !BB_MMU
+ G.root_fd = xopen("/", O_RDONLY | O_DIRECTORY);
+ close_on_exec_on(G.root_fd);
+#endif
+ if (chroot(basedir) == 0)
+ basedir = "/";
+#if !BB_MMU
+ else {
+ close(G.root_fd);
+ G.root_fd = -1;
+ }
+#endif
+ /*
+ * If chroot failed, assume that we aren't root,
+ * and at least chdir to the specified DIR
+ * (older versions were dying with error message).
+ * If chroot worked, move current dir to new "/":
+ */
+ xchdir(basedir);
+ }
+
+#if ENABLE_FEATURE_FTP_AUTHENTICATION
+ change_identity(pw);
+#endif
+
/* RFC-959 Section 5.1
* The following commands and options MUST be supported by every
* server-FTP and user-FTP, except in cases where the underlying
@@ -1291,7 +1317,7 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv)
WRITE_OK(FTP_ALLOOK);
else if (cmdval == const_SYST)
cmdio_write_raw(STR(FTP_SYSTOK)" UNIX Type: L8\r\n");
- else if (cmdval == const_PWD)
+ else if (cmdval == const_PWD || cmdval == const_XPWD)
handle_pwd();
else if (cmdval == const_CWD)
handle_cwd();
diff --git a/release/src/router/busybox/networking/ftpgetput.c b/release/src/router/busybox/networking/ftpgetput.c
index 8283366ccc..91fb4569af 100644
--- a/release/src/router/busybox/networking/ftpgetput.c
+++ b/release/src/router/busybox/networking/ftpgetput.c
@@ -50,6 +50,7 @@
//usage: )
#include "libbb.h"
+#include "common_bufsiz.h"
struct globals {
const char *user;
@@ -60,11 +61,8 @@ struct globals {
int do_continue;
char buf[4]; /* actually [BUFSZ] */
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
enum { BUFSZ = COMMON_BUFSIZE - offsetof(struct globals, buf) };
-struct BUG_G_too_big {
- char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
-};
#define user (G.user )
#define password (G.password )
#define lsa (G.lsa )
@@ -72,7 +70,10 @@ struct BUG_G_too_big {
#define verbose_flag (G.verbose_flag )
#define do_continue (G.do_continue )
#define buf (G.buf )
-#define INIT_G() do { } while (0)
+#define INIT_G() do { \
+ setup_common_bufsiz(); \
+ BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
+} while (0)
static void ftp_die(const char *msg) NORETURN;
diff --git a/release/src/router/busybox/networking/hostname.c b/release/src/router/busybox/networking/hostname.c
index d2516b5fb9..b3e3522426 100644
--- a/release/src/router/busybox/networking/hostname.c
+++ b/release/src/router/busybox/networking/hostname.c
@@ -106,7 +106,7 @@ int hostname_main(int argc UNUSED_PARAM, char **argv)
OPT_i = 0x4,
OPT_s = 0x8,
OPT_F = 0x10,
- OPT_dfis = 0xf,
+ OPT_dfi = 0x7,
};
unsigned opts;
@@ -134,7 +134,7 @@ int hostname_main(int argc UNUSED_PARAM, char **argv)
if (applet_name[0] == 'd') /* dnsdomainname? */
opts = OPT_d;
- if (opts & OPT_dfis) {
+ if (opts & OPT_dfi) {
/* Cases when we need full hostname (or its part) */
struct hostent *hp;
char *p;
@@ -159,6 +159,9 @@ int hostname_main(int argc UNUSED_PARAM, char **argv)
bb_putchar('\n');
}
}
+ } else if (opts & OPT_s) {
+ strchrnul(buf, '.')[0] = '\0';
+ puts(buf);
} else if (opts & OPT_F) {
/* Set the hostname */
do_sethostname(hostname_str, 1);
diff --git a/release/src/router/busybox/networking/httpd.c b/release/src/router/busybox/networking/httpd.c
index 12218a0a32..abe83a458d 100644
--- a/release/src/router/busybox/networking/httpd.c
+++ b/release/src/router/busybox/networking/httpd.c
@@ -125,6 +125,7 @@
//usage: "\n -d STRING URL decode STRING"
#include "libbb.h"
+#include "common_bufsiz.h"
#if ENABLE_PAM
/* PAM may include <locale.h>. We may need to undefine bbox's stub define: */
# undef setlocale
@@ -133,7 +134,7 @@
# include <security/pam_appl.h>
# include <security/pam_misc.h>
#endif
-#if ENABLE_FEATURE_HTTPD_USE_SENDFILE
+#if ENABLE_FEATURE_USE_SENDFILE
# include <sys/sendfile.h>
#endif
/* amount of buffering in a pipe */
@@ -307,7 +308,8 @@ struct globals {
Htaccess *script_i; /* config script interpreters */
#endif
char *iobuf; /* [IOBUF_SIZE] */
-#define hdr_buf bb_common_bufsiz1
+#define hdr_buf bb_common_bufsiz1
+#define sizeof_hdr_buf COMMON_BUFSIZE
char *hdr_ptr;
int hdr_cnt;
#if ENABLE_FEATURE_HTTPD_ERROR_PAGES
@@ -368,6 +370,7 @@ enum {
# define content_gzip 0
#endif
#define INIT_G() do { \
+ setup_common_bufsiz(); \
SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
IF_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \
IF_FEATURE_HTTPD_RANGES(range_start = -1;) \
@@ -697,7 +700,7 @@ static void parse_conf(const char *path, int flag)
goto config_error;
}
*host_port++ = '\0';
- if (strncmp(host_port, "http://", 7) == 0)
+ if (is_prefixed_with(host_port, "http://"))
host_port += 7;
if (*host_port == '\0') {
goto config_error;
@@ -796,9 +799,9 @@ static void parse_conf(const char *path, int flag)
/* the line is not recognized */
config_error:
bb_error_msg("config error '%s' in '%s'", buf, filename);
- } /* while (fgets) */
+ } /* while (fgets) */
- fclose(f);
+ fclose(f);
}
#if ENABLE_FEATURE_HTTPD_ENCODE_URL_STR
@@ -967,19 +970,30 @@ static void send_headers(int responseNum)
}
#endif
if (responseNum == HTTP_MOVED_TEMPORARILY) {
- len += sprintf(iobuf + len, "Location: %s/%s%s\r\n",
+ /* Responding to "GET /dir" with
+ * "HTTP/1.0 302 Found" "Location: /dir/"
+ * - IOW, asking them to repeat with a slash.
+ * Here, overflow IS possible, can't use sprintf:
+ * mkdir test
+ * python -c 'print("get /test?" + ("x" * 8192))' | busybox httpd -i -h .
+ */
+ len += snprintf(iobuf + len, IOBUF_SIZE-3 - len,
+ "Location: %s/%s%s\r\n",
found_moved_temporarily,
(g_query ? "?" : ""),
(g_query ? g_query : ""));
+ if (len > IOBUF_SIZE-3)
+ len = IOBUF_SIZE-3;
}
#if ENABLE_FEATURE_HTTPD_ERROR_PAGES
if (error_page && access(error_page, R_OK) == 0) {
- strcat(iobuf, "\r\n");
- len += 2;
-
- if (DEBUG)
+ iobuf[len++] = '\r';
+ iobuf[len++] = '\n';
+ if (DEBUG) {
+ iobuf[len] = '\0';
fprintf(stderr, "headers: '%s'\n", iobuf);
+ }
full_write(STDOUT_FILENO, iobuf, len);
if (DEBUG)
fprintf(stderr, "writing error page: '%s'\n", error_page);
@@ -1021,8 +1035,10 @@ static void send_headers(int responseNum)
responseNum, responseString,
responseNum, responseString, infoString);
}
- if (DEBUG)
+ if (DEBUG) {
+ iobuf[len] = '\0';
fprintf(stderr, "headers: '%s'\n", iobuf);
+ }
if (full_write(STDOUT_FILENO, iobuf, len) != len) {
if (verbose > 1)
bb_perror_msg("error");
@@ -1053,7 +1069,7 @@ static int get_line(void)
alarm(HEADER_READ_TIMEOUT);
while (1) {
if (hdr_cnt <= 0) {
- hdr_cnt = safe_read(STDIN_FILENO, hdr_buf, sizeof(hdr_buf));
+ hdr_cnt = safe_read(STDIN_FILENO, hdr_buf, sizeof_hdr_buf);
if (hdr_cnt <= 0)
break;
hdr_ptr = hdr_buf;
@@ -1104,18 +1120,31 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post
/* NB: breaking out of this loop jumps to log_and_exit() */
out_cnt = 0;
+ pfd[FROM_CGI].fd = fromCgi_rd;
+ pfd[FROM_CGI].events = POLLIN;
+ pfd[TO_CGI].fd = toCgi_wr;
while (1) {
- memset(pfd, 0, sizeof(pfd));
-
- pfd[FROM_CGI].fd = fromCgi_rd;
- pfd[FROM_CGI].events = POLLIN;
-
- if (toCgi_wr) {
- pfd[TO_CGI].fd = toCgi_wr;
- if (hdr_cnt > 0) {
- pfd[TO_CGI].events = POLLOUT;
- } else if (post_len > 0) {
- pfd[0].events = POLLIN;
+ /* Note: even pfd[0].events == 0 won't prevent
+ * revents == POLLHUP|POLLERR reports from closed stdin.
+ * Setting fd to -1 works: */
+ pfd[0].fd = -1;
+ pfd[0].events = POLLIN;
+ pfd[0].revents = 0; /* probably not needed, paranoia */
+
+ /* We always poll this fd, thus kernel always sets revents: */
+ /*pfd[FROM_CGI].events = POLLIN; - moved out of loop */
+ /*pfd[FROM_CGI].revents = 0; - not needed */
+
+ /* gcc-4.8.0 still doesnt fill two shorts with one insn :( */
+ /* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47059 */
+ /* hopefully one day it will... */
+ pfd[TO_CGI].events = POLLOUT;
+ pfd[TO_CGI].revents = 0; /* needed! */
+
+ if (toCgi_wr && hdr_cnt <= 0) {
+ if (post_len > 0) {
+ /* Expect more POST data from network */
+ pfd[0].fd = 0;
} else {
/* post_len <= 0 && hdr_cnt <= 0:
* no more POST data to CGI,
@@ -1127,7 +1156,7 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post
}
/* Now wait on the set of sockets */
- count = safe_poll(pfd, toCgi_wr ? TO_CGI+1 : FROM_CGI+1, -1);
+ count = safe_poll(pfd, hdr_cnt > 0 ? TO_CGI+1 : FROM_CGI+1, -1);
if (count <= 0) {
#if 0
if (safe_waitpid(pid, &status, WNOHANG) <= 0) {
@@ -1144,7 +1173,7 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post
}
if (pfd[TO_CGI].revents) {
- /* hdr_cnt > 0 here due to the way pfd[TO_CGI].events set */
+ /* hdr_cnt > 0 here due to the way poll() called */
/* Have data from peer and can write to CGI */
count = safe_write(toCgi_wr, hdr_ptr, hdr_cnt);
/* Doesn't happen, we dont use nonblocking IO here
@@ -1165,9 +1194,9 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post
/* We expect data, prev data portion is eaten by CGI
* and there *is* data to read from the peer
* (POSTDATA) */
- //count = post_len > (int)sizeof(hdr_buf) ? (int)sizeof(hdr_buf) : post_len;
+ //count = post_len > (int)sizeof_hdr_buf ? (int)sizeof_hdr_buf : post_len;
//count = safe_read(STDIN_FILENO, hdr_buf, count);
- count = safe_read(STDIN_FILENO, hdr_buf, sizeof(hdr_buf));
+ count = safe_read(STDIN_FILENO, hdr_buf, sizeof_hdr_buf);
if (count > 0) {
hdr_cnt = count;
hdr_ptr = hdr_buf;
@@ -1209,12 +1238,12 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post
out_cnt += count;
count = 0;
/* "Status" header format is: "Status: 302 Redirected\r\n" */
- if (out_cnt >= 8 && memcmp(rbuf, "Status: ", 8) == 0) {
+ if (out_cnt >= 7 && memcmp(rbuf, "Status:", 7) == 0) {
/* send "HTTP/1.0 " */
if (full_write(STDOUT_FILENO, HTTP_200, 9) != 9)
break;
- rbuf += 8; /* skip "Status: " */
- count = out_cnt - 8;
+ rbuf += 7; /* skip "Status:" */
+ count = out_cnt - 7;
out_cnt = -1; /* buffering off */
} else if (out_cnt >= 4) {
/* Did CGI add "HTTP"? */
@@ -1414,7 +1443,7 @@ static void send_cgi_and_exit(
if (script != url) { /* paranoia */
*script = '\0';
if (chdir(url + 1) != 0) {
- bb_perror_msg("chdir(%s)", url + 1);
+ bb_perror_msg("can't change directory to '%s'", url + 1);
goto error_execing_cgi;
}
// not needed: *script = '/';
@@ -1611,7 +1640,7 @@ static NOINLINE void send_file_and_exit(const char *url, int what)
#endif
if (what & SEND_HEADERS)
send_headers(HTTP_OK);
-#if ENABLE_FEATURE_HTTPD_USE_SENDFILE
+#if ENABLE_FEATURE_USE_SENDFILE
{
off_t offset = range_start;
while (1) {
@@ -1641,7 +1670,7 @@ static NOINLINE void send_file_and_exit(const char *url, int what)
break;
}
if (count < 0) {
- IF_FEATURE_HTTPD_USE_SENDFILE(fin:)
+ IF_FEATURE_USE_SENDFILE(fin:)
if (verbose > 1)
bb_perror_msg("error");
}
@@ -1708,9 +1737,9 @@ static int pam_talker(int num_msg,
case PAM_PROMPT_ECHO_OFF:
s = userinfo->pw;
break;
- case PAM_ERROR_MSG:
- case PAM_TEXT_INFO:
- s = "";
+ case PAM_ERROR_MSG:
+ case PAM_TEXT_INFO:
+ s = "";
break;
default:
free(response);
@@ -1881,7 +1910,7 @@ static Htaccess_Proxy *find_proxy_entry(const char *url)
{
Htaccess_Proxy *p;
for (p = proxy; p; p = p->next) {
- if (strncmp(url, p->url_from, strlen(p->url_from)) == 0)
+ if (is_prefixed_with(url, p->url_from))
return p;
}
return NULL;
@@ -1964,7 +1993,9 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
send_headers_and_exit(HTTP_BAD_REQUEST);
/* Determine type of request (GET/POST) */
- urlp = strpbrk(iobuf, " \t");
+ // rfc2616: method and URI is separated by exactly one space
+ //urlp = strpbrk(iobuf, " \t"); - no, tab isn't allowed
+ urlp = strchr(iobuf, ' ');
if (urlp == NULL)
send_headers_and_exit(HTTP_BAD_REQUEST);
*urlp++ = '\0';
@@ -1982,7 +2013,8 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
if (strcasecmp(iobuf, request_GET) != 0)
send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
#endif
- urlp = skip_whitespace(urlp);
+ // rfc2616: method and URI is separated by exactly one space
+ //urlp = skip_whitespace(urlp); - should not be necessary
if (urlp[0] != '/')
send_headers_and_exit(HTTP_BAD_REQUEST);
@@ -2167,7 +2199,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
if (STRNCASECMP(iobuf, "Range:") == 0) {
/* We know only bytes=NNN-[MMM] */
char *s = skip_whitespace(iobuf + sizeof("Range:")-1);
- if (strncmp(s, "bytes=", 6) == 0) {
+ if (is_prefixed_with(s, "bytes=") == 0) {
s += sizeof("bytes=")-1;
range_start = BB_STRTOOFF(s, &s, 10);
if (s[0] != '-' || range_start < 0) {
@@ -2253,7 +2285,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
tptr = urlcopy + 1; /* skip first '/' */
#if ENABLE_FEATURE_HTTPD_CGI
- if (strncmp(tptr, "cgi-bin/", 8) == 0) {
+ if (is_prefixed_with(tptr, "cgi-bin/")) {
if (tptr[8] == '\0') {
/* protect listing "cgi-bin/" */
send_headers_and_exit(HTTP_FORBIDDEN);
@@ -2336,7 +2368,7 @@ static void mini_httpd(int server_socket)
continue;
/* set the KEEPALIVE option to cull dead connections */
- setsockopt(n, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));
+ setsockopt_keepalive(n);
if (fork() == 0) {
/* child */
@@ -2379,7 +2411,7 @@ static void mini_httpd_nommu(int server_socket, int argc, char **argv)
continue;
/* set the KEEPALIVE option to cull dead connections */
- setsockopt(n, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));
+ setsockopt_keepalive(n);
if (vfork() == 0) {
/* child */
diff --git a/release/src/router/busybox/networking/httpd_indexcgi.c b/release/src/router/busybox/networking/httpd_indexcgi.c
index d732cd4f8a..562cd7fbef 100644
--- a/release/src/router/busybox/networking/httpd_indexcgi.c
+++ b/release/src/router/busybox/networking/httpd_indexcgi.c
@@ -35,6 +35,7 @@ httpd_indexcgi.c -o index.cgi
* 2576 4 2048 4628 1214 index.cgi.o
*/
+#define _GNU_SOURCE 1 /* for strchrnul */
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
diff --git a/release/src/router/busybox/networking/httpd_ssi.c b/release/src/router/busybox/networking/httpd_ssi.c
index cfe64eb46e..4bd9a6d97d 100644
--- a/release/src/router/busybox/networking/httpd_ssi.c
+++ b/release/src/router/busybox/networking/httpd_ssi.c
@@ -133,7 +133,7 @@ static void process_includes(const char *filename)
process_includes(include_directive);
/* Print everything after directive */
- if (end) {
+ if (end) {
fputs(end, stdout);
free(end);
}
diff --git a/release/src/router/busybox/networking/ifconfig.c b/release/src/router/busybox/networking/ifconfig.c
index b6604f5d15..8984b02077 100644
--- a/release/src/router/busybox/networking/ifconfig.c
+++ b/release/src/router/busybox/networking/ifconfig.c
@@ -56,7 +56,7 @@
#endif
#if ENABLE_FEATURE_IFCONFIG_SLIP
-# include <net/if_slip.h>
+# include <linux/if_slip.h>
#endif
/* I don't know if this is needed for busybox or not. Anyone? */
@@ -174,10 +174,6 @@ struct in6_ifreq {
#define ARG_ADD_DEL (A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER)
-/*
- * Set up the tables. Warning! They must have corresponding order!
- */
-
struct arg1opt {
const char *name;
unsigned short selector;
@@ -198,6 +194,10 @@ struct options {
#define ifreq_offsetof(x) offsetof(struct ifreq, x)
+/*
+ * Set up the tables. Warning! They must have corresponding order!
+ */
+
static const struct arg1opt Arg1Opt[] = {
{ "SIFMETRIC", SIOCSIFMETRIC, ifreq_offsetof(ifr_metric) },
{ "SIFMTU", SIOCSIFMTU, ifreq_offsetof(ifr_mtu) },
@@ -220,11 +220,11 @@ static const struct arg1opt Arg1Opt[] = {
{ "SIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.base_addr) },
{ "SIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.irq) },
#endif
- /* Last entry if for unmatched (possibly hostname) arg. */
#if ENABLE_FEATURE_IPV6
{ "SIFADDR", SIOCSIFADDR, ifreq_offsetof(ifr_addr) }, /* IPv6 version ignores the offset */
{ "DIFADDR", SIOCDIFADDR, ifreq_offsetof(ifr_addr) }, /* IPv6 version ignores the offset */
#endif
+ /* Last entry is for unmatched (assumed to be hostname/address) arg. */
{ "SIFADDR", SIOCSIFADDR, ifreq_offsetof(ifr_addr) },
};
@@ -265,16 +265,6 @@ static const struct options OptArray[] = {
{ NULL, 0, ARG_HOSTNAME, (IFF_UP | IFF_RUNNING) }
};
-/*
- * A couple of prototypes.
- */
-#if ENABLE_FEATURE_IFCONFIG_HW
-static int in_ether(const char *bufp, struct sockaddr *sap);
-#endif
-
-/*
- * Our main function.
- */
int ifconfig_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int ifconfig_main(int argc UNUSED_PARAM, char **argv)
{
@@ -330,7 +320,7 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
strncpy_IFNAMSIZ(ifr.ifr_name, *argv);
/* Process the remaining arguments. */
- while (*++argv != (char *) NULL) {
+ while (*++argv != NULL) {
p = *argv;
mask = N_MASK;
if (*p == '-') { /* If the arg starts with '-'... */
@@ -356,9 +346,9 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
FOUND_ARG:
if (mask & ARG_MASK) {
mask = op->arg_flags;
- a1op = Arg1Opt + (op - OptArray);
if (mask & A_NETMASK & did_flags)
bb_show_usage();
+ a1op = Arg1Opt + (op - OptArray);
if (*++argv == NULL) {
if (mask & A_ARG_REQ)
bb_show_usage();
@@ -371,19 +361,9 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
#if ENABLE_FEATURE_IFCONFIG_HW
if (mask & A_CAST_RESOLVE) {
#endif
-#if ENABLE_FEATURE_IPV6
- char *prefix;
- int prefix_len = 0;
-#endif
- /*safe_strncpy(host, *argv, (sizeof host));*/
host = *argv;
-#if ENABLE_FEATURE_IPV6
- prefix = strchr(host, '/');
- if (prefix) {
- prefix_len = xatou_range(prefix + 1, 0, 128);
- *prefix = '\0';
- }
-#endif
+ if (strcmp(host, "inet") == 0)
+ continue; /* compat stuff */
sai.sin_family = AF_INET;
sai.sin_port = 0;
if (strcmp(host, "default") == 0) {
@@ -391,7 +371,8 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
sai.sin_addr.s_addr = INADDR_ANY;
}
#if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS
- else if ((host[0] == '+' && !host[1]) && (mask & A_BROADCAST)
+ else if ((host[0] == '+' && !host[1])
+ && (mask & A_BROADCAST)
&& (did_flags & (A_NETMASK|A_HOSTNAME)) == (A_NETMASK|A_HOSTNAME)
) {
/* + is special, meaning broadcast is derived. */
@@ -400,23 +381,36 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
#endif
else {
len_and_sockaddr *lsa;
- if (strcmp(host, "inet") == 0)
- continue; /* compat stuff */
+#if ENABLE_FEATURE_IPV6
+ char *prefix;
+ int prefix_len = 0;
+ prefix = strchr(host, '/');
+ if (prefix) {
+ prefix_len = xatou_range(prefix + 1, 0, 128);
+ *prefix = '\0';
+ }
+ resolve:
+#endif
lsa = xhost2sockaddr(host, 0);
#if ENABLE_FEATURE_IPV6
+ if (lsa->u.sa.sa_family != AF_INET6 && prefix) {
+/* TODO: we do not support "ifconfig eth0 up 1.2.3.4/17".
+ * For now, just make it fail instead of silently ignoring "/17" part:
+ */
+ *prefix = '/';
+ goto resolve;
+ }
if (lsa->u.sa.sa_family == AF_INET6) {
int sockfd6;
struct in6_ifreq ifr6;
- memcpy((char *) &ifr6.ifr6_addr,
- (char *) &(lsa->u.sin6.sin6_addr),
- sizeof(struct in6_addr));
-
- /* Create a channel to the NET kernel. */
sockfd6 = xsocket(AF_INET6, SOCK_DGRAM, 0);
- xioctl(sockfd6, SIOGIFINDEX, &ifr);
+ xioctl(sockfd6, SIOCGIFINDEX, &ifr);
ifr6.ifr6_ifindex = ifr.ifr_ifindex;
ifr6.ifr6_prefixlen = prefix_len;
+ memcpy(&ifr6.ifr6_addr,
+ &lsa->u.sin6.sin6_addr,
+ sizeof(struct in6_addr));
ioctl_or_perror_and_die(sockfd6, a1op->selector, &ifr6, "SIOC%s", a1op->name);
if (ENABLE_FEATURE_CLEAN_UP)
free(lsa);
@@ -437,19 +431,18 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
#if ENABLE_FEATURE_IFCONFIG_HW
} else { /* A_CAST_HOST_COPY_IN_ETHER */
/* This is the "hw" arg case. */
- smalluint hw_class= index_in_substrings("ether\0"
+ smalluint hw_class = index_in_substrings("ether\0"
IF_FEATURE_HWIB("infiniband\0"), *argv) + 1;
if (!hw_class || !*++argv)
bb_show_usage();
- /*safe_strncpy(host, *argv, sizeof(host));*/
host = *argv;
if (hw_class == 1 ? in_ether(host, &sa) : in_ib(host, &sa))
bb_error_msg_and_die("invalid hw-addr %s", host);
p = (char *) &sa;
}
#endif
- memcpy( (((char *)&ifr) + a1op->ifr_offset),
- p, sizeof(struct sockaddr));
+ memcpy( ((char *)&ifr) + a1op->ifr_offset,
+ p, sizeof(struct sockaddr));
} else {
/* FIXME: error check?? */
unsigned long i = strtoul(*argv, NULL, 0);
@@ -458,17 +451,17 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
if (mask & A_MAP_TYPE) {
xioctl(sockfd, SIOCGIFMAP, &ifr);
if ((mask & A_MAP_UCHAR) == A_MAP_UCHAR)
- *((unsigned char *) p) = i;
+ *(unsigned char *) p = i;
else if (mask & A_MAP_USHORT)
- *((unsigned short *) p) = i;
+ *(unsigned short *) p = i;
else
- *((unsigned long *) p) = i;
+ *(unsigned long *) p = i;
} else
#endif
if (mask & A_CAST_CHAR_PTR)
- *((caddr_t *) p) = (caddr_t) i;
+ *(caddr_t *) p = (caddr_t) i;
else /* A_CAST_INT */
- *((int *) p) = i;
+ *(int *) p = i;
}
ioctl_or_perror_and_die(sockfd, a1op->selector, &ifr, "SIOC%s", a1op->name);
@@ -494,7 +487,7 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
if (!(mask & A_SET_AFTER))
continue;
mask = N_SET;
- }
+ } /* if (mask & ARG_MASK) */
xioctl(sockfd, SIOCGIFFLAGS, &ifr);
selector = op->selector;
@@ -509,46 +502,3 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
close(sockfd);
return 0;
}
-
-#if ENABLE_FEATURE_IFCONFIG_HW
-/* Input an Ethernet address and convert to binary. */
-static int in_ether(const char *bufp, struct sockaddr *sap)
-{
- char *ptr;
- int i, j;
- unsigned char val;
- unsigned char c;
-
- sap->sa_family = ARPHRD_ETHER;
- ptr = (char *) sap->sa_data;
-
- i = 0;
- do {
- j = val = 0;
-
- /* We might get a semicolon here - not required. */
- if (i && (*bufp == ':')) {
- bufp++;
- }
-
- do {
- c = *bufp;
- if (((unsigned char)(c - '0')) <= 9) {
- c -= '0';
- } else if (((unsigned char)((c|0x20) - 'a')) <= 5) {
- c = (c|0x20) - ('a'-10);
- } else if (j && (c == ':' || c == 0)) {
- break;
- } else {
- return -1;
- }
- ++bufp;
- val <<= 4;
- val += c;
- } while (++j < 2);
- *ptr++ = val;
- } while (++i < ETH_ALEN);
-
- return *bufp; /* Error if we don't end at end of string. */
-}
-#endif
diff --git a/release/src/router/busybox/networking/ifenslave.c b/release/src/router/busybox/networking/ifenslave.c
index ae7719f52f..6b234adee5 100644
--- a/release/src/router/busybox/networking/ifenslave.c
+++ b/release/src/router/busybox/networking/ifenslave.c
@@ -270,7 +270,7 @@ static int set_if_addr(char *master_ifname, char *slave_ifname)
if (res < 0) {
ifr.ifr_addr.sa_family = AF_INET;
memset(ifr.ifr_addr.sa_data, 0,
- sizeof(ifr.ifr_addr.sa_data));
+ sizeof(ifr.ifr_addr.sa_data));
}
res = set_ifrname_and_do_ioctl(ifra[i].s_ioctl, &ifr, slave_ifname);
@@ -546,7 +546,7 @@ int ifenslave_main(int argc UNUSED_PARAM, char **argv)
#ifdef WHY_BOTHER
/* Neither -c[hange] nor -d[etach] -> it's "enslave" then;
* and -f[orce] is not there too. Check that it's ethernet. */
- if (!(opt & (OPT_d|OPT_c|OPT_f)) {
+ if (!(opt & (OPT_d|OPT_c|OPT_f))) {
/* The family '1' is ARPHRD_ETHER for ethernet. */
if (master.hwaddr.ifr_hwaddr.sa_family != 1) {
bb_error_msg_and_die(
@@ -577,8 +577,8 @@ int ifenslave_main(int argc UNUSED_PARAM, char **argv)
/* Can't work with this slave, */
/* remember the error and skip it */
bb_perror_msg(
- "skipping %s: can't get flags",
- slave_ifname);
+ "skipping %s: can't get %s",
+ slave_ifname, "flags");
res = rv;
continue;
}
@@ -595,8 +595,8 @@ int ifenslave_main(int argc UNUSED_PARAM, char **argv)
/* Can't work with this slave, */
/* remember the error and skip it */
bb_perror_msg(
- "skipping %s: can't get settings",
- slave_ifname);
+ "skipping %s: can't get %s",
+ slave_ifname, "settings");
res = rv;
continue;
}
diff --git a/release/src/router/busybox/networking/ifplugd.c b/release/src/router/busybox/networking/ifplugd.c
index d8358cdfd5..f0defb5c83 100644
--- a/release/src/router/busybox/networking/ifplugd.c
+++ b/release/src/router/busybox/networking/ifplugd.c
@@ -22,9 +22,9 @@
//usage: "\n -r PROG Script to run"
//usage: "\n -x ARG Extra argument for script"
//usage: "\n -I Don't exit on nonzero exit code from script"
-//usage: "\n -p Don't run script on daemon startup"
-//usage: "\n -q Don't run script on daemon quit"
-//usage: "\n -l Run script on startup even if no cable is detected"
+//usage: "\n -p Don't run \"up\" script on startup"
+//usage: "\n -q Don't run \"down\" script on exit"
+//usage: "\n -l Always run script on startup"
//usage: "\n -t SECS Poll time in seconds"
//usage: "\n -u SECS Delay before running script after link up"
//usage: "\n -d SECS Delay after link down"
@@ -38,7 +38,17 @@
#include <linux/mii.h>
#include <linux/ethtool.h>
#ifdef HAVE_NET_ETHERNET_H
-# include <net/ethernet.h>
+/* musl breakage:
+ * In file included from /usr/include/net/ethernet.h:10,
+ * from networking/ifplugd.c:41:
+ * /usr/include/netinet/if_ether.h:96: error: redefinition of 'struct ethhdr'
+ *
+ * Build succeeds without it on musl. Commented it out.
+ * If on your system you need it, consider removing <linux/ethtool.h>
+ * and copy-pasting its definitions here (<linux/ethtool.h> is what pulls in
+ * conflicting definition of struct ethhdr on musl).
+ */
+/* # include <net/ethernet.h> */
#endif
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
@@ -48,6 +58,10 @@
#define __user
#include <linux/wireless.h>
+#ifndef ETH_ALEN
+# define ETH_ALEN 6
+#endif
+
/*
From initial port to busybox, removed most of the redundancy by
converting implementation of a polymorphic interface to the strict
@@ -289,8 +303,6 @@ static const struct {
{ "IFF_RUNNING" , &detect_link_iff },
};
-
-
static const char *strstatus(int status)
{
if (status == IFSTATUS_ERR)
@@ -451,20 +463,24 @@ static smallint detect_link(void)
static NOINLINE int check_existence_through_netlink(void)
{
int iface_len;
- char replybuf[1024];
+ /* Buffer was 1K, but on linux-3.9.9 it was reported to be too small.
+ * netlink.h: "limit to 8K to avoid MSG_TRUNC when PAGE_SIZE is very large".
+ * Note: on error returns (-1) we exit, no need to free replybuf.
+ */
+ enum { BUF_SIZE = 8 * 1024 };
+ char *replybuf = xmalloc(BUF_SIZE);
iface_len = strlen(G.iface);
while (1) {
struct nlmsghdr *mhdr;
ssize_t bytes;
- bytes = recv(netlink_fd, &replybuf, sizeof(replybuf), MSG_DONTWAIT);
+ bytes = recv(netlink_fd, replybuf, BUF_SIZE, MSG_DONTWAIT);
if (bytes < 0) {
if (errno == EAGAIN)
- return G.iface_exists;
+ goto ret;
if (errno == EINTR)
continue;
-
bb_perror_msg("netlink: recv");
return -1;
}
@@ -507,6 +523,8 @@ static NOINLINE int check_existence_through_netlink(void)
}
}
+ ret:
+ free(replybuf);
return G.iface_exists;
}
@@ -551,12 +569,13 @@ int ifplugd_main(int argc UNUSED_PARAM, char **argv)
applet_name = xasprintf("ifplugd(%s)", G.iface);
#if ENABLE_FEATURE_PIDFILE
- pidfile_name = xasprintf(_PATH_VARRUN"ifplugd.%s.pid", G.iface);
+ pidfile_name = xasprintf(CONFIG_PID_FILE_PATH "/ifplugd.%s.pid", G.iface);
pid_from_pidfile = read_pid(pidfile_name);
if (opts & FLAG_KILL) {
if (pid_from_pidfile > 0)
- kill(pid_from_pidfile, SIGQUIT);
+ /* Upstream tool use SIGINT for -k */
+ kill(pid_from_pidfile, SIGINT);
return EXIT_SUCCESS;
}
@@ -645,7 +664,6 @@ int ifplugd_main(int argc UNUSED_PARAM, char **argv)
delay_time = 0;
while (1) {
int iface_status_old;
- int iface_exists_old;
switch (bb_got_signal) {
case SIGINT:
@@ -671,12 +689,12 @@ int ifplugd_main(int argc UNUSED_PARAM, char **argv)
goto exiting;
}
- iface_status_old = iface_status;
- iface_exists_old = G.iface_exists;
-
if ((opts & FLAG_MONITOR)
&& (netlink_pollfd[0].revents & POLLIN)
) {
+ int iface_exists_old;
+
+ iface_exists_old = G.iface_exists;
G.iface_exists = check_existence_through_netlink();
if (G.iface_exists < 0) /* error */
goto exiting;
@@ -689,6 +707,7 @@ int ifplugd_main(int argc UNUSED_PARAM, char **argv)
}
/* note: if !G.iface_exists, returns DOWN */
+ iface_status_old = iface_status;
iface_status = detect_link();
if (iface_status == IFSTATUS_ERR) {
if (!(opts & FLAG_MONITOR))
@@ -702,7 +721,7 @@ int ifplugd_main(int argc UNUSED_PARAM, char **argv)
if (delay_time) {
/* link restored its old status before
- * we run script. don't run the script: */
+ * we ran script. don't run the script: */
delay_time = 0;
} else {
delay_time = monotonic_sec();
@@ -710,15 +729,19 @@ int ifplugd_main(int argc UNUSED_PARAM, char **argv)
delay_time += G.delay_up;
if (iface_status == IFSTATUS_DOWN)
delay_time += G.delay_down;
- if (delay_time == 0)
- delay_time++;
+#if 0 /* if you are back in 1970... */
+ if (delay_time == 0) {
+ sleep(1);
+ delay_time = 1;
+ }
+#endif
}
}
if (delay_time && (int)(monotonic_sec() - delay_time) >= 0) {
- delay_time = 0;
if (run_script(iface_status_str) != 0)
goto exiting;
+ delay_time = 0;
}
} /* while (1) */
diff --git a/release/src/router/busybox/networking/ifupdown.c b/release/src/router/busybox/networking/ifupdown.c
index 9b34986964..25b04c9d75 100644
--- a/release/src/router/busybox/networking/ifupdown.c
+++ b/release/src/router/busybox/networking/ifupdown.c
@@ -44,14 +44,12 @@
//usage: "\n -f Force de/configuration"
#include "libbb.h"
+#include "common_bufsiz.h"
/* After libbb.h, since it needs sys/types.h on some systems */
#include <sys/utsname.h>
#include <fnmatch.h>
#define MAX_OPT_DEPTH 10
-#define EUNBALBRACK 10001
-#define EUNDEFVAR 10002
-#define EUNBALPER 10000
#if ENABLE_FEATURE_IFUPDOWN_MAPPING
#define MAX_INTERFACE_LENGTH 10
@@ -132,8 +130,8 @@ struct globals {
const char *startup_PATH;
char *shell;
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
-#define INIT_G() do { } while (0)
+#define G (*(struct globals*)bb_common_bufsiz1)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
static const char keywords_up_down[] ALIGN1 =
@@ -233,7 +231,7 @@ static int count_netmask_bits(const char *dotted_quad)
static char *parse(const char *command, struct interface_defn_t *ifd)
{
size_t old_pos[MAX_OPT_DEPTH] = { 0 };
- int okay[MAX_OPT_DEPTH] = { 1 };
+ smallint okay[MAX_OPT_DEPTH] = { 1 };
int opt_depth = 1;
char *result = NULL;
@@ -244,13 +242,10 @@ static char *parse(const char *command, struct interface_defn_t *ifd)
command++;
break;
case '\\':
- if (command[1]) {
- addstr(&result, command + 1, 1);
- command += 2;
- } else {
- addstr(&result, command, 1);
+ if (command[1])
command++;
- }
+ addstr(&result, command, 1);
+ command++;
break;
case '[':
if (command[1] == '[' && opt_depth < MAX_OPT_DEPTH) {
@@ -259,7 +254,7 @@ static char *parse(const char *command, struct interface_defn_t *ifd)
opt_depth++;
command += 2;
} else {
- addstr(&result, "[", 1);
+ addstr(&result, command, 1);
command++;
}
break;
@@ -271,7 +266,7 @@ static char *parse(const char *command, struct interface_defn_t *ifd)
}
command += 2;
} else {
- addstr(&result, "]", 1);
+ addstr(&result, command, 1);
command++;
}
break;
@@ -283,7 +278,7 @@ static char *parse(const char *command, struct interface_defn_t *ifd)
command++;
nextpercent = strchr(command, '%');
if (!nextpercent) {
- errno = EUNBALPER;
+ /* Unterminated %var% */
free(result);
return NULL;
}
@@ -295,7 +290,7 @@ static char *parse(const char *command, struct interface_defn_t *ifd)
/* "hwaddress <class> <address>":
* unlike ifconfig, ip doesnt want <class>
* (usually "ether" keyword). Skip it. */
- if (strncmp(command, "hwaddress", 9) == 0) {
+ if (is_prefixed_with(command, "hwaddress")) {
varvalue = skip_whitespace(skip_non_whitespace(varvalue));
}
# endif
@@ -304,7 +299,7 @@ static char *parse(const char *command, struct interface_defn_t *ifd)
# if ENABLE_FEATURE_IFUPDOWN_IP
/* Sigh... Add a special case for 'ip' to convert from
* dotted quad to bit count style netmasks. */
- if (strncmp(command, "bnmask", 6) == 0) {
+ if (is_prefixed_with(command, "bnmask")) {
unsigned res;
varvalue = get_var("netmask", 7, ifd);
if (varvalue) {
@@ -328,13 +323,13 @@ static char *parse(const char *command, struct interface_defn_t *ifd)
}
if (opt_depth > 1) {
- errno = EUNBALBRACK;
+ /* Unbalanced bracket */
free(result);
return NULL;
}
if (!okay[0]) {
- errno = EUNDEFVAR;
+ /* Undefined variable and we aren't in a bracket */
free(result);
return NULL;
}
@@ -400,8 +395,8 @@ static int FAST_FUNC static_up6(struct interface_defn_t *ifd, execfn *exec)
# if ENABLE_FEATURE_IFUPDOWN_IP
result = execute("ip addr add %address%/%netmask% dev %iface%[[ label %label%]]", ifd, exec);
result += execute("ip link set[[ mtu %mtu%]][[ addr %hwaddress%]] %iface% up", ifd, exec);
- /* Was: "[[ ip ....%gateway% ]]". Removed extra spaces w/o checking */
- result += execute("[[ip route add ::/0 via %gateway%]][[ prio %metric%]]", ifd, exec);
+ /* Reportedly, IPv6 needs "dev %iface%", but IPv4 does not: */
+ result += execute("[[ip route add ::/0 via %gateway% dev %iface%]][[ metric %metric%]]", ifd, exec);
# else
result = execute("ifconfig %iface%[[ media %media%]][[ hw %hwaddress%]][[ mtu %mtu%]] up", ifd, exec);
result += execute("ifconfig %iface% add %address%/%netmask%", ifd, exec);
@@ -427,7 +422,8 @@ static int FAST_FUNC v4tunnel_up(struct interface_defn_t *ifd, execfn *exec)
"%endpoint%[[ local %local%]][[ ttl %ttl%]]", ifd, exec);
result += execute("ip link set %iface% up", ifd, exec);
result += execute("ip addr add %address%/%netmask% dev %iface%", ifd, exec);
- result += execute("[[ip route add ::/0 via %gateway%]]", ifd, exec);
+ /* Reportedly, IPv6 needs "dev %iface%", but IPv4 does not: */
+ result += execute("[[ip route add ::/0 via %gateway% dev %iface%]]", ifd, exec);
return ((result == 4) ? 4 : 0);
}
@@ -488,7 +484,7 @@ static int FAST_FUNC static_up(struct interface_defn_t *ifd, execfn *exec)
result = execute("ip addr add %address%/%bnmask%[[ broadcast %broadcast%]] "
"dev %iface%[[ peer %pointopoint%]][[ label %label%]]", ifd, exec);
result += execute("ip link set[[ mtu %mtu%]][[ addr %hwaddress%]] %iface% up", ifd, exec);
- result += execute("[[ip route add default via %gateway% dev %iface%[[ prio %metric%]]]]", ifd, exec);
+ result += execute("[[ip route add default via %gateway% dev %iface%[[ metric %metric%]]]]", ifd, exec);
return ((result == 3) ? 3 : 0);
# else
/* ifconfig said to set iface up before it processes hw %hwaddress%,
@@ -540,7 +536,7 @@ static const struct dhcp_client_t ext_dhcp_clients[] = {
"pump -i %iface% -k",
},
{ "udhcpc",
- "udhcpc " UDHCPC_CMD_OPTIONS " -p /var/run/udhcpc.%iface%.pid -i %iface%[[ -H %hostname%]][[ -c %client%]]"
+ "udhcpc " UDHCPC_CMD_OPTIONS " -p /var/run/udhcpc.%iface%.pid -i %iface%[[ -x hostname:%hostname%]][[ -c %client%]]"
"[[ -s %script%]][[ %udhcpc_opts%]]",
"kill `cat /var/run/udhcpc.%iface%.pid` 2>/dev/null",
},
@@ -561,7 +557,7 @@ static int FAST_FUNC dhcp_up(struct interface_defn_t *ifd, execfn *exec)
return 0;
# endif
for (i = 0; i < ARRAY_SIZE(ext_dhcp_clients); i++) {
- if (exists_execable(ext_dhcp_clients[i].name))
+ if (executable_exists(ext_dhcp_clients[i].name))
return execute(ext_dhcp_clients[i].startcmd, ifd, exec);
}
bb_error_msg("no dhcp clients found");
@@ -580,7 +576,7 @@ static int FAST_FUNC dhcp_up(struct interface_defn_t *ifd, execfn *exec)
return 0;
# endif
return execute("udhcpc " UDHCPC_CMD_OPTIONS " -p /var/run/udhcpc.%iface%.pid "
- "-i %iface%[[ -H %hostname%]][[ -c %client%]][[ -s %script%]][[ %udhcpc_opts%]]",
+ "-i %iface%[[ -x hostname:%hostname%]][[ -c %client%]][[ -s %script%]][[ %udhcpc_opts%]]",
ifd, exec);
}
# else
@@ -598,7 +594,7 @@ static int FAST_FUNC dhcp_down(struct interface_defn_t *ifd, execfn *exec)
unsigned i;
for (i = 0; i < ARRAY_SIZE(ext_dhcp_clients); i++) {
- if (exists_execable(ext_dhcp_clients[i].name)) {
+ if (executable_exists(ext_dhcp_clients[i].name)) {
result = execute(ext_dhcp_clients[i].stopcmd, ifd, exec);
if (result)
break;
@@ -691,6 +687,18 @@ static const struct address_family_t addr_inet = {
#endif /* FEATURE_IFUPDOWN_IPV4 */
+static int FAST_FUNC link_up_down(struct interface_defn_t *ifd UNUSED_PARAM, execfn *exec UNUSED_PARAM)
+{
+ return 1;
+}
+
+static const struct method_t link_methods[] = {
+ { "none", link_up_down, link_up_down }
+};
+
+static const struct address_family_t addr_link = {
+ "link", ARRAY_SIZE(link_methods), link_methods
+};
/* Returns pointer to the next word, or NULL.
* In 1st case, advances *buf to the word after this one.
@@ -749,7 +757,7 @@ static const struct method_t *get_method(const struct address_family_t *af, char
return NULL;
}
-static struct interfaces_file_t *read_interfaces(const char *filename)
+static struct interfaces_file_t *read_interfaces(const char *filename, struct interfaces_file_t *defn)
{
/* Let's try to be compatible.
*
@@ -764,19 +772,25 @@ static struct interfaces_file_t *read_interfaces(const char *filename)
* be ignored. Blank lines are ignored. Lines may be indented freely.
* A "\" character at the very end of the line indicates the next line
* should be treated as a continuation of the current one.
+ *
+ * Lines beginning with "source" are used to include stanzas from
+ * other files, so configuration can be split into many files.
+ * The word "source" is followed by the path of file to be sourced.
*/
#if ENABLE_FEATURE_IFUPDOWN_MAPPING
struct mapping_defn_t *currmap = NULL;
#endif
struct interface_defn_t *currif = NULL;
- struct interfaces_file_t *defn;
FILE *f;
char *buf;
char *first_word;
char *rest_of_line;
enum { NONE, IFACE, MAPPING } currently_processing = NONE;
- defn = xzalloc(sizeof(*defn));
+ if (!defn)
+ defn = xzalloc(sizeof(*defn));
+
+ debug_noise("reading %s file:\n", filename);
f = xfopen_for_read(filename);
while ((buf = xmalloc_fgetline(f)) != NULL) {
@@ -831,12 +845,12 @@ static struct interfaces_file_t *read_interfaces(const char *filename)
#if ENABLE_FEATURE_IFUPDOWN_IPV6
&addr_inet6,
#endif
+ &addr_link,
NULL
};
char *iface_name;
char *address_family_name;
char *method_name;
- llist_t *iface_list;
currif = xzalloc(sizeof(*currif));
iface_name = next_word(&rest_of_line);
@@ -861,7 +875,20 @@ static struct interfaces_file_t *read_interfaces(const char *filename)
currif->method = get_method(currif->address_family, method_name);
if (!currif->method)
bb_error_msg_and_die("unknown method \"%s\"", method_name);
-
+#if 0
+// Allegedly, Debian allows a duplicate definition:
+// iface eth0 inet static
+// address 192.168.0.15
+// netmask 255.255.0.0
+// gateway 192.168.0.1
+//
+// iface eth0 inet static
+// address 10.0.0.1
+// netmask 255.255.255.0
+//
+// This adds *two* addresses to eth0 (probably requires use of "ip", not "ifconfig"
+//
+ llist_t *iface_list;
for (iface_list = defn->ifaces; iface_list; iface_list = iface_list->link) {
struct interface_defn_t *tmp = (struct interface_defn_t *) iface_list->data;
if ((strcmp(tmp->iface, currif->iface) == 0)
@@ -870,6 +897,7 @@ static struct interfaces_file_t *read_interfaces(const char *filename)
bb_error_msg_and_die("duplicate interface \"%s\"", tmp->iface);
}
}
+#endif
llist_add_to_end(&(defn->ifaces), (char*)currif);
debug_noise("iface %s %s %s\n", currif->iface, address_family_name, method_name);
@@ -887,6 +915,8 @@ static struct interfaces_file_t *read_interfaces(const char *filename)
debug_noise("\nauto %s\n", first_word);
}
currently_processing = NONE;
+ } else if (strcmp(first_word, "source") == 0) {
+ read_interfaces(next_word(&rest_of_line), defn);
} else {
switch (currently_processing) {
case IFACE:
@@ -940,6 +970,7 @@ static struct interfaces_file_t *read_interfaces(const char *filename)
bb_error_msg_and_die("%s: I/O error", filename);
}
fclose(f);
+ debug_noise("\ndone reading %s\n\n", filename);
return defn;
}
@@ -1058,7 +1089,7 @@ static int iface_up(struct interface_defn_t *iface)
static int iface_down(struct interface_defn_t *iface)
{
- if (!iface->method->down(iface,check)) return -1;
+ if (!iface->method->down(iface, check)) return -1;
set_environ(iface, "stop", "pre-down");
if (!execute_all(iface, "down")) return 0;
if (!iface->method->down(iface, doit)) return 0;
@@ -1143,12 +1174,12 @@ static char *run_mapping(char *physical, struct mapping_defn_t *map)
static llist_t *find_iface_state(llist_t *state_list, const char *iface)
{
- unsigned iface_len = strlen(iface);
llist_t *search = state_list;
while (search) {
- if ((strncmp(search->data, iface, iface_len) == 0)
- && (search->data[iface_len] == '=')
+ char *after_iface = is_prefixed_with(search->data, iface);
+ if (after_iface
+ && *after_iface == '='
) {
return search;
}
@@ -1205,9 +1236,7 @@ int ifupdown_main(int argc UNUSED_PARAM, char **argv)
if (!DO_ALL) bb_show_usage();
}
- debug_noise("reading %s file:\n", interfaces);
- defn = read_interfaces(interfaces);
- debug_noise("\ndone reading %s\n\n", interfaces);
+ defn = read_interfaces(interfaces, NULL);
/* Create a list of interfaces to work on */
if (DO_ALL) {
@@ -1225,6 +1254,7 @@ int ifupdown_main(int argc UNUSED_PARAM, char **argv)
char *pch;
bool okay = 0;
int cmds_ret;
+ bool curr_failure = 0;
iface = xstrdup(target_list->data);
target_list = target_list->link;
@@ -1290,11 +1320,11 @@ int ifupdown_main(int argc UNUSED_PARAM, char **argv)
/* Call the cmds function pointer, does either iface_up() or iface_down() */
cmds_ret = cmds(currif);
if (cmds_ret == -1) {
- bb_error_msg("don't seem to have all the variables for %s/%s",
+ bb_error_msg("don't have all variables for %s/%s",
liface, currif->address_family->name);
- any_failures = 1;
+ any_failures = curr_failure = 1;
} else if (cmds_ret == 0) {
- any_failures = 1;
+ any_failures = curr_failure = 1;
}
currif->iface = oldiface;
@@ -1315,7 +1345,7 @@ int ifupdown_main(int argc UNUSED_PARAM, char **argv)
llist_t *state_list = read_iface_state();
llist_t *iface_state = find_iface_state(state_list, iface);
- if (cmds == iface_up && !any_failures) {
+ if (cmds == iface_up && !curr_failure) {
char *newiface = xasprintf("%s=%s", iface, liface);
if (!iface_state) {
llist_add_to_end(&state_list, newiface);
diff --git a/release/src/router/busybox/networking/inetd.c b/release/src/router/busybox/networking/inetd.c
index 26b66992d4..8d44b5198a 100644
--- a/release/src/router/busybox/networking/inetd.c
+++ b/release/src/router/busybox/networking/inetd.c
@@ -165,9 +165,12 @@
//usage: "\n (default: 0 - disabled)"
#include <syslog.h>
+#include <sys/resource.h> /* setrlimit */
+#include <sys/socket.h> /* un.h may need this */
#include <sys/un.h>
#include "libbb.h"
+#include "common_bufsiz.h"
#if ENABLE_FEATURE_INETD_RPC
# if defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_RPC__)
@@ -184,8 +187,6 @@
#define ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN 0
#endif
-#define _PATH_INETDPID "/var/run/inetd.pid"
-
#define CNT_INTERVAL 60 /* servers in CNT_INTERVAL sec. */
#define RETRYTIME 60 /* retry after bind or server fail */
@@ -327,11 +328,8 @@ struct globals {
/* Used in next_line(), and as scratch read buffer */
char line[256]; /* _at least_ 256, see LINE_SIZE */
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
enum { LINE_SIZE = COMMON_BUFSIZE - offsetof(struct globals, line) };
-struct BUG_G_too_big {
- char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
-};
#define rlim_ofile_cur (G.rlim_ofile_cur )
#define rlim_ofile (G.rlim_ofile )
#define serv_list (G.serv_list )
@@ -352,6 +350,8 @@ struct BUG_G_too_big {
#define allsock (G.allsock )
#define line (G.line )
#define INIT_G() do { \
+ setup_common_bufsiz(); \
+ BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
rlim_ofile_cur = OPEN_MAX; \
global_queuelen = 128; \
config_filename = "/etc/inetd.conf"; \
@@ -645,7 +645,7 @@ static servtab_t *dup_servtab(servtab_t *sep)
}
/* gcc generates much more code if this is inlined */
-static servtab_t *parse_one_line(void)
+static NOINLINE servtab_t *parse_one_line(void)
{
int argc;
char *token[6+MAXARGV];
@@ -675,6 +675,8 @@ static servtab_t *parse_one_line(void)
* default host for the following lines. */
free(default_local_hostname);
default_local_hostname = sep->se_local_hostname;
+ /*sep->se_local_hostname = NULL; - redundant */
+ /* (we'll overwrite this field anyway) */
goto more;
}
} else
@@ -688,10 +690,10 @@ static servtab_t *parse_one_line(void)
parse_err:
bb_error_msg("parse error on line %u, line is ignored",
parser->lineno);
- free_servtab_strings(sep);
/* Just "goto more" can make sep to carry over e.g.
* "rpc"-ness (by having se_rpcver_lo != 0).
* We will be more paranoid: */
+ free_servtab_strings(sep);
free(sep);
goto new;
}
@@ -725,7 +727,7 @@ static servtab_t *parse_one_line(void)
goto parse_err;
#endif
}
- if (strncmp(arg, "rpc/", 4) == 0) {
+ if (is_prefixed_with(arg, "rpc/")) {
#if ENABLE_FEATURE_INETD_RPC
unsigned n;
arg += 4;
@@ -815,7 +817,7 @@ static servtab_t *parse_one_line(void)
}
#endif
argc = 0;
- while ((arg = token[6+argc]) != NULL && argc < MAXARGV)
+ while (argc < MAXARGV && (arg = token[6+argc]) != NULL)
sep->se_argv[argc++] = xstrdup(arg);
/* Some inetd.conf files have no argv's, not even argv[0].
* Fix them up.
@@ -834,10 +836,10 @@ static servtab_t *parse_one_line(void)
goto parse_err;
}
-// bb_info_msg(
-// "ENTRY[%s][%s][%s][%d][%d][%d][%d][%d][%s][%s][%s]",
-// sep->se_local_hostname, sep->se_service, sep->se_proto, sep->se_wait, sep->se_proto_no,
-// sep->se_max, sep->se_count, sep->se_time, sep->se_user, sep->se_group, sep->se_program);
+ //bb_error_msg(
+ // "ENTRY[%s][%s][%s][%d][%d][%d][%d][%d][%s][%s][%s]",
+ // sep->se_local_hostname, sep->se_service, sep->se_proto, sep->se_wait, sep->se_proto_no,
+ // sep->se_max, sep->se_count, sep->se_time, sep->se_user, sep->se_group, sep->se_program);
/* check if the hostname specifier is a comma separated list
* of hostnames. we'll make new entries for each address. */
@@ -1130,7 +1132,7 @@ static void clean_up_and_exit(int sig UNUSED_PARAM)
if (ENABLE_FEATURE_CLEAN_UP)
close(sep->se_fd);
}
- remove_pidfile(_PATH_INETDPID);
+ remove_pidfile(CONFIG_PID_FILE_PATH "/inetd.pid");
exit(EXIT_SUCCESS);
}
@@ -1179,7 +1181,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
setgroups(1, &gid);
}
- write_pidfile(_PATH_INETDPID);
+ write_pidfile(CONFIG_PID_FILE_PATH "/inetd.pid");
/* never fails under Linux (except if you pass it bad arguments) */
getrlimit(RLIMIT_NOFILE, &rlim_ofile);
@@ -1654,7 +1656,7 @@ static void FAST_FUNC daytime_stream(int s, servtab_t *sep UNUSED_PARAM)
{
time_t t;
- t = time(NULL);
+ time(&t);
fdprintf(s, "%.24s\r\n", ctime(&t));
}
static void FAST_FUNC daytime_dg(int s, servtab_t *sep)
diff --git a/release/src/router/busybox/networking/interface.c b/release/src/router/busybox/networking/interface.c
index 4a319bfb3b..e5723b4283 100644
--- a/release/src/router/busybox/networking/interface.c
+++ b/release/src/router/busybox/networking/interface.c
@@ -27,7 +27,7 @@
* {1.34} - 19980630 - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
* - gettext instead of catgets for i18n
* 10/1998 - Andi Kleen. Use interface list primitives.
- * 20001008 - Bernd Eckenfels, Patch from RH for setting mtu
+ * 20001008 - Bernd Eckenfels, Patch from RH for setting mtu
* (default AF was wrong)
*/
@@ -89,13 +89,9 @@ struct in6_ifreq {
/* Display an Internet socket address. */
static const char* FAST_FUNC INET_sprint(struct sockaddr *sap, int numeric)
{
- static char *buff; /* defaults to NULL */
-
- free(buff);
if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
return "[NONE SET]";
- buff = INET_rresolve((struct sockaddr_in *) sap, numeric, 0xffffff00);
- return buff;
+ return auto_string(INET_rresolve((struct sockaddr_in *) sap, numeric, 0xffffff00));
}
#ifdef UNUSED_AND_BUGGY
@@ -171,13 +167,9 @@ static const struct aftype inet_aftype = {
/* dirty! struct sockaddr usually doesn't suffer for inet6 addresses, fst. */
static const char* FAST_FUNC INET6_sprint(struct sockaddr *sap, int numeric)
{
- static char *buff;
-
- free(buff);
if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
return "[NONE SET]";
- buff = INET6_rresolve((struct sockaddr_in6 *) sap, numeric);
- return buff;
+ return auto_string(INET6_rresolve((struct sockaddr_in6 *) sap, numeric));
}
#ifdef UNUSED
@@ -223,13 +215,11 @@ static const struct aftype inet6_aftype = {
/* Display an UNSPEC address. */
static char* FAST_FUNC UNSPEC_print(unsigned char *ptr)
{
- static char *buff;
-
+ char *buff;
char *pos;
unsigned int i;
- if (!buff)
- buff = xmalloc(sizeof(struct sockaddr) * 3 + 1);
+ buff = auto_string(xmalloc(sizeof(struct sockaddr) * 3 + 1));
pos = buff;
for (i = 0; i < sizeof(struct sockaddr); i++) {
/* careful -- not every libc's sprintf returns # bytes written */
@@ -712,78 +702,23 @@ static const struct hwtype loop_hwtype = {
/* Display an Ethernet address in readable format. */
static char* FAST_FUNC ether_print(unsigned char *ptr)
{
- static char *buff;
-
- free(buff);
+ char *buff;
buff = xasprintf("%02X:%02X:%02X:%02X:%02X:%02X",
(ptr[0] & 0377), (ptr[1] & 0377), (ptr[2] & 0377),
(ptr[3] & 0377), (ptr[4] & 0377), (ptr[5] & 0377)
);
- return buff;
+ return auto_string(buff);
}
-static int FAST_FUNC ether_input(const char *bufp, struct sockaddr *sap);
-
static const struct hwtype ether_hwtype = {
.name = "ether",
.title = "Ethernet",
.type = ARPHRD_ETHER,
.alen = ETH_ALEN,
.print = ether_print,
- .input = ether_input
+ .input = in_ether
};
-static unsigned hexchar2int(char c)
-{
- if (isdigit(c))
- return c - '0';
- c &= ~0x20; /* a -> A */
- if ((unsigned)(c - 'A') <= 5)
- return c - ('A' - 10);
- return ~0U;
-}
-
-/* Input an Ethernet address and convert to binary. */
-static int FAST_FUNC ether_input(const char *bufp, struct sockaddr *sap)
-{
- unsigned char *ptr;
- char c;
- int i;
- unsigned val;
-
- sap->sa_family = ether_hwtype.type;
- ptr = (unsigned char*) sap->sa_data;
-
- i = 0;
- while ((*bufp != '\0') && (i < ETH_ALEN)) {
- val = hexchar2int(*bufp++) * 0x10;
- if (val > 0xff) {
- errno = EINVAL;
- return -1;
- }
- c = *bufp;
- if (c == ':' || c == 0)
- val >>= 4;
- else {
- val |= hexchar2int(c);
- if (val > 0xff) {
- errno = EINVAL;
- return -1;
- }
- }
- if (c != 0)
- bufp++;
- *ptr++ = (unsigned char) val;
- i++;
-
- /* We might get a semicolon here - not required. */
- if (*bufp == ':') {
- bufp++;
- }
- }
- return 0;
-}
-
static const struct hwtype ppp_hwtype = {
.name = "ppp",
.title = "Point-to-Point Protocol",
@@ -927,7 +862,7 @@ static void print_bytes_scaled(unsigned long long ull, const char *end)
static void ife_print6(struct interface *ptr)
{
FILE *f;
- char addr6[40], devname[20];
+ char addr6[40], devname[21];
struct sockaddr_in6 sap;
int plen, scope, dad_status, if_idx;
char addr6p[8][5];
@@ -946,12 +881,13 @@ static void ife_print6(struct interface *ptr)
sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
addr6p[0], addr6p[1], addr6p[2], addr6p[3],
addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
+ memset(&sap, 0, sizeof(sap));
inet_pton(AF_INET6, addr6,
(struct sockaddr *) &sap.sin6_addr);
sap.sin6_family = AF_INET6;
- printf(" inet6 addr: %s/%d",
- INET6_sprint((struct sockaddr *) &sap, 1),
- plen);
+ printf(" inet6 addr: %s/%d",
+ INET6_sprint((struct sockaddr *) &sap, 1),
+ plen);
printf(" Scope:");
switch (scope & IPV6_ADDR_SCOPE_MASK) {
case 0:
@@ -1000,7 +936,7 @@ static void ife_print(struct interface *ptr)
if (hw == NULL)
hw = get_hwntype(-1);
- printf("%-10s Link encap:%s ", ptr->name, hw->title);
+ printf("%-9s Link encap:%s ", ptr->name, hw->title);
/* For some hardware types (eg Ash, ATM) we don't print the
hardware address if it's null. */
if (hw->print != NULL
@@ -1018,8 +954,8 @@ static void ife_print(struct interface *ptr)
bb_putchar('\n');
if (ptr->has_ip) {
- printf(" %s addr:%s ", ap->name,
- ap->sprint(&ptr->addr, 1));
+ printf(" %s addr:%s ", ap->name,
+ ap->sprint(&ptr->addr, 1));
if (ptr->flags & IFF_POINTOPOINT) {
printf(" P-t-P:%s ", ap->sprint(&ptr->dstaddr, 1));
}
@@ -1031,7 +967,7 @@ static void ife_print(struct interface *ptr)
ife_print6(ptr);
- printf(" ");
+ printf(" ");
/* DONT FORGET TO ADD THE FLAGS IN ife_print_short, too */
if (ptr->flags == 0) {
@@ -1099,26 +1035,26 @@ static void ife_print(struct interface *ptr)
* not for the aliases, although strictly speaking they're shared
* by all addresses.
*/
- printf(" ");
+ printf(" ");
printf("RX packets:%llu errors:%lu dropped:%lu overruns:%lu frame:%lu\n",
- ptr->stats.rx_packets, ptr->stats.rx_errors,
- ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors,
- ptr->stats.rx_frame_errors);
+ ptr->stats.rx_packets, ptr->stats.rx_errors,
+ ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors,
+ ptr->stats.rx_frame_errors);
if (can_compress)
- printf(" compressed:%lu\n",
- ptr->stats.rx_compressed);
- printf(" ");
+ printf(" compressed:%lu\n",
+ ptr->stats.rx_compressed);
+ printf(" ");
printf("TX packets:%llu errors:%lu dropped:%lu overruns:%lu carrier:%lu\n",
- ptr->stats.tx_packets, ptr->stats.tx_errors,
- ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors,
- ptr->stats.tx_carrier_errors);
- printf(" collisions:%lu ", ptr->stats.collisions);
+ ptr->stats.tx_packets, ptr->stats.tx_errors,
+ ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors,
+ ptr->stats.tx_carrier_errors);
+ printf(" collisions:%lu ", ptr->stats.collisions);
if (can_compress)
printf("compressed:%lu ", ptr->stats.tx_compressed);
if (ptr->tx_queue_len != -1)
printf("txqueuelen:%d ", ptr->tx_queue_len);
- printf("\n R");
+ printf("\n R");
print_bytes_scaled(ptr->stats.rx_bytes, " T");
print_bytes_scaled(ptr->stats.tx_bytes, "\n");
}
@@ -1126,16 +1062,15 @@ static void ife_print(struct interface *ptr)
if (ptr->map.irq || ptr->map.mem_start
|| ptr->map.dma || ptr->map.base_addr
) {
- printf(" ");
+ printf(" ");
if (ptr->map.irq)
printf("Interrupt:%d ", ptr->map.irq);
- if (ptr->map.base_addr >= 0x100) /* Only print devices using it for
- I/O maps */
+ if (ptr->map.base_addr >= 0x100) /* Only print devices using it for I/O maps */
printf("Base address:0x%lx ",
- (unsigned long) ptr->map.base_addr);
+ (unsigned long) ptr->map.base_addr);
if (ptr->map.mem_start) {
printf("Memory:%lx-%lx ", ptr->map.mem_start,
- ptr->map.mem_end);
+ ptr->map.mem_end);
}
if (ptr->map.dma)
printf("DMA chan:%x ", ptr->map.dma);
@@ -1168,7 +1103,7 @@ static struct interface *lookup_interface(char *name)
#ifdef UNUSED
static int for_all_interfaces(int (*doit) (struct interface *, void *),
- void *cookie)
+ void *cookie)
{
struct interface *ife;
diff --git a/release/src/router/busybox/networking/ip.c b/release/src/router/busybox/networking/ip.c
index 98fe621b16..ddfe74e9cd 100644
--- a/release/src/router/busybox/networking/ip.c
+++ b/release/src/router/busybox/networking/ip.c
@@ -16,6 +16,7 @@
//usage: IF_FEATURE_IP_ROUTE("route | ")
//usage: IF_FEATURE_IP_LINK("link | ")
//usage: IF_FEATURE_IP_TUNNEL("tunnel | ")
+//usage: IF_FEATURE_IP_NEIGH("neigh | ")
//usage: IF_FEATURE_IP_RULE("rule")
//usage: "} {COMMAND}"
//usage:#define ip_full_usage "\n\n"
@@ -25,6 +26,7 @@
//usage: IF_FEATURE_IP_ROUTE("route | ")
//usage: IF_FEATURE_IP_LINK("link | ")
//usage: IF_FEATURE_IP_TUNNEL("tunnel | ")
+//usage: IF_FEATURE_IP_NEIGH("neigh | ")
//usage: IF_FEATURE_IP_RULE("rule")
//usage: "}\n"
//usage: "OPTIONS := { -f[amily] { inet | inet6 | link } | -o[neline] }"
@@ -33,7 +35,7 @@
//usage: "{ {add|del} IFADDR dev STRING | {show|flush}\n"
//usage: " [dev STRING] [to PREFIX] }"
//usage:#define ipaddr_full_usage "\n\n"
-//usage: "ipaddr {add|delete} IFADDR dev STRING\n"
+//usage: "ipaddr {add|change|replace|delete} IFADDR dev STRING\n"
//usage: "ipaddr {show|flush} [dev STRING] [scope SCOPE-ID]\n"
//usage: " [to PREFIX] [label PATTERN]\n"
//usage: " IFADDR := PREFIX | ADDR peer PREFIX\n"
@@ -80,6 +82,11 @@
//usage: " [mode { ipip | gre | sit }] [remote ADDR] [local ADDR]\n"
//usage: " [[i|o]seq] [[i|o]key KEY] [[i|o]csum]\n"
//usage: " [ttl TTL] [tos TOS] [[no]pmtudisc] [dev PHYS_DEV]"
+//usage:
+//usage:#define ipneigh_trivial_usage
+//usage: "{ show | flush} [ to PREFIX ] [ dev DEV ] [ nud STATE ]"
+//usage:#define ipneigh_full_usage "\n\n"
+//usage: "ipneigh { show | flush} [ to PREFIX ] [ dev DEV ] [ nud STATE ]"
#include "libbb.h"
@@ -90,7 +97,8 @@
|| ENABLE_FEATURE_IP_ROUTE \
|| ENABLE_FEATURE_IP_LINK \
|| ENABLE_FEATURE_IP_TUNNEL \
- || ENABLE_FEATURE_IP_RULE
+ || ENABLE_FEATURE_IP_RULE \
+ || ENABLE_FEATURE_IP_NEIGH
static int FAST_FUNC ip_print_help(char **argv UNUSED_PARAM)
{
@@ -140,6 +148,13 @@ int iptunnel_main(int argc UNUSED_PARAM, char **argv)
return ip_do(do_iptunnel, argv);
}
#endif
+#if ENABLE_FEATURE_IP_NEIGH
+int ipneigh_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int ipneigh_main(int argc UNUSED_PARAM, char **argv)
+{
+ return ip_do(do_ipneigh, argv);
+}
+#endif
int ip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -153,6 +168,7 @@ int ip_main(int argc UNUSED_PARAM, char **argv)
IF_FEATURE_IP_TUNNEL("tunnel\0")
IF_FEATURE_IP_TUNNEL("tunl\0")
IF_FEATURE_IP_RULE("rule\0")
+ IF_FEATURE_IP_NEIGH("neigh\0")
;
static const ip_func_ptr_t ip_func_ptrs[] = {
ip_print_help,
@@ -163,6 +179,7 @@ int ip_main(int argc UNUSED_PARAM, char **argv)
IF_FEATURE_IP_TUNNEL(do_iptunnel,)
IF_FEATURE_IP_TUNNEL(do_iptunnel,)
IF_FEATURE_IP_RULE(do_iprule,)
+ IF_FEATURE_IP_NEIGH(do_ipneigh,)
};
ip_func_ptr_t ip_func;
int key;
diff --git a/release/src/router/busybox/networking/ipcalc.c b/release/src/router/busybox/networking/ipcalc.c
index 3c8b8bfc91..f4bacd7dcc 100644
--- a/release/src/router/busybox/networking/ipcalc.c
+++ b/release/src/router/busybox/networking/ipcalc.c
@@ -13,7 +13,8 @@
*/
//usage:#define ipcalc_trivial_usage
-//usage: "[OPTIONS] ADDRESS[[/]NETMASK] [NETMASK]"
+//usage: "[OPTIONS] ADDRESS"
+//usage: IF_FEATURE_IPCALC_FANCY("[/PREFIX]") " [NETMASK]"
//usage:#define ipcalc_full_usage "\n\n"
//usage: "Calculate IP network settings from a IP address\n"
//usage: IF_FEATURE_IPCALC_LONG_OPTIONS(
diff --git a/release/src/router/busybox/networking/isrv.c b/release/src/router/busybox/networking/isrv.c
index 1c6491edda..3673db715e 100644
--- a/release/src/router/busybox/networking/isrv.c
+++ b/release/src/router/busybox/networking/isrv.c
@@ -194,7 +194,6 @@ static void handle_accept(isrv_state_t *state, int fd)
remove_peer(state, n); /* unsuccesful peer start */
}
-void BUG_sizeof_fd_set_is_strange(void);
static void handle_fd_set(isrv_state_t *state, fd_set *fds, int (*h)(int, void **))
{
enum { LONG_CNT = sizeof(fd_set) / sizeof(long) };
@@ -203,8 +202,7 @@ static void handle_fd_set(isrv_state_t *state, fd_set *fds, int (*h)(int, void *
/* need to know value at _the beginning_ of this routine */
int fd_cnt = FD_COUNT;
- if (LONG_CNT * sizeof(long) != sizeof(fd_set))
- BUG_sizeof_fd_set_is_strange();
+ BUILD_BUG_ON(LONG_CNT * sizeof(long) != sizeof(fd_set));
fds_pos = 0;
while (1) {
diff --git a/release/src/router/busybox/networking/isrv.h b/release/src/router/busybox/networking/isrv.h
index 4c7e01dd1f..7b12e0edd2 100644
--- a/release/src/router/busybox/networking/isrv.h
+++ b/release/src/router/busybox/networking/isrv.h
@@ -23,7 +23,31 @@ int isrv_register_fd(isrv_state_t *state, int peer, int fd);
void isrv_close_fd(isrv_state_t *state, int fd);
int isrv_register_peer(isrv_state_t *state, void *param);
-/* driver */
+/* Driver:
+ *
+ * Select on listen_fd for <linger_timeout> (or forever if 0).
+ *
+ * If we time out and we have no peers, exit.
+ * If we have peers, call do_timeout(peer_param),
+ * if it returns !0, peer is removed.
+ *
+ * If listen_fd is active, accept new connection ("peer"),
+ * call new_peer() on it, and if it returns 0,
+ * add it to fds to select on.
+ * Now, select will wait for <timeout>, not <linger_timeout>
+ * (as long as we have more than zero peers).
+ *
+ * If a peer's fd is active, we call do_rd() on it if read
+ * bit was set, and then do_wr() if write bit was also set.
+ * If either returns !0, peer is removed.
+ * Reaching this place also resets timeout counter for this peer.
+ *
+ * Note that peer must indicate that he wants to be selected
+ * for read and/or write using isrv_want_rd()/isrv_want_wr()
+ * [can be called in new_peer() or in do_rd()/do_wr()].
+ * If it never wants to be selected for write, do_wr()
+ * will never be called (can be NULL).
+ */
void isrv_run(
int listen_fd,
int (*new_peer)(isrv_state_t *state, int fd),
diff --git a/release/src/router/busybox/networking/isrv_identd.c b/release/src/router/busybox/networking/isrv_identd.c
index a41405c333..8a15926e58 100644
--- a/release/src/router/busybox/networking/isrv_identd.c
+++ b/release/src/router/busybox/networking/isrv_identd.c
@@ -18,6 +18,7 @@
//usage: "\n STRING Ident answer string (default: nobody)"
#include "libbb.h"
+#include "common_bufsiz.h"
#include <syslog.h>
#include "isrv.h"
@@ -25,8 +26,7 @@ enum { TIMEOUT = 20 };
typedef struct identd_buf_t {
int pos;
- int fd_flag;
- char buf[64 - 2*sizeof(int)];
+ char buf[64 - sizeof(int)];
} identd_buf_t;
#define bogouser bb_common_bufsiz1
@@ -42,7 +42,7 @@ static int new_peer(isrv_state_t *state, int fd)
if (isrv_register_fd(state, peer, fd) < 0)
return peer; /* failure, unregister peer */
- buf->fd_flag = fcntl(fd, F_GETFL) | O_NONBLOCK;
+ ndelay_on(fd);
isrv_want_rd(state, fd);
return 0;
}
@@ -51,19 +51,16 @@ static int do_rd(int fd, void **paramp)
{
identd_buf_t *buf = *paramp;
char *cur, *p;
- int retval = 0; /* session is ok (so far) */
int sz;
cur = buf->buf + buf->pos;
- if (buf->fd_flag & O_NONBLOCK)
- fcntl(fd, F_SETFL, buf->fd_flag);
- sz = safe_read(fd, cur, sizeof(buf->buf) - buf->pos);
+ sz = safe_read(fd, cur, sizeof(buf->buf) - 1 - buf->pos);
if (sz < 0) {
if (errno != EAGAIN)
- goto term; /* terminate this session if !EAGAIN */
- goto ok;
+ goto term;
+ return 0; /* "session is ok" */
}
buf->pos += sz;
@@ -71,19 +68,22 @@ static int do_rd(int fd, void **paramp)
p = strpbrk(cur, "\r\n");
if (p)
*p = '\0';
- if (!p && sz && buf->pos <= (int)sizeof(buf->buf))
- goto ok;
+ if (!p && sz)
+ return 0; /* "session is ok" */
+
/* Terminate session. If we are in server mode, then
* fd is still in nonblocking mode - we never block here */
- if (fd == 0) fd++; /* inetd mode? then write to fd 1 */
+ if (fd == 0)
+ fd++; /* inetd mode? then write to fd 1 */
fdprintf(fd, "%s : USERID : UNIX : %s\r\n", buf->buf, bogouser);
+ /*
+ * Why bother if we are going to close fd now anyway?
+ * if (server)
+ * ndelay_off(fd);
+ */
term:
free(buf);
- retval = 1; /* terminate */
- ok:
- if (buf->fd_flag & O_NONBLOCK)
- fcntl(fd, F_SETFL, buf->fd_flag & ~O_NONBLOCK);
- return retval;
+ return 1; /* "terminate" */
}
static int do_timeout(void **paramp UNUSED_PARAM)
@@ -95,10 +95,9 @@ static void inetd_mode(void)
{
identd_buf_t *buf = xzalloc(sizeof(*buf));
/* buf->pos = 0; - xzalloc did it */
- /* We do NOT want nonblocking I/O here! */
- /* buf->fd_flag = 0; - xzalloc did it */
do
alarm(TIMEOUT);
+ /* Note: we do NOT want nonblocking I/O here! */
while (do_rd(0, (void*)&buf) == 0);
}
@@ -117,10 +116,12 @@ int fakeidentd_main(int argc UNUSED_PARAM, char **argv)
unsigned opt;
int fd;
+ setup_common_bufsiz();
+
opt = getopt32(argv, "fiwb:", &bind_address);
strcpy(bogouser, "nobody");
if (argv[optind])
- strncpy(bogouser, argv[optind], sizeof(bogouser));
+ strncpy(bogouser, argv[optind], COMMON_BUFSIZE - 1);
/* Daemonize if no -f and no -i and no -w */
if (!(opt & OPT_fiw))
diff --git a/release/src/router/busybox/networking/libiproute/Kbuild.src b/release/src/router/busybox/networking/libiproute/Kbuild.src
index 7c78f3c6a5..c20e2fee86 100644
--- a/release/src/router/busybox/networking/libiproute/Kbuild.src
+++ b/release/src/router/busybox/networking/libiproute/Kbuild.src
@@ -64,3 +64,11 @@ lib-$(CONFIG_FEATURE_IP_RULE) += \
iprule.o \
rt_names.o \
utils.o
+
+lib-$(CONFIG_FEATURE_IP_NEIGH) += \
+ ip_parse_common_args.o \
+ ipneigh.o \
+ libnetlink.o \
+ ll_map.o \
+ rt_names.o \
+ utils.o
diff --git a/release/src/router/busybox/networking/libiproute/ip_common.h b/release/src/router/busybox/networking/libiproute/ip_common.h
index 30c7e595b5..40171bed9a 100644
--- a/release/src/router/busybox/networking/libiproute/ip_common.h
+++ b/release/src/router/busybox/networking/libiproute/ip_common.h
@@ -24,7 +24,7 @@ int FAST_FUNC ipaddr_list_or_flush(char **argv, int flush);
int FAST_FUNC do_ipaddr(char **argv);
int FAST_FUNC do_iproute(char **argv);
int FAST_FUNC do_iprule(char **argv);
-//int FAST_FUNC do_ipneigh(char **argv);
+int FAST_FUNC do_ipneigh(char **argv);
int FAST_FUNC do_iptunnel(char **argv);
int FAST_FUNC do_iplink(char **argv);
//int FAST_FUNC do_ipmonitor(char **argv);
diff --git a/release/src/router/busybox/networking/libiproute/ip_parse_common_args.c b/release/src/router/busybox/networking/libiproute/ip_parse_common_args.c
index 59c759b239..1a298f7380 100644
--- a/release/src/router/busybox/networking/libiproute/ip_parse_common_args.c
+++ b/release/src/router/busybox/networking/libiproute/ip_parse_common_args.c
@@ -67,7 +67,7 @@ char** FAST_FUNC ip_parse_common_args(char **argv)
bb_show_usage();
arg = index_in_strings(families, *argv);
if (arg < 0)
- invarg(*argv, "protocol family");
+ invarg_1_to_2(*argv, "family");
/* now arg == 0, 1 or 2 */
} else {
arg -= ARG_IPv4;
diff --git a/release/src/router/busybox/networking/libiproute/ipaddress.c b/release/src/router/busybox/networking/libiproute/ipaddress.c
index b3748e8c59..d9e0996075 100644
--- a/release/src/router/busybox/networking/libiproute/ipaddress.c
+++ b/release/src/router/busybox/networking/libiproute/ipaddress.c
@@ -13,6 +13,7 @@
#include <net/if_arp.h>
#include "ip_common.h" /* #include "libbb.h" is inside */
+#include "common_bufsiz.h"
#include "rt_names.h"
#include "utils.h"
@@ -39,8 +40,8 @@ struct filter_t {
} FIX_ALIASING;
typedef struct filter_t filter_t;
-#define G_filter (*(filter_t*)&bb_common_bufsiz1)
-
+#define G_filter (*(filter_t*)bb_common_bufsiz1)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
static void print_link_flags(unsigned flags, unsigned mdown)
{
@@ -137,12 +138,11 @@ static NOINLINE int print_linkinfo(const struct nlmsghdr *n)
{
unsigned m_flag = 0;
if (tb[IFLA_LINK]) {
- SPRINT_BUF(b1);
int iflink = *(int*)RTA_DATA(tb[IFLA_LINK]);
if (iflink == 0)
printf("@NONE: ");
else {
- printf("@%s: ", ll_idx_n2a(iflink, b1));
+ printf("@%s: ", ll_index_to_name(iflink));
m_flag = ll_index_to_flags(iflink);
m_flag = !(m_flag & IFF_UP);
}
@@ -158,8 +158,7 @@ static NOINLINE int print_linkinfo(const struct nlmsghdr *n)
printf("qdisc %s ", (char*)RTA_DATA(tb[IFLA_QDISC]));
#ifdef IFLA_MASTER
if (tb[IFLA_MASTER]) {
- SPRINT_BUF(b1);
- printf("master %s ", ll_idx_n2a(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1));
+ printf("master %s ", ll_index_to_name(*(int*)RTA_DATA(tb[IFLA_MASTER])));
}
#endif
/* IFLA_OPERSTATE was added to kernel with the same commit as IFF_DORMANT */
@@ -216,9 +215,7 @@ static int FAST_FUNC print_addrinfo(const struct sockaddr_nl *who UNUSED_PARAM,
{
struct ifaddrmsg *ifa = NLMSG_DATA(n);
int len = n->nlmsg_len;
- struct rtattr * rta_tb[IFA_MAX+1];
- char abuf[256];
- SPRINT_BUF(b1);
+ struct rtattr *rta_tb[IFA_MAX+1];
if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR)
return 0;
@@ -250,7 +247,7 @@ static int FAST_FUNC print_addrinfo(const struct sockaddr_nl *who UNUSED_PARAM,
if (rta_tb[IFA_LABEL])
label = RTA_DATA(rta_tb[IFA_LABEL]);
else
- label = ll_idx_n2a(ifa->ifa_index, b1);
+ label = ll_index_to_name(ifa->ifa_index);
if (fnmatch(G_filter.label, label, 0) != 0)
return 0;
}
@@ -294,9 +291,9 @@ static int FAST_FUNC print_addrinfo(const struct sockaddr_nl *who UNUSED_PARAM,
printf(" family %d ", ifa->ifa_family);
if (rta_tb[IFA_LOCAL]) {
- fputs(rt_addr_n2a(ifa->ifa_family,
- RTA_DATA(rta_tb[IFA_LOCAL]),
- abuf, sizeof(abuf)), stdout);
+ fputs(rt_addr_n2a(ifa->ifa_family, RTA_DATA(rta_tb[IFA_LOCAL])),
+ stdout
+ );
if (rta_tb[IFA_ADDRESS] == NULL
|| memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]), 4) == 0
@@ -304,26 +301,25 @@ static int FAST_FUNC print_addrinfo(const struct sockaddr_nl *who UNUSED_PARAM,
printf("/%d ", ifa->ifa_prefixlen);
} else {
printf(" peer %s/%d ",
- rt_addr_n2a(ifa->ifa_family,
- RTA_DATA(rta_tb[IFA_ADDRESS]),
- abuf, sizeof(abuf)),
- ifa->ifa_prefixlen);
+ rt_addr_n2a(ifa->ifa_family, RTA_DATA(rta_tb[IFA_ADDRESS])),
+ ifa->ifa_prefixlen
+ );
}
}
if (rta_tb[IFA_BROADCAST]) {
printf("brd %s ",
rt_addr_n2a(ifa->ifa_family,
- RTA_DATA(rta_tb[IFA_BROADCAST]),
- abuf, sizeof(abuf)));
+ RTA_DATA(rta_tb[IFA_BROADCAST]))
+ );
}
if (rta_tb[IFA_ANYCAST]) {
printf("any %s ",
rt_addr_n2a(ifa->ifa_family,
- RTA_DATA(rta_tb[IFA_ANYCAST]),
- abuf, sizeof(abuf)));
+ RTA_DATA(rta_tb[IFA_ANYCAST]))
+ );
}
- printf("scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1));
+ printf("scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope));
if (ifa->ifa_flags & IFA_F_SECONDARY) {
ifa->ifa_flags &= ~IFA_F_SECONDARY;
printf("secondary ");
@@ -456,7 +452,7 @@ int FAST_FUNC ipaddr_list_or_flush(char **argv, int flush)
G_filter.scopemask = -1;
if (rtnl_rtscope_a2n(&scope, *argv)) {
if (strcmp(*argv, "all") != 0) {
- invarg(*argv, "scope");
+ invarg_1_to_2(*argv, "scope");
}
scope = RT_SCOPE_NOWHERE;
G_filter.scopemask = 0;
@@ -554,12 +550,11 @@ int FAST_FUNC ipaddr_list_or_flush(char **argv, int flush)
continue;
}
if (G_filter.label) {
- SPRINT_BUF(b1);
const char *label;
if (tb[IFA_LABEL])
label = RTA_DATA(tb[IFA_LABEL]);
else
- label = ll_idx_n2a(ifa->ifa_index, b1);
+ label = ll_index_to_name(ifa->ifa_index);
if (fnmatch(G_filter.label, label, 0) != 0)
continue;
}
@@ -596,7 +591,7 @@ static int default_scope(inet_prefix *lcl)
}
/* Return value becomes exitcode. It's okay to not return at all */
-static int ipaddr_modify(int cmd, char **argv)
+static int ipaddr_modify(int cmd, int flags, char **argv)
{
static const char option[] ALIGN1 =
"peer\0""remote\0""broadcast\0""brd\0"
@@ -620,15 +615,17 @@ static int ipaddr_modify(int cmd, char **argv)
memset(&req, 0, sizeof(req));
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
- req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_flags = NLM_F_REQUEST | flags;
req.n.nlmsg_type = cmd;
req.ifa.ifa_family = preferred_family;
while (*argv) {
- const smalluint arg = index_in_strings(option, *argv);
- if (arg <= 1) { /* peer, remote */
+ unsigned arg = index_in_strings(option, *argv);
+ /* if search fails, "local" is assumed */
+ if ((int)arg >= 0)
NEXT_ARG();
+ if (arg <= 1) { /* peer, remote */
if (peer_len) {
duparg("peer", *argv);
}
@@ -641,7 +638,6 @@ static int ipaddr_modify(int cmd, char **argv)
req.ifa.ifa_prefixlen = peer.bitlen;
} else if (arg <= 3) { /* broadcast, brd */
inet_prefix addr;
- NEXT_ARG();
if (brd_len) {
duparg("broadcast", *argv);
}
@@ -658,7 +654,6 @@ static int ipaddr_modify(int cmd, char **argv)
}
} else if (arg == 4) { /* anycast */
inet_prefix addr;
- NEXT_ARG();
if (any_len) {
duparg("anycast", *argv);
}
@@ -670,22 +665,18 @@ static int ipaddr_modify(int cmd, char **argv)
any_len = addr.bytelen;
} else if (arg == 5) { /* scope */
uint32_t scope = 0;
- NEXT_ARG();
if (rtnl_rtscope_a2n(&scope, *argv)) {
- invarg(*argv, "scope");
+ invarg_1_to_2(*argv, "scope");
}
req.ifa.ifa_scope = scope;
scoped = 1;
} else if (arg == 6) { /* dev */
- NEXT_ARG();
d = *argv;
} else if (arg == 7) { /* label */
- NEXT_ARG();
l = *argv;
addattr_l(&req.n, sizeof(req), IFA_LABEL, l, strlen(l) + 1);
} else {
- if (arg == 8) /* local */
- NEXT_ARG();
+ /* local (specified or assumed) */
if (local_len) {
duparg2("local", *argv);
}
@@ -703,7 +694,7 @@ static int ipaddr_modify(int cmd, char **argv)
/* There was no "dev IFACE", but we need that */
bb_error_msg_and_die("need \"dev IFACE\"");
}
- if (l && strncmp(d, l, strlen(d)) != 0) {
+ if (l && !is_prefixed_with(l, d)) {
bb_error_msg_and_die("\"dev\" (%s) must match \"label\" (%s)", d, l);
}
@@ -722,7 +713,7 @@ static int ipaddr_modify(int cmd, char **argv)
}
brd = peer;
if (brd.bitlen <= 30) {
- for (i=31; i>=brd.bitlen; i--) {
+ for (i = 31; i >= brd.bitlen; i--) {
if (brd_len == -1)
brd.data[0] |= htonl(1<<(31-i));
else
@@ -751,16 +742,27 @@ static int ipaddr_modify(int cmd, char **argv)
int FAST_FUNC do_ipaddr(char **argv)
{
static const char commands[] ALIGN1 =
- "add\0""delete\0""list\0""show\0""lst\0""flush\0";
- smalluint cmd = 2;
+ /* 0 1 2 3 4 5 6 7 8 */
+ "add\0""change\0""chg\0""replace\0""delete\0""list\0""show\0""lst\0""flush\0";
+ int cmd = 2;
+
+ INIT_G();
+
if (*argv) {
cmd = index_in_substrings(commands, *argv);
- if (cmd > 5)
- bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
+ if (cmd < 0)
+ invarg_1_to_2(*argv, applet_name);
argv++;
- if (cmd <= 1)
- return ipaddr_modify((cmd == 0) ? RTM_NEWADDR : RTM_DELADDR, argv);
+ if (cmd <= 4) {
+ return ipaddr_modify(
+ /*cmd:*/ cmd == 4 ? RTM_DELADDR : RTM_NEWADDR,
+ /*flags:*/
+ cmd == 0 ? NLM_F_CREATE|NLM_F_EXCL : /* add */
+ cmd == 1 || cmd == 2 ? NLM_F_REPLACE : /* change */
+ cmd == 3 ? NLM_F_CREATE|NLM_F_REPLACE : /* replace */
+ 0 /* delete */
+ , argv);
+ }
}
- /* 2 == list, 3 == show, 4 == lst */
- return ipaddr_list_or_flush(argv, cmd == 5);
+ return ipaddr_list_or_flush(argv, cmd == 8);
}
diff --git a/release/src/router/busybox/networking/libiproute/iplink.c b/release/src/router/busybox/networking/libiproute/iplink.c
index bad2017feb..ae3ef0ceb2 100644
--- a/release/src/router/busybox/networking/libiproute/iplink.c
+++ b/release/src/router/busybox/networking/libiproute/iplink.c
@@ -1,26 +1,57 @@
/* vi: set sw=4 ts=4: */
/*
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ * Patrick McHardy <kaber@trash.net>
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
#include <net/if.h>
-#include <net/if_packet.h>
+/*#include <net/if_packet.h> - not needed? */
#include <netpacket/packet.h>
#include <netinet/if_ether.h>
+#include <linux/if_vlan.h>
#include "ip_common.h" /* #include "libbb.h" is inside */
#include "rt_names.h"
#include "utils.h"
+#undef ETH_P_8021AD
+#define ETH_P_8021AD 0x88A8
+#undef VLAN_FLAG_REORDER_HDR
+#define VLAN_FLAG_REORDER_HDR 0x1
+#undef VLAN_FLAG_GVRP
+#define VLAN_FLAG_GVRP 0x2
+#undef VLAN_FLAG_LOOSE_BINDING
+#define VLAN_FLAG_LOOSE_BINDING 0x4
+#undef VLAN_FLAG_MVRP
+#define VLAN_FLAG_MVRP 0x8
+#undef IFLA_VLAN_PROTOCOL
+#define IFLA_VLAN_PROTOCOL 5
+
#ifndef IFLA_LINKINFO
# define IFLA_LINKINFO 18
# define IFLA_INFO_KIND 1
+# define IFLA_INFO_DATA 2
+#endif
+
+#ifndef IFLA_VLAN_MAX
+# define IFLA_VLAN_ID 1
+# define IFLA_VLAN_FLAGS 2
+struct ifla_vlan_flags {
+ uint32_t flags;
+ uint32_t mask;
+};
#endif
/* taken from linux/sockios.h */
#define SIOCSIFNAME 0x8923 /* set interface name */
+#if 0
+# define dbg(...) bb_error_msg(__VA_ARGS__)
+#else
+# define dbg(...) ((void)0)
+#endif
+
/* Exits on error */
static int get_ctl_fd(void)
{
@@ -277,20 +308,112 @@ static int ipaddr_list_link(char **argv)
return ipaddr_list_or_flush(argv, 0);
}
+static void vlan_parse_opt(char **argv, struct nlmsghdr *n, unsigned int size)
+{
+ static const char keywords[] ALIGN1 =
+ "id\0"
+ "protocol\0"
+ "reorder_hdr\0"
+ "gvrp\0"
+ "mvrp\0"
+ "loose_binding\0"
+ ;
+ static const char protocols[] ALIGN1 =
+ "802.1q\0"
+ "802.1ad\0"
+ ;
+ static const char str_on_off[] ALIGN1 =
+ "on\0"
+ "off\0"
+ ;
+ enum {
+ ARG_id = 0,
+ ARG_reorder_hdr,
+ ARG_gvrp,
+ ARG_mvrp,
+ ARG_loose_binding,
+ ARG_protocol,
+ };
+ enum {
+ PROTO_8021Q = 0,
+ PROTO_8021AD,
+ };
+ enum {
+ PARM_on = 0,
+ PARM_off
+ };
+ int arg;
+ uint16_t id, proto;
+ struct ifla_vlan_flags flags = {};
+
+ while (*argv) {
+ arg = index_in_substrings(keywords, *argv);
+ if (arg < 0)
+ invarg_1_to_2(*argv, "type vlan");
+
+ NEXT_ARG();
+ if (arg == ARG_id) {
+ id = get_u16(*argv, "id");
+ addattr_l(n, size, IFLA_VLAN_ID, &id, sizeof(id));
+ } else if (arg == ARG_protocol) {
+ arg = index_in_substrings(protocols, *argv);
+ if (arg == PROTO_8021Q)
+ proto = ETH_P_8021Q;
+ else if (arg == PROTO_8021AD)
+ proto = ETH_P_8021AD;
+ else
+ bb_error_msg_and_die("unknown VLAN encapsulation protocol '%s'",
+ *argv);
+ addattr_l(n, size, IFLA_VLAN_PROTOCOL, &proto, sizeof(proto));
+ } else {
+ int param = index_in_strings(str_on_off, *argv);
+ if (param < 0)
+ die_must_be_on_off(nth_string(keywords, arg));
+
+ if (arg == ARG_reorder_hdr) {
+ flags.mask |= VLAN_FLAG_REORDER_HDR;
+ flags.flags &= ~VLAN_FLAG_REORDER_HDR;
+ if (param == PARM_on)
+ flags.flags |= VLAN_FLAG_REORDER_HDR;
+ } else if (arg == ARG_gvrp) {
+ flags.mask |= VLAN_FLAG_GVRP;
+ flags.flags &= ~VLAN_FLAG_GVRP;
+ if (param == PARM_on)
+ flags.flags |= VLAN_FLAG_GVRP;
+ } else if (arg == ARG_mvrp) {
+ flags.mask |= VLAN_FLAG_MVRP;
+ flags.flags &= ~VLAN_FLAG_MVRP;
+ if (param == PARM_on)
+ flags.flags |= VLAN_FLAG_MVRP;
+ } else { /*if (arg == ARG_loose_binding) */
+ flags.mask |= VLAN_FLAG_LOOSE_BINDING;
+ flags.flags &= ~VLAN_FLAG_LOOSE_BINDING;
+ if (param == PARM_on)
+ flags.flags |= VLAN_FLAG_LOOSE_BINDING;
+ }
+ }
+ argv++;
+ }
+
+ if (flags.mask)
+ addattr_l(n, size, IFLA_VLAN_FLAGS, &flags, sizeof(flags));
+}
+
#ifndef NLMSG_TAIL
#define NLMSG_TAIL(nmsg) \
((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
#endif
/* Return value becomes exitcode. It's okay to not return at all */
-static int do_change(char **argv, const unsigned rtm)
+static int do_add_or_delete(char **argv, const unsigned rtm)
{
static const char keywords[] ALIGN1 =
- "link\0""name\0""type\0""dev\0";
+ "link\0""name\0""type\0""dev\0""address\0";
enum {
ARG_link,
ARG_name,
ARG_type,
ARG_dev,
+ ARG_address,
};
struct rtnl_handle rth;
struct {
@@ -299,7 +422,11 @@ static int do_change(char **argv, const unsigned rtm)
char buf[1024];
} req;
smalluint arg;
- char *name_str = NULL, *link_str = NULL, *type_str = NULL, *dev_str = NULL;
+ char *name_str = NULL;
+ char *link_str = NULL;
+ char *type_str = NULL;
+ char *dev_str = NULL;
+ char *address_str = NULL;
memset(&req, 0, sizeof(req));
@@ -312,15 +439,24 @@ static int do_change(char **argv, const unsigned rtm)
while (*argv) {
arg = index_in_substrings(keywords, *argv);
+ if (arg == ARG_type) {
+ NEXT_ARG();
+ type_str = *argv++;
+ dbg("type_str:'%s'", type_str);
+ break;
+ }
if (arg == ARG_link) {
NEXT_ARG();
link_str = *argv;
+ dbg("link_str:'%s'", link_str);
} else if (arg == ARG_name) {
NEXT_ARG();
name_str = *argv;
- } else if (arg == ARG_type) {
+ dbg("name_str:'%s'", name_str);
+ } else if (arg == ARG_address) {
NEXT_ARG();
- type_str = *argv;
+ address_str = *argv;
+ dbg("address_str:'%s'", name_str);
} else {
if (arg == ARG_dev) {
if (dev_str)
@@ -328,6 +464,7 @@ static int do_change(char **argv, const unsigned rtm)
NEXT_ARG();
}
dev_str = *argv;
+ dbg("dev_str:'%s'", dev_str);
}
argv++;
}
@@ -339,6 +476,17 @@ static int do_change(char **argv, const unsigned rtm)
addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type_str,
strlen(type_str));
+
+ if (*argv) {
+ struct rtattr *data = NLMSG_TAIL(&req.n);
+ addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0);
+
+ if (strcmp(type_str, "vlan") == 0)
+ vlan_parse_opt(argv, &req.n, sizeof(req));
+
+ data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
+ }
+
linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
}
if (rtm != RTM_NEWLINK) {
@@ -352,11 +500,19 @@ static int do_change(char **argv, const unsigned rtm)
int idx = xll_name_to_index(link_str);
addattr_l(&req.n, sizeof(req), IFLA_LINK, &idx, 4);
}
+ if (address_str) {
+ unsigned char abuf[32];
+ int len = ll_addr_a2n(abuf, sizeof(abuf), address_str);
+ dbg("address len:%d", len);
+ if (len < 0)
+ return -1;
+ addattr_l(&req.n, sizeof(req), IFLA_ADDRESS, abuf, len);
+ }
}
if (name_str) {
const size_t name_len = strlen(name_str) + 1;
if (name_len < 2 || name_len > IFNAMSIZ)
- invarg(name_str, "name");
+ invarg_1_to_2(name_str, "name");
addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name_str, name_len);
}
if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
@@ -364,19 +520,177 @@ static int do_change(char **argv, const unsigned rtm)
return 0;
}
+/* Other keywords recognized by iproute2-3.12.0: */
+#if 0
+ } else if (matches(*argv, "broadcast") == 0 ||
+ strcmp(*argv, "brd") == 0) {
+ NEXT_ARG();
+ len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
+ if (len < 0)
+ return -1;
+ addattr_l(&req->n, sizeof(*req), IFLA_BROADCAST, abuf, len);
+ } else if (matches(*argv, "txqueuelen") == 0 ||
+ strcmp(*argv, "qlen") == 0 ||
+ matches(*argv, "txqlen") == 0) {
+ NEXT_ARG();
+ if (qlen != -1)
+ duparg("txqueuelen", *argv);
+ if (get_integer(&qlen, *argv, 0))
+ invarg_1_to_2(*argv, "txqueuelen");
+ addattr_l(&req->n, sizeof(*req), IFLA_TXQLEN, &qlen, 4);
+ } else if (strcmp(*argv, "mtu") == 0) {
+ NEXT_ARG();
+ if (mtu != -1)
+ duparg("mtu", *argv);
+ if (get_integer(&mtu, *argv, 0))
+ invarg_1_to_2(*argv, "mtu");
+ addattr_l(&req->n, sizeof(*req), IFLA_MTU, &mtu, 4);
+ } else if (strcmp(*argv, "netns") == 0) {
+ NEXT_ARG();
+ if (netns != -1)
+ duparg("netns", *argv);
+ if ((netns = get_netns_fd(*argv)) >= 0)
+ addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_FD, &netns, 4);
+ else if (get_integer(&netns, *argv, 0) == 0)
+ addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4);
+ else
+ invarg_1_to_2(*argv, "netns");
+ } else if (strcmp(*argv, "multicast") == 0) {
+ NEXT_ARG();
+ req->i.ifi_change |= IFF_MULTICAST;
+ if (strcmp(*argv, "on") == 0) {
+ req->i.ifi_flags |= IFF_MULTICAST;
+ } else if (strcmp(*argv, "off") == 0) {
+ req->i.ifi_flags &= ~IFF_MULTICAST;
+ } else
+ return on_off("multicast", *argv);
+ } else if (strcmp(*argv, "allmulticast") == 0) {
+ NEXT_ARG();
+ req->i.ifi_change |= IFF_ALLMULTI;
+ if (strcmp(*argv, "on") == 0) {
+ req->i.ifi_flags |= IFF_ALLMULTI;
+ } else if (strcmp(*argv, "off") == 0) {
+ req->i.ifi_flags &= ~IFF_ALLMULTI;
+ } else
+ return on_off("allmulticast", *argv);
+ } else if (strcmp(*argv, "promisc") == 0) {
+ NEXT_ARG();
+ req->i.ifi_change |= IFF_PROMISC;
+ if (strcmp(*argv, "on") == 0) {
+ req->i.ifi_flags |= IFF_PROMISC;
+ } else if (strcmp(*argv, "off") == 0) {
+ req->i.ifi_flags &= ~IFF_PROMISC;
+ } else
+ return on_off("promisc", *argv);
+ } else if (strcmp(*argv, "trailers") == 0) {
+ NEXT_ARG();
+ req->i.ifi_change |= IFF_NOTRAILERS;
+ if (strcmp(*argv, "off") == 0) {
+ req->i.ifi_flags |= IFF_NOTRAILERS;
+ } else if (strcmp(*argv, "on") == 0) {
+ req->i.ifi_flags &= ~IFF_NOTRAILERS;
+ } else
+ return on_off("trailers", *argv);
+ } else if (strcmp(*argv, "arp") == 0) {
+ NEXT_ARG();
+ req->i.ifi_change |= IFF_NOARP;
+ if (strcmp(*argv, "on") == 0) {
+ req->i.ifi_flags &= ~IFF_NOARP;
+ } else if (strcmp(*argv, "off") == 0) {
+ req->i.ifi_flags |= IFF_NOARP;
+ } else
+ return on_off("noarp", *argv);
+ } else if (strcmp(*argv, "vf") == 0) {
+ struct rtattr *vflist;
+ NEXT_ARG();
+ if (get_integer(&vf, *argv, 0)) {
+ invarg_1_to_2(*argv, "vf");
+ }
+ vflist = addattr_nest(&req->n, sizeof(*req),
+ IFLA_VFINFO_LIST);
+ len = iplink_parse_vf(vf, &argc, &argv, req);
+ if (len < 0)
+ return -1;
+ addattr_nest_end(&req->n, vflist);
+ } else if (matches(*argv, "master") == 0) {
+ int ifindex;
+ NEXT_ARG();
+ ifindex = ll_name_to_index(*argv);
+ if (!ifindex)
+ invarg_1_to_2(*argv, "master");
+ addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
+ &ifindex, 4);
+ } else if (matches(*argv, "nomaster") == 0) {
+ int ifindex = 0;
+ addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
+ &ifindex, 4);
+ } else if (matches(*argv, "dynamic") == 0) {
+ NEXT_ARG();
+ req->i.ifi_change |= IFF_DYNAMIC;
+ if (strcmp(*argv, "on") == 0) {
+ req->i.ifi_flags |= IFF_DYNAMIC;
+ } else if (strcmp(*argv, "off") == 0) {
+ req->i.ifi_flags &= ~IFF_DYNAMIC;
+ } else
+ return on_off("dynamic", *argv);
+ } else if (matches(*argv, "alias") == 0) {
+ NEXT_ARG();
+ addattr_l(&req->n, sizeof(*req), IFLA_IFALIAS,
+ *argv, strlen(*argv));
+ argc--; argv++;
+ break;
+ } else if (strcmp(*argv, "group") == 0) {
+ NEXT_ARG();
+ if (*group != -1)
+ duparg("group", *argv);
+ if (rtnl_group_a2n(group, *argv))
+ invarg_1_to_2(*argv, "group");
+ } else if (strcmp(*argv, "mode") == 0) {
+ int mode;
+ NEXT_ARG();
+ mode = get_link_mode(*argv);
+ if (mode < 0)
+ invarg_1_to_2(*argv, "mode");
+ addattr8(&req->n, sizeof(*req), IFLA_LINKMODE, mode);
+ } else if (strcmp(*argv, "state") == 0) {
+ int state;
+ NEXT_ARG();
+ state = get_operstate(*argv);
+ if (state < 0)
+ invarg_1_to_2(*argv, "state");
+ addattr8(&req->n, sizeof(*req), IFLA_OPERSTATE, state);
+ } else if (matches(*argv, "numtxqueues") == 0) {
+ NEXT_ARG();
+ if (numtxqueues != -1)
+ duparg("numtxqueues", *argv);
+ if (get_integer(&numtxqueues, *argv, 0))
+ invarg_1_to_2(*argv, "numtxqueues");
+ addattr_l(&req->n, sizeof(*req), IFLA_NUM_TX_QUEUES,
+ &numtxqueues, 4);
+ } else if (matches(*argv, "numrxqueues") == 0) {
+ NEXT_ARG();
+ if (numrxqueues != -1)
+ duparg("numrxqueues", *argv);
+ if (get_integer(&numrxqueues, *argv, 0))
+ invarg_1_to_2(*argv, "numrxqueues");
+ addattr_l(&req->n, sizeof(*req), IFLA_NUM_RX_QUEUES,
+ &numrxqueues, 4);
+ }
+#endif
+
/* Return value becomes exitcode. It's okay to not return at all */
int FAST_FUNC do_iplink(char **argv)
{
static const char keywords[] ALIGN1 =
"add\0""delete\0""set\0""show\0""lst\0""list\0";
if (*argv) {
- smalluint key = index_in_substrings(keywords, *argv);
- if (key > 5) /* invalid argument */
- bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
+ int key = index_in_substrings(keywords, *argv);
+ if (key < 0) /* invalid argument */
+ invarg_1_to_2(*argv, applet_name);
argv++;
if (key <= 1) /* add/delete */
- return do_change(argv, key ? RTM_DELLINK : RTM_NEWLINK);
- else if (key == 2) /* set */
+ return do_add_or_delete(argv, key ? RTM_DELLINK : RTM_NEWLINK);
+ if (key == 2) /* set */
return do_set(argv);
}
/* show, lst, list */
diff --git a/release/src/router/busybox/networking/libiproute/ipneigh.c b/release/src/router/busybox/networking/libiproute/ipneigh.c
new file mode 100644
index 0000000000..2a1c20e20b
--- /dev/null
+++ b/release/src/router/busybox/networking/libiproute/ipneigh.c
@@ -0,0 +1,357 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ *
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * Ported to Busybox by: Curt Brune <curt@cumulusnetworks.com>
+ */
+
+#include "ip_common.h" /* #include "libbb.h" is inside */
+#include "common_bufsiz.h"
+#include "rt_names.h"
+#include "utils.h"
+#include <linux/neighbour.h>
+#include <net/if_arp.h>
+
+//static int xshow_stats = 3;
+enum { xshow_stats = 3 };
+
+static inline uint32_t rta_getattr_u32(const struct rtattr *rta)
+{
+ return *(uint32_t *)RTA_DATA(rta);
+}
+
+#ifndef RTAX_RTTVAR
+#define RTAX_RTTVAR RTAX_HOPS
+#endif
+
+
+struct filter_t {
+ int family;
+ int index;
+ int state;
+ int unused_only;
+ inet_prefix pfx;
+ int flushed;
+ char *flushb;
+ int flushp;
+ int flushe;
+ struct rtnl_handle *rth;
+} FIX_ALIASING;
+typedef struct filter_t filter_t;
+
+#define G_filter (*(filter_t*)bb_common_bufsiz1)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
+
+static int flush_update(void)
+{
+ if (rtnl_send(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) {
+ bb_perror_msg("can't send flush request");
+ return -1;
+ }
+ G_filter.flushp = 0;
+ return 0;
+}
+
+static unsigned nud_state_a2n(char *arg)
+{
+ static const char keywords[] ALIGN1 =
+ /* "ip neigh show/flush" parameters: */
+ "permanent\0" "reachable\0" "noarp\0" "none\0"
+ "stale\0" "incomplete\0" "delay\0" "probe\0"
+ "failed\0"
+ ;
+ static uint8_t nuds[] ALIGN1 = {
+ NUD_PERMANENT,NUD_REACHABLE, NUD_NOARP,NUD_NONE,
+ NUD_STALE, NUD_INCOMPLETE,NUD_DELAY,NUD_PROBE,
+ NUD_FAILED
+ };
+ int id;
+
+ BUILD_BUG_ON(
+ (NUD_PERMANENT|NUD_REACHABLE| NUD_NOARP|NUD_NONE|
+ NUD_STALE| NUD_INCOMPLETE|NUD_DELAY|NUD_PROBE|
+ NUD_FAILED) > 0xff
+ );
+
+ id = index_in_substrings(keywords, arg);
+ if (id < 0)
+ bb_error_msg_and_die(bb_msg_invalid_arg_to, arg, "nud state");
+ return nuds[id];
+}
+
+#ifndef NDA_RTA
+#define NDA_RTA(r) \
+ ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
+#endif
+
+
+static int FAST_FUNC print_neigh(const struct sockaddr_nl *who UNUSED_PARAM,
+ struct nlmsghdr *n, void *arg UNUSED_PARAM)
+{
+ struct ndmsg *r = NLMSG_DATA(n);
+ int len = n->nlmsg_len;
+ struct rtattr *tb[NDA_MAX+1];
+
+ if (n->nlmsg_type != RTM_NEWNEIGH && n->nlmsg_type != RTM_DELNEIGH) {
+ bb_error_msg_and_die("not RTM_NEWNEIGH: %08x %08x %08x",
+ n->nlmsg_len, n->nlmsg_type,
+ n->nlmsg_flags);
+ }
+ len -= NLMSG_LENGTH(sizeof(*r));
+ if (len < 0) {
+ bb_error_msg_and_die("BUG: wrong nlmsg len %d", len);
+ }
+
+ if (G_filter.flushb && n->nlmsg_type != RTM_NEWNEIGH)
+ return 0;
+
+ if (G_filter.family && G_filter.family != r->ndm_family)
+ return 0;
+ if (G_filter.index && G_filter.index != r->ndm_ifindex)
+ return 0;
+ if (!(G_filter.state&r->ndm_state) &&
+ !(r->ndm_flags & NTF_PROXY) &&
+ (r->ndm_state || !(G_filter.state & 0x100)) &&
+ (r->ndm_family != AF_DECnet))
+ return 0;
+
+ parse_rtattr(tb, NDA_MAX, NDA_RTA(r), n->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
+
+ if (tb[NDA_DST]) {
+ if (G_filter.pfx.family) {
+ inet_prefix dst;
+ memset(&dst, 0, sizeof(dst));
+ dst.family = r->ndm_family;
+ memcpy(&dst.data, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST]));
+ if (inet_addr_match(&dst, &G_filter.pfx, G_filter.pfx.bitlen))
+ return 0;
+ }
+ }
+ if (G_filter.unused_only && tb[NDA_CACHEINFO]) {
+ struct nda_cacheinfo *ci = RTA_DATA(tb[NDA_CACHEINFO]);
+ if (ci->ndm_refcnt)
+ return 0;
+ }
+
+ if (G_filter.flushb) {
+ struct nlmsghdr *fn;
+ if (NLMSG_ALIGN(G_filter.flushp) + n->nlmsg_len > G_filter.flushe) {
+ if (flush_update())
+ return -1;
+ }
+ fn = (struct nlmsghdr*)(G_filter.flushb + NLMSG_ALIGN(G_filter.flushp));
+ memcpy(fn, n, n->nlmsg_len);
+ fn->nlmsg_type = RTM_DELNEIGH;
+ fn->nlmsg_flags = NLM_F_REQUEST;
+ fn->nlmsg_seq = ++(G_filter.rth->seq);
+ G_filter.flushp = (((char*)fn) + n->nlmsg_len) - G_filter.flushb;
+ G_filter.flushed++;
+ if (xshow_stats < 2)
+ return 0;
+ }
+
+ if (tb[NDA_DST]) {
+ printf("%s ",
+ format_host(r->ndm_family,
+ RTA_PAYLOAD(tb[NDA_DST]),
+ RTA_DATA(tb[NDA_DST]))
+ );
+ }
+ if (!G_filter.index && r->ndm_ifindex)
+ printf("dev %s ", ll_index_to_name(r->ndm_ifindex));
+ if (tb[NDA_LLADDR]) {
+ SPRINT_BUF(b1);
+ printf("lladdr %s", ll_addr_n2a(RTA_DATA(tb[NDA_LLADDR]),
+ RTA_PAYLOAD(tb[NDA_LLADDR]),
+ ARPHRD_ETHER,
+ b1, sizeof(b1)));
+ }
+ if (r->ndm_flags & NTF_ROUTER) {
+ printf(" router");
+ }
+ if (r->ndm_flags & NTF_PROXY) {
+ printf(" proxy");
+ }
+ if (tb[NDA_CACHEINFO] && xshow_stats) {
+ struct nda_cacheinfo *ci = RTA_DATA(tb[NDA_CACHEINFO]);
+ int hz = get_hz();
+
+ if (ci->ndm_refcnt)
+ printf(" ref %d", ci->ndm_refcnt);
+ printf(" used %d/%d/%d", ci->ndm_used/hz,
+ ci->ndm_confirmed/hz, ci->ndm_updated/hz);
+ }
+
+ if (tb[NDA_PROBES] && xshow_stats) {
+ uint32_t p = rta_getattr_u32(tb[NDA_PROBES]);
+ printf(" probes %u", p);
+ }
+
+ /*if (r->ndm_state)*/ {
+ int nud = r->ndm_state;
+ char c = ' ';
+#define PRINT_FLAG(f) \
+ if (nud & NUD_##f) { \
+ printf("%c"#f, c); \
+ c = ','; \
+ }
+ PRINT_FLAG(INCOMPLETE);
+ PRINT_FLAG(REACHABLE);
+ PRINT_FLAG(STALE);
+ PRINT_FLAG(DELAY);
+ PRINT_FLAG(PROBE);
+ PRINT_FLAG(FAILED);
+ PRINT_FLAG(NOARP);
+ PRINT_FLAG(PERMANENT);
+#undef PRINT_FLAG
+ }
+ bb_putchar('\n');
+
+ return 0;
+}
+
+static void ipneigh_reset_filter(void)
+{
+ memset(&G_filter, 0, sizeof(G_filter));
+ G_filter.state = ~0;
+}
+
+#define MAX_ROUNDS 10
+/* Return value becomes exitcode. It's okay to not return at all */
+static int FAST_FUNC ipneigh_list_or_flush(char **argv, int flush)
+{
+ static const char keywords[] ALIGN1 =
+ /* "ip neigh show/flush" parameters: */
+ "to\0" "dev\0" "nud\0";
+ enum {
+ KW_to, KW_dev, KW_nud,
+ };
+ struct rtnl_handle rth;
+ struct ndmsg ndm = { 0 };
+ char *filter_dev = NULL;
+ int state_given = 0;
+ int arg;
+
+ ipneigh_reset_filter();
+
+ if (flush && !*argv)
+ bb_error_msg_and_die(bb_msg_requires_arg, "\"ip neigh flush\"");
+
+ if (!G_filter.family)
+ G_filter.family = preferred_family;
+
+ G_filter.state = (flush) ?
+ ~(NUD_PERMANENT|NUD_NOARP) : 0xFF & ~NUD_NOARP;
+
+ while (*argv) {
+ arg = index_in_substrings(keywords, *argv);
+ if (arg == KW_dev) {
+ NEXT_ARG();
+ filter_dev = *argv;
+ } else if (arg == KW_nud) {
+ unsigned state;
+ NEXT_ARG();
+ if (!state_given) {
+ state_given = 1;
+ G_filter.state = 0;
+ }
+ if (strcmp(*argv, "all") == 0) {
+ state = ~0;
+ if (flush)
+ state &= ~NUD_NOARP;
+ } else {
+ state = nud_state_a2n(*argv);
+ }
+ if (state == 0)
+ state = 0x100;
+ G_filter.state |= state;
+ } else {
+ if (arg == KW_to) {
+ NEXT_ARG();
+ }
+ get_prefix(&G_filter.pfx, *argv, G_filter.family);
+ if (G_filter.family == AF_UNSPEC)
+ G_filter.family = G_filter.pfx.family;
+ }
+ argv++;
+ }
+
+ xrtnl_open(&rth);
+ ll_init_map(&rth);
+
+ if (filter_dev) {
+ G_filter.index = xll_name_to_index(filter_dev);
+ if (G_filter.index == 0) {
+ bb_error_msg_and_die("can't find device '%s'", filter_dev);
+ }
+ }
+
+ if (flush) {
+ int round = 0;
+ char flushb[4096-512];
+ G_filter.flushb = flushb;
+ G_filter.flushp = 0;
+ G_filter.flushe = sizeof(flushb);
+ G_filter.state &= ~NUD_FAILED;
+ G_filter.rth = &rth;
+
+ while (round < MAX_ROUNDS) {
+ if (xrtnl_wilddump_request(&rth, G_filter.family, RTM_GETNEIGH) < 0) {
+ bb_perror_msg_and_die("can't send dump request");
+ }
+ G_filter.flushed = 0;
+ if (xrtnl_dump_filter(&rth, print_neigh, NULL) < 0) {
+ bb_perror_msg_and_die("flush terminated");
+ }
+ if (G_filter.flushed == 0) {
+ if (round == 0)
+ puts("Nothing to flush");
+ else
+ printf("*** Flush is complete after %d round(s) ***\n", round);
+ return 0;
+ }
+ round++;
+ if (flush_update() < 0)
+ xfunc_die();
+ printf("\n*** Round %d, deleting %d entries ***\n", round, G_filter.flushed);
+ }
+ bb_error_msg_and_die("*** Flush not complete bailing out after %d rounds", MAX_ROUNDS);
+ }
+
+ ndm.ndm_family = G_filter.family;
+
+ if (rtnl_dump_request(&rth, RTM_GETNEIGH, &ndm, sizeof(struct ndmsg)) < 0) {
+ bb_perror_msg_and_die("can't send dump request");
+ }
+
+ if (xrtnl_dump_filter(&rth, print_neigh, NULL) < 0) {
+ bb_error_msg_and_die("dump terminated");
+ }
+
+ return 0;
+}
+
+/* Return value becomes exitcode. It's okay to not return at all */
+int FAST_FUNC do_ipneigh(char **argv)
+{
+ static const char ip_neigh_commands[] ALIGN1 =
+ /*0-1*/ "show\0" "flush\0";
+ int command_num;
+
+ INIT_G();
+
+ if (!*argv)
+ return ipneigh_list_or_flush(argv, 0);
+
+ command_num = index_in_substrings(ip_neigh_commands, *argv);
+ switch (command_num) {
+ case 0: /* show */
+ return ipneigh_list_or_flush(argv + 1, 0);
+ case 1: /* flush */
+ return ipneigh_list_or_flush(argv + 1, 1);
+ }
+ invarg_1_to_2(*argv, applet_name);
+ return 1;
+}
diff --git a/release/src/router/busybox/networking/libiproute/iproute.c b/release/src/router/busybox/networking/libiproute/iproute.c
index f8a67d9eed..48dc6e3d9c 100644
--- a/release/src/router/busybox/networking/libiproute/iproute.c
+++ b/release/src/router/busybox/networking/libiproute/iproute.c
@@ -11,6 +11,7 @@
*/
#include "ip_common.h" /* #include "libbb.h" is inside */
+#include "common_bufsiz.h"
#include "rt_names.h"
#include "utils.h"
@@ -43,7 +44,8 @@ struct filter_t {
} FIX_ALIASING;
typedef struct filter_t filter_t;
-#define G_filter (*(filter_t*)&bb_common_bufsiz1)
+#define G_filter (*(filter_t*)bb_common_bufsiz1)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
static int flush_update(void)
{
@@ -55,39 +57,15 @@ static int flush_update(void)
return 0;
}
-static unsigned get_hz(void)
-{
- static unsigned hz_internal;
- FILE *fp;
-
- if (hz_internal)
- return hz_internal;
-
- fp = fopen_for_read("/proc/net/psched");
- if (fp) {
- unsigned nom, denom;
-
- if (fscanf(fp, "%*08x%*08x%08x%08x", &nom, &denom) == 2)
- if (nom == 1000000)
- hz_internal = denom;
- fclose(fp);
- }
- if (!hz_internal)
- hz_internal = sysconf(_SC_CLK_TCK);
- return hz_internal;
-}
-
static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
struct nlmsghdr *n, void *arg UNUSED_PARAM)
{
struct rtmsg *r = NLMSG_DATA(n);
int len = n->nlmsg_len;
struct rtattr *tb[RTA_MAX+1];
- char abuf[256];
inet_prefix dst;
inet_prefix src;
int host_len = -1;
- SPRINT_BUF(b1);
if (n->nlmsg_type != RTM_NEWROUTE && n->nlmsg_type != RTM_DELROUTE) {
fprintf(stderr, "Not a route: %08x %08x %08x\n",
@@ -218,7 +196,7 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
if (NLMSG_ALIGN(G_filter.flushp) + n->nlmsg_len > G_filter.flushe) {
if (flush_update())
- bb_error_msg_and_die("flush");
+ xfunc_die();
}
fn = (void*)(G_filter.flushb + NLMSG_ALIGN(G_filter.flushp));
memcpy(fn, n, n->nlmsg_len);
@@ -236,22 +214,20 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
printf("Deleted ");
}
if (r->rtm_type != RTN_UNICAST /* && !G_filter.type - always 0 */) {
- printf("%s ", rtnl_rtntype_n2a(r->rtm_type, b1));
+ printf("%s ", rtnl_rtntype_n2a(r->rtm_type));
}
if (tb[RTA_DST]) {
if (r->rtm_dst_len != host_len) {
- printf("%s/%u ", rt_addr_n2a(r->rtm_family,
- RTA_DATA(tb[RTA_DST]),
- abuf, sizeof(abuf)),
- r->rtm_dst_len
- );
+ printf("%s/%u ",
+ rt_addr_n2a(r->rtm_family, RTA_DATA(tb[RTA_DST])),
+ r->rtm_dst_len
+ );
} else {
printf("%s ", format_host(r->rtm_family,
RTA_PAYLOAD(tb[RTA_DST]),
- RTA_DATA(tb[RTA_DST]),
- abuf, sizeof(abuf))
- );
+ RTA_DATA(tb[RTA_DST]))
+ );
}
} else if (r->rtm_dst_len) {
printf("0/%d ", r->rtm_dst_len);
@@ -260,17 +236,15 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
}
if (tb[RTA_SRC]) {
if (r->rtm_src_len != host_len) {
- printf("from %s/%u ", rt_addr_n2a(r->rtm_family,
- RTA_DATA(tb[RTA_SRC]),
- abuf, sizeof(abuf)),
- r->rtm_src_len
- );
+ printf("from %s/%u ",
+ rt_addr_n2a(r->rtm_family, RTA_DATA(tb[RTA_SRC])),
+ r->rtm_src_len
+ );
} else {
printf("from %s ", format_host(r->rtm_family,
RTA_PAYLOAD(tb[RTA_SRC]),
- RTA_DATA(tb[RTA_SRC]),
- abuf, sizeof(abuf))
- );
+ RTA_DATA(tb[RTA_SRC]))
+ );
}
} else if (r->rtm_src_len) {
printf("from 0/%u ", r->rtm_src_len);
@@ -278,8 +252,8 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
if (tb[RTA_GATEWAY] && G_filter.rvia.bitlen != host_len) {
printf("via %s ", format_host(r->rtm_family,
RTA_PAYLOAD(tb[RTA_GATEWAY]),
- RTA_DATA(tb[RTA_GATEWAY]),
- abuf, sizeof(abuf)));
+ RTA_DATA(tb[RTA_GATEWAY]))
+ );
}
if (tb[RTA_OIF]) {
printf("dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF])));
@@ -292,12 +266,24 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
and symbolic name will not be useful.
*/
printf(" src %s ", rt_addr_n2a(r->rtm_family,
- RTA_DATA(tb[RTA_PREFSRC]),
- abuf, sizeof(abuf)));
+ RTA_DATA(tb[RTA_PREFSRC])));
}
if (tb[RTA_PRIORITY]) {
printf(" metric %d ", *(uint32_t*)RTA_DATA(tb[RTA_PRIORITY]));
}
+ if (r->rtm_flags & RTNH_F_DEAD) {
+ printf("dead ");
+ }
+ if (r->rtm_flags & RTNH_F_ONLINK) {
+ printf("onlink ");
+ }
+ if (r->rtm_flags & RTNH_F_PERVASIVE) {
+ printf("pervasive ");
+ }
+ if (r->rtm_flags & RTM_F_NOTIFY) {
+ printf("notify ");
+ }
+
if (r->rtm_family == AF_INET6) {
struct rta_cacheinfo *ci = NULL;
if (tb[RTA_CACHEINFO]) {
@@ -329,18 +315,20 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
static int iproute_modify(int cmd, unsigned flags, char **argv)
{
static const char keywords[] ALIGN1 =
- "src\0""via\0""mtu\0""lock\0""protocol\0"IF_FEATURE_IP_RULE("table\0")
- "dev\0""oif\0""to\0""metric\0";
+ "src\0""via\0""mtu\0""lock\0""scope\0""protocol\0"IF_FEATURE_IP_RULE("table\0")
+ "dev\0""oif\0""to\0""metric\0""onlink\0";
enum {
ARG_src,
ARG_via,
ARG_mtu, PARM_lock,
+ ARG_scope,
ARG_protocol,
IF_FEATURE_IP_RULE(ARG_table,)
ARG_dev,
ARG_oif,
ARG_to,
ARG_metric,
+ ARG_onlink,
};
enum {
gw_ok = 1 << 0,
@@ -359,6 +347,7 @@ IF_FEATURE_IP_RULE(ARG_table,)
unsigned mxlock = 0;
char *d = NULL;
smalluint ok = 0;
+ smalluint scope_ok = 0;
int arg;
memset(&req, 0, sizeof(req));
@@ -367,15 +356,17 @@ IF_FEATURE_IP_RULE(ARG_table,)
req.n.nlmsg_flags = NLM_F_REQUEST | flags;
req.n.nlmsg_type = cmd;
req.r.rtm_family = preferred_family;
- if (RT_TABLE_MAIN) /* if it is zero, memset already did it */
+ if (RT_TABLE_MAIN != 0) /* if it is zero, memset already did it */
req.r.rtm_table = RT_TABLE_MAIN;
- if (RT_SCOPE_NOWHERE)
+ if (RT_SCOPE_NOWHERE != 0)
req.r.rtm_scope = RT_SCOPE_NOWHERE;
if (cmd != RTM_DELROUTE) {
- req.r.rtm_protocol = RTPROT_BOOT;
req.r.rtm_scope = RT_SCOPE_UNIVERSE;
- req.r.rtm_type = RTN_UNICAST;
+ if (RTPROT_BOOT != 0)
+ req.r.rtm_protocol = RTPROT_BOOT;
+ if (RTN_UNICAST != 0)
+ req.r.rtm_type = RTN_UNICAST;
}
mxrta->rta_type = RTA_METRICS;
@@ -408,11 +399,18 @@ IF_FEATURE_IP_RULE(ARG_table,)
}
mtu = get_unsigned(*argv, "mtu");
rta_addattr32(mxrta, sizeof(mxbuf), RTAX_MTU, mtu);
+ } else if (arg == ARG_scope) {
+ uint32_t scope;
+ NEXT_ARG();
+ if (rtnl_rtscope_a2n(&scope, *argv))
+ invarg_1_to_2(*argv, "scope");
+ req.r.rtm_scope = scope;
+ scope_ok = 1;
} else if (arg == ARG_protocol) {
uint32_t prot;
NEXT_ARG();
if (rtnl_rtprot_a2n(&prot, *argv))
- invarg(*argv, "protocol");
+ invarg_1_to_2(*argv, "protocol");
req.r.rtm_protocol = prot;
ok |= proto_ok;
#if ENABLE_FEATURE_IP_RULE
@@ -420,7 +418,7 @@ IF_FEATURE_IP_RULE(ARG_table,)
uint32_t tid;
NEXT_ARG();
if (rtnl_rttable_a2n(&tid, *argv))
- invarg(*argv, "table");
+ invarg_1_to_2(*argv, "table");
req.r.rtm_table = tid;
#endif
} else if (arg == ARG_dev || arg == ARG_oif) {
@@ -431,6 +429,8 @@ IF_FEATURE_IP_RULE(ARG_table,)
NEXT_ARG();
metric = get_u32(*argv, "metric");
addattr32(&req.n, sizeof(req), RTA_PRIORITY, metric);
+ } else if (arg == ARG_onlink) {
+ req.r.rtm_flags |= RTNH_F_ONLINK;
} else {
int type;
inet_prefix dst;
@@ -482,20 +482,22 @@ IF_FEATURE_IP_RULE(ARG_table,)
addattr_l(&req.n, sizeof(req), RTA_METRICS, RTA_DATA(mxrta), RTA_PAYLOAD(mxrta));
}
- if (req.r.rtm_type == RTN_LOCAL || req.r.rtm_type == RTN_NAT)
- req.r.rtm_scope = RT_SCOPE_HOST;
- else
- if (req.r.rtm_type == RTN_BROADCAST
- || req.r.rtm_type == RTN_MULTICAST
- || req.r.rtm_type == RTN_ANYCAST
- ) {
- req.r.rtm_scope = RT_SCOPE_LINK;
- }
- else if (req.r.rtm_type == RTN_UNICAST || req.r.rtm_type == RTN_UNSPEC) {
- if (cmd == RTM_DELROUTE)
- req.r.rtm_scope = RT_SCOPE_NOWHERE;
- else if (!(ok & gw_ok))
+ if (!scope_ok) {
+ if (req.r.rtm_type == RTN_LOCAL || req.r.rtm_type == RTN_NAT)
+ req.r.rtm_scope = RT_SCOPE_HOST;
+ else
+ if (req.r.rtm_type == RTN_BROADCAST
+ || req.r.rtm_type == RTN_MULTICAST
+ || req.r.rtm_type == RTN_ANYCAST
+ ) {
req.r.rtm_scope = RT_SCOPE_LINK;
+ }
+ else if (req.r.rtm_type == RTN_UNICAST || req.r.rtm_type == RTN_UNSPEC) {
+ if (cmd == RTM_DELROUTE)
+ req.r.rtm_scope = RT_SCOPE_NOWHERE;
+ else if (!(ok & gw_ok))
+ req.r.rtm_scope = RT_SCOPE_LINK;
+ }
}
if (req.r.rtm_family == AF_UNSPEC) {
@@ -604,7 +606,7 @@ static int iproute_list_or_flush(char **argv, int flush)
//G_filter.protocolmask = -1;
if (rtnl_rtprot_a2n(&prot, *argv)) {
if (index_in_strings(keywords, *argv) != KW_all)
- invarg(*argv, "protocol");
+ invarg_1_to_2(*argv, "protocol");
prot = 0;
//G_filter.protocolmask = 0;
}
@@ -629,10 +631,10 @@ static int iproute_list_or_flush(char **argv, int flush)
#if ENABLE_FEATURE_IP_RULE
uint32_t tid;
if (rtnl_rttable_a2n(&tid, *argv))
- invarg(*argv, "table");
+ invarg_1_to_2(*argv, "table");
G_filter.tb = tid;
#else
- invarg(*argv, "table");
+ invarg_1_to_2(*argv, "table");
#endif
}
} else if (arg == KW_cache) {
@@ -901,6 +903,8 @@ int FAST_FUNC do_iproute(char **argv)
unsigned flags = 0;
int cmd = RTM_NEWROUTE;
+ INIT_G();
+
if (!*argv)
return iproute_list_or_flush(argv, 0);
@@ -939,7 +943,7 @@ int FAST_FUNC do_iproute(char **argv)
case 11: /* flush */
return iproute_list_or_flush(argv+1, 1);
default:
- bb_error_msg_and_die("unknown command %s", *argv);
+ invarg_1_to_2(*argv, applet_name);
}
return iproute_modify(cmd, flags, argv+1);
diff --git a/release/src/router/busybox/networking/libiproute/iprule.c b/release/src/router/busybox/networking/libiproute/iprule.c
index dd3265c7cd..dba64346f3 100644
--- a/release/src/router/busybox/networking/libiproute/iprule.c
+++ b/release/src/router/busybox/networking/libiproute/iprule.c
@@ -44,8 +44,6 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM,
int len = n->nlmsg_len;
int host_len = -1;
struct rtattr * tb[RTA_MAX+1];
- char abuf[256];
- SPRINT_BUF(b1);
if (n->nlmsg_type != RTM_NEWRULE)
return 0;
@@ -72,16 +70,16 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM,
printf("from ");
if (tb[RTA_SRC]) {
if (r->rtm_src_len != host_len) {
- printf("%s/%u", rt_addr_n2a(r->rtm_family,
- RTA_DATA(tb[RTA_SRC]),
- abuf, sizeof(abuf)),
+ printf("%s/%u",
+ rt_addr_n2a(r->rtm_family, RTA_DATA(tb[RTA_SRC])),
r->rtm_src_len
- );
+ );
} else {
fputs(format_host(r->rtm_family,
- RTA_PAYLOAD(tb[RTA_SRC]),
- RTA_DATA(tb[RTA_SRC]),
- abuf, sizeof(abuf)), stdout);
+ RTA_PAYLOAD(tb[RTA_SRC]),
+ RTA_DATA(tb[RTA_SRC])),
+ stdout
+ );
}
} else if (r->rtm_src_len) {
printf("0/%d", r->rtm_src_len);
@@ -93,22 +91,20 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM,
if (tb[RTA_DST]) {
if (r->rtm_dst_len != host_len) {
printf("to %s/%u ", rt_addr_n2a(r->rtm_family,
- RTA_DATA(tb[RTA_DST]),
- abuf, sizeof(abuf)),
+ RTA_DATA(tb[RTA_DST])),
r->rtm_dst_len
);
} else {
printf("to %s ", format_host(r->rtm_family,
RTA_PAYLOAD(tb[RTA_DST]),
- RTA_DATA(tb[RTA_DST]),
- abuf, sizeof(abuf)));
+ RTA_DATA(tb[RTA_DST])));
}
} else if (r->rtm_dst_len) {
printf("to 0/%d ", r->rtm_dst_len);
}
if (r->rtm_tos) {
- printf("tos %s ", rtnl_dsfield_n2a(r->rtm_tos, b1));
+ printf("tos %s ", rtnl_dsfield_n2a(r->rtm_tos));
}
if (tb[RTA_PROTOINFO]) {
printf("fwmark %#x ", *(uint32_t*)RTA_DATA(tb[RTA_PROTOINFO]));
@@ -119,7 +115,7 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM,
}
if (r->rtm_table)
- printf("lookup %s ", rtnl_rttable_n2a(r->rtm_table, b1));
+ printf("lookup %s ", rtnl_rttable_n2a(r->rtm_table));
if (tb[RTA_FLOW]) {
uint32_t to = *(uint32_t*)RTA_DATA(tb[RTA_FLOW]);
@@ -127,10 +123,10 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM,
to &= 0xFFFF;
if (from) {
printf("realms %s/",
- rtnl_rtrealm_n2a(from, b1));
+ rtnl_rtrealm_n2a(from));
}
printf("%s ",
- rtnl_rtrealm_n2a(to, b1));
+ rtnl_rtrealm_n2a(to));
}
if (r->rtm_type == RTN_NAT) {
@@ -138,12 +134,12 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM,
printf("map-to %s ",
format_host(r->rtm_family,
RTA_PAYLOAD(tb[RTA_GATEWAY]),
- RTA_DATA(tb[RTA_GATEWAY]),
- abuf, sizeof(abuf)));
+ RTA_DATA(tb[RTA_GATEWAY]))
+ );
} else
printf("masquerade");
} else if (r->rtm_type != RTN_UNICAST)
- fputs(rtnl_rtntype_n2a(r->rtm_type, b1), stdout);
+ fputs(rtnl_rtntype_n2a(r->rtm_type), stdout);
bb_putchar('\n');
/*fflush_all();*/
@@ -213,7 +209,7 @@ static int iprule_modify(int cmd, char **argv)
while (*argv) {
key = index_in_substrings(keywords, *argv) + 1;
if (key == 0) /* no match found in keywords array, bail out. */
- bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
+ invarg_1_to_2(*argv, applet_name);
if (key == ARG_from) {
inet_prefix dst;
NEXT_ARG();
@@ -238,7 +234,7 @@ static int iprule_modify(int cmd, char **argv)
uint32_t tos;
NEXT_ARG();
if (rtnl_dsfield_a2n(&tos, *argv))
- invarg(*argv, "TOS");
+ invarg_1_to_2(*argv, "TOS");
req.r.rtm_tos = tos;
} else if (key == ARG_fwmark) {
uint32_t fwmark;
@@ -249,7 +245,7 @@ static int iprule_modify(int cmd, char **argv)
uint32_t realm;
NEXT_ARG();
if (get_rt_realms(&realm, *argv))
- invarg(*argv, "realms");
+ invarg_1_to_2(*argv, "realms");
addattr32(&req.n, sizeof(req), RTA_FLOW, realm);
} else if (key == ARG_table ||
key == ARG_lookup
@@ -257,7 +253,7 @@ static int iprule_modify(int cmd, char **argv)
uint32_t tid;
NEXT_ARG();
if (rtnl_rttable_a2n(&tid, *argv))
- invarg(*argv, "table ID");
+ invarg_1_to_2(*argv, "table ID");
req.r.rtm_table = tid;
table_ok = 1;
} else if (key == ARG_dev ||
@@ -280,7 +276,7 @@ static int iprule_modify(int cmd, char **argv)
if (key == ARG_help)
bb_show_usage();
if (rtnl_rtntype_a2n(&type, *argv))
- invarg(*argv, "type");
+ invarg_1_to_2(*argv, "type");
req.r.rtm_type = type;
}
argv++;
@@ -306,9 +302,9 @@ int FAST_FUNC do_iprule(char **argv)
static const char ip_rule_commands[] ALIGN1 =
"add\0""delete\0""list\0""show\0";
if (*argv) {
- smalluint cmd = index_in_substrings(ip_rule_commands, *argv);
- if (cmd > 3)
- bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
+ int cmd = index_in_substrings(ip_rule_commands, *argv);
+ if (cmd < 0)
+ invarg_1_to_2(*argv, applet_name);
argv++;
if (cmd < 2)
return iprule_modify((cmd == 0) ? RTM_NEWRULE : RTM_DELRULE, argv);
diff --git a/release/src/router/busybox/networking/libiproute/iptunnel.c b/release/src/router/busybox/networking/libiproute/iptunnel.c
index 5942feafc4..eb136e435d 100644
--- a/release/src/router/busybox/networking/libiproute/iptunnel.c
+++ b/release/src/router/busybox/networking/libiproute/iptunnel.c
@@ -294,7 +294,7 @@ static void parse_args(char **argv, int cmd, struct ip_tunnel_parm *p)
if (key != ARG_inherit) {
uval = get_unsigned(*argv, "TTL");
if (uval > 255)
- invarg(*argv, "TTL must be <=255");
+ invarg_1_to_2(*argv, "TTL");
p->iph.ttl = uval;
}
} else if (key == ARG_tos ||
@@ -305,7 +305,7 @@ static void parse_args(char **argv, int cmd, struct ip_tunnel_parm *p)
key = index_in_strings(keywords, *argv);
if (key != ARG_inherit) {
if (rtnl_dsfield_a2n(&uval, *argv))
- invarg(*argv, "TOS");
+ invarg_1_to_2(*argv, "TOS");
p->iph.tos = uval;
} else
p->iph.tos = 1;
@@ -404,22 +404,18 @@ static int do_del(char **argv)
static void print_tunnel(struct ip_tunnel_parm *p)
{
- char s1[256];
- char s2[256];
- char s3[64];
- char s4[64];
-
- format_host(AF_INET, 4, &p->iph.daddr, s1, sizeof(s1));
- format_host(AF_INET, 4, &p->iph.saddr, s2, sizeof(s2));
- inet_ntop(AF_INET, &p->i_key, s3, sizeof(s3));
- inet_ntop(AF_INET, &p->o_key, s4, sizeof(s4));
+ char s3[INET_ADDRSTRLEN];
+ char s4[INET_ADDRSTRLEN];
printf("%s: %s/ip remote %s local %s ",
- p->name,
- p->iph.protocol == IPPROTO_IPIP ? "ip" :
- (p->iph.protocol == IPPROTO_GRE ? "gre" :
- (p->iph.protocol == IPPROTO_IPV6 ? "ipv6" : "unknown")),
- p->iph.daddr ? s1 : "any", p->iph.saddr ? s2 : "any");
+ p->name,
+ p->iph.protocol == IPPROTO_IPIP ? "ip" :
+ p->iph.protocol == IPPROTO_GRE ? "gre" :
+ p->iph.protocol == IPPROTO_IPV6 ? "ipv6" :
+ "unknown",
+ p->iph.daddr ? format_host(AF_INET, 4, &p->iph.daddr) : "any",
+ p->iph.saddr ? format_host(AF_INET, 4, &p->iph.saddr) : "any"
+ );
if (p->link) {
char *n = do_ioctl_get_ifname(p->link);
if (n) {
@@ -432,20 +428,21 @@ static void print_tunnel(struct ip_tunnel_parm *p)
else
printf(" ttl inherit ");
if (p->iph.tos) {
- SPRINT_BUF(b1);
printf(" tos");
if (p->iph.tos & 1)
printf(" inherit");
if (p->iph.tos & ~1)
printf("%c%s ", p->iph.tos & 1 ? '/' : ' ',
- rtnl_dsfield_n2a(p->iph.tos & ~1, b1));
+ rtnl_dsfield_n2a(p->iph.tos & ~1));
}
if (!(p->iph.frag_off & htons(IP_DF)))
printf(" nopmtudisc");
+ inet_ntop(AF_INET, &p->i_key, s3, sizeof(s3));
+ inet_ntop(AF_INET, &p->o_key, s4, sizeof(s4));
if ((p->i_flags & GRE_KEY) && (p->o_flags & GRE_KEY) && p->o_key == p->i_key)
printf(" key %s", s3);
- else if ((p->i_flags | p->o_flags) & GRE_KEY) {
+ else {
if (p->i_flags & GRE_KEY)
printf(" ikey %s ", s3);
if (p->o_flags & GRE_KEY)
@@ -561,9 +558,9 @@ int FAST_FUNC do_iptunnel(char **argv)
enum { ARG_add = 0, ARG_change, ARG_del, ARG_show, ARG_list, ARG_lst };
if (*argv) {
- smalluint key = index_in_substrings(keywords, *argv);
- if (key > 5)
- bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
+ int key = index_in_substrings(keywords, *argv);
+ if (key < 0)
+ invarg_1_to_2(*argv, applet_name);
argv++;
if (key == ARG_add)
return do_add(SIOCADDTUNNEL, argv);
diff --git a/release/src/router/busybox/networking/libiproute/libnetlink.c b/release/src/router/busybox/networking/libiproute/libnetlink.c
index c7533a4a70..cbb5daf95f 100644
--- a/release/src/router/busybox/networking/libiproute/libnetlink.c
+++ b/release/src/router/busybox/networking/libiproute/libnetlink.c
@@ -71,11 +71,15 @@ int FAST_FUNC rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, in
struct nlmsghdr nlh;
struct sockaddr_nl nladdr;
struct iovec iov[2] = { { &nlh, sizeof(nlh) }, { req, len } };
+ /* Use designated initializers, struct layout is non-portable */
struct msghdr msg = {
- (void*)&nladdr, sizeof(nladdr),
- iov, 2,
- NULL, 0,
- 0
+ .msg_name = (void*)&nladdr,
+ .msg_namelen = sizeof(nladdr),
+ .msg_iov = iov,
+ .msg_iovlen = 2,
+ .msg_control = NULL,
+ .msg_controllen = 0,
+ .msg_flags = 0
};
memset(&nladdr, 0, sizeof(nladdr));
@@ -104,12 +108,15 @@ static int rtnl_dump_filter(struct rtnl_handle *rth,
while (1) {
int status;
struct nlmsghdr *h;
-
+ /* Use designated initializers, struct layout is non-portable */
struct msghdr msg = {
- (void*)&nladdr, sizeof(nladdr),
- &iov, 1,
- NULL, 0,
- 0
+ .msg_name = (void*)&nladdr,
+ .msg_namelen = sizeof(nladdr),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ .msg_control = NULL,
+ .msg_controllen = 0,
+ .msg_flags = 0
};
status = recvmsg(rth->fd, &msg, 0);
@@ -211,11 +218,15 @@ int FAST_FUNC rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
struct sockaddr_nl nladdr;
struct iovec iov = { (void*)n, n->nlmsg_len };
char *buf = xmalloc(8*1024); /* avoid big stack buffer */
+ /* Use designated initializers, struct layout is non-portable */
struct msghdr msg = {
- (void*)&nladdr, sizeof(nladdr),
- &iov, 1,
- NULL, 0,
- 0
+ .msg_name = (void*)&nladdr,
+ .msg_namelen = sizeof(nladdr),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ .msg_control = NULL,
+ .msg_controllen = 0,
+ .msg_flags = 0
};
memset(&nladdr, 0, sizeof(nladdr));
diff --git a/release/src/router/busybox/networking/libiproute/ll_map.c b/release/src/router/busybox/networking/libiproute/ll_map.c
index 27cd90f34e..af9eb46f7e 100644
--- a/release/src/router/busybox/networking/libiproute/ll_map.c
+++ b/release/src/router/busybox/networking/libiproute/ll_map.c
@@ -86,7 +86,8 @@ int FAST_FUNC ll_remember_index(const struct sockaddr_nl *who UNUSED_PARAM,
return 0;
}
-const char FAST_FUNC *ll_idx_n2a(int idx, char *buf)
+static
+const char FAST_FUNC *ll_idx_n2a(int idx/*, char *buf*/)
{
struct idxmap *im;
@@ -95,16 +96,15 @@ const char FAST_FUNC *ll_idx_n2a(int idx, char *buf)
im = find_by_index(idx);
if (im)
return im->name;
- snprintf(buf, 16, "if%d", idx);
- return buf;
+ //snprintf(buf, 16, "if%d", idx);
+ //return buf;
+ return auto_string(xasprintf("if%d", idx));
}
-
const char FAST_FUNC *ll_index_to_name(int idx)
{
- static char nbuf[16];
-
- return ll_idx_n2a(idx, nbuf);
+ //static char nbuf[16];
+ return ll_idx_n2a(idx/*, nbuf*/);
}
#ifdef UNUSED
@@ -136,7 +136,6 @@ unsigned FAST_FUNC ll_index_to_flags(int idx)
int FAST_FUNC xll_name_to_index(const char *name)
{
int ret = 0;
- int sock_fd;
/* caching is not warranted - no users which repeatedly call it */
#ifdef UNUSED
@@ -164,30 +163,8 @@ int FAST_FUNC xll_name_to_index(const char *name)
}
}
}
- /* We have not found the interface in our cache, but the kernel
- * may still know about it. One reason is that we may be using
- * module on-demand loading, which means that the kernel will
- * load the module and make the interface exist only when
- * we explicitely request it (check for dev_load() in net/core/dev.c).
- * I can think of other similar scenario, but they are less common...
- * Jean II */
#endif
-
- sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
- if (sock_fd >= 0) {
- struct ifreq ifr;
- int tmp;
-
- strncpy_IFNAMSIZ(ifr.ifr_name, name);
- ifr.ifr_ifindex = -1;
- tmp = ioctl(sock_fd, SIOCGIFINDEX, &ifr);
- close(sock_fd);
- if (tmp >= 0)
- /* In theory, we should redump the interface list
- * to update our cache, this is left as an exercise
- * to the reader... Jean II */
- ret = ifr.ifr_ifindex;
- }
+ ret = if_nametoindex(name);
/* out:*/
if (ret <= 0)
bb_error_msg_and_die("can't find device '%s'", name);
diff --git a/release/src/router/busybox/networking/libiproute/ll_map.h b/release/src/router/busybox/networking/libiproute/ll_map.h
index c5d3834222..7ea383c81a 100644
--- a/release/src/router/busybox/networking/libiproute/ll_map.h
+++ b/release/src/router/busybox/networking/libiproute/ll_map.h
@@ -7,8 +7,8 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
int ll_remember_index(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) FAST_FUNC;
int ll_init_map(struct rtnl_handle *rth) FAST_FUNC;
int xll_name_to_index(const char *name) FAST_FUNC;
+//static: const char *ll_idx_n2a(int idx, char *buf) FAST_FUNC;
const char *ll_index_to_name(int idx) FAST_FUNC;
-const char *ll_idx_n2a(int idx, char *buf) FAST_FUNC;
/* int ll_index_to_type(int idx); */
unsigned ll_index_to_flags(int idx) FAST_FUNC;
diff --git a/release/src/router/busybox/networking/libiproute/ll_proto.c b/release/src/router/busybox/networking/libiproute/ll_proto.c
index 7aac8364d3..4c32ae5741 100644
--- a/release/src/router/busybox/networking/libiproute/ll_proto.c
+++ b/release/src/router/busybox/networking/libiproute/ll_proto.c
@@ -14,19 +14,10 @@
#include <netinet/if_ether.h>
-#if !ENABLE_WERROR
-#warning de-bloat
-#endif
-/* Before re-enabling this, please (1) conditionalize exotic protocols
- * on CONFIG_something, and (2) decouple strings and numbers
- * (use llproto_ids[] = n,n,n..; and llproto_names[] = "loop\0" "pup\0" ...;)
- */
+/* Please conditionalize exotic protocols on CONFIG_something */
-#define __PF(f,n) { ETH_P_##f, #n },
-static struct {
- int id;
- const char *name;
-} llproto_names[] = {
+static const uint16_t llproto_ids[] = {
+#define __PF(f,n) ETH_P_##f,
__PF(LOOP,loop)
__PF(PUP,pup)
#ifdef ETH_P_PUPAT
@@ -86,33 +77,104 @@ __PF(IRDA,irda)
__PF(ECONET,econet)
#endif
-{ 0x8100, "802.1Q" },
-{ ETH_P_IP, "ipv4" },
+0x8100,
+ETH_P_IP
};
#undef __PF
+/* Keep declarations above and below in sync! */
+
+static const char llproto_names[] ALIGN1 =
+#define __PF(f,n) #n "\0"
+__PF(LOOP,loop)
+__PF(PUP,pup)
+#ifdef ETH_P_PUPAT
+__PF(PUPAT,pupat)
+#endif
+__PF(IP,ip)
+__PF(X25,x25)
+__PF(ARP,arp)
+__PF(BPQ,bpq)
+#ifdef ETH_P_IEEEPUP
+__PF(IEEEPUP,ieeepup)
+#endif
+#ifdef ETH_P_IEEEPUPAT
+__PF(IEEEPUPAT,ieeepupat)
+#endif
+__PF(DEC,dec)
+__PF(DNA_DL,dna_dl)
+__PF(DNA_RC,dna_rc)
+__PF(DNA_RT,dna_rt)
+__PF(LAT,lat)
+__PF(DIAG,diag)
+__PF(CUST,cust)
+__PF(SCA,sca)
+__PF(RARP,rarp)
+__PF(ATALK,atalk)
+__PF(AARP,aarp)
+__PF(IPX,ipx)
+__PF(IPV6,ipv6)
+#ifdef ETH_P_PPP_DISC
+__PF(PPP_DISC,ppp_disc)
+#endif
+#ifdef ETH_P_PPP_SES
+__PF(PPP_SES,ppp_ses)
+#endif
+#ifdef ETH_P_ATMMPOA
+__PF(ATMMPOA,atmmpoa)
+#endif
+#ifdef ETH_P_ATMFATE
+__PF(ATMFATE,atmfate)
+#endif
+
+__PF(802_3,802_3)
+__PF(AX25,ax25)
+__PF(ALL,all)
+__PF(802_2,802_2)
+__PF(SNAP,snap)
+__PF(DDCMP,ddcmp)
+__PF(WAN_PPP,wan_ppp)
+__PF(PPP_MP,ppp_mp)
+__PF(LOCALTALK,localtalk)
+__PF(PPPTALK,ppptalk)
+__PF(TR_802_2,tr_802_2)
+__PF(MOBITEX,mobitex)
+__PF(CONTROL,control)
+__PF(IRDA,irda)
+#ifdef ETH_P_ECONET
+__PF(ECONET,econet)
+#endif
+
+"802.1Q" "\0"
+"ipv4" "\0"
+;
+#undef __PF
+
const char* FAST_FUNC ll_proto_n2a(unsigned short id, char *buf, int len)
{
unsigned i;
id = ntohs(id);
- for (i = 0; i < ARRAY_SIZE(llproto_names); i++) {
- if (llproto_names[i].id == id)
- return llproto_names[i].name;
+ for (i = 0; i < ARRAY_SIZE(llproto_ids); i++) {
+ if (llproto_ids[i] == id)
+ return nth_string(llproto_names, i);
}
- snprintf(buf, len, "[%d]", id);
+ snprintf(buf, len, "[%u]", id);
return buf;
}
int FAST_FUNC ll_proto_a2n(unsigned short *id, char *buf)
{
unsigned i;
- for (i = 0; i < ARRAY_SIZE(llproto_names); i++) {
- if (strcasecmp(llproto_names[i].name, buf) == 0) {
- i = llproto_names[i].id;
- goto good;
- }
+ const char *name = llproto_names;
+ for (i = 0; i < ARRAY_SIZE(llproto_ids); i++) {
+ if (strcasecmp(name, buf) == 0) {
+ i = llproto_ids[i];
+ goto good;
+ }
+ name += strlen(name) + 1;
}
+ errno = 0;
i = bb_strtou(buf, NULL, 0);
if (errno || i > 0xffff)
return -1;
diff --git a/release/src/router/busybox/networking/libiproute/ll_types.c b/release/src/router/busybox/networking/libiproute/ll_types.c
index bb42e269e5..62ee0cc549 100644
--- a/release/src/router/busybox/networking/libiproute/ll_types.c
+++ b/release/src/router/busybox/networking/libiproute/ll_types.c
@@ -16,7 +16,7 @@
const char* FAST_FUNC ll_type_n2a(int type, char *buf)
{
- static const char arphrd_name[] =
+ static const char arphrd_name[] ALIGN1 =
/* 0, */ "generic" "\0"
/* ARPHRD_LOOPBACK, */ "loopback" "\0"
/* ARPHRD_ETHER, */ "ether" "\0"
@@ -105,7 +105,7 @@ const char* FAST_FUNC ll_type_n2a(int type, char *buf)
/* Keep these arrays in sync! */
- static const uint16_t arphrd_type[] = {
+ static const uint16_t arphrd_type[] ALIGN2 = {
0, /* "generic" "\0" */
ARPHRD_LOOPBACK, /* "loopback" "\0" */
ARPHRD_ETHER, /* "ether" "\0" */
diff --git a/release/src/router/busybox/networking/libiproute/rt_names.c b/release/src/router/busybox/networking/libiproute/rt_names.c
index c474ab903e..51f2e9bdb1 100644
--- a/release/src/router/busybox/networking/libiproute/rt_names.c
+++ b/release/src/router/busybox/networking/libiproute/rt_names.c
@@ -10,20 +10,32 @@
#include "libbb.h"
#include "rt_names.h"
+#define CONFDIR CONFIG_FEATURE_IP_ROUTE_DIR
+
typedef struct rtnl_tab_t {
const char *cached_str;
unsigned cached_result;
- const char *tab[256];
+ /* upstream version switched to a hash table and removed
+ * id < 256 limit. For now bbox bumps this array size from 256
+ * to 1024. If you plan to change this to a hash table,
+ * consider merging several hash tables we have (for example,
+ * awk has resizable one!
+ */
+#define RT_TABLE_MAX 1023
+ const char *tab[RT_TABLE_MAX+1];
} rtnl_tab_t;
static void rtnl_tab_initialize(const char *file, const char **tab)
{
char *token[2];
- parser_t *parser = config_open2(file, fopen_for_read);
+ char fullname[sizeof(CONFDIR"/rt_dsfield") + 8];
+ parser_t *parser;
+ sprintf(fullname, CONFDIR"/rt_%s", file);
+ parser = config_open2(fullname, fopen_for_read);
while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL)) {
unsigned id = bb_strtou(token[0], NULL, 0);
- if (id > 256) {
+ if (id > RT_TABLE_MAX) {
bb_error_msg("database %s is corrupted at line %d",
file, parser->lineno);
break;
@@ -42,7 +54,7 @@ static int rtnl_a2n(rtnl_tab_t *tab, uint32_t *id, const char *arg, int base)
return 0;
}
- for (i = 0; i < 256; i++) {
+ for (i = 0; i <= RT_TABLE_MAX; i++) {
if (tab->tab[i]
&& strcmp(tab->tab[i], arg) == 0
) {
@@ -54,7 +66,7 @@ static int rtnl_a2n(rtnl_tab_t *tab, uint32_t *id, const char *arg, int base)
}
i = bb_strtou(arg, NULL, base);
- if (i > 255)
+ if (i > RT_TABLE_MAX)
return -1;
*id = i;
return 0;
@@ -85,24 +97,23 @@ static void rtnl_rtprot_initialize(void)
return;
rtnl_rtprot_tab = xzalloc(sizeof(*rtnl_rtprot_tab));
memcpy(rtnl_rtprot_tab->tab, init_tab, sizeof(init_tab));
- rtnl_tab_initialize("/etc/iproute2/rt_protos", rtnl_rtprot_tab->tab);
+ rtnl_tab_initialize("protos", rtnl_rtprot_tab->tab);
}
-const char* FAST_FUNC rtnl_rtprot_n2a(int id, char *buf)
+#if 0 /* UNUSED */
+const char* FAST_FUNC rtnl_rtprot_n2a(int id)
{
- if (id < 0 || id >= 256) {
- sprintf(buf, "%d", id);
- return buf;
+ if (id < 0 || id > RT_TABLE_MAX) {
+ return itoa(id);
}
rtnl_rtprot_initialize();
if (rtnl_rtprot_tab->tab[id])
return rtnl_rtprot_tab->tab[id];
- /* buf is SPRINT_BSIZE big */
- sprintf(buf, "%d", id);
- return buf;
+ return itoa(id);
}
+#endif
int FAST_FUNC rtnl_rtprot_a2n(uint32_t *id, char *arg)
{
@@ -123,23 +134,20 @@ static void rtnl_rtscope_initialize(void)
rtnl_rtscope_tab->tab[254] = "host";
rtnl_rtscope_tab->tab[253] = "link";
rtnl_rtscope_tab->tab[200] = "site";
- rtnl_tab_initialize("/etc/iproute2/rt_scopes", rtnl_rtscope_tab->tab);
+ rtnl_tab_initialize("scopes", rtnl_rtscope_tab->tab);
}
-const char* FAST_FUNC rtnl_rtscope_n2a(int id, char *buf)
+const char* FAST_FUNC rtnl_rtscope_n2a(int id)
{
- if (id < 0 || id >= 256) {
- sprintf(buf, "%d", id);
- return buf;
+ if (id < 0 || id > RT_TABLE_MAX) {
+ return itoa(id);
}
rtnl_rtscope_initialize();
if (rtnl_rtscope_tab->tab[id])
return rtnl_rtscope_tab->tab[id];
- /* buf is SPRINT_BSIZE big */
- sprintf(buf, "%d", id);
- return buf;
+ return itoa(id);
}
int FAST_FUNC rtnl_rtscope_a2n(uint32_t *id, char *arg)
@@ -156,7 +164,7 @@ static void rtnl_rtrealm_initialize(void)
if (rtnl_rtrealm_tab) return;
rtnl_rtrealm_tab = xzalloc(sizeof(*rtnl_rtrealm_tab));
rtnl_rtrealm_tab->tab[0] = "unknown";
- rtnl_tab_initialize("/etc/iproute2/rt_realms", rtnl_rtrealm_tab->tab);
+ rtnl_tab_initialize("realms", rtnl_rtrealm_tab->tab);
}
int FAST_FUNC rtnl_rtrealm_a2n(uint32_t *id, char *arg)
@@ -166,20 +174,17 @@ int FAST_FUNC rtnl_rtrealm_a2n(uint32_t *id, char *arg)
}
#if ENABLE_FEATURE_IP_RULE
-const char* FAST_FUNC rtnl_rtrealm_n2a(int id, char *buf)
+const char* FAST_FUNC rtnl_rtrealm_n2a(int id)
{
- if (id < 0 || id >= 256) {
- sprintf(buf, "%d", id);
- return buf;
+ if (id < 0 || id > RT_TABLE_MAX) {
+ return itoa(id);
}
rtnl_rtrealm_initialize();
if (rtnl_rtrealm_tab->tab[id])
return rtnl_rtrealm_tab->tab[id];
- /* buf is SPRINT_BSIZE big */
- sprintf(buf, "%d", id);
- return buf;
+ return itoa(id);
}
#endif
@@ -191,23 +196,20 @@ static void rtnl_rtdsfield_initialize(void)
if (rtnl_rtdsfield_tab) return;
rtnl_rtdsfield_tab = xzalloc(sizeof(*rtnl_rtdsfield_tab));
rtnl_rtdsfield_tab->tab[0] = "0";
- rtnl_tab_initialize("/etc/iproute2/rt_dsfield", rtnl_rtdsfield_tab->tab);
+ rtnl_tab_initialize("dsfield", rtnl_rtdsfield_tab->tab);
}
-const char* FAST_FUNC rtnl_dsfield_n2a(int id, char *buf)
+const char* FAST_FUNC rtnl_dsfield_n2a(int id)
{
- if (id < 0 || id >= 256) {
- sprintf(buf, "%d", id);
- return buf;
+ if (id < 0 || id > RT_TABLE_MAX) {
+ return itoa(id);
}
rtnl_rtdsfield_initialize();
if (rtnl_rtdsfield_tab->tab[id])
return rtnl_rtdsfield_tab->tab[id];
- /* buf is SPRINT_BSIZE big */
- sprintf(buf, "0x%02x", id);
- return buf;
+ return itoa(id);
}
int FAST_FUNC rtnl_dsfield_a2n(uint32_t *id, char *arg)
@@ -222,29 +224,28 @@ static rtnl_tab_t *rtnl_rttable_tab;
static void rtnl_rttable_initialize(void)
{
- if (rtnl_rtdsfield_tab) return;
+ if (rtnl_rttable_tab)
+ return;
+
rtnl_rttable_tab = xzalloc(sizeof(*rtnl_rttable_tab));
rtnl_rttable_tab->tab[0] = "unspec";
rtnl_rttable_tab->tab[255] = "local";
rtnl_rttable_tab->tab[254] = "main";
rtnl_rttable_tab->tab[253] = "default";
- rtnl_tab_initialize("/etc/iproute2/rt_tables", rtnl_rttable_tab->tab);
+ rtnl_tab_initialize("tables", rtnl_rttable_tab->tab);
}
-const char* FAST_FUNC rtnl_rttable_n2a(int id, char *buf)
+const char* FAST_FUNC rtnl_rttable_n2a(int id)
{
- if (id < 0 || id >= 256) {
- sprintf(buf, "%d", id);
- return buf;
+ if (id < 0 || id > RT_TABLE_MAX) {
+ return itoa(id);
}
rtnl_rttable_initialize();
if (rtnl_rttable_tab->tab[id])
return rtnl_rttable_tab->tab[id];
- /* buf is SPRINT_BSIZE big */
- sprintf(buf, "%d", id);
- return buf;
+ return itoa(id);
}
int FAST_FUNC rtnl_rttable_a2n(uint32_t *id, char *arg)
diff --git a/release/src/router/busybox/networking/libiproute/rt_names.h b/release/src/router/busybox/networking/libiproute/rt_names.h
index e73aa851c0..29932d6a49 100644
--- a/release/src/router/busybox/networking/libiproute/rt_names.h
+++ b/release/src/router/busybox/networking/libiproute/rt_names.h
@@ -4,12 +4,11 @@
PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
-/* buf is SPRINT_BSIZE big */
-extern const char* rtnl_rtprot_n2a(int id, char *buf) FAST_FUNC;
-extern const char* rtnl_rtscope_n2a(int id, char *buf) FAST_FUNC;
-extern const char* rtnl_rtrealm_n2a(int id, char *buf) FAST_FUNC;
-extern const char* rtnl_dsfield_n2a(int id, char *buf) FAST_FUNC;
-extern const char* rtnl_rttable_n2a(int id, char *buf) FAST_FUNC;
+extern const char* rtnl_rtprot_n2a(int id) FAST_FUNC;
+extern const char* rtnl_rtscope_n2a(int id) FAST_FUNC;
+extern const char* rtnl_rtrealm_n2a(int id) FAST_FUNC;
+extern const char* rtnl_dsfield_n2a(int id) FAST_FUNC;
+extern const char* rtnl_rttable_n2a(int id) FAST_FUNC;
extern int rtnl_rtprot_a2n(uint32_t *id, char *arg) FAST_FUNC;
extern int rtnl_rtscope_a2n(uint32_t *id, char *arg) FAST_FUNC;
extern int rtnl_rtrealm_a2n(uint32_t *id, char *arg) FAST_FUNC;
diff --git a/release/src/router/busybox/networking/libiproute/rtm_map.c b/release/src/router/busybox/networking/libiproute/rtm_map.c
index 3bab53baf2..c763da049c 100644
--- a/release/src/router/busybox/networking/libiproute/rtm_map.c
+++ b/release/src/router/busybox/networking/libiproute/rtm_map.c
@@ -12,7 +12,7 @@
#include "rt_names.h"
#include "utils.h"
-const char* FAST_FUNC rtnl_rtntype_n2a(int id, char *buf)
+const char* FAST_FUNC rtnl_rtntype_n2a(int id)
{
switch (id) {
case RTN_UNSPEC:
@@ -40,9 +40,7 @@ const char* FAST_FUNC rtnl_rtntype_n2a(int id, char *buf)
case RTN_XRESOLVE:
return "xresolve";
default:
- /* buf is SPRINT_BSIZE big */
- sprintf(buf, "%d", id);
- return buf;
+ return itoa(id);
}
}
diff --git a/release/src/router/busybox/networking/libiproute/rtm_map.h b/release/src/router/busybox/networking/libiproute/rtm_map.h
index 4377bd5902..63b665169d 100644
--- a/release/src/router/busybox/networking/libiproute/rtm_map.h
+++ b/release/src/router/busybox/networking/libiproute/rtm_map.h
@@ -4,7 +4,7 @@
PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
-const char *rtnl_rtntype_n2a(int id, char *buf) FAST_FUNC;
+const char *rtnl_rtntype_n2a(int id) FAST_FUNC;
int rtnl_rtntype_a2n(int *id, char *arg) FAST_FUNC;
int get_rt_realms(uint32_t *realms, char *arg) FAST_FUNC;
diff --git a/release/src/router/busybox/networking/libiproute/utils.c b/release/src/router/busybox/networking/libiproute/utils.c
index d0fe30605c..42025bc669 100644
--- a/release/src/router/busybox/networking/libiproute/utils.c
+++ b/release/src/router/busybox/networking/libiproute/utils.c
@@ -13,6 +13,28 @@
#include "utils.h"
#include "inet_common.h"
+unsigned get_hz(void)
+{
+ static unsigned hz_internal;
+ FILE *fp;
+
+ if (hz_internal)
+ return hz_internal;
+
+ fp = fopen_for_read("/proc/net/psched");
+ if (fp) {
+ unsigned nom, denom;
+
+ if (fscanf(fp, "%*08x%*08x%08x%08x", &nom, &denom) == 2)
+ if (nom == 1000000)
+ hz_internal = denom;
+ fclose(fp);
+ }
+ if (!hz_internal)
+ hz_internal = bb_clk_tck();
+ return hz_internal;
+}
+
unsigned get_unsigned(char *arg, const char *errmsg)
{
unsigned long res;
@@ -25,7 +47,7 @@ unsigned get_unsigned(char *arg, const char *errmsg)
return res;
}
}
- invarg(arg, errmsg); /* does not return */
+ invarg_1_to_2(arg, errmsg); /* does not return */
}
uint32_t get_u32(char *arg, const char *errmsg)
@@ -40,7 +62,7 @@ uint32_t get_u32(char *arg, const char *errmsg)
return res;
}
}
- invarg(arg, errmsg); /* does not return */
+ invarg_1_to_2(arg, errmsg); /* does not return */
}
uint16_t get_u16(char *arg, const char *errmsg)
@@ -55,7 +77,7 @@ uint16_t get_u16(char *arg, const char *errmsg)
return res;
}
}
- invarg(arg, errmsg); /* does not return */
+ invarg_1_to_2(arg, errmsg); /* does not return */
}
int get_addr_1(inet_prefix *addr, char *name, int family)
@@ -208,12 +230,12 @@ uint32_t get_addr32(char *name)
void incomplete_command(void)
{
- bb_error_msg_and_die("command line is not complete, try option \"help\"");
+ bb_error_msg_and_die("command line is not complete, try \"help\"");
}
-void invarg(const char *arg, const char *opt)
+void invarg_1_to_2(const char *arg, const char *opt)
{
- bb_error_msg_and_die(bb_msg_invalid_arg, arg, opt);
+ bb_error_msg_and_die(bb_msg_invalid_arg_to, arg, opt);
}
void duparg(const char *key, const char *arg)
@@ -254,20 +276,21 @@ int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits)
return 0;
}
-const char *rt_addr_n2a(int af,
- void *addr, char *buf, int buflen)
+const char *rt_addr_n2a(int af, void *addr)
{
switch (af) {
case AF_INET:
case AF_INET6:
- return inet_ntop(af, addr, buf, buflen);
+ return inet_ntop(af, addr,
+ auto_string(xzalloc(INET6_ADDRSTRLEN)), INET6_ADDRSTRLEN
+ );
default:
return "???";
}
}
#ifdef RESOLVE_HOSTNAMES
-const char *format_host(int af, int len, void *addr, char *buf, int buflen)
+const char *format_host(int af, int len, void *addr)
{
if (resolve_hosts) {
struct hostent *h_ent;
@@ -286,11 +309,10 @@ const char *format_host(int af, int len, void *addr, char *buf, int buflen)
if (len > 0) {
h_ent = gethostbyaddr(addr, len, af);
if (h_ent != NULL) {
- safe_strncpy(buf, h_ent->h_name, buflen);
- return buf;
+ return auto_string(xstrdup(h_ent->h_name));
}
}
}
- return rt_addr_n2a(af, addr, buf, buflen);
+ return rt_addr_n2a(af, addr);
}
#endif
diff --git a/release/src/router/busybox/networking/libiproute/utils.h b/release/src/router/busybox/networking/libiproute/utils.h
index 5fb4a862cc..408d5f65ff 100644
--- a/release/src/router/busybox/networking/libiproute/utils.h
+++ b/release/src/router/busybox/networking/libiproute/utils.h
@@ -66,15 +66,15 @@ extern unsigned get_unsigned(char *arg, const char *errmsg);
extern uint32_t get_u32(char *arg, const char *errmsg);
extern uint16_t get_u16(char *arg, const char *errmsg);
-extern const char *rt_addr_n2a(int af, void *addr, char *buf, int buflen);
+extern const char *rt_addr_n2a(int af, void *addr);
#ifdef RESOLVE_HOSTNAMES
-extern const char *format_host(int af, int len, void *addr, char *buf, int buflen);
+extern const char *format_host(int af, int len, void *addr);
#else
-#define format_host(af, len, addr, buf, buflen) \
- rt_addr_n2a(af, addr, buf, buflen)
+#define format_host(af, len, addr) \
+ rt_addr_n2a(af, addr)
#endif
-void invarg(const char *, const char *) NORETURN;
+void invarg_1_to_2(const char *, const char *) NORETURN;
void duparg(const char *, const char *) NORETURN;
void duparg2(const char *, const char *) NORETURN;
int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits);
@@ -85,6 +85,8 @@ int dnet_pton(int af, const char *src, void *addr);
const char *ipx_ntop(int af, const void *addr, char *str, size_t len);
int ipx_pton(int af, const char *src, void *addr);
+unsigned get_hz(void);
+
POP_SAVED_FUNCTION_VISIBILITY
#endif
diff --git a/release/src/router/busybox/networking/nameif.c b/release/src/router/busybox/networking/nameif.c
index 5d7e8f9a44..9b18a6d164 100644
--- a/release/src/router/busybox/networking/nameif.c
+++ b/release/src/router/busybox/networking/nameif.c
@@ -161,19 +161,19 @@ static void nameif_parse_selector(ethtable_t *ch, char *selector)
if (*next)
*next++ = '\0';
/* Check for selectors, mac= is assumed */
- if (strncmp(selector, "bus=", 4) == 0) {
+ if (is_prefixed_with(selector, "bus=")) {
ch->bus_info = xstrdup(selector + 4);
found_selector++;
- } else if (strncmp(selector, "driver=", 7) == 0) {
+ } else if (is_prefixed_with(selector, "driver=")) {
ch->driver = xstrdup(selector + 7);
found_selector++;
- } else if (strncmp(selector, "phyaddr=", 8) == 0) {
+ } else if (is_prefixed_with(selector, "phyaddr=")) {
ch->phy_address = xatoi_positive(selector + 8);
found_selector++;
} else {
#endif
lmac = xmalloc(ETH_ALEN);
- ch->mac = ether_aton_r(selector + (strncmp(selector, "mac=", 4) != 0 ? 0 : 4), lmac);
+ ch->mac = ether_aton_r(selector + (is_prefixed_with(selector, "mac=") ? 4 : 0), lmac);
if (ch->mac == NULL)
bb_error_msg_and_die("can't parse %s", selector);
#if ENABLE_FEATURE_NAMEIF_EXTENDED
@@ -292,12 +292,11 @@ int nameif_main(int argc UNUSED_PARAM, char **argv)
if (ch->mac && memcmp(ch->mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN) != 0)
continue;
/* if we came here, all selectors have matched */
- break;
+ goto found;
}
/* Nothing found for current interface */
- if (!ch)
- continue;
-
+ continue;
+ found:
if (strcmp(ifr.ifr_name, ch->ifname) != 0) {
strcpy(ifr.ifr_newname, ch->ifname);
ioctl_or_perror_and_die(ctl_sk, SIOCSIFNAME, &ifr,
@@ -313,10 +312,14 @@ int nameif_main(int argc UNUSED_PARAM, char **argv)
ch->next->prev = ch->prev;
if (ENABLE_FEATURE_CLEAN_UP)
delete_eth_table(ch);
- }
+ } /* while */
+
if (ENABLE_FEATURE_CLEAN_UP) {
- for (ch = clist; ch; ch = ch->next)
+ ethtable_t *next;
+ for (ch = clist; ch; ch = next) {
+ next = ch->next;
delete_eth_table(ch);
+ }
config_close(parser);
};
diff --git a/release/src/router/busybox/networking/nbd-client.c b/release/src/router/busybox/networking/nbd-client.c
index cadda5261d..70869d6519 100644
--- a/release/src/router/busybox/networking/nbd-client.c
+++ b/release/src/router/busybox/networking/nbd-client.c
@@ -57,9 +57,8 @@ int nbdclient_main(int argc, char **argv)
uint32_t flags;
char data[124];
} nbd_header;
- struct bug_check {
- char c[offsetof(struct nbd_header_t, data) == 8+8+8+4 ? 1 : -1];
- };
+
+ BUILD_BUG_ON(offsetof(struct nbd_header_t, data) != 8+8+8+4);
// Parse command line stuff (just a stub now)
if (argc != 4)
@@ -83,7 +82,7 @@ int nbdclient_main(int argc, char **argv)
// Find and connect to server
sock = create_and_connect_stream_or_die(host, xatou16(port));
- setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &const_int_1, sizeof(const_int_1));
+ setsockopt_1(sock, IPPROTO_TCP, TCP_NODELAY);
// Log on to the server
xread(sock, &nbd_header, 8+8+8+4 + 124);
diff --git a/release/src/router/busybox/networking/nc.c b/release/src/router/busybox/networking/nc.c
index 1b32e3aa33..13a9b48a89 100644
--- a/release/src/router/busybox/networking/nc.c
+++ b/release/src/router/busybox/networking/nc.c
@@ -8,6 +8,7 @@
*/
#include "libbb.h"
+#include "common_bufsiz.h"
//config:config NC
//config: bool "nc"
@@ -24,7 +25,7 @@
//config: Allow netcat to act as a server.
//config:
//config:config NC_EXTRA
-//config: bool "Netcat extensions (-eiw and filename)"
+//config: bool "Netcat extensions (-eiw and -f FILE)"
//config: default y
//config: depends on NC
//config: help
@@ -40,7 +41,7 @@
//config: This option makes nc closely follow original nc-1.10.
//config: The code is about 2.5k bigger. It enables
//config: -s ADDR, -n, -u, -v, -o FILE, -z options, but loses
-//config: busybox-specific extensions: -f FILE and -ll.
+//config: busybox-specific extensions: -f FILE.
#if ENABLE_NC_110_COMPAT
# include "nc_bloaty.c"
@@ -60,17 +61,18 @@
//usage:#define nc_full_usage "\n\n"
//usage: "Open a pipe to IP:PORT" IF_NC_EXTRA(" or FILE")
//usage: NC_OPTIONS_STR
-//usage: IF_NC_EXTRA(
-//usage: "\n -e PROG Run PROG after connect"
//usage: IF_NC_SERVER(
//usage: "\n -l Listen mode, for inbound connects"
//usage: IF_NC_EXTRA(
-//usage: "\n (use -l twice with -e for persistent server)")
+//usage: "\n (use -ll with -e for persistent server)"
+//usage: )
//usage: "\n -p PORT Local port"
//usage: )
-//usage: "\n -w SEC Timeout for connect"
+//usage: IF_NC_EXTRA(
+//usage: "\n -w SEC Connect timeout"
//usage: "\n -i SEC Delay interval for lines sent"
//usage: "\n -f FILE Use file (ala /dev/ttyS0) instead of network"
+//usage: "\n -e PROG Run PROG after connect"
//usage: )
//usage:
//usage:#define nc_notes_usage ""
@@ -120,7 +122,7 @@ int nc_main(int argc, char **argv)
/* getopt32 is _almost_ usable:
** it cannot handle "... -e PROG -prog-opt" */
while ((opt = getopt(argc, argv,
- "" IF_NC_SERVER("lp:") IF_NC_EXTRA("w:i:f:e:") )) > 0
+ "" IF_NC_SERVER("lp:") IF_NC_EXTRA("w:i:f:e:") )) > 0
) {
if (ENABLE_NC_SERVER && opt == 'l')
IF_NC_SERVER(do_listen++);
@@ -147,7 +149,7 @@ int nc_main(int argc, char **argv)
*p++ = argv[optind++];
}
)
- /* optind points to argv[arvc] (NULL) now.
+ /* optind points to argv[argc] (NULL) now.
** FIXME: we assume that getopt will not count options
** possibly present on "-e PROG ARGS" and will not
** include them into final value of optind
@@ -226,10 +228,9 @@ int nc_main(int argc, char **argv)
/* child, or main thread if only one -l */
xmove_fd(cfd, 0);
xdup2(0, 1);
- xdup2(0, 2);
+ /*xdup2(0, 2); - original nc 1.10 does this, we don't */
IF_NC_EXTRA(BB_EXECVP(execparam[0], execparam);)
- /* Don't print stuff or it will go over the wire... */
- _exit(127);
+ IF_NC_EXTRA(bb_perror_msg_and_die("can't execute '%s'", execparam[0]);)
}
/* Select loop copying stdin to cfd, and cfd to stdout */
@@ -238,6 +239,8 @@ int nc_main(int argc, char **argv)
FD_SET(cfd, &readfds);
FD_SET(STDIN_FILENO, &readfds);
+#define iobuf bb_common_bufsiz1
+ setup_common_bufsiz();
for (;;) {
int fd;
int ofd;
@@ -248,11 +251,10 @@ int nc_main(int argc, char **argv)
if (select(cfd + 1, &testfds, NULL, NULL, NULL) < 0)
bb_perror_msg_and_die("select");
-#define iobuf bb_common_bufsiz1
fd = STDIN_FILENO;
while (1) {
if (FD_ISSET(fd, &testfds)) {
- nread = safe_read(fd, iobuf, sizeof(iobuf));
+ nread = safe_read(fd, iobuf, COMMON_BUFSIZE);
if (fd == cfd) {
if (nread < 1)
exit(EXIT_SUCCESS);
@@ -261,7 +263,7 @@ int nc_main(int argc, char **argv)
if (nread < 1) {
/* Close outgoing half-connection so they get EOF,
* but leave incoming alone so we can see response */
- shutdown(cfd, 1);
+ shutdown(cfd, SHUT_WR);
FD_CLR(STDIN_FILENO, &readfds);
}
ofd = cfd;
diff --git a/release/src/router/busybox/networking/nc_bloaty.c b/release/src/router/busybox/networking/nc_bloaty.c
index 62a0251165..471ae1a12f 100644
--- a/release/src/router/busybox/networking/nc_bloaty.c
+++ b/release/src/router/busybox/networking/nc_bloaty.c
@@ -48,6 +48,12 @@
* - TCP connects from wrong ip/ports (if peer ip:port is specified
* on the command line, but accept() says that it came from different addr)
* are closed, but we don't exit - we continue to listen/accept.
+ * Since bbox 1.22:
+ * - nc exits when _both_ stdin and network are closed.
+ * This makes these two commands:
+ * echo "Yes" | nc 127.0.0.1 1234
+ * echo "no" | nc -lp 1234
+ * exchange their data _and exit_ instead of being stuck.
*/
/* done in nc.c: #include "libbb.h" */
@@ -63,6 +69,12 @@
//usage: " -e PROG Run PROG after connect (must be last)"
//usage: IF_NC_SERVER(
//usage: "\n -l Listen mode, for inbound connects"
+//usage: "\n -lk With -e, provides persistent server"
+/* -ll does the same as -lk, but its our extension, while -k is BSD'd,
+ * presumably more widely known. Therefore we advertise it, not -ll.
+ * I would like to drop -ll support, but our "small" nc supports it,
+ * and Rob uses it.
+ */
//usage: )
//usage: "\n -p PORT Local port"
//usage: "\n -s ADDR Local address"
@@ -128,8 +140,6 @@ struct globals {
jmp_buf jbuf; /* timer crud */
- fd_set ding1; /* for select loop */
- fd_set ding2;
char bigbuf_in[BIGSIZ]; /* data buffers */
char bigbuf_net[BIGSIZ];
};
@@ -141,8 +151,6 @@ struct globals {
#define themaddr (G.themaddr )
#define remend (G.remend )
#define jbuf (G.jbuf )
-#define ding1 (G.ding1 )
-#define ding2 (G.ding2 )
#define bigbuf_in (G.bigbuf_in )
#define bigbuf_net (G.bigbuf_net)
#define o_verbose (G.o_verbose )
@@ -166,18 +174,14 @@ enum {
OPT_v = (1 << 4),
OPT_w = (1 << 5),
OPT_l = (1 << 6) * ENABLE_NC_SERVER,
- OPT_i = (1 << (6+ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
- OPT_o = (1 << (7+ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
- OPT_z = (1 << (8+ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
+ OPT_k = (1 << 7) * ENABLE_NC_SERVER,
+ OPT_i = (1 << (6+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
+ OPT_o = (1 << (7+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
+ OPT_z = (1 << (8+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
};
#define o_nflag (option_mask32 & OPT_n)
#define o_udpmode (option_mask32 & OPT_u)
-#if ENABLE_NC_SERVER
-#define o_listen (option_mask32 & OPT_l)
-#else
-#define o_listen 0
-#endif
#if ENABLE_NC_EXTRA
#define o_ofile (option_mask32 & OPT_o)
#define o_zero (option_mask32 & OPT_z)
@@ -298,7 +302,7 @@ static int connect_w_timeout(int fd)
incoming and returns an open connection *from* someplace. If we were
given host/port args, any connections from elsewhere are rejected. This
in conjunction with local-address binding should limit things nicely... */
-static void dolisten(void)
+static void dolisten(int is_persistent, char **proggie)
{
int rr;
@@ -371,6 +375,7 @@ create new one, and bind() it. TODO */
xconnect(netfd, &remend.u.sa, ouraddr->len);
} else {
/* TCP */
+ another:
arm(o_wait); /* wrap this in a timer, too; 0 = forever */
if (setjmp(jbuf) == 0) {
again:
@@ -405,6 +410,19 @@ create new one, and bind() it. TODO */
unarm();
} else
bb_error_msg_and_die("timeout");
+
+ if (is_persistent && proggie) {
+ /* -l -k -e PROG */
+ signal(SIGCHLD, SIG_IGN); /* no zombies please */
+ if (xvfork() != 0) {
+ /* parent: go back and accept more connections */
+ close(rr);
+ goto another;
+ }
+ /* child */
+ signal(SIGCHLD, SIG_DFL);
+ }
+
xmove_fd(rr, netfd); /* dump the old socket, here's our new one */
/* find out what address the connection was *to* on our end, in case we're
doing a listen-on-any on a multihomed machine. This allows one to
@@ -454,6 +472,9 @@ create new one, and bind() it. TODO */
if (!o_nflag)
free(remhostname);
}
+
+ if (proggie)
+ doexec(proggie);
}
/* udptest:
@@ -571,26 +592,27 @@ static int readwrite(void)
unsigned rzleft;
unsigned rnleft;
unsigned netretry; /* net-read retry counter */
- unsigned wretry; /* net-write sanity counter */
- unsigned wfirst; /* one-shot flag to skip first net read */
+ unsigned fds_open;
/* if you don't have all this FD_* macro hair in sys/types.h, you'll have to
either find it or do your own bit-bashing: *ding1 |= (1 << fd), etc... */
- FD_SET(netfd, &ding1); /* global: the net is open */
+ fd_set ding1; /* for select loop */
+ fd_set ding2;
+ FD_ZERO(&ding1);
+ FD_SET(netfd, &ding1);
+ FD_SET(STDIN_FILENO, &ding1);
+ fds_open = 2;
+
netretry = 2;
- wfirst = 0;
rzleft = rnleft = 0;
if (o_interval)
sleep(o_interval); /* pause *before* sending stuff, too */
- errno = 0; /* clear from sleep, close, whatever */
/* and now the big ol' select shoveling loop ... */
- while (FD_ISSET(netfd, &ding1)) { /* i.e. till the *net* closes! */
- wretry = 8200; /* more than we'll ever hafta write */
- if (wfirst) { /* any saved stdin buffer? */
- wfirst = 0; /* clear flag for the duration */
- goto shovel; /* and go handle it first */
- }
+ /* nc 1.10 has "while (FD_ISSET(netfd)" here */
+ while (fds_open) {
+ unsigned wretry = 8200; /* net-write sanity counter */
+
ding2 = ding1; /* FD_COPY ain't portable... */
/* some systems, notably linux, crap into their select timers on return, so
we create a expendable copy and give *that* to select. */
@@ -610,13 +632,14 @@ static int readwrite(void)
/* if we have a timeout AND stdin is closed AND we haven't heard anything
from the net during that time, assume it's dead and close it too. */
if (rr == 0) {
- if (!FD_ISSET(STDIN_FILENO, &ding1))
+ if (!FD_ISSET(STDIN_FILENO, &ding1)) {
netretry--; /* we actually try a coupla times. */
- if (!netretry) {
- if (o_verbose > 1) /* normally we don't care */
- fprintf(stderr, "net timeout\n");
- close(netfd);
- return 0; /* not an error! */
+ if (!netretry) {
+ if (o_verbose > 1) /* normally we don't care */
+ fprintf(stderr, "net timeout\n");
+ /*close(netfd); - redundant, exit will do it */
+ return 0; /* not an error! */
+ }
}
} /* select timeout */
/* xxx: should we check the exception fds too? The read fds seem to give
@@ -630,7 +653,8 @@ static int readwrite(void)
/* nc 1.10 doesn't do this */
bb_perror_msg("net read");
}
- FD_CLR(netfd, &ding1); /* net closed, we'll finish up... */
+ FD_CLR(netfd, &ding1); /* net closed */
+ fds_open--;
rzleft = 0; /* can't write anymore: broken pipe */
} else {
rnleft = rr;
@@ -650,11 +674,12 @@ Debug("got %d from the net, errno %d", rr, errno);
/* Considered making reads here smaller for UDP mode, but 8192-byte
mobygrams are kinda fun and exercise the reassembler. */
if (rr <= 0) { /* at end, or fukt, or ... */
- FD_CLR(STDIN_FILENO, &ding1); /* disable and close stdin */
- close(STDIN_FILENO);
-// Does it make sense to shutdown(net_fd, SHUT_WR)
-// to let other side know that we won't write anything anymore?
-// (and what about keeping compat if we do that?)
+ FD_CLR(STDIN_FILENO, &ding1); /* disable stdin */
+ /*close(STDIN_FILENO); - not really necessary */
+ /* Let peer know we have no more data */
+ /* nc 1.10 doesn't do this: */
+ shutdown(netfd, SHUT_WR);
+ fds_open--;
} else {
rzleft = rr;
zp = bigbuf_in;
@@ -665,24 +690,14 @@ Debug("got %d from the net, errno %d", rr, errno);
Geez, why does this look an awful lot like the big loop in "rsh"? ...
not sure if the order of this matters, but write net -> stdout first. */
- /* sanity check. Works because they're both unsigned... */
- if ((rzleft > 8200) || (rnleft > 8200)) {
- holler_error("bogus buffers: %u, %u", rzleft, rnleft);
- rzleft = rnleft = 0;
- }
- /* net write retries sometimes happen on UDP connections */
- if (!wretry) { /* is something hung? */
- holler_error("too many output retries");
- return 1;
- }
if (rnleft) {
rr = write(STDOUT_FILENO, np, rnleft);
if (rr > 0) {
if (o_ofile) /* log the stdout */
oprint('<', (unsigned char *)np, rr);
- np += rr; /* fix up ptrs and whatnot */
- rnleft -= rr; /* will get sanity-checked above */
- wrote_out += rr; /* global count */
+ np += rr;
+ rnleft -= rr;
+ wrote_out += rr; /* global count */
}
Debug("wrote %d to stdout, errno %d", rr, errno);
} /* rnleft */
@@ -697,20 +712,24 @@ Debug("wrote %d to stdout, errno %d", rr, errno);
oprint('>', (unsigned char *)zp, rr);
zp += rr;
rzleft -= rr;
- wrote_net += rr; /* global count */
+ wrote_net += rr; /* global count */
}
Debug("wrote %d to net, errno %d", rr, errno);
} /* rzleft */
if (o_interval) { /* cycle between slow lines, or ... */
sleep(o_interval);
- errno = 0; /* clear from sleep */
continue; /* ...with hairy select loop... */
}
- if ((rzleft) || (rnleft)) { /* shovel that shit till they ain't */
+ if (rzleft || rnleft) { /* shovel that shit till they ain't */
wretry--; /* none left, and get another load */
+ /* net write retries sometimes happen on UDP connections */
+ if (!wretry) { /* is something hung? */
+ holler_error("too many output retries");
+ return 1;
+ }
goto shovel;
}
- } /* while ding1:netfd is open */
+ } /* while (fds_open) */
/* XXX: maybe want a more graceful shutdown() here, or screw around with
linger times?? I suspect that I don't need to since I'm always doing
@@ -730,6 +749,7 @@ int nc_main(int argc UNUSED_PARAM, char **argv)
char *themdotted = themdotted; /* for compiler */
char **proggie;
int x;
+ unsigned cnt_l = 0;
unsigned o_lport = 0;
INIT_G();
@@ -760,7 +780,7 @@ int nc_main(int argc UNUSED_PARAM, char **argv)
if (proggie[0][0] == '-') {
char *optpos = *proggie + 1;
/* Skip all valid opts w/o params */
- optpos = optpos + strspn(optpos, "nuv"IF_NC_SERVER("l")IF_NC_EXTRA("z"));
+ optpos = optpos + strspn(optpos, "nuv"IF_NC_SERVER("lk")IF_NC_EXTRA("z"));
if (*optpos == 'e' && !optpos[1]) {
*optpos = '\0';
proggie++;
@@ -774,17 +794,21 @@ int nc_main(int argc UNUSED_PARAM, char **argv)
e_found:
// -g -G -t -r deleted, unimplemented -a deleted too
- opt_complementary = "?2:vv:w+"; /* max 2 params; -v is a counter; -w N */
- getopt32(argv, "np:s:uvw:" IF_NC_SERVER("l")
+ opt_complementary = "?2:vv:ll:w+"; /* max 2 params; -v and -l are counters; -w N */
+ getopt32(argv, "np:s:uvw:" IF_NC_SERVER("lk")
IF_NC_EXTRA("i:o:z"),
&str_p, &str_s, &o_wait
- IF_NC_EXTRA(, &str_i, &str_o), &o_verbose);
+ IF_NC_EXTRA(, &str_i, &str_o), &o_verbose IF_NC_SERVER(, &cnt_l));
argv += optind;
#if ENABLE_NC_EXTRA
if (option_mask32 & OPT_i) /* line-interval time */
o_interval = xatou_range(str_i, 1, 0xffff);
#endif
+#if ENABLE_NC_SERVER
//if (option_mask32 & OPT_l) /* listen mode */
+ if (option_mask32 & OPT_k) /* persistent server mode */
+ cnt_l = 2;
+#endif
//if (option_mask32 & OPT_n) /* numeric-only, no DNS lookups */
//if (option_mask32 & OPT_o) /* hexdump log */
if (option_mask32 & OPT_p) { /* local source port */
@@ -833,14 +857,14 @@ int nc_main(int argc UNUSED_PARAM, char **argv)
if (o_udpmode)
socket_want_pktinfo(netfd);
if (!ENABLE_FEATURE_UNIX_LOCAL
- || o_listen
+ || cnt_l != 0 /* listen */
|| ouraddr->u.sa.sa_family != AF_UNIX
) {
xbind(netfd, &ouraddr->u.sa, ouraddr->len);
}
#if 0
- setsockopt(netfd, SOL_SOCKET, SO_RCVBUF, &o_rcvbuf, sizeof o_rcvbuf);
- setsockopt(netfd, SOL_SOCKET, SO_SNDBUF, &o_sndbuf, sizeof o_sndbuf);
+ setsockopt_SOL_SOCKET_int(netfd, SO_RCVBUF, o_rcvbuf);
+ setsockopt_SOL_SOCKET_int(netfd, SO_SNDBUF, o_sndbuf);
#endif
#ifdef BLOAT
@@ -852,9 +876,8 @@ int nc_main(int argc UNUSED_PARAM, char **argv)
}
#endif
- FD_SET(STDIN_FILENO, &ding1); /* stdin *is* initially open */
if (proggie) {
- close(0); /* won't need stdin */
+ close(STDIN_FILENO); /* won't need stdin */
option_mask32 &= ~OPT_o; /* -o with -e is meaningless! */
}
#if ENABLE_NC_EXTRA
@@ -862,11 +885,9 @@ int nc_main(int argc UNUSED_PARAM, char **argv)
xmove_fd(xopen(str_o, O_WRONLY|O_CREAT|O_TRUNC), ofd);
#endif
- if (o_listen) {
- dolisten();
+ if (cnt_l != 0) {
+ dolisten((cnt_l - 1), proggie);
/* dolisten does its own connect reporting */
- if (proggie) /* -e given? */
- doexec(proggie);
x = readwrite(); /* it even works with UDP! */
} else {
/* Outbound connects. Now we're more picky about args... */
diff --git a/release/src/router/busybox/networking/netstat.c b/release/src/router/busybox/networking/netstat.c
index 9c239579fe..2196d42f74 100644
--- a/release/src/router/busybox/networking/netstat.c
+++ b/release/src/router/busybox/networking/netstat.c
@@ -119,16 +119,16 @@ typedef enum {
#define ADDR_NORMAL_WIDTH 23
/* When there are IPv6 connections the IPv6 addresses will be
* truncated to none-recognition. The '-W' option makes the
- * address columns wide enough to accomodate for longest possible
+ * address columns wide enough to accommodate for longest possible
* IPv6 addresses, i.e. addresses of the form
* xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:ddd.ddd.ddd.ddd
*/
#define ADDR_WIDE 51 /* INET6_ADDRSTRLEN + 5 for the port number */
#if ENABLE_FEATURE_NETSTAT_WIDE
-# define FMT_NET_CONN_DATA "%s %6ld %6ld %-*s %-*s %-12s"
+# define FMT_NET_CONN_DATA "%s %6lu %6lu %-*s %-*s %-12s"
# define FMT_NET_CONN_HEADER "\nProto Recv-Q Send-Q %-*s %-*s State %s\n"
#else
-# define FMT_NET_CONN_DATA "%s %6ld %6ld %-23s %-23s %-12s"
+# define FMT_NET_CONN_DATA "%s %6lu %6lu %-23s %-23s %-12s"
# define FMT_NET_CONN_HEADER "\nProto Recv-Q Send-Q %-23s %-23s State %s\n"
#endif
@@ -187,7 +187,7 @@ static void prg_cache_add(long inode, char *name)
for (pnp = prg_hash + hi; (pn = *pnp) != NULL; pnp = &pn->next) {
if (pn->inode == inode) {
/* Some warning should be appropriate here
- as we got multiple processes for one i-node */
+ * as we got multiple processes for one i-node */
return;
}
}
@@ -228,12 +228,12 @@ static long extract_socket_inode(const char *lname)
{
long inode = -1;
- if (strncmp(lname, "socket:[", sizeof("socket:[")-1) == 0) {
+ if (is_prefixed_with(lname, "socket:[")) {
/* "socket:[12345]", extract the "12345" as inode */
inode = bb_strtoul(lname + sizeof("socket:[")-1, (char**)&lname, 0);
if (*lname != ']')
inode = -1;
- } else if (strncmp(lname, "[0000]:", sizeof("[0000]:")-1) == 0) {
+ } else if (is_prefixed_with(lname, "[0000]:")) {
/* "[0000]:12345", extract the "12345" as inode */
inode = bb_strtoul(lname + sizeof("[0000]:")-1, NULL, 0);
if (errno) /* not NUL terminated? */
@@ -403,7 +403,7 @@ static int scan_inet_proc_line(struct inet_params *param, char *line)
"%*d: %32[0-9A-Fa-f]:%X "
"%32[0-9A-Fa-f]:%X %X "
"%lX:%lX %*X:%*X "
- "%*X %d %*d %ld ",
+ "%*X %d %*d %lu ",
local_addr, &param->local_port,
rem_addr, &param->rem_port, &param->state,
&param->txq, &param->rxq,
@@ -611,7 +611,7 @@ static int FAST_FUNC unix_do_one(char *line)
strcat(ss_flags, "N ");
strcat(ss_flags, "]");
- printf("%-5s %-6ld %-11s %-10s %-13s %6lu ",
+ printf("%-5s %-6lu %-11s %-10s %-13s %6lu ",
ss_proto, refcnt, ss_flags, ss_type, ss_state, inode
);
@@ -622,7 +622,7 @@ static int FAST_FUNC unix_do_one(char *line)
/* TODO: currently we stop at first NUL byte. Is it a problem? */
line += path_ofs;
- *strchrnul(line, '\n') = '\0';
+ chomp(line);
while (*line)
fputc_printable(*line++, stdout);
bb_putchar('\n');
diff --git a/release/src/router/busybox/networking/nslookup.c b/release/src/router/busybox/networking/nslookup.c
index f4fd407dd7..dd4b1ffedd 100644
--- a/release/src/router/busybox/networking/nslookup.c
+++ b/release/src/router/busybox/networking/nslookup.c
@@ -138,6 +138,9 @@ static void set_default_dns(const char *server)
{
len_and_sockaddr *lsa;
+ if (!server)
+ return;
+
/* NB: this works even with, say, "[::1]:5353"! :) */
lsa = xhost2sockaddr(server, 53);
@@ -181,9 +184,17 @@ int nslookup_main(int argc, char **argv)
/* (but it also says "may be enabled in /etc/resolv.conf") */
/*_res.options |= RES_USE_INET6;*/
- if (argv[2])
- set_default_dns(argv[2]);
+ set_default_dns(argv[2]);
server_print();
+
+ /* getaddrinfo and friends are free to request a resolver
+ * reinitialization. Just in case, set_default_dns() again
+ * after getaddrinfo (in server_print). This reportedly helps
+ * with bug 675 "nslookup does not properly use second argument"
+ * at least on Debian Wheezy and Openwrt AA (eglibc based).
+ */
+ set_default_dns(argv[2]);
+
return print_host(argv[1], "Name:");
}
diff --git a/release/src/router/busybox/networking/ntpd.c b/release/src/router/busybox/networking/ntpd.c
index ecfc2a6245..c68872835d 100644
--- a/release/src/router/busybox/networking/ntpd.c
+++ b/release/src/router/busybox/networking/ntpd.c
@@ -1,35 +1,48 @@
/*
* NTP client/server, based on OpenNTPD 3.9p1
*
- * Author: Adam Tkac <vonsch@gmail.com>
+ * Busybox port author: Adam Tkac (C) 2009 <vonsch@gmail.com>
*
- * Licensed under GPLv2, see file LICENSE in this source tree.
+ * OpenNTPd 3.9p1 copyright holders:
+ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
+ * Copyright (c) 2004 Alexander Guy <alexander.guy@andern.org>
+ *
+ * OpenNTPd code is licensed under ISC-style licence:
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ ***********************************************************************
*
* Parts of OpenNTPD clock syncronization code is replaced by
- * code which is based on ntp-4.2.6, whuch carries the following
+ * code which is based on ntp-4.2.6, which carries the following
* copyright notice:
*
- ***********************************************************************
- * *
- * Copyright (c) University of Delaware 1992-2009 *
- * *
- * Permission to use, copy, modify, and distribute this software and *
- * its documentation for any purpose with or without fee is hereby *
- * granted, provided that the above copyright notice appears in all *
- * copies and that both the copyright notice and this permission *
- * notice appear in supporting documentation, and that the name *
- * University of Delaware not be used in advertising or publicity *
- * pertaining to distribution of the software without specific, *
- * written prior permission. The University of Delaware makes no *
- * representations about the suitability this software for any *
- * purpose. It is provided "as is" without express or implied *
- * warranty. *
- * *
+ * Copyright (c) University of Delaware 1992-2009
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose with or without fee is hereby
+ * granted, provided that the above copyright notice appears in all
+ * copies and that both the copyright notice and this permission
+ * notice appear in supporting documentation, and that the name
+ * University of Delaware not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission. The University of Delaware makes no
+ * representations about the suitability this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
***********************************************************************
*/
//usage:#define ntpd_trivial_usage
-//usage: "[-dnqNwt"IF_FEATURE_NTPD_SERVER("l")"] [-S PROG] [-p PEER]..."
+//usage: "[-dnqNwt"IF_FEATURE_NTPD_SERVER("l -I IFACE")"] [-S PROG] [-p PEER]..."
//usage:#define ntpd_full_usage "\n\n"
//usage: "NTP client/server\n"
//usage: "\n -d Verbose"
@@ -38,29 +51,36 @@
//usage: "\n -N Run at high priority"
//usage: "\n -w Do not set time (only query peers), implies -n"
//usage: "\n -t Trust network and server, no RFC-4330 cross-checks"
-//usage: IF_FEATURE_NTPD_SERVER(
-//usage: "\n -l Run as server on port 123"
-//usage: )
//usage: "\n -S PROG Run PROG after stepping time, stratum change, and every 11 mins"
//usage: "\n -p PEER Obtain time from PEER (may be repeated)"
+//usage: IF_FEATURE_NTPD_CONF(
+//usage: "\n If -p is not given, 'server HOST' lines"
+//usage: "\n from /etc/ntp.conf are used"
+//usage: )
+//usage: IF_FEATURE_NTPD_SERVER(
+//usage: "\n -l Also run as server on port 123"
+//usage: "\n -I IFACE Bind server to IFACE, implies -l"
+//usage: )
+
+// -l and -p options are not compatible with "standard" ntpd:
+// it has them as "-l logfile" and "-p pidfile".
+// -S and -w are not compat either, "standard" ntpd has no such opts.
#include "libbb.h"
#include <math.h>
#include <netinet/ip.h> /* For IPTOS_LOWDELAY definition */
+#include <sys/resource.h> /* setpriority */
#include <sys/timex.h>
#ifndef IPTOS_LOWDELAY
# define IPTOS_LOWDELAY 0x10
#endif
-#ifndef IP_PKTINFO
-# error "Sorry, your kernel has to support IP_PKTINFO"
-#endif
/* Verbosity control (max level of -dddd options accepted).
- * max 5 is very talkative (and bloated). 2 is non-bloated,
+ * max 6 is very talkative (and bloated). 3 is non-bloated,
* production level setting.
*/
-#define MAX_VERBOSE 2
+#define MAX_VERBOSE 3
/* High-level description of the algorithm:
@@ -90,33 +110,61 @@
* was hibernated, someone set totally wrong date, etc),
* then the time is stepped, all datapoints are discarded,
* and we go back to steady state.
+ *
+ * Made some changes to speed up re-syncing after our clock goes bad
+ * (tested with suspending my laptop):
+ * - if largish offset (>= STEP_THRESHOLD == 1 sec) is seen
+ * from a peer, schedule next query for this peer soon
+ * without drastically lowering poll interval for everybody.
+ * This makes us collect enough data for step much faster:
+ * e.g. at poll = 10 (1024 secs), step was done within 5 minutes
+ * after first reply which indicated that our clock is 14 seconds off.
+ * - on step, do not discard d_dispersion data of the existing datapoints,
+ * do not clear reachable_bits. This prevents discarding first ~8
+ * datapoints after the step.
*/
-#define RETRY_INTERVAL 5 /* on error, retry in N secs */
-#define RESPONSE_INTERVAL 15 /* wait for reply up to N secs */
-#define INITIAL_SAMPLES 4 /* how many samples do we want for init */
+#define INITIAL_SAMPLES 1 /* how many samples do we want for init */
+#define BAD_DELAY_GROWTH 4 /* drop packet if its delay grew by more than this */
-/* Clock discipline parameters and constants */
+#define RETRY_INTERVAL 32 /* on send/recv error, retry in N secs (need to be power of 2) */
+#define NOREPLY_INTERVAL 512 /* sent, but got no reply: cap next query by this many seconds */
+#define RESPONSE_INTERVAL 16 /* wait for reply up to N secs */
/* Step threshold (sec). std ntpd uses 0.128.
- * Using exact power of 2 (1/8) results in smaller code */
-#define STEP_THRESHOLD 0.125
-#define WATCH_THRESHOLD 128 /* stepout threshold (sec). std ntpd uses 900 (11 mins (!)) */
+ */
+#define STEP_THRESHOLD 1
+/* Slew threshold (sec): adjtimex() won't accept offsets larger than this.
+ * Using exact power of 2 (1/8) results in smaller code
+ */
+#define SLEW_THRESHOLD 0.25
+/* Stepout threshold (sec). std ntpd uses 900 (11 mins (!)) */
+#define WATCH_THRESHOLD 128
/* NB: set WATCH_THRESHOLD to ~60 when debugging to save time) */
//UNUSED: #define PANIC_THRESHOLD 1000 /* panic threshold (sec) */
+/*
+ * If we got |offset| > BIGOFF from a peer, cap next query interval
+ * for this peer by this many seconds:
+ */
+#define BIGOFF STEP_THRESHOLD
+#define BIGOFF_INTERVAL (1 << 7) /* 128 s */
+
#define FREQ_TOLERANCE 0.000015 /* frequency tolerance (15 PPM) */
#define BURSTPOLL 0 /* initial poll */
-#define MINPOLL 5 /* minimum poll interval. std ntpd uses 6 (6: 64 sec) */
-/* If offset > discipline_jitter * POLLADJ_GATE, and poll interval is >= 2^BIGPOLL,
- * then it is decreased _at once_. (If < 2^BIGPOLL, it will be decreased _eventually_).
+#define MINPOLL 6 /* minimum poll interval. std ntpd uses 6 (6: 64 sec) */
+/*
+ * If offset > discipline_jitter * POLLADJ_GATE, and poll interval is > 2^BIGPOLL,
+ * then it is decreased _at once_. (If <= 2^BIGPOLL, it will be decreased _eventually_).
*/
-#define BIGPOLL 10 /* 2^10 sec ~= 17 min */
-#define MAXPOLL 12 /* maximum poll interval (12: 1.1h, 17: 36.4h). std ntpd uses 17 */
-/* Actively lower poll when we see such big offsets.
- * With STEP_THRESHOLD = 0.125, it means we try to sync more aggressively
- * if offset increases over ~0.04 sec */
-#define POLLDOWN_OFFSET (STEP_THRESHOLD / 3)
+#define BIGPOLL 9 /* 2^9 sec ~= 8.5 min */
+#define MAXPOLL 16 /* maximum poll interval (12: 1.1h, 17: 36.4h). std ntpd uses 17 */
+/*
+ * Actively lower poll when we see such big offsets.
+ * With SLEW_THRESHOLD = 0.125, it means we try to sync more aggressively
+ * if offset increases over ~0.04 sec
+ */
+//#define POLLDOWN_OFFSET (SLEW_THRESHOLD / 3)
#define MINDISP 0.01 /* minimum dispersion (sec) */
#define MAXDISP 16 /* maximum dispersion (sec) */
#define MAXSTRAT 16 /* maximum stratum (infinity metric) */
@@ -133,7 +181,7 @@
* and when it goes below -POLLADJ_LIMIT, we poll_exp--.
* (Bumped from 30 to 40 since otherwise I often see poll_exp going *2* steps down)
*/
-#define POLLADJ_LIMIT 40
+#define POLLADJ_LIMIT 36
/* If offset < discipline_jitter * POLLADJ_GATE, then we decide to increase
* poll interval (we think we can't improve timekeeping
* by staying at smaller poll).
@@ -221,16 +269,19 @@ typedef struct {
typedef struct {
len_and_sockaddr *p_lsa;
char *p_dotted;
- /* when to send new query (if p_fd == -1)
- * or when receive times out (if p_fd >= 0): */
int p_fd;
int datapoint_idx;
uint32_t lastpkt_refid;
uint8_t lastpkt_status;
uint8_t lastpkt_stratum;
uint8_t reachable_bits;
+ /* when to send new query (if p_fd == -1)
+ * or when receive times out (if p_fd >= 0): */
double next_action_time;
double p_xmttime;
+ double p_raw_delay;
+ /* p_raw_delay is set even by "high delay" packets */
+ /* lastpkt_delay isn't */
double lastpkt_recv_time;
double lastpkt_delay;
double lastpkt_rootdelay;
@@ -242,6 +293,7 @@ typedef struct {
datapoint_t filter_datapoint[NUM_DATAPOINTS];
/* last sent packet: */
msg_t p_xmt_msg;
+ char p_hostname[1];
} peer_t;
@@ -260,6 +312,7 @@ enum {
OPT_S = (1 << 6),
OPT_t = (1 << 7),
OPT_l = (1 << 8) * ENABLE_FEATURE_NTPD_SERVER,
+ OPT_I = (1 << 9) * ENABLE_FEATURE_NTPD_SERVER,
/* We hijack some bits for other purposes */
OPT_qq = (1 << 31),
};
@@ -278,6 +331,7 @@ struct globals {
llist_t *ntp_peers;
#if ENABLE_FEATURE_NTPD_SERVER
int listen_fd;
+ char *if_name;
# define G_listen_fd (G.listen_fd)
#else
# define G_listen_fd (-1)
@@ -329,12 +383,10 @@ struct globals {
*/
#define G_precision_sec 0.002
uint8_t stratum;
- /* Bool. After set to 1, never goes back to 0: */
- smallint initial_poll_complete;
#define STATE_NSET 0 /* initial state, "nothing is set" */
//#define STATE_FSET 1 /* frequency set from file */
-#define STATE_SPIK 2 /* spike detected */
+//#define STATE_SPIK 2 /* spike detected */
//#define STATE_FREQ 3 /* initial frequency */
#define STATE_SYNC 4 /* clock synchronized (normal operation) */
uint8_t discipline_state; // doc calls it c.state
@@ -359,14 +411,13 @@ struct globals {
};
#define G (*ptr_to_globals)
-static const int const_IPTOS_LOWDELAY = IPTOS_LOWDELAY;
-
#define VERB1 if (MAX_VERBOSE && G.verbose)
#define VERB2 if (MAX_VERBOSE >= 2 && G.verbose >= 2)
#define VERB3 if (MAX_VERBOSE >= 3 && G.verbose >= 3)
#define VERB4 if (MAX_VERBOSE >= 4 && G.verbose >= 4)
#define VERB5 if (MAX_VERBOSE >= 5 && G.verbose >= 5)
+#define VERB6 if (MAX_VERBOSE >= 6 && G.verbose >= 6)
static double LOG2D(int a)
@@ -568,7 +619,7 @@ filter_datapoints(peer_t *p)
got_newest = 0;
sum = 0;
for (i = 0; i < NUM_DATAPOINTS; i++) {
- VERB4 {
+ VERB5 {
bb_error_msg("datapoint[%d]: off:%f disp:%f(%f) age:%f%s",
i,
fdp[idx].d_offset,
@@ -665,7 +716,7 @@ filter_datapoints(peer_t *p)
sum = SQRT(sum / NUM_DATAPOINTS);
p->filter_jitter = sum > G_precision_sec ? sum : G_precision_sec;
- VERB3 bb_error_msg("filter offset:%+f disp:%f jitter:%f",
+ VERB4 bb_error_msg("filter offset:%+f disp:%f jitter:%f",
p->filter_offset,
p->filter_dispersion,
p->filter_jitter);
@@ -675,7 +726,19 @@ static void
reset_peer_stats(peer_t *p, double offset)
{
int i;
- bool small_ofs = fabs(offset) < 16 * STEP_THRESHOLD;
+ bool small_ofs = fabs(offset) < STEP_THRESHOLD;
+
+ /* Used to set p->filter_datapoint[i].d_dispersion = MAXDISP
+ * and clear reachable bits, but this proved to be too agressive:
+ * after step (tested with suspending laptop for ~30 secs),
+ * this caused all previous data to be considered invalid,
+ * making us needing to collect full ~8 datapoins per peer
+ * after step in order to start trusting them.
+ * In turn, this was making poll interval decrease even after
+ * step was done. (Poll interval decreases already before step
+ * in this scenario, because we see large offsets and end up with
+ * no good peer to select).
+ */
for (i = 0; i < NUM_DATAPOINTS; i++) {
if (small_ofs) {
@@ -690,31 +753,72 @@ reset_peer_stats(peer_t *p, double offset)
} else {
p->filter_datapoint[i].d_recv_time = G.cur_time;
p->filter_datapoint[i].d_offset = 0;
- p->filter_datapoint[i].d_dispersion = MAXDISP;
+ /*p->filter_datapoint[i].d_dispersion = MAXDISP;*/
}
}
if (small_ofs) {
p->lastpkt_recv_time += offset;
} else {
- p->reachable_bits = 0;
+ /*p->reachable_bits = 0;*/
p->lastpkt_recv_time = G.cur_time;
}
filter_datapoints(p); /* recalc p->filter_xxx */
- VERB5 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time);
+ VERB6 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time);
+}
+
+static void
+resolve_peer_hostname(peer_t *p, int loop_on_fail)
+{
+ len_and_sockaddr *lsa;
+
+ again:
+ lsa = host2sockaddr(p->p_hostname, 123);
+ if (!lsa) {
+ /* error message already emitted by host2sockaddr() */
+ if (!loop_on_fail)
+ return;
+//FIXME: do this to avoid infinite looping on typo in a hostname?
+//well... in which case, what is a good value for loop_on_fail?
+ //if (--loop_on_fail == 0)
+ // xfunc_die();
+ sleep(5);
+ goto again;
+ }
+ free(p->p_lsa);
+ free(p->p_dotted);
+ p->p_lsa = lsa;
+ p->p_dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
}
static void
-add_peers(char *s)
+add_peers(const char *s)
{
+ llist_t *item;
peer_t *p;
- p = xzalloc(sizeof(*p));
- p->p_lsa = xhost2sockaddr(s, 123);
- p->p_dotted = xmalloc_sockaddr2dotted_noport(&p->p_lsa->u.sa);
+ p = xzalloc(sizeof(*p) + strlen(s));
+ strcpy(p->p_hostname, s);
+ resolve_peer_hostname(p, /*loop_on_fail=*/ 1);
+
+ /* Names like N.<country2chars>.pool.ntp.org are randomly resolved
+ * to a pool of machines. Sometimes different N's resolve to the same IP.
+ * It is not useful to have two peers with same IP. We skip duplicates.
+ */
+ for (item = G.ntp_peers; item != NULL; item = item->link) {
+ peer_t *pp = (peer_t *) item->data;
+ if (strcmp(p->p_dotted, pp->p_dotted) == 0) {
+ bb_error_msg("duplicate peer %s (%s)", s, p->p_dotted);
+ free(p->p_lsa);
+ free(p->p_dotted);
+ free(p);
+ return;
+ }
+ }
+
p->p_fd = -1;
p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3);
p->next_action_time = G.cur_time; /* = set_next(p, 0); */
- reset_peer_stats(p, 16 * STEP_THRESHOLD);
+ reset_peer_stats(p, STEP_THRESHOLD);
llist_add_to(&G.ntp_peers, p);
G.peer_cnt++;
@@ -778,7 +882,7 @@ send_query_to_peer(peer_t *p)
#if ENABLE_FEATURE_IPV6
if (family == AF_INET)
#endif
- setsockopt(fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY));
+ setsockopt_int(fd, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY);
free(local_lsa);
}
@@ -801,26 +905,38 @@ send_query_to_peer(peer_t *p)
*
* Save the real transmit timestamp locally.
*/
- p->p_xmt_msg.m_xmttime.int_partl = random();
- p->p_xmt_msg.m_xmttime.fractionl = random();
+ p->p_xmt_msg.m_xmttime.int_partl = rand();
+ p->p_xmt_msg.m_xmttime.fractionl = rand();
p->p_xmttime = gettime1900d();
+ /* Were doing it only if sendto worked, but
+ * loss of sync detection needs reachable_bits updated
+ * even if sending fails *locally*:
+ * "network is unreachable" because cable was pulled?
+ * We still need to declare "unsync" if this condition persists.
+ */
+ p->reachable_bits <<= 1;
+
if (do_sendto(p->p_fd, /*from:*/ NULL, /*to:*/ &p->p_lsa->u.sa, /*addrlen:*/ p->p_lsa->len,
&p->p_xmt_msg, NTP_MSGSIZE_NOAUTH) == -1
) {
close(p->p_fd);
p->p_fd = -1;
+ /*
+ * We know that we sent nothing.
+ * We can retry *soon* without fearing
+ * that we are flooding the peer.
+ */
set_next(p, RETRY_INTERVAL);
return;
}
- p->reachable_bits <<= 1;
set_next(p, RESPONSE_INTERVAL);
}
/* Note that there is no provision to prevent several run_scripts
- * to be done in quick succession. In fact, it happens rather often
+ * to be started in quick succession. In fact, it happens rather often
* if initial syncronization results in a step.
* You will see "step" and then "stratum" script runs, sometimes
* as close as only 0.002 seconds apart.
@@ -831,6 +947,8 @@ static void run_script(const char *action, double offset)
char *argv[3];
char *env1, *env2, *env3, *env4;
+ G.last_script_run = G.cur_time;
+
if (!G.script_name)
return;
@@ -867,8 +985,6 @@ static void run_script(const char *action, double offset)
free(env2);
free(env3);
free(env4);
-
- G.last_script_run = G.cur_time;
}
static NOINLINE void
@@ -888,15 +1004,20 @@ step_time(double offset)
VERB2 {
tval = tvc.tv_sec;
- strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&tval));
+ strftime_YYYYMMDDHHMMSS(buf, sizeof(buf), &tval);
bb_error_msg("current time is %s.%06u", buf, (unsigned)tvc.tv_usec);
}
tval = tvn.tv_sec;
- strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&tval));
+ strftime_YYYYMMDDHHMMSS(buf, sizeof(buf), &tval);
bb_error_msg("setting time to %s.%06u (offset %+fs)", buf, (unsigned)tvn.tv_usec, offset);
/* Correct various fields which contain time-relative values: */
+ /* Globals: */
+ G.cur_time += offset;
+ G.last_update_recv_time += offset;
+ G.last_script_run += offset;
+
/* p->lastpkt_recv_time, p->next_action_time and such: */
for (item = G.ntp_peers; item != NULL; item = item->link) {
peer_t *pp = (peer_t *) item->data;
@@ -904,11 +1025,26 @@ step_time(double offset)
//bb_error_msg("offset:%+f pp->next_action_time:%f -> %f",
// offset, pp->next_action_time, pp->next_action_time + offset);
pp->next_action_time += offset;
+ if (pp->p_fd >= 0) {
+ /* We wait for reply from this peer too.
+ * But due to step we are doing, reply's data is no longer
+ * useful (in fact, it'll be bogus). Stop waiting for it.
+ */
+ close(pp->p_fd);
+ pp->p_fd = -1;
+ set_next(pp, RETRY_INTERVAL);
+ }
}
- /* Globals: */
- G.cur_time += offset;
- G.last_update_recv_time += offset;
- G.last_script_run += offset;
+}
+
+static void clamp_pollexp_and_set_MAXSTRAT(void)
+{
+ if (G.poll_exp < MINPOLL)
+ G.poll_exp = MINPOLL;
+ if (G.poll_exp > BIGPOLL)
+ G.poll_exp = BIGPOLL;
+ G.polladj_count = 0;
+ G.stratum = MAXSTRAT;
}
@@ -950,7 +1086,7 @@ fit(peer_t *p, double rd)
{
if ((p->reachable_bits & (p->reachable_bits-1)) == 0) {
/* One or zero bits in reachable_bits */
- VERB3 bb_error_msg("peer %s unfit for selection: unreachable", p->p_dotted);
+ VERB4 bb_error_msg("peer %s unfit for selection: unreachable", p->p_dotted);
return 0;
}
if (option_mask32 & OPT_t) /* RFC-4330 check disabled */
@@ -960,13 +1096,13 @@ fit(peer_t *p, double rd)
if ((p->lastpkt_status & LI_ALARM) == LI_ALARM
|| p->lastpkt_stratum >= MAXSTRAT
) {
- VERB3 bb_error_msg("peer %s unfit for selection: bad status/stratum", p->p_dotted);
+ VERB4 bb_error_msg("peer %s unfit for selection: bad status/stratum", p->p_dotted);
return 0;
}
#endif
/* rd is root_distance(p) */
if (rd > MAXDIST + FREQ_TOLERANCE * (1 << G.poll_exp)) {
- VERB3 bb_error_msg("peer %s unfit for selection: root distance too high", p->p_dotted);
+ VERB4 bb_error_msg("peer %s unfit for selection: root distance too high", p->p_dotted);
return 0;
}
//TODO
@@ -995,7 +1131,7 @@ select_and_cluster(void)
num_points = 0;
item = G.ntp_peers;
- if (G.initial_poll_complete) while (item != NULL) {
+ while (item != NULL) {
double rd, offset;
p = (peer_t *) item->data;
@@ -1006,7 +1142,7 @@ select_and_cluster(void)
continue;
}
- VERB4 bb_error_msg("interval: [%f %f %f] %s",
+ VERB5 bb_error_msg("interval: [%f %f %f] %s",
offset - rd,
offset,
offset + rd,
@@ -1031,7 +1167,7 @@ select_and_cluster(void)
}
num_candidates = num_points / 3;
if (num_candidates == 0) {
- VERB3 bb_error_msg("no valid datapoints, no peer selected");
+ VERB3 bb_error_msg("no valid datapoints%s", ", no peer selected");
return NULL;
}
//TODO: sorting does not seem to be done in reference code
@@ -1089,12 +1225,13 @@ select_and_cluster(void)
break;
num_falsetickers++;
if (num_falsetickers * 2 >= num_candidates) {
- VERB3 bb_error_msg("too many falsetickers:%d (candidates:%d), no peer selected",
- num_falsetickers, num_candidates);
+ VERB3 bb_error_msg("falsetickers:%d, candidates:%d%s",
+ num_falsetickers, num_candidates,
+ ", no peer selected");
return NULL;
}
}
- VERB3 bb_error_msg("selected interval: [%f, %f]; candidates:%d falsetickers:%d",
+ VERB4 bb_error_msg("selected interval: [%f, %f]; candidates:%d falsetickers:%d",
low, high, num_candidates, num_falsetickers);
/* Clustering */
@@ -1112,7 +1249,7 @@ select_and_cluster(void)
survivor[num_survivors].p = p;
/* x.opt_rd == root_distance(p); */
survivor[num_survivors].metric = MAXDIST * p->lastpkt_stratum + point[i].opt_rd;
- VERB4 bb_error_msg("survivor[%d] metric:%f peer:%s",
+ VERB5 bb_error_msg("survivor[%d] metric:%f peer:%s",
num_survivors, survivor[num_survivors].metric, p->p_dotted);
num_survivors++;
}
@@ -1122,8 +1259,9 @@ select_and_cluster(void)
* is acceptable.
*/
if (num_survivors < MIN_SELECTED) {
- VERB3 bb_error_msg("num_survivors %d < %d, no peer selected",
- num_survivors, MIN_SELECTED);
+ VERB3 bb_error_msg("survivors:%d%s",
+ num_survivors,
+ ", no peer selected");
return NULL;
}
@@ -1143,7 +1281,7 @@ select_and_cluster(void)
double min_jitter = min_jitter;
if (num_survivors <= MIN_CLUSTERED) {
- VERB3 bb_error_msg("num_survivors %d <= %d, not discarding more",
+ VERB4 bb_error_msg("num_survivors %d <= %d, not discarding more",
num_survivors, MIN_CLUSTERED);
break;
}
@@ -1169,11 +1307,11 @@ select_and_cluster(void)
max_selection_jitter = selection_jitter_sq;
max_idx = i;
}
- VERB5 bb_error_msg("survivor %d selection_jitter^2:%f",
+ VERB6 bb_error_msg("survivor %d selection_jitter^2:%f",
i, selection_jitter_sq);
}
max_selection_jitter = SQRT(max_selection_jitter / num_survivors);
- VERB4 bb_error_msg("max_selection_jitter (at %d):%f min_jitter:%f",
+ VERB5 bb_error_msg("max_selection_jitter (at %d):%f min_jitter:%f",
max_idx, max_selection_jitter, min_jitter);
/* If the maximum selection jitter is less than the
@@ -1182,7 +1320,7 @@ select_and_cluster(void)
* as well stop.
*/
if (max_selection_jitter < min_jitter) {
- VERB3 bb_error_msg("max_selection_jitter:%f < min_jitter:%f, num_survivors:%d, not discarding more",
+ VERB4 bb_error_msg("max_selection_jitter:%f < min_jitter:%f, num_survivors:%d, not discarding more",
max_selection_jitter, min_jitter, num_survivors);
break;
}
@@ -1190,7 +1328,7 @@ select_and_cluster(void)
/* Delete survivor[max_idx] from the list
* and go around again.
*/
- VERB5 bb_error_msg("dropping survivor %d", max_idx);
+ VERB6 bb_error_msg("dropping survivor %d", max_idx);
num_survivors--;
while (max_idx < num_survivors) {
survivor[max_idx] = survivor[max_idx + 1];
@@ -1232,7 +1370,7 @@ select_and_cluster(void)
/* Starting from 1 is ok here */
for (i = 1; i < num_survivors; i++) {
if (G.last_update_peer == survivor[i].p) {
- VERB4 bb_error_msg("keeping old synced peer");
+ VERB5 bb_error_msg("keeping old synced peer");
p = G.last_update_peer;
goto keep_old;
}
@@ -1240,7 +1378,7 @@ select_and_cluster(void)
}
G.last_update_peer = p;
keep_old:
- VERB3 bb_error_msg("selected peer %s filter_offset:%+f age:%f",
+ VERB4 bb_error_msg("selected peer %s filter_offset:%+f age:%f",
p->p_dotted,
p->filter_offset,
G.cur_time - p->lastpkt_recv_time
@@ -1259,7 +1397,7 @@ set_new_values(int disc_state, double offset, double recv_time)
* of the last clock filter sample, which must be earlier than
* the current time.
*/
- VERB3 bb_error_msg("disc_state=%d last update offset=%f recv_time=%f",
+ VERB4 bb_error_msg("disc_state=%d last update offset=%f recv_time=%f",
disc_state, offset, recv_time);
G.discipline_state = disc_state;
G.last_update_offset = offset;
@@ -1278,7 +1416,9 @@ update_local_clock(peer_t *p)
#if !USING_KERNEL_PLL_LOOP
double freq_drift;
#endif
+#if !USING_KERNEL_PLL_LOOP || USING_INITIAL_FREQ_ESTIMATION
double since_last_update;
+#endif
double etemp, dtemp;
abs_offset = fabs(offset);
@@ -1297,8 +1437,8 @@ update_local_clock(peer_t *p)
* an old sample or the same sample twice.
*/
if (recv_time <= G.last_update_recv_time) {
- VERB3 bb_error_msg("same or older datapoint: %f >= %f, not using it",
- G.last_update_recv_time, recv_time);
+ VERB3 bb_error_msg("update from %s: same or older datapoint, not using it",
+ p->p_dotted);
return 0; /* "leave poll interval as is" */
}
@@ -1306,7 +1446,9 @@ update_local_clock(peer_t *p)
* action is and defines how the system reacts to large time
* and frequency errors.
*/
+#if !USING_KERNEL_PLL_LOOP || USING_INITIAL_FREQ_ESTIMATION
since_last_update = recv_time - G.reftime;
+#endif
#if !USING_KERNEL_PLL_LOOP
freq_drift = 0;
#endif
@@ -1314,7 +1456,7 @@ update_local_clock(peer_t *p)
if (G.discipline_state == STATE_FREQ) {
/* Ignore updates until the stepout threshold */
if (since_last_update < WATCH_THRESHOLD) {
- VERB3 bb_error_msg("measuring drift, datapoint ignored, %f sec remains",
+ VERB4 bb_error_msg("measuring drift, datapoint ignored, %f sec remains",
WATCH_THRESHOLD - since_last_update);
return 0; /* "leave poll interval as is" */
}
@@ -1328,10 +1470,21 @@ update_local_clock(peer_t *p)
* offset exceeds the step threshold and when it does not.
*/
if (abs_offset > STEP_THRESHOLD) {
+#if 0
+ double remains;
+
+// This "spike state" seems to be useless, peer selection already drops
+// occassional "bad" datapoints. If we are here, there were _many_
+// large offsets. When a few first large offsets are seen,
+// we end up in "no valid datapoints, no peer selected" state.
+// Only when enough of them are seen (which means it's not a fluke),
+// we end up here. Looks like _our_ clock is off.
switch (G.discipline_state) {
case STATE_SYNC:
/* The first outlyer: ignore it, switch to SPIK state */
- VERB3 bb_error_msg("offset:%+f - spike detected", offset);
+ VERB3 bb_error_msg("update from %s: offset:%+f, spike%s",
+ p->p_dotted, offset,
+ "");
G.discipline_state = STATE_SPIK;
return -1; /* "decrease poll interval" */
@@ -1339,13 +1492,16 @@ update_local_clock(peer_t *p)
/* Ignore succeeding outlyers until either an inlyer
* is found or the stepout threshold is exceeded.
*/
- if (since_last_update < WATCH_THRESHOLD) {
- VERB3 bb_error_msg("spike detected, datapoint ignored, %f sec remains",
- WATCH_THRESHOLD - since_last_update);
+ remains = WATCH_THRESHOLD - since_last_update;
+ if (remains > 0) {
+ VERB3 bb_error_msg("update from %s: offset:%+f, spike%s",
+ p->p_dotted, offset,
+ ", datapoint ignored");
return -1; /* "decrease poll interval" */
}
/* fall through: we need to step */
} /* switch */
+#endif
/* Step the time and clamp down the poll interval.
*
@@ -1368,19 +1524,19 @@ update_local_clock(peer_t *p)
* is always suppressed, even at the longer poll
* intervals.
*/
- VERB3 bb_error_msg("stepping time by %+f; poll_exp=MINPOLL", offset);
+ VERB4 bb_error_msg("stepping time by %+f; poll_exp=MINPOLL", offset);
step_time(offset);
if (option_mask32 & OPT_q) {
/* We were only asked to set time once. Done. */
exit(0);
}
- G.polladj_count = 0;
- G.poll_exp = MINPOLL;
- G.stratum = MAXSTRAT;
+ clamp_pollexp_and_set_MAXSTRAT();
run_script("step", offset);
+ recv_time += offset;
+
#if USING_INITIAL_FREQ_ESTIMATION
if (G.discipline_state == STATE_NSET) {
set_new_values(STATE_FREQ, /*offset:*/ 0, recv_time);
@@ -1389,14 +1545,12 @@ update_local_clock(peer_t *p)
#endif
abs_offset = offset = 0;
set_new_values(STATE_SYNC, offset, recv_time);
-
} else { /* abs_offset <= STEP_THRESHOLD */
- if (G.poll_exp < MINPOLL && G.initial_poll_complete) {
- VERB3 bb_error_msg("small offset:%+f, disabling burst mode", offset);
- G.polladj_count = 0;
- G.poll_exp = MINPOLL;
- }
+ /* The ratio is calculated before jitter is updated to make
+ * poll adjust code more sensitive to large offsets.
+ */
+ G.offset_to_jitter_ratio = abs_offset / G.discipline_jitter;
/* Compute the clock jitter as the RMS of exponentially
* weighted offset differences. Used by the poll adjust code.
@@ -1404,6 +1558,8 @@ update_local_clock(peer_t *p)
etemp = SQUARE(G.discipline_jitter);
dtemp = SQUARE(offset - G.last_update_offset);
G.discipline_jitter = SQRT(etemp + (dtemp - etemp) / AVG);
+ if (G.discipline_jitter < G_precision_sec)
+ G.discipline_jitter = G_precision_sec;
switch (G.discipline_state) {
case STATE_NSET:
@@ -1422,7 +1578,7 @@ update_local_clock(peer_t *p)
#else
set_new_values(STATE_SYNC, offset, recv_time);
#endif
- VERB3 bb_error_msg("transitioning to FREQ, datapoint ignored");
+ VERB4 bb_error_msg("transitioning to FREQ, datapoint ignored");
return 0; /* "leave poll interval as is" */
#if 0 /* this is dead code for now */
@@ -1480,10 +1636,6 @@ update_local_clock(peer_t *p)
}
}
- if (G.discipline_jitter < G_precision_sec)
- G.discipline_jitter = G_precision_sec;
- G.offset_to_jitter_ratio = abs_offset / G.discipline_jitter;
-
G.reftime = G.cur_time;
G.ntp_status = p->lastpkt_status;
G.refid = p->lastpkt_refid;
@@ -1491,7 +1643,7 @@ update_local_clock(peer_t *p)
dtemp = p->filter_jitter; // SQRT(SQUARE(p->filter_jitter) + SQUARE(G.cluster_jitter));
dtemp += MAXD(p->filter_dispersion + FREQ_TOLERANCE * (G.cur_time - p->lastpkt_recv_time) + abs_offset, MINDISP);
G.rootdisp = p->lastpkt_rootdisp + dtemp;
- VERB3 bb_error_msg("updating leap/refid/reftime/rootdisp from peer %s", p->p_dotted);
+ VERB4 bb_error_msg("updating leap/refid/reftime/rootdisp from peer %s", p->p_dotted);
/* We are in STATE_SYNC now, but did not do adjtimex yet.
* (Any other state does not reach this, they all return earlier)
@@ -1511,13 +1663,13 @@ update_local_clock(peer_t *p)
dtemp = SQUARE(dtemp);
G.discipline_wander = SQRT(etemp + (dtemp - etemp) / AVG);
- VERB3 bb_error_msg("discipline freq_drift=%.9f(int:%ld corr:%e) wander=%f",
+ VERB4 bb_error_msg("discipline freq_drift=%.9f(int:%ld corr:%e) wander=%f",
G.discipline_freq_drift,
(long)(G.discipline_freq_drift * 65536e6),
freq_drift,
G.discipline_wander);
#endif
- VERB3 {
+ VERB4 {
memset(&tmx, 0, sizeof(tmx));
if (adjtimex(&tmx) < 0)
bb_perror_msg_and_die("adjtimex");
@@ -1536,14 +1688,7 @@ update_local_clock(peer_t *p)
tmx.freq = G.discipline_freq_drift * 65536e6;
#endif
tmx.modes = ADJ_OFFSET | ADJ_STATUS | ADJ_TIMECONST;// | ADJ_MAXERROR | ADJ_ESTERROR;
- tmx.offset = (offset * 1000000); /* usec */
- tmx.status = STA_PLL;
- if (G.ntp_status & LI_PLUSSEC)
- tmx.status |= STA_INS;
- if (G.ntp_status & LI_MINUSSEC)
- tmx.status |= STA_DEL;
-
- tmx.constant = G.poll_exp - 4;
+ tmx.constant = (int)G.poll_exp - 4;
/* EXPERIMENTAL.
* The below if statement should be unnecessary, but...
* It looks like Linux kernel's PLL is far too gentle in changing
@@ -1554,8 +1699,27 @@ update_local_clock(peer_t *p)
* To be on a safe side, let's do it only if offset is significantly
* larger than jitter.
*/
- if (tmx.constant > 0 && G.offset_to_jitter_ratio >= TIMECONST_HACK_GATE)
+ if (G.offset_to_jitter_ratio >= TIMECONST_HACK_GATE)
tmx.constant--;
+ tmx.offset = (long)(offset * 1000000); /* usec */
+ if (SLEW_THRESHOLD < STEP_THRESHOLD) {
+ if (tmx.offset > (long)(SLEW_THRESHOLD * 1000000)) {
+ tmx.offset = (long)(SLEW_THRESHOLD * 1000000);
+ tmx.constant--;
+ }
+ if (tmx.offset < -(long)(SLEW_THRESHOLD * 1000000)) {
+ tmx.offset = -(long)(SLEW_THRESHOLD * 1000000);
+ tmx.constant--;
+ }
+ }
+ if (tmx.constant < 0)
+ tmx.constant = 0;
+
+ tmx.status = STA_PLL;
+ if (G.ntp_status & LI_PLUSSEC)
+ tmx.status |= STA_INS;
+ if (G.ntp_status & LI_MINUSSEC)
+ tmx.status |= STA_DEL;
//tmx.esterror = (uint32_t)(clock_jitter * 1e6);
//tmx.maxerror = (uint32_t)((sys_rootdelay / 2 + sys_rootdisp) * 1e6);
@@ -1565,11 +1729,17 @@ update_local_clock(peer_t *p)
/* NB: here kernel returns constant == G.poll_exp, not == G.poll_exp - 4.
* Not sure why. Perhaps it is normal.
*/
- VERB3 bb_error_msg("adjtimex:%d freq:%ld offset:%+ld status:0x%x",
+ VERB4 bb_error_msg("adjtimex:%d freq:%ld offset:%+ld status:0x%x",
rc, tmx.freq, tmx.offset, tmx.status);
G.kernel_freq_drift = tmx.freq / 65536;
- VERB2 bb_error_msg("update from:%s offset:%+f jitter:%f clock drift:%+.3fppm tc:%d",
- p->p_dotted, offset, G.discipline_jitter, (double)tmx.freq / 65536, (int)tmx.constant);
+ VERB2 bb_error_msg("update from:%s offset:%+f delay:%f jitter:%f clock drift:%+.3fppm tc:%d",
+ p->p_dotted,
+ offset,
+ p->lastpkt_delay,
+ G.discipline_jitter,
+ (double)tmx.freq / 65536,
+ (int)tmx.constant
+ );
return 1; /* "ok to increase poll interval" */
}
@@ -1580,28 +1750,52 @@ update_local_clock(peer_t *p)
* (helpers first)
*/
static unsigned
-retry_interval(void)
+poll_interval(int upper_bound)
{
- /* Local problem, want to retry soon */
- unsigned interval, r;
- interval = RETRY_INTERVAL;
- r = random();
- interval += r % (unsigned)(RETRY_INTERVAL / 4);
- VERB3 bb_error_msg("chose retry interval:%u", interval);
+ unsigned interval, r, mask;
+ interval = 1 << G.poll_exp;
+ if (interval > upper_bound)
+ interval = upper_bound;
+ mask = ((interval-1) >> 4) | 1;
+ r = rand();
+ interval += r & mask; /* ~ random(0..1) * interval/16 */
+ VERB4 bb_error_msg("chose poll interval:%u (poll_exp:%d)", interval, G.poll_exp);
return interval;
}
-static unsigned
-poll_interval(int exponent)
+static void
+adjust_poll(int count)
{
- unsigned interval, r;
- exponent = G.poll_exp + exponent;
- if (exponent < 0)
- exponent = 0;
- interval = 1 << exponent;
- r = random();
- interval += ((r & (interval-1)) >> 4) + ((r >> 8) & 1); /* + 1/16 of interval, max */
- VERB3 bb_error_msg("chose poll interval:%u (poll_exp:%d exp:%d)", interval, G.poll_exp, exponent);
- return interval;
+ G.polladj_count += count;
+ if (G.polladj_count > POLLADJ_LIMIT) {
+ G.polladj_count = 0;
+ if (G.poll_exp < MAXPOLL) {
+ G.poll_exp++;
+ VERB4 bb_error_msg("polladj: discipline_jitter:%f ++poll_exp=%d",
+ G.discipline_jitter, G.poll_exp);
+ }
+ } else if (G.polladj_count < -POLLADJ_LIMIT || (count < 0 && G.poll_exp > BIGPOLL)) {
+ G.polladj_count = 0;
+ if (G.poll_exp > MINPOLL) {
+ llist_t *item;
+
+ G.poll_exp--;
+ /* Correct p->next_action_time in each peer
+ * which waits for sending, so that they send earlier.
+ * Old pp->next_action_time are on the order
+ * of t + (1 << old_poll_exp) + small_random,
+ * we simply need to subtract ~half of that.
+ */
+ for (item = G.ntp_peers; item != NULL; item = item->link) {
+ peer_t *pp = (peer_t *) item->data;
+ if (pp->p_fd < 0)
+ pp->next_action_time -= (1 << G.poll_exp);
+ }
+ VERB4 bb_error_msg("polladj: discipline_jitter:%f --poll_exp=%d",
+ G.discipline_jitter, G.poll_exp);
+ }
+ } else {
+ VERB4 bb_error_msg("polladj: count:%d", G.polladj_count);
+ }
}
static NOINLINE void
recv_and_process_peer_pkt(peer_t *p)
@@ -1610,63 +1804,77 @@ recv_and_process_peer_pkt(peer_t *p)
ssize_t size;
msg_t msg;
double T1, T2, T3, T4;
+ double offset;
+ double prev_delay, delay;
unsigned interval;
datapoint_t *datapoint;
peer_t *q;
+ offset = 0;
+
/* We can recvfrom here and check from.IP, but some multihomed
* ntp servers reply from their *other IP*.
* TODO: maybe we should check at least what we can: from.port == 123?
*/
+ recv_again:
size = recv(p->p_fd, &msg, sizeof(msg), MSG_DONTWAIT);
- if (size == -1) {
- bb_perror_msg("recv(%s) error", p->p_dotted);
- if (errno == EHOSTUNREACH || errno == EHOSTDOWN
- || errno == ENETUNREACH || errno == ENETDOWN
- || errno == ECONNREFUSED || errno == EADDRNOTAVAIL
- || errno == EAGAIN
- ) {
-//TODO: always do this?
- interval = retry_interval();
- goto set_next_and_close_sock;
- }
- xfunc_die();
+ if (size < 0) {
+ if (errno == EINTR)
+ /* Signal caught */
+ goto recv_again;
+ if (errno == EAGAIN)
+ /* There was no packet after all
+ * (poll() returning POLLIN for a fd
+ * is not a ironclad guarantee that data is there)
+ */
+ return;
+ /*
+ * If you need a different handling for a specific
+ * errno, always explain it in comment.
+ */
+ bb_perror_msg_and_die("recv(%s) error", p->p_dotted);
}
if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) {
bb_error_msg("malformed packet received from %s", p->p_dotted);
- goto bail;
+ return;
}
if (msg.m_orgtime.int_partl != p->p_xmt_msg.m_xmttime.int_partl
|| msg.m_orgtime.fractionl != p->p_xmt_msg.m_xmttime.fractionl
) {
- goto bail;
+ /* Somebody else's packet */
+ return;
}
+ /* We do not expect any more packets from this peer for now.
+ * Closing the socket informs kernel about it.
+ * We open a new socket when we send a new query.
+ */
+ close(p->p_fd);
+ p->p_fd = -1;
+
if (!(option_mask32 & OPT_t) /* RFC-4330 check enabled by default */
&& ((msg.m_status & LI_ALARM) == LI_ALARM
|| msg.m_stratum == 0
|| msg.m_stratum > NTP_MAXSTRATUM)
) {
-// TODO: stratum 0 responses may have commands in 32-bit m_refid field:
-// "DENY", "RSTR" - peer does not like us at all
-// "RATE" - peer is overloaded, reduce polling freq
- interval = poll_interval(0);
- bb_error_msg("reply from %s: not synced, next query in %us", p->p_dotted, interval);
- goto set_next_and_close_sock;
+ bb_error_msg("reply from %s: peer is unsynced", p->p_dotted);
+ /*
+ * Stratum 0 responses may have commands in 32-bit m_refid field:
+ * "DENY", "RSTR" - peer does not like us at all,
+ * "RATE" - peer is overloaded, reduce polling freq.
+ * If poll interval is small, increase it.
+ */
+ if (G.poll_exp < BIGPOLL)
+ goto increase_interval;
+ goto pick_normal_interval;
}
// /* Verify valid root distance */
// if (msg.m_rootdelay / 2 + msg.m_rootdisp >= MAXDISP || p->lastpkt_reftime > msg.m_xmt)
// return; /* invalid header values */
- p->lastpkt_status = msg.m_status;
- p->lastpkt_stratum = msg.m_stratum;
- p->lastpkt_rootdelay = sfp_to_d(msg.m_rootdelay);
- p->lastpkt_rootdisp = sfp_to_d(msg.m_rootdisp);
- p->lastpkt_refid = msg.m_refid;
-
/*
* From RFC 2030 (with a correction to the delay math):
*
@@ -1686,28 +1894,45 @@ recv_and_process_peer_pkt(peer_t *p)
T3 = lfp_to_d(msg.m_xmttime);
T4 = G.cur_time;
- p->lastpkt_recv_time = T4;
-
- VERB5 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time);
- p->datapoint_idx = p->reachable_bits ? (p->datapoint_idx + 1) % NUM_DATAPOINTS : 0;
- datapoint = &p->filter_datapoint[p->datapoint_idx];
- datapoint->d_recv_time = T4;
- datapoint->d_offset = ((T2 - T1) + (T3 - T4)) / 2;
/* The delay calculation is a special case. In cases where the
* server and client clocks are running at different rates and
* with very fast networks, the delay can appear negative. In
* order to avoid violating the Principle of Least Astonishment,
* the delay is clamped not less than the system precision.
*/
- p->lastpkt_delay = (T4 - T1) - (T3 - T2);
- if (p->lastpkt_delay < G_precision_sec)
- p->lastpkt_delay = G_precision_sec;
+ delay = (T4 - T1) - (T3 - T2);
+ if (delay < G_precision_sec)
+ delay = G_precision_sec;
+ /*
+ * If this packet's delay is much bigger than the last one,
+ * it's better to just ignore it than use its much less precise value.
+ */
+ prev_delay = p->p_raw_delay;
+ p->p_raw_delay = delay;
+ if (p->reachable_bits && delay > prev_delay * BAD_DELAY_GROWTH) {
+ bb_error_msg("reply from %s: delay %f is too high, ignoring", p->p_dotted, delay);
+ goto pick_normal_interval;
+ }
+
+ p->lastpkt_delay = delay;
+ p->lastpkt_recv_time = T4;
+ VERB6 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time);
+ p->lastpkt_status = msg.m_status;
+ p->lastpkt_stratum = msg.m_stratum;
+ p->lastpkt_rootdelay = sfp_to_d(msg.m_rootdelay);
+ p->lastpkt_rootdisp = sfp_to_d(msg.m_rootdisp);
+ p->lastpkt_refid = msg.m_refid;
+
+ p->datapoint_idx = p->reachable_bits ? (p->datapoint_idx + 1) % NUM_DATAPOINTS : 0;
+ datapoint = &p->filter_datapoint[p->datapoint_idx];
+ datapoint->d_recv_time = T4;
+ datapoint->d_offset = offset = ((T2 - T1) + (T3 - T4)) / 2;
datapoint->d_dispersion = LOG2D(msg.m_precision_exp) + G_precision_sec;
if (!p->reachable_bits) {
/* 1st datapoint ever - replicate offset in every element */
int i;
for (i = 0; i < NUM_DATAPOINTS; i++) {
- p->filter_datapoint[i].d_offset = datapoint->d_offset;
+ p->filter_datapoint[i].d_offset = offset;
}
}
@@ -1715,7 +1940,7 @@ recv_and_process_peer_pkt(peer_t *p)
if ((MAX_VERBOSE && G.verbose) || (option_mask32 & OPT_w)) {
bb_error_msg("reply from %s: offset:%+f delay:%f status:0x%02x strat:%d refid:0x%08x rootdelay:%f reach:0x%02x",
p->p_dotted,
- datapoint->d_offset,
+ offset,
p->lastpkt_delay,
p->lastpkt_status,
p->lastpkt_stratum,
@@ -1731,21 +1956,36 @@ recv_and_process_peer_pkt(peer_t *p)
/* Muck with statictics and update the clock */
filter_datapoints(p);
q = select_and_cluster();
- rc = -1;
+ rc = 0;
if (q) {
- rc = 0;
if (!(option_mask32 & OPT_w)) {
rc = update_local_clock(q);
+#if 0
+//Disabled this because there is a case where largish offsets
+//are unavoidable: if network round-trip delay is, say, ~0.6s,
+//error in offset estimation would be ~delay/2 ~= 0.3s.
+//Thus, offsets will be usually in -0.3...0.3s range.
+//In this case, this code would keep poll interval small,
+//but it won't be helping.
+//BIGOFF check below deals with a case of seeing multi-second offsets.
+
/* If drift is dangerously large, immediately
* drop poll interval one step down.
*/
if (fabs(q->filter_offset) >= POLLDOWN_OFFSET) {
- VERB3 bb_error_msg("offset:%+f > POLLDOWN_OFFSET", q->filter_offset);
- goto poll_down;
+ VERB4 bb_error_msg("offset:%+f > POLLDOWN_OFFSET", q->filter_offset);
+ adjust_poll(-POLLADJ_LIMIT * 3);
+ rc = 0;
}
+#endif
}
+ } else {
+ /* No peer selected.
+ * If poll interval is small, increase it.
+ */
+ if (G.poll_exp < BIGPOLL)
+ goto increase_interval;
}
- /* else: no peer selected, rc = -1: we want to poll more often */
if (rc != 0) {
/* Adjust the poll interval by comparing the current offset
@@ -1757,59 +1997,35 @@ recv_and_process_peer_pkt(peer_t *p)
if (rc > 0 && G.offset_to_jitter_ratio <= POLLADJ_GATE) {
/* was += G.poll_exp but it is a bit
* too optimistic for my taste at high poll_exp's */
- G.polladj_count += MINPOLL;
- if (G.polladj_count > POLLADJ_LIMIT) {
- G.polladj_count = 0;
- if (G.poll_exp < MAXPOLL) {
- G.poll_exp++;
- VERB3 bb_error_msg("polladj: discipline_jitter:%f ++poll_exp=%d",
- G.discipline_jitter, G.poll_exp);
- }
- } else {
- VERB3 bb_error_msg("polladj: incr:%d", G.polladj_count);
- }
+ increase_interval:
+ adjust_poll(MINPOLL);
} else {
- G.polladj_count -= G.poll_exp * 2;
- if (G.polladj_count < -POLLADJ_LIMIT || G.poll_exp >= BIGPOLL) {
- poll_down:
- G.polladj_count = 0;
- if (G.poll_exp > MINPOLL) {
- llist_t *item;
-
- G.poll_exp--;
- /* Correct p->next_action_time in each peer
- * which waits for sending, so that they send earlier.
- * Old pp->next_action_time are on the order
- * of t + (1 << old_poll_exp) + small_random,
- * we simply need to subtract ~half of that.
- */
- for (item = G.ntp_peers; item != NULL; item = item->link) {
- peer_t *pp = (peer_t *) item->data;
- if (pp->p_fd < 0)
- pp->next_action_time -= (1 << G.poll_exp);
- }
- VERB3 bb_error_msg("polladj: discipline_jitter:%f --poll_exp=%d",
- G.discipline_jitter, G.poll_exp);
- }
- } else {
- VERB3 bb_error_msg("polladj: decr:%d", G.polladj_count);
- }
+ VERB3 if (rc > 0)
+ bb_error_msg("want smaller interval: offset/jitter = %u",
+ G.offset_to_jitter_ratio);
+ adjust_poll(-G.poll_exp * 2);
}
}
/* Decide when to send new query for this peer */
- interval = poll_interval(0);
+ pick_normal_interval:
+ interval = poll_interval(INT_MAX);
+ if (fabs(offset) >= BIGOFF && interval > BIGOFF_INTERVAL) {
+ /* If we are synced, offsets are less than SLEW_THRESHOLD,
+ * or at the very least not much larger than it.
+ * Now we see a largish one.
+ * Either this peer is feeling bad, or packet got corrupted,
+ * or _our_ clock is wrong now and _all_ peers will show similar
+ * largish offsets too.
+ * I observed this with laptop suspend stopping clock.
+ * In any case, it makes sense to make next request soonish:
+ * cases 1 and 2: get a better datapoint,
+ * case 3: allows to resync faster.
+ */
+ interval = BIGOFF_INTERVAL;
+ }
- set_next_and_close_sock:
set_next(p, interval);
- /* We do not expect any more packets from this peer for now.
- * Closing the socket informs kernel about it.
- * We open a new socket when we send a new query.
- */
- close(p->p_fd);
- p->p_fd = -1;
- bail:
- return;
}
#if ENABLE_FEATURE_NTPD_SERVER
@@ -1841,15 +2057,22 @@ recv_and_process_client_pkt(void /*int fd*/)
goto bail;
}
+ /* Respond only to client and symmetric active packets */
+ if ((msg.m_status & MODE_MASK) != MODE_CLIENT
+ && (msg.m_status & MODE_MASK) != MODE_SYM_ACT
+ ) {
+ goto bail;
+ }
+
query_status = msg.m_status;
query_xmttime = msg.m_xmttime;
/* Build a reply packet */
memset(&msg, 0, sizeof(msg));
- msg.m_status = G.stratum < MAXSTRAT ? G.ntp_status : LI_ALARM;
+ msg.m_status = G.stratum < MAXSTRAT ? (G.ntp_status & LI_MASK) : LI_ALARM;
msg.m_status |= (query_status & VERSION_MASK);
msg.m_status |= ((query_status & MODE_MASK) == MODE_CLIENT) ?
- MODE_SERVER : MODE_SYM_PAS;
+ MODE_SERVER : MODE_SYM_PAS;
msg.m_stratum = G.stratum;
msg.m_ppoll = G.poll_exp;
msg.m_precision_exp = G_precision_exp;
@@ -1973,12 +2196,13 @@ static NOINLINE void ntp_init(char **argv)
unsigned opts;
llist_t *peers;
- srandom(getpid());
+ srand(getpid());
if (getuid())
bb_error_msg_and_die(bb_msg_you_must_be_root);
/* Set some globals */
+ G.discipline_jitter = G_precision_sec;
G.stratum = MAXSTRAT;
if (BURSTPOLL != 0)
G.poll_exp = BURSTPOLL; /* speeds up initial sync */
@@ -1986,36 +2210,66 @@ static NOINLINE void ntp_init(char **argv)
/* Parse options */
peers = NULL;
- opt_complementary = "dd:p::wn"; /* d: counter; p: list; -w implies -n */
+ opt_complementary = "dd:p::wn" /* -d: counter; -p: list; -w implies -n */
+ IF_FEATURE_NTPD_SERVER(":Il"); /* -I implies -l */
opts = getopt32(argv,
"nqNx" /* compat */
"wp:S:t"IF_FEATURE_NTPD_SERVER("l") /* NOT compat */
+ IF_FEATURE_NTPD_SERVER("I:") /* compat */
"d" /* compat */
"46aAbgL", /* compat, ignored */
- &peers, &G.script_name, &G.verbose);
- if (!(opts & (OPT_p|OPT_l)))
- bb_show_usage();
+ &peers,&G.script_name,
+#if ENABLE_FEATURE_NTPD_SERVER
+ &G.if_name,
+#endif
+ &G.verbose);
+
// if (opts & OPT_x) /* disable stepping, only slew is allowed */
// G.time_was_stepped = 1;
if (peers) {
while (peers)
add_peers(llist_pop(&peers));
- } else {
+ }
+#if ENABLE_FEATURE_NTPD_CONF
+ else {
+ parser_t *parser;
+ char *token[3];
+
+ parser = config_open("/etc/ntp.conf");
+ while (config_read(parser, token, 3, 1, "# \t", PARSE_NORMAL)) {
+ if (strcmp(token[0], "server") == 0 && token[1]) {
+ add_peers(token[1]);
+ continue;
+ }
+ bb_error_msg("skipping %s:%u: unimplemented command '%s'",
+ "/etc/ntp.conf", parser->lineno, token[0]
+ );
+ }
+ config_close(parser);
+ }
+#endif
+ if (G.peer_cnt == 0) {
+ if (!(opts & OPT_l))
+ bb_show_usage();
/* -l but no peers: "stratum 1 server" mode */
G.stratum = 1;
}
- if (!(opts & OPT_n)) {
- bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv);
- logmode = LOGMODE_NONE;
- }
#if ENABLE_FEATURE_NTPD_SERVER
G_listen_fd = -1;
if (opts & OPT_l) {
G_listen_fd = create_and_bind_dgram_or_die(NULL, 123);
+ if (opts & OPT_I) {
+ if (setsockopt_bindtodevice(G_listen_fd, G.if_name))
+ xfunc_die();
+ }
socket_want_pktinfo(G_listen_fd);
- setsockopt(G_listen_fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY));
+ setsockopt_int(G_listen_fd, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY);
}
#endif
+ if (!(opts & OPT_n)) {
+ bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv);
+ logmode = LOGMODE_NONE;
+ }
/* I hesitate to set -20 prio. -15 should be high enough for timekeeping */
if (opts & OPT_N)
setpriority(PRIO_PROCESS, 0, -15);
@@ -2072,9 +2326,10 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
* fewer packets to it and more to other peers.
* NB2: sync usually happens using INITIAL_SAMPLES packets,
* since last reply does not come back instantaneously.
- * NB3: sync by single answer if exit after sync requested.
*/
- cnt = G.peer_cnt * ((option_mask32 & OPT_q) ? 1 : (INITIAL_SAMPLES + 1));
+ cnt = G.peer_cnt * (INITIAL_SAMPLES + 1);
+
+ write_pidfile(CONFIG_PID_FILE_PATH "/ntpd.pid");
while (!bb_got_signal) {
llist_t *item;
@@ -2102,16 +2357,26 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
if (p->p_fd == -1) {
/* Time to send new req */
if (--cnt == 0) {
- G.initial_poll_complete = 1;
+ VERB4 bb_error_msg("disabling burst mode");
+ G.polladj_count = 0;
+ G.poll_exp = MINPOLL;
}
send_query_to_peer(p);
} else {
/* Timed out waiting for reply */
close(p->p_fd);
p->p_fd = -1;
- timeout = poll_interval(-2); /* -2: try a bit sooner */
+ /* If poll interval is small, increase it */
+ if (G.poll_exp < BIGPOLL)
+ adjust_poll(MINPOLL);
+ timeout = poll_interval(NOREPLY_INTERVAL);
bb_error_msg("timed out waiting for %s, reach 0x%02x, next query in %us",
p->p_dotted, p->reachable_bits, timeout);
+
+ /* What if don't see it because it changed its IP? */
+ if (p->reachable_bits == 0)
+ resolve_peer_hostname(p, /*loop_on_fail=*/ 0);
+
set_next(p, timeout);
}
}
@@ -2153,12 +2418,14 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
did_poll:
gettime1900d(); /* sets G.cur_time */
if (nfds <= 0) {
- if (G.script_name && G.cur_time - G.last_script_run > 11*60) {
+ if (!bb_got_signal /* poll wasn't interrupted by a signal */
+ && G.cur_time - G.last_script_run > 11*60
+ ) {
/* Useful for updating battery-backed RTC and such */
run_script("periodic", G.last_update_offset);
gettime1900d(); /* sets G.cur_time */
}
- continue;
+ goto check_unsync;
}
/* Process any received packets */
@@ -2189,8 +2456,22 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
gettime1900d(); /* sets G.cur_time */
}
}
+
+ check_unsync:
+ if (G.ntp_peers && G.stratum != MAXSTRAT) {
+ for (item = G.ntp_peers; item != NULL; item = item->link) {
+ peer_t *p = (peer_t *) item->data;
+ if (p->reachable_bits)
+ goto have_reachable_peer;
+ }
+ /* No peer responded for last 8 packets, panic */
+ clamp_pollexp_and_set_MAXSTRAT();
+ run_script("unsync", 0.0);
+ have_reachable_peer: ;
+ }
} /* while (!bb_got_signal) */
+ remove_pidfile(CONFIG_PID_FILE_PATH "/ntpd.pid");
kill_myself_with_sig(bb_got_signal);
}
@@ -2321,14 +2602,13 @@ set_freq(double freq) /* frequency update */
if (pps_enable) {
if (!(pll_status & STA_PPSTIME))
report_event(EVNT_KERN,
- NULL, "PPS enabled");
+ NULL, "PPS enabled");
ntv.status |= STA_PPSTIME | STA_PPSFREQ;
} else {
if (pll_status & STA_PPSTIME)
report_event(EVNT_KERN,
- NULL, "PPS disabled");
- ntv.status &= ~(STA_PPSTIME |
- STA_PPSFREQ);
+ NULL, "PPS disabled");
+ ntv.status &= ~(STA_PPSTIME | STA_PPSFREQ);
}
if (sys_leap == LEAP_ADDSECOND)
ntv.status |= STA_INS;
@@ -2344,7 +2624,7 @@ set_freq(double freq) /* frequency update */
if (ntp_adjtime(&ntv) == TIME_ERROR) {
if (!(ntv.status & STA_PPSSIGNAL))
report_event(EVNT_KERN, NULL,
- "PPS no signal");
+ "PPS no signal");
}
pll_status = ntv.status;
#ifdef STA_NANO
diff --git a/release/src/router/busybox/networking/ntpd.diff b/release/src/router/busybox/networking/ntpd.diff
new file mode 100644
index 0000000000..4afd7e1349
--- /dev/null
+++ b/release/src/router/busybox/networking/ntpd.diff
@@ -0,0 +1,24 @@
+This patch scales down small offsets quadratically. Reduces sensitivity to jitter
+
+diff --git a/networking/ntpd.c b/networking/ntpd.c
+index 4695c33..ac05815 100644
+--- a/networking/ntpd.c
++++ b/networking/ntpd.c
+@@ -1654,6 +1654,17 @@ update_local_clock(peer_t *p)
+ */
+ if (G.offset_to_jitter_ratio >= TIMECONST_HACK_GATE)
+ tmx.constant--;
++
++{
++ double d = p->lastpkt_delay;
++ if (d > SLEW_THRESHOLD)
++ d = SLEW_THRESHOLD;
++ d /= 2;
++ if ((abs_offset / d) < 1) {
++ offset *= (abs_offset / d);
++ }
++}
++
+ tmx.offset = (long)(offset * 1000000); /* usec */
+ if (SLEW_THRESHOLD < STEP_THRESHOLD) {
+ if (tmx.offset > (long)(SLEW_THRESHOLD * 1000000)) {
diff --git a/release/src/router/busybox/networking/ntpd_simple.c b/release/src/router/busybox/networking/ntpd_simple.c
deleted file mode 100644
index 4ad44e4f35..0000000000
--- a/release/src/router/busybox/networking/ntpd_simple.c
+++ /dev/null
@@ -1,1007 +0,0 @@
-/*
- * NTP client/server, based on OpenNTPD 3.9p1
- *
- * Author: Adam Tkac <vonsch@gmail.com>
- *
- * Licensed under GPLv2, see file LICENSE in this source tree.
- */
-#include "libbb.h"
-#include <netinet/ip.h> /* For IPTOS_LOWDELAY definition */
-#ifndef IPTOS_LOWDELAY
-# define IPTOS_LOWDELAY 0x10
-#endif
-#ifndef IP_PKTINFO
-# error "Sorry, your kernel has to support IP_PKTINFO"
-#endif
-
-
-/* Sync to peers every N secs */
-#define INTERVAL_QUERY_NORMAL 30
-#define INTERVAL_QUERY_PATHETIC 60
-#define INTERVAL_QUERY_AGRESSIVE 5
-
-/* Bad if *less than* TRUSTLEVEL_BADPEER */
-#define TRUSTLEVEL_BADPEER 6
-#define TRUSTLEVEL_PATHETIC 2
-#define TRUSTLEVEL_AGRESSIVE 8
-#define TRUSTLEVEL_MAX 10
-
-#define QSCALE_OFF_MIN 0.05
-#define QSCALE_OFF_MAX 0.50
-
-/* Single query might take N secs max */
-#define QUERYTIME_MAX 15
-/* Min offset for settime at start. "man ntpd" says it's 128 ms */
-#define STEPTIME_MIN_OFFSET 0.128
-
-typedef struct {
- uint32_t int_partl;
- uint32_t fractionl;
-} l_fixedpt_t;
-
-typedef struct {
- uint16_t int_parts;
- uint16_t fractions;
-} s_fixedpt_t;
-
-enum {
- NTP_DIGESTSIZE = 16,
- NTP_MSGSIZE_NOAUTH = 48,
- NTP_MSGSIZE = (NTP_MSGSIZE_NOAUTH + 4 + NTP_DIGESTSIZE),
-};
-
-typedef struct {
- uint8_t m_status; /* status of local clock and leap info */
- uint8_t m_stratum; /* stratum level */
- uint8_t m_ppoll; /* poll value */
- int8_t m_precision_exp;
- s_fixedpt_t m_rootdelay;
- s_fixedpt_t m_dispersion;
- uint32_t m_refid;
- l_fixedpt_t m_reftime;
- l_fixedpt_t m_orgtime;
- l_fixedpt_t m_rectime;
- l_fixedpt_t m_xmttime;
- uint32_t m_keyid;
- uint8_t m_digest[NTP_DIGESTSIZE];
-} msg_t;
-
-enum {
- NTP_VERSION = 4,
- NTP_MAXSTRATUM = 15,
-
- /* Status Masks */
- MODE_MASK = (7 << 0),
- VERSION_MASK = (7 << 3),
- VERSION_SHIFT = 3,
- LI_MASK = (3 << 6),
-
- /* Leap Second Codes (high order two bits of m_status) */
- LI_NOWARNING = (0 << 6), /* no warning */
- LI_PLUSSEC = (1 << 6), /* add a second (61 seconds) */
- LI_MINUSSEC = (2 << 6), /* minus a second (59 seconds) */
- LI_ALARM = (3 << 6), /* alarm condition */
-
- /* Mode values */
- MODE_RES0 = 0, /* reserved */
- MODE_SYM_ACT = 1, /* symmetric active */
- MODE_SYM_PAS = 2, /* symmetric passive */
- MODE_CLIENT = 3, /* client */
- MODE_SERVER = 4, /* server */
- MODE_BROADCAST = 5, /* broadcast */
- MODE_RES1 = 6, /* reserved for NTP control message */
- MODE_RES2 = 7, /* reserved for private use */
-};
-
-#define OFFSET_1900_1970 2208988800UL /* 1970 - 1900 in seconds */
-
-typedef struct {
- double d_offset;
- double d_delay;
- //UNUSED: double d_error;
- time_t d_rcv_time;
- uint32_t d_refid4;
- uint8_t d_leap;
- uint8_t d_stratum;
- uint8_t d_good;
-} datapoint_t;
-
-#define NUM_DATAPOINTS 8
-typedef struct {
- len_and_sockaddr *p_lsa;
- char *p_dotted;
- /* When to send new query (if p_fd == -1)
- * or when receive times out (if p_fd >= 0): */
- time_t next_action_time;
- int p_fd;
- uint8_t p_datapoint_idx;
- uint8_t p_trustlevel;
- double p_xmttime;
- datapoint_t update;
- datapoint_t p_datapoint[NUM_DATAPOINTS];
- msg_t p_xmt_msg;
-} peer_t;
-
-enum {
- OPT_n = (1 << 0),
- OPT_q = (1 << 1),
- OPT_N = (1 << 2),
- OPT_x = (1 << 3),
- /* Insert new options above this line. */
- /* Non-compat options: */
- OPT_p = (1 << 4),
- OPT_l = (1 << 5) * ENABLE_FEATURE_NTPD_SERVER,
-};
-
-
-struct globals {
- /* total round trip delay to currently selected reference clock */
- double rootdelay;
- /* reference timestamp: time when the system clock was last set or corrected */
- double reftime;
- llist_t *ntp_peers;
-#if ENABLE_FEATURE_NTPD_SERVER
- int listen_fd;
-#endif
- unsigned verbose;
- unsigned peer_cnt;
- unsigned scale;
- uint32_t refid;
- uint32_t refid4;
- uint8_t synced;
- uint8_t leap;
-#define G_precision_exp -6
-// int8_t precision_exp;
- uint8_t stratum;
- uint8_t time_was_stepped;
- uint8_t first_adj_done;
-};
-#define G (*ptr_to_globals)
-
-static const int const_IPTOS_LOWDELAY = IPTOS_LOWDELAY;
-
-
-static void
-set_next(peer_t *p, unsigned t)
-{
- p->next_action_time = time(NULL) + t;
-}
-
-static void
-add_peers(char *s)
-{
- peer_t *p;
-
- p = xzalloc(sizeof(*p));
- p->p_lsa = xhost2sockaddr(s, 123);
- p->p_dotted = xmalloc_sockaddr2dotted_noport(&p->p_lsa->u.sa);
- p->p_fd = -1;
- p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3);
- p->p_trustlevel = TRUSTLEVEL_PATHETIC;
- p->next_action_time = time(NULL); /* = set_next(p, 0); */
-
- llist_add_to(&G.ntp_peers, p);
- G.peer_cnt++;
-}
-
-static double
-gettime1900d(void)
-{
- struct timeval tv;
- gettimeofday(&tv, NULL); /* never fails */
- return (tv.tv_sec + 1.0e-6 * tv.tv_usec + OFFSET_1900_1970);
-}
-
-static void
-d_to_tv(double d, struct timeval *tv)
-{
- tv->tv_sec = (long)d;
- tv->tv_usec = (d - tv->tv_sec) * 1000000;
-}
-
-static double
-lfp_to_d(l_fixedpt_t lfp)
-{
- double ret;
- lfp.int_partl = ntohl(lfp.int_partl);
- lfp.fractionl = ntohl(lfp.fractionl);
- ret = (double)lfp.int_partl + ((double)lfp.fractionl / UINT_MAX);
- return ret;
-}
-
-#if 0 //UNUSED
-static double
-sfp_to_d(s_fixedpt_t sfp)
-{
- double ret;
- sfp.int_parts = ntohs(sfp.int_parts);
- sfp.fractions = ntohs(sfp.fractions);
- ret = (double)sfp.int_parts + ((double)sfp.fractions / USHRT_MAX);
- return ret;
-}
-#endif
-
-#if ENABLE_FEATURE_NTPD_SERVER
-static l_fixedpt_t
-d_to_lfp(double d)
-{
- l_fixedpt_t lfp;
- lfp.int_partl = (uint32_t)d;
- lfp.fractionl = (uint32_t)((d - lfp.int_partl) * UINT_MAX);
- lfp.int_partl = htonl(lfp.int_partl);
- lfp.fractionl = htonl(lfp.fractionl);
- return lfp;
-}
-
-static s_fixedpt_t
-d_to_sfp(double d)
-{
- s_fixedpt_t sfp;
- sfp.int_parts = (uint16_t)d;
- sfp.fractions = (uint16_t)((d - sfp.int_parts) * USHRT_MAX);
- sfp.int_parts = htons(sfp.int_parts);
- sfp.fractions = htons(sfp.fractions);
- return sfp;
-}
-#endif
-
-static unsigned
-error_interval(void)
-{
- unsigned interval, r;
- interval = INTERVAL_QUERY_PATHETIC * QSCALE_OFF_MAX / QSCALE_OFF_MIN;
- r = (unsigned)random() % (unsigned)(interval / 10);
- return (interval + r);
-}
-
-static int
-do_sendto(int fd,
- const struct sockaddr *from, const struct sockaddr *to, socklen_t addrlen,
- msg_t *msg, ssize_t len)
-{
- ssize_t ret;
-
- errno = 0;
- if (!from) {
- ret = sendto(fd, msg, len, MSG_DONTWAIT, to, addrlen);
- } else {
- ret = send_to_from(fd, msg, len, MSG_DONTWAIT, to, from, addrlen);
- }
- if (ret != len) {
- bb_perror_msg("send failed");
- return -1;
- }
- return 0;
-}
-
-static int
-send_query_to_peer(peer_t *p)
-{
- // Why do we need to bind()?
- // See what happens when we don't bind:
- //
- // socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
- // setsockopt(3, SOL_IP, IP_TOS, [16], 4) = 0
- // gettimeofday({1259071266, 327885}, NULL) = 0
- // sendto(3, "xxx", 48, MSG_DONTWAIT, {sa_family=AF_INET, sin_port=htons(123), sin_addr=inet_addr("10.34.32.125")}, 16) = 48
- // ^^^ we sent it from some source port picked by kernel.
- // time(NULL) = 1259071266
- // write(2, "ntpd: entering poll 15 secs\n", 28) = 28
- // poll([{fd=3, events=POLLIN}], 1, 15000) = 1 ([{fd=3, revents=POLLIN}])
- // recv(3, "yyy", 68, MSG_DONTWAIT) = 48
- // ^^^ this recv will receive packets to any local port!
- //
- // Uncomment this and use strace to see it in action:
-#define PROBE_LOCAL_ADDR // { len_and_sockaddr lsa; lsa.len = LSA_SIZEOF_SA; getsockname(p->query.fd, &lsa.u.sa, &lsa.len); }
-
- if (p->p_fd == -1) {
- int fd, family;
- len_and_sockaddr *local_lsa;
-
- family = p->p_lsa->u.sa.sa_family;
- p->p_fd = fd = xsocket_type(&local_lsa, family, SOCK_DGRAM);
- /* local_lsa has "null" address and port 0 now.
- * bind() ensures we have a *particular port* selected by kernel
- * and remembered in p->p_fd, thus later recv(p->p_fd)
- * receives only packets sent to this port.
- */
- PROBE_LOCAL_ADDR
- xbind(fd, &local_lsa->u.sa, local_lsa->len);
- PROBE_LOCAL_ADDR
-#if ENABLE_FEATURE_IPV6
- if (family == AF_INET)
-#endif
- setsockopt(fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY));
- free(local_lsa);
- }
-
- /*
- * Send out a random 64-bit number as our transmit time. The NTP
- * server will copy said number into the originate field on the
- * response that it sends us. This is totally legal per the SNTP spec.
- *
- * The impact of this is two fold: we no longer send out the current
- * system time for the world to see (which may aid an attacker), and
- * it gives us a (not very secure) way of knowing that we're not
- * getting spoofed by an attacker that can't capture our traffic
- * but can spoof packets from the NTP server we're communicating with.
- *
- * Save the real transmit timestamp locally.
- */
- p->p_xmt_msg.m_xmttime.int_partl = random();
- p->p_xmt_msg.m_xmttime.fractionl = random();
- p->p_xmttime = gettime1900d();
-
- if (do_sendto(p->p_fd, /*from:*/ NULL, /*to:*/ &p->p_lsa->u.sa, /*addrlen:*/ p->p_lsa->len,
- &p->p_xmt_msg, NTP_MSGSIZE_NOAUTH) == -1
- ) {
- close(p->p_fd);
- p->p_fd = -1;
- set_next(p, INTERVAL_QUERY_PATHETIC);
- return -1;
- }
-
- if (G.verbose)
- bb_error_msg("sent query to %s", p->p_dotted);
- set_next(p, QUERYTIME_MAX);
-
- return 0;
-}
-
-
-/* Time is stepped only once, when the first packet from a peer is received.
- */
-static void
-step_time_once(double offset)
-{
- double dtime;
- llist_t *item;
- struct timeval tv;
- char buf[80];
- time_t tval;
-
- if (G.time_was_stepped)
- goto bail;
- G.time_was_stepped = 1;
-
- /* if the offset is small, don't step, slew (later) */
- if (offset < STEPTIME_MIN_OFFSET && offset > -STEPTIME_MIN_OFFSET)
- goto bail;
-
- gettimeofday(&tv, NULL); /* never fails */
- dtime = offset + tv.tv_sec;
- dtime += 1.0e-6 * tv.tv_usec;
- d_to_tv(dtime, &tv);
-
- if (settimeofday(&tv, NULL) == -1)
- bb_perror_msg_and_die("settimeofday");
-
- tval = tv.tv_sec;
- strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y", localtime(&tval));
-
- bb_error_msg("setting clock to %s (offset %fs)", buf, offset);
-
- for (item = G.ntp_peers; item != NULL; item = item->link) {
- peer_t *p = (peer_t *) item->data;
- p->next_action_time -= (time_t)offset;
- }
-
- bail:
- if (option_mask32 & OPT_q)
- exit(0);
-}
-
-
-/* Time is periodically slewed when we collect enough
- * good data points.
- */
-static int
-compare_offsets(const void *aa, const void *bb)
-{
- const peer_t *const *a = aa;
- const peer_t *const *b = bb;
- if ((*a)->update.d_offset < (*b)->update.d_offset)
- return -1;
- return ((*a)->update.d_offset > (*b)->update.d_offset);
-}
-static unsigned
-updated_scale(double offset)
-{
- if (offset < 0)
- offset = -offset;
- if (offset > QSCALE_OFF_MAX)
- return 1;
- if (offset < QSCALE_OFF_MIN)
- return QSCALE_OFF_MAX / QSCALE_OFF_MIN;
- return QSCALE_OFF_MAX / offset;
-}
-static void
-slew_time(void)
-{
- llist_t *item;
- double offset_median;
- struct timeval tv;
-
- {
- peer_t **peers = xzalloc(sizeof(peers[0]) * G.peer_cnt);
- unsigned goodpeer_cnt = 0;
- unsigned middle;
-
- for (item = G.ntp_peers; item != NULL; item = item->link) {
- peer_t *p = (peer_t *) item->data;
- if (p->p_trustlevel < TRUSTLEVEL_BADPEER)
- continue;
- if (!p->update.d_good) {
- free(peers);
- return;
- }
- peers[goodpeer_cnt++] = p;
- }
-
- if (goodpeer_cnt == 0) {
- free(peers);
- goto clear_good;
- }
-
- qsort(peers, goodpeer_cnt, sizeof(peers[0]), compare_offsets);
-
- middle = goodpeer_cnt / 2;
- if (middle != 0 && (goodpeer_cnt & 1) == 0) {
- offset_median = (peers[middle-1]->update.d_offset + peers[middle]->update.d_offset) / 2;
- G.rootdelay = (peers[middle-1]->update.d_delay + peers[middle]->update.d_delay) / 2;
- G.stratum = 1 + MAX(peers[middle-1]->update.d_stratum, peers[middle]->update.d_stratum);
- } else {
- offset_median = peers[middle]->update.d_offset;
- G.rootdelay = peers[middle]->update.d_delay;
- G.stratum = 1 + peers[middle]->update.d_stratum;
- }
- G.leap = peers[middle]->update.d_leap;
- G.refid4 = peers[middle]->update.d_refid4;
- G.refid =
-#if ENABLE_FEATURE_IPV6
- peers[middle]->p_lsa->u.sa.sa_family != AF_INET ?
- G.refid4 :
-#endif
- peers[middle]->p_lsa->u.sin.sin_addr.s_addr;
- free(peers);
- }
-//TODO: if (offset_median > BIG) step_time(offset_median)?
-
- G.scale = updated_scale(offset_median);
-
- bb_error_msg("adjusting clock by %fs, our stratum is %u, time scale %u",
- offset_median, G.stratum, G.scale);
-
- errno = 0;
- d_to_tv(offset_median, &tv);
- if (adjtime(&tv, &tv) == -1)
- bb_perror_msg_and_die("adjtime failed");
- if (G.verbose >= 2)
- bb_error_msg("old adjust: %d.%06u", (int)tv.tv_sec, (unsigned)tv.tv_usec);
-
- if (G.first_adj_done) {
- uint8_t synced = (tv.tv_sec == 0 && tv.tv_usec == 0);
- if (synced != G.synced) {
- G.synced = synced;
- bb_error_msg("clock is %ssynced", synced ? "" : "un");
- }
- }
- G.first_adj_done = 1;
-
- G.reftime = gettime1900d();
-
- clear_good:
- for (item = G.ntp_peers; item != NULL; item = item->link) {
- peer_t *p = (peer_t *) item->data;
- p->update.d_good = 0;
- }
-}
-
-static void
-update_peer_data(peer_t *p)
-{
- /* Clock filter.
- * Find the datapoint with the lowest delay.
- * Use that as the peer update.
- * Invalidate it and all older ones.
- */
- int i;
- int best = -1;
- int good = 0;
-
- for (i = 0; i < NUM_DATAPOINTS; i++) {
- if (p->p_datapoint[i].d_good) {
- good++;
- if (best < 0 || p->p_datapoint[i].d_delay < p->p_datapoint[best].d_delay)
- best = i;
- }
- }
-
- if (good < 8) //FIXME: was it meant to be NUM_DATAPOINTS, not 8?
- return;
-
- p->update = p->p_datapoint[best]; /* struct copy */
- slew_time();
-
- for (i = 0; i < NUM_DATAPOINTS; i++)
- if (p->p_datapoint[i].d_rcv_time <= p->p_datapoint[best].d_rcv_time)
- p->p_datapoint[i].d_good = 0;
-}
-
-static unsigned
-scale_interval(unsigned requested)
-{
- unsigned interval, r;
- interval = requested * G.scale;
- r = (unsigned)random() % (unsigned)(MAX(5, interval / 10));
- return (interval + r);
-}
-static void
-recv_and_process_peer_pkt(peer_t *p)
-{
- ssize_t size;
- msg_t msg;
- double T1, T2, T3, T4;
- unsigned interval;
- datapoint_t *datapoint;
-
- /* We can recvfrom here and check from.IP, but some multihomed
- * ntp servers reply from their *other IP*.
- * TODO: maybe we should check at least what we can: from.port == 123?
- */
- size = recv(p->p_fd, &msg, sizeof(msg), MSG_DONTWAIT);
- if (size == -1) {
- bb_perror_msg("recv(%s) error", p->p_dotted);
- if (errno == EHOSTUNREACH || errno == EHOSTDOWN
- || errno == ENETUNREACH || errno == ENETDOWN
- || errno == ECONNREFUSED || errno == EADDRNOTAVAIL
- || errno == EAGAIN
- ) {
-//TODO: always do this?
- set_next(p, error_interval());
- goto close_sock;
- }
- xfunc_die();
- }
-
- if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) {
- bb_error_msg("malformed packet received from %s", p->p_dotted);
- goto bail;
- }
-
- if (msg.m_orgtime.int_partl != p->p_xmt_msg.m_xmttime.int_partl
- || msg.m_orgtime.fractionl != p->p_xmt_msg.m_xmttime.fractionl
- ) {
- goto bail;
- }
-
- if ((msg.m_status & LI_ALARM) == LI_ALARM
- || msg.m_stratum == 0
- || msg.m_stratum > NTP_MAXSTRATUM
- ) {
-// TODO: stratum 0 responses may have commands in 32-bit m_refid field:
-// "DENY", "RSTR" - peer does not like us at all
-// "RATE" - peer is overloaded, reduce polling freq
- interval = error_interval();
- bb_error_msg("reply from %s: not synced, next query in %us", p->p_dotted, interval);
- goto close_sock;
- }
-
- /*
- * From RFC 2030 (with a correction to the delay math):
- *
- * Timestamp Name ID When Generated
- * ------------------------------------------------------------
- * Originate Timestamp T1 time request sent by client
- * Receive Timestamp T2 time request received by server
- * Transmit Timestamp T3 time reply sent by server
- * Destination Timestamp T4 time reply received by client
- *
- * The roundtrip delay and local clock offset are defined as
- *
- * delay = (T4 - T1) - (T3 - T2); offset = ((T2 - T1) + (T3 - T4)) / 2
- */
- T1 = p->p_xmttime;
- T2 = lfp_to_d(msg.m_rectime);
- T3 = lfp_to_d(msg.m_xmttime);
- T4 = gettime1900d();
-
- datapoint = &p->p_datapoint[p->p_datapoint_idx];
-
- datapoint->d_offset = ((T2 - T1) + (T3 - T4)) / 2;
- datapoint->d_delay = (T4 - T1) - (T3 - T2);
- if (datapoint->d_delay < 0) {
- bb_error_msg("reply from %s: negative delay %f", p->p_dotted, datapoint->d_delay);
- interval = error_interval();
- set_next(p, interval);
- goto close_sock;
- }
- //UNUSED: datapoint->d_error = (T2 - T1) - (T3 - T4);
- datapoint->d_rcv_time = (time_t)(T4 - OFFSET_1900_1970); /* = time(NULL); */
- datapoint->d_good = 1;
-
- datapoint->d_leap = (msg.m_status & LI_MASK);
- //UNUSED: datapoint->o_precision = msg.m_precision_exp;
- //UNUSED: datapoint->o_rootdelay = sfp_to_d(msg.m_rootdelay);
- //UNUSED: datapoint->o_rootdispersion = sfp_to_d(msg.m_dispersion);
- //UNUSED: datapoint->d_refid = ntohl(msg.m_refid);
- datapoint->d_refid4 = msg.m_xmttime.fractionl;
- //UNUSED: datapoint->o_reftime = lfp_to_d(msg.m_reftime);
- //UNUSED: datapoint->o_poll = msg.m_ppoll;
- datapoint->d_stratum = msg.m_stratum;
-
- if (p->p_trustlevel < TRUSTLEVEL_PATHETIC)
- interval = scale_interval(INTERVAL_QUERY_PATHETIC);
- else if (p->p_trustlevel < TRUSTLEVEL_AGRESSIVE)
- interval = scale_interval(INTERVAL_QUERY_AGRESSIVE);
- else
- interval = scale_interval(INTERVAL_QUERY_NORMAL);
-
- set_next(p, interval);
-
- /* Every received reply which we do not discard increases trust */
- if (p->p_trustlevel < TRUSTLEVEL_MAX) {
- p->p_trustlevel++;
- if (p->p_trustlevel == TRUSTLEVEL_BADPEER)
- bb_error_msg("peer %s now valid", p->p_dotted);
- }
-
- if (G.verbose)
- bb_error_msg("reply from %s: offset %f delay %f, next query in %us", p->p_dotted,
- datapoint->d_offset, datapoint->d_delay, interval);
-
- update_peer_data(p);
-//TODO: do it after all peers had a chance to return at least one reply?
- step_time_once(datapoint->d_offset);
-
- p->p_datapoint_idx++;
- if (p->p_datapoint_idx >= NUM_DATAPOINTS)
- p->p_datapoint_idx = 0;
-
- close_sock:
- /* We do not expect any more packets from this peer for now.
- * Closing the socket informs kernel about it.
- * We open a new socket when we send a new query.
- */
- close(p->p_fd);
- p->p_fd = -1;
- bail:
- return;
-}
-
-#if ENABLE_FEATURE_NTPD_SERVER
-static void
-recv_and_process_client_pkt(void /*int fd*/)
-{
- ssize_t size;
- uint8_t version;
- double rectime;
- len_and_sockaddr *to;
- struct sockaddr *from;
- msg_t msg;
- uint8_t query_status;
- uint8_t query_ppoll;
- l_fixedpt_t query_xmttime;
-
- to = get_sock_lsa(G.listen_fd);
- from = xzalloc(to->len);
-
- size = recv_from_to(G.listen_fd, &msg, sizeof(msg), MSG_DONTWAIT, from, &to->u.sa, to->len);
- if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) {
- char *addr;
- if (size < 0) {
- if (errno == EAGAIN)
- goto bail;
- bb_perror_msg_and_die("recv");
- }
- addr = xmalloc_sockaddr2dotted_noport(from);
- bb_error_msg("malformed packet received from %s: size %u", addr, (int)size);
- free(addr);
- goto bail;
- }
-
- query_status = msg.m_status;
- query_ppoll = msg.m_ppoll;
- query_xmttime = msg.m_xmttime;
-
- /* Build a reply packet */
- memset(&msg, 0, sizeof(msg));
- msg.m_status = G.synced ? G.leap : LI_ALARM;
- msg.m_status |= (query_status & VERSION_MASK);
- msg.m_status |= ((query_status & MODE_MASK) == MODE_CLIENT) ?
- MODE_SERVER : MODE_SYM_PAS;
- msg.m_stratum = G.stratum;
- msg.m_ppoll = query_ppoll;
- msg.m_precision_exp = G_precision_exp;
- rectime = gettime1900d();
- msg.m_xmttime = msg.m_rectime = d_to_lfp(rectime);
- msg.m_reftime = d_to_lfp(G.reftime);
- //msg.m_xmttime = d_to_lfp(gettime1900d()); // = msg.m_rectime
- msg.m_orgtime = query_xmttime;
- msg.m_rootdelay = d_to_sfp(G.rootdelay);
- version = (query_status & VERSION_MASK); /* ... >> VERSION_SHIFT - done below instead */
- msg.m_refid = (version > (3 << VERSION_SHIFT)) ? G.refid4 : G.refid;
-
- /* We reply from the local address packet was sent to,
- * this makes to/from look swapped here: */
- do_sendto(G.listen_fd,
- /*from:*/ &to->u.sa, /*to:*/ from, /*addrlen:*/ to->len,
- &msg, size);
-
- bail:
- free(to);
- free(from);
-}
-#endif
-
-/* Upstream ntpd's options:
- *
- * -4 Force DNS resolution of host names to the IPv4 namespace.
- * -6 Force DNS resolution of host names to the IPv6 namespace.
- * -a Require cryptographic authentication for broadcast client,
- * multicast client and symmetric passive associations.
- * This is the default.
- * -A Do not require cryptographic authentication for broadcast client,
- * multicast client and symmetric passive associations.
- * This is almost never a good idea.
- * -b Enable the client to synchronize to broadcast servers.
- * -c conffile
- * Specify the name and path of the configuration file,
- * default /etc/ntp.conf
- * -d Specify debugging mode. This option may occur more than once,
- * with each occurrence indicating greater detail of display.
- * -D level
- * Specify debugging level directly.
- * -f driftfile
- * Specify the name and path of the frequency file.
- * This is the same operation as the "driftfile FILE"
- * configuration command.
- * -g Normally, ntpd exits with a message to the system log
- * if the offset exceeds the panic threshold, which is 1000 s
- * by default. This option allows the time to be set to any value
- * without restriction; however, this can happen only once.
- * If the threshold is exceeded after that, ntpd will exit
- * with a message to the system log. This option can be used
- * with the -q and -x options. See the tinker command for other options.
- * -i jaildir
- * Chroot the server to the directory jaildir. This option also implies
- * that the server attempts to drop root privileges at startup
- * (otherwise, chroot gives very little additional security).
- * You may need to also specify a -u option.
- * -k keyfile
- * Specify the name and path of the symmetric key file,
- * default /etc/ntp/keys. This is the same operation
- * as the "keys FILE" configuration command.
- * -l logfile
- * Specify the name and path of the log file. The default
- * is the system log file. This is the same operation as
- * the "logfile FILE" configuration command.
- * -L Do not listen to virtual IPs. The default is to listen.
- * -n Don't fork.
- * -N To the extent permitted by the operating system,
- * run the ntpd at the highest priority.
- * -p pidfile
- * Specify the name and path of the file used to record the ntpd
- * process ID. This is the same operation as the "pidfile FILE"
- * configuration command.
- * -P priority
- * To the extent permitted by the operating system,
- * run the ntpd at the specified priority.
- * -q Exit the ntpd just after the first time the clock is set.
- * This behavior mimics that of the ntpdate program, which is
- * to be retired. The -g and -x options can be used with this option.
- * Note: The kernel time discipline is disabled with this option.
- * -r broadcastdelay
- * Specify the default propagation delay from the broadcast/multicast
- * server to this client. This is necessary only if the delay
- * cannot be computed automatically by the protocol.
- * -s statsdir
- * Specify the directory path for files created by the statistics
- * facility. This is the same operation as the "statsdir DIR"
- * configuration command.
- * -t key
- * Add a key number to the trusted key list. This option can occur
- * more than once.
- * -u user[:group]
- * Specify a user, and optionally a group, to switch to.
- * -v variable
- * -V variable
- * Add a system variable listed by default.
- * -x Normally, the time is slewed if the offset is less than the step
- * threshold, which is 128 ms by default, and stepped if above
- * the threshold. This option sets the threshold to 600 s, which is
- * well within the accuracy window to set the clock manually.
- * Note: since the slew rate of typical Unix kernels is limited
- * to 0.5 ms/s, each second of adjustment requires an amortization
- * interval of 2000 s. Thus, an adjustment as much as 600 s
- * will take almost 14 days to complete. This option can be used
- * with the -g and -q options. See the tinker command for other options.
- * Note: The kernel time discipline is disabled with this option.
- */
-
-/* By doing init in a separate function we decrease stack usage
- * in main loop.
- */
-static NOINLINE void ntp_init(char **argv)
-{
- unsigned opts;
- llist_t *peers;
-
- srandom(getpid());
-
- if (getuid())
- bb_error_msg_and_die(bb_msg_you_must_be_root);
-
- peers = NULL;
- opt_complementary = "dd:p::"; /* d: counter, p: list */
- opts = getopt32(argv,
- "nqNx" /* compat */
- "p:"IF_FEATURE_NTPD_SERVER("l") /* NOT compat */
- "d" /* compat */
- "46aAbgL", /* compat, ignored */
- &peers, &G.verbose);
- if (!(opts & (OPT_p|OPT_l)))
- bb_show_usage();
- if (opts & OPT_x) /* disable stepping, only slew is allowed */
- G.time_was_stepped = 1;
- while (peers)
- add_peers(llist_pop(&peers));
- if (!(opts & OPT_n)) {
- bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv);
- logmode = LOGMODE_NONE;
- }
-#if ENABLE_FEATURE_NTPD_SERVER
- G.listen_fd = -1;
- if (opts & OPT_l) {
- G.listen_fd = create_and_bind_dgram_or_die(NULL, 123);
- socket_want_pktinfo(G.listen_fd);
- setsockopt(G.listen_fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY));
- }
-#endif
- /* I hesitate to set -20 prio. -15 should be high enough for timekeeping */
- if (opts & OPT_N)
- setpriority(PRIO_PROCESS, 0, -15);
-
- /* Set some globals */
-#if 0
- /* With constant b = 100, G.precision_exp is also constant -6.
- * Uncomment this and you'll see */
- {
- int prec = 0;
- int b;
-# if 0
- struct timespec tp;
- /* We can use sys_clock_getres but assuming 10ms tick should be fine */
- clock_getres(CLOCK_REALTIME, &tp);
- tp.tv_sec = 0;
- tp.tv_nsec = 10000000;
- b = 1000000000 / tp.tv_nsec; /* convert to Hz */
-# else
- b = 100; /* b = 1000000000/10000000 = 100 */
-# endif
- while (b > 1)
- prec--, b >>= 1;
- //G.precision_exp = prec;
- bb_error_msg("G.precision_exp:%d", prec); /* -6 */
- }
-#endif
- G.scale = 1;
-
- bb_signals((1 << SIGTERM) | (1 << SIGINT), record_signo);
- bb_signals((1 << SIGPIPE) | (1 << SIGHUP), SIG_IGN);
-}
-
-int ntpd_main(int argc UNUSED_PARAM, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int ntpd_main(int argc UNUSED_PARAM, char **argv)
-{
- struct globals g;
- struct pollfd *pfd;
- peer_t **idx2peer;
-
- memset(&g, 0, sizeof(g));
- SET_PTR_TO_GLOBALS(&g);
-
- ntp_init(argv);
-
- {
- /* if ENABLE_FEATURE_NTPD_SERVER, + 1 for listen_fd: */
- unsigned cnt = g.peer_cnt + ENABLE_FEATURE_NTPD_SERVER;
- idx2peer = xzalloc(sizeof(idx2peer[0]) * cnt);
- pfd = xzalloc(sizeof(pfd[0]) * cnt);
- }
-
- while (!bb_got_signal) {
- llist_t *item;
- unsigned i, j;
- unsigned sent_cnt, trial_cnt;
- int nfds, timeout;
- time_t cur_time, nextaction;
-
- /* Nothing between here and poll() blocks for any significant time */
-
- cur_time = time(NULL);
- nextaction = cur_time + 3600;
-
- i = 0;
-#if ENABLE_FEATURE_NTPD_SERVER
- if (g.listen_fd != -1) {
- pfd[0].fd = g.listen_fd;
- pfd[0].events = POLLIN;
- i++;
- }
-#endif
- /* Pass over peer list, send requests, time out on receives */
- sent_cnt = trial_cnt = 0;
- for (item = g.ntp_peers; item != NULL; item = item->link) {
- peer_t *p = (peer_t *) item->data;
-
- /* Overflow-safe "if (p->next_action_time <= cur_time) ..." */
- if ((int)(cur_time - p->next_action_time) >= 0) {
- if (p->p_fd == -1) {
- /* Time to send new req */
- trial_cnt++;
- if (send_query_to_peer(p) == 0)
- sent_cnt++;
- } else {
- /* Timed out waiting for reply */
- close(p->p_fd);
- p->p_fd = -1;
- timeout = error_interval();
- bb_error_msg("timed out waiting for %s, "
- "next query in %us", p->p_dotted, timeout);
- if (p->p_trustlevel >= TRUSTLEVEL_BADPEER) {
- p->p_trustlevel /= 2;
- if (p->p_trustlevel < TRUSTLEVEL_BADPEER)
- bb_error_msg("peer %s now invalid", p->p_dotted);
- }
- set_next(p, timeout);
- }
- }
-
- if (p->next_action_time < nextaction)
- nextaction = p->next_action_time;
-
- if (p->p_fd >= 0) {
- /* Wait for reply from this peer */
- pfd[i].fd = p->p_fd;
- pfd[i].events = POLLIN;
- idx2peer[i] = p;
- i++;
- }
- }
-
- if ((trial_cnt > 0 && sent_cnt == 0) || g.peer_cnt == 0)
- step_time_once(0); /* no good peers, don't wait */
-
- timeout = nextaction - cur_time;
- if (timeout < 1)
- timeout = 1;
-
- /* Here we may block */
- if (g.verbose >= 2)
- bb_error_msg("poll %us, sockets:%u", timeout, i);
- nfds = poll(pfd, i, timeout * 1000);
- if (nfds <= 0)
- continue;
-
- /* Process any received packets */
- j = 0;
-#if ENABLE_FEATURE_NTPD_SERVER
- if (g.listen_fd != -1) {
- if (pfd[0].revents /* & (POLLIN|POLLERR)*/) {
- nfds--;
- recv_and_process_client_pkt(/*g.listen_fd*/);
- }
- j = 1;
- }
-#endif
- for (; nfds != 0 && j < i; j++) {
- if (pfd[j].revents /* & (POLLIN|POLLERR)*/) {
- nfds--;
- recv_and_process_peer_pkt(idx2peer[j]);
- }
- }
- } /* while (!bb_got_signal) */
-
- kill_myself_with_sig(bb_got_signal);
-}
diff --git a/release/src/router/busybox/networking/ping.c b/release/src/router/busybox/networking/ping.c
index b8bf2de312..6f107f4cbf 100644
--- a/release/src/router/busybox/networking/ping.c
+++ b/release/src/router/busybox/networking/ping.c
@@ -28,6 +28,7 @@
#include <net/if.h>
#include <netinet/ip_icmp.h>
#include "libbb.h"
+#include "common_bufsiz.h"
#ifdef __BIONIC__
/* should be in netinet/ip_icmp.h */
@@ -89,7 +90,9 @@
//usage: "[OPTIONS] HOST"
//usage:# define ping_full_usage "\n\n"
//usage: "Send ICMP ECHO_REQUEST packets to network hosts\n"
+//usage: IF_PING6(
//usage: "\n -4,-6 Force IP or IPv6 name resolution"
+//usage: )
//usage: "\n -c CNT Send only CNT pings"
//usage: "\n -s SIZE Send SIZE data bytes in packets (default:56)"
//usage: "\n -t TTL Set TTL"
@@ -99,8 +102,9 @@
//usage: "\n (after all -c CNT packets are sent)"
//usage: "\n -w SEC Seconds until ping exits (default:infinite)"
//usage: "\n (can exit earlier with -c CNT)"
-//usage: "\n -q Quiet, only displays output at start"
+//usage: "\n -q Quiet, only display output at start"
//usage: "\n and when finished"
+//usage: "\n -p Pattern to use for payload"
//usage:
//usage:# define ping6_trivial_usage
//usage: "[OPTIONS] HOST"
@@ -108,11 +112,12 @@
//usage: "Send ICMP ECHO_REQUEST packets to network hosts\n"
//usage: "\n -c CNT Send only CNT pings"
//usage: "\n -s SIZE Send SIZE data bytes in packets (default:56)"
-//usage: "\n -t TTL Set TTL"
+//usage: "\n -t HL Set Hop Limit"
//usage: "\n -I IFACE/IP Use interface or IP address as source"
//usage: "\n -M hint Path MTU Discovery strategy [do|want|dont]"
-//usage: "\n -q Quiet, only displays output at start"
+//usage: "\n -q Quiet, only display output at start"
//usage: "\n and when finished"
+//usage: "\n -p Pattern to use for payload"
//usage:
//usage:#endif
//usage:
@@ -155,8 +160,33 @@ enum {
MAX_DUP_CHK = (8 * 128),
MAXWAIT = 10,
PINGINTERVAL = 1, /* 1 second */
+ pingsock = 0,
};
+static void
+#if ENABLE_PING6
+create_icmp_socket(len_and_sockaddr *lsa)
+#else
+create_icmp_socket(void)
+#define create_icmp_socket(lsa) create_icmp_socket()
+#endif
+{
+ int sock;
+#if ENABLE_PING6
+ if (lsa->u.sa.sa_family == AF_INET6)
+ sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+ else
+#endif
+ sock = socket(AF_INET, SOCK_RAW, 1); /* 1 == ICMP */
+ if (sock < 0) {
+ if (errno == EPERM)
+ bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
+ bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket);
+ }
+
+ xmove_fd(sock, pingsock);
+}
+
#if !ENABLE_FEATURE_FANCY_PING
/* Simple version */
@@ -165,8 +195,8 @@ struct globals {
char *hostname;
char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
-#define INIT_G() do { } while (0)
+#define G (*(struct globals*)bb_common_bufsiz1)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
static void noresp(int ign UNUSED_PARAM)
{
@@ -177,12 +207,10 @@ static void noresp(int ign UNUSED_PARAM)
static void ping4(len_and_sockaddr *lsa)
{
struct icmp *pkt;
- int pingsock, c;
-
- pingsock = create_icmp_socket();
+ int c;
pkt = (struct icmp *) G.packet;
- memset(pkt, 0, sizeof(G.packet));
+ /*memset(pkt, 0, sizeof(G.packet)); already is */
pkt->icmp_type = ICMP_ECHO;
pkt->icmp_cksum = inet_cksum((uint16_t *) pkt, sizeof(G.packet));
@@ -190,11 +218,15 @@ static void ping4(len_and_sockaddr *lsa)
/* listen for replies */
while (1) {
+#if 0
struct sockaddr_in from;
socklen_t fromlen = sizeof(from);
c = recvfrom(pingsock, G.packet, sizeof(G.packet), 0,
(struct sockaddr *) &from, &fromlen);
+#else
+ c = recv(pingsock, G.packet, sizeof(G.packet), 0);
+#endif
if (c < 0) {
if (errno != EINTR)
bb_perror_msg("recvfrom");
@@ -216,34 +248,35 @@ static void ping4(len_and_sockaddr *lsa)
static void ping6(len_and_sockaddr *lsa)
{
struct icmp6_hdr *pkt;
- int pingsock, c;
+ int c;
int sockopt;
- pingsock = create_icmp6_socket();
-
pkt = (struct icmp6_hdr *) G.packet;
- memset(pkt, 0, sizeof(G.packet));
+ /*memset(pkt, 0, sizeof(G.packet)); already is */
pkt->icmp6_type = ICMP6_ECHO_REQUEST;
sockopt = offsetof(struct icmp6_hdr, icmp6_cksum);
- setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM, &sockopt, sizeof(sockopt));
+ setsockopt_int(pingsock, SOL_RAW, IPV6_CHECKSUM, sockopt);
xsendto(pingsock, G.packet, DEFDATALEN + sizeof(struct icmp6_hdr), &lsa->u.sa, lsa->len);
/* listen for replies */
while (1) {
+#if 0
struct sockaddr_in6 from;
socklen_t fromlen = sizeof(from);
c = recvfrom(pingsock, G.packet, sizeof(G.packet), 0,
(struct sockaddr *) &from, &fromlen);
+#else
+ c = recv(pingsock, G.packet, sizeof(G.packet), 0);
+#endif
if (c < 0) {
if (errno != EINTR)
bb_perror_msg("recvfrom");
continue;
}
- if (c >= ICMP_MINLEN) { /* icmp6_hdr */
- pkt = (struct icmp6_hdr *) G.packet;
+ if (c >= ICMP_MINLEN) { /* icmp6_hdr */
if (pkt->icmp6_type == ICMP6_ECHO_REPLY)
break;
}
@@ -291,6 +324,7 @@ static int common_ping_main(sa_family_t af, char **argv)
signal(SIGALRM, noresp);
alarm(5); /* give the host 5000ms to respond */
+ create_icmp_socket(lsa);
#if ENABLE_PING6
if (lsa->u.sa.sa_family == AF_INET6)
ping6(lsa);
@@ -307,33 +341,35 @@ static int common_ping_main(sa_family_t af, char **argv)
/* Full(er) version */
-#define OPT_STRING ("qvc:s:t:w:W:I:M:4" IF_PING6("6"))
+#define OPT_STRING ("qvc:s:t:w:W:I:np:M:4" IF_PING6("6"))
enum {
- OPT_QUIET = 1 << 0,
- OPT_VERBOSE = 1 << 1,
+ OPT_QUIET = 1 << 0,
+ OPT_VERBOSE = 1 << 1,
OPT_c = 1 << 2,
OPT_s = 1 << 3,
OPT_t = 1 << 4,
OPT_w = 1 << 5,
OPT_W = 1 << 6,
OPT_I = 1 << 7,
- OPT_M = 1 << 8,
- OPT_IPV4 = 1 << 9,
- OPT_IPV6 = (1 << 10) * ENABLE_PING6,
+ /*OPT_n = 1 << 8, - ignored */
+ OPT_p = 1 << 9,
+ OPT_M = 1 << 10,
+ OPT_IPV4 = 1 << 11,
+ OPT_IPV6 = (1 << 12) * ENABLE_PING6,
};
struct globals {
- int pingsock;
int if_index;
char *str_I;
len_and_sockaddr *source_lsa;
unsigned datalen;
unsigned pingcount; /* must be int-sized */
unsigned opt_ttl;
- int pmtudisc;
unsigned long ntransmitted, nreceived, nrepeats;
uint16_t myid;
+ uint8_t pattern;
+ int pmtudisc;
unsigned tmin, tmax; /* in us */
unsigned long long tsum; /* in us, sum of all times */
unsigned deadline;
@@ -351,21 +387,17 @@ struct globals {
struct sockaddr_in6 sin6;
#endif
} pingaddr;
- char rcvd_tbl[MAX_DUP_CHK / 8];
+ unsigned char rcvd_tbl[MAX_DUP_CHK / 8];
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
-#define pingsock (G.pingsock )
+#define G (*(struct globals*)bb_common_bufsiz1)
#define if_index (G.if_index )
#define source_lsa (G.source_lsa )
#define str_I (G.str_I )
#define datalen (G.datalen )
-#define ntransmitted (G.ntransmitted)
-#define nreceived (G.nreceived )
-#define nrepeats (G.nrepeats )
#define pingcount (G.pingcount )
#define opt_ttl (G.opt_ttl )
-#define pmtudisc (G.pmtudisc )
#define myid (G.myid )
+#define pmtudisc (G.pmtudisc )
#define tmin (G.tmin )
#define tmax (G.tmax )
#define tsum (G.tsum )
@@ -376,56 +408,59 @@ struct globals {
#define dotted (G.dotted )
#define pingaddr (G.pingaddr )
#define rcvd_tbl (G.rcvd_tbl )
-void BUG_ping_globals_too_big(void);
#define INIT_G() do { \
- if (sizeof(G) > COMMON_BUFSIZE) \
- BUG_ping_globals_too_big(); \
- pingsock = -1; \
+ setup_common_bufsiz(); \
+ BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
+ pmtudisc = -1; \
datalen = DEFDATALEN; \
timeout = MAXWAIT; \
tmin = UINT_MAX; \
- pmtudisc = -1; \
} while (0)
-#define A(bit) rcvd_tbl[(bit)>>3] /* identify byte in array */
-#define B(bit) (1 << ((bit) & 0x07)) /* identify bit in byte */
-#define SET(bit) (A(bit) |= B(bit))
-#define CLR(bit) (A(bit) &= (~B(bit)))
-#define TST(bit) (A(bit) & B(bit))
-
-/**************************************************************************/
+#define BYTE(bit) rcvd_tbl[(bit)>>3]
+#define MASK(bit) (1 << ((bit) & 7))
+#define SET(bit) (BYTE(bit) |= MASK(bit))
+#define CLR(bit) (BYTE(bit) &= (~MASK(bit)))
+#define TST(bit) (BYTE(bit) & MASK(bit))
static void print_stats_and_exit(int junk) NORETURN;
static void print_stats_and_exit(int junk UNUSED_PARAM)
{
+ unsigned long ul;
+ unsigned long nrecv;
+
signal(SIGINT, SIG_IGN);
- printf("\n--- %s ping statistics ---\n", hostname);
- printf("%lu packets transmitted, ", ntransmitted);
- printf("%lu packets received, ", nreceived);
- if (nrepeats)
- printf("%lu duplicates, ", nrepeats);
- if (ntransmitted)
- ntransmitted = (ntransmitted - nreceived) * 100 / ntransmitted;
- printf("%lu%% packet loss\n", ntransmitted);
+ nrecv = G.nreceived;
+ printf("\n--- %s ping statistics ---\n"
+ "%lu packets transmitted, "
+ "%lu packets received, ",
+ hostname, G.ntransmitted, nrecv
+ );
+ if (G.nrepeats)
+ printf("%lu duplicates, ", G.nrepeats);
+ ul = G.ntransmitted;
+ if (ul != 0)
+ ul = (ul - nrecv) * 100 / ul;
+ printf("%lu%% packet loss\n", ul);
if (tmin != UINT_MAX) {
- unsigned tavg = tsum / (nreceived + nrepeats);
+ unsigned tavg = tsum / (nrecv + G.nrepeats);
printf("round-trip min/avg/max = %u.%03u/%u.%03u/%u.%03u ms\n",
tmin / 1000, tmin % 1000,
tavg / 1000, tavg % 1000,
tmax / 1000, tmax % 1000);
}
/* if condition is true, exit with 1 -- 'failure' */
- exit(nreceived == 0 || (deadline && nreceived < pingcount));
+ exit(nrecv == 0 || (deadline && nrecv < pingcount));
}
static void sendping_tail(void (*sp)(int), int size_pkt)
{
int sz;
- CLR((uint16_t)ntransmitted % MAX_DUP_CHK);
- ntransmitted++;
+ CLR((uint16_t)G.ntransmitted % MAX_DUP_CHK);
+ G.ntransmitted++;
size_pkt += datalen;
@@ -435,7 +470,7 @@ static void sendping_tail(void (*sp)(int), int size_pkt)
if (sz != size_pkt)
bb_error_msg_and_die(bb_msg_write_error);
- if (pingcount == 0 || deadline || ntransmitted < pingcount) {
+ if (pingcount == 0 || deadline || G.ntransmitted < pingcount) {
/* Didn't send all pings yet - schedule next in 1s */
signal(SIGALRM, sp);
if (deadline) {
@@ -451,7 +486,7 @@ static void sendping_tail(void (*sp)(int), int size_pkt)
* otherwise ping waits for two RTTs. */
unsigned expire = timeout;
- if (nreceived) {
+ if (G.nreceived) {
/* approx. 2*tmax, in seconds (2 RTT) */
expire = tmax / (512*1024);
if (expire == 0)
@@ -466,11 +501,11 @@ static void sendping4(int junk UNUSED_PARAM)
{
struct icmp *pkt = G.snd_packet;
- //memset(pkt, 0, datalen + ICMP_MINLEN + 4); - G.snd_packet was xzalloced
+ memset(pkt, G.pattern, datalen + ICMP_MINLEN + 4);
pkt->icmp_type = ICMP_ECHO;
/*pkt->icmp_code = 0;*/
pkt->icmp_cksum = 0; /* cksum is calculated with this field set to 0 */
- pkt->icmp_seq = htons(ntransmitted); /* don't ++ here, it can be a macro */
+ pkt->icmp_seq = htons(G.ntransmitted); /* don't ++ here, it can be a macro */
pkt->icmp_id = myid;
/* If datalen < 4, we store timestamp _past_ the packet,
@@ -489,15 +524,15 @@ static void sendping6(int junk UNUSED_PARAM)
{
struct icmp6_hdr *pkt = G.snd_packet;
- //memset(pkt, 0, datalen + sizeof(struct icmp6_hdr) + 4);
+ memset(pkt, G.pattern, datalen + sizeof(struct icmp6_hdr) + 4);
pkt->icmp6_type = ICMP6_ECHO_REQUEST;
/*pkt->icmp6_code = 0;*/
/*pkt->icmp6_cksum = 0;*/
- pkt->icmp6_seq = htons(ntransmitted); /* don't ++ here, it can be a macro */
+ pkt->icmp6_seq = htons(G.ntransmitted); /* don't ++ here, it can be a macro */
pkt->icmp6_id = myid;
/*if (datalen >= 4)*/
- *(uint32_t*)(&pkt->icmp6_data8[4]) = monotonic_us();
+ *(bb__aliased_uint32_t*)(&pkt->icmp6_data8[4]) = monotonic_us();
//TODO? pkt->icmp_cksum = inet_cksum(...);
@@ -557,11 +592,10 @@ static void unpack_tail(int sz, uint32_t *tp,
const char *from_str,
uint16_t recv_seq, int ttl)
{
+ unsigned char *b, m;
const char *dupmsg = " (DUP!)";
unsigned triptime = triptime; /* for gcc */
- ++nreceived;
-
if (tp) {
/* (int32_t) cast is for hypothetical 64-bit unsigned */
/* (doesn't hurt 32-bit real-world anyway) */
@@ -573,11 +607,15 @@ static void unpack_tail(int sz, uint32_t *tp,
tmax = triptime;
}
- if (TST(recv_seq % MAX_DUP_CHK)) {
- ++nrepeats;
- --nreceived;
+ b = &BYTE(recv_seq % MAX_DUP_CHK);
+ m = MASK(recv_seq % MAX_DUP_CHK);
+ /*if TST(recv_seq % MAX_DUP_CHK):*/
+ if (*b & m) {
+ ++G.nrepeats;
} else {
- SET(recv_seq % MAX_DUP_CHK);
+ /*SET(recv_seq % MAX_DUP_CHK):*/
+ *b |= m;
+ ++G.nreceived;
dupmsg += 7;
}
@@ -660,7 +698,6 @@ static void ping4(len_and_sockaddr *lsa)
{
int sockopt;
- pingsock = create_icmp_socket();
pingaddr.sin = lsa->u.sin;
if (source_lsa) {
if (setsockopt(pingsock, IPPROTO_IP, IP_MULTICAST_IF,
@@ -668,8 +705,6 @@ static void ping4(len_and_sockaddr *lsa)
bb_error_msg_and_die("can't set multicast source interface");
xbind(pingsock, &source_lsa->u.sa, source_lsa->len);
}
- if (str_I)
- setsockopt_bindtodevice(pingsock, str_I);
/* enable broadcast pings */
setsockopt_broadcast(pingsock);
@@ -677,28 +712,22 @@ static void ping4(len_and_sockaddr *lsa)
/* set recv buf (needed if we can get lots of responses: flood ping,
* broadcast ping etc) */
sockopt = (datalen * 2) + 7 * 1024; /* giving it a bit of extra room */
- setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof(sockopt));
+ setsockopt_SOL_SOCKET_int(pingsock, SO_RCVBUF, sockopt);
if (opt_ttl != 0) {
- setsockopt(pingsock, IPPROTO_IP, IP_TTL, &opt_ttl, sizeof(opt_ttl));
+ setsockopt_int(pingsock, IPPROTO_IP, IP_TTL, opt_ttl);
/* above doesnt affect packets sent to bcast IP, so... */
- setsockopt(pingsock, IPPROTO_IP, IP_MULTICAST_TTL, &opt_ttl, sizeof(opt_ttl));
- }
-
- if (opt_ttl != 0) {
- setsockopt(pingsock, IPPROTO_IP, IP_TTL, &opt_ttl, sizeof(opt_ttl));
- /* above doesnt affect packets sent to bcast IP, so... */
- setsockopt(pingsock, IPPROTO_IP, IP_MULTICAST_TTL, &opt_ttl, sizeof(opt_ttl));
+ setsockopt_int(pingsock, IPPROTO_IP, IP_MULTICAST_TTL, opt_ttl);
}
if (IN_MULTICAST(ntohl(pingaddr.sin.sin_addr.s_addr))) {
- if (myid && pmtudisc >= 0 && pmtudisc != IPV6_PMTUDISC_DO)
+ if (myid && pmtudisc >= 0 && pmtudisc != IP_PMTUDISC_DO)
bb_error_msg_and_die("multicast ping does not fragment");
if (pmtudisc < 0)
- pmtudisc = IPV6_PMTUDISC_DO;
+ pmtudisc = IP_PMTUDISC_DO;
}
if (pmtudisc >= 0)
- setsockopt(pingsock, SOL_IP, IP_MTU_DISCOVER, &pmtudisc, sizeof(pmtudisc));
+ setsockopt_int(pingsock, SOL_IP, IP_MTU_DISCOVER, pmtudisc);
signal(SIGINT, print_stats_and_exit);
@@ -719,12 +748,11 @@ static void ping4(len_and_sockaddr *lsa)
continue;
}
unpack4(G.rcv_packet, c, &from);
- if (pingcount && nreceived >= pingcount)
+ if (pingcount && G.nreceived >= pingcount)
break;
}
}
#if ENABLE_PING6
-extern int BUG_bad_offsetof_icmp6_cksum(void);
static void ping6(len_and_sockaddr *lsa)
{
int sockopt;
@@ -733,13 +761,9 @@ static void ping6(len_and_sockaddr *lsa)
struct iovec iov;
char control_buf[CMSG_SPACE(36)];
- pingsock = create_icmp6_socket();
pingaddr.sin6 = lsa->u.sin6;
- /* untested whether "-I addr" really works for IPv6: */
if (source_lsa)
xbind(pingsock, &source_lsa->u.sa, source_lsa->len);
- if (str_I)
- setsockopt_bindtodevice(pingsock, str_I);
#ifdef ICMP6_FILTER
{
@@ -751,8 +775,8 @@ static void ping6(len_and_sockaddr *lsa)
ICMP6_FILTER_SETPASSALL(&filt);
}
if (setsockopt(pingsock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
- sizeof(filt)) < 0)
- bb_error_msg_and_die("setsockopt(ICMP6_FILTER)");
+ sizeof(filt)) < 0)
+ bb_error_msg_and_die("setsockopt(%s)", "ICMP6_FILTER");
}
#endif /*ICMP6_FILTER*/
@@ -762,20 +786,19 @@ static void ping6(len_and_sockaddr *lsa)
/* set recv buf (needed if we can get lots of responses: flood ping,
* broadcast ping etc) */
sockopt = (datalen * 2) + 7 * 1024; /* giving it a bit of extra room */
- setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof(sockopt));
+ setsockopt_SOL_SOCKET_int(pingsock, SO_RCVBUF, sockopt);
sockopt = offsetof(struct icmp6_hdr, icmp6_cksum);
- if (offsetof(struct icmp6_hdr, icmp6_cksum) != 2)
- BUG_bad_offsetof_icmp6_cksum();
- setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM, &sockopt, sizeof(sockopt));
+ BUILD_BUG_ON(offsetof(struct icmp6_hdr, icmp6_cksum) != 2);
+ setsockopt_int(pingsock, SOL_RAW, IPV6_CHECKSUM, sockopt);
if (opt_ttl != 0) {
- setsockopt(pingsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &opt_ttl, sizeof(opt_ttl));
- setsockopt(pingsock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &opt_ttl, sizeof(opt_ttl));
+ setsockopt_int(pingsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, opt_ttl);
+ setsockopt_int(pingsock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, opt_ttl);
}
/* request ttl info to be returned in ancillary data */
- setsockopt(pingsock, SOL_IPV6, IPV6_HOPLIMIT, &const_int_1, sizeof(const_int_1));
+ setsockopt_1(pingsock, SOL_IPV6, IPV6_HOPLIMIT);
if (if_index)
pingaddr.sin6.sin6_scope_id = if_index;
@@ -787,7 +810,7 @@ static void ping6(len_and_sockaddr *lsa)
pmtudisc = IPV6_PMTUDISC_DO;
}
if (pmtudisc >= 0)
- setsockopt(pingsock, SOL_IPV6, IPV6_MTU_DISCOVER, &pmtudisc, sizeof(pmtudisc));
+ setsockopt_int(pingsock, SOL_IPV6, IPV6_MTU_DISCOVER, pmtudisc);
signal(SIGINT, print_stats_and_exit);
@@ -825,7 +848,7 @@ static void ping6(len_and_sockaddr *lsa)
}
}
unpack6(G.rcv_packet, c, &from, hoplimit);
- if (pingcount && nreceived >= pingcount)
+ if (pingcount && G.nreceived >= pingcount)
break;
}
}
@@ -840,6 +863,11 @@ static void ping(len_and_sockaddr *lsa)
}
printf(": %d data bytes\n", datalen);
+ create_icmp_socket(lsa);
+ /* untested whether "-I addr" really works for IPv6: */
+ if (str_I)
+ setsockopt_bindtodevice(pingsock, str_I);
+
G.sizeof_rcv_packet = datalen + MAXIPLEN + MAXICMPLEN;
G.rcv_packet = xzalloc(G.sizeof_rcv_packet);
#if ENABLE_PING6
@@ -859,13 +887,13 @@ static void ping(len_and_sockaddr *lsa)
static int common_ping_main(int opt, char **argv)
{
len_and_sockaddr *lsa;
- char *str_s, *str_M;
+ char *str_s, *str_p, *str_M;
INIT_G();
/* exactly one argument needed; -v and -q don't mix; -c NUM, -t NUM, -w NUM, -W NUM */
opt_complementary = "=1:q--v:v--q:c+:t+:w+:W+";
- opt |= getopt32(argv, OPT_STRING, &pingcount, &str_s, &opt_ttl, &deadline, &timeout, &str_I, &str_M);
+ opt |= getopt32(argv, OPT_STRING, &pingcount, &str_s, &opt_ttl, &deadline, &timeout, &str_I, &str_p, &str_M);
if (opt & OPT_s)
datalen = xatou16(str_s); // -s
if (opt & OPT_I) { // -I
@@ -876,6 +904,19 @@ static int common_ping_main(int opt, char **argv)
str_I = NULL; /* don't try to bind to device later */
}
}
+ if (opt & OPT_p)
+ G.pattern = xstrtou_range(str_p, 16, 0, 255);
+ if (opt & OPT_M) { // -M
+ if (strcmp(str_M, "do") == 0)
+ pmtudisc = IP_PMTUDISC_DO;
+ else if (strcmp(str_M, "dont") == 0)
+ pmtudisc = IP_PMTUDISC_DONT;
+ else if (strcmp(str_M, "want") == 0)
+ pmtudisc = IP_PMTUDISC_WANT;
+ else
+ bb_show_usage();
+ }
+
myid = (uint16_t) getpid();
hostname = argv[optind];
#if ENABLE_PING6
@@ -890,14 +931,6 @@ static int common_ping_main(int opt, char **argv)
#else
lsa = xhost_and_af2sockaddr(hostname, 0, AF_INET);
#endif
- if (opt & OPT_M) { // -M
- if (strcmp(str_M, "do") == 0)
- pmtudisc = IP_PMTUDISC_DO;
- else if (strcmp(str_M, "dont") == 0)
- pmtudisc = IP_PMTUDISC_DONT;
- else if (strcmp(str_M, "want") == 0)
- pmtudisc = IP_PMTUDISC_WANT;
- }
if (source_lsa && source_lsa->u.sa.sa_family != lsa->u.sa.sa_family)
/* leaking it here... */
diff --git a/release/src/router/busybox/networking/pscan.c b/release/src/router/busybox/networking/pscan.c
index 28005ad57e..72ed8cdb5c 100644
--- a/release/src/router/busybox/networking/pscan.c
+++ b/release/src/router/busybox/networking/pscan.c
@@ -157,7 +157,7 @@ int pscan_main(int argc UNUSED_PARAM, char **argv)
}
if (ENABLE_FEATURE_CLEAN_UP) free(lsap);
- printf("%d closed, %d open, %d timed out (or blocked) ports\n",
+ printf("%u closed, %u open, %u timed out (or blocked) ports\n",
closed_ports,
open_ports,
nports - (closed_ports + open_ports));
diff --git a/release/src/router/busybox/networking/route.c b/release/src/router/busybox/networking/route.c
index b7b5a02e69..65c2fb7c85 100644
--- a/release/src/router/busybox/networking/route.c
+++ b/release/src/router/busybox/networking/route.c
@@ -55,6 +55,7 @@
#define RTF_WINDOW 0x0080 /* per route window clamping */
#define RTF_IRTT 0x0100 /* Initial round trip time */
#define RTF_REJECT 0x0200 /* Reject route */
+#define RTF_NONEXTHOP 0x00200000 /* route with no nexthop */
#endif
#if defined(SIOCADDRTOLD) || defined(RTF_IRTT) /* route */
@@ -128,7 +129,7 @@ static const char tbl_ipvx[] ALIGN1 =
"\013\043reinstate" /* Since last, we can save a byte. */
;
-static const int flags_ipvx[] = { /* MUST match tbl_ipvx[] values above. */
+static const uint16_t flags_ipvx[] = { /* MUST match tbl_ipvx[] values above. */
#ifdef RTF_REJECT
RTF_REJECT,
#endif
@@ -283,7 +284,7 @@ static NOINLINE void INET_setroute(int action, char **args)
if (k == KW_IPVx_IRTT) {
rt->rt_flags |= RTF_IRTT;
rt->rt_irtt = xatoul(args_m1);
- rt->rt_irtt *= (sysconf(_SC_CLK_TCK) / 100); /* FIXME */
+ rt->rt_irtt *= (bb_clk_tck() / 100); /* FIXME */
#if 0 /* FIXME: do we need to check anything of this? */
if (rt->rt_irtt < 1 || rt->rt_irtt > (120 * HZ)) {
bb_error_msg_and_die("bad irtt");
@@ -409,7 +410,7 @@ static NOINLINE void INET6_setroute(int action, char **args)
bb_error_msg_and_die("resolving %s", args_m1);
}
memcpy(&rt.rtmsg_gateway, sa6.sin6_addr.s6_addr,
- sizeof(struct in6_addr));
+ sizeof(struct in6_addr));
rt.rtmsg_flags |= RTF_GATEWAY;
continue;
}
@@ -435,7 +436,7 @@ static NOINLINE void INET6_setroute(int action, char **args)
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy_IFNAMSIZ(ifr.ifr_name, devname);
- xioctl(skfd, SIOGIFINDEX, &ifr);
+ xioctl(skfd, SIOCGIFINDEX, &ifr);
rt.rtmsg_ifindex = ifr.ifr_ifindex;
}
@@ -449,7 +450,11 @@ static NOINLINE void INET6_setroute(int action, char **args)
}
#endif
-static const unsigned flagvals[] = { /* Must agree with flagchars[]. */
+static const
+IF_NOT_FEATURE_IPV6(uint16_t)
+IF_FEATURE_IPV6(unsigned)
+flagvals[] = { /* Must agree with flagchars[]. */
+ RTF_UP,
RTF_GATEWAY,
RTF_HOST,
RTF_REINSTATE,
@@ -458,27 +463,25 @@ static const unsigned flagvals[] = { /* Must agree with flagchars[]. */
#if ENABLE_FEATURE_IPV6
RTF_DEFAULT,
RTF_ADDRCONF,
- RTF_CACHE
+ RTF_CACHE,
+ RTF_REJECT,
+ RTF_NONEXTHOP, /* this one doesn't fit into 16 bits */
#endif
};
-
-#define IPV4_MASK (RTF_GATEWAY|RTF_HOST|RTF_REINSTATE|RTF_DYNAMIC|RTF_MODIFIED)
-#define IPV6_MASK (RTF_GATEWAY|RTF_HOST|RTF_DEFAULT|RTF_ADDRCONF|RTF_CACHE)
-
/* Must agree with flagvals[]. */
static const char flagchars[] ALIGN1 =
- "GHRDM"
+ "UGHRDM"
#if ENABLE_FEATURE_IPV6
- "DAC"
+ "DAC!n"
#endif
;
+#define IPV4_MASK (RTF_UP|RTF_GATEWAY|RTF_HOST|RTF_REINSTATE|RTF_DYNAMIC|RTF_MODIFIED)
+#define IPV6_MASK (RTF_UP|RTF_GATEWAY|RTF_HOST|RTF_DEFAULT|RTF_ADDRCONF|RTF_CACHE|RTF_REJECT|RTF_NONEXTHOP)
static void set_flags(char *flagstr, int flags)
{
int i;
- *flagstr++ = 'U';
-
for (i = 0; (*flagstr = flagchars[i]) != 0; i++) {
if (flags & flagvals[i]) {
++flagstr;
@@ -491,6 +494,7 @@ void FAST_FUNC bb_displayroutes(int noresolve, int netstatfmt)
{
char devname[64], flags[16], *sdest, *sgw;
unsigned long d, g, m;
+ int r;
int flgs, ref, use, metric, mtu, win, ir;
struct sockaddr_in s_addr;
struct in_addr mask;
@@ -498,23 +502,27 @@ void FAST_FUNC bb_displayroutes(int noresolve, int netstatfmt)
FILE *fp = xfopen_for_read("/proc/net/route");
printf("Kernel IP routing table\n"
- "Destination Gateway Genmask Flags %s Iface\n",
+ "Destination Gateway Genmask Flags %s Iface\n",
netstatfmt ? " MSS Window irtt" : "Metric Ref Use");
- if (fscanf(fp, "%*[^\n]\n") < 0) { /* Skip the first line. */
- goto ERROR; /* Empty or missing line, or read error. */
+ /* Skip the first line. */
+ r = fscanf(fp, "%*[^\n]\n");
+ if (r < 0) {
+ /* Empty line, read error, or EOF. Yes, if routing table
+ * is completely empty, /proc/net/route has no header.
+ */
+ goto ERROR;
}
while (1) {
- int r;
r = fscanf(fp, "%63s%lx%lx%X%d%d%d%lx%d%d%d\n",
- devname, &d, &g, &flgs, &ref, &use, &metric, &m,
- &mtu, &win, &ir);
+ devname, &d, &g, &flgs, &ref, &use, &metric, &m,
+ &mtu, &win, &ir);
if (r != 11) {
+ ERROR:
if ((r < 0) && feof(fp)) { /* EOF with no (nonspace) chars read. */
break;
}
- ERROR:
- bb_error_msg_and_die("fscanf");
+ bb_perror_msg_and_die(bb_msg_read_error);
}
if (!(flgs & RTF_UP)) { /* Skip interfaces that are down. */
@@ -567,20 +575,20 @@ static void INET6_displayroutes(void)
FILE *fp = xfopen_for_read("/proc/net/ipv6_route");
printf("Kernel IPv6 routing table\n%-44s%-40s"
- "Flags Metric Ref Use Iface\n",
- "Destination", "Next Hop");
+ "Flags Metric Ref Use Iface\n",
+ "Destination", "Next Hop");
while (1) {
int r;
r = fscanf(fp, "%32s%x%*s%x%32s%x%x%x%x%s\n",
addr6x+14, &prefix_len, &slen, addr6x+40+7,
- &metric, &use, &refcnt, &iflags, iface);
+ &metric, &refcnt, &use, &iflags, iface);
if (r != 9) {
if ((r < 0) && feof(fp)) { /* EOF with no (nonspace) chars read. */
break;
}
ERROR:
- bb_error_msg_and_die("fscanf");
+ bb_perror_msg_and_die(bb_msg_read_error);
}
/* Do the addr6x shift-and-insert changes to ':'-delimit addresses.
@@ -606,10 +614,6 @@ static void INET6_displayroutes(void)
} while (i < 40+28+7);
}
- if (!(iflags & RTF_UP)) { /* Skip interfaces that are down. */
- continue;
- }
-
set_flags(flags, (iflags & IPV6_MASK));
r = 0;
@@ -618,8 +622,8 @@ static void INET6_displayroutes(void)
(struct sockaddr *) &snaddr6.sin6_addr);
snaddr6.sin6_family = AF_INET6;
naddr6 = INET6_rresolve((struct sockaddr_in6 *) &snaddr6,
- 0x0fff /* Apparently, upstream never resolves. */
- );
+ 0x0fff /* Apparently, upstream never resolves. */
+ );
if (!r) { /* 1st pass */
snprintf(addr6, sizeof(addr6), "%s/%d", naddr6, prefix_len);
diff --git a/release/src/router/busybox/networking/slattach.c b/release/src/router/busybox/networking/slattach.c
index a500da6d06..2d1305e32a 100644
--- a/release/src/router/busybox/networking/slattach.c
+++ b/release/src/router/busybox/networking/slattach.c
@@ -27,18 +27,19 @@
//usage: "\n -F Disable RTS/CTS flow control"
#include "libbb.h"
-#include "libiproute/utils.h" /* invarg() */
+#include "common_bufsiz.h"
+#include "libiproute/utils.h" /* invarg_1_to_2() */
struct globals {
int handle;
int saved_disc;
struct termios saved_state;
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define handle (G.handle )
#define saved_disc (G.saved_disc )
#define saved_state (G.saved_state )
-#define INIT_G() do { } while (0)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
/*
@@ -175,7 +176,7 @@ int slattach_main(int argc UNUSED_PARAM, char **argv)
encap = index_in_strings(proto_names, proto);
if (encap < 0)
- invarg(proto, "protocol");
+ invarg_1_to_2(proto, "protocol");
if (encap > 3)
encap = 8;
@@ -183,7 +184,7 @@ int slattach_main(int argc UNUSED_PARAM, char **argv)
if (opt & OPT_s_baud) {
baud_code = tty_value_to_baud(xatoi(baud_str));
if (baud_code < 0)
- invarg(baud_str, "baud rate");
+ invarg_1_to_2(baud_str, "baud rate");
}
/* Trap signals in order to restore tty states upon exit */
diff --git a/release/src/router/busybox/networking/ssl_helper-wolfssl/00cfg-wolfssl-3.6.8 b/release/src/router/busybox/networking/ssl_helper-wolfssl/00cfg-wolfssl-3.6.8
new file mode 100755
index 0000000000..50b6102d9e
--- /dev/null
+++ b/release/src/router/busybox/networking/ssl_helper-wolfssl/00cfg-wolfssl-3.6.8
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# How to configure & build a static wolfssl-3.6.8 library
+# suitable for static build of ssl_helper.
+
+export CC="i686-gcc"
+export CFLAGS="\
+-Os \
+-static \
+-fomit-frame-pointer \
+-falign-functions=1 -falign-labels=1 -falign-loops=1 -falign-jumps=1 \
+-ffunction-sections -fdata-sections \
+"
+
+./configure \
+ --host=i686 \
+ --enable-static \
+ --enable-singlethreaded \
+ --disable-shared \
+|| exit $?
+
+make
diff --git a/release/src/router/busybox/networking/ssl_helper-wolfssl/README b/release/src/router/busybox/networking/ssl_helper-wolfssl/README
new file mode 100644
index 0000000000..58a381c204
--- /dev/null
+++ b/release/src/router/busybox/networking/ssl_helper-wolfssl/README
@@ -0,0 +1,20 @@
+A small SSL helper for busybox wget.
+
+Precompiled static binary may be found in
+http://busybox.net/downloads/binaries/
+
+Build instructions:
+
+* Unpack wolfssl-3.6.8.zip
+* Build it:
+ ./configure --enable-static --disable-shared && make
+* Drop this directory into wolfssl-3.6.8/ssl_helper
+* Run ssl_helper.sh to compile and link the helper
+
+Usage: "ssl_helper -d FILE_DESCRIPTOR" where FILE_DESCRIPTOR is open to the peer.
+
+In bash, you can do it this way:
+$ ssl_helper -d3 3<>/dev/tcp/HOST/PORT
+
+Stdin will be SSL-encrypted and sent to FILE_DESCRIPTOR.
+Data from FILE_DESCRIPTOR will be decrypted and sent to stdout.
diff --git a/release/src/router/busybox/networking/ssl_helper-wolfssl/ssl_helper.c b/release/src/router/busybox/networking/ssl_helper-wolfssl/ssl_helper.c
new file mode 100644
index 0000000000..38b7b56c63
--- /dev/null
+++ b/release/src/router/busybox/networking/ssl_helper-wolfssl/ssl_helper.c
@@ -0,0 +1,480 @@
+/*
+ * Adapted from:
+ *
+ * client.c
+ *
+ * Copyright (C) 2006-2015 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL. (formerly known as CyaSSL)
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <time.h>
+#include <poll.h>
+#include <sys/socket.h>
+
+#include <wolfssl/wolfcrypt/types.h>
+#include <wolfssl/ssl.h>
+
+#if 0
+# define dbg(...) say(__VA_ARGS__)
+#else
+# define dbg(...) ((void)0)
+#endif
+
+static ssize_t safe_write(int fd, const void *buf, size_t count)
+{
+ ssize_t n;
+
+ do {
+ n = write(fd, buf, count);
+ } while (n < 0 && errno == EINTR);
+
+ return n;
+}
+
+static ssize_t full_write(int fd, const void *buf, size_t len)
+{
+ ssize_t cc;
+ ssize_t total;
+
+ total = 0;
+
+ while (len) {
+ cc = safe_write(fd, buf, len);
+
+ if (cc < 0) {
+ if (total) {
+ /* we already wrote some! */
+ /* user can do another write to know the error code */
+ return total;
+ }
+ return cc; /* write() returns -1 on failure. */
+ }
+
+ total += cc;
+ buf = ((const char *)buf) + cc;
+ len -= cc;
+ }
+
+ return total;
+}
+
+static void say(const char *s, ...)
+{
+ char buf[256];
+ va_list p;
+ int sz;
+
+ va_start(p, s);
+ sz = vsnprintf(buf, sizeof(buf), s, p);
+ full_write(STDERR_FILENO, buf, sz >= 0 && sz < sizeof(buf) ? sz : strlen(buf));
+ va_end(p);
+}
+
+static void die(const char *s, ...)
+{
+ char buf[256];
+ va_list p;
+ int sz;
+
+ va_start(p, s);
+ sz = vsnprintf(buf, sizeof(buf), s, p);
+ full_write(STDERR_FILENO, buf, sz >= 0 && sz < sizeof(buf) ? sz : strlen(buf));
+ exit(1);
+ va_end(p);
+}
+
+static void err_sys(const char *msg)
+{
+ die("%s\n", msg);
+}
+
+/* ==== */
+
+#if 0
+static void showPeer(WOLFSSL* ssl)
+{
+ WOLFSSL_CIPHER* cipher;
+ WOLFSSL_X509* peer = wolfSSL_get_peer_certificate(ssl);
+ if (peer)
+ ShowX509(peer, "peer's cert info:");
+ else
+ say("peer has no cert!\n");
+ say("SSL version is %s\n", wolfSSL_get_version(ssl));
+
+ cipher = wolfSSL_get_current_cipher(ssl);
+ say("SSL cipher suite is %s\n", wolfSSL_CIPHER_get_name(cipher));
+
+ {
+ WOLFSSL_X509_CHAIN* chain = wolfSSL_get_peer_chain(ssl);
+ int count = wolfSSL_get_chain_count(chain);
+ int i;
+
+ for (i = 0; i < count; i++) {
+ int length;
+ unsigned char buffer[3072];
+ WOLFSSL_X509* chainX509;
+
+ wolfSSL_get_chain_cert_pem(chain, i, buffer, sizeof(buffer), &length);
+ buffer[length] = 0;
+ say("cert %d has length %d data = \n%s\n", i, length, buffer);
+
+ chainX509 = wolfSSL_get_chain_X509(chain, i);
+ if (chainX509)
+ ShowX509(chainX509, "session cert info:");
+ else
+ say("get_chain_X509 failed\n");
+ wolfSSL_FreeX509(chainX509);
+ }
+ }
+}
+#endif
+
+WOLFSSL *prepare(int sockfd)
+{
+ WOLFSSL_METHOD* method;
+ WOLFSSL_CTX* ctx;
+ WOLFSSL* ssl;
+
+ wolfSSL_Init();
+
+ method = wolfTLSv1_1_client_method();
+ if (method == NULL)
+ err_sys("out of memory");
+ ctx = wolfSSL_CTX_new(method);
+ if (ctx == NULL)
+ err_sys("out of memory");
+// if (cipherList)
+// if (wolfSSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS)
+// err_sys("client can't set cipher list 1");
+
+// if (fewerPackets)
+// wolfSSL_CTX_set_group_messages(ctx);
+
+//#ifndef NO_DH
+// wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits);
+//#endif
+
+// if (usePsk) {
+// wolfSSL_CTX_set_psk_client_callback(ctx, my_psk_client_cb);
+// if (cipherList == NULL) {
+// const char *defaultCipherList;
+//#if defined(HAVE_AESGCM) && !defined(NO_DH)
+// defaultCipherList = "DHE-PSK-AES128-GCM-SHA256";
+//#elif defined(HAVE_NULL_CIPHER)
+// defaultCipherList = "PSK-NULL-SHA256";
+//#else
+// defaultCipherList = "PSK-AES128-CBC-SHA256";
+//#endif
+// if (wolfSSL_CTX_set_cipher_list(ctx,defaultCipherList) != SSL_SUCCESS)
+// err_sys("client can't set cipher list 2");
+// }
+// useClientCert = 0;
+// }
+
+// if (useAnon) {
+// if (cipherList == NULL) {
+// wolfSSL_CTX_allow_anon_cipher(ctx);
+// if (wolfSSL_CTX_set_cipher_list(ctx,"ADH-AES128-SHA") != SSL_SUCCESS)
+// err_sys("client can't set cipher list 4");
+// }
+// useClientCert = 0;
+// }
+
+//#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+// wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
+//#endif
+
+// if (useOcsp) {
+// if (ocspUrl != NULL) {
+// wolfSSL_CTX_SetOCSP_OverrideURL(ctx, ocspUrl);
+// wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE
+// | WOLFSSL_OCSP_URL_OVERRIDE);
+// }
+// else
+// wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE);
+// }
+//
+//#ifdef USER_CA_CB
+// wolfSSL_CTX_SetCACb(ctx, CaCb);
+//#endif
+//
+//#ifdef VERIFY_CALLBACK
+// wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myVerify);
+//#endif
+//#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
+// if (useClientCert) {
+// if (wolfSSL_CTX_use_certificate_chain_file(ctx, ourCert) != SSL_SUCCESS)
+// err_sys("can't load client cert file, check file and run from"
+// " wolfSSL home dir");
+// if (wolfSSL_CTX_use_PrivateKey_file(ctx, ourKey, SSL_FILETYPE_PEM) != SSL_SUCCESS)
+// err_sys("can't load client private key file, check file and run "
+// "from wolfSSL home dir");
+// }
+//
+// if (!usePsk && !useAnon) {
+// if (wolfSSL_CTX_load_verify_locations(ctx, verifyCert,0) != SSL_SUCCESS)
+// err_sys("can't load ca file, Please run from wolfSSL home dir");
+//#ifdef HAVE_ECC
+// /* load ecc verify too, echoserver uses it by default w/ ecc */
+// if (wolfSSL_CTX_load_verify_locations(ctx, eccCert, 0) != SSL_SUCCESS)
+// err_sys("can't load ecc ca file, Please run from wolfSSL home dir");
+//#endif
+// }
+//#endif /* !NO_FILESYSTEM && !NO_CERTS */
+
+//#if !defined(NO_CERTS)
+// if (!usePsk && !useAnon && doPeerCheck == 0)
+// wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
+// if (!usePsk && !useAnon && overrideDateErrors == 1)
+// wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myDateCb);
+//#endif
+
+ wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
+
+//#ifdef HAVE_SNI
+// if (sniHostName)
+// if (wolfSSL_CTX_UseSNI(ctx, 0, sniHostName, XSTRLEN(sniHostName)) != SSL_SUCCESS)
+// err_sys("UseSNI failed");
+//#endif
+
+//#ifdef HAVE_MAX_FRAGMENT
+// if (maxFragment)
+// if (wolfSSL_CTX_UseMaxFragment(ctx, maxFragment) != SSL_SUCCESS)
+// err_sys("UseMaxFragment failed");
+//#endif
+//#ifdef HAVE_TRUNCATED_HMAC
+// if (truncatedHMAC)
+// if (wolfSSL_CTX_UseTruncatedHMAC(ctx) != SSL_SUCCESS)
+// err_sys("UseTruncatedHMAC failed");
+//#endif
+//#ifdef HAVE_SESSION_TICKET
+// if (wolfSSL_CTX_UseSessionTicket(ctx) != SSL_SUCCESS)
+// err_sys("UseSessionTicket failed");
+//#endif
+
+//#if defined(WOLFSSL_MDK_ARM)
+// wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
+//#endif
+
+ ssl = wolfSSL_new(ctx);
+ if (ssl == NULL)
+ err_sys("out of memory");
+
+//#ifdef HAVE_SESSION_TICKET
+// wolfSSL_set_SessionTicket_cb(ssl, sessionTicketCB, (void*)"initial session");
+//#endif
+
+// if (doDTLS) {
+// SOCKADDR_IN_T addr;
+// build_addr(&addr, host, port, 1);
+// wolfSSL_dtls_set_peer(ssl, &addr, sizeof(addr));
+// tcp_socket(&sockfd, 1);
+// } wlse {
+// tcp_connect(&sockfd, host, port, 0);
+// }
+
+//#ifdef HAVE_POLY1305
+// /* use old poly to connect with google server */
+// if (!XSTRNCMP(domain, "www.google.com", 14)) {
+// if (wolfSSL_use_old_poly(ssl, 1) != 0)
+// err_sys("unable to set to old poly");
+// }
+//#endif
+
+ wolfSSL_set_fd(ssl, sockfd);
+
+//#ifdef HAVE_CRL
+// if (disableCRL == 0) {
+// if (wolfSSL_EnableCRL(ssl, WOLFSSL_CRL_CHECKALL) != SSL_SUCCESS)
+// err_sys("can't enable crl check");
+// if (wolfSSL_LoadCRL(ssl, crlPemDir, SSL_FILETYPE_PEM, 0) != SSL_SUCCESS)
+// err_sys("can't load crl, check crlfile and date validity");
+// if (wolfSSL_SetCRL_Cb(ssl, CRL_CallBack) != SSL_SUCCESS)
+// err_sys("can't set crl callback");
+// }
+//#endif
+//#ifdef HAVE_SECURE_RENEGOTIATION
+// if (scr) {
+// if (wolfSSL_UseSecureRenegotiation(ssl) != SSL_SUCCESS)
+// err_sys("can't enable secure renegotiation");
+// }
+//#endif
+//#ifdef ATOMIC_USER
+// if (atomicUser)
+// SetupAtomicUser(ctx, ssl);
+//#endif
+//#ifdef HAVE_PK_CALLBACKS
+// if (pkCallbacks)
+// SetupPkCallbacks(ctx, ssl);
+//#endif
+// if (matchName && doPeerCheck)
+// wolfSSL_check_domain_name(ssl, domain);
+
+ if (wolfSSL_connect(ssl) != SSL_SUCCESS) {
+// /* see note at top of README */
+// int err = wolfSSL_get_error(ssl, 0);
+// char buffer[WOLFSSL_MAX_ERROR_SZ];
+// say("err = %d, %s\n", err,
+// wolfSSL_ERR_error_string(err, buffer));
+ err_sys("SSL_connect failed");
+ }
+// showPeer(ssl);
+
+//#ifdef HAVE_SECURE_RENEGOTIATION
+// if (scr && forceScr) {
+// if (wolfSSL_Rehandshake(ssl) != SSL_SUCCESS) {
+// int err = wolfSSL_get_error(ssl, 0);
+// char buffer[WOLFSSL_MAX_ERROR_SZ];
+// say("err = %d, %s\n", err,
+// wolfSSL_ERR_error_string(err, buffer));
+// err_sys("wolfSSL_Rehandshake failed");
+// }
+// }
+//#endif
+
+ return ssl;
+}
+
+static struct pollfd pfd[2] = {
+ { -1, POLLIN|POLLERR|POLLHUP, 0 },
+ { -1, POLLIN|POLLERR|POLLHUP, 0 },
+};
+#define STDIN pfd[0]
+#define NETWORK pfd[1]
+#define STDIN_READY() (pfd[0].revents & (POLLIN|POLLERR|POLLHUP))
+#define NETWORK_READY() (pfd[1].revents & (POLLIN|POLLERR|POLLHUP))
+
+static void wait_for_input(void)
+{
+ if (STDIN.fd == NETWORK.fd) /* means both are -1 */
+ exit(0);
+ dbg("polling\n");
+ STDIN.revents = NETWORK.revents = 0;
+ while (poll(pfd, 2, -1) < 0 && errno == EINTR)
+ continue;
+}
+
+static void do_io_until_eof_and_exit(WOLFSSL *ssl, int fd)
+{
+ int len;
+ char ibuf[4 * 1024];
+
+ NETWORK.fd = fd;
+ STDIN.fd = 0;
+
+ len = 0; /* only to suppress compiler warning */
+ for (;;) {
+ wait_for_input();
+
+ if (STDIN_READY()) {
+ dbg("reading stdin\n");
+ len = read(STDIN_FILENO, ibuf, sizeof(ibuf));
+ if (len < 0)
+ die("read error on stdin\n");
+ if (len == 0) {
+ dbg("read len = 0, stdin not polled anymore\n");
+ STDIN.fd = -1;
+ } else {
+ int n = wolfSSL_write(ssl, ibuf, len);
+ if (n != len)
+ die("SSL_write(%d) failed (returned %d)\n", len, n);
+ }
+ }
+
+ if (NETWORK_READY()) {
+ dbg("%s%s%s\n",
+ (pfd[1].revents & POLLIN) ? "POLLIN" : "",
+ (pfd[1].revents & POLLERR) ? "|POLLERR" : "",
+ (pfd[1].revents & POLLHUP) ? "|POLLHUP" : ""
+ );
+/* We are using blocking socket here.
+ * (Nonblocking socket would complicate writing to it).
+ * Therefore, SSL_read _can block_ here.
+ * This is not what wget expects (it wants to see short reads).
+ * Therefore, we use smallish buffer here, to approximate that.
+ */
+ len = wolfSSL_read(ssl, ibuf,
+ sizeof(ibuf) < 1024 ? sizeof(ibuf) : 1024
+ );
+ if (len < 0)
+ die("SSL_read error on network (%d)\n", len);
+ if (len > 0) {
+ int n;
+ n = full_write(STDOUT_FILENO, ibuf, len);
+ if (n != len)
+ die("write(%d) to stdout returned %d\n", len, n);
+ continue;
+ }
+/* Blocking reads are easier wtr EOF detection (no EAGAIN error to check for) */
+ dbg("read len = 0, network not polled anymore\n");
+ NETWORK.fd = -1;
+ /* saw EOF on network, and we processed
+ * and wrote out all ssl data. Signal it:
+ */
+ close(STDOUT_FILENO);
+ }
+ }
+}
+
+int main(int argc, char **argv)
+{
+ WOLFSSL *ssl;
+ int fd;
+ char *fd_str;
+
+ if (!argv[1])
+ die("Syntax error\n");
+ if (argv[1][0] != '-')
+ die("Syntax error\n");
+ if (argv[1][1] != 'd')
+ die("Syntax error\n");
+ fd_str = argv[1] + 2;
+ if (!fd_str[0])
+ fd_str = argv[2];
+ if (!fd_str || fd_str[0] < '0' || fd_str[0] > '9')
+ die("Syntax error\n");
+
+ fd = atoi(fd_str);
+ if (fd < 3)
+ die("Syntax error\n");
+
+ ssl = prepare(fd);
+ do_io_until_eof_and_exit(ssl, fd);
+ /* does not return */
+
+// if (doDTLS == 0) { /* don't send alert after "break" command */
+// ret = wolfSSL_shutdown(ssl);
+// if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE)
+// wolfSSL_shutdown(ssl); /* bidirectional shutdown */
+// }
+//#ifdef ATOMIC_USER
+// if (atomicUser)
+// FreeAtomicUser(ssl);
+//#endif
+// wolfSSL_free(ssl);
+// CloseSocket(sockfd);
+// wolfSSL_CTX_free(ctx);
+
+ return 0;
+}
diff --git a/release/src/router/busybox/networking/ssl_helper-wolfssl/ssl_helper.sh b/release/src/router/busybox/networking/ssl_helper-wolfssl/ssl_helper.sh
new file mode 100755
index 0000000000..184ffe67e0
--- /dev/null
+++ b/release/src/router/busybox/networking/ssl_helper-wolfssl/ssl_helper.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# I use this to build static uclibc based binary using Aboriginal Linux toolchain:
+PREFIX="i686-"
+STATIC="-static"
+# Standard build:
+#PREFIX=""
+#STATIC=""
+
+${PREFIX}gcc -Os -Wall -I.. -c ssl_helper.c -o ssl_helper.o
+${PREFIX}gcc $STATIC --start-group ssl_helper.o -lm ../src/.libs/libwolfssl.a --end-group -o ssl_helper
+${PREFIX}-strip ssl_helper
diff --git a/release/src/router/busybox/networking/ssl_helper/README b/release/src/router/busybox/networking/ssl_helper/README
new file mode 100644
index 0000000000..4d0508fbbe
--- /dev/null
+++ b/release/src/router/busybox/networking/ssl_helper/README
@@ -0,0 +1,16 @@
+Build instructions:
+
+* Unpack matrixssl-3-4-2-open.tgz.
+* Build it: "make"
+* Drop this directory into matrixssl-3-4-2-open/ssl_helper
+* Run ssl_helper.sh to compile and link the helper
+
+Usage: "ssl_helper -d <FILE_DESCRIPTOR>" where FILE_DESCRIPTOR is open to the peer.
+
+In bash, you can do it this way:
+$ ssl_helper -d3 3<>/dev/tcp/HOST/PORT
+
+Stdin will be SSL-encrypted and sent to FILE_DESCRIPTOR.
+Data from FILE_DESCRIPTOR will be decrypted and sent to stdout.
+
+The plan is to adapt it for wget https helper, and for ssl support in nc.
diff --git a/release/src/router/busybox/networking/ssl_helper/ssl_helper.c b/release/src/router/busybox/networking/ssl_helper/ssl_helper.c
new file mode 100644
index 0000000000..d840b1b880
--- /dev/null
+++ b/release/src/router/busybox/networking/ssl_helper/ssl_helper.c
@@ -0,0 +1,406 @@
+/*
+ * Copyright (c) 2013 INSIDE Secure Corporation
+ * Copyright (c) PeerSec Networks, 2002-2011
+ * All Rights Reserved
+ *
+ * The latest version of this code is available at http://www.matrixssl.org
+ *
+ * This software is open source; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <time.h>
+#include <poll.h>
+#include <sys/socket.h>
+
+#include "matrixssl/matrixsslApi.h"
+
+//#warning "DO NOT USE THESE DEFAULT KEYS IN PRODUCTION ENVIRONMENTS."
+
+/*
+ * If supporting client authentication, pick ONE identity to auto select a
+ * certificate and private key that support desired algorithms.
+ */
+#define ID_RSA /* RSA Certificate and Key */
+
+#define USE_HEADER_KEYS
+
+/* If the algorithm type is supported, load a CA for it */
+#ifdef USE_HEADER_KEYS
+/* CAs */
+# include "sampleCerts/RSA/ALL_RSA_CAS.h"
+/* Identity Certs and Keys for use with Client Authentication */
+# ifdef ID_RSA
+# define EXAMPLE_RSA_KEYS
+# include "sampleCerts/RSA/2048_RSA.h"
+# include "sampleCerts/RSA/2048_RSA_KEY.h"
+# endif
+#endif
+
+static ssize_t safe_write(int fd, const void *buf, size_t count)
+{
+ ssize_t n;
+
+ do {
+ n = write(fd, buf, count);
+ } while (n < 0 && errno == EINTR);
+
+ return n;
+}
+
+static ssize_t full_write(int fd, const void *buf, size_t len)
+{
+ ssize_t cc;
+ ssize_t total;
+
+ total = 0;
+
+ while (len) {
+ cc = safe_write(fd, buf, len);
+
+ if (cc < 0) {
+ if (total) {
+ /* we already wrote some! */
+ /* user can do another write to know the error code */
+ return total;
+ }
+ return cc; /* write() returns -1 on failure. */
+ }
+
+ total += cc;
+ buf = ((const char *)buf) + cc;
+ len -= cc;
+ }
+
+ return total;
+}
+
+static void say(const char *s, ...)
+{
+ char buf[256];
+ va_list p;
+ int sz;
+
+ va_start(p, s);
+ sz = vsnprintf(buf, sizeof(buf), s, p);
+ full_write(STDERR_FILENO, buf, sz >= 0 && sz < sizeof(buf) ? sz : strlen(buf));
+ va_end(p);
+}
+
+static void die(const char *s, ...)
+{
+ char buf[256];
+ va_list p;
+ int sz;
+
+ va_start(p, s);
+ sz = vsnprintf(buf, sizeof(buf), s, p);
+ full_write(STDERR_FILENO, buf, sz >= 0 && sz < sizeof(buf) ? sz : strlen(buf));
+ exit(1);
+ va_end(p);
+}
+
+#if 0
+# define dbg(...) say(__VA_ARGS__)
+#else
+# define dbg(...) ((void)0)
+#endif
+
+static struct pollfd pfd[2] = {
+ { -1, POLLIN|POLLERR|POLLHUP, 0 },
+ { -1, POLLIN|POLLERR|POLLHUP, 0 },
+};
+#define STDIN pfd[0]
+#define NETWORK pfd[1]
+#define STDIN_READY() (pfd[0].revents & (POLLIN|POLLERR|POLLHUP))
+#define NETWORK_READY() (pfd[1].revents & (POLLIN|POLLERR|POLLHUP))
+
+static int wait_for_input(void)
+{
+ if (STDIN.fd == NETWORK.fd) /* means both are -1 */
+ exit(0);
+ dbg("polling\n");
+ STDIN.revents = NETWORK.revents = 0;
+ return poll(pfd, 2, -1);
+}
+
+static int32 certCb(ssl_t *ssl, psX509Cert_t *cert, int32 alert)
+{
+ /* Example to allow anonymous connections based on a define */
+ if (alert > 0) {
+ return SSL_ALLOW_ANON_CONNECTION; // = 254
+ }
+#if 0
+ /* Validate the 'not before' and 'not after' dates, etc */
+ return PS_FAILURE; /* if we don't like this cert */
+#endif
+ return PS_SUCCESS;
+}
+
+static void close_conn_and_exit(ssl_t *ssl, int fd)
+{
+ unsigned char *buf;
+ int len;
+
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
+ /* Quick attempt to send a closure alert, don't worry about failure */
+ if (matrixSslEncodeClosureAlert(ssl) >= 0) {
+ len = matrixSslGetOutdata(ssl, &buf);
+ if (len > 0) {
+ len = safe_write(fd, buf, len);
+ //if (len > 0) {
+ // matrixSslSentData(ssl, len);
+ //}
+ }
+ }
+ //matrixSslDeleteSession(ssl);
+ shutdown(fd, SHUT_WR);
+ exit(0);
+}
+
+static int encode_data(ssl_t *ssl, const void *data, int len)
+{
+ unsigned char *buf;
+ int available;
+
+ available = matrixSslGetWritebuf(ssl, &buf, len);
+ if (available < 0)
+ die("matrixSslGetWritebuf\n");
+ if (len > available)
+ die("len > available\n");
+ memcpy(buf, data, len);
+ if (matrixSslEncodeWritebuf(ssl, len) < 0)
+ die("matrixSslEncodeWritebuf\n");
+ return len;
+}
+
+static void flush_to_net(ssl_t *ssl, int fd)
+{
+ int rc;
+ int len;
+ unsigned char *buf;
+
+ while ((len = matrixSslGetOutdata(ssl, &buf)) > 0) {
+ dbg("writing net %d bytes\n", len);
+ if (full_write(fd, buf, len) != len)
+ die("write to network\n");
+ rc = matrixSslSentData(ssl, len);
+ if (rc < 0)
+ die("matrixSslSentData\n");
+ }
+}
+
+static void do_io_until_eof_and_exit(int fd, sslKeys_t *keys)
+{
+ int rc;
+ int len;
+ uint32_t len32u;
+ sslSessionId_t *sid;
+ ssl_t *ssl;
+ unsigned char *buf;
+
+ NETWORK.fd = fd;
+ /* Note! STDIN.fd is disabled (-1) until SSL handshake is over:
+ * we do not attempt to feed any user data to MatrixSSL
+ * before it is ready.
+ */
+
+ matrixSslNewSessionId(&sid);
+ rc = matrixSslNewClientSession(&ssl, keys, sid, 0, certCb, NULL, NULL, 0);
+dbg("matrixSslNewClientSession:rc=%d\n", rc);
+ if (rc != MATRIXSSL_REQUEST_SEND)
+ die("matrixSslNewClientSession\n");
+
+ len = 0; /* only to suppress compiler warning */
+ again:
+ switch (rc) {
+ case MATRIXSSL_REQUEST_SEND:
+ dbg("MATRIXSSL_REQUEST_SEND\n");
+ flush_to_net(ssl, fd);
+ goto poll_input;
+
+ case 0:
+ dbg("rc==0\n");
+ flush_to_net(ssl, fd);
+ goto poll_input;
+
+ case MATRIXSSL_REQUEST_CLOSE:
+ /* what does this mean if we are here? */
+ dbg("MATRIXSSL_REQUEST_CLOSE\n");
+ close_conn_and_exit(ssl, fd);
+
+ case MATRIXSSL_HANDSHAKE_COMPLETE:
+ dbg("MATRIXSSL_HANDSHAKE_COMPLETE\n");
+ /* Init complete, can start reading local user's data: */
+ STDIN.fd = STDIN_FILENO;
+ poll_input:
+ wait_for_input();
+ if (STDIN_READY()) {
+ char ibuf[4 * 1024];
+ dbg("reading stdin\n");
+ len = read(STDIN_FILENO, ibuf, sizeof(ibuf));
+ if (len < 0)
+ die("read error on stdin\n");
+ if (len == 0)
+ STDIN.fd = -1;
+ else {
+ len = encode_data(ssl, ibuf, len);
+ if (len) {
+ rc = MATRIXSSL_REQUEST_SEND;
+dbg("rc=%d\n", rc);
+ goto again;
+ }
+ }
+ }
+ read_network:
+ if (NETWORK_READY()) {
+ dbg("%s%s%s\n",
+ (pfd[1].revents & POLLIN) ? "POLLIN" : "",
+ (pfd[1].revents & POLLERR) ? "|POLLERR" : "",
+ (pfd[1].revents & POLLHUP) ? "|POLLHUP" : ""
+ );
+ len = matrixSslGetReadbuf(ssl, &buf);
+ if (len <= 0)
+ die("matrixSslGetReadbuf\n");
+ dbg("reading net up to %d\n", len);
+ len = read(fd, buf, len);
+ dbg("reading net:%d\n", len);
+ if (len < 0)
+ die("read error on network\n");
+ if (len == 0) /*eof*/
+ NETWORK.fd = -1;
+ len32u = len;
+ rc = matrixSslReceivedData(ssl, len, &buf, &len32u);
+dbg("matrixSslReceivedData:rc=%d\n", rc);
+ len = len32u;
+ if (rc < 0)
+ die("matrixSslReceivedData\n");
+ }
+ goto again;
+
+ case MATRIXSSL_APP_DATA:
+ dbg("MATRIXSSL_APP_DATA: writing stdout\n");
+ do {
+ if (full_write(STDOUT_FILENO, buf, len) != len)
+ die("write to stdout\n");
+ len32u = len;
+ rc = matrixSslProcessedData(ssl, &buf, &len32u);
+//this was seen returning rc=0:
+dbg("matrixSslProcessedData:rc=%d\n", rc);
+ len = len32u;
+ } while (rc == MATRIXSSL_APP_DATA);
+ if (pfd[1].fd == -1) {
+ /* Already saw EOF on network, and we processed
+ * and wrote out all ssl data. Signal it:
+ */
+ close(STDOUT_FILENO);
+ }
+ goto again;
+
+ case MATRIXSSL_REQUEST_RECV:
+ dbg("MATRIXSSL_REQUEST_RECV\n");
+ wait_for_input();
+ goto read_network;
+
+ case MATRIXSSL_RECEIVED_ALERT:
+ dbg("MATRIXSSL_RECEIVED_ALERT\n");
+ /* The first byte of the buffer is the level */
+ /* The second byte is the description */
+ if (buf[0] == SSL_ALERT_LEVEL_FATAL)
+ die("Fatal alert\n");
+ /* Closure alert is normal (and best) way to close */
+ if (buf[1] == SSL_ALERT_CLOSE_NOTIFY)
+ close_conn_and_exit(ssl, fd);
+ die("Warning alert\n");
+ len32u = len;
+ rc = matrixSslProcessedData(ssl, &buf, &len32u);
+dbg("matrixSslProcessedData:rc=%d\n", rc);
+ len = len32u;
+ goto again;
+
+ default:
+ /* If rc < 0 it is an error */
+ die("bad rc:%d\n", rc);
+ }
+}
+
+static sslKeys_t* make_keys(void)
+{
+ int rc, CAstreamLen;
+ char *CAstream;
+ sslKeys_t *keys;
+
+ if (matrixSslNewKeys(&keys) < 0)
+ die("matrixSslNewKeys\n");
+
+#ifdef USE_HEADER_KEYS
+ /*
+ * In-memory based keys
+ * Build the CA list first for potential client auth usage
+ */
+ CAstream = NULL;
+ CAstreamLen = sizeof(RSACAS);
+ if (CAstreamLen > 0) {
+ CAstream = psMalloc(NULL, CAstreamLen);
+ memcpy(CAstream, RSACAS, sizeof(RSACAS));
+ }
+
+ #ifdef ID_RSA
+ rc = matrixSslLoadRsaKeysMem(keys, RSA2048, sizeof(RSA2048),
+ RSA2048KEY, sizeof(RSA2048KEY), (unsigned char*)CAstream,
+ CAstreamLen);
+ if (rc < 0)
+ die("matrixSslLoadRsaKeysMem\n");
+ #endif
+
+ if (CAstream)
+ psFree(CAstream);
+#endif /* USE_HEADER_KEYS */
+ return keys;
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+ char *fd_str;
+
+ if (!argv[1])
+ die("Syntax error\n");
+ if (argv[1][0] != '-')
+ die("Syntax error\n");
+ if (argv[1][1] != 'd')
+ die("Syntax error\n");
+ fd_str = argv[1] + 2;
+ if (!fd_str[0])
+ fd_str = argv[2];
+ if (!fd_str || fd_str[0] < '0' || fd_str[0] > '9')
+ die("Syntax error\n");
+
+ fd = atoi(fd_str);
+ if (fd < 3)
+ die("Syntax error\n");
+
+ if (matrixSslOpen() < 0)
+ die("matrixSslOpen\n");
+
+ do_io_until_eof_and_exit(fd, make_keys());
+ /* does not return */
+
+ return 0;
+}
diff --git a/release/src/router/busybox/networking/ssl_helper/ssl_helper.sh b/release/src/router/busybox/networking/ssl_helper/ssl_helper.sh
new file mode 100755
index 0000000000..dc52de7781
--- /dev/null
+++ b/release/src/router/busybox/networking/ssl_helper/ssl_helper.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+# I use this to build static uclibc based binary using Aboriginal Linux toolchain:
+PREFIX=x86_64-
+STATIC=-static
+# Standard build:
+PREFIX=""
+STATIC=""
+
+${PREFIX}gcc -Os -DPOSIX -I.. -I../sampleCerts -Wall -c ssl_helper.c -o ssl_helper.o
+${PREFIX}gcc $STATIC ssl_helper.o ../libmatrixssl.a -lc ../libmatrixssl.a -o ssl_helper
diff --git a/release/src/router/busybox/networking/tc.c b/release/src/router/busybox/networking/tc.c
index 1574353a5c..d0bcbdeaa6 100644
--- a/release/src/router/busybox/networking/tc.c
+++ b/release/src/router/busybox/networking/tc.c
@@ -29,6 +29,7 @@
//usage: "filter show [ dev STRING ] [ root | parent CLASSID ]"
#include "libbb.h"
+#include "common_bufsiz.h"
#include "libiproute/utils.h"
#include "libiproute/ip_common.h"
@@ -63,16 +64,16 @@ struct globals {
uint32_t filter_prio;
uint32_t filter_proto;
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
-struct BUG_G_too_big {
- char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
-};
+#define G (*(struct globals*)bb_common_bufsiz1)
#define filter_ifindex (G.filter_ifindex)
#define filter_qdisc (G.filter_qdisc)
#define filter_parent (G.filter_parent)
#define filter_prio (G.filter_prio)
#define filter_proto (G.filter_proto)
-#define INIT_G() do { } while (0)
+#define INIT_G() do { \
+ setup_common_bufsiz(); \
+ BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
+} while (0)
/* Allocates a buffer containing the name of a class id.
* The caller must free the returned memory. */
@@ -151,17 +152,17 @@ static void print_rate(char *buf, int len, uint32_t rate)
double tmp = (double)rate*8;
if (use_iec) {
- if (tmp >= 1000.0*1024.0*1024.0)
- snprintf(buf, len, "%.0fMibit", tmp/1024.0*1024.0);
- else if (tmp >= 1000.0*1024)
+ if (tmp >= 1000*1024*1024)
+ snprintf(buf, len, "%.0fMibit", tmp/(1024*1024));
+ else if (tmp >= 1000*1024)
snprintf(buf, len, "%.0fKibit", tmp/1024);
else
snprintf(buf, len, "%.0fbit", tmp);
} else {
- if (tmp >= 1000.0*1000000.0)
- snprintf(buf, len, "%.0fMbit", tmp/1000000.0);
- else if (tmp >= 1000.0 * 1000.0)
- snprintf(buf, len, "%.0fKbit", tmp/1000.0);
+ if (tmp >= 1000*1000000)
+ snprintf(buf, len, "%.0fMbit", tmp/1000000);
+ else if (tmp >= 1000*1000)
+ snprintf(buf, len, "%.0fKbit", tmp/1000);
else
snprintf(buf, len, "%.0fbit", tmp);
}
@@ -391,7 +392,7 @@ static int print_class(const struct sockaddr_nl *who UNUSED_PARAM,
printf("root ");
else if (msg->tcm_parent) {
classid = print_tc_classid(filter_qdisc ?
- TC_H_MIN(msg->tcm_parent) : msg->tcm_parent);
+ TC_H_MIN(msg->tcm_parent) : msg->tcm_parent);
printf("parent %s ", classid);
if (ENABLE_FEATURE_CLEAN_UP)
free(classid);
@@ -418,9 +419,6 @@ static int print_class(const struct sockaddr_nl *who UNUSED_PARAM,
static int print_filter(const struct sockaddr_nl *who UNUSED_PARAM,
struct nlmsghdr *hdr, void *arg UNUSED_PARAM)
{
- struct tcmsg *msg = NLMSG_DATA(hdr);
- int len = hdr->nlmsg_len;
- struct rtattr * tb[TCA_MAX+1];
return 0;
}
@@ -463,14 +461,14 @@ int tc_main(int argc UNUSED_PARAM, char **argv)
obj = index_in_substrings(objects, *argv++);
- if (obj < OBJ_qdisc)
+ if (obj < 0)
bb_show_usage();
if (!*argv)
cmd = CMD_show; /* list is the default */
else {
cmd = index_in_substrings(commands, *argv);
if (cmd < 0)
- bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
+ invarg_1_to_2(*argv, argv[-1]);
argv++;
}
memset(&msg, 0, sizeof(msg));
@@ -493,7 +491,7 @@ int tc_main(int argc UNUSED_PARAM, char **argv)
NEXT_ARG();
/* We don't care about duparg2("qdisc handle",*argv) for now */
if (get_qdisc_handle(&filter_qdisc, *argv))
- invarg(*argv, "qdisc");
+ invarg_1_to_2(*argv, "qdisc");
} else
if (obj != OBJ_qdisc
&& (arg == ARG_root
@@ -503,7 +501,7 @@ int tc_main(int argc UNUSED_PARAM, char **argv)
) {
/* nothing */
} else {
- invarg(*argv, "command");
+ invarg_1_to_2(*argv, "command");
}
NEXT_ARG();
if (arg == ARG_root) {
@@ -517,7 +515,7 @@ int tc_main(int argc UNUSED_PARAM, char **argv)
if (msg.tcm_parent)
duparg(*argv, "parent");
if (get_tc_classid(&handle, *argv))
- invarg(*argv, "parent");
+ invarg_1_to_2(*argv, "parent");
msg.tcm_parent = handle;
if (obj == OBJ_filter)
filter_parent = handle;
@@ -526,7 +524,8 @@ int tc_main(int argc UNUSED_PARAM, char **argv)
duparg(*argv, "handle");
/* reject LONG_MIN || LONG_MAX */
/* TODO: for fw
- if ((slash = strchr(handle, '/')) != NULL)
+ slash = strchr(handle, '/');
+ if (slash != NULL)
*slash = '\0';
*/
msg.tcm_handle = get_u32(*argv, "handle");
@@ -541,7 +540,7 @@ int tc_main(int argc UNUSED_PARAM, char **argv)
if (filter_proto)
duparg(*argv, "protocol");
if (ll_proto_a2n(&tmp, *argv))
- invarg(*argv, "protocol");
+ invarg_1_to_2(*argv, "protocol");
filter_proto = tmp;
}
}
diff --git a/release/src/router/busybox/networking/tcpudp.c b/release/src/router/busybox/networking/tcpudp.c
index 3df6a98d8c..31bc704594 100644
--- a/release/src/router/busybox/networking/tcpudp.c
+++ b/release/src/router/busybox/networking/tcpudp.c
@@ -67,6 +67,7 @@
//usage: "\n -v Verbose"
#include "libbb.h"
+#include "common_bufsiz.h"
/* Wants <limits.h> etc, thus included after libbb.h: */
#ifdef __linux__
@@ -91,7 +92,7 @@ struct globals {
char **env_cur;
char *env_var[1]; /* actually bigger */
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define verbose (G.verbose )
#define max_per_host (G.max_per_host)
#define cur_per_host (G.cur_per_host)
@@ -100,6 +101,7 @@ struct globals {
#define env_cur (G.env_cur )
#define env_var (G.env_var )
#define INIT_G() do { \
+ setup_common_bufsiz(); \
cmax = 30; \
env_cur = &env_var[0]; \
} while (0)
diff --git a/release/src/router/busybox/networking/telnet.c b/release/src/router/busybox/networking/telnet.c
index e8e51dce4a..d2daf5c8ce 100644
--- a/release/src/router/busybox/networking/telnet.c
+++ b/release/src/router/busybox/networking/telnet.c
@@ -39,6 +39,7 @@
#include <arpa/telnet.h>
#include <netinet/in.h>
#include "libbb.h"
+#include "common_bufsiz.h"
#ifdef __BIONIC__
/* should be in arpa/telnet.h */
@@ -108,11 +109,10 @@ struct globals {
struct termios termios_def;
struct termios termios_raw;
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define INIT_G() do { \
- struct G_sizecheck { \
- char G_sizecheck[sizeof(G) > COMMON_BUFSIZE ? -1 : 1]; \
- }; \
+ setup_common_bufsiz(); \
+ BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
} while (0)
@@ -125,12 +125,10 @@ static void subneg(byte c);
static void iac_flush(void)
{
- write(netfd, G.iacbuf, G.iaclen);
+ full_write(netfd, G.iacbuf, G.iaclen);
G.iaclen = 0;
}
-#define write_str(fd, str) write(fd, str, sizeof(str) - 1)
-
static void doexit(int ev) NORETURN;
static void doexit(int ev)
{
@@ -145,7 +143,7 @@ static void con_escape(void)
if (bb_got_signal) /* came from line mode... go raw */
rawmode();
- write_str(1, "\r\nConsole escape. Commands are:\r\n\n"
+ full_write1_str("\r\nConsole escape. Commands are:\r\n\n"
" l go to line mode\r\n"
" c go to character mode\r\n"
" z suspend telnet\r\n"
@@ -176,7 +174,7 @@ static void con_escape(void)
doexit(EXIT_SUCCESS);
}
- write_str(1, "continuing...\r\n");
+ full_write1_str("continuing...\r\n");
if (bb_got_signal)
cookmode();
@@ -186,40 +184,35 @@ static void con_escape(void)
static void handle_net_output(int len)
{
- /* here we could do smart tricks how to handle 0xFF:s in output
- * stream like writing twice every sequence of FF:s (thus doing
- * many write()s. But I think interactive telnet application does
- * not need to be 100% 8-bit clean, so changing every 0xff:s to
- * 0x7f:s
- *
- * 2002-mar-21, Przemyslaw Czerpak (druzus@polbox.com)
- * I don't agree.
- * first - I cannot use programs like sz/rz
- * second - the 0x0D is sent as one character and if the next
- * char is 0x0A then it's eaten by a server side.
- * third - why do you have to make 'many write()s'?
- * I don't understand.
- * So I implemented it. It's really useful for me. I hope that
- * other people will find it interesting too.
- */
byte outbuf[2 * DATABUFSIZE];
- byte *p = (byte*)G.buf;
- int j = 0;
+ byte *dst = outbuf;
+ byte *src = (byte*)G.buf;
+ byte *end = src + len;
- for (; len > 0; len--, p++) {
- byte c = *p;
+ while (src < end) {
+ byte c = *src++;
if (c == 0x1d) {
con_escape();
return;
}
- outbuf[j++] = c;
+ *dst = c;
if (c == IAC)
- outbuf[j++] = c; /* IAC -> IAC IAC */
- else if (c == '\r')
- outbuf[j++] = '\0'; /* CR -> CR NUL */
+ *++dst = c; /* IAC -> IAC IAC */
+ else
+ if (c == '\r' || c == '\n') {
+ /* Enter key sends '\r' in raw mode and '\n' in cooked one.
+ *
+ * See RFC 1123 3.3.1 Telnet End-of-Line Convention.
+ * Using CR LF instead of other allowed possibilities
+ * like CR NUL - easier to talk to HTTP/SMTP servers.
+ */
+ *dst = '\r'; /* Enter -> CR LF */
+ *++dst = '\n';
+ }
+ dst++;
}
- if (j > 0)
- full_write(netfd, outbuf, j);
+ if (dst - outbuf != 0)
+ full_write(netfd, outbuf, dst - outbuf);
}
static void handle_net_input(int len)
@@ -388,30 +381,31 @@ static void put_iac_naws(byte c, int x, int y)
put_iac(SB);
put_iac(c);
- put_iac((x >> 8) & 0xff);
- put_iac(x & 0xff);
- put_iac((y >> 8) & 0xff);
- put_iac(y & 0xff);
+ /* "... & 0xff" implicitly done below */
+ put_iac(x >> 8);
+ put_iac(x);
+ put_iac(y >> 8);
+ put_iac(y);
put_iac(IAC);
put_iac(SE);
}
#endif
-static char const escapecharis[] ALIGN1 = "\r\nEscape character is ";
-
static void setConMode(void)
{
if (G.telflags & UF_ECHO) {
if (G.charmode == CHM_TRY) {
G.charmode = CHM_ON;
- printf("\r\nEntering character mode%s'^]'.\r\n", escapecharis);
+ printf("\r\nEntering %s mode"
+ "\r\nEscape character is '^%c'.\r\n", "character", ']');
rawmode();
}
} else {
if (G.charmode != CHM_OFF) {
G.charmode = CHM_OFF;
- printf("\r\nEntering line mode%s'^C'.\r\n", escapecharis);
+ printf("\r\nEntering %s mode"
+ "\r\nEscape character is '^%c'.\r\n", "line", 'C');
cookmode();
}
}
@@ -629,7 +623,7 @@ int telnet_main(int argc UNUSED_PARAM, char **argv)
xmove_fd(create_and_connect_stream_or_die(host, port), netfd);
- setsockopt(netfd, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));
+ setsockopt_keepalive(netfd);
signal(SIGINT, record_signo);
diff --git a/release/src/router/busybox/networking/telnetd.c b/release/src/router/busybox/networking/telnetd.c
index 0bc595ab9c..a4f19ee1dc 100644
--- a/release/src/router/busybox/networking/telnetd.c
+++ b/release/src/router/busybox/networking/telnetd.c
@@ -44,6 +44,7 @@
#define DEBUG 0
#include "libbb.h"
+#include "common_bufsiz.h"
#include <syslog.h>
#if DEBUG
@@ -82,8 +83,9 @@ struct globals {
const char *issuefile;
int maxfd;
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define INIT_G() do { \
+ setup_common_bufsiz(); \
G.loginpath = "/bin/login"; \
G.issuefile = "/etc/issue.net"; \
} while (0)
@@ -125,6 +127,7 @@ remove_iacs(struct tsession *ts, int *pnum_totty)
/* We map \r\n ==> \r for pragmatic reasons.
* Many client implementations send \r\n when
* the user hits the CarriageReturn key.
+ * See RFC 1123 3.3.1 Telnet End-of-Line Convention.
*/
if (c == '\r' && ptr < end && (*ptr == '\n' || *ptr == '\0'))
ptr++;
@@ -264,7 +267,7 @@ make_new_session(
close_on_exec_on(fd);
/* SO_KEEPALIVE by popular demand */
- setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));
+ setsockopt_keepalive(sock);
#if ENABLE_FEATURE_TELNETD_STANDALONE
ts->sockfd_read = sock;
ndelay_on(sock);
@@ -329,8 +332,7 @@ make_new_session(
/* Careful - we are after vfork! */
/* Restore default signal handling ASAP */
- bb_signals((1 << SIGCHLD) + (1 << SIGPIPE), SIG_DFL);
- signal(SIGINT, SIG_DFL);
+ bb_signals((1 << SIGCHLD) + (1 << SIGPIPE) + (1 << SIGINT), SIG_DFL);
pid = getpid();
@@ -462,15 +464,7 @@ static void handle_sigchld(int sig UNUSED_PARAM)
while (ts) {
if (ts->shell_pid == pid) {
ts->shell_pid = -1;
-// man utmp:
-// When init(8) finds that a process has exited, it locates its utmp entry
-// by ut_pid, sets ut_type to DEAD_PROCESS, and clears ut_user, ut_host
-// and ut_time with null bytes.
-// [same applies to other processes which maintain utmp entries, like telnetd]
-//
-// We do not bother actually clearing fields:
-// it might be interesting to know who was logged in and from where
- update_utmp(pid, DEAD_PROCESS, /*tty_name:*/ NULL, /*username:*/ NULL, /*hostname:*/ NULL);
+ update_utmp_DEAD_PROCESS(pid);
break;
}
ts = ts->next;
@@ -739,7 +733,7 @@ int telnetd_main(int argc UNUSED_PARAM, char **argv)
continue;
kill_session:
if (ts->shell_pid > 0)
- update_utmp(ts->shell_pid, DEAD_PROCESS, /*tty_name:*/ NULL, /*username:*/ NULL, /*hostname:*/ NULL);
+ update_utmp_DEAD_PROCESS(ts->shell_pid);
free_session(ts);
ts = next;
}
diff --git a/release/src/router/busybox/networking/telnetd.ctrlSQ.patch b/release/src/router/busybox/networking/telnetd.ctrlSQ.patch
index 7060e1c6ed..bc26d2279e 100644
--- a/release/src/router/busybox/networking/telnetd.ctrlSQ.patch
+++ b/release/src/router/busybox/networking/telnetd.ctrlSQ.patch
@@ -94,9 +94,9 @@ exceptional conditions.
#endif
+#ifdef TIOCPKT
+ int control;
-+ static const char lflow_on[] =
++ static const char lflow_on[] ALIGN1 =
+ {IAC, SB, TELOPT_LFLOW, LFLOW_ON, IAC, SE};
-+ static const char lflow_off[] =
++ static const char lflow_off[] ALIGN1 =
+ {IAC, SB, TELOPT_LFLOW, LFLOW_OFF, IAC, SE};
+# define RESERVED sizeof(lflow_on)
+#else
diff --git a/release/src/router/busybox/networking/tftp.c b/release/src/router/busybox/networking/tftp.c
index ce48a1edd5..e879c4674c 100644
--- a/release/src/router/busybox/networking/tftp.c
+++ b/release/src/router/busybox/networking/tftp.c
@@ -51,6 +51,7 @@
//usage: "\n -l Log to syslog (inetd mode requires this)"
#include "libbb.h"
+#include "common_bufsiz.h"
#include <syslog.h>
#if ENABLE_FEATURE_TFTP_GET || ENABLE_FEATURE_TFTP_PUT
@@ -116,9 +117,11 @@ enum {
struct globals {
/* u16 TFTP_ERROR; u16 reason; both network-endian, then error text: */
uint8_t error_pkt[4 + 32];
- char *user_opt;
- /* used in tftpd_main(), a bit big for stack: */
- char block_buf[TFTP_BLKSIZE_DEFAULT];
+ struct passwd *pw;
+ /* Used in tftpd_main() for initial packet */
+ /* Some HP PA-RISC firmware always sends fixed 516-byte requests */
+ char block_buf[516];
+ char block_buf_tail[1];
#if ENABLE_FEATURE_TFTP_PROGRESS_BAR
off_t pos;
off_t size;
@@ -126,17 +129,14 @@ struct globals {
bb_progress_t pmt;
#endif
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
-struct BUG_G_too_big {
- char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
-};
-#define block_buf (G.block_buf )
-#define user_opt (G.user_opt )
-#define error_pkt (G.error_pkt )
-#define INIT_G() do { } while (0)
+#define G (*(struct globals*)bb_common_bufsiz1)
+#define INIT_G() do { \
+ setup_common_bufsiz(); \
+ BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
+} while (0)
-#define error_pkt_reason (error_pkt[3])
-#define error_pkt_str (error_pkt + 4)
+#define G_error_pkt_reason (G.error_pkt[3])
+#define G_error_pkt_str ((char*)(G.error_pkt + 4))
#if ENABLE_FEATURE_TFTP_PROGRESS_BAR
static void tftp_progress_update(void)
@@ -272,12 +272,11 @@ static int tftp_protocol(
xconnect(socket_fd, &peer_lsa->u.sa, peer_lsa->len);
/* Is there an error already? Send pkt and bail out */
- if (error_pkt_reason || error_pkt_str[0])
+ if (G_error_pkt_reason || G_error_pkt_str[0])
goto send_err_pkt;
- if (user_opt) {
- struct passwd *pw = xgetpwnam(user_opt);
- change_identity(pw); /* initgroups, setgid, setuid */
+ if (G.pw) {
+ change_identity(G.pw); /* initgroups, setgid, setuid */
}
}
@@ -329,8 +328,8 @@ static int tftp_protocol(
/* Open file (must be after changing user) */
local_fd = open(local_file, open_mode, 0666);
if (local_fd < 0) {
- error_pkt_reason = ERR_NOFILE;
- strcpy((char*)error_pkt_str, "can't open file");
+ G_error_pkt_reason = ERR_NOFILE;
+ strcpy(G_error_pkt_str, "can't open file");
goto send_err_pkt;
}
/* gcc 4.3.1 would NOT optimize it out as it should! */
@@ -350,7 +349,6 @@ static int tftp_protocol(
* as if it is "block 0" */
block_nr = 0;
}
-
} else { /* tftp */
/* Open file (must be after changing user) */
local_fd = CMD_GET(option_mask32) ? STDOUT_FILENO : STDIN_FILENO;
@@ -575,7 +573,7 @@ static int tftp_protocol(
if (res) {
blksize = tftp_blksize_check(res, blksize);
if (blksize < 0) {
- error_pkt_reason = ERR_BAD_OPT;
+ G_error_pkt_reason = ERR_BAD_OPT;
goto send_err_pkt;
}
io_bufsize = blksize + 4;
@@ -614,8 +612,8 @@ static int tftp_protocol(
if (recv_blk == block_nr) {
int sz = full_write(local_fd, &rbuf[4], len - 4);
if (sz != len - 4) {
- strcpy((char*)error_pkt_str, bb_msg_write_error);
- error_pkt_reason = ERR_WRITE;
+ strcpy(G_error_pkt_str, bb_msg_write_error);
+ G_error_pkt_reason = ERR_WRITE;
goto send_err_pkt;
}
if (sz != blksize) {
@@ -664,12 +662,12 @@ static int tftp_protocol(
return finished == 0; /* returns 1 on failure */
send_read_err_pkt:
- strcpy((char*)error_pkt_str, bb_msg_read_error);
+ strcpy(G_error_pkt_str, bb_msg_read_error);
send_err_pkt:
- if (error_pkt_str[0])
- bb_error_msg("%s", (char*)error_pkt_str);
- error_pkt[1] = TFTP_ERROR;
- xsendto(socket_fd, error_pkt, 4 + 1 + strlen((char*)error_pkt_str),
+ if (G_error_pkt_str[0])
+ bb_error_msg("%s", G_error_pkt_str);
+ G.error_pkt[1] = TFTP_ERROR;
+ xsendto(socket_fd, G.error_pkt, 4 + 1 + strlen(G_error_pkt_str),
&peer_lsa->u.sa, peer_lsa->len);
return EXIT_FAILURE;
#undef remote_file
@@ -761,7 +759,8 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
{
len_and_sockaddr *our_lsa;
len_and_sockaddr *peer_lsa;
- char *local_file, *mode;
+ char *mode, *user_opt;
+ char *local_file = local_file;
const char *error_msg;
int opt, result, opcode;
IF_FEATURE_TFTP_BLOCKSIZE(int blksize = TFTP_BLKSIZE_DEFAULT;)
@@ -789,18 +788,24 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
openlog(applet_name, LOG_PID, LOG_DAEMON);
logmode = LOGMODE_SYSLOG;
}
+ if (opt & TFTPD_OPT_u) {
+ /* Must be before xchroot */
+ G.pw = xgetpwnam(user_opt);
+ }
if (argv[0]) {
xchroot(argv[0]);
}
- result = recv_from_to(STDIN_FILENO, block_buf, sizeof(block_buf),
+ result = recv_from_to(STDIN_FILENO,
+ G.block_buf, sizeof(G.block_buf) + 1,
+ /* ^^^ sizeof+1 to reliably detect oversized input */
0 /* flags */,
&peer_lsa->u.sa, &our_lsa->u.sa, our_lsa->len);
error_msg = "malformed packet";
- opcode = ntohs(*(uint16_t*)block_buf);
- if (result < 4 || result >= sizeof(block_buf)
- || block_buf[result-1] != '\0'
+ opcode = ntohs(*(uint16_t*)G.block_buf);
+ if (result < 4 || result > sizeof(G.block_buf)
+ /*|| G.block_buf[result-1] != '\0' - bug compatibility, see below */
|| (IF_FEATURE_TFTP_PUT(opcode != TFTP_RRQ) /* not download */
IF_GETPUT(&&)
IF_FEATURE_TFTP_GET(opcode != TFTP_WRQ) /* not upload */
@@ -808,27 +813,34 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
) {
goto err;
}
- local_file = block_buf + 2;
+ /* Some HP PA-RISC firmware always sends fixed 516-byte requests,
+ * with trailing garbage.
+ * Support that by not requiring NUL to be the last byte (see above).
+ * To make strXYZ() ops safe, force NUL termination:
+ */
+ G.block_buf_tail[0] = '\0';
+
+ local_file = G.block_buf + 2;
if (local_file[0] == '.' || strstr(local_file, "/.")) {
error_msg = "dot in file name";
goto err;
}
mode = local_file + strlen(local_file) + 1;
/* RFC 1350 says mode string is case independent */
- if (mode >= block_buf + result || strcasecmp(mode, "octet") != 0) {
+ if (mode >= G.block_buf + result || strcasecmp(mode, "octet") != 0) {
goto err;
}
# if ENABLE_FEATURE_TFTP_BLOCKSIZE
{
char *res;
char *opt_str = mode + sizeof("octet");
- int opt_len = block_buf + result - opt_str;
+ int opt_len = G.block_buf + result - opt_str;
if (opt_len > 0) {
res = tftp_get_option("blksize", opt_str, opt_len);
if (res) {
blksize = tftp_blksize_check(res, 65564);
if (blksize < 0) {
- error_pkt_reason = ERR_BAD_OPT;
+ G_error_pkt_reason = ERR_BAD_OPT;
/* will just send error pkt */
goto do_proto;
}
@@ -846,7 +858,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
if (!ENABLE_FEATURE_TFTP_PUT || opcode == TFTP_WRQ) {
if (opt & TFTPD_OPT_r) {
/* This would mean "disk full" - not true */
- /*error_pkt_reason = ERR_WRITE;*/
+ /*G_error_pkt_reason = ERR_WRITE;*/
error_msg = bb_msg_write_error;
goto err;
}
@@ -855,7 +867,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
IF_GETPUT(option_mask32 |= TFTP_OPT_PUT;) /* will send file's data */
}
- /* NB: if error_pkt_str or error_pkt_reason is set up,
+ /* NB: if G_error_pkt_str or G_error_pkt_reason is set up,
* tftp_protocol() just sends one error pkt and returns */
do_proto:
@@ -870,7 +882,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
return result;
err:
- strcpy((char*)error_pkt_str, error_msg);
+ strcpy(G_error_pkt_str, error_msg);
goto do_proto;
}
diff --git a/release/src/router/busybox/networking/traceroute.c b/release/src/router/busybox/networking/traceroute.c
index c6c5bccde5..b98aed3b49 100644
--- a/release/src/router/busybox/networking/traceroute.c
+++ b/release/src/router/busybox/networking/traceroute.c
@@ -211,60 +211,62 @@
*/
//usage:#define traceroute_trivial_usage
-//usage: "[-"IF_TRACEROUTE6("46")"FIldnrv] [-f 1ST_TTL] [-m MAXTTL] [-p PORT] [-q PROBES]\n"
-//usage: " [-s SRC_IP] [-t TOS] [-w WAIT_SEC] [-g GATEWAY] [-i IFACE]\n"
+//usage: "[-"IF_TRACEROUTE6("46")"FIlnrv] [-f 1ST_TTL] [-m MAXTTL] [-q PROBES] [-p PORT]\n"
+//usage: " [-t TOS] [-w WAIT_SEC]"
+//usage: IF_FEATURE_TRACEROUTE_SOURCE_ROUTE(" [-g GATEWAY]")" [-s SRC_IP] [-i IFACE]\n"
//usage: " [-z PAUSE_MSEC] HOST [BYTES]"
//usage:#define traceroute_full_usage "\n\n"
//usage: "Trace the route to HOST\n"
//usage: IF_TRACEROUTE6(
//usage: "\n -4,-6 Force IP or IPv6 name resolution"
//usage: )
-//usage: "\n -F Set the don't fragment bit"
+//usage: "\n -F Set don't fragment bit"
+//usage: IF_FEATURE_TRACEROUTE_USE_ICMP(
//usage: "\n -I Use ICMP ECHO instead of UDP datagrams"
-//usage: "\n -l Display the TTL value of the returned packet"
-//usage: "\n -d Set SO_DEBUG options to socket"
+//usage: )
+//usage: "\n -l Display TTL value of the returned packet"
+//Currently disabled (TRACEROUTE_SO_DEBUG==0)
+////usage: "\n -d Set SO_DEBUG options to socket"
//usage: "\n -n Print numeric addresses"
//usage: "\n -r Bypass routing tables, send directly to HOST"
+//usage: IF_FEATURE_TRACEROUTE_VERBOSE(
//usage: "\n -v Verbose"
-//usage: "\n -m Max time-to-live (max number of hops)"
-//usage: "\n -p Base UDP port number used in probes"
+//usage: )
+//usage: "\n -f N First number of hops (default 1)"
+//usage: "\n -m N Max number of hops"
+//usage: "\n -q N Number of probes per hop (default 3)"
+//usage: "\n -p N Base UDP port number used in probes"
//usage: "\n (default 33434)"
-//usage: "\n -q Number of probes per TTL (default 3)"
-//usage: "\n -s IP address to use as the source address"
-//usage: "\n -t Type-of-service in probe packets (default 0)"
-//usage: "\n -w Time in seconds to wait for a response (default 3)"
-//usage: "\n -g Loose source route gateway (8 max)"
+//usage: "\n -s IP Source address"
+//usage: "\n -i IFACE Source interface"
+//usage: "\n -t N Type-of-service in probe packets (default 0)"
+//usage: "\n -w SEC Time to wait for a response (default 3)"
+//usage: "\n -g IP Loose source route gateway (8 max)"
//usage:
//usage:#define traceroute6_trivial_usage
-//usage: "[-dnrv] [-m MAXTTL] [-p PORT] [-q PROBES]\n"
-//usage: " [-s SRC_IP] [-t TOS] [-w WAIT_SEC] [-i IFACE]\n"
+//usage: "[-nrv] [-m MAXTTL] [-q PROBES] [-p PORT]\n"
+//usage: " [-t TOS] [-w WAIT_SEC] [-s SRC_IP] [-i IFACE]\n"
//usage: " HOST [BYTES]"
//usage:#define traceroute6_full_usage "\n\n"
//usage: "Trace the route to HOST\n"
-//usage: "\n -d Set SO_DEBUG options to socket"
+//Currently disabled (TRACEROUTE_SO_DEBUG==0)
+////usage: "\n -d Set SO_DEBUG options to socket"
//usage: "\n -n Print numeric addresses"
//usage: "\n -r Bypass routing tables, send directly to HOST"
+//usage: IF_FEATURE_TRACEROUTE_VERBOSE(
//usage: "\n -v Verbose"
-//usage: "\n -m Max time-to-live (max number of hops)"
-//usage: "\n -p Base UDP port number used in probes"
-//usage: "\n (default is 33434)"
-//usage: "\n -q Number of probes per TTL (default 3)"
-//usage: "\n -s IP address to use as the source address"
-//usage: "\n -t Type-of-service in probe packets (default 0)"
-//usage: "\n -w Time in seconds to wait for a response (default 3)"
+//usage: )
+//usage: "\n -m N Max number of hops"
+//usage: "\n -q N Number of probes per hop (default 3)"
+//usage: "\n -p N Base UDP port number used in probes"
+//usage: "\n (default 33434)"
+//usage: "\n -s IP Source address"
+//usage: "\n -i IFACE Source interface"
+//usage: "\n -t N Type-of-service in probe packets (default 0)"
+//usage: "\n -w SEC Time wait for a response (default 3)"
#define TRACEROUTE_SO_DEBUG 0
-/* TODO: undefs were uncommented - ??! we have config system for that! */
-/* probably ok to remove altogether */
-//#undef CONFIG_FEATURE_TRACEROUTE_VERBOSE
-//#define CONFIG_FEATURE_TRACEROUTE_VERBOSE
-//#undef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
-//#define CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
-//#undef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
-//#define CONFIG_FEATURE_TRACEROUTE_USE_ICMP
-
-
#include <net/if.h>
#include <arpa/inet.h>
#include <netinet/in.h>
@@ -290,9 +292,10 @@
#endif
-#define OPT_STRING "FIlnrdvxt:i:m:p:q:s:w:z:f:" \
- IF_FEATURE_TRACEROUTE_SOURCE_ROUTE("g:") \
- "4" IF_TRACEROUTE6("6")
+#define OPT_STRING \
+ "FIlnrdvxt:i:m:p:q:s:w:z:f:" \
+ IF_FEATURE_TRACEROUTE_SOURCE_ROUTE("g:") \
+ "4" IF_TRACEROUTE6("6")
enum {
OPT_DONT_FRAGMNT = (1 << 0), /* F */
OPT_USE_ICMP = (1 << 1) * ENABLE_FEATURE_TRACEROUTE_USE_ICMP, /* I */
@@ -386,15 +389,6 @@ struct globals {
#define outudp ((struct udphdr *)(outip + 1))
-/* libbb candidate? tftp uses this idiom too */
-static len_and_sockaddr* dup_sockaddr(const len_and_sockaddr *lsa)
-{
- len_and_sockaddr *new_lsa = xzalloc(LSA_LEN_SIZE + lsa->len);
- memcpy(new_lsa, lsa, LSA_LEN_SIZE + lsa->len);
- return new_lsa;
-}
-
-
static int
wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to, unsigned *timestamp_us, int *left_ms)
{
@@ -479,18 +473,18 @@ send_probe(int seq, int ttl)
#if ENABLE_TRACEROUTE6
if (dest_lsa->u.sa.sa_family == AF_INET6) {
- res = setsockopt(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
- if (res < 0)
- bb_perror_msg_and_die("setsockopt UNICAST_HOPS %d", ttl);
+ res = setsockopt_int(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, ttl);
+ if (res != 0)
+ bb_perror_msg_and_die("setsockopt(%s) %d", "UNICAST_HOPS", ttl);
out = outip;
len = packlen;
} else
#endif
{
#if defined IP_TTL
- res = setsockopt(sndsock, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
- if (res < 0)
- bb_perror_msg_and_die("setsockopt ttl %d", ttl);
+ res = setsockopt_int(sndsock, IPPROTO_IP, IP_TTL, ttl);
+ if (res != 0)
+ bb_perror_msg_and_die("setsockopt(%s) %d", "TTL", ttl);
#endif
out = outicmp;
len = packlen - sizeof(*outip);
@@ -503,7 +497,7 @@ send_probe(int seq, int ttl)
res = xsendto(sndsock, out, len, &dest_lsa->u.sa, dest_lsa->len);
if (res != len)
- bb_info_msg("sent %d octets, ret=%d", len, res);
+ bb_error_msg("sent %d octets, ret=%d", len, res);
}
#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
@@ -790,7 +784,9 @@ static int
common_traceroute_main(int op, char **argv)
{
int minpacket;
+#ifdef IP_TOS
int tos = 0;
+#endif
int max_ttl = 30;
int nprobes = 3;
int first_ttl = 1;
@@ -804,6 +800,7 @@ common_traceroute_main(int op, char **argv)
char *waittime_str;
char *pausemsecs_str;
char *first_ttl_str;
+ char *dest_str;
#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
llist_t *source_route_list = NULL;
int lsrr = 0;
@@ -836,8 +833,10 @@ common_traceroute_main(int op, char **argv)
if (op & OPT_IP_CHKSUM)
bb_error_msg("warning: ip checksums disabled");
#endif
+#ifdef IP_TOS
if (op & OPT_TOS)
tos = xatou_range(tos_str, 0, 255);
+#endif
if (op & OPT_MAX_TTL)
max_ttl = xatou_range(max_ttl_str, 1, 255);
if (op & OPT_PORT)
@@ -911,18 +910,15 @@ common_traceroute_main(int op, char **argv)
#if TRACEROUTE_SO_DEBUG
if (op & OPT_DEBUG)
- setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG,
- &const_int_1, sizeof(const_int_1));
+ setsockopt_SOL_SOCKET_1(rcvsock, SO_DEBUG);
#endif
if (op & OPT_BYPASS_ROUTE)
- setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE,
- &const_int_1, sizeof(const_int_1));
+ setsockopt_SOL_SOCKET_1(rcvsock, SO_DONTROUTE);
#if ENABLE_TRACEROUTE6
if (af == AF_INET6) {
- static const int two = 2;
- if (setsockopt(rcvsock, SOL_RAW, IPV6_CHECKSUM, &two, sizeof(two)) < 0)
- bb_perror_msg_and_die("setsockopt RAW_CHECKSUM");
+ if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0)
+ bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM");
xmove_fd(xsocket(af, SOCK_DGRAM, 0), sndsock);
} else
#endif
@@ -959,28 +955,25 @@ common_traceroute_main(int op, char **argv)
}
#ifdef SO_SNDBUF
- if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, &packlen, sizeof(packlen)) < 0) {
- bb_perror_msg_and_die("SO_SNDBUF");
+ if (setsockopt_SOL_SOCKET_int(sndsock, SO_SNDBUF, packlen) != 0) {
+ bb_perror_msg_and_die("setsockopt(%s)", "SO_SNDBUF");
}
#endif
#ifdef IP_TOS
- if ((op & OPT_TOS) && setsockopt(sndsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) {
- bb_perror_msg_and_die("setsockopt tos %d", tos);
+ if ((op & OPT_TOS) && setsockopt_int(sndsock, IPPROTO_IP, IP_TOS, tos) != 0) {
+ bb_perror_msg_and_die("setsockopt(%s) %d", "TOS", tos);
}
#endif
#ifdef IP_DONTFRAG
if (op & OPT_DONT_FRAGMNT)
- setsockopt(sndsock, IPPROTO_IP, IP_DONTFRAG,
- &const_int_1, sizeof(const_int_1));
+ setsockopt_1(sndsock, IPPROTO_IP, IP_DONTFRAG);
#endif
#if TRACEROUTE_SO_DEBUG
if (op & OPT_DEBUG)
- setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
- &const_int_1, sizeof(const_int_1));
+ setsockopt_SOL_SOCKET_1(sndsock, SO_DEBUG);
#endif
if (op & OPT_BYPASS_ROUTE)
- setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
- &const_int_1, sizeof(const_int_1));
+ setsockopt_SOL_SOCKET_1(sndsock, SO_DONTROUTE);
outip = xzalloc(packlen);
@@ -1050,13 +1043,17 @@ common_traceroute_main(int op, char **argv)
xsetgid(getgid());
xsetuid(getuid());
- printf("traceroute to %s (%s)", argv[0],
- xmalloc_sockaddr2dotted_noport(&dest_lsa->u.sa));
+ dest_str = xmalloc_sockaddr2dotted_noport(&dest_lsa->u.sa);
+ printf("traceroute to %s (%s)", argv[0], dest_str);
+ if (ENABLE_FEATURE_CLEAN_UP) {
+ free(dest_str);
+ }
+
if (op & OPT_SOURCE)
printf(" from %s", source);
printf(", %d hops max, %d byte packets\n", max_ttl, packlen);
- from_lsa = dup_sockaddr(dest_lsa);
+ from_lsa = xmemdup(dest_lsa, LSA_LEN_SIZE + dest_lsa->len);
lastaddr = xzalloc(dest_lsa->len);
to = xzalloc(dest_lsa->len);
seq = 0;
@@ -1207,6 +1204,12 @@ common_traceroute_main(int op, char **argv)
}
}
+ if (ENABLE_FEATURE_CLEAN_UP) {
+ free(to);
+ free(lastaddr);
+ free(from_lsa);
+ }
+
return 0;
}
diff --git a/release/src/router/busybox/networking/tunctl.c b/release/src/router/busybox/networking/tunctl.c
index 3a0870eb5d..941e8bbd30 100644
--- a/release/src/router/busybox/networking/tunctl.c
+++ b/release/src/router/busybox/networking/tunctl.c
@@ -82,7 +82,7 @@ int tunctl_main(int argc UNUSED_PARAM, char **argv)
// delete?
if (opts & OPT_d) {
IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)0);
- bb_info_msg("Set '%s' %spersistent", ifr.ifr_name, "non");
+ printf("Set '%s' nonpersistent\n", ifr.ifr_name);
return EXIT_SUCCESS;
}
diff --git a/release/src/router/busybox/networking/udhcp/Config.src b/release/src/router/busybox/networking/udhcp/Config.src
index 35536d4a83..34b6031431 100644
--- a/release/src/router/busybox/networking/udhcp/Config.src
+++ b/release/src/router/busybox/networking/udhcp/Config.src
@@ -107,7 +107,7 @@ config UDHCP_DEBUG
int "Maximum verbosity level for udhcp applets (0..9)"
default 9
range 0 9
- depends on UDHCPD || UDHCPC || DHCPRELAY || DHCP6C || DHCP6RELAY
+ depends on UDHCPD || UDHCPC || DHCPRELAY
help
Verbosity can be increased with multiple -v options.
This option controls how high it can be cranked up.
@@ -115,10 +115,18 @@ config UDHCP_DEBUG
Bigger values result in bigger code. Levels above 1
are very verbose and useful for debugging only.
+config FEATURE_UDHCP_RFC5969
+ bool "Support for RFC5969 IPv6 Rapid Deployment (6RD)"
+ default y
+ depends on UDHCPC && FEATURE_IPV6
+ help
+ If selected, client will support passing of 6rd delegated
+ prefix via option 212, specified in RFC 5969.
+
config FEATURE_UDHCP_RFC3397
bool "Support for RFC3397 domain search (experimental)"
default y
- depends on UDHCPD || UDHCPC || DHCP6C
+ depends on UDHCPD || UDHCPC
help
If selected, both client and server will support passing of domain
search lists via option 119, specified in RFC 3397,
@@ -163,27 +171,3 @@ config UDHCPC_SLACK_FOR_BUGGY_SERVERS
maximum size of entire IP packet, and sends packets which are
28 bytes too large.
Seednet (ISP) VDSL: sends packets 2 bytes too large.
-
-config DHCP6C
- bool "DHCPv6 client daemon (dhcp6c)"
- default n
- depends on PLATFORM_LINUX && FEATURE_IPV6
- help
- dhcp6c is a DHCPv6 client geared primarily toward embedded systems,
- while striving to be fully functional and RFC compliant.
-
-config FEATURE_DHCP6_AUTH
- bool "Support DHCPv6 messages authentication"
- default n
- depends on DHCP6C
- help
- If selected, client will support DHCPv6 messages authentication,
- currently HMAC-MD5 only.
-
-config DHCP6RELAY
- bool "dhcp6relay"
- default n
- depends on FEATURE_IPV6 && DHCP6C
- help
- dhcp6relay listens for DHCPv6 requests on one or more interfaces
- and forwards these requests to a different interface.
diff --git a/release/src/router/busybox/networking/udhcp/Kbuild.src b/release/src/router/busybox/networking/udhcp/Kbuild.src
index 100a6decef..b8767baea4 100644
--- a/release/src/router/busybox/networking/udhcp/Kbuild.src
+++ b/release/src/router/busybox/networking/udhcp/Kbuild.src
@@ -17,12 +17,5 @@ lib-$(CONFIG_UDHCPD) += dhcpd.o arpping.o files.o leases.o static_leases.o
lib-$(CONFIG_DUMPLEASES) += dumpleases.o
lib-$(CONFIG_DHCPRELAY) += dhcprelay.o
-lib-$(CONFIG_DHCP6C) += common6.o common.o
-
-lib-$(CONFIG_DHCP6C) += dhcp6c.o config6.o dhcp6c_script.o dhcp6c_ia.o if6.o timer.o
-lib-$(CONFIG_DHCP6RELAY) += dhcp6relay.o domain_codec.o
-
-lib-$(CONFIG_FEATURE_DHCP6_AUTH) += auth6.o
-
lib-$(CONFIG_FEATURE_UDHCPC_ARPING) += arpping.o
lib-$(CONFIG_FEATURE_UDHCP_RFC3397) += domain_codec.o
diff --git a/release/src/router/busybox/networking/udhcp/arpping.c b/release/src/router/busybox/networking/udhcp/arpping.c
index fad2283c3e..c980273161 100644
--- a/release/src/router/busybox/networking/udhcp/arpping.c
+++ b/release/src/router/busybox/networking/udhcp/arpping.c
@@ -132,6 +132,6 @@ int FAST_FUNC arpping(uint32_t test_nip,
ret:
close(s);
- log1("%srp reply received for this address", rv ? "No a" : "A");
+ log1("%srp reply received for this address", rv ? "no a" : "A");
return rv;
}
diff --git a/release/src/router/busybox/networking/udhcp/common.c b/release/src/router/busybox/networking/udhcp/common.c
index afe91338f9..02a9ec3453 100644
--- a/release/src/router/busybox/networking/udhcp/common.c
+++ b/release/src/router/busybox/networking/udhcp/common.c
@@ -62,11 +62,11 @@ const struct dhcp_optflag dhcp_optflags[] = {
{ OPTION_U16 , 0x84 }, /* DHCP_VLAN_ID */
{ OPTION_U8 , 0x85 }, /* DHCP_VLAN_PRIORITY */
#endif
- { OPTION_STRING , 0xd1 }, /* DHCP_PXE_CONF_FILE */
- { OPTION_STRING , 0xd2 }, /* DHCP_PXE_PATH_PREFIX */
-#if ENABLE_FEATURE_IPV6
+ { OPTION_STRING , 0xd1 }, /* DHCP_PXE_CONF_FILE */
+ { OPTION_STRING , 0xd2 }, /* DHCP_PXE_PATH_PREFIX */
+#if ENABLE_FEATURE_UDHCP_RFC5969
{ OPTION_6RD , 0xd4 }, /* DHCP_6RD */
- { OPTION_6RD , 0x96 }, /* DHCP_COMCAST_6RD */
+// { OPTION_6RD , 0x96 }, /* DHCP_COMCAST_6RD */
#endif
{ OPTION_STATIC_ROUTES | OPTION_LIST , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */
{ OPTION_STRING , 0xfc }, /* DHCP_WPAD */
@@ -135,9 +135,9 @@ const char dhcp_option_strings[] ALIGN1 =
#endif
"pxeconffile" "\0" /* DHCP_PXE_CONF_FILE */
"pxepathprefix" "\0" /* DHCP_PXE_PATH_PREFIX */
-#if ENABLE_FEATURE_IPV6
- "ip6rd" "\0" /* DHCP_COMCAST_6RD */
+#if ENABLE_FEATURE_UDHCP_RFC5969
"ip6rd" "\0" /* DHCP_6RD */
+// "ip6rd" "\0" /* DHCP_COMCAST_6RD */
#endif
"msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */
"wpad" "\0" /* DHCP_WPAD */
@@ -148,7 +148,7 @@ const char dhcp_option_strings[] ALIGN1 =
* udhcp_str2optset: to determine how many bytes to allocate.
* xmalloc_optname_optval: to estimate string length
* from binary option length: (option[LEN] / dhcp_option_lengths[opt_type])
- * is the number of elements, multiply in by one element's string width
+ * is the number of elements, multiply it by one element's string width
* (len_of_option_as_string[opt_type]) and you know how wide string you need.
*/
const uint8_t dhcp_option_lengths[] ALIGN1 = {
@@ -168,8 +168,19 @@ const uint8_t dhcp_option_lengths[] ALIGN1 = {
[OPTION_S32] = 4,
/* Just like OPTION_STRING, we use minimum length here */
[OPTION_STATIC_ROUTES] = 5,
-#if ENABLE_FEATURE_IPV6
- [OPTION_6RD] = 22, /* ignored by udhcp_str2optset */
+#if ENABLE_FEATURE_UDHCP_RFC5969
+ [OPTION_6RD] = 12, /* ignored by udhcp_str2optset */
+ /* The above value was chosen as follows:
+ * len_of_option_as_string[] for this option is >60: it's a string of the form
+ * "32 128 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 255.255.255.255 ".
+ * Each additional ipv4 address takes 4 bytes in binary option and appends
+ * another "255.255.255.255 " 16-byte string. We can set [OPTION_6RD] = 4
+ * but this severely overestimates string length: instead of 16 bytes,
+ * it adds >60 for every 4 bytes in binary option.
+ * We cheat and declare here that option is in units of 12 bytes.
+ * This adds more than 60 bytes for every three ipv4 addresses - more than enough.
+ * (Even 16 instead of 12 should work, but let's be paranoid).
+ */
#endif
};
@@ -180,7 +191,7 @@ static void log_option(const char *pfx, const uint8_t *opt)
if (dhcp_verbose >= 2) {
char buf[256 * 2 + 2];
*bin2hex(buf, (void*) (opt + OPT_DATA), opt[OPT_LEN]) = '\0';
- bb_info_msg("%s: 0x%02x %s", pfx, opt[OPT_CODE], buf);
+ bb_error_msg("%s: 0x%02x %s", pfx, opt[OPT_CODE], buf);
}
}
#else
@@ -254,7 +265,7 @@ uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code)
continue; /* complain and return NULL */
if (optionptr[OPT_CODE] == code) {
- log_option("Option found", optionptr);
+ log_option("option found", optionptr);
return optionptr + OPT_DATA;
}
@@ -266,7 +277,7 @@ uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code)
}
/* log3 because udhcpc uses it a lot - very noisy */
- log3("Option 0x%02x not found", code);
+ log3("option 0x%02x not found", code);
return NULL;
}
@@ -300,7 +311,7 @@ void FAST_FUNC udhcp_add_binary_option(struct dhcp_packet *packet, uint8_t *addo
addopt[OPT_CODE]);
return;
}
- log_option("Adding option", addopt);
+ log_option("adding option", addopt);
memcpy(optionptr + end, addopt, len);
optionptr[end + len] = DHCP_END;
}
@@ -354,23 +365,6 @@ int FAST_FUNC udhcp_str2nip(const char *str, void *arg)
return 1;
}
-/* Convert IPv6 address into string */
-int FAST_FUNC sprint_nip6(char *dest, const uint8_t *ip6)
-{
- int i, len = 0;
-
- for (i = 0; i < 16; i += 2)
- {
- if (i > 0)
- dest[len++] = ':';
- bin2hex(dest + len, (const char * )&ip6[i], 2);
- len += 4;
- }
- dest[len] = '\0';
-
- return len;
-}
-
/* udhcp_str2optset:
* Parse string option representation to binary form and add it to opt_list.
* Called to parse "udhcpc -x OPTNAME:OPTVAL"
@@ -416,7 +410,7 @@ static NOINLINE void attach_option(
struct option_set *new, **curr;
/* make a new option */
- log2("Attaching option %02x to list", optflag->code);
+ log2("attaching option %02x to list", optflag->code);
new = xmalloc(sizeof(*new));
new->data = xmalloc(length + OPT_DATA);
new->data[OPT_CODE] = optflag->code;
@@ -436,7 +430,7 @@ static NOINLINE void attach_option(
unsigned old_len;
/* add it to an existing option */
- log2("Attaching option %02x to existing member of list", optflag->code);
+ log2("attaching option %02x to existing member of list", optflag->code);
old_len = existing->data[OPT_LEN];
if (old_len + length < 255) {
/* actually 255 is ok too, but adding a space can overlow it */
@@ -587,3 +581,22 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg)
return retval;
}
+
+/* note: ip is a pointer to an IPv6 in network order, possibly misaliged */
+int FAST_FUNC sprint_nip6(char *dest, /*const char *pre,*/ const uint8_t *ip)
+{
+ char hexstrbuf[16 * 2];
+ bin2hex(hexstrbuf, (void*)ip, 16);
+ return sprintf(dest, /* "%s" */
+ "%.4s:%.4s:%.4s:%.4s:%.4s:%.4s:%.4s:%.4s",
+ /* pre, */
+ hexstrbuf + 0 * 4,
+ hexstrbuf + 1 * 4,
+ hexstrbuf + 2 * 4,
+ hexstrbuf + 3 * 4,
+ hexstrbuf + 4 * 4,
+ hexstrbuf + 5 * 4,
+ hexstrbuf + 6 * 4,
+ hexstrbuf + 7 * 4
+ );
+}
diff --git a/release/src/router/busybox/networking/udhcp/common.h b/release/src/router/busybox/networking/udhcp/common.h
index 2db5ab45f8..6a799f9618 100644
--- a/release/src/router/busybox/networking/udhcp/common.h
+++ b/release/src/router/busybox/networking/udhcp/common.h
@@ -9,6 +9,7 @@
#define UDHCP_COMMON_H 1
#include "libbb.h"
+#include "common_bufsiz.h"
#include <netinet/udp.h>
#include <netinet/ip.h>
@@ -91,7 +92,7 @@ enum {
OPTION_S32,
OPTION_BIN,
OPTION_STATIC_ROUTES,
-#if ENABLE_FEATURE_IPV6
+#if ENABLE_FEATURE_UDHCP_RFC5969
OPTION_6RD,
#endif
#if ENABLE_FEATURE_UDHCP_RFC3397
@@ -155,8 +156,6 @@ enum {
//#define DHCP_VLAN_PRIORITY 0x85 /* 802.1Q VLAN priority */
//#define DHCP_PXE_CONF_FILE 0xd1 /* RFC 5071 Configuration File */
//#define DHCP_PXE_PATH_PREFIX 0xd2 /* RFC 5071 Configuration File */
-//#define DHCP_6RD 0xd4 /* RFC 5969 6RD option */
-//#define DHCP_COMCAST_6RD 0x96 /* Comcast ISP RFC 5969 compatible 6RD option */
//#define DHCP_MS_STATIC_ROUTES 0xf9 /* Microsoft's pre-RFC 3442 code for 0x79? */
//#define DHCP_WPAD 0xfc /* MSIE's Web Proxy Autodiscovery Protocol */
#define DHCP_END 0xff
@@ -202,7 +201,7 @@ uint8_t *udhcp_get_option(struct dhcp_packet *packet, int code) FAST_FUNC;
int udhcp_end_option(uint8_t *optionptr) FAST_FUNC;
void udhcp_add_binary_option(struct dhcp_packet *packet, uint8_t *addopt) FAST_FUNC;
void udhcp_add_simple_option(struct dhcp_packet *packet, uint8_t code, uint32_t data) FAST_FUNC;
-#if ENABLE_FEATURE_UDHCP_RFC3397 || ENABLE_DHCP6RELAY
+#if ENABLE_FEATURE_UDHCP_RFC3397
char *dname_dec(const uint8_t *cstr, int clen, const char *pre) FAST_FUNC;
uint8_t *dname_enc(const uint8_t *cstr, int clen, const char *src, int *retlen) FAST_FUNC;
#endif
@@ -260,16 +259,16 @@ struct option_set *udhcp_find_option(struct option_set *opt_list, uint8_t code)
#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
# define IF_UDHCP_VERBOSE(...) __VA_ARGS__
extern unsigned dhcp_verbose;
-# define log1(...) do { if (dhcp_verbose >= 1) bb_info_msg(__VA_ARGS__); } while (0)
+# define log1(...) do { if (dhcp_verbose >= 1) bb_error_msg(__VA_ARGS__); } while (0)
# if CONFIG_UDHCP_DEBUG >= 2
void udhcp_dump_packet(struct dhcp_packet *packet) FAST_FUNC;
-# define log2(...) do { if (dhcp_verbose >= 2) bb_info_msg(__VA_ARGS__); } while (0)
+# define log2(...) do { if (dhcp_verbose >= 2) bb_error_msg(__VA_ARGS__); } while (0)
# else
# define udhcp_dump_packet(...) ((void)0)
# define log2(...) ((void)0)
# endif
# if CONFIG_UDHCP_DEBUG >= 3
-# define log3(...) do { if (dhcp_verbose >= 3) bb_info_msg(__VA_ARGS__); } while (0)
+# define log3(...) do { if (dhcp_verbose >= 3) bb_error_msg(__VA_ARGS__); } while (0)
# else
# define log3(...) ((void)0)
# endif
@@ -284,8 +283,6 @@ void udhcp_dump_packet(struct dhcp_packet *packet) FAST_FUNC;
/*** Other shared functions ***/
-int FAST_FUNC sprint_nip6(char *, const uint8_t *);
-
/* 2nd param is "uint32_t*" */
int FAST_FUNC udhcp_str2nip(const char *str, void *arg);
/* 2nd param is "struct option_set**" */
diff --git a/release/src/router/busybox/networking/udhcp/d6_dhcpc.c b/release/src/router/busybox/networking/udhcp/d6_dhcpc.c
index a792a9dcab..ca678dc3d3 100644
--- a/release/src/router/busybox/networking/udhcp/d6_dhcpc.c
+++ b/release/src/router/busybox/networking/udhcp/d6_dhcpc.c
@@ -12,10 +12,11 @@
*/
//config:config UDHCPC6
-//config: bool "udhcp client for DHCPv6 (udhcpc6)"
-//config: default n # not yet ready
-//config: help
-//config: udhcpc6 is a DHCPv6 client
+//config: bool "udhcp client for DHCPv6 (udhcpc6)"
+//config: default n # not yet ready
+//config: depends on FEATURE_IPV6
+//config: help
+//config: udhcpc6 is a DHCPv6 client
//applet:IF_UDHCPC6(APPLET(udhcpc6, BB_DIR_USR_BIN, BB_SUID_DROP))
@@ -117,7 +118,7 @@ static void *d6_copy_option(uint8_t *option, uint8_t *option_end, unsigned code)
uint8_t *opt = d6_find_option(option, option_end, code);
if (!opt)
return opt;
- return memcpy(xmalloc(opt[3] + 4), opt, opt[3] + 4);
+ return xmemdup(opt, opt[3] + 4);
}
static void *d6_store_blob(void *dst, const void *src, unsigned len)
@@ -250,7 +251,7 @@ static void d6_run_script(struct d6_packet *packet, const char *name)
envp = fill_envp(packet);
/* call script */
- log1("Executing %s %s", client_config.script, name);
+ log1("executing %s %s", client_config.script, name);
argv[0] = (char*) client_config.script;
argv[1] = (char*) name;
argv[2] = NULL;
@@ -310,8 +311,8 @@ static int d6_mcast_from_client_config_ifindex(struct d6_packet *packet, uint8_t
return d6_send_raw_packet(
packet, (end - (uint8_t*) packet),
- /*src*/ NULL, CLIENT_PORT,
- /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT, MAC_BCAST_ADDR,
+ /*src*/ NULL, CLIENT_PORT6,
+ /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_BCAST_ADDR,
client_config.ifindex
);
}
@@ -427,7 +428,7 @@ static NOINLINE int send_d6_discover(uint32_t xid, struct in6_addr *requested_ip
*/
opt_ptr = add_d6_client_options(opt_ptr);
- bb_info_msg("Sending discover...");
+ bb_error_msg("sending %s", "discover");
return d6_mcast_from_client_config_ifindex(&packet, opt_ptr);
}
@@ -480,7 +481,7 @@ static NOINLINE int send_d6_select(uint32_t xid)
*/
opt_ptr = add_d6_client_options(opt_ptr);
- bb_info_msg("Sending select...");
+ bb_error_msg("sending %s", "select");
return d6_mcast_from_client_config_ifindex(&packet, opt_ptr);
}
@@ -549,12 +550,12 @@ static NOINLINE int send_d6_renew(uint32_t xid, struct in6_addr *server_ipv6, st
*/
opt_ptr = add_d6_client_options(opt_ptr);
- bb_info_msg("Sending renew...");
+ bb_error_msg("sending %s", "renew");
if (server_ipv6)
return d6_send_kernel_packet(
&packet, (opt_ptr - (uint8_t*) &packet),
- our_cur_ipv6, CLIENT_PORT,
- server_ipv6, SERVER_PORT
+ our_cur_ipv6, CLIENT_PORT6,
+ server_ipv6, SERVER_PORT6
);
return d6_mcast_from_client_config_ifindex(&packet, opt_ptr);
}
@@ -572,11 +573,11 @@ static int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cu
/* IA NA (contains our current IP) */
opt_ptr = d6_store_blob(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2);
- bb_info_msg("Sending release...");
+ bb_error_msg("sending %s", "release");
return d6_send_kernel_packet(
&packet, (opt_ptr - (uint8_t*) &packet),
- our_cur_ipv6, CLIENT_PORT,
- server_ipv6, SERVER_PORT
+ our_cur_ipv6, CLIENT_PORT6,
+ server_ipv6, SERVER_PORT6
);
}
@@ -591,19 +592,19 @@ static NOINLINE int d6_recv_raw_packet(struct in6_addr *peer_ipv6
bytes = safe_read(fd, &packet, sizeof(packet));
if (bytes < 0) {
- log1("Packet read error, ignoring");
+ log1("packet read error, ignoring");
/* NB: possible down interface, etc. Caller should pause. */
return bytes; /* returns -1 */
}
if (bytes < (int) (sizeof(packet.ip6) + sizeof(packet.udp))) {
- log1("Packet is too short, ignoring");
+ log1("packet is too short, ignoring");
return -2;
}
if (bytes < sizeof(packet.ip6) + ntohs(packet.ip6.ip6_plen)) {
/* packet is bigger than sizeof(packet), we did partial read */
- log1("Oversized packet, ignoring");
+ log1("oversized packet, ignoring");
return -2;
}
@@ -613,11 +614,11 @@ static NOINLINE int d6_recv_raw_packet(struct in6_addr *peer_ipv6
/* make sure its the right packet for us, and that it passes sanity checks */
if (packet.ip6.ip6_nxt != IPPROTO_UDP
|| (packet.ip6.ip6_vfc >> 4) != 6
- || packet.udp.dest != htons(CLIENT_PORT)
+ || packet.udp.dest != htons(CLIENT_PORT6)
/* || bytes > (int) sizeof(packet) - can't happen */
|| packet.udp.len != packet.ip6.ip6_plen
) {
- log1("Unrelated/bogus packet, ignoring");
+ log1("unrelated/bogus packet, ignoring");
return -2;
}
@@ -629,11 +630,11 @@ static NOINLINE int d6_recv_raw_packet(struct in6_addr *peer_ipv6
// check = packet.udp.check;
// packet.udp.check = 0;
// if (check && check != inet_cksum((uint16_t *)&packet, bytes)) {
-// log1("Packet with bad UDP checksum received, ignoring");
+// log1("packet with bad UDP checksum received, ignoring");
// return -2;
// }
- log1("Received a packet");
+ log1("received %s", "a packet");
d6_dump_packet(&packet.data);
bytes -= sizeof(packet.ip6) + sizeof(packet.udp);
@@ -707,10 +708,10 @@ static int d6_raw_socket(int ifindex)
BPF_STMT(BPF_LDX|BPF_B|BPF_MSH, 0),
/* load udp destination port from halfword[header_len + 2] */
BPF_STMT(BPF_LD|BPF_H|BPF_IND, 2),
- /* jump to L3 if udp dport is CLIENT_PORT, else to L4 */
+ /* jump to L3 if udp dport is CLIENT_PORT6, else to L4 */
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 68, 0, 1),
/* L3: accept packet */
- BPF_STMT(BPF_RET|BPF_K, 0xffffffff),
+ BPF_STMT(BPF_RET|BPF_K, 0x7fffffff),
/* L4: discard packet */
BPF_STMT(BPF_RET|BPF_K, 0),
};
@@ -721,10 +722,10 @@ static int d6_raw_socket(int ifindex)
};
#endif
- log1("Opening raw socket on ifindex %d", ifindex); //log2?
+ log1("opening raw socket on ifindex %d", ifindex); //log2?
fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6));
- log1("Got raw socket fd %d", fd); //log2?
+ log1("got raw socket fd %d", fd); //log2?
sock.sll_family = AF_PACKET;
sock.sll_protocol = htons(ETH_P_IPV6);
@@ -732,23 +733,23 @@ static int d6_raw_socket(int ifindex)
xbind(fd, (struct sockaddr *) &sock, sizeof(sock));
#if 0
- if (CLIENT_PORT == 68) {
+ if (CLIENT_PORT6 == 546) {
/* Use only if standard port is in use */
/* Ignoring error (kernel may lack support for this) */
if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog,
sizeof(filter_prog)) >= 0)
- log1("Attached filter to raw socket fd %d", fd); // log?
+ log1("attached filter to raw socket fd %d", fd); // log?
}
#endif
- log1("Created raw socket");
+ log1("created raw socket");
return fd;
}
static void change_listen_mode(int new_mode)
{
- log1("Entering listen mode: %s",
+ log1("entering listen mode: %s",
new_mode != LISTEN_NONE
? (new_mode == LISTEN_KERNEL ? "kernel" : "raw")
: "none"
@@ -760,7 +761,7 @@ static void change_listen_mode(int new_mode)
sockfd = -1;
}
if (new_mode == LISTEN_KERNEL)
- sockfd = udhcp_listen_socket(/*INADDR_ANY,*/ CLIENT_PORT, client_config.interface);
+ sockfd = udhcp_listen_socket(/*INADDR_ANY,*/ CLIENT_PORT6, client_config.interface);
else if (new_mode != LISTEN_NONE)
sockfd = d6_raw_socket(client_config.ifindex);
/* else LISTEN_NONE: sockfd stays closed */
@@ -769,7 +770,7 @@ static void change_listen_mode(int new_mode)
/* Called only on SIGUSR1 */
static void perform_renew(void)
{
- bb_info_msg("Performing a DHCP renew");
+ bb_error_msg("performing DHCP renew");
switch (state) {
case BOUND:
change_listen_mode(LISTEN_KERNEL);
@@ -792,13 +793,22 @@ static void perform_renew(void)
static void perform_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6)
{
/* send release packet */
- if (state == BOUND || state == RENEWING || state == REBINDING) {
- bb_info_msg("Unicasting a release");
+ if (state == BOUND
+ || state == RENEWING
+ || state == REBINDING
+ || state == RENEW_REQUESTED
+ ) {
+ bb_error_msg("unicasting a release");
send_d6_release(server_ipv6, our_cur_ipv6); /* unicast */
- d6_run_script(NULL, "deconfig");
}
- bb_info_msg("Entering released state");
-
+ bb_error_msg("entering released state");
+/*
+ * We can be here on: SIGUSR2,
+ * or on exit (SIGTERM) and -R "release on quit" is specified.
+ * Users requested to be notified in all cases, even if not in one
+ * of the states above.
+ */
+ d6_run_script(NULL, "deconfig");
change_listen_mode(LISTEN_NONE);
state = RELEASED;
}
@@ -929,9 +939,11 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
int retval;
fd_set rfds;
+ setup_common_bufsiz();
+
/* Default options */
- IF_FEATURE_UDHCP_PORT(SERVER_PORT = 547;)
- IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 546;)
+ IF_FEATURE_UDHCP_PORT(SERVER_PORT6 = 547;)
+ IF_FEATURE_UDHCP_PORT(CLIENT_PORT6 = 546;)
client_config.interface = "eth0";
client_config.script = CONFIG_UDHCPC_DEFAULT_SCRIPT;
@@ -960,12 +972,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
}
#if ENABLE_FEATURE_UDHCP_PORT
if (opt & OPT_P) {
- CLIENT_PORT = xatou16(str_P);
- SERVER_PORT = CLIENT_PORT - 1;
+ CLIENT_PORT6 = xatou16(str_P);
+ SERVER_PORT6 = CLIENT_PORT6 + 1;
}
#endif
- if (opt & OPT_o)
- client_config.no_default_options = 1;
while (list_O) {
char *optstr = llist_pop(&list_O);
unsigned n = bb_strtou(optstr, NULL, 0);
@@ -975,6 +985,16 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
}
client_config.opt_mask[n >> 3] |= 1 << (n & 7);
}
+ if (!(opt & OPT_o)) {
+ /*
+ unsigned i, n;
+ for (i = 0; (n = dhcp_optflags[i].code) != 0; i++) {
+ if (dhcp_optflags[i].flags & OPTION_REQ) {
+ client_config.opt_mask[n >> 3] |= 1 << (n & 7);
+ }
+ }
+ */
+ }
while (list_x) {
char *optstr = llist_pop(&list_x);
char *colon = strchr(optstr, ':');
@@ -988,7 +1008,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
if (udhcp_read_interface(client_config.interface,
&client_config.ifindex,
NULL,
- client_config.client_mac)
+ client_config.client_mac,
+ NULL)
) {
return 1;
}
@@ -1025,7 +1046,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
/* Create pidfile */
write_pidfile(client_config.pidfile);
/* Goes to stdout (unless NOMMU) and possibly syslog */
- bb_info_msg("%s (v"BB_VER") started", applet_name);
+ bb_error_msg("started, v"BB_VER);
/* Set up the signal pipe */
udhcp_sp_setup();
/* We want random_xid to be random... */
@@ -1065,8 +1086,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
retval = 0;
/* If we already timed out, fall through with retval = 0, else... */
if ((int)tv.tv_sec > 0) {
+ log1("waiting on select %u seconds", (int)tv.tv_sec);
timestamp_before_wait = (unsigned)monotonic_sec();
- log1("Waiting on select...");
retval = select(max_fd + 1, &rfds, NULL, NULL, &tv);
if (retval < 0) {
/* EINTR? A signal was caught, don't panic */
@@ -1091,7 +1112,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
if (udhcp_read_interface(client_config.interface,
&client_config.ifindex,
NULL,
- client_config.client_mac)
+ client_config.client_mac,
+ NULL)
) {
goto ret0; /* iface is gone? */
}
@@ -1102,7 +1124,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
switch (state) {
case INIT_SELECTING:
- if (packet_num < discover_retries) {
+ if (!discover_retries || packet_num < discover_retries) {
if (packet_num == 0)
xid = random_xid();
/* multicast */
@@ -1115,14 +1137,14 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
d6_run_script(NULL, "leasefail");
#if BB_MMU /* -b is not supported on NOMMU */
if (opt & OPT_b) { /* background if no lease */
- bb_info_msg("No lease, forking to background");
+ bb_error_msg("no lease, forking to background");
client_background();
/* do not background again! */
opt = ((opt & ~OPT_b) | OPT_f);
} else
#endif
if (opt & OPT_n) { /* abort if no lease */
- bb_info_msg("No lease, failing");
+ bb_error_msg("no lease, failing");
retval = 1;
goto ret;
}
@@ -1131,7 +1153,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
packet_num = 0;
continue;
case REQUESTING:
- if (packet_num < discover_retries) {
+ if (!discover_retries || packet_num < discover_retries) {
/* send multicast select packet */
send_d6_select(xid);
timeout = discover_timeout;
@@ -1150,7 +1172,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
state = RENEWING;
client_config.first_secs = 0; /* make secs field count from 0 */
change_listen_mode(LISTEN_KERNEL);
- log1("Entering renew state");
+ log1("entering renew state");
/* fall right through */
case RENEW_REQUESTED: /* manual (SIGUSR1) renew */
case_RENEW_REQUESTED:
@@ -1170,7 +1192,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
continue;
}
/* Timed out, enter rebinding state */
- log1("Entering rebinding state");
+ log1("entering rebinding state");
state = REBINDING;
/* fall right through */
case REBINDING:
@@ -1185,7 +1207,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
continue;
}
/* Timed out, enter init state */
- bb_info_msg("Lease lost, entering init state");
+ bb_error_msg("lease lost, entering init state");
d6_run_script(NULL, "deconfig");
state = INIT_SELECTING;
client_config.first_secs = 0; /* make secs field count from 0 */
@@ -1233,7 +1255,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
timeout = INT_MAX;
continue;
case SIGTERM:
- bb_info_msg("Received SIGTERM");
+ bb_error_msg("received %s", "SIGTERM");
goto ret0;
}
@@ -1251,7 +1273,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
len = d6_recv_raw_packet(&srv6_buf, &packet, sockfd);
if (len == -1) {
/* Error is severe, reopen socket */
- bb_info_msg("Read error: %s, reopening socket", strerror(errno));
+ bb_error_msg("read error: %s, reopening socket", strerror(errno));
sleep(discover_timeout); /* 3 seconds by default */
change_listen_mode(listen_mode); /* just close and reopen */
}
@@ -1289,7 +1311,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
option = d6_find_option(packet.d6_options, packet_end, D6_OPT_STATUS_CODE);
if (option && option->data[4] != 0) {
/* return to init state */
- bb_info_msg("Received DHCP NAK (%u)", option->data[4]);
+ bb_error_msg("received DHCP NAK (%u)", option->data[4]);
d6_run_script(&packet, "nak");
if (state != REQUESTING)
d6_run_script(NULL, "deconfig");
@@ -1444,7 +1466,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
lease_seconds = 0x0fffffff;
/* enter bound state */
timeout = lease_seconds / 2;
- bb_info_msg("Lease obtained, lease time %u",
+ bb_error_msg("lease obtained, lease time %u",
/*inet_ntoa(temp_addr),*/ (unsigned)lease_seconds);
d6_run_script(&packet, state == REQUESTING ? "bound" : "renew");
diff --git a/release/src/router/busybox/networking/udhcp/d6_packet.c b/release/src/router/busybox/networking/udhcp/d6_packet.c
index 79b2946ef8..e166f520de 100644
--- a/release/src/router/busybox/networking/udhcp/d6_packet.c
+++ b/release/src/router/busybox/networking/udhcp/d6_packet.c
@@ -17,12 +17,12 @@ void FAST_FUNC d6_dump_packet(struct d6_packet *packet)
if (dhcp_verbose < 2)
return;
- bb_info_msg(
- " xid %x"
+ bb_error_msg(
+ "xid %x"
, packet->d6_xid32
);
//*bin2hex(buf, (void *) packet->chaddr, sizeof(packet->chaddr)) = '\0';
- //bb_info_msg(" chaddr %s", buf);
+ //bb_error_msg(" chaddr %s", buf);
}
#endif
@@ -35,15 +35,15 @@ int FAST_FUNC d6_recv_kernel_packet(struct in6_addr *peer_ipv6
memset(packet, 0, sizeof(*packet));
bytes = safe_read(fd, packet, sizeof(*packet));
if (bytes < 0) {
- log1("Packet read error, ignoring");
+ log1("packet read error, ignoring");
return bytes; /* returns -1 */
}
if (bytes < offsetof(struct d6_packet, d6_options)) {
- bb_info_msg("Packet with bad magic, ignoring");
+ bb_error_msg("packet with bad magic, ignoring");
return -2;
}
- log1("Received a packet");
+ log1("received %s", "a packet");
d6_dump_packet(packet);
return bytes;
diff --git a/release/src/router/busybox/networking/udhcp/d6_socket.c b/release/src/router/busybox/networking/udhcp/d6_socket.c
index 56f69f6a1b..910f296a31 100644
--- a/release/src/router/busybox/networking/udhcp/d6_socket.c
+++ b/release/src/router/busybox/networking/udhcp/d6_socket.c
@@ -13,7 +13,7 @@ int FAST_FUNC d6_listen_socket(int port, const char *inf)
int fd;
struct sockaddr_in6 addr;
- log1("Opening listen socket on *:%d %s", port, inf);
+ log1("opening listen socket on *:%d %s", port, inf);
fd = xsocket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
setsockopt_reuseaddr(fd);
diff --git a/release/src/router/busybox/networking/udhcp/dhcpc.c b/release/src/router/busybox/networking/udhcp/dhcpc.c
index 7b800fa4a8..827a4cda49 100644
--- a/release/src/router/busybox/networking/udhcp/dhcpc.c
+++ b/release/src/router/busybox/networking/udhcp/dhcpc.c
@@ -109,12 +109,12 @@ enum {
/*** Script execution code ***/
/* get a rough idea of how long an option will be (rounding up...) */
-static const uint8_t len_of_option_as_string[] = {
+static const uint8_t len_of_option_as_string[] ALIGN1 = {
[OPTION_IP ] = sizeof("255.255.255.255 "),
[OPTION_IP_PAIR ] = sizeof("255.255.255.255 ") * 2,
[OPTION_STATIC_ROUTES ] = sizeof("255.255.255.255/32 255.255.255.255 "),
-#if ENABLE_FEATURE_IPV6
- [OPTION_6RD ] = sizeof("32 128 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 255.255.255.255 "),
+#if ENABLE_FEATURE_UDHCP_RFC5969
+ [OPTION_6RD ] = sizeof("132 128 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 255.255.255.255 "),
#endif
[OPTION_STRING ] = 1,
[OPTION_STRING_HOST ] = 1,
@@ -224,7 +224,7 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
type = optflag->flags & OPTION_TYPE_MASK;
optlen = dhcp_option_lengths[type];
upper_length = len_of_option_as_string[type]
- * ((unsigned)(len + optlen - 1) / (unsigned)optlen);
+ * ((unsigned)(len + optlen) / (unsigned)optlen);
dest = ret = xmalloc(upper_length + strlen(opt_name) + 2);
dest += sprintf(ret, "%s=", opt_name);
@@ -313,7 +313,7 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
return ret;
}
-#if ENABLE_FEATURE_IPV6
+#if ENABLE_FEATURE_UDHCP_RFC5969
case OPTION_6RD:
/* Option binary format (see RFC 5969):
* 0 1 2 3
@@ -565,7 +565,7 @@ static void udhcp_run_script(struct dhcp_packet *packet, const char *name)
envp = fill_envp(packet);
/* call script */
- log1("Executing %s %s", client_config.script, name);
+ log1("executing %s %s", client_config.script, name);
argv[0] = (char*) client_config.script;
argv[1] = (char*) name;
argv[2] = NULL;
@@ -682,10 +682,10 @@ static void add_client_options(struct dhcp_packet *packet)
* client reverts to using the IP broadcast address.
*/
-static int raw_bcast_from_client_config_ifindex(struct dhcp_packet *packet, uint32_t ciaddr)
+static int raw_bcast_from_client_config_ifindex(struct dhcp_packet *packet, uint32_t src_nip)
{
return udhcp_send_raw_packet(packet,
- /*src*/ ciaddr, CLIENT_PORT,
+ /*src*/ src_nip, CLIENT_PORT,
/*dst*/ INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR,
client_config.ifindex);
}
@@ -721,7 +721,7 @@ static NOINLINE int send_discover(uint32_t xid, uint32_t requested)
*/
add_client_options(&packet);
- bb_info_msg("Sending discover...");
+ bb_error_msg("sending %s", "discover");
return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY);
}
@@ -765,7 +765,7 @@ static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requeste
add_client_options(&packet);
addr.s_addr = requested;
- bb_info_msg("Sending select for %s...", inet_ntoa(addr));
+ bb_error_msg("sending select for %s", inet_ntoa(addr));
return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY);
}
@@ -804,7 +804,7 @@ static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr)
*/
add_client_options(&packet);
- bb_info_msg("Sending renew...");
+ bb_error_msg("sending %s", "renew");
return bcast_or_ucast(&packet, ciaddr, server);
}
@@ -833,7 +833,7 @@ static NOINLINE int send_decline(/*uint32_t xid,*/ uint32_t server, uint32_t req
udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server);
- bb_info_msg("Sending decline...");
+ bb_error_msg("sending %s", "decline");
return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY);
}
#endif
@@ -853,7 +853,7 @@ static int send_release(uint32_t server, uint32_t ciaddr)
udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server);
- bb_info_msg("Sending release...");
+ bb_error_msg("sending %s", "release");
/* Note: normally we unicast here since "server" is not zero.
* However, there _are_ people who run "address-less" DHCP servers,
* and reportedly ISC dhcp client and Windows allow that.
@@ -888,7 +888,7 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
if (bytes < 0) {
if (errno == EINTR)
continue;
- log1("Packet read error, ignoring");
+ log1("packet read error, ignoring");
/* NB: possible down interface, etc. Caller should pause. */
return bytes; /* returns -1 */
}
@@ -896,13 +896,13 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
}
if (bytes < (int) (sizeof(packet.ip) + sizeof(packet.udp))) {
- log1("Packet is too short, ignoring");
+ log1("packet is too short, ignoring");
return -2;
}
if (bytes < ntohs(packet.ip.tot_len)) {
/* packet is bigger than sizeof(packet), we did partial read */
- log1("Oversized packet, ignoring");
+ log1("oversized packet, ignoring");
return -2;
}
@@ -917,7 +917,7 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
/* || bytes > (int) sizeof(packet) - can't happen */
|| ntohs(packet.udp.len) != (uint16_t)(bytes - sizeof(packet.ip))
) {
- log1("Unrelated/bogus packet, ignoring");
+ log1("unrelated/bogus packet, ignoring");
return -2;
}
@@ -925,7 +925,7 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
check = packet.ip.check;
packet.ip.check = 0;
if (check != inet_cksum((uint16_t *)&packet.ip, sizeof(packet.ip))) {
- log1("Bad IP header checksum, ignoring");
+ log1("bad IP header checksum, ignoring");
return -2;
}
@@ -950,17 +950,17 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
check = packet.udp.check;
packet.udp.check = 0;
if (check && check != inet_cksum((uint16_t *)&packet, bytes)) {
- log1("Packet with bad UDP checksum received, ignoring");
+ log1("packet with bad UDP checksum received, ignoring");
return -2;
}
skip_udp_sum_check:
if (packet.data.cookie != htonl(DHCP_MAGIC)) {
- bb_info_msg("Packet with bad magic, ignoring");
+ bb_error_msg("packet with bad magic, ignoring");
return -2;
}
- log1("Received a packet");
+ log1("received %s", "a packet");
udhcp_dump_packet(&packet.data);
bytes -= sizeof(packet.ip) + sizeof(packet.udp);
@@ -999,14 +999,14 @@ static int udhcp_raw_socket(int ifindex)
int fd;
struct sockaddr_ll sock;
- log1("Opening raw socket on ifindex %d", ifindex); //log2?
+ log1("opening raw socket on ifindex %d", ifindex); //log2?
fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
/* ^^^^^
* SOCK_DGRAM: remove link-layer headers on input (SOCK_RAW keeps them)
* ETH_P_IP: want to receive only packets with IPv4 eth type
*/
- log1("Got raw socket fd"); //log2?
+ log1("got raw socket fd"); //log2?
sock.sll_family = AF_PACKET;
sock.sll_protocol = htons(ETH_P_IP);
@@ -1061,24 +1061,22 @@ static int udhcp_raw_socket(int ifindex)
/* Ignoring error (kernel may lack support for this) */
if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog,
sizeof(filter_prog)) >= 0)
- log1("Attached filter to raw socket fd"); // log?
+ log1("attached filter to raw socket fd"); // log?
}
- if (setsockopt(fd, SOL_PACKET, PACKET_AUXDATA,
- &const_int_1, sizeof(int)) < 0
- ) {
+ if (setsockopt_1(fd, SOL_PACKET, PACKET_AUXDATA) != 0) {
if (errno != ENOPROTOOPT)
- log1("Can't set PACKET_AUXDATA on raw socket");
+ log1("can't set PACKET_AUXDATA on raw socket");
}
- log1("Created raw socket");
+ log1("created raw socket");
return fd;
}
static void change_listen_mode(int new_mode)
{
- log1("Entering listen mode: %s",
+ log1("entering listen mode: %s",
new_mode != LISTEN_NONE
? (new_mode == LISTEN_KERNEL ? "kernel" : "raw")
: "none"
@@ -1099,7 +1097,7 @@ static void change_listen_mode(int new_mode)
/* Called only on SIGUSR1 */
static void perform_renew(void)
{
- bb_info_msg("Performing a DHCP renew");
+ bb_error_msg("performing DHCP renew");
switch (state) {
case BOUND:
change_listen_mode(LISTEN_KERNEL);
@@ -1125,16 +1123,26 @@ static void perform_release(uint32_t server_addr, uint32_t requested_ip)
struct in_addr temp_addr;
/* send release packet */
- if (state == BOUND || state == RENEWING || state == REBINDING) {
+ if (state == BOUND
+ || state == RENEWING
+ || state == REBINDING
+ || state == RENEW_REQUESTED
+ ) {
temp_addr.s_addr = server_addr;
strcpy(buffer, inet_ntoa(temp_addr));
temp_addr.s_addr = requested_ip;
- bb_info_msg("Unicasting a release of %s to %s",
+ bb_error_msg("unicasting a release of %s to %s",
inet_ntoa(temp_addr), buffer);
send_release(server_addr, requested_ip); /* unicast */
- udhcp_run_script(NULL, "deconfig");
}
- bb_info_msg("Entering released state");
+ bb_error_msg("entering released state");
+/*
+ * We can be here on: SIGUSR2,
+ * or on exit (SIGTERM) and -R "release on quit" is specified.
+ * Users requested to be notified in all cases, even if not in one
+ * of the states above.
+ */
+ udhcp_run_script(NULL, "deconfig");
change_listen_mode(LISTEN_NONE);
state = RELEASED;
@@ -1202,6 +1210,7 @@ static void client_background(void)
//usage: "\n -x lease:3600 - option 51 (lease time)"
//usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)"
//usage: "\n -F,--fqdn NAME Ask server to update DNS mapping for NAME"
+//usage: "\n -H,-h,--hostname NAME Send NAME as client hostname"
//usage: "\n -V,--vendorclass VENDOR Vendor identifier (default 'udhcp VERSION')"
//usage: "\n -C,--clientid-none Don't send MAC as client identifier"
//usage: IF_UDHCP_VERBOSE(
@@ -1239,6 +1248,7 @@ static void client_background(void)
//usage: "\n -x lease:3600 - option 51 (lease time)"
//usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)"
//usage: "\n -F NAME Ask server to update DNS mapping for NAME"
+//usage: "\n -H,-h NAME Send NAME as client hostname"
//usage: "\n -V VENDOR Vendor identifier (default 'udhcp VERSION')"
//usage: "\n -C Don't send MAC as client identifier"
//usage: IF_UDHCP_VERBOSE(
@@ -1276,6 +1286,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
int retval;
fd_set rfds;
+ setup_common_bufsiz();
+
/* Default options */
IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;)
IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;)
@@ -1404,7 +1416,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
/* Create pidfile */
write_pidfile(client_config.pidfile);
/* Goes to stdout (unless NOMMU) and possibly syslog */
- bb_info_msg("%s (v"BB_VER") started", applet_name);
+ bb_error_msg("started, v"BB_VER);
/* Set up the signal pipe */
udhcp_sp_setup();
/* We want random_xid to be random... */
@@ -1444,7 +1456,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
retval = 0;
/* If we already timed out, fall through with retval = 0, else... */
if ((int)tv.tv_sec > 0) {
- log1("Waiting on select %u seconds", (int)tv.tv_sec);
+ log1("waiting on select %u seconds", (int)tv.tv_sec);
timestamp_before_wait = (unsigned)monotonic_sec();
retval = select(max_fd + 1, &rfds, NULL, NULL, &tv);
if (retval < 0) {
@@ -1496,14 +1508,14 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
udhcp_run_script(NULL, "leasefail");
#if BB_MMU /* -b is not supported on NOMMU */
if (opt & OPT_b) { /* background if no lease */
- bb_info_msg("No lease, forking to background");
+ bb_error_msg("no lease, forking to background");
client_background();
/* do not background again! */
opt = ((opt & ~OPT_b) | OPT_f);
} else
#endif
if (opt & OPT_n) { /* abort if no lease */
- bb_info_msg("No lease, failing");
+ bb_error_msg("no lease, failing");
retval = 1;
goto ret;
}
@@ -1512,7 +1524,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
packet_num = 0;
continue;
case REQUESTING:
- if (!discover_retries || packet_num < discover_retries) {
+ if (packet_num < 3) {
/* send broadcast select packet */
send_select(xid, server_addr, requested_ip);
timeout = discover_timeout;
@@ -1531,7 +1543,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
state = RENEWING;
client_config.first_secs = 0; /* make secs field count from 0 */
change_listen_mode(LISTEN_KERNEL);
- log1("Entering renew state");
+ log1("entering renew state");
/* fall right through */
case RENEW_REQUESTED: /* manual (SIGUSR1) renew */
case_RENEW_REQUESTED:
@@ -1551,7 +1563,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
continue;
}
/* Timed out, enter rebinding state */
- log1("Entering rebinding state");
+ log1("entering rebinding state");
state = REBINDING;
/* fall right through */
case REBINDING:
@@ -1566,7 +1578,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
continue;
}
/* Timed out, enter init state */
- bb_info_msg("Lease lost, entering init state");
+ bb_error_msg("lease lost, entering init state");
udhcp_run_script(NULL, "deconfig");
state = INIT_SELECTING;
client_config.first_secs = 0; /* make secs field count from 0 */
@@ -1619,7 +1631,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
timeout = INT_MAX;
continue;
case SIGTERM:
- bb_info_msg("Received SIGTERM");
+ bb_error_msg("received %s", "SIGTERM");
goto ret0;
}
@@ -1637,7 +1649,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
len = udhcp_recv_raw_packet(&packet, sockfd);
if (len == -1) {
/* Error is severe, reopen socket */
- bb_info_msg("Read error: %s, reopening socket", strerror(errno));
+ bb_error_msg("read error: %s, reopening socket", strerror(errno));
sleep(discover_timeout); /* 3 seconds by default */
change_listen_mode(listen_mode); /* just close and reopen */
}
@@ -1760,7 +1772,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
client_config.interface,
arpping_ms)
) {
- bb_info_msg("Offered address is in use "
+ bb_error_msg("offered address is in use "
"(got ARP reply), declining");
send_decline(/*xid,*/ server_addr, packet.yiaddr);
@@ -1779,7 +1791,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
#endif
/* enter bound state */
temp_addr.s_addr = packet.yiaddr;
- bb_info_msg("Lease of %s obtained, lease time %u",
+ bb_error_msg("lease of %s obtained, lease time %u",
inet_ntoa(temp_addr), (unsigned)lease_seconds);
requested_ip = packet.yiaddr;
@@ -1824,9 +1836,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
temp = udhcp_get_option(&packet, DHCP_SERVER_ID);
if (!temp) {
non_matching_svid:
- log1("%s with wrong server ID, ignoring packet",
- "Received DHCP NAK"
- );
+ log1("received DHCP NAK with wrong"
+ " server ID, ignoring packet");
continue;
}
move_from_unaligned32(svid, temp);
@@ -1834,7 +1845,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
goto non_matching_svid;
}
/* return to init state */
- bb_info_msg("Received DHCP NAK");
+ bb_error_msg("received %s", "DHCP NAK");
udhcp_run_script(&packet, "nak");
if (state != REQUESTING)
udhcp_run_script(NULL, "deconfig");
diff --git a/release/src/router/busybox/networking/udhcp/dhcpc.h b/release/src/router/busybox/networking/udhcp/dhcpc.h
index 63fa543140..3814d8f950 100644
--- a/release/src/router/busybox/networking/udhcp/dhcpc.h
+++ b/release/src/router/busybox/networking/udhcp/dhcpc.h
@@ -30,9 +30,11 @@ struct client_config_t {
#define client_config (*(struct client_config_t*)(&bb_common_bufsiz1[COMMON_BUFSIZE / 2]))
#if ENABLE_FEATURE_UDHCP_PORT
-#define CLIENT_PORT (client_config.port)
+#define CLIENT_PORT (client_config.port)
+#define CLIENT_PORT6 (client_config.port)
#else
-#define CLIENT_PORT 68
+#define CLIENT_PORT 68
+#define CLIENT_PORT6 546
#endif
POP_SAVED_FUNCTION_VISIBILITY
diff --git a/release/src/router/busybox/networking/udhcp/dhcpd.c b/release/src/router/busybox/networking/udhcp/dhcpd.c
index 25cccbbccb..a1769051d0 100644
--- a/release/src/router/busybox/networking/udhcp/dhcpd.c
+++ b/release/src/router/busybox/networking/udhcp/dhcpd.c
@@ -61,11 +61,11 @@ static void send_packet_to_client(struct dhcp_packet *dhcp_pkt, int force_broadc
|| (dhcp_pkt->flags & htons(BROADCAST_FLAG))
|| dhcp_pkt->ciaddr == 0
) {
- log1("Broadcasting packet to client");
+ log1("broadcasting packet to client");
ciaddr = INADDR_BROADCAST;
chaddr = MAC_BCAST_ADDR;
} else {
- log1("Unicasting packet to client ciaddr");
+ log1("unicasting packet to client ciaddr");
ciaddr = dhcp_pkt->ciaddr;
chaddr = dhcp_pkt->chaddr;
}
@@ -79,7 +79,7 @@ static void send_packet_to_client(struct dhcp_packet *dhcp_pkt, int force_broadc
/* Send a packet to gateway_nip using the kernel ip stack */
static void send_packet_to_relay(struct dhcp_packet *dhcp_pkt)
{
- log1("Forwarding packet to relay");
+ log1("forwarding packet to relay");
udhcp_send_kernel_packet(dhcp_pkt,
server_config.server_nip, SERVER_PORT,
@@ -214,7 +214,7 @@ static NOINLINE void send_offer(struct dhcp_packet *oldpacket,
add_server_options(&packet);
addr.s_addr = packet.yiaddr;
- bb_info_msg("Sending OFFER of %s", inet_ntoa(addr));
+ bb_error_msg("sending OFFER of %s", inet_ntoa(addr));
/* send_packet emits error message itself if it detects failure */
send_packet(&packet, /*force_bcast:*/ 0);
}
@@ -226,7 +226,7 @@ static NOINLINE void send_NAK(struct dhcp_packet *oldpacket)
init_packet(&packet, oldpacket, DHCPNAK);
- log1("Sending NAK");
+ log1("sending %s", "NAK");
send_packet(&packet, /*force_bcast:*/ 1);
}
@@ -247,7 +247,7 @@ static NOINLINE void send_ACK(struct dhcp_packet *oldpacket, uint32_t yiaddr)
add_server_options(&packet);
addr.s_addr = yiaddr;
- bb_info_msg("Sending ACK to %s", inet_ntoa(addr));
+ bb_error_msg("sending ACK to %s", inet_ntoa(addr));
send_packet(&packet, /*force_bcast:*/ 0);
p_host_name = (const char*) udhcp_get_option(oldpacket, DHCP_HOST_NAME);
@@ -310,10 +310,10 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
unsigned arpping_ms;
IF_FEATURE_UDHCP_PORT(char *str_P;)
-#if ENABLE_FEATURE_UDHCP_PORT
- SERVER_PORT = 67;
- CLIENT_PORT = 68;
-#endif
+ setup_common_bufsiz();
+
+ IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;)
+ IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;)
#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
opt_complementary = "vv";
@@ -361,7 +361,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
write_pidfile(server_config.pidfile);
/* if (!..) bb_perror_msg("can't create pidfile %s", pidfile); */
- bb_info_msg("%s (v"BB_VER") started", applet_name);
+ bb_error_msg("started, v"BB_VER);
option = udhcp_find_option(server_config.options, DHCP_LEASE_TIME);
server_config.max_lease_sec = DEFAULT_LEASE_TIME;
@@ -428,18 +428,18 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
goto continue_with_autotime;
}
if (retval < 0 && errno != EINTR) {
- log1("Error on select");
+ log1("error on select");
continue;
}
switch (udhcp_sp_read(&rfds)) {
case SIGUSR1:
- bb_info_msg("Received SIGUSR1");
+ bb_error_msg("received %s", "SIGUSR1");
write_leases();
/* why not just reset the timeout, eh */
goto continue_with_autotime;
case SIGTERM:
- bb_info_msg("Received SIGTERM");
+ bb_error_msg("received %s", "SIGTERM");
write_leases();
goto ret0;
case 0: /* no signal: read a packet */
@@ -452,7 +452,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
if (bytes < 0) {
/* bytes can also be -2 ("bad packet data") */
if (bytes == -1 && errno != EINTR) {
- log1("Read error: %s, reopening socket", strerror(errno));
+ log1("read error: %s, reopening socket", strerror(errno));
close(server_socket);
server_socket = -1;
}
@@ -487,7 +487,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
/* Look for a static/dynamic lease */
static_lease_nip = get_static_nip_by_mac(server_config.static_leases, &packet.chaddr);
if (static_lease_nip) {
- bb_info_msg("Found static lease: %x", static_lease_nip);
+ bb_error_msg("found static lease: %x", static_lease_nip);
memcpy(&fake_lease.lease_mac, &packet.chaddr, 6);
fake_lease.lease_nip = static_lease_nip;
fake_lease.expires = 0;
@@ -505,13 +505,13 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
switch (state[0]) {
case DHCPDISCOVER:
- log1("Received DISCOVER");
+ log1("received %s", "DISCOVER");
send_offer(&packet, static_lease_nip, lease, requested_ip_opt, arpping_ms);
break;
case DHCPREQUEST:
- log1("Received REQUEST");
+ log1("received %s", "REQUEST");
/* RFC 2131:
o DHCPREQUEST generated during SELECTING state:
@@ -636,7 +636,7 @@ o DHCPREQUEST generated during REBINDING state:
* chaddr must be filled in,
* ciaddr must be 0 (we do not check this)
*/
- log1("Received DECLINE");
+ log1("received %s", "DECLINE");
if (server_id_opt
&& requested_ip_opt
&& lease /* chaddr matches this lease */
@@ -656,7 +656,7 @@ o DHCPREQUEST generated during REBINDING state:
* chaddr must be filled in,
* ciaddr must be filled in
*/
- log1("Received RELEASE");
+ log1("received %s", "RELEASE");
if (server_id_opt
&& lease /* chaddr matches this lease */
&& packet.ciaddr == lease->lease_nip
@@ -666,7 +666,7 @@ o DHCPREQUEST generated during REBINDING state:
break;
case DHCPINFORM:
- log1("Received INFORM");
+ log1("received %s", "INFORM");
send_inform(&packet);
break;
}
diff --git a/release/src/router/busybox/networking/udhcp/dhcpd.h b/release/src/router/busybox/networking/udhcp/dhcpd.h
index 6154167684..9dd5bef9eb 100644
--- a/release/src/router/busybox/networking/udhcp/dhcpd.h
+++ b/release/src/router/busybox/networking/udhcp/dhcpd.h
@@ -57,13 +57,15 @@ struct server_config_t {
struct static_lease *static_leases; /* List of ip/mac pairs to assign static leases */
} FIX_ALIASING;
-#define server_config (*(struct server_config_t*)&bb_common_bufsiz1)
+#define server_config (*(struct server_config_t*)bb_common_bufsiz1)
/* client_config sits in 2nd half of bb_common_bufsiz1 */
#if ENABLE_FEATURE_UDHCP_PORT
-#define SERVER_PORT (server_config.port)
+#define SERVER_PORT (server_config.port)
+#define SERVER_PORT6 (server_config.port)
#else
-#define SERVER_PORT 67
+#define SERVER_PORT 67
+#define SERVER_PORT6 547
#endif
diff --git a/release/src/router/busybox/networking/udhcp/dhcprelay.c b/release/src/router/busybox/networking/udhcp/dhcprelay.c
index a17a2bf4be..11482d22f1 100644
--- a/release/src/router/busybox/networking/udhcp/dhcprelay.c
+++ b/release/src/router/busybox/networking/udhcp/dhcprelay.c
@@ -33,7 +33,8 @@ struct xid_item {
struct xid_item *next;
} FIX_ALIASING;
-#define dhcprelay_xid_list (*(struct xid_item*)&bb_common_bufsiz1)
+#define dhcprelay_xid_list (*(struct xid_item*)bb_common_bufsiz1)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
static struct xid_item *xid_add(uint32_t xid, struct sockaddr_in *ip, int client)
{
@@ -257,6 +258,8 @@ int dhcprelay_main(int argc, char **argv)
int num_sockets, max_socket;
uint32_t our_nip;
+ INIT_G();
+
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
server_addr.sin_port = htons(SERVER_PORT);
diff --git a/release/src/router/busybox/networking/udhcp/domain_codec.c b/release/src/router/busybox/networking/udhcp/domain_codec.c
index c1325d8be9..5a923cc2cc 100644
--- a/release/src/router/busybox/networking/udhcp/domain_codec.c
+++ b/release/src/router/busybox/networking/udhcp/domain_codec.c
@@ -7,6 +7,7 @@
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
#ifdef DNS_COMPR_TESTING
+# define _GNU_SOURCE
# define FAST_FUNC /* nothing */
# define xmalloc malloc
# include <stdlib.h>
@@ -42,7 +43,7 @@ char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre)
*/
while (1) {
/* note: "return NULL" below are leak-safe since
- * dst isn't yet allocated */
+ * dst isn't allocated yet */
const uint8_t *c;
unsigned crtpos, retpos, depth, len;
@@ -63,11 +64,10 @@ char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre)
if (crtpos + *c + 1 > clen) /* label too long? abort */
return NULL;
if (dst)
- memcpy(dst + len, c + 1, *c);
+ /* \3com ---> "com." */
+ ((char*)mempcpy(dst + len, c + 1, *c))[0] = '.';
len += *c + 1;
crtpos += *c + 1;
- if (dst)
- dst[len - 1] = '.';
} else {
/* NUL: end of current domain name */
if (retpos == 0) {
@@ -78,7 +78,10 @@ char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre)
crtpos = retpos;
retpos = depth = 0;
}
- if (dst)
+ if (dst && len != 0)
+ /* \4host\3com\0\4host and we are at \0:
+ * \3com was converted to "com.", change dot to space.
+ */
dst[len - 1] = ' ';
}
@@ -95,9 +98,8 @@ char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre)
if (!dst) { /* first pass? */
/* allocate dst buffer and copy pre */
unsigned plen = strlen(pre);
- ret = dst = xmalloc(plen + len);
- memcpy(dst, pre, plen);
- dst += plen;
+ ret = xmalloc(plen + len);
+ dst = stpcpy(ret, pre);
} else {
dst[len - 1] = '\0';
break;
@@ -228,6 +230,9 @@ int main(int argc, char **argv)
int len;
uint8_t *encoded;
+ uint8_t str[6] = { 0x00, 0x00, 0x02, 0x65, 0x65, 0x00 };
+ printf("NUL:'%s'\n", dname_dec(str, 6, ""));
+
#define DNAME_DEC(encoded,pre) dname_dec((uint8_t*)(encoded), sizeof(encoded), (pre))
printf("'%s'\n", DNAME_DEC("\4host\3com\0", "test1:"));
printf("test2:'%s'\n", DNAME_DEC("\4host\3com\0\4host\3com\0", ""));
diff --git a/release/src/router/busybox/networking/udhcp/files.c b/release/src/router/busybox/networking/udhcp/files.c
index 1c8808c0f1..b22425352d 100644
--- a/release/src/router/busybox/networking/udhcp/files.c
+++ b/release/src/router/busybox/networking/udhcp/files.c
@@ -57,33 +57,35 @@ static int FAST_FUNC read_staticlease(const char *const_line, void *arg)
struct config_keyword {
const char *keyword;
int (*handler)(const char *line, void *var) FAST_FUNC;
- void *var;
+ unsigned ofs;
const char *def;
};
+#define OFS(field) offsetof(struct server_config_t, field)
+
static const struct config_keyword keywords[] = {
/* keyword handler variable address default */
- {"start" , udhcp_str2nip , &server_config.start_ip , "192.168.0.20"},
- {"end" , udhcp_str2nip , &server_config.end_ip , "192.168.0.254"},
- {"interface" , read_str , &server_config.interface , "eth0"},
+ {"start" , udhcp_str2nip , OFS(start_ip ), "192.168.0.20"},
+ {"end" , udhcp_str2nip , OFS(end_ip ), "192.168.0.254"},
+ {"interface" , read_str , OFS(interface ), "eth0"},
/* Avoid "max_leases value not sane" warning by setting default
* to default_end_ip - default_start_ip + 1: */
- {"max_leases" , read_u32 , &server_config.max_leases , "235"},
- {"auto_time" , read_u32 , &server_config.auto_time , "7200"},
- {"decline_time" , read_u32 , &server_config.decline_time , "3600"},
- {"conflict_time", read_u32 , &server_config.conflict_time, "3600"},
- {"offer_time" , read_u32 , &server_config.offer_time , "60"},
- {"min_lease" , read_u32 , &server_config.min_lease_sec, "60"},
- {"lease_file" , read_str , &server_config.lease_file , LEASES_FILE},
- {"pidfile" , read_str , &server_config.pidfile , "/var/run/udhcpd.pid"},
- {"siaddr" , udhcp_str2nip , &server_config.siaddr_nip , "0.0.0.0"},
+ {"max_leases" , read_u32 , OFS(max_leases ), "235"},
+ {"auto_time" , read_u32 , OFS(auto_time ), "7200"},
+ {"decline_time" , read_u32 , OFS(decline_time ), "3600"},
+ {"conflict_time", read_u32 , OFS(conflict_time), "3600"},
+ {"offer_time" , read_u32 , OFS(offer_time ), "60"},
+ {"min_lease" , read_u32 , OFS(min_lease_sec), "60"},
+ {"lease_file" , read_str , OFS(lease_file ), LEASES_FILE},
+ {"pidfile" , read_str , OFS(pidfile ), "/var/run/udhcpd.pid"},
+ {"siaddr" , udhcp_str2nip , OFS(siaddr_nip ), "0.0.0.0"},
/* keywords with no defaults must be last! */
- {"option" , udhcp_str2optset, &server_config.options , ""},
- {"opt" , udhcp_str2optset, &server_config.options , ""},
- {"notify_file" , read_str , &server_config.notify_file , NULL},
- {"sname" , read_str , &server_config.sname , NULL},
- {"boot_file" , read_str , &server_config.boot_file , NULL},
- {"static_lease" , read_staticlease, &server_config.static_leases, ""},
+ {"option" , udhcp_str2optset, OFS(options ), ""},
+ {"opt" , udhcp_str2optset, OFS(options ), ""},
+ {"notify_file" , read_str , OFS(notify_file ), NULL},
+ {"sname" , read_str , OFS(sname ), NULL},
+ {"boot_file" , read_str , OFS(boot_file ), NULL},
+ {"static_lease" , read_staticlease, OFS(static_leases), ""},
};
enum { KWS_WITH_DEFAULTS = ARRAY_SIZE(keywords) - 6 };
@@ -95,17 +97,17 @@ void FAST_FUNC read_config(const char *file)
char *token[2];
for (i = 0; i < KWS_WITH_DEFAULTS; i++)
- keywords[i].handler(keywords[i].def, keywords[i].var);
+ keywords[i].handler(keywords[i].def, (char*)&server_config + keywords[i].ofs);
parser = config_open(file);
while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL)) {
for (k = keywords, i = 0; i < ARRAY_SIZE(keywords); k++, i++) {
if (strcasecmp(token[0], k->keyword) == 0) {
- if (!k->handler(token[1], k->var)) {
+ if (!k->handler(token[1], (char*)&server_config + k->ofs)) {
bb_error_msg("can't parse line %u in %s",
parser->lineno, file);
/* reset back to the default value */
- k->handler(k->def, k->var);
+ k->handler(k->def, (char*)&server_config + k->ofs);
}
break;
}
@@ -195,7 +197,11 @@ void FAST_FUNC read_leases(const char *file)
uint32_t static_nip;
if (expires <= 0)
- continue;
+ /* We keep expired leases: add_lease() will add
+ * a lease with 0 seconds remaining.
+ * Fewer IP address changes this way for mass reboot scenario.
+ */
+ expires = 0;
/* Check if there is a different static lease for this IP or MAC */
static_nip = get_static_nip_by_mac(server_config.static_leases, lease.lease_mac);
@@ -222,7 +228,7 @@ void FAST_FUNC read_leases(const char *file)
#endif
}
}
- log1("Read %d leases", i);
+ log1("read %d leases", i);
ret:
close(fd);
}
diff --git a/release/src/router/busybox/networking/udhcp/leases.c b/release/src/router/busybox/networking/udhcp/leases.c
index 844bb60b17..2b0dbb2e31 100644
--- a/release/src/router/busybox/networking/udhcp/leases.c
+++ b/release/src/router/busybox/networking/udhcp/leases.c
@@ -17,7 +17,9 @@ static struct dyn_lease *oldest_expired_lease(void)
/* Unexpired leases have g_leases[i].expires >= current time
* and therefore can't ever match */
for (i = 0; i < server_config.max_leases; i++) {
- if (g_leases[i].expires < oldest_time) {
+ if (g_leases[i].expires == 0 /* empty entry */
+ || g_leases[i].expires < oldest_time
+ ) {
oldest_time = g_leases[i].expires;
oldest_lease = &g_leases[i];
}
@@ -131,7 +133,7 @@ static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac, unsigne
return r;
temp.s_addr = nip;
- bb_info_msg("%s belongs to someone, reserving it for %u seconds",
+ bb_error_msg("%s belongs to someone, reserving it for %u seconds",
inet_ntoa(temp), (unsigned)server_config.conflict_time);
add_lease(NULL, nip, server_config.conflict_time, NULL, 0);
return 0;
@@ -152,7 +154,7 @@ uint32_t FAST_FUNC find_free_or_expired_nip(const uint8_t *safe_mac, unsigned ar
*/
hash = 0;
for (i = 0; i < 6; i++)
- hash += safe_mac[i] + (hash << 6) + (hash << 16) - hash;
+ hash = safe_mac[i] + (hash << 6) + (hash << 16) - hash;
/* pick a seed based on hwaddr then iterate until we find a free address. */
addr = server_config.start_ip
diff --git a/release/src/router/busybox/networking/udhcp/packet.c b/release/src/router/busybox/networking/udhcp/packet.c
index 148f52551a..223813f352 100644
--- a/release/src/router/busybox/networking/udhcp/packet.c
+++ b/release/src/router/busybox/networking/udhcp/packet.c
@@ -38,8 +38,8 @@ void FAST_FUNC udhcp_dump_packet(struct dhcp_packet *packet)
if (dhcp_verbose < 2)
return;
- bb_info_msg(
- //" op %x"
+ bb_error_msg(
+ //"op %x"
//" htype %x"
" hlen %x"
//" hops %x"
@@ -73,7 +73,7 @@ void FAST_FUNC udhcp_dump_packet(struct dhcp_packet *packet)
//, packet->options[]
);
*bin2hex(buf, (void *) packet->chaddr, sizeof(packet->chaddr)) = '\0';
- bb_info_msg(" chaddr %s", buf);
+ bb_error_msg("chaddr %s", buf);
}
#endif
@@ -85,17 +85,17 @@ int FAST_FUNC udhcp_recv_kernel_packet(struct dhcp_packet *packet, int fd)
memset(packet, 0, sizeof(*packet));
bytes = safe_read(fd, packet, sizeof(*packet));
if (bytes < 0) {
- log1("Packet read error, ignoring");
+ log1("packet read error, ignoring");
return bytes; /* returns -1 */
}
if (bytes < offsetof(struct dhcp_packet, options)
|| packet->cookie != htonl(DHCP_MAGIC)
) {
- bb_info_msg("Packet with bad magic, ignoring");
+ bb_error_msg("packet with bad magic, ignoring");
return -2;
}
- log1("Received a packet");
+ log1("received %s", "a packet");
udhcp_dump_packet(packet);
return bytes;
@@ -110,12 +110,23 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt,
struct sockaddr_ll dest_sll;
struct ip_udp_dhcp_packet packet;
unsigned padding;
- int fd;
+ int fd, ttl;
int result = -1;
+ socklen_t optlen;
const char *msg;
+ fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (fd < 0)
+ goto ret_sock;
+
+ optlen = sizeof(ttl);
+ if (getsockopt(fd, IPPROTO_IP, IP_TTL, &ttl, &optlen) < 0)
+ ttl = IPDEFTTL;
+ close(fd);
+
fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
if (fd < 0) {
+ ret_sock:
msg = "socket(%s)";
goto ret_msg;
}
@@ -168,7 +179,7 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt,
packet.ip.tot_len = htons(IP_UDP_DHCP_SIZE - padding);
packet.ip.ihl = sizeof(packet.ip) >> 2;
packet.ip.version = IPVERSION;
- packet.ip.ttl = IPDEFTTL;
+ packet.ip.ttl = ttl;
packet.ip.check = inet_cksum((uint16_t *)&packet.ip, sizeof(packet.ip));
udhcp_dump_packet(dhcp_pkt);
diff --git a/release/src/router/busybox/networking/udhcp/socket.c b/release/src/router/busybox/networking/udhcp/socket.c
index 1a12fb4886..06738ca581 100644
--- a/release/src/router/busybox/networking/udhcp/socket.c
+++ b/release/src/router/busybox/networking/udhcp/socket.c
@@ -57,7 +57,7 @@ int FAST_FUNC udhcp_read_interface(const char *interface, int *ifindex,
close(fd);
return -1;
}
- log1("Adapter index %d", ifr->ifr_ifindex);
+ log1("adapter index %d", ifr->ifr_ifindex);
*ifindex = ifr->ifr_ifindex;
}
@@ -76,7 +76,7 @@ int FAST_FUNC udhcp_read_interface(const char *interface, int *ifindex,
close(fd);
return -1;
}
- log1("Adapter mtu %d", ifr->ifr_mtu);
+ log1("MTU %d", ifr->ifr_mtu);
*mtu = ifr->ifr_mtu;
}
@@ -92,7 +92,7 @@ int FAST_FUNC udhcp_listen_socket(/*uint32_t ip,*/ int port, const char *inf)
struct sockaddr_in addr;
char *colon;
- log1("Opening listen socket on *:%d %s", port, inf);
+ log1("opening listen socket on *:%d %s", port, inf);
fd = xsocket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
setsockopt_reuseaddr(fd);
diff --git a/release/src/router/busybox/networking/udhcp/static_leases.c b/release/src/router/busybox/networking/udhcp/static_leases.c
index f4a24ab627..b7f9e5c594 100644
--- a/release/src/router/busybox/networking/udhcp/static_leases.c
+++ b/release/src/router/busybox/networking/udhcp/static_leases.c
@@ -66,7 +66,7 @@ void FAST_FUNC log_static_leases(struct static_lease **st_lease_pp)
cur = *st_lease_pp;
while (cur) {
- bb_info_msg("static lease: mac:%02x:%02x:%02x:%02x:%02x:%02x nip:%x",
+ bb_error_msg("static lease: mac:%02x:%02x:%02x:%02x:%02x:%02x nip:%x",
cur->mac[0], cur->mac[1], cur->mac[2],
cur->mac[3], cur->mac[4], cur->mac[5],
cur->nip
diff --git a/release/src/router/busybox/networking/wget.c b/release/src/router/busybox/networking/wget.c
index 46511d5876..e21c4dfdcc 100644
--- a/release/src/router/busybox/networking/wget.c
+++ b/release/src/router/busybox/networking/wget.c
@@ -9,12 +9,102 @@
* Kuhn's copyrights are licensed GPLv2-or-later. File as a whole remains GPLv2.
*/
+//config:config WGET
+//config: bool "wget"
+//config: default y
+//config: help
+//config: wget is a utility for non-interactive download of files from HTTP
+//config: and FTP servers.
+//config:
+//config:config FEATURE_WGET_STATUSBAR
+//config: bool "Enable a nifty process meter (+2k)"
+//config: default y
+//config: depends on WGET
+//config: help
+//config: Enable the transfer progress bar for wget transfers.
+//config:
+//config:config FEATURE_WGET_AUTHENTICATION
+//config: bool "Enable HTTP authentication"
+//config: default y
+//config: depends on WGET
+//config: help
+//config: Support authenticated HTTP transfers.
+//config:
+//config:config FEATURE_WGET_LONG_OPTIONS
+//config: bool "Enable long options"
+//config: default y
+//config: depends on WGET && LONG_OPTS
+//config: help
+//config: Support long options for the wget applet.
+//config:
+//config:config FEATURE_WGET_TIMEOUT
+//config: bool "Enable timeout option -T SEC"
+//config: default y
+//config: depends on WGET
+//config: help
+//config: Supports network read and connect timeouts for wget,
+//config: so that wget will give up and timeout, through the -T
+//config: command line option.
+//config:
+//config: Currently only connect and network data read timeout are
+//config: supported (i.e., timeout is not applied to the DNS query). When
+//config: FEATURE_WGET_LONG_OPTIONS is also enabled, the --timeout option
+//config: will work in addition to -T.
+//config:
+//config:config FEATURE_WGET_OPENSSL
+//config: bool "Try to connect to HTTPS using openssl"
+//config: default y
+//config: depends on WGET
+//config: help
+//config: Choose how wget establishes SSL connection for https:// URLs.
+//config:
+//config: Busybox itself contains no SSL code. wget will spawn
+//config: a helper program to talk over HTTPS.
+//config:
+//config: OpenSSL has a simple SSL client for debug purposes.
+//config: If you select "openssl" helper, wget will effectively call
+//config: "openssl s_client -quiet -connect IP:443 2>/dev/null"
+//config: and pipe its data through it.
+//config: Note inconvenient API: host resolution is done twice,
+//config: and there is no guarantee openssl's idea of IPv6 address
+//config: format is the same as ours.
+//config: Another problem is that s_client prints debug information
+//config: to stderr, and it needs to be suppressed. This means
+//config: all error messages get suppressed too.
+//config: openssl is also a big binary, often dynamically linked
+//config: against ~15 libraries.
+//config:
+//config:config FEATURE_WGET_SSL_HELPER
+//config: bool "Try to connect to HTTPS using ssl_helper"
+//config: default y
+//config: depends on WGET
+//config: help
+//config: Choose how wget establishes SSL connection for https:// URLs.
+//config:
+//config: Busybox itself contains no SSL code. wget will spawn
+//config: a helper program to talk over HTTPS.
+//config:
+//config: ssl_helper is a tool which can be built statically
+//config: from busybox sources against a small embedded SSL library.
+//config: Please see networking/ssl_helper/README.
+//config: It does not require double host resolution and emits
+//config: error messages to stderr.
+//config:
+//config: Precompiled static binary may be available at
+//config: http://busybox.net/downloads/binaries/
+
+//applet:IF_WGET(APPLET(wget, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_WGET) += wget.o
+
//usage:#define wget_trivial_usage
//usage: IF_FEATURE_WGET_LONG_OPTIONS(
//usage: "[-c|--continue] [-s|--spider] [-q|--quiet] [-O|--output-document FILE]\n"
//usage: " [--header 'header: value'] [-Y|--proxy on/off] [-P DIR]\n"
-//usage: " [--no-check-certificate] [-U|--user-agent AGENT]"
-//usage: IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..."
+/* Since we ignore these opts, we don't show them in --help */
+/* //usage: " [--no-check-certificate] [--no-cache] [--passive-ftp] [-t TRIES]" */
+/* //usage: " [-nv] [-nc] [-nH] [-np]" */
+//usage: " [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..."
//usage: )
//usage: IF_NOT_FEATURE_WGET_LONG_OPTIONS(
//usage: "[-csq] [-O FILE] [-Y on/off] [-P DIR] [-U AGENT]"
@@ -35,19 +125,63 @@
#include "libbb.h"
-//#define log_io(...) bb_error_msg(__VA_ARGS__)
-#define log_io(...) ((void)0)
+#if 0
+# define log_io(...) bb_error_msg(__VA_ARGS__)
+# define SENDFMT(fp, fmt, ...) \
+ do { \
+ log_io("> " fmt, ##__VA_ARGS__); \
+ fprintf(fp, fmt, ##__VA_ARGS__); \
+ } while (0);
+#else
+# define log_io(...) ((void)0)
+# define SENDFMT(fp, fmt, ...) fprintf(fp, fmt, ##__VA_ARGS__)
+#endif
struct host_info {
char *allocated;
const char *path;
- const char *user;
+ char *user;
+ const char *protocol;
char *host;
int port;
- smallint is_ftp;
};
+static const char P_FTP[] ALIGN1 = "ftp";
+static const char P_HTTP[] ALIGN1 = "http";
+#if ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_SSL_HELPER
+static const char P_HTTPS[] ALIGN1 = "https";
+#endif
+#if ENABLE_FEATURE_WGET_LONG_OPTIONS
+/* User-specified headers prevent using our corresponding built-in headers. */
+enum {
+ HDR_HOST = (1<<0),
+ HDR_USER_AGENT = (1<<1),
+ HDR_RANGE = (1<<2),
+ HDR_AUTH = (1<<3) * ENABLE_FEATURE_WGET_AUTHENTICATION,
+ HDR_PROXY_AUTH = (1<<4) * ENABLE_FEATURE_WGET_AUTHENTICATION,
+};
+static const char wget_user_headers[] ALIGN1 =
+ "Host:\0"
+ "User-Agent:\0"
+ "Range:\0"
+# if ENABLE_FEATURE_WGET_AUTHENTICATION
+ "Authorization:\0"
+ "Proxy-Authorization:\0"
+# endif
+ ;
+# define USR_HEADER_HOST (G.user_headers & HDR_HOST)
+# define USR_HEADER_USER_AGENT (G.user_headers & HDR_USER_AGENT)
+# define USR_HEADER_RANGE (G.user_headers & HDR_RANGE)
+# define USR_HEADER_AUTH (G.user_headers & HDR_AUTH)
+# define USR_HEADER_PROXY_AUTH (G.user_headers & HDR_PROXY_AUTH)
+#else /* No long options, no user-headers :( */
+# define USR_HEADER_HOST 0
+# define USR_HEADER_USER_AGENT 0
+# define USR_HEADER_RANGE 0
+# define USR_HEADER_AUTH 0
+# define USR_HEADER_PROXY_AUTH 0
+#endif
/* Globals */
struct globals {
@@ -58,16 +192,18 @@ struct globals {
const char *curfile; /* Name of current file being transferred */
bb_progress_t pmt;
#endif
- char *dir_prefix;
+ char *dir_prefix;
#if ENABLE_FEATURE_WGET_LONG_OPTIONS
- char *post_data;
- char *extra_headers;
+ char *post_data;
+ char *extra_headers;
+ unsigned char user_headers; /* Headers mentioned by the user */
#endif
- char *fname_out; /* where to direct output (-O) */
- const char *proxy_flag; /* Use proxies if env vars are set */
- const char *user_agent; /* "User-Agent" header field */
+ char *fname_out; /* where to direct output (-O) */
+ const char *proxy_flag; /* Use proxies if env vars are set */
+ const char *user_agent; /* "User-Agent" header field */
#if ENABLE_FEATURE_WGET_TIMEOUT
unsigned timeout_seconds;
+ bool die_if_timed_out;
#endif
int output_fd;
int o_flags;
@@ -82,8 +218,10 @@ struct globals {
} FIX_ALIASING;
#define G (*ptr_to_globals)
#define INIT_G() do { \
- SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
- IF_FEATURE_WGET_TIMEOUT(G.timeout_seconds = 900;) \
+ SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
+} while (0)
+#define FINI_G() do { \
+ FREE_PTR_TO_GLOBALS(); \
} while (0)
@@ -191,14 +329,39 @@ static char* sanitize_string(char *s)
return s;
}
+#if ENABLE_FEATURE_WGET_TIMEOUT
+static void alarm_handler(int sig UNUSED_PARAM)
+{
+ /* This is theoretically unsafe (uses stdio and malloc in signal handler) */
+ if (G.die_if_timed_out)
+ bb_error_msg_and_die("download timed out");
+}
+static void set_alarm(void)
+{
+ if (G.timeout_seconds) {
+ alarm(G.timeout_seconds);
+ G.die_if_timed_out = 1;
+ }
+}
+# define clear_alarm() ((void)(G.die_if_timed_out = 0))
+#else
+# define set_alarm() ((void)0)
+# define clear_alarm() ((void)0)
+#endif
+
static FILE *open_socket(len_and_sockaddr *lsa)
{
+ int fd;
FILE *fp;
+ set_alarm();
+ fd = xconnect_stream(lsa);
+ clear_alarm();
+
/* glibc 2.4 seems to try seeking on it - ??! */
/* hopefully it understands what ESPIPE means... */
- fp = fdopen(xconnect_stream(lsa), "r+");
- if (fp == NULL)
+ fp = fdopen(fd, "r+");
+ if (!fp)
bb_perror_msg_and_die(bb_msg_memory_exhausted);
return fp;
@@ -210,8 +373,10 @@ static char fgets_and_trim(FILE *fp)
char c;
char *buf_ptr;
+ set_alarm();
if (fgets(G.wget_buf, sizeof(G.wget_buf) - 1, fp) == NULL)
bb_perror_msg_and_die("error getting response");
+ clear_alarm();
buf_ptr = strchrnul(G.wget_buf, '\n');
c = *buf_ptr;
@@ -252,16 +417,33 @@ static void parse_url(const char *src_url, struct host_info *h)
free(h->allocated);
h->allocated = url = xstrdup(src_url);
- if (strncmp(url, "http://", 7) == 0) {
- h->port = bb_lookup_port("http", "tcp", 80);
- h->host = url + 7;
- h->is_ftp = 0;
- } else if (strncmp(url, "ftp://", 6) == 0) {
- h->port = bb_lookup_port("ftp", "tcp", 21);
- h->host = url + 6;
- h->is_ftp = 1;
- } else
- bb_error_msg_and_die("not an http or ftp url: %s", sanitize_string(url));
+ h->protocol = P_FTP;
+ p = strstr(url, "://");
+ if (p) {
+ *p = '\0';
+ h->host = p + 3;
+ if (strcmp(url, P_FTP) == 0) {
+ h->port = bb_lookup_port(P_FTP, "tcp", 21);
+ } else
+#if ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_SSL_HELPER
+ if (strcmp(url, P_HTTPS) == 0) {
+ h->port = bb_lookup_port(P_HTTPS, "tcp", 443);
+ h->protocol = P_HTTPS;
+ } else
+#endif
+ if (strcmp(url, P_HTTP) == 0) {
+ http:
+ h->port = bb_lookup_port(P_HTTP, "tcp", 80);
+ h->protocol = P_HTTP;
+ } else {
+ *p = ':';
+ bb_error_msg_and_die("not an http or ftp url: %s", sanitize_string(url));
+ }
+ } else {
+ // GNU wget is user-friendly and falls back to http://
+ h->host = url;
+ goto http;
+ }
// FYI:
// "Real" wget 'http://busybox.net?var=a/b' sends this request:
@@ -293,9 +475,6 @@ static void parse_url(const char *src_url, struct host_info *h)
h->path = sp;
}
- // We used to set h->user to NULL here, but this interferes
- // with handling of code 302 ("object was moved")
-
sp = strrchr(h->host, '@');
if (sp != NULL) {
// URL-decode "user:password" string before base64-encoding:
@@ -304,11 +483,13 @@ static void parse_url(const char *src_url, struct host_info *h)
// which decodes to "test:my pass".
// Standard wget and curl do this too.
*sp = '\0';
- h->user = percent_decode_in_place(h->host, /*strict:*/ 0);
+ free(h->user);
+ h->user = xstrdup(percent_decode_in_place(h->host, /*strict:*/ 0));
h->host = sp + 1;
}
-
- sp = h->host;
+ /* else: h->user remains NULL, or as set by original request
+ * before redirect (if we are here after a redirect).
+ */
}
static char *gethdr(FILE *fp)
@@ -316,8 +497,6 @@ static char *gethdr(FILE *fp)
char *s, *hdrval;
int c;
- /* *istrunc = 0; */
-
/* retrieve header line */
c = fgets_and_trim(fp);
@@ -326,8 +505,16 @@ static char *gethdr(FILE *fp)
return NULL;
/* convert the header name to lower case */
- for (s = G.wget_buf; isalnum(*s) || *s == '-' || *s == '.'; ++s) {
- /* tolower for "A-Z", no-op for "0-9a-z-." */
+ for (s = G.wget_buf; isalnum(*s) || *s == '-' || *s == '.' || *s == '_'; ++s) {
+ /*
+ * No-op for 20-3f and 60-7f. "0-9a-z-." are in these ranges.
+ * 40-5f range ("@A-Z[\]^_") maps to 60-7f.
+ * "A-Z" maps to "a-z".
+ * "@[\]" can't occur in header names.
+ * "^_" maps to "~,DEL" (which is wrong).
+ * "^" was never seen yet, "_" was seen from web.archive.org
+ * (x-archive-orig-x_commoncrawl_Signature: HEXSTRING).
+ */
*s |= 0x20;
}
@@ -438,6 +625,104 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_
return sfp;
}
+#if ENABLE_FEATURE_WGET_OPENSSL
+static int spawn_https_helper_openssl(const char *host, unsigned port)
+{
+ char *allocated = NULL;
+ int sp[2];
+ int pid;
+ IF_FEATURE_WGET_SSL_HELPER(volatile int child_failed = 0;)
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0)
+ /* Kernel can have AF_UNIX support disabled */
+ bb_perror_msg_and_die("socketpair");
+
+ if (!strchr(host, ':'))
+ host = allocated = xasprintf("%s:%u", host, port);
+
+ fflush_all();
+ pid = xvfork();
+ if (pid == 0) {
+ /* Child */
+ char *argv[6];
+
+ close(sp[0]);
+ xmove_fd(sp[1], 0);
+ xdup2(0, 1);
+ /*
+ * openssl s_client -quiet -connect www.kernel.org:443 2>/dev/null
+ * It prints some debug stuff on stderr, don't know how to suppress it.
+ * Work around by dev-nulling stderr. We lose all error messages :(
+ */
+ xmove_fd(2, 3);
+ xopen("/dev/null", O_RDWR);
+ argv[0] = (char*)"openssl";
+ argv[1] = (char*)"s_client";
+ argv[2] = (char*)"-quiet";
+ argv[3] = (char*)"-connect";
+ argv[4] = (char*)host;
+ argv[5] = NULL;
+ BB_EXECVP(argv[0], argv);
+ xmove_fd(3, 2);
+# if ENABLE_FEATURE_WGET_SSL_HELPER
+ child_failed = 1;
+ xfunc_die();
+# else
+ bb_perror_msg_and_die("can't execute '%s'", argv[0]);
+# endif
+ /* notreached */
+ }
+
+ /* Parent */
+ free(allocated);
+ close(sp[1]);
+# if ENABLE_FEATURE_WGET_SSL_HELPER
+ if (child_failed) {
+ close(sp[0]);
+ return -1;
+ }
+# endif
+ return sp[0];
+}
+#endif
+
+/* See networking/ssl_helper/README how to build one */
+#if ENABLE_FEATURE_WGET_SSL_HELPER
+static void spawn_https_helper_small(int network_fd)
+{
+ int sp[2];
+ int pid;
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0)
+ /* Kernel can have AF_UNIX support disabled */
+ bb_perror_msg_and_die("socketpair");
+
+ pid = BB_MMU ? xfork() : xvfork();
+ if (pid == 0) {
+ /* Child */
+ char *argv[3];
+
+ close(sp[0]);
+ xmove_fd(sp[1], 0);
+ xdup2(0, 1);
+ xmove_fd(network_fd, 3);
+ /*
+ * A simple ssl/tls helper
+ */
+ argv[0] = (char*)"ssl_helper";
+ argv[1] = (char*)"-d3";
+ argv[2] = NULL;
+ BB_EXECVP(argv[0], argv);
+ bb_perror_msg_and_die("can't execute '%s'", argv[0]);
+ /* notreached */
+ }
+
+ /* Parent */
+ close(sp[1]);
+ xmove_fd(sp[0], network_fd);
+}
+#endif
+
static void NOINLINE retrieve_file_data(FILE *dfp)
{
#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
@@ -506,7 +791,7 @@ static void NOINLINE retrieve_file_data(FILE *dfp)
#if ENABLE_FEATURE_WGET_TIMEOUT
second_cnt = G.timeout_seconds;
#endif
- continue;
+ goto bump;
}
/* n <= 0.
@@ -539,11 +824,12 @@ static void NOINLINE retrieve_file_data(FILE *dfp)
* to try reading anyway.
*/
}
+#endif
+ bump:
/* Need to do it _every_ second for "stalled" indicator
* to be shown properly.
*/
progress_meter(PROGRESS_BUMP);
-#endif
} /* while (reading data) */
#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
@@ -610,7 +896,8 @@ static void download_one_url(const char *url)
/* Use the proxy if necessary */
use_proxy = (strcmp(G.proxy_flag, "off") != 0);
if (use_proxy) {
- proxy = getenv(target.is_ftp ? "ftp_proxy" : "http_proxy");
+ proxy = getenv(target.protocol == P_FTP ? "ftp_proxy" : "http_proxy");
+//FIXME: what if protocol is https? Ok to use http_proxy?
use_proxy = (proxy && proxy[0]);
if (use_proxy)
parse_url(proxy, &server);
@@ -670,57 +957,88 @@ static void download_one_url(const char *url)
/*G.content_len = 0; - redundant, got_clen = 0 is enough */
G.got_clen = 0;
G.chunked = 0;
- if (use_proxy || !target.is_ftp) {
+ if (use_proxy || target.protocol != P_FTP) {
/*
* HTTP session
*/
char *str;
int status;
-
- /* Open socket to http server */
+ /* Open socket to http(s) server */
+#if ENABLE_FEATURE_WGET_OPENSSL
+ /* openssl (and maybe ssl_helper) support is configured */
+ if (target.protocol == P_HTTPS) {
+ /* openssl-based helper
+ * Inconvenient API since we can't give it an open fd
+ */
+ int fd = spawn_https_helper_openssl(server.host, server.port);
+# if ENABLE_FEATURE_WGET_SSL_HELPER
+ if (fd < 0) { /* no openssl? try ssl_helper */
+ sfp = open_socket(lsa);
+ spawn_https_helper_small(fileno(sfp));
+ goto socket_opened;
+ }
+# else
+ /* We don't check for exec("openssl") failure in this case */
+# endif
+ sfp = fdopen(fd, "r+");
+ if (!sfp)
+ bb_perror_msg_and_die(bb_msg_memory_exhausted);
+ goto socket_opened;
+ }
sfp = open_socket(lsa);
-
+ socket_opened:
+#elif ENABLE_FEATURE_WGET_SSL_HELPER
+ /* Only ssl_helper support is configured */
+ sfp = open_socket(lsa);
+ if (target.protocol == P_HTTPS)
+ spawn_https_helper_small(fileno(sfp));
+#else
+ /* ssl (https) support is not configured */
+ sfp = open_socket(lsa);
+#endif
/* Send HTTP request */
if (use_proxy) {
- fprintf(sfp, "GET %stp://%s/%s HTTP/1.1\r\n",
- target.is_ftp ? "f" : "ht", target.host,
+ SENDFMT(sfp, "GET %s://%s/%s HTTP/1.1\r\n",
+ target.protocol, target.host,
target.path);
} else {
- if (option_mask32 & WGET_OPT_POST_DATA)
- fprintf(sfp, "POST /%s HTTP/1.1\r\n", target.path);
- else
- fprintf(sfp, "GET /%s HTTP/1.1\r\n", target.path);
+ SENDFMT(sfp, "%s /%s HTTP/1.1\r\n",
+ (option_mask32 & WGET_OPT_POST_DATA) ? "POST" : "GET",
+ target.path);
}
-
- fprintf(sfp, "Host: %s\r\nUser-Agent: %s\r\n",
- target.host, G.user_agent);
+ if (!USR_HEADER_HOST)
+ SENDFMT(sfp, "Host: %s\r\n", target.host);
+ if (!USR_HEADER_USER_AGENT)
+ SENDFMT(sfp, "User-Agent: %s\r\n", G.user_agent);
/* Ask server to close the connection as soon as we are done
* (IOW: we do not intend to send more requests)
*/
- fprintf(sfp, "Connection: close\r\n");
+ SENDFMT(sfp, "Connection: close\r\n");
#if ENABLE_FEATURE_WGET_AUTHENTICATION
- if (target.user) {
- fprintf(sfp, "Proxy-Authorization: Basic %s\r\n"+6,
+ if (target.user && !USR_HEADER_AUTH) {
+ SENDFMT(sfp, "Proxy-Authorization: Basic %s\r\n"+6,
base64enc(target.user));
}
- if (use_proxy && server.user) {
- fprintf(sfp, "Proxy-Authorization: Basic %s\r\n",
+ if (use_proxy && server.user && !USR_HEADER_PROXY_AUTH) {
+ SENDFMT(sfp, "Proxy-Authorization: Basic %s\r\n",
base64enc(server.user));
}
#endif
- if (G.beg_range != 0)
- fprintf(sfp, "Range: bytes=%"OFF_FMT"u-\r\n", G.beg_range);
+ if (G.beg_range != 0 && !USR_HEADER_RANGE)
+ SENDFMT(sfp, "Range: bytes=%"OFF_FMT"u-\r\n", G.beg_range);
#if ENABLE_FEATURE_WGET_LONG_OPTIONS
- if (G.extra_headers)
+ if (G.extra_headers) {
+ log_io(G.extra_headers);
fputs(G.extra_headers, sfp);
+ }
if (option_mask32 & WGET_OPT_POST_DATA) {
- fprintf(sfp,
+ SENDFMT(sfp,
"Content-Type: application/x-www-form-urlencoded\r\n"
"Content-Length: %u\r\n"
"\r\n"
@@ -730,7 +1048,7 @@ static void download_one_url(const char *url)
} else
#endif
{
- fprintf(sfp, "\r\n");
+ SENDFMT(sfp, "\r\n");
}
fflush(sfp);
@@ -791,6 +1109,13 @@ However, in real world it was observed that some web servers
case 302:
case 303:
break;
+ case 416: /* Requested Range Not Satisfiable */
+ if (G.beg_range != 0) {
+ G.content_len = 0;
+ G.got_clen = 1;
+ goto skip_response;
+ }
+ /* fall through */
case 206: /* Partial Content */
if (G.beg_range != 0)
/* "Range:..." worked. Good. */
@@ -845,6 +1170,7 @@ However, in real world it was observed that some web servers
} else {
parse_url(str, &target);
if (!use_proxy) {
+ /* server.user remains untouched */
free(server.allocated);
server.allocated = NULL;
server.host = target.host;
@@ -861,9 +1187,9 @@ However, in real world it was observed that some web servers
// if (status >= 300)
// bb_error_msg_and_die("bad redirection (no Location: header from server)");
+ skip_response:
/* For HTTP, data is pumped over the same connection */
dfp = sfp;
-
} else {
/*
* FTP session
@@ -894,6 +1220,8 @@ However, in real world it was observed that some web servers
free(server.allocated);
free(target.allocated);
+ free(server.user);
+ free(target.user);
free(fname_out_alloc);
free(redirected_path);
}
@@ -912,17 +1240,22 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
"directory-prefix\0" Required_argument "P"
"proxy\0" Required_argument "Y"
"user-agent\0" Required_argument "U"
-#if ENABLE_FEATURE_WGET_TIMEOUT
- "timeout\0" Required_argument "T"
-#endif
+IF_FEATURE_WGET_TIMEOUT(
+ "timeout\0" Required_argument "T")
/* Ignored: */
- // "tries\0" Required_argument "t"
+IF_DESKTOP( "tries\0" Required_argument "t")
+ "header\0" Required_argument "\xff"
+ "post-data\0" Required_argument "\xfe"
/* Ignored (we always use PASV): */
- "passive-ftp\0" No_argument "\xff"
- "header\0" Required_argument "\xfe"
- "post-data\0" Required_argument "\xfd"
+IF_DESKTOP( "passive-ftp\0" No_argument "\xf0")
/* Ignored (we don't do ssl) */
- "no-check-certificate\0" No_argument "\xfc"
+IF_DESKTOP( "no-check-certificate\0" No_argument "\xf0")
+ /* Ignored (we don't support caching) */
+IF_DESKTOP( "no-cache\0" No_argument "\xf0")
+IF_DESKTOP( "no-verbose\0" No_argument "\xf0")
+IF_DESKTOP( "no-clobber\0" No_argument "\xf0")
+IF_DESKTOP( "no-host-directories\0" No_argument "\xf0")
+IF_DESKTOP( "no-parent\0" No_argument "\xf0")
;
#endif
@@ -932,19 +1265,35 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
INIT_G();
- IF_FEATURE_WGET_TIMEOUT(G.timeout_seconds = 900;)
+#if ENABLE_FEATURE_WGET_TIMEOUT
+ G.timeout_seconds = 900;
+ signal(SIGALRM, alarm_handler);
+#endif
G.proxy_flag = "on"; /* use proxies if env vars are set */
G.user_agent = "Wget"; /* "User-Agent" header field */
#if ENABLE_FEATURE_WGET_LONG_OPTIONS
applet_long_options = wget_longopts;
#endif
- opt_complementary = "-1" IF_FEATURE_WGET_TIMEOUT(":T+") IF_FEATURE_WGET_LONG_OPTIONS(":\xfe::");
- getopt32(argv, "csqO:P:Y:U:T:" /*ignored:*/ "t:",
- &G.fname_out, &G.dir_prefix,
+ opt_complementary = "-1" /* at least one URL */
+ IF_FEATURE_WGET_TIMEOUT(":T+") /* -T NUM */
+ IF_FEATURE_WGET_LONG_OPTIONS(":\xff::"); /* --header is a list */
+ getopt32(argv, "csqO:P:Y:U:T:"
+ /*ignored:*/ "t:"
+ /*ignored:*/ "n::"
+ /* wget has exactly four -n<letter> opts, all of which we can ignore:
+ * -nv --no-verbose: be moderately quiet (-q is full quiet)
+ * -nc --no-clobber: abort if exists, neither download to FILE.n nor overwrite FILE
+ * -nH --no-host-directories: wget -r http://host/ won't create host/
+ * -np --no-parent
+ * "n::" above says that we accept -n[ARG].
+ * Specifying "n:" would be a bug: "-n ARG" would eat ARG!
+ */
+ , &G.fname_out, &G.dir_prefix,
&G.proxy_flag, &G.user_agent,
IF_FEATURE_WGET_TIMEOUT(&G.timeout_seconds) IF_NOT_FEATURE_WGET_TIMEOUT(NULL),
- NULL /* -t RETRIES */
+ NULL, /* -t RETRIES */
+ NULL /* -n[ARG] */
IF_FEATURE_WGET_LONG_OPTIONS(, &headers_llist)
IF_FEATURE_WGET_LONG_OPTIONS(, &G.post_data)
);
@@ -952,16 +1301,32 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
#if ENABLE_FEATURE_WGET_LONG_OPTIONS
if (headers_llist) {
- int size = 1;
- char *cp;
+ int size = 0;
+ char *hdr;
llist_t *ll = headers_llist;
while (ll) {
size += strlen(ll->data) + 2;
ll = ll->link;
}
- G.extra_headers = cp = xmalloc(size);
+ G.extra_headers = hdr = xmalloc(size + 1);
while (headers_llist) {
- cp += sprintf(cp, "%s\r\n", (char*)llist_pop(&headers_llist));
+ int bit;
+ const char *words;
+
+ size = sprintf(hdr, "%s\r\n",
+ (char*)llist_pop(&headers_llist));
+ /* a bit like index_in_substrings but don't match full key */
+ bit = 1;
+ words = wget_user_headers;
+ while (*words) {
+ if (strstr(hdr, words) == hdr) {
+ G.user_headers |= bit;
+ break;
+ }
+ bit <<= 1;
+ words += strlen(words) + 1;
+ }
+ hdr += size;
}
}
#endif
@@ -983,5 +1348,10 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
if (G.output_fd >= 0)
xclose(G.output_fd);
+#if ENABLE_FEATURE_CLEAN_UP && ENABLE_FEATURE_WGET_LONG_OPTIONS
+ free(G.extra_headers);
+#endif
+ FINI_G();
+
return EXIT_SUCCESS;
}
diff --git a/release/src/router/busybox/networking/zcip.c b/release/src/router/busybox/networking/zcip.c
index 520d09f149..23d66d4775 100644
--- a/release/src/router/busybox/networking/zcip.c
+++ b/release/src/router/busybox/networking/zcip.c
@@ -34,6 +34,9 @@
//usage: "\n -p FILE Create pidfile"
//usage: "\n -v Verbose"
//usage: "\n"
+//usage: "\n$LOGGING=none Suppress logging"
+//usage: "\n$LOGGING=syslog Log to syslog"
+//usage: "\n"
//usage: "\nWith no -q, runs continuously monitoring for ARP conflicts,"
//usage: "\nexits only on I/O errors (link down etc)"
@@ -41,6 +44,7 @@
#define WANT_PIDFILE 1
#include "libbb.h"
+#include "common_bufsiz.h"
#include <netinet/ether.h>
#include <net/if.h>
#include <net/if_arp.h>
@@ -57,26 +61,23 @@ struct arp_packet {
} PACKED;
enum {
-/* 169.254.0.0 */
- LINKLOCAL_ADDR = 0xa9fe0000,
-
-/* protocol timeout parameters, specified in seconds */
+ /* 0-1 seconds before sending 1st probe */
PROBE_WAIT = 1,
+ /* 1-2 seconds between probes */
PROBE_MIN = 1,
PROBE_MAX = 2,
- PROBE_NUM = 3,
- MAX_CONFLICTS = 10,
- RATE_LIMIT_INTERVAL = 60,
- ANNOUNCE_WAIT = 2,
- ANNOUNCE_NUM = 2,
- ANNOUNCE_INTERVAL = 2,
- DEFEND_INTERVAL = 10
+ PROBE_NUM = 3, /* total probes to send */
+ ANNOUNCE_INTERVAL = 2, /* 2 seconds between announces */
+ ANNOUNCE_NUM = 3, /* announces to send */
+ /* if probe/announce sees a conflict, multiply RANDOM(NUM_CONFLICT) by... */
+ CONFLICT_MULTIPLIER = 2,
+ /* if we monitor and see a conflict, how long is defend state? */
+ DEFEND_INTERVAL = 10,
};
/* States during the configuration process. */
enum {
PROBE = 0,
- RATE_LIMIT_PROBE,
ANNOUNCE,
MONITOR,
DEFEND
@@ -90,18 +91,14 @@ enum {
};
struct globals {
- struct sockaddr saddr;
- struct ether_addr eth_addr;
+ struct sockaddr iface_sockaddr;
+ struct ether_addr our_ethaddr;
uint32_t localnet_ip;
- int verbose;
char *pidfile;
+ int verbose;
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
-#define saddr (G.saddr )
-#define eth_addr (G.eth_addr)
-#define verbose (G.verbose )
-#define pidfile (G.pidfile )
-#define INIT_G() do { } while (0)
+#define G (*(struct globals*)bb_common_bufsiz1)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
/**
@@ -118,17 +115,24 @@ static uint32_t pick_nip(void)
return htonl((G.localnet_ip + 0x0100) + tmp);
}
+static const char *nip_to_a(uint32_t nip)
+{
+ struct in_addr in;
+ in.s_addr = nip;
+ return inet_ntoa(in);
+}
+
/**
* Broadcast an ARP packet.
*/
-static void arp(
+static void send_arp_request(
/* int op, - always ARPOP_REQUEST */
- /* const struct ether_addr *source_eth, - always &eth_addr */
- struct in_addr source_ip,
- const struct ether_addr *target_eth, struct in_addr target_ip)
+ /* const struct ether_addr *source_eth, - always &G.our_ethaddr */
+ uint32_t source_nip,
+ const struct ether_addr *target_eth, uint32_t target_nip)
{
enum { op = ARPOP_REQUEST };
-#define source_eth (&eth_addr)
+#define source_eth (&G.our_ethaddr)
struct arp_packet p;
memset(&p, 0, sizeof(p));
@@ -145,18 +149,18 @@ static void arp(
p.arp.arp_pln = 4;
p.arp.arp_op = htons(op);
memcpy(&p.arp.arp_sha, source_eth, ETH_ALEN);
- memcpy(&p.arp.arp_spa, &source_ip, sizeof(p.arp.arp_spa));
+ memcpy(&p.arp.arp_spa, &source_nip, 4);
memcpy(&p.arp.arp_tha, target_eth, ETH_ALEN);
- memcpy(&p.arp.arp_tpa, &target_ip, sizeof(p.arp.arp_tpa));
+ memcpy(&p.arp.arp_tpa, &target_nip, 4);
// send it
- // Even though sock_fd is already bound to saddr, just send()
+ // Even though sock_fd is already bound to G.iface_sockaddr, just send()
// won't work, because "socket is not connected"
// (and connect() won't fix that, "operation not supported").
- // Thus we sendto() to saddr. I wonder which sockaddr
+ // Thus we sendto() to G.iface_sockaddr. I wonder which sockaddr
// (from bind() or from sendto()?) kernel actually uses
// to determine iface to emit the packet from...
- xsendto(sock_fd, &p, sizeof(p), &saddr, sizeof(saddr));
+ xsendto(sock_fd, &p, sizeof(p), &G.iface_sockaddr, sizeof(G.iface_sockaddr));
#undef source_eth
}
@@ -164,23 +168,23 @@ static void arp(
* Run a script.
* argv[0]:intf argv[1]:script_name argv[2]:junk argv[3]:NULL
*/
-static int run(char *argv[3], const char *param, struct in_addr *ip)
+static int run(char *argv[3], const char *param, uint32_t nip)
{
int status;
- char *addr = addr; /* for gcc */
+ const char *addr = addr; /* for gcc */
const char *fmt = "%s %s %s" + 3;
argv[2] = (char*)param;
VDBG("%s run %s %s\n", argv[0], argv[1], argv[2]);
- if (ip) {
- addr = inet_ntoa(*ip);
+ if (nip != 0) {
+ addr = nip_to_a(nip);
xsetenv("ip", addr);
fmt -= 3;
}
- if (verbose)
- bb_info_msg(fmt, argv[2], argv[0], addr);
+ if (G.verbose)
+ bb_error_msg(fmt, argv[2], argv[0], addr);
status = spawn_and_wait(argv + 1);
if (status < 0) {
@@ -197,13 +201,19 @@ static int run(char *argv[3], const char *param, struct in_addr *ip)
*/
static ALWAYS_INLINE unsigned random_delay_ms(unsigned secs)
{
- return rand() % (secs * 1000);
+ return (unsigned)rand() % (secs * 1000);
}
-static void zcip_shutdown(int sig UNUSED_PARAM)
+static void cleanup(void)
{
- remove_pidfile(pidfile);
- exit(EXIT_SUCCESS);
+ remove_pidfile(G.pidfile);
+}
+
+static void zcip_shutdown(int sig) NORETURN;
+static void zcip_shutdown(int sig)
+{
+ cleanup();
+ kill_myself_with_sig(sig);
}
/**
@@ -212,48 +222,42 @@ static void zcip_shutdown(int sig UNUSED_PARAM)
int zcip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int zcip_main(int argc UNUSED_PARAM, char **argv)
{
- int state;
char *r_opt;
const char *l_opt = "169.254.0.0";
+ int state;
+ int nsent;
unsigned opts;
- // ugly trick, but I want these zeroed in one go
+ // Ugly trick, but I want these zeroed in one go
struct {
- const struct in_addr null_ip;
- const struct ether_addr null_addr;
- struct in_addr ip;
+ const struct ether_addr null_ethaddr;
struct ifreq ifr;
- int timeout_ms; /* must be signed */
- unsigned conflicts;
- unsigned nprobes;
- unsigned nclaims;
- int ready;
+ uint32_t chosen_nip;
+ int conflicts;
+ int timeout_ms; // must be signed
} L;
-#define null_ip (L.null_ip )
-#define null_addr (L.null_addr )
-#define ip (L.ip )
-#define ifr (L.ifr )
-#define timeout_ms (L.timeout_ms)
-#define conflicts (L.conflicts )
-#define nprobes (L.nprobes )
-#define nclaims (L.nclaims )
-#define ready (L.ready )
+#define null_ethaddr (L.null_ethaddr)
+#define ifr (L.ifr )
+#define chosen_nip (L.chosen_nip )
+#define conflicts (L.conflicts )
+#define timeout_ms (L.timeout_ms )
+#define verbose (G.verbose )
memset(&L, 0, sizeof(L));
INIT_G();
#define FOREGROUND (opts & 1)
#define QUIT (opts & 2)
- // parse commandline: prog [options] ifname script
+ // Parse commandline: prog [options] ifname script
// exactly 2 args; -v accumulates and implies -f
opt_complementary = "=2:vv:vf";
- opts = getopt32(argv, "fqr:l:p:v", &r_opt, &l_opt, &pidfile, &verbose);
+ opts = getopt32(argv, "fqr:l:p:v", &r_opt, &l_opt, &G.pidfile, &verbose);
#if !BB_MMU
// on NOMMU reexec early (or else we will rerun things twice)
if (!FOREGROUND)
bb_daemonize_or_rexec(0 /*was: DAEMON_CHDIR_ROOT*/, argv);
#endif
- // open an ARP socket
+ // Open an ARP socket
// (need to do it before openlog to prevent openlog from taking
// fd 3 (sock_fd==3))
xmove_fd(xsocket(AF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)), sock_fd);
@@ -261,7 +265,10 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
// do it before all bb_xx_msg calls
openlog(applet_name, 0, LOG_DAEMON);
logmode |= LOGMODE_SYSLOG;
- }
+ } else if (!verbose)
+ verbose++;
+ bb_logenv_override();
+
{ // -l n.n.n.n
struct in_addr net;
if (inet_aton(l_opt, &net) == 0
@@ -272,13 +279,14 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
G.localnet_ip = ntohl(net.s_addr);
}
if (opts & 4) { // -r n.n.n.n
+ struct in_addr ip;
if (inet_aton(r_opt, &ip) == 0
|| (ntohl(ip.s_addr) & IN_CLASSB_NET) != G.localnet_ip
) {
bb_error_msg_and_die("invalid link address");
}
+ chosen_nip = ip.s_addr;
}
-
argv += optind - 1;
/* Now: argv[0]:junk argv[1]:intf argv[2]:script argv[3]:NULL */
@@ -290,26 +298,29 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
xsetenv("interface", argv_intf);
- // initialize the interface (modprobe, ifup, etc)
- if (run(argv, "init", NULL))
- return EXIT_FAILURE;
+ die_func = cleanup;
+ write_pidfile(G.pidfile);
- // initialize saddr
- // saddr is: { u16 sa_family; u8 sa_data[14]; }
- //memset(&saddr, 0, sizeof(saddr));
+ // Initialize the interface (modprobe, ifup, etc)
+ if (run(argv, "init", 0))
+ goto err;
+
+ // Initialize G.iface_sockaddr
+ // G.iface_sockaddr is: { u16 sa_family; u8 sa_data[14]; }
+ //memset(&G.iface_sockaddr, 0, sizeof(G.iface_sockaddr));
//TODO: are we leaving sa_family == 0 (AF_UNSPEC)?!
- safe_strncpy(saddr.sa_data, argv_intf, sizeof(saddr.sa_data));
+ safe_strncpy(G.iface_sockaddr.sa_data, argv_intf, sizeof(G.iface_sockaddr.sa_data));
- // bind to the interface's ARP socket
- xbind(sock_fd, &saddr, sizeof(saddr));
+ // Bind to the interface's ARP socket
+ xbind(sock_fd, &G.iface_sockaddr, sizeof(G.iface_sockaddr));
- // get the interface's ethernet address
+ // Get the interface's ethernet address
//memset(&ifr, 0, sizeof(ifr));
strncpy_IFNAMSIZ(ifr.ifr_name, argv_intf);
xioctl(sock_fd, SIOCGIFHWADDR, &ifr);
- memcpy(&eth_addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+ memcpy(&G.our_ethaddr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
- // start with some stable ip address, either a function of
+ // Start with some stable ip address, either a function of
// the hardware address or else the last address we used.
// we are taking low-order four bytes, as top-order ones
// aren't random enough.
@@ -317,34 +328,34 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
// depending on when we detect conflicts.
{
uint32_t t;
- move_from_unaligned32(t, ((char *)&eth_addr + 2));
+ move_from_unaligned32(t, ((char *)&G.our_ethaddr + 2));
srand(t);
}
- if (ip.s_addr == 0)
- ip.s_addr = pick_nip();
-
// FIXME cases to handle:
// - zcip already running!
// - link already has local address... just defend/update
- // daemonize now; don't delay system startup
+ // Daemonize now; don't delay system startup
if (!FOREGROUND) {
#if BB_MMU
bb_daemonize(0 /*was: DAEMON_CHDIR_ROOT*/);
+ /* rewrite pidfile, as our pid is different now */
+ write_pidfile(G.pidfile);
#endif
if (verbose)
- bb_info_msg("start, interface %s", argv_intf);
+ bb_error_msg("start, interface %s", argv_intf);
}
- write_pidfile(pidfile);
bb_signals(BB_FATAL_SIGS, zcip_shutdown);
- // run the dynamic address negotiation protocol,
+ // Run the dynamic address negotiation protocol,
// restarting after address conflicts:
// - start with some address we want to try
// - short random delay
// - arp probes to see if another host uses it
+ // 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff arp who-has 169.254.194.171 tell 0.0.0.0
// - arp announcements that we're claiming it
+ // 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff arp who-has 169.254.194.171 (00:04:e2:64:23:c2) tell 169.254.194.171
// - use it
// - defend it, within limits
// exit if:
@@ -352,271 +363,197 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
// run "<script> config", then exit with exitcode 0
// - poll error (when does this happen?)
// - read error (when does this happen?)
- // - sendto error (in arp()) (when does this happen?)
+ // - sendto error (in send_arp_request()) (when does this happen?)
// - revents & POLLERR (link down). run "<script> deconfig" first
+ if (chosen_nip == 0) {
+ new_nip_and_PROBE:
+ chosen_nip = pick_nip();
+ }
+ nsent = 0;
state = PROBE;
while (1) {
struct pollfd fds[1];
- unsigned deadline_us;
+ unsigned deadline_us = deadline_us;
struct arp_packet p;
- int source_ip_conflict;
- int target_ip_conflict;
+ int ip_conflict;
+ int n;
fds[0].fd = sock_fd;
fds[0].events = POLLIN;
fds[0].revents = 0;
- // poll, being ready to adjust current timeout
+ // Poll, being ready to adjust current timeout
if (!timeout_ms) {
timeout_ms = random_delay_ms(PROBE_WAIT);
// FIXME setsockopt(sock_fd, SO_ATTACH_FILTER, ...) to
// make the kernel filter out all packets except
// ones we'd care about.
}
- // set deadline_us to the point in time when we timeout
- deadline_us = MONOTONIC_US() + timeout_ms * 1000;
-
- VDBG("...wait %d %s nprobes=%u, nclaims=%u\n",
- timeout_ms, argv_intf, nprobes, nclaims);
+ if (timeout_ms >= 0) {
+ // Set deadline_us to the point in time when we timeout
+ deadline_us = MONOTONIC_US() + timeout_ms * 1000;
+ }
- switch (safe_poll(fds, 1, timeout_ms)) {
+ VDBG("...wait %d %s nsent=%u\n",
+ timeout_ms, argv_intf, nsent);
- default:
+ n = safe_poll(fds, 1, timeout_ms);
+ if (n < 0) {
//bb_perror_msg("poll"); - done in safe_poll
- goto die;
-
- // timeout
- case 0:
- VDBG("state = %d\n", state);
+ goto err;
+ }
+ if (n == 0) { // timed out?
+ VDBG("state:%d\n", state);
switch (state) {
case PROBE:
- // timeouts in the PROBE state mean no conflicting ARP packets
- // have been received, so we can progress through the states
- if (nprobes < PROBE_NUM) {
- nprobes++;
+ // No conflicting ARP packets were seen:
+ // we can progress through the states
+ if (nsent < PROBE_NUM) {
+ nsent++;
VDBG("probe/%u %s@%s\n",
- nprobes, argv_intf, inet_ntoa(ip));
+ nsent, argv_intf, nip_to_a(chosen_nip));
timeout_ms = PROBE_MIN * 1000;
timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN);
- arp(/* ARPOP_REQUEST, */
- /* &eth_addr, */ null_ip,
- &null_addr, ip);
- }
- else {
- // Switch to announce state.
- state = ANNOUNCE;
- nclaims = 0;
- VDBG("announce/%u %s@%s\n",
- nclaims, argv_intf, inet_ntoa(ip));
- timeout_ms = ANNOUNCE_INTERVAL * 1000;
- arp(/* ARPOP_REQUEST, */
- /* &eth_addr, */ ip,
- &eth_addr, ip);
+ send_arp_request(0, &null_ethaddr, chosen_nip);
+ continue;
}
- break;
- case RATE_LIMIT_PROBE:
- // timeouts in the RATE_LIMIT_PROBE state mean no conflicting ARP packets
- // have been received, so we can move immediately to the announce state
+ // Switch to announce state
+ nsent = 0;
state = ANNOUNCE;
- nclaims = 0;
- VDBG("announce/%u %s@%s\n",
- nclaims, argv_intf, inet_ntoa(ip));
- timeout_ms = ANNOUNCE_INTERVAL * 1000;
- arp(/* ARPOP_REQUEST, */
- /* &eth_addr, */ ip,
- &eth_addr, ip);
- break;
+ goto send_announce;
case ANNOUNCE:
- // timeouts in the ANNOUNCE state mean no conflicting ARP packets
- // have been received, so we can progress through the states
- if (nclaims < ANNOUNCE_NUM) {
- nclaims++;
+ // No conflicting ARP packets were seen:
+ // we can progress through the states
+ if (nsent < ANNOUNCE_NUM) {
+ send_announce:
+ nsent++;
VDBG("announce/%u %s@%s\n",
- nclaims, argv_intf, inet_ntoa(ip));
+ nsent, argv_intf, nip_to_a(chosen_nip));
timeout_ms = ANNOUNCE_INTERVAL * 1000;
- arp(/* ARPOP_REQUEST, */
- /* &eth_addr, */ ip,
- &eth_addr, ip);
+ send_arp_request(chosen_nip, &G.our_ethaddr, chosen_nip);
+ continue;
}
- else {
- // Switch to monitor state.
- state = MONITOR;
- // link is ok to use earlier
- // FIXME update filters
- run(argv, "config", &ip);
- ready = 1;
- conflicts = 0;
- timeout_ms = -1; // Never timeout in the monitor state.
-
- // NOTE: all other exit paths
- // should deconfig ...
- if (QUIT) {
- xfunc_error_retval = EXIT_SUCCESS;
- goto die;
- }
- }
- break;
- case DEFEND:
- // We won! No ARP replies, so just go back to monitor.
- state = MONITOR;
- timeout_ms = -1;
- conflicts = 0;
- break;
+ // Switch to monitor state
+ // FIXME update filters
+ run(argv, "config", chosen_nip);
+ // NOTE: all other exit paths should deconfig...
+ if (QUIT)
+ goto done;
+ // fall through: switch to MONITOR
default:
- // Invalid, should never happen. Restart the whole protocol.
- state = PROBE;
- ip.s_addr = pick_nip();
- timeout_ms = 0;
- nprobes = 0;
- nclaims = 0;
- break;
- } // switch (state)
- break; // case 0 (timeout)
-
- // packets arriving, or link went down
- case 1:
- // We need to adjust the timeout in case we didn't receive
- // a conflicting packet.
- if (timeout_ms > 0) {
- unsigned diff = deadline_us - MONOTONIC_US();
- if ((int)(diff) < 0) {
- // Current time is greater than the expected timeout time.
- // Should never happen.
- VDBG("missed an expected timeout\n");
- timeout_ms = 0;
- } else {
- VDBG("adjusting timeout\n");
- timeout_ms = (diff / 1000) | 1; /* never 0 */
- }
+ // case DEFEND:
+ // case MONITOR: (shouldn't happen, MONITOR timeout is infinite)
+ // Defend period ended with no ARP replies - we won
+ timeout_ms = -1; // never timeout in monitor state
+ state = MONITOR;
+ continue;
}
+ }
- if ((fds[0].revents & POLLIN) == 0) {
- if (fds[0].revents & POLLERR) {
- // FIXME: links routinely go down;
- // this shouldn't necessarily exit.
- bb_error_msg("iface %s is down", argv_intf);
- if (ready) {
- run(argv, "deconfig", &ip);
- }
- goto die;
- }
- continue;
+ // Packet arrived, or link went down.
+ // We need to adjust the timeout in case we didn't receive
+ // a conflicting packet.
+ if (timeout_ms > 0) {
+ unsigned diff = deadline_us - MONOTONIC_US();
+ if ((int)(diff) < 0) {
+ // Current time is greater than the expected timeout time.
+ diff = 0;
}
+ VDBG("adjusting timeout\n");
+ timeout_ms = (diff / 1000) | 1; // never 0
+ }
- // read ARP packet
- if (safe_read(sock_fd, &p, sizeof(p)) < 0) {
- bb_perror_msg(bb_msg_read_error);
- goto die;
+ if ((fds[0].revents & POLLIN) == 0) {
+ if (fds[0].revents & POLLERR) {
+ // FIXME: links routinely go down;
+ // this shouldn't necessarily exit.
+ bb_error_msg("iface %s is down", argv_intf);
+ if (state >= MONITOR) {
+ // Only if we are in MONITOR or DEFEND
+ run(argv, "deconfig", chosen_nip);
+ }
+ goto err;
}
- if (p.eth.ether_type != htons(ETHERTYPE_ARP))
- continue;
+ continue;
+ }
+
+ // Read ARP packet
+ if (safe_read(sock_fd, &p, sizeof(p)) < 0) {
+ bb_perror_msg_and_die(bb_msg_read_error);
+ }
+
+ if (p.eth.ether_type != htons(ETHERTYPE_ARP))
+ continue;
+ if (p.arp.arp_op != htons(ARPOP_REQUEST)
+ && p.arp.arp_op != htons(ARPOP_REPLY)
+ ) {
+ continue;
+ }
#ifdef DEBUG
- {
- struct ether_addr *sha = (struct ether_addr *) p.arp.arp_sha;
- struct ether_addr *tha = (struct ether_addr *) p.arp.arp_tha;
- struct in_addr *spa = (struct in_addr *) p.arp.arp_spa;
- struct in_addr *tpa = (struct in_addr *) p.arp.arp_tpa;
- VDBG("%s recv arp type=%d, op=%d,\n",
- argv_intf, ntohs(p.eth.ether_type),
- ntohs(p.arp.arp_op));
- VDBG("\tsource=%s %s\n",
- ether_ntoa(sha),
- inet_ntoa(*spa));
- VDBG("\ttarget=%s %s\n",
- ether_ntoa(tha),
- inet_ntoa(*tpa));
- }
+ {
+ struct ether_addr *sha = (struct ether_addr *) p.arp.arp_sha;
+ struct ether_addr *tha = (struct ether_addr *) p.arp.arp_tha;
+ struct in_addr *spa = (struct in_addr *) p.arp.arp_spa;
+ struct in_addr *tpa = (struct in_addr *) p.arp.arp_tpa;
+ VDBG("source=%s %s\n", ether_ntoa(sha), inet_ntoa(*spa));
+ VDBG("target=%s %s\n", ether_ntoa(tha), inet_ntoa(*tpa));
+ }
#endif
- if (p.arp.arp_op != htons(ARPOP_REQUEST)
- && p.arp.arp_op != htons(ARPOP_REPLY)
+ ip_conflict = 0;
+ if (memcmp(&p.arp.arp_sha, &G.our_ethaddr, ETH_ALEN) != 0) {
+ if (memcmp(p.arp.arp_spa, &chosen_nip, 4) == 0) {
+ // A probe or reply with source_ip == chosen ip
+ ip_conflict = 1;
+ }
+ if (p.arp.arp_op == htons(ARPOP_REQUEST)
+ && memcmp(p.arp.arp_spa, &const_int_0, 4) == 0
+ && memcmp(p.arp.arp_tpa, &chosen_nip, 4) == 0
) {
- continue;
+ // A probe with source_ip == 0.0.0.0, target_ip == chosen ip:
+ // another host trying to claim this ip!
+ ip_conflict |= 2;
}
+ }
+ VDBG("state:%d ip_conflict:%d\n", state, ip_conflict);
+ if (!ip_conflict)
+ continue;
+
+ // Either src or target IP conflict exists
+ if (state <= ANNOUNCE) {
+ // PROBE or ANNOUNCE
+ conflicts++;
+ timeout_ms = PROBE_MIN * 1000
+ + CONFLICT_MULTIPLIER * random_delay_ms(conflicts);
+ goto new_nip_and_PROBE;
+ }
- source_ip_conflict = 0;
- target_ip_conflict = 0;
-
- if (memcmp(&p.arp.arp_sha, &eth_addr, ETH_ALEN) != 0) {
- if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr)) == 0) {
- /* A probe or reply with source_ip == chosen ip */
- source_ip_conflict = 1;
- }
- if (p.arp.arp_op == htons(ARPOP_REQUEST)
- && memcmp(p.arp.arp_spa, &null_ip, sizeof(struct in_addr)) == 0
- && memcmp(p.arp.arp_tpa, &ip.s_addr, sizeof(struct in_addr)) == 0
- ) {
- /* A probe with source_ip == 0.0.0.0, target_ip == chosen ip:
- * another host trying to claim this ip!
- */
- target_ip_conflict = 1;
- }
+ // MONITOR or DEFEND: only src IP conflict is a problem
+ if (ip_conflict & 1) {
+ if (state == MONITOR) {
+ // Src IP conflict, defend with a single ARP probe
+ VDBG("monitor conflict - defending\n");
+ timeout_ms = DEFEND_INTERVAL * 1000;
+ state = DEFEND;
+ send_arp_request(chosen_nip, &G.our_ethaddr, chosen_nip);
+ continue;
}
-
- VDBG("state = %d, source ip conflict = %d, target ip conflict = %d\n",
- state, source_ip_conflict, target_ip_conflict);
- switch (state) {
- case PROBE:
- case ANNOUNCE:
- // When probing or announcing, check for source IP conflicts
- // and other hosts doing ARP probes (target IP conflicts).
- if (source_ip_conflict || target_ip_conflict) {
- conflicts++;
- if (conflicts >= MAX_CONFLICTS) {
- VDBG("%s ratelimit\n", argv_intf);
- timeout_ms = RATE_LIMIT_INTERVAL * 1000;
- state = RATE_LIMIT_PROBE;
- }
-
- // restart the whole protocol
- ip.s_addr = pick_nip();
- timeout_ms = 0;
- nprobes = 0;
- nclaims = 0;
- }
- break;
- case MONITOR:
- // If a conflict, we try to defend with a single ARP probe.
- if (source_ip_conflict) {
- VDBG("monitor conflict -- defending\n");
- state = DEFEND;
- timeout_ms = DEFEND_INTERVAL * 1000;
- arp(/* ARPOP_REQUEST, */
- /* &eth_addr, */ ip,
- &eth_addr, ip);
- }
- break;
- case DEFEND:
- // Well, we tried. Start over (on conflict).
- if (source_ip_conflict) {
- state = PROBE;
- VDBG("defend conflict -- starting over\n");
- ready = 0;
- run(argv, "deconfig", &ip);
-
- // restart the whole protocol
- ip.s_addr = pick_nip();
- timeout_ms = 0;
- nprobes = 0;
- nclaims = 0;
- }
- break;
- default:
- // Invalid, should never happen. Restart the whole protocol.
- VDBG("invalid state -- starting over\n");
- state = PROBE;
- ip.s_addr = pick_nip();
- timeout_ms = 0;
- nprobes = 0;
- nclaims = 0;
- break;
- } // switch state
- break; // case 1 (packets arriving)
- } // switch poll
+ // state == DEFEND
+ // Another src IP conflict, start over
+ VDBG("defend conflict - starting over\n");
+ run(argv, "deconfig", chosen_nip);
+ conflicts = 0;
+ timeout_ms = 0;
+ goto new_nip_and_PROBE;
+ }
+ // Note: if we only have a target IP conflict here (ip_conflict & 2),
+ // IOW: if we just saw this sort of ARP packet:
+ // aa:bb:cc:dd:ee:ff > xx:xx:xx:xx:xx:xx arp who-has <chosen_nip> tell 0.0.0.0
+ // we expect _kernel_ to respond to that, because <chosen_nip>
+ // is (expected to be) configured on this iface.
} // while (1)
-
-die:
- remove_pidfile(pidfile);
+done:
+ xfunc_error_retval = EXIT_SUCCESS;
+err:
xfunc_die();
-
#undef argv_intf
}
diff --git a/release/src/router/busybox/printutils/Config.src b/release/src/router/busybox/printutils/Config.src
index cc4ab8d28f..e53b9d0935 100644
--- a/release/src/router/busybox/printutils/Config.src
+++ b/release/src/router/busybox/printutils/Config.src
@@ -7,22 +7,4 @@ menu "Print Utilities"
INSERT
-config LPD
- bool "lpd"
- default y
- help
- lpd is a print spooling daemon.
-
-config LPR
- bool "lpr"
- default y
- help
- lpr sends files (or standard input) to a print spooling daemon.
-
-config LPQ
- bool "lpq"
- default y
- help
- lpq is a print spool queue examination and manipulation program.
-
endmenu
diff --git a/release/src/router/busybox/printutils/Kbuild.src b/release/src/router/busybox/printutils/Kbuild.src
index 194fe01d65..10c8230631 100644
--- a/release/src/router/busybox/printutils/Kbuild.src
+++ b/release/src/router/busybox/printutils/Kbuild.src
@@ -4,6 +4,4 @@
lib-y :=
-lib-$(CONFIG_LPD) += lpd.o
-lib-$(CONFIG_LPR) += lpr.o
-lib-$(CONFIG_LPQ) += lpr.o
+INSERT
diff --git a/release/src/router/busybox/printutils/lpd.c b/release/src/router/busybox/printutils/lpd.c
index 642e8a89e7..8823934368 100644
--- a/release/src/router/busybox/printutils/lpd.c
+++ b/release/src/router/busybox/printutils/lpd.c
@@ -69,6 +69,15 @@
* cat ./"$DATAFILE" >/dev/lp0
* mv -f ./"$DATAFILE" save/
*/
+//config:config LPD
+//config: bool "lpd"
+//config: default y
+//config: help
+//config: lpd is a print spooling daemon.
+
+//applet:IF_LPD(APPLET(lpd, BB_DIR_USR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_LPD) += lpd.o
//usage:#define lpd_trivial_usage
//usage: "SPOOLDIR [HELPER [ARGS]]"
@@ -200,15 +209,15 @@ int lpd_main(int argc UNUSED_PARAM, char *argv[])
if (2 != s[0] && 3 != s[0])
goto unsupported_cmd;
if (spooling & (1 << (s[0]-1))) {
- printf("Duplicated subcommand\n");
+ puts("Duplicated subcommand");
goto err_exit;
}
// get filename
- *strchrnul(s, '\n') = '\0';
+ chomp(s);
fname = strchr(s, ' ');
if (!fname) {
// bad_fname:
- printf("No or bad filename\n");
+ puts("No or bad filename");
goto err_exit;
}
*fname++ = '\0';
@@ -219,13 +228,13 @@ int lpd_main(int argc UNUSED_PARAM, char *argv[])
// get length
expected_len = bb_strtou(s + 1, NULL, 10);
if (errno || expected_len < 0) {
- printf("Bad length\n");
+ puts("Bad length");
goto err_exit;
}
if (2 == s[0] && expected_len > 16 * 1024) {
// SECURITY:
// ctrlfile can't be big (we want to read it back later!)
- printf("File is too big\n");
+ puts("File is too big");
goto err_exit;
}
diff --git a/release/src/router/busybox/printutils/lpr.c b/release/src/router/busybox/printutils/lpr.c
index fc6bca9e8d..ed6a84a936 100644
--- a/release/src/router/busybox/printutils/lpr.c
+++ b/release/src/router/busybox/printutils/lpr.c
@@ -11,6 +11,23 @@
*
* See RFC 1179 for protocol description.
*/
+//config:config LPR
+//config: bool "lpr"
+//config: default y
+//config: help
+//config: lpr sends files (or standard input) to a print spooling daemon.
+//config:
+//config:config LPQ
+//config: bool "lpq"
+//config: default y
+//config: help
+//config: lpq is a print spool queue examination and manipulation program.
+
+//applet:IF_LPQ(APPLET_ODDNAME(lpq, lpqr, BB_DIR_USR_BIN, BB_SUID_DROP, lpq))
+//applet:IF_LPR(APPLET_ODDNAME(lpr, lpqr, BB_DIR_USR_BIN, BB_SUID_DROP, lpr))
+
+//kbuild:lib-$(CONFIG_LPR) += lpr.o
+//kbuild:lib-$(CONFIG_LPQ) += lpr.o
//usage:#define lpr_trivial_usage
//usage: "-P queue[@host[:port]] -U USERNAME -J TITLE -Vmh [FILE]..."
@@ -89,6 +106,10 @@ int lpqr_main(int argc UNUSED_PARAM, char *argv[])
unsigned opts;
int fd;
+ queue = getenv("PRINTER");
+ if (!queue)
+ queue = "lp";
+
// parse options
// TODO: set opt_complementary: s,d,f are mutually exclusive
opts = getopt32(argv,
@@ -98,16 +119,7 @@ int lpqr_main(int argc UNUSED_PARAM, char *argv[])
);
argv += optind;
- // if queue is not specified -> use $PRINTER
- if (!(opts & OPT_P))
- queue = getenv("PRINTER");
- // if queue is still not specified ->
- if (!queue) {
- // ... queue defaults to "lp"
- // server defaults to "localhost"
- queue = "lp";
- // if queue is specified ->
- } else {
+ {
// queue name is to the left of '@'
char *s = strchr(queue, '@');
if (s) {
@@ -186,6 +198,17 @@ int lpqr_main(int argc UNUSED_PARAM, char *argv[])
dfd = xopen(*argv, O_RDONLY);
}
+ st.st_size = 0; /* paranoia: fstat may theoretically fail */
+ fstat(dfd, &st);
+
+ /* Apparently, some servers are buggy and won't accept 0-sized jobs.
+ * Standard lpr works around it by refusing to send such jobs:
+ */
+ if (st.st_size == 0) {
+ bb_error_msg("nothing to print");
+ continue;
+ }
+
/* "The name ... should start with ASCII "cfA",
* followed by a three digit job number, followed
* by the host name which has constructed the file."
@@ -210,14 +233,11 @@ int lpqr_main(int argc UNUSED_PARAM, char *argv[])
, (opts & LPR_m) ? user : ""
, remote_filename
);
- // delete possible "\nX\n" patterns
+ // delete possible "\nX\n" (that is, one-char) patterns
c = controlfile;
- cflen = (unsigned)strlen(controlfile);
while ((c = strchr(c, '\n')) != NULL) {
if (c[1] && c[2] == '\n') {
- /* can't use strcpy, results are undefined */
- memmove(c, c+2, cflen - (c-controlfile) - 1);
- cflen -= 2;
+ overlapping_strcpy(c, c+2);
} else {
c++;
}
@@ -228,6 +248,7 @@ int lpqr_main(int argc UNUSED_PARAM, char *argv[])
bb_error_msg("sending control file");
/* "Acknowledgement processing must occur as usual
* after the command is sent." */
+ cflen = (unsigned)strlen(controlfile);
fdprintf(fd, "\x2" "%u c%s\n", cflen, remote_filename);
get_response_or_say_and_die(fd, "sending control file");
/* "Once all of the contents have
@@ -241,8 +262,6 @@ int lpqr_main(int argc UNUSED_PARAM, char *argv[])
// send data file, with name "dfaXXX"
if (opts & LPR_V)
bb_error_msg("sending data file");
- st.st_size = 0; /* paranoia: fstat may theoretically fail */
- fstat(dfd, &st);
fdprintf(fd, "\x3" "%"OFF_FMT"u d%s\n", st.st_size, remote_filename);
get_response_or_say_and_die(fd, "sending data file");
if (bb_copyfd_size(dfd, fd, st.st_size) != st.st_size) {
diff --git a/release/src/router/busybox/procps/Config.src b/release/src/router/busybox/procps/Config.src
index 5cd47c84f5..527d9ee0c4 100644
--- a/release/src/router/busybox/procps/Config.src
+++ b/release/src/router/busybox/procps/Config.src
@@ -140,60 +140,6 @@ config BB_SYSCTL
help
Configure kernel parameters at runtime.
-config TOP
- bool "top"
- default y
- help
- The top program provides a dynamic real-time view of a running
- system.
-
-config FEATURE_TOP_CPU_USAGE_PERCENTAGE
- bool "Show CPU per-process usage percentage"
- default y
- depends on TOP
- help
- Make top display CPU usage for each process.
- This adds about 2k.
-
-config FEATURE_TOP_CPU_GLOBAL_PERCENTS
- bool "Show CPU global usage percentage"
- default y
- depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE
- help
- Makes top display "CPU: NN% usr NN% sys..." line.
- This adds about 0.5k.
-
-config FEATURE_TOP_SMP_CPU
- bool "SMP CPU usage display ('c' key)"
- default y
- depends on FEATURE_TOP_CPU_GLOBAL_PERCENTS
- help
- Allow 'c' key to switch between individual/cumulative CPU stats
- This adds about 0.5k.
-
-config FEATURE_TOP_DECIMALS
- bool "Show 1/10th of a percent in CPU/mem statistics"
- default y
- depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE
- help
- Show 1/10th of a percent in CPU/mem statistics.
- This adds about 0.3k.
-
-config FEATURE_TOP_SMP_PROCESS
- bool "Show CPU process runs on ('j' field)"
- default y
- depends on TOP
- help
- Show CPU where process was last found running on.
- This is the 'j' field.
-
-config FEATURE_TOPMEM
- bool "Topmem command ('s' key)"
- default y
- depends on TOP
- help
- Enable 's' in top (gives lots of memory info).
-
config FEATURE_SHOW_THREADS
bool "Support for showing threads in ps/pstree/top"
default y
diff --git a/release/src/router/busybox/procps/free.c b/release/src/router/busybox/procps/free.c
index 47f2fc3b25..fca9a22426 100644
--- a/release/src/router/busybox/procps/free.c
+++ b/release/src/router/busybox/procps/free.c
@@ -22,6 +22,7 @@
//usage: "Total: 386144 257128 129016\n"
#include "libbb.h"
+#include "common_bufsiz.h"
#ifdef __linux__
# include <sys/sysinfo.h>
#endif
@@ -35,8 +36,8 @@ struct globals {
# define G_unit_steps 10
#endif
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
-#define INIT_G() do { } while (0)
+#define G (*(struct globals*)bb_common_bufsiz1)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
static unsigned long long scale(unsigned long d)
@@ -44,11 +45,28 @@ static unsigned long long scale(unsigned long d)
return ((unsigned long long)d * G.mem_unit) >> G_unit_steps;
}
+static unsigned long parse_cached_kb(void)
+{
+ char buf[60]; /* actual lines we expect are ~30 chars or less */
+ FILE *fp;
+ unsigned long cached = 0;
+
+ fp = xfopen_for_read("/proc/meminfo");
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ if (sscanf(buf, "Cached: %lu %*s\n", &cached) == 1)
+ break;
+ }
+ if (ENABLE_FEATURE_CLEAN_UP)
+ fclose(fp);
+
+ return cached;
+}
int free_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM))
{
struct sysinfo info;
+ unsigned long long cached;
INIT_G();
@@ -73,49 +91,47 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM))
}
}
#endif
-
- sysinfo(&info);
-
- /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */
- G.mem_unit = (info.mem_unit ? info.mem_unit : 1);
-
- printf(" %13s%13s%13s%13s%13s\n",
+ printf(" %11s%11s%11s%11s%11s%11s\n"
+ "Mem: ",
"total",
"used",
"free",
- "shared", "buffers" /* swap and total don't have these columns */
- /* procps version 3.2.8 also shows "cached" column, but
- * sysinfo() does not provide this value, need to parse
- * /proc/meminfo instead and get "Cached: NNN kB" from there.
- */
+ "shared", "buffers", "cached" /* swap and total don't have these columns */
);
-#define FIELDS_5 "%13llu%13llu%13llu%13llu%13llu\n"
-#define FIELDS_3 (FIELDS_5 + 2*6)
-#define FIELDS_2 (FIELDS_5 + 3*6)
+ sysinfo(&info);
+ /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */
+ G.mem_unit = (info.mem_unit ? info.mem_unit : 1);
+ /* Extract cached from /proc/meminfo and convert to mem_units */
+ cached = ((unsigned long long) parse_cached_kb() * 1024) / G.mem_unit;
+
+#define FIELDS_6 "%11llu%11llu%11llu%11llu%11llu%11llu\n"
+#define FIELDS_3 (FIELDS_6 + 3*6)
+#define FIELDS_2 (FIELDS_6 + 4*6)
- printf("Mem: ");
- printf(FIELDS_5,
- scale(info.totalram),
- scale(info.totalram - info.freeram),
- scale(info.freeram),
- scale(info.sharedram),
- scale(info.bufferram)
+ printf(FIELDS_6,
+ scale(info.totalram), //total
+ scale(info.totalram - info.freeram), //used
+ scale(info.freeram), //free
+ scale(info.sharedram), //shared
+ scale(info.bufferram), //buffers
+ scale(cached) //cached
);
/* Show alternate, more meaningful busy/free numbers by counting
- * buffer cache as free memory (make it "-/+ buffers/cache"
- * if/when we add support for "cached" column): */
- printf("-/+ buffers: ");
+ * buffer cache as free memory. */
+ printf("-/+ buffers/cache:");
+ cached += info.freeram;
+ cached += info.bufferram;
printf(FIELDS_2,
- scale(info.totalram - info.freeram - info.bufferram),
- scale(info.freeram + info.bufferram)
+ scale(info.totalram - cached), //used
+ scale(cached) //free
);
#if BB_MMU
- printf("Swap:");
+ printf("Swap: ");
printf(FIELDS_3,
- scale(info.totalswap),
- scale(info.totalswap - info.freeswap),
- scale(info.freeswap)
+ scale(info.totalswap), //total
+ scale(info.totalswap - info.freeswap), //used
+ scale(info.freeswap) //free
);
#endif
return EXIT_SUCCESS;
diff --git a/release/src/router/busybox/procps/fuser.c b/release/src/router/busybox/procps/fuser.c
index 05b52abb1c..6dac852ed1 100644
--- a/release/src/router/busybox/procps/fuser.c
+++ b/release/src/router/busybox/procps/fuser.c
@@ -18,6 +18,7 @@
//usage: "\n -SIGNAL Signal to send (default: KILL)"
#include "libbb.h"
+#include "common_bufsiz.h"
#define MAX_LINE 255
@@ -43,8 +44,9 @@ struct globals {
smallint kill_failed;
int killsig;
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define INIT_G() do { \
+ setup_common_bufsiz(); \
G.mypid = getpid(); \
G.killsig = SIGKILL; \
} while (0)
diff --git a/release/src/router/busybox/procps/iostat.c b/release/src/router/busybox/procps/iostat.c
index 978d234305..c290c594b8 100644
--- a/release/src/router/busybox/procps/iostat.c
+++ b/release/src/router/busybox/procps/iostat.c
@@ -109,11 +109,6 @@ enum {
OPT_m = 1 << 5,
};
-static ALWAYS_INLINE unsigned get_user_hz(void)
-{
- return sysconf(_SC_CLK_TCK);
-}
-
static ALWAYS_INLINE int this_is_smp(void)
{
return (G.total_cpus > 1);
@@ -147,7 +142,7 @@ static void print_timestamp(void)
/* %x: date representation for the current locale */
/* %X: time representation for the current locale */
strftime(buf, sizeof(buf), "%x %X", &G.tmtime);
- printf("%s\n", buf);
+ puts(buf);
}
static cputime_t get_smp_uptime(void)
@@ -414,7 +409,7 @@ int iostat_main(int argc UNUSED_PARAM, char **argv)
memset(&stats_data, 0, sizeof(stats_data));
/* Get number of clock ticks per sec */
- G.clk_tck = get_user_hz();
+ G.clk_tck = bb_clk_tck();
/* Determine number of CPUs */
G.total_cpus = get_cpu_count();
diff --git a/release/src/router/busybox/procps/kill.c b/release/src/router/busybox/procps/kill.c
index cd189bcd61..c5c7a8d729 100644
--- a/release/src/router/busybox/procps/kill.c
+++ b/release/src/router/busybox/procps/kill.c
@@ -60,7 +60,7 @@
* This is needed to avoid collision with kill -9 ... syntax
*/
-int kill_main(int argc, char **argv)
+int kill_main(int argc UNUSED_PARAM, char **argv)
{
char *arg;
pid_t pid;
@@ -79,10 +79,9 @@ int kill_main(int argc, char **argv)
#endif
/* Parse any options */
- argc--;
arg = *++argv;
- if (argc < 1 || arg[0] != '-') {
+ if (!arg || arg[0] != '-') {
goto do_it_now;
}
@@ -91,13 +90,14 @@ int kill_main(int argc, char **argv)
* echo "Died of SIG`kill -l $?`"
* We try to mimic what kill from coreutils-6.8 does */
if (arg[1] == 'l' && arg[2] == '\0') {
- if (argc == 1) {
+ arg = *++argv;
+ if (!arg) {
/* Print the whole signal list */
print_signames();
return 0;
}
/* -l <sig list> */
- while ((arg = *++argv)) {
+ do {
if (isdigit(arg[0])) {
signo = bb_strtou(arg, NULL, 10);
if (errno) {
@@ -118,8 +118,8 @@ int kill_main(int argc, char **argv)
}
printf("%d\n", signo);
}
- }
- /* If they specified -l, we are all done */
+ arg = *++argv;
+ } while (arg);
return EXIT_SUCCESS;
}
@@ -127,8 +127,7 @@ int kill_main(int argc, char **argv)
if (killall && arg[1] == 'q' && arg[2] == '\0') {
quiet = 1;
arg = *++argv;
- argc--;
- if (argc < 1)
+ if (!arg)
bb_show_usage();
if (arg[0] != '-')
goto do_it_now;
@@ -140,8 +139,7 @@ int kill_main(int argc, char **argv)
if (killall5 && arg[0] == 'o')
goto do_it_now;
- if (argc > 1 && arg[0] == 's' && arg[1] == '\0') { /* -s SIG? */
- argc--;
+ if (argv[1] && arg[0] == 's' && arg[1] == '\0') { /* -s SIG? */
arg = *++argv;
} /* else it must be -SIG */
signo = get_signum(arg);
@@ -150,7 +148,6 @@ int kill_main(int argc, char **argv)
return EXIT_FAILURE;
}
arg = *++argv;
- argc--;
do_it_now:
pid = getpid();
@@ -158,7 +155,8 @@ int kill_main(int argc, char **argv)
if (killall5) {
pid_t sid;
procps_status_t* p = NULL;
- int ret = 0;
+ /* compat: exitcode 2 is "no one was signaled" */
+ int ret = 2;
/* Find out our session id */
sid = getsid(pid);
@@ -167,9 +165,10 @@ int kill_main(int argc, char **argv)
kill(-1, SIGSTOP);
/* Signal all processes except those in our session */
while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_SID)) != NULL) {
- int i;
+ char **args;
if (p->sid == (unsigned)sid
+ || p->sid == 0 /* compat: kernel thread, don't signal it */
|| p->pid == (unsigned)pid
|| p->pid == 1
) {
@@ -178,18 +177,19 @@ int kill_main(int argc, char **argv)
/* All remaining args must be -o PID options.
* Check p->pid against them. */
- for (i = 0; i < argc; i++) {
+ args = argv;
+ while (*args) {
pid_t omit;
- arg = argv[i];
+ arg = *args++;
if (arg[0] != '-' || arg[1] != 'o') {
bb_error_msg("bad option '%s'", arg);
ret = 1;
goto resume;
}
arg += 2;
- if (!arg[0] && argv[++i])
- arg = argv[i];
+ if (!arg[0] && *args)
+ arg = *args++;
omit = bb_strtoi(arg, NULL, 10);
if (errno) {
bb_error_msg("invalid number '%s'", arg);
@@ -200,6 +200,7 @@ int kill_main(int argc, char **argv)
goto dont_kill;
}
kill(p->pid, signo);
+ ret = 0;
dont_kill: ;
}
resume:
@@ -210,14 +211,14 @@ int kill_main(int argc, char **argv)
}
/* Pid or name is required for kill/killall */
- if (argc < 1) {
+ if (!arg) {
bb_error_msg("you need to specify whom to kill");
return EXIT_FAILURE;
}
if (killall) {
/* Looks like they want to do a killall. Do that */
- while (arg) {
+ do {
pid_t* pidList;
pidList = find_pid_by_name(arg);
@@ -240,7 +241,7 @@ int kill_main(int argc, char **argv)
}
free(pidList);
arg = *++argv;
- }
+ } while (arg);
return errors;
}
diff --git a/release/src/router/busybox/procps/lsof.c b/release/src/router/busybox/procps/lsof.c
index 7e0ffa4e5e..b0156a5381 100644
--- a/release/src/router/busybox/procps/lsof.c
+++ b/release/src/router/busybox/procps/lsof.c
@@ -61,9 +61,12 @@ int lsof_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
d_fd = opendir(name);
if (d_fd) {
while ((entry = readdir(d_fd)) != NULL) {
- if (entry->d_type == DT_LNK) {
- safe_strncpy(name + baseofs, entry->d_name, 10);
- fdlink = xmalloc_readlink(name);
+ /* Skip entries '.' and '..' (and any hidden file) */
+ if (entry->d_name[0] == '.')
+ continue;
+
+ safe_strncpy(name + baseofs, entry->d_name, 10);
+ if ((fdlink = xmalloc_readlink(name)) != NULL) {
printf("%d\t%s\t%s\n", proc->pid, proc->exe, fdlink);
free(fdlink);
}
diff --git a/release/src/router/busybox/procps/mpstat.c b/release/src/router/busybox/procps/mpstat.c
index aa5a5c73f2..6028903fa5 100644
--- a/release/src/router/busybox/procps/mpstat.c
+++ b/release/src/router/busybox/procps/mpstat.c
@@ -522,13 +522,11 @@ static void get_irqs_from_stat(struct stats_irq *irq)
FILE *fp;
char buf[1024];
- fp = fopen_for_read(PROCFS_STAT);
- if (!fp)
- return;
+ fp = xfopen_for_read(PROCFS_STAT);
while (fgets(buf, sizeof(buf), fp)) {
//bb_error_msg("/proc/stat:'%s'", buf);
- if (strncmp(buf, "intr ", 5) == 0) {
+ if (is_prefixed_with(buf, "intr ")) {
/* Read total number of IRQs since system boot */
sscanf(buf + 5, "%"FMT_DATA"u", &irq->irq_nr);
}
@@ -644,9 +642,7 @@ static void get_uptime(data_t *uptime)
char buf[sizeof(long)*3 * 2 + 4]; /* enough for long.long */
unsigned long uptime_sec, decimal;
- fp = fopen_for_read(PROCFS_UPTIME);
- if (!fp)
- return;
+ fp = xfopen_for_read(PROCFS_UPTIME);
if (fgets(buf, sizeof(buf), fp)) {
if (sscanf(buf, "%lu.%lu", &uptime_sec, &decimal) == 2) {
*uptime = (data_t)uptime_sec * G.hz + decimal * G.hz / 100;
@@ -775,12 +771,6 @@ static void main_loop(void)
/* Initialization */
-/* Get number of clock ticks per sec */
-static ALWAYS_INLINE unsigned get_hz(void)
-{
- return sysconf(_SC_CLK_TCK);
-}
-
static void alloc_struct(int cpus)
{
int i;
@@ -873,7 +863,7 @@ int mpstat_main(int UNUSED_PARAM argc, char **argv)
G.cpu_nr = get_cpu_count();
/* Get number of clock ticks per sec */
- G.hz = get_hz();
+ G.hz = bb_clk_tck();
/* Calculate number of interrupts per processor */
G.irqcpu_nr = get_irqcpu_nr(PROCFS_INTERRUPTS, NR_IRQS) + NR_IRQCPU_PREALLOC;
diff --git a/release/src/router/busybox/procps/nmeter.c b/release/src/router/busybox/procps/nmeter.c
index ed54790248..3eac2d3b2c 100644
--- a/release/src/router/busybox/procps/nmeter.c
+++ b/release/src/router/busybox/procps/nmeter.c
@@ -21,7 +21,7 @@
//usage:#define nmeter_full_usage "\n\n"
//usage: "Monitor system in real time"
//usage: "\n"
-//usage: "\n -d MSEC Milliseconds between updates (default:1000)"
+//usage: "\n -d MSEC Milliseconds between updates, default:1000, none:-1"
//usage: "\n"
//usage: "\nFormat specifiers:"
//usage: "\n %Nc or %[cN] CPU. N - bar size (default:10)"
@@ -53,6 +53,7 @@
// totalswap=134209536, freeswap=134209536, procs=157})
#include "libbb.h"
+#include "common_bufsiz.h"
typedef unsigned long long ullong;
@@ -83,10 +84,10 @@ struct globals {
smallint is26;
// 1 if sample delay is not an integer fraction of a second
smallint need_seconds;
+ char final_char;
char *cur_outbuf;
- const char *final_str;
int delta;
- int deltanz;
+ unsigned deltanz;
struct timeval tv;
#define first_proc_file proc_stat
proc_file proc_stat; // Must match the order of proc_name's!
@@ -101,9 +102,6 @@ struct globals {
#define is26 (G.is26 )
#define need_seconds (G.need_seconds )
#define cur_outbuf (G.cur_outbuf )
-#define final_str (G.final_str )
-#define delta (G.delta )
-#define deltanz (G.deltanz )
#define tv (G.tv )
#define proc_stat (G.proc_stat )
#define proc_loadavg (G.proc_loadavg )
@@ -111,16 +109,15 @@ struct globals {
#define proc_meminfo (G.proc_meminfo )
#define proc_diskstats (G.proc_diskstats )
#define proc_sys_fs_filenr (G.proc_sys_fs_filenr)
+#define outbuf bb_common_bufsiz1
#define INIT_G() do { \
+ setup_common_bufsiz(); \
SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
cur_outbuf = outbuf; \
- final_str = "\n"; \
- deltanz = delta = 1000000; \
+ G.final_char = '\n'; \
+ G.deltanz = G.delta = 1000000; \
} while (0)
-// We depend on this being a char[], not char* - we take sizeof() of it
-#define outbuf bb_common_bufsiz1
-
static inline void reset_outbuf(void)
{
cur_outbuf = outbuf;
@@ -142,16 +139,16 @@ static void print_outbuf(void)
static void put(const char *s)
{
- int sz = strlen(s);
- if (sz > outbuf + sizeof(outbuf) - cur_outbuf)
- sz = outbuf + sizeof(outbuf) - cur_outbuf;
- memcpy(cur_outbuf, s, sz);
- cur_outbuf += sz;
+ char *p = cur_outbuf;
+ int sz = outbuf + COMMON_BUFSIZE - p;
+ while (*s && --sz >= 0)
+ *p++ = *s++;
+ cur_outbuf = p;
}
static void put_c(char c)
{
- if (cur_outbuf < outbuf + sizeof(outbuf))
+ if (cur_outbuf < outbuf + COMMON_BUFSIZE)
*cur_outbuf++ = c;
}
@@ -208,70 +205,55 @@ static ullong read_after_slash(const char *p)
return strtoull(p+1, NULL, 10);
}
-enum conv_type { conv_decimal, conv_slash };
+enum conv_type {
+ conv_decimal = 0,
+ conv_slash = 1
+};
// Reads decimal values from line. Values start after key, for example:
// "cpu 649369 0 341297 4336769..." - key is "cpu" here.
-// Values are stored in vec[]. arg_ptr has list of positions
-// we are interested in: for example: 1,2,5 - we want 1st, 2nd and 5th value.
-static int vrdval(const char* p, const char* key,
- enum conv_type conv, ullong *vec, va_list arg_ptr)
+// Values are stored in vec[].
+// posbits is a bit lit of positions we are interested in.
+// for example: 00100110 - we want 1st, 2nd and 5th value.
+// posbits.bit0 encodes conversion type.
+static int rdval(const char* p, const char* key, ullong *vec, long posbits)
{
- int indexline;
- int indexnext;
+ unsigned curpos;
p = strstr(p, key);
if (!p) return 1;
p += strlen(key);
- indexline = 1;
- indexnext = va_arg(arg_ptr, int);
+ curpos = 1 << 1;
while (1) {
while (*p == ' ' || *p == '\t') p++;
if (*p == '\n' || *p == '\0') break;
- if (indexline == indexnext) { // read this value
- *vec++ = conv==conv_decimal ?
+ if (curpos & posbits) { // read this value
+ *vec++ = (posbits & 1) == conv_decimal ?
strtoull(p, NULL, 10) :
read_after_slash(p);
- indexnext = va_arg(arg_ptr, int);
+ posbits -= curpos;
+ if (posbits <= 1)
+ return 0;
}
- while (*p > ' ') p++; // skip over value
- indexline++;
+ while (*p > ' ') // skip over the value
+ p++;
+ curpos <<= 1;
}
return 0;
}
-// Parses files with lines like "cpu0 21727 0 15718 1813856 9461 10485 0 0":
-// rdval(file_contents, "string_to_find", result_vector, value#, value#...)
-// value# start with 1
-static int rdval(const char* p, const char* key, ullong *vec, ...)
-{
- va_list arg_ptr;
- int result;
-
- va_start(arg_ptr, vec);
- result = vrdval(p, key, conv_decimal, vec, arg_ptr);
- va_end(arg_ptr);
-
- return result;
-}
-
// Parses files with lines like "... ... ... 3/148 ...."
-static int rdval_loadavg(const char* p, ullong *vec, ...)
+static int rdval_loadavg(const char* p, ullong *vec, long posbits)
{
- va_list arg_ptr;
int result;
-
- va_start(arg_ptr, vec);
- result = vrdval(p, "", conv_slash, vec, arg_ptr);
- va_end(arg_ptr);
-
+ result = rdval(p, "", vec, posbits | conv_slash);
return result;
}
// Parses /proc/diskstats
-// 1 2 3 4 5 6(rd) 7 8 9 10(wr) 11 12 13 14
+// 1 2 3 4 5 6(rd) 7 8 9 10(wr) 11 12 13 14
// 3 0 hda 51292 14441 841783 926052 25717 79650 843256 3029804 0 148459 3956933
// 3 1 hda1 0 0 0 0 <- ignore if only 4 fields
// Linux 3.0 (maybe earlier) started printing full stats for hda1 too.
@@ -333,12 +315,10 @@ static void scale(ullong ul)
char buf[5];
/* see http://en.wikipedia.org/wiki/Tera */
- smart_ulltoa4(ul, buf, " kmgtpezy");
- buf[4] = '\0';
+ smart_ulltoa4(ul, buf, " kmgtpezy")[0] = '\0';
put(buf);
}
-
#define S_STAT(a) \
typedef struct a { \
struct s_stat *next; \
@@ -360,21 +340,12 @@ static s_stat* init_literal(void)
return (s_stat*)s;
}
-static s_stat* init_delay(const char *param)
-{
- delta = strtoul(param, NULL, 0) * 1000; /* param can be "" */
- deltanz = delta > 0 ? delta : 1;
- need_seconds = (1000000%deltanz) != 0;
- return NULL;
-}
-
static s_stat* init_cr(const char *param UNUSED_PARAM)
{
- final_str = "\r";
- return (s_stat*)0;
+ G.final_char = '\r';
+ return NULL;
}
-
// user nice system idle iowait irq softirq (last 3 only in 2.6)
//cpu 649369 0 341297 4336769 11640 7122 1183
//cpuN 649369 0 341297 4336769 11640 7122 1183
@@ -382,10 +353,9 @@ enum { CPU_FIELDCNT = 7 };
S_STAT(cpu_stat)
ullong old[CPU_FIELDCNT];
int bar_sz;
- char *bar;
+ char bar[1];
S_STAT_END(cpu_stat)
-
static void FAST_FUNC collect_cpu(cpu_stat *s)
{
ullong data[CPU_FIELDCNT] = { 0, 0, 0, 0, 0, 0, 0 };
@@ -396,7 +366,15 @@ static void FAST_FUNC collect_cpu(cpu_stat *s)
char *bar = s->bar;
int i;
- if (rdval(get_file(&proc_stat), "cpu ", data, 1, 2, 3, 4, 5, 6, 7)) {
+ if (rdval(get_file(&proc_stat), "cpu ", data, 0
+ | (1 << 1)
+ | (1 << 2)
+ | (1 << 3)
+ | (1 << 4)
+ | (1 << 5)
+ | (1 << 6)
+ | (1 << 7))
+ ) {
put_question_marks(bar_sz);
return;
}
@@ -439,22 +417,20 @@ static void FAST_FUNC collect_cpu(cpu_stat *s)
put(s->bar);
}
-
static s_stat* init_cpu(const char *param)
{
int sz;
- cpu_stat *s = xzalloc(sizeof(*s));
- s->collect = collect_cpu;
+ cpu_stat *s;
sz = strtoul(param, NULL, 0); /* param can be "" */
if (sz < 10) sz = 10;
if (sz > 1000) sz = 1000;
- s->bar = xzalloc(sz+1);
+ s = xzalloc(sizeof(*s) + sz);
/*s->bar[sz] = '\0'; - xzalloc did it */
s->bar_sz = sz;
+ s->collect = collect_cpu;
return (s_stat*)s;
}
-
S_STAT(int_stat)
ullong old;
int no;
@@ -465,7 +441,7 @@ static void FAST_FUNC collect_int(int_stat *s)
ullong data[1];
ullong old;
- if (rdval(get_file(&proc_stat), "intr", data, s->no)) {
+ if (rdval(get_file(&proc_stat), "intr", data, 1 << s->no)) {
put_question_marks(4);
return;
}
@@ -489,7 +465,6 @@ static s_stat* init_int(const char *param)
return (s_stat*)s;
}
-
S_STAT(ctx_stat)
ullong old;
S_STAT_END(ctx_stat)
@@ -499,7 +474,7 @@ static void FAST_FUNC collect_ctx(ctx_stat *s)
ullong data[1];
ullong old;
- if (rdval(get_file(&proc_stat), "ctxt", data, 1)) {
+ if (rdval(get_file(&proc_stat), "ctxt", data, 1 << 1)) {
put_question_marks(4);
return;
}
@@ -517,7 +492,6 @@ static s_stat* init_ctx(const char *param UNUSED_PARAM)
return (s_stat*)s;
}
-
S_STAT(blk_stat)
const char* lookfor;
ullong old[2];
@@ -531,7 +505,10 @@ static void FAST_FUNC collect_blk(blk_stat *s)
if (is26) {
i = rdval_diskstats(get_file(&proc_diskstats), data);
} else {
- i = rdval(get_file(&proc_stat), s->lookfor, data, 1, 2);
+ i = rdval(get_file(&proc_stat), s->lookfor, data, 0
+ | (1 << 1)
+ | (1 << 2)
+ );
// Linux 2.4 reports bio in Kbytes, convert to sectors:
data[0] *= 2;
data[1] *= 2;
@@ -560,7 +537,6 @@ static s_stat* init_blk(const char *param UNUSED_PARAM)
return (s_stat*)s;
}
-
S_STAT(fork_stat)
ullong old;
S_STAT_END(fork_stat)
@@ -569,7 +545,7 @@ static void FAST_FUNC collect_thread_nr(fork_stat *s UNUSED_PARAM)
{
ullong data[1];
- if (rdval_loadavg(get_file(&proc_loadavg), data, 4)) {
+ if (rdval_loadavg(get_file(&proc_loadavg), data, 1 << 4)) {
put_question_marks(4);
return;
}
@@ -581,7 +557,7 @@ static void FAST_FUNC collect_fork(fork_stat *s)
ullong data[1];
ullong old;
- if (rdval(get_file(&proc_stat), "processes", data, 1)) {
+ if (rdval(get_file(&proc_stat), "processes", data, 1 << 1)) {
put_question_marks(4);
return;
}
@@ -603,7 +579,6 @@ static s_stat* init_fork(const char *param)
return (s_stat*)s;
}
-
S_STAT(if_stat)
ullong old[4];
const char *device;
@@ -615,7 +590,12 @@ static void FAST_FUNC collect_if(if_stat *s)
ullong data[4];
int i;
- if (rdval(get_file(&proc_net_dev), s->device_colon, data, 1, 3, 9, 11)) {
+ if (rdval(get_file(&proc_net_dev), s->device_colon, data, 0
+ | (1 << 1)
+ | (1 << 3)
+ | (1 << 9)
+ | (1 << 11))
+ ) {
put_question_marks(10);
return;
}
@@ -645,7 +625,6 @@ static s_stat* init_if(const char *device)
return (s_stat*)s;
}
-
S_STAT(mem_stat)
char opt;
S_STAT_END(mem_stat)
@@ -693,7 +672,7 @@ static void FAST_FUNC collect_mem(mem_stat *s)
ullong m_cached = 0;
ullong m_slab = 0;
- if (rdval(get_file(&proc_meminfo), "MemTotal:", &m_total, 1)) {
+ if (rdval(get_file(&proc_meminfo), "MemTotal:", &m_total, 1 << 1)) {
put_question_marks(4);
return;
}
@@ -702,10 +681,10 @@ static void FAST_FUNC collect_mem(mem_stat *s)
return;
}
- if (rdval(proc_meminfo.file, "MemFree:", &m_free , 1)
- || rdval(proc_meminfo.file, "Buffers:", &m_bufs , 1)
- || rdval(proc_meminfo.file, "Cached:", &m_cached, 1)
- || rdval(proc_meminfo.file, "Slab:", &m_slab , 1)
+ if (rdval(proc_meminfo.file, "MemFree:", &m_free , 1 << 1)
+ || rdval(proc_meminfo.file, "Buffers:", &m_bufs , 1 << 1)
+ || rdval(proc_meminfo.file, "Cached:", &m_cached, 1 << 1)
+ || rdval(proc_meminfo.file, "Slab:", &m_slab , 1 << 1)
) {
put_question_marks(4);
return;
@@ -728,7 +707,6 @@ static s_stat* init_mem(const char *param)
return (s_stat*)s;
}
-
S_STAT(swp_stat)
S_STAT_END(swp_stat)
@@ -736,8 +714,8 @@ static void FAST_FUNC collect_swp(swp_stat *s UNUSED_PARAM)
{
ullong s_total[1];
ullong s_free[1];
- if (rdval(get_file(&proc_meminfo), "SwapTotal:", s_total, 1)
- || rdval(proc_meminfo.file, "SwapFree:" , s_free, 1)
+ if (rdval(get_file(&proc_meminfo), "SwapTotal:", s_total, 1 << 1)
+ || rdval(proc_meminfo.file, "SwapFree:" , s_free, 1 << 1)
) {
put_question_marks(4);
return;
@@ -752,7 +730,6 @@ static s_stat* init_swp(const char *param UNUSED_PARAM)
return (s_stat*)s;
}
-
S_STAT(fd_stat)
S_STAT_END(fd_stat)
@@ -760,7 +737,10 @@ static void FAST_FUNC collect_fd(fd_stat *s UNUSED_PARAM)
{
ullong data[2];
- if (rdval(get_file(&proc_sys_fs_filenr), "", data, 1, 2)) {
+ if (rdval(get_file(&proc_sys_fs_filenr), "", data, 0
+ | (1 << 1)
+ | (1 << 2))
+ ) {
put_question_marks(4);
return;
}
@@ -775,17 +755,16 @@ static s_stat* init_fd(const char *param UNUSED_PARAM)
return (s_stat*)s;
}
-
S_STAT(time_stat)
- int prec;
- int scale;
+ unsigned prec;
+ unsigned scale;
S_STAT_END(time_stat)
static void FAST_FUNC collect_time(time_stat *s)
{
char buf[sizeof("12:34:56.123456")];
struct tm* tm;
- int us = tv.tv_usec + s->scale/2;
+ unsigned us = tv.tv_usec + s->scale/2;
time_t t = tv.tv_sec;
if (us >= 1000000) {
@@ -826,11 +805,9 @@ static void FAST_FUNC collect_info(s_stat *s)
}
}
-
typedef s_stat* init_func(const char *param);
-// Deprecated %NNNd is to be removed, -d MSEC supersedes it
-static const char options[] ALIGN1 = "ncmsfixptbdr";
+static const char options[] ALIGN1 = "ncmsfixptbr";
static init_func *const init_functions[] = {
init_if,
init_cpu,
@@ -842,7 +819,6 @@ static init_func *const init_functions[] = {
init_fork,
init_time,
init_blk,
- init_delay,
init_cr
};
@@ -865,8 +841,11 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv)
is26 = (strstr(buf, " 2.4.") == NULL);
}
- if (getopt32(argv, "d:", &opt_d))
- init_delay(opt_d);
+ if (getopt32(argv, "d:", &opt_d)) {
+ G.delta = xatoi(opt_d) * 1000;
+ G.deltanz = G.delta > 0 ? G.delta : 1;
+ need_seconds = (1000000 % G.deltanz) != 0;
+ }
argv += optind;
if (!argv[0])
@@ -921,8 +900,8 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv)
last->next = s;
last = s;
} else {
- // %NNNNd or %r option. remove it from string
- strcpy(prev + strlen(prev), cur);
+ // %r option. remove it from string
+ overlapping_strcpy(prev + strlen(prev), cur);
cur = prev;
}
}
@@ -940,15 +919,15 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv)
// Generate first samples but do not print them, they're bogus
collect_info(first);
reset_outbuf();
- if (delta >= 0) {
+ if (G.delta >= 0) {
gettimeofday(&tv, NULL);
- usleep(delta > 1000000 ? 1000000 : delta - tv.tv_usec%deltanz);
+ usleep(G.delta > 1000000 ? 1000000 : G.delta - tv.tv_usec % G.deltanz);
}
while (1) {
gettimeofday(&tv, NULL);
collect_info(first);
- put(final_str);
+ put_c(G.final_char);
print_outbuf();
// Negative delta -> no usleep at all
@@ -956,18 +935,18 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv)
// time resolution ;)
// TODO: detect and avoid useless updates
// (like: nothing happens except time)
- if (delta >= 0) {
+ if (G.delta >= 0) {
int rem;
// can be commented out, will sacrifice sleep time precision a bit
gettimeofday(&tv, NULL);
if (need_seconds)
- rem = delta - ((ullong)tv.tv_sec*1000000 + tv.tv_usec) % deltanz;
+ rem = G.delta - ((ullong)tv.tv_sec*1000000 + tv.tv_usec) % G.deltanz;
else
- rem = delta - tv.tv_usec%deltanz;
+ rem = G.delta - (unsigned)tv.tv_usec % G.deltanz;
// Sometimes kernel wakes us up just a tiny bit earlier than asked
// Do not go to very short sleep in this case
- if (rem < delta/128) {
- rem += delta;
+ if (rem < (unsigned)G.delta / 128) {
+ rem += G.delta;
}
usleep(rem);
}
diff --git a/release/src/router/busybox/procps/pgrep.c b/release/src/router/busybox/procps/pgrep.c
index dc7ffff486..1c7c7c48b8 100644
--- a/release/src/router/busybox/procps/pgrep.c
+++ b/release/src/router/busybox/procps/pgrep.c
@@ -65,9 +65,9 @@ static void act(unsigned pid, char *cmd, int signo)
{
if (pgrep) {
if (option_mask32 & (1 << OPTBIT_L)) /* OPT_LIST */
- printf("%d %s\n", pid, cmd);
+ printf("%u %s\n", pid, cmd);
else
- printf("%d\n", pid);
+ printf("%u\n", pid);
} else
kill(pid, signo);
}
@@ -128,7 +128,7 @@ int pgrep_main(int argc UNUSED_PARAM, char **argv)
bb_show_usage();
if (argv[0])
- xregcomp(&re_buffer, argv[0], REG_EXTENDED | REG_NOSUB);
+ xregcomp(&re_buffer, argv[0], OPT_ANCHOR ? REG_EXTENDED : (REG_EXTENDED|REG_NOSUB));
matched_pid = 0;
cmd_last = NULL;
diff --git a/release/src/router/busybox/procps/pmap.c b/release/src/router/busybox/procps/pmap.c
index fd995a54d2..aa221cfb89 100644
--- a/release/src/router/busybox/procps/pmap.c
+++ b/release/src/router/busybox/procps/pmap.c
@@ -20,7 +20,7 @@
//usage:#define pmap_trivial_usage
//usage: "[-xq] PID"
//usage:#define pmap_full_usage "\n\n"
-//usage: "Display detailed process memory usage"
+//usage: "Display process memory usage"
//usage: "\n"
//usage: "\n -x Show details"
//usage: "\n -q Quiet"
@@ -66,7 +66,7 @@ static int procps_get_maps(pid_t pid, unsigned opt)
int ret;
char buf[256];
- read_cmdline(buf, sizeof(buf), pid, "no such process");
+ read_cmdline(buf, sizeof(buf), pid, NULL);
printf("%u: %s\n", (int)pid, buf);
if (!(opt & OPT_q) && (opt & OPT_x))
diff --git a/release/src/router/busybox/procps/powertop.c b/release/src/router/busybox/procps/powertop.c
index 008cdfca4e..ce85f4191e 100644
--- a/release/src/router/busybox/procps/powertop.c
+++ b/release/src/router/busybox/procps/powertop.c
@@ -9,7 +9,7 @@
* Licensed under GPLv2, see file LICENSE in this source tree.
*/
-//applet:IF_POWERTOP(APPLET(powertop, BB_DIR_BIN, BB_SUID_DROP))
+//applet:IF_POWERTOP(APPLET(powertop, BB_DIR_USR_SBIN, BB_SUID_DROP))
//kbuild:lib-$(CONFIG_POWERTOP) += powertop.o
@@ -360,7 +360,7 @@ static void process_irq_counts(void)
}
name = p;
- strchrnul(name, '\n')[0] = '\0';
+ chomp(p);
/* Save description of the interrupt */
if (nr >= 20000)
sprintf(irq_desc, " <kernel IPI> : %s", name);
@@ -458,9 +458,9 @@ static NOINLINE int process_timer_stats(void)
// func = "Load balancing tick";
//}
- if (strncmp(func, "tick_nohz_", 10) == 0)
+ if (is_prefixed_with(func, "tick_nohz_"))
continue;
- if (strncmp(func, "tick_setup_sched_timer", 20) == 0)
+ if (is_prefixed_with(func, "tick_setup_sched_timer"))
continue;
//if (strcmp(process, "powertop") == 0)
// continue;
@@ -470,7 +470,7 @@ static NOINLINE int process_timer_stats(void)
process = idx < 2 ? "[kernel module]" : "<kernel core>";
}
- strchrnul(p, '\n')[0] = '\0';
+ chomp(p);
// 46D\01136\0kondemand/1\0do_dbs_timer (delayed_work_timer_fn)
// ^ ^ ^
@@ -493,7 +493,7 @@ static NOINLINE int process_timer_stats(void)
* Get information about CPU using CPUID opcode.
*/
static void cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx,
- unsigned int *edx)
+ unsigned int *edx)
{
/* EAX value specifies what information to return */
__asm__(
@@ -591,7 +591,7 @@ static NOINLINE void print_intel_cstates(void)
if (!edx || !(ecx & 1))
return;
- printf("Your CPU supports the following C-states: ");
+ printf("Your %s the following C-states: ", "CPU supports");
i = 0;
while (edx) {
if (edx & 7)
@@ -602,7 +602,7 @@ static NOINLINE void print_intel_cstates(void)
bb_putchar('\n');
/* Print BIOS C-States */
- printf("Your BIOS reports the following C-states: ");
+ printf("Your %s the following C-states: ", "BIOS reports");
for (i = 0; i < ARRAY_SIZE(bios_table); i++)
if (bios_table[i])
printf("C%u ", i);
@@ -627,7 +627,6 @@ static void show_timerstats(void)
int i, n = 0;
char strbuf6[6];
- strbuf6[5] = '\0';
puts("\nTop causes for wakeups:");
for (i = 0; i < G.lines_cnt; i++) {
if ((G.lines[i].count > 0 /*|| G.lines[i].disk_count > 0*/)
@@ -639,7 +638,7 @@ static void show_timerstats(void)
/*char c = ' ';
if (G.lines[i].disk_count)
c = 'D';*/
- smart_ulltoa5(G.lines[i].count, strbuf6, " KMGTPEZY");
+ smart_ulltoa5(G.lines[i].count, strbuf6, " KMGTPEZY")[0] = '\0';
printf(/*" %5.1f%% (%s)%c %s\n"*/
" %5.1f%% (%s) %s\n",
G.lines[i].count * 100.0 / G.lines_cumulative_count,
@@ -650,7 +649,7 @@ static void show_timerstats(void)
} else {
bb_putchar('\n');
bb_error_msg("no stats available; run as root or"
- " enable the cpufreq_stats module");
+ " enable the timer_stats module");
}
}
@@ -675,7 +674,7 @@ static void show_timerstats(void)
//usage:#define powertop_trivial_usage
//usage: ""
//usage:#define powertop_full_usage "\n\n"
-//usage: "Analyze power consumption on Intel-based laptops\n"
+//usage: "Analyze power consumption on Intel-based laptops"
int powertop_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv)
@@ -705,7 +704,7 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv)
/* Get number of CPUs */
G.total_cpus = get_cpu_count();
- printf("Collecting data for "DEFAULT_SLEEP_STR" seconds\n");
+ puts("Collecting data for "DEFAULT_SLEEP_STR" seconds");
#if ENABLE_FEATURE_USE_TERMIOS
tcgetattr(0, (void *)&G.init_settings);
diff --git a/release/src/router/busybox/procps/ps.c b/release/src/router/busybox/procps/ps.c
index 3a5af7c186..08dfce12e1 100644
--- a/release/src/router/busybox/procps/ps.c
+++ b/release/src/router/busybox/procps/ps.c
@@ -62,6 +62,7 @@
//usage: " 2990 andersen andersen R ps\n"
#include "libbb.h"
+#include "common_bufsiz.h"
#ifdef __linux__
# include <sys/sysinfo.h>
#endif
@@ -70,7 +71,7 @@
enum { MAX_WIDTH = 2*1024 };
#if ENABLE_FEATURE_PS_TIME || ENABLE_FEATURE_PS_LONG
-static long get_uptime(void)
+static unsigned long get_uptime(void)
{
#ifdef __linux__
struct sysinfo info;
@@ -78,12 +79,15 @@ static long get_uptime(void)
return 0;
return info.uptime;
#elif 1
- char buf[64];
- long uptime;
+ unsigned long uptime;
+ char buf[sizeof(uptime)*3 + 2];
+ /* /proc/uptime is "UPTIME_SEC.NN IDLE_SEC.NN\n"
+ * (where IDLE is cumulative over all CPUs)
+ */
if (open_read_close("/proc/uptime", buf, sizeof(buf)) <= 0)
- bb_perror_msg_and_die("can't read %s", "/proc/uptime");
+ bb_perror_msg_and_die("can't read '%s'", "/proc/uptime");
buf[sizeof(buf)-1] = '\0';
- sscanf(buf, "%l", &uptime);
+ sscanf(buf, "%lu", &uptime);
return uptime;
#else
struct timespec ts;
@@ -138,10 +142,10 @@ struct globals {
unsigned terminal_width;
#if ENABLE_FEATURE_PS_TIME
unsigned kernel_HZ;
- unsigned long long seconds_since_boot;
+ unsigned long seconds_since_boot;
#endif
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define out (G.out )
#define out_cnt (G.out_cnt )
#define print_header (G.print_header )
@@ -149,14 +153,13 @@ struct globals {
#define buffer (G.buffer )
#define terminal_width (G.terminal_width )
#define kernel_HZ (G.kernel_HZ )
-#define seconds_since_boot (G.seconds_since_boot)
-#define INIT_G() do { } while (0)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
#if ENABLE_FEATURE_PS_TIME
/* for ELF executables, notes are pushed before environment and args */
-static ptrdiff_t find_elf_note(ptrdiff_t findme)
+static uintptr_t find_elf_note(uintptr_t findme)
{
- ptrdiff_t *ep = (ptrdiff_t *) environ;
+ uintptr_t *ep = (uintptr_t *) environ;
while (*ep++)
continue;
@@ -222,7 +225,6 @@ static inline unsigned get_HZ_by_waiting(void)
static unsigned get_kernel_HZ(void)
{
-
if (kernel_HZ)
return kernel_HZ;
@@ -231,7 +233,7 @@ static unsigned get_kernel_HZ(void)
if (kernel_HZ == (unsigned)-1)
kernel_HZ = get_HZ_by_waiting();
- seconds_since_boot = get_uptime();
+ G.seconds_since_boot = get_uptime();
return kernel_HZ;
}
@@ -298,8 +300,7 @@ static void put_lu(char *buf, int size, unsigned long u)
char buf4[5];
/* see http://en.wikipedia.org/wiki/Tera */
- smart_ulltoa4(u, buf4, " mgtpezy");
- buf4[4] = '\0';
+ smart_ulltoa4(u, buf4, " mgtpezy")[0] = '\0';
sprintf(buf, "%.*s", size, buf4);
}
@@ -350,7 +351,7 @@ static void func_etime(char *buf, int size, const procps_status_t *ps)
mm = ps->start_time / get_kernel_HZ();
/* must be after get_kernel_HZ()! */
- mm = seconds_since_boot - mm;
+ mm = G.seconds_since_boot - mm;
ss = mm % 60;
mm /= 60;
snprintf(buf, size+1, "%3lu:%02u", mm, ss);
@@ -588,7 +589,7 @@ int ps_main(int argc UNUSED_PARAM, char **argv)
// -o col1,col2,col3=header
// Select which columns to display
/* We allow (and ignore) most of the above. FIXME.
- * -T is picked for threads (POSIX hasn't it standardized).
+ * -T is picked for threads (POSIX hasn't standardized it).
* procps v3.2.7 supports -T and shows tids as SPID column,
* it also supports -L where it shows tids as LWP column.
*/
@@ -599,7 +600,9 @@ int ps_main(int argc UNUSED_PARAM, char **argv)
parse_o(llist_pop(&opt_o));
} while (opt_o);
} else {
- /* Below: parse_o() needs char*, NOT const char*, can't give it default_o */
+ /* Below: parse_o() needs char*, NOT const char*,
+ * can't pass it constant string. Need to make a copy first.
+ */
#if ENABLE_SELINUX
if (!(opt & OPT_Z) || !is_selinux_enabled()) {
/* no -Z or no SELinux: do not show LABEL */
@@ -620,7 +623,7 @@ int ps_main(int argc UNUSED_PARAM, char **argv)
* and such large widths */
terminal_width = MAX_WIDTH;
if (isatty(1)) {
- get_terminal_width_height(0, &terminal_width, NULL);
+ terminal_width = get_terminal_width(0);
if (--terminal_width > MAX_WIDTH)
terminal_width = MAX_WIDTH;
}
@@ -652,12 +655,12 @@ int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
OPT_l = (1 << ENABLE_SELINUX) * (1 << ENABLE_FEATURE_SHOW_THREADS) * ENABLE_FEATURE_PS_LONG,
};
#if ENABLE_FEATURE_PS_LONG
- time_t now = now;
- long uptime;
+ time_t now = now; /* for compiler */
+ unsigned long uptime = uptime;
#endif
- int opts = 0;
/* If we support any options, parse argv */
#if ENABLE_SELINUX || ENABLE_FEATURE_SHOW_THREADS || ENABLE_FEATURE_PS_WIDE || ENABLE_FEATURE_PS_LONG
+ int opts = 0;
# if ENABLE_FEATURE_PS_WIDE
/* -w is a bit complicated */
int w_count = 0;
@@ -670,7 +673,7 @@ int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
if (w_count) {
terminal_width = (w_count == 1) ? 132 : MAX_WIDTH;
} else {
- get_terminal_width_height(0, &terminal_width, NULL);
+ terminal_width = get_terminal_width(0);
/* Go one less... */
if (--terminal_width > MAX_WIDTH)
terminal_width = MAX_WIDTH;
@@ -711,10 +714,10 @@ int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
* We also show STIME (standard says that -f shows it, -l doesn't).
*/
puts("S UID PID PPID VSZ RSS TTY STIME TIME CMD");
-#if ENABLE_FEATURE_PS_LONG
+# if ENABLE_FEATURE_PS_LONG
now = time(NULL);
uptime = get_uptime();
-#endif
+# endif
}
else {
puts(" PID USER VSZ STAT COMMAND");
@@ -737,8 +740,7 @@ int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
#endif
{
char buf6[6];
- smart_ulltoa5(p->vsz, buf6, " mgtpezy");
- buf6[5] = '\0';
+ smart_ulltoa5(p->vsz, buf6, " mgtpezy")[0] = '\0';
#if ENABLE_FEATURE_PS_LONG
if (opts & OPT_l) {
char bufr[6], stime_str[6];
@@ -749,8 +751,7 @@ int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
time_t start = now - elapsed;
struct tm *tm = localtime(&start);
- smart_ulltoa5(p->rss, bufr, " mgtpezy");
- bufr[5] = '\0';
+ smart_ulltoa5(p->rss, bufr, " mgtpezy")[0] = '\0';
if (p->tty_major == 136)
/* It should be pts/N, not ptsN, but N > 9
@@ -786,9 +787,11 @@ int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
{
int sz = terminal_width - len;
- char buf[sz + 1];
- read_cmdline(buf, sz, p->pid, p->comm);
- puts(buf);
+ if (sz >= 0) {
+ char buf[sz + 1];
+ read_cmdline(buf, sz, p->pid, p->comm);
+ puts(buf);
+ }
}
}
if (ENABLE_FEATURE_CLEAN_UP)
diff --git a/release/src/router/busybox/procps/pstree.c b/release/src/router/busybox/procps/pstree.c
index 8ba30795dc..c5fb83688e 100644
--- a/release/src/router/busybox/procps/pstree.c
+++ b/release/src/router/busybox/procps/pstree.c
@@ -34,8 +34,15 @@
struct child;
+#ifdef ENABLE_FEATURE_SHOW_THREADS
+/* For threads, we add {...} around the comm, so we need two extra bytes */
+# define COMM_DISP_LEN (COMM_LEN + 2)
+#else
+# define COMM_DISP_LEN COMM_LEN
+#endif
+
typedef struct proc {
- char comm[COMM_LEN + 1];
+ char comm[COMM_DISP_LEN + 1];
// char flags; - unused, delete?
pid_t pid;
uid_t uid;
@@ -341,8 +348,8 @@ static void dump_by_user(PROC *current, uid_t uid)
#if ENABLE_FEATURE_SHOW_THREADS
static void handle_thread(const char *comm, pid_t pid, pid_t ppid, uid_t uid)
{
- char threadname[COMM_LEN + 2];
- sprintf(threadname, "{%.*s}", COMM_LEN - 2, comm);
+ char threadname[COMM_DISP_LEN + 1];
+ sprintf(threadname, "{%.*s}", (int)sizeof(threadname) - 3, comm);
add_proc(threadname, pid, ppid, uid/*, 1*/);
}
#endif
@@ -374,7 +381,7 @@ int pstree_main(int argc UNUSED_PARAM, char **argv)
INIT_G();
- get_terminal_width_height(0, &G.output_width, NULL);
+ G.output_width = get_terminal_width(0);
opt_complementary = "?1";
getopt32(argv, "p");
diff --git a/release/src/router/busybox/procps/pwdx.c b/release/src/router/busybox/procps/pwdx.c
index 7818104885..4e34149ed3 100644
--- a/release/src/router/busybox/procps/pwdx.c
+++ b/release/src/router/busybox/procps/pwdx.c
@@ -21,7 +21,7 @@
//usage:#define pwdx_trivial_usage
//usage: "PID..."
//usage:#define pwdx_full_usage "\n\n"
-//usage: "Show current directory for PIDs\n"
+//usage: "Show current directory for PIDs"
#include "libbb.h"
@@ -41,7 +41,7 @@ int pwdx_main(int argc UNUSED_PARAM, char **argv)
// Allowed on the command line:
// /proc/NUM
// NUM
- if (strncmp(arg, "/proc/", 6) == 0)
+ if (is_prefixed_with(arg, "/proc/"))
arg += 6;
pid = bb_strtou(arg, NULL, 10);
diff --git a/release/src/router/busybox/procps/renice.c b/release/src/router/busybox/procps/renice.c
index 77f400a1d6..2b690e0ed0 100644
--- a/release/src/router/busybox/procps/renice.c
+++ b/release/src/router/busybox/procps/renice.c
@@ -20,13 +20,14 @@
*/
//usage:#define renice_trivial_usage
-//usage: "{{-n INCREMENT} | PRIORITY} [[-p | -g | -u] ID...]"
+//usage: "[-n] PRIORITY [[-p | -g | -u] ID...]..."
//usage:#define renice_full_usage "\n\n"
-//usage: "Change scheduling priority for a running process\n"
-//usage: "\n -n Adjust current nice value (smaller is faster)"
-//usage: "\n -p Process id(s) (default)"
-//usage: "\n -g Process group id(s)"
-//usage: "\n -u Process user name(s) and/or id(s)"
+//usage: "Change scheduling priority of a running process\n"
+//usage: "\n -n Add PRIORITY to current nice value"
+//usage: "\n Without -n, nice value is set to PRIORITY"
+//usage: "\n -p Process ids (default)"
+//usage: "\n -g Process group ids"
+//usage: "\n -u Process user names"
#include "libbb.h"
#include <sys/resource.h>
diff --git a/release/src/router/busybox/procps/sysctl.c b/release/src/router/busybox/procps/sysctl.c
index 5296d0f581..f0883f0540 100644
--- a/release/src/router/busybox/procps/sysctl.c
+++ b/release/src/router/busybox/procps/sysctl.c
@@ -12,21 +12,23 @@
*/
//usage:#define sysctl_trivial_usage
-//usage: "[OPTIONS] [VALUE]..."
+//usage: "[OPTIONS] [KEY[=VALUE]]..."
//usage:#define sysctl_full_usage "\n\n"
-//usage: "Configure kernel parameters at runtime\n"
-//usage: "\n -n Don't print key names"
+//usage: "Show/set kernel parameters\n"
//usage: "\n -e Don't warn about unknown keys"
-//usage: "\n -w Change sysctl setting"
-//usage: "\n -p FILE Load sysctl settings from FILE (default /etc/sysctl.conf)"
-//usage: "\n -a Display all values"
-//usage: "\n -A Display all values in table form"
+//usage: "\n -n Don't show key names"
+//usage: "\n -a Show all values"
+/* Same as -a, no need to show it */
+/* //usage: "\n -A Show all values in table form" */
+//usage: "\n -w Set values"
+//usage: "\n -p FILE Set values from FILE (default /etc/sysctl.conf)"
+//usage: "\n -q Set values silently"
//usage:
//usage:#define sysctl_example_usage
//usage: "sysctl [-n] [-e] variable...\n"
-//usage: "sysctl [-n] [-e] -w variable=value...\n"
+//usage: "sysctl [-n] [-e] [-q] -w variable=value...\n"
//usage: "sysctl [-n] [-e] -a\n"
-//usage: "sysctl [-n] [-e] -p file (default /etc/sysctl.conf)\n"
+//usage: "sysctl [-n] [-e] [-q] -p file (default /etc/sysctl.conf)\n"
//usage: "sysctl [-n] [-e] -A\n"
#include "libbb.h"
@@ -37,9 +39,11 @@ enum {
FLAG_TABLE_FORMAT = 1 << 2, /* not implemented */
FLAG_SHOW_ALL = 1 << 3,
FLAG_PRELOAD_FILE = 1 << 4,
+/* TODO: procps 3.2.8 seems to not require -w for KEY=VAL to work: */
FLAG_WRITE = 1 << 5,
+ FLAG_QUIET = 1 << 6,
};
-#define OPTION_STR "neAapw"
+#define OPTION_STR "neAapwq"
static void sysctl_dots_to_slashes(char *name)
{
@@ -125,6 +129,9 @@ static int sysctl_act_on_setting(char *setting)
if (fd < 0) {
switch (errno) {
+ case EACCES:
+ /* Happens for write-only settings, e.g. net.ipv6.route.flush */
+ goto end;
case ENOENT:
if (option_mask32 & FLAG_SHOW_KEY_ERRORS)
bb_error_msg("error: '%s' is an unknown key", outname);
@@ -144,9 +151,11 @@ static int sysctl_act_on_setting(char *setting)
//TODO: procps 3.2.7 writes "value\n", note trailing "\n"
xwrite_str(fd, value);
close(fd);
- if (option_mask32 & FLAG_SHOW_KEYS)
- printf("%s = ", outname);
- puts(value);
+ if (!(option_mask32 & FLAG_QUIET)) {
+ if (option_mask32 & FLAG_SHOW_KEYS)
+ printf("%s = ", outname);
+ puts(value);
+ }
} else {
char c;
@@ -199,7 +208,7 @@ static int sysctl_act_recursive(const char *path)
continue; /* d_name is "." or ".." */
/* if path was ".", drop "./" prefix: */
retval |= sysctl_act_recursive((next[0] == '.' && next[1] == '/') ?
- next + 2 : next);
+ next + 2 : next);
free(next);
}
closedir(dirp);
diff --git a/release/src/router/busybox/procps/top.c b/release/src/router/busybox/procps/top.c
index 15eb624cce..73cd285f0f 100644
--- a/release/src/router/busybox/procps/top.c
+++ b/release/src/router/busybox/procps/top.c
@@ -50,7 +50,62 @@
* chroot . ./top -bn1 >top1.out
*/
+//config:config TOP
+//config: bool "top"
+//config: default y
+//config: help
+//config: The top program provides a dynamic real-time view of a running
+//config: system.
+//config:
+//config:config FEATURE_TOP_CPU_USAGE_PERCENTAGE
+//config: bool "Show CPU per-process usage percentage"
+//config: default y
+//config: depends on TOP
+//config: help
+//config: Make top display CPU usage for each process.
+//config: This adds about 2k.
+//config:
+//config:config FEATURE_TOP_CPU_GLOBAL_PERCENTS
+//config: bool "Show CPU global usage percentage"
+//config: default y
+//config: depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE
+//config: help
+//config: Makes top display "CPU: NN% usr NN% sys..." line.
+//config: This adds about 0.5k.
+//config:
+//config:config FEATURE_TOP_SMP_CPU
+//config: bool "SMP CPU usage display ('c' key)"
+//config: default y
+//config: depends on FEATURE_TOP_CPU_GLOBAL_PERCENTS
+//config: help
+//config: Allow 'c' key to switch between individual/cumulative CPU stats
+//config: This adds about 0.5k.
+//config:
+//config:config FEATURE_TOP_DECIMALS
+//config: bool "Show 1/10th of a percent in CPU/mem statistics"
+//config: default y
+//config: depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE
+//config: help
+//config: Show 1/10th of a percent in CPU/mem statistics.
+//config: This adds about 0.3k.
+//config:
+//config:config FEATURE_TOP_SMP_PROCESS
+//config: bool "Show CPU process runs on ('j' field)"
+//config: default y
+//config: depends on TOP
+//config: help
+//config: Show CPU where process was last found running on.
+//config: This is the 'j' field.
+//config:
+//config:config FEATURE_TOPMEM
+//config: bool "Topmem command ('s' key)"
+//config: default y
+//config: depends on TOP
+//config: help
+//config: Enable 's' in top (gives lots of memory info).
+
#include "libbb.h"
+#include "common_bufsiz.h"
typedef struct top_status_t {
@@ -99,8 +154,13 @@ struct globals {
#if ENABLE_FEATURE_TOP_SMP_CPU
smallint smp_cpu_info; /* one/many cpu info lines? */
#endif
+ unsigned lines; /* screen height */
#if ENABLE_FEATURE_USE_TERMIOS
struct termios initial_settings;
+ int scroll_ofs;
+#define G_scroll_ofs G.scroll_ofs
+#else
+#define G_scroll_ofs 0
#endif
#if !ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
cmp_funcp sort_function[1];
@@ -118,14 +178,13 @@ struct globals {
jiffy_counts_t *cpu_jif, *cpu_prev_jif;
int num_cpus;
#endif
+#if ENABLE_FEATURE_USE_TERMIOS
+ char kbd_input[KEYCODE_BUFFER_SIZE];
+#endif
char line_buf[80];
}; //FIX_ALIASING; - large code growth
enum { LINE_BUF_SIZE = COMMON_BUFSIZE - offsetof(struct globals, line_buf) };
-#define G (*(struct globals*)&bb_common_bufsiz1)
-struct BUG_bad_size {
- char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
- char BUG_line_buf_too_small[LINE_BUF_SIZE > 80 ? 1 : -1];
-};
+#define G (*(struct globals*)bb_common_bufsiz1)
#define top (G.top )
#define ntop (G.ntop )
#define sort_field (G.sort_field )
@@ -142,7 +201,11 @@ struct BUG_bad_size {
#define num_cpus (G.num_cpus )
#define total_pcpu (G.total_pcpu )
#define line_buf (G.line_buf )
-#define INIT_G() do { } while (0)
+#define INIT_G() do { \
+ setup_common_bufsiz(); \
+ BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
+ BUILD_BUG_ON(LINE_BUF_SIZE <= 80); \
+} while (0)
enum {
OPT_d = (1 << 0),
@@ -202,9 +265,9 @@ static int mult_lvl_cmp(void* a, void* b)
static NOINLINE int read_cpu_jiffy(FILE *fp, jiffy_counts_t *p_jif)
{
#if !ENABLE_FEATURE_TOP_SMP_CPU
- static const char fmt[] = "cpu %llu %llu %llu %llu %llu %llu %llu %llu";
+ static const char fmt[] ALIGN1 = "cpu %llu %llu %llu %llu %llu %llu %llu %llu";
#else
- static const char fmt[] = "cp%*s %llu %llu %llu %llu %llu %llu %llu %llu";
+ static const char fmt[] ALIGN1 = "cp%*s %llu %llu %llu %llu %llu %llu %llu %llu";
#endif
int ret;
@@ -232,7 +295,7 @@ static void get_jiffy_counts(void)
* they are used to calculate per process CPU% */
prev_jif = cur_jif;
if (read_cpu_jiffy(fp, &cur_jif) < 4)
- bb_error_msg_and_die("can't read /proc/stat");
+ bb_error_msg_and_die("can't read '%s'", "/proc/stat");
#if !ENABLE_FEATURE_TOP_SMP_CPU
fclose(fp);
@@ -437,85 +500,93 @@ static void display_cpus(int scr_width, char *scrbuf, int *lines_rem_p)
# define display_cpus(scr_width, scrbuf, lines_rem) ((void)0)
#endif
-static unsigned long display_header(int scr_width, int *lines_rem_p)
-{
- FILE *fp;
- char buf[80];
- char scrbuf[80];
- unsigned long total, used, mfree, shared, buffers, cached;
-
- /* read memory info */
- fp = xfopen_for_read("meminfo");
+enum {
+ MI_MEMTOTAL,
+ MI_MEMFREE,
+ MI_MEMSHARED,
+ MI_SHMEM,
+ MI_BUFFERS,
+ MI_CACHED,
+ MI_SWAPTOTAL,
+ MI_SWAPFREE,
+ MI_DIRTY,
+ MI_WRITEBACK,
+ MI_ANONPAGES,
+ MI_MAPPED,
+ MI_SLAB,
+ MI_MAX
+};
- /*
- * Old kernels (such as 2.4.x) had a nice summary of memory info that
- * we could parse, however this is gone entirely in 2.6. Try parsing
- * the old way first, and if that fails, parse each field manually.
- *
- * First, we read in the first line. Old kernels will have bogus
- * strings we don't care about, whereas new kernels will start right
- * out with MemTotal:
- * -- PFM.
- */
- if (fscanf(fp, "MemTotal: %lu %s\n", &total, buf) != 2) {
- fgets(buf, sizeof(buf), fp); /* skip first line */
-
- fscanf(fp, "Mem: %lu %lu %lu %lu %lu %lu",
- &total, &used, &mfree, &shared, &buffers, &cached);
- /* convert to kilobytes */
- used /= 1024;
- mfree /= 1024;
- shared /= 1024;
- buffers /= 1024;
- cached /= 1024;
- total /= 1024;
- } else {
- /*
- * Revert to manual parsing, which incidentally already has the
- * sizes in kilobytes. This should be safe for both 2.4 and
- * 2.6.
- */
- fscanf(fp, "MemFree: %lu %s\n", &mfree, buf);
+static void parse_meminfo(unsigned long meminfo[MI_MAX])
+{
+ static const char fields[] ALIGN1 =
+ "MemTotal\0"
+ "MemFree\0"
+ "MemShared\0"
+ "Shmem\0"
+ "Buffers\0"
+ "Cached\0"
+ "SwapTotal\0"
+ "SwapFree\0"
+ "Dirty\0"
+ "Writeback\0"
+ "AnonPages\0"
+ "Mapped\0"
+ "Slab\0";
+ char buf[60]; /* actual lines we expect are ~30 chars or less */
+ FILE *f;
+ int i;
- /*
- * MemShared: is no longer present in 2.6. Report this as 0,
- * to maintain consistent behavior with normal procps.
- */
- if (fscanf(fp, "MemShared: %lu %s\n", &shared, buf) != 2)
- shared = 0;
+ memset(meminfo, 0, sizeof(meminfo[0]) * MI_MAX);
+ f = xfopen_for_read("meminfo");
+ while (fgets(buf, sizeof(buf), f) != NULL) {
+ char *c = strchr(buf, ':');
+ if (!c)
+ continue;
+ *c = '\0';
+ i = index_in_strings(fields, buf);
+ if (i >= 0)
+ meminfo[i] = strtoul(c+1, NULL, 10);
+ }
+ fclose(f);
+}
- fscanf(fp, "Buffers: %lu %s\n", &buffers, buf);
- fscanf(fp, "Cached: %lu %s\n", &cached, buf);
+static unsigned long display_header(int scr_width, int *lines_rem_p)
+{
+ char scrbuf[100]; /* [80] was a bit too low on 8Gb ram box */
+ char *buf;
+ unsigned long meminfo[MI_MAX];
- used = total - mfree;
- }
- fclose(fp);
+ parse_meminfo(meminfo);
- /* output memory info */
+ /* Output memory info */
if (scr_width > (int)sizeof(scrbuf))
scr_width = sizeof(scrbuf);
snprintf(scrbuf, scr_width,
"Mem: %luK used, %luK free, %luK shrd, %luK buff, %luK cached",
- used, mfree, shared, buffers, cached);
- /* go to top & clear to the end of screen */
+ meminfo[MI_MEMTOTAL] - meminfo[MI_MEMFREE],
+ meminfo[MI_MEMFREE],
+ meminfo[MI_MEMSHARED] + meminfo[MI_SHMEM],
+ meminfo[MI_BUFFERS],
+ meminfo[MI_CACHED]);
+ /* Go to top & clear to the end of screen */
printf(OPT_BATCH_MODE ? "%s\n" : "\033[H\033[J%s\n", scrbuf);
(*lines_rem_p)--;
- /* Display CPU time split as percentage of total time
- * This displays either a cumulative line or one line per CPU
+ /* Display CPU time split as percentage of total time.
+ * This displays either a cumulative line or one line per CPU.
*/
display_cpus(scr_width, scrbuf, lines_rem_p);
- /* read load average as a string */
- buf[0] = '\0';
- open_read_close("loadavg", buf, sizeof(buf) - 1);
- buf[sizeof(buf) - 1] = '\n';
- *strchr(buf, '\n') = '\0';
- snprintf(scrbuf, scr_width, "Load average: %s", buf);
+ /* Read load average as a string */
+ buf = stpcpy(scrbuf, "Load average: ");
+ open_read_close("loadavg", buf, sizeof(scrbuf) - sizeof("Load average: "));
+ scrbuf[scr_width - 1] = '\0';
+ strchrnul(buf, '\n')[0] = '\0';
puts(scrbuf);
(*lines_rem_p)--;
- return total;
+ return meminfo[MI_MEMTOTAL];
}
static NOINLINE void display_process_list(int lines_rem, int scr_width)
@@ -602,9 +673,9 @@ static NOINLINE void display_process_list(int lines_rem, int scr_width)
/* Ok, all preliminary data is ready, go through the list */
scr_width += 2; /* account for leading '\n' and trailing NUL */
- if (lines_rem > ntop)
- lines_rem = ntop;
- s = top;
+ if (lines_rem > ntop - G_scroll_ofs)
+ lines_rem = ntop - G_scroll_ofs;
+ s = top + G_scroll_ofs;
while (--lines_rem >= 0) {
unsigned col;
CALC_STAT(pmem, (s->vsz*pmem_scale + pmem_half) >> pmem_shift);
@@ -615,7 +686,7 @@ static NOINLINE void display_process_list(int lines_rem, int scr_width)
if (s->vsz >= 100000)
sprintf(vsz_str_buf, "%6ldm", s->vsz/1024);
else
- sprintf(vsz_str_buf, "%7ld", s->vsz);
+ sprintf(vsz_str_buf, "%7lu", s->vsz);
/* PID PPID USER STAT VSZ %VSZ [%CPU] COMMAND */
col = snprintf(line_buf, scr_width,
"\n" "%5u%6u %-8.8s %s%s" FMT
@@ -649,14 +720,14 @@ static void clearmems(void)
clear_username_cache();
free(top);
top = NULL;
- ntop = 0;
}
#if ENABLE_FEATURE_USE_TERMIOS
static void reset_term(void)
{
- tcsetattr_stdin_TCSANOW(&initial_settings);
+ if (!OPT_BATCH_MODE)
+ tcsetattr_stdin_TCSANOW(&initial_settings);
if (ENABLE_FEATURE_CLEAN_UP) {
clearmems();
# if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
@@ -665,10 +736,10 @@ static void reset_term(void)
}
}
-static void sig_catcher(int sig UNUSED_PARAM)
+static void sig_catcher(int sig)
{
reset_term();
- _exit(EXIT_FAILURE);
+ kill_myself_with_sig(sig);
}
#endif /* FEATURE_USE_TERMIOS */
@@ -719,64 +790,31 @@ static int topmem_sort(char *a, char *b)
/* display header info (meminfo / loadavg) */
static void display_topmem_header(int scr_width, int *lines_rem_p)
{
- enum {
- TOTAL = 0, MFREE, BUF, CACHE,
- SWAPTOTAL, SWAPFREE, DIRTY,
- MWRITE, ANON, MAP, SLAB,
- NUM_FIELDS
- };
- static const char match[NUM_FIELDS][12] = {
- "\x09" "MemTotal:", // TOTAL
- "\x08" "MemFree:", // MFREE
- "\x08" "Buffers:", // BUF
- "\x07" "Cached:", // CACHE
- "\x0a" "SwapTotal:", // SWAPTOTAL
- "\x09" "SwapFree:", // SWAPFREE
- "\x06" "Dirty:", // DIRTY
- "\x0a" "Writeback:", // MWRITE
- "\x0a" "AnonPages:", // ANON
- "\x07" "Mapped:", // MAP
- "\x05" "Slab:", // SLAB
- };
- char meminfo_buf[4 * 1024];
- const char *Z[NUM_FIELDS];
- unsigned i;
- int sz;
-
- for (i = 0; i < NUM_FIELDS; i++)
- Z[i] = "?";
-
- /* read memory info */
- sz = open_read_close("meminfo", meminfo_buf, sizeof(meminfo_buf) - 1);
- if (sz >= 0) {
- char *p = meminfo_buf;
- meminfo_buf[sz] = '\0';
- /* Note that fields always appear in the match[] order */
- for (i = 0; i < NUM_FIELDS; i++) {
- char *found = strstr(p, match[i] + 1);
- if (found) {
- /* Cut "NNNN" out of " NNNN kb" */
- char *s = skip_whitespace(found + match[i][0]);
- p = skip_non_whitespace(s);
- *p++ = '\0';
- Z[i] = s;
- }
- }
- }
+ unsigned long meminfo[MI_MAX];
+
+ parse_meminfo(meminfo);
snprintf(line_buf, LINE_BUF_SIZE,
- "Mem total:%s anon:%s map:%s free:%s",
- Z[TOTAL], Z[ANON], Z[MAP], Z[MFREE]);
+ "Mem total:%lu anon:%lu map:%lu free:%lu",
+ meminfo[MI_MEMTOTAL],
+ meminfo[MI_ANONPAGES],
+ meminfo[MI_MAPPED],
+ meminfo[MI_MEMFREE]);
printf(OPT_BATCH_MODE ? "%.*s\n" : "\033[H\033[J%.*s\n", scr_width, line_buf);
snprintf(line_buf, LINE_BUF_SIZE,
- " slab:%s buf:%s cache:%s dirty:%s write:%s",
- Z[SLAB], Z[BUF], Z[CACHE], Z[DIRTY], Z[MWRITE]);
+ " slab:%lu buf:%lu cache:%lu dirty:%lu write:%lu",
+ meminfo[MI_SLAB],
+ meminfo[MI_BUFFERS],
+ meminfo[MI_CACHED],
+ meminfo[MI_DIRTY],
+ meminfo[MI_WRITEBACK]);
printf("%.*s\n", scr_width, line_buf);
snprintf(line_buf, LINE_BUF_SIZE,
- "Swap total:%s free:%s", // TODO: % used?
- Z[SWAPTOTAL], Z[SWAPFREE]);
+ "Swap total:%lu free:%lu", // TODO: % used?
+ meminfo[MI_SWAPTOTAL],
+ meminfo[MI_SWAPFREE]);
printf("%.*s\n", scr_width, line_buf);
(*lines_rem_p) -= 3;
@@ -785,24 +823,30 @@ static void display_topmem_header(int scr_width, int *lines_rem_p)
static void ulltoa6_and_space(unsigned long long ul, char buf[6])
{
/* see http://en.wikipedia.org/wiki/Tera */
- smart_ulltoa5(ul, buf, " mgtpezy");
- buf[5] = ' ';
+ smart_ulltoa5(ul, buf, " mgtpezy")[0] = ' ';
}
static NOINLINE void display_topmem_process_list(int lines_rem, int scr_width)
{
#define HDR_STR " PID VSZ VSZRW RSS (SHR) DIRTY (SHR) STACK"
#define MIN_WIDTH sizeof(HDR_STR)
- const topmem_status_t *s = topmem;
+ const topmem_status_t *s = topmem + G_scroll_ofs;
+ char *cp, ch;
display_topmem_header(scr_width, &lines_rem);
+
strcpy(line_buf, HDR_STR " COMMAND");
- line_buf[11 + sort_field * 6] = "^_"[inverted];
+ /* Mark the ^FIELD^ we sort by */
+ cp = &line_buf[5 + sort_field * 6];
+ ch = "^_"[inverted];
+ cp[6] = ch;
+ do *cp++ = ch; while (*cp == ' ');
+
printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width, line_buf);
lines_rem--;
- if (lines_rem > ntop)
- lines_rem = ntop;
+ if (lines_rem > ntop - G_scroll_ofs)
+ lines_rem = ntop - G_scroll_ofs;
while (--lines_rem >= 0) {
/* PID VSZ VSZRW RSS (SHR) DIRTY (SHR) COMMAND */
ulltoa6_and_space(s->pid , &line_buf[0*6]);
@@ -856,26 +900,58 @@ enum {
#if ENABLE_FEATURE_USE_TERMIOS
static unsigned handle_input(unsigned scan_mask, unsigned interval)
{
- unsigned char c;
- struct pollfd pfd[1];
-
- pfd[0].fd = 0;
- pfd[0].events = POLLIN;
+ if (option_mask32 & OPT_EOF) {
+ /* EOF on stdin ("top </dev/null") */
+ sleep(interval);
+ return scan_mask;
+ }
while (1) {
- if (safe_poll(pfd, 1, interval * 1000) <= 0)
- return scan_mask;
- interval = 0;
+ int32_t c;
- if (safe_read(STDIN_FILENO, &c, 1) != 1) { /* error/EOF? */
+ c = read_key(STDIN_FILENO, G.kbd_input, interval * 1000);
+ if (c == -1 && errno != EAGAIN) {
+ /* error/EOF */
option_mask32 |= OPT_EOF;
- return scan_mask;
+ break;
}
+ interval = 0;
if (c == initial_settings.c_cc[VINTR])
return EXIT_MASK;
if (c == initial_settings.c_cc[VEOF])
return EXIT_MASK;
+
+ if (c == KEYCODE_UP) {
+ G_scroll_ofs--;
+ goto normalize_ofs;
+ }
+ if (c == KEYCODE_DOWN) {
+ G_scroll_ofs++;
+ goto normalize_ofs;
+ }
+ if (c == KEYCODE_HOME) {
+ G_scroll_ofs = 0;
+ break;
+ }
+ if (c == KEYCODE_END) {
+ G_scroll_ofs = ntop - G.lines / 2;
+ goto normalize_ofs;
+ }
+ if (c == KEYCODE_PAGEUP) {
+ G_scroll_ofs -= G.lines / 2;
+ goto normalize_ofs;
+ }
+ if (c == KEYCODE_PAGEDOWN) {
+ G_scroll_ofs += G.lines / 2;
+ normalize_ofs:
+ if (G_scroll_ofs >= ntop)
+ G_scroll_ofs = ntop - 1;
+ if (G_scroll_ofs < 0)
+ G_scroll_ofs = 0;
+ break;
+ }
+
c |= 0x20; /* lowercase */
if (c == 'q')
return EXIT_MASK;
@@ -896,7 +972,7 @@ static unsigned handle_input(unsigned scan_mask, unsigned interval)
}
# if ENABLE_FEATURE_SHOW_THREADS
if (c == 'h'
- IF_FEATURE_TOPMEM(&& scan_mask != TOPMEM_MASK)
+ IF_FEATURE_TOPMEM(&& scan_mask != TOPMEM_MASK)
) {
scan_mask ^= PSSCAN_TASKS;
continue;
@@ -1011,7 +1087,7 @@ int top_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int top_main(int argc UNUSED_PARAM, char **argv)
{
int iterations;
- unsigned lines, col;
+ unsigned col;
unsigned interval;
char *str_interval, *str_iterations;
unsigned scan_mask = TOP_MASK;
@@ -1062,10 +1138,13 @@ int top_main(int argc UNUSED_PARAM, char **argv)
sort_function[0] = mem_sort;
#endif
+ if (OPT_BATCH_MODE) {
+ option_mask32 |= OPT_EOF;
+ }
#if ENABLE_FEATURE_USE_TERMIOS
- tcgetattr(0, (void *) &initial_settings);
- memcpy(&new_settings, &initial_settings, sizeof(new_settings));
- if (!OPT_BATCH_MODE) {
+ else {
+ tcgetattr(0, (void *) &initial_settings);
+ memcpy(&new_settings, &initial_settings, sizeof(new_settings));
/* unbuffered input, turn off echo */
new_settings.c_lflag &= ~(ISIG | ICANON | ECHO | ECHONL);
tcsetattr_stdin_TCSANOW(&new_settings);
@@ -1081,15 +1160,15 @@ int top_main(int argc UNUSED_PARAM, char **argv)
procps_status_t *p = NULL;
if (OPT_BATCH_MODE) {
- lines = INT_MAX;
+ G.lines = INT_MAX;
col = LINE_BUF_SIZE - 2; /* +2 bytes for '\n', NUL */
} else {
- lines = 24; /* default */
+ G.lines = 24; /* default */
col = 79;
#if ENABLE_FEATURE_USE_TERMIOS
/* We output to stdout, we need size of stdout (not stdin)! */
- get_terminal_width_height(STDOUT_FILENO, &col, &lines);
- if (lines < 5 || col < 10) {
+ get_terminal_width_height(STDOUT_FILENO, &col, &G.lines);
+ if (G.lines < 5 || col < 10) {
sleep(interval);
continue;
}
@@ -1099,12 +1178,11 @@ int top_main(int argc UNUSED_PARAM, char **argv)
}
/* read process IDs & status for all the processes */
+ ntop = 0;
while ((p = procps_scan(p, scan_mask)) != NULL) {
int n;
-#if ENABLE_FEATURE_TOPMEM
- if (scan_mask != TOPMEM_MASK)
-#endif
- {
+
+ IF_FEATURE_TOPMEM(if (scan_mask != TOPMEM_MASK)) {
n = ntop;
top = xrealloc_vector(top, 6, ntop++);
top[n].pid = p->pid;
@@ -1144,7 +1222,7 @@ int top_main(int argc UNUSED_PARAM, char **argv)
break;
}
- if (scan_mask != TOPMEM_MASK) {
+ IF_FEATURE_TOPMEM(if (scan_mask != TOPMEM_MASK)) {
#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
if (!prev_hist_count) {
do_stats();
@@ -1158,30 +1236,22 @@ int top_main(int argc UNUSED_PARAM, char **argv)
#else
qsort(top, ntop, sizeof(top_status_t), (void*)(sort_function[0]));
#endif
+ display_process_list(G.lines, col);
}
#if ENABLE_FEATURE_TOPMEM
else { /* TOPMEM */
qsort(topmem, ntop, sizeof(topmem_status_t), (void*)topmem_sort);
+ display_topmem_process_list(G.lines, col);
}
#endif
- if (scan_mask != TOPMEM_MASK)
- display_process_list(lines, col);
-#if ENABLE_FEATURE_TOPMEM
- else
- display_topmem_process_list(lines, col);
-#endif
clearmems();
if (iterations >= 0 && !--iterations)
break;
#if !ENABLE_FEATURE_USE_TERMIOS
sleep(interval);
#else
- if (option_mask32 & OPT_EOF)
- /* EOF on stdin ("top </dev/null") */
- sleep(interval);
- else
- scan_mask = handle_input(scan_mask, interval);
-#endif /* FEATURE_USE_TERMIOS */
+ scan_mask = handle_input(scan_mask, interval);
+#endif
} /* end of "while (not Q)" */
bb_putchar('\n');
diff --git a/release/src/router/busybox/procps/uptime.c b/release/src/router/busybox/procps/uptime.c
index 778812a6f5..149bae6e59 100644
--- a/release/src/router/busybox/procps/uptime.c
+++ b/release/src/router/busybox/procps/uptime.c
@@ -81,10 +81,10 @@ int uptime_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
#if ENABLE_FEATURE_UPTIME_UTMP_SUPPORT
{
- struct utmp *ut;
+ struct utmpx *ut;
unsigned users = 0;
- while ((ut = getutent()) != NULL) {
- if ((ut->ut_type == USER_PROCESS) && (ut->ut_name[0] != '\0'))
+ while ((ut = getutxent()) != NULL) {
+ if ((ut->ut_type == USER_PROCESS) && (ut->ut_user[0] != '\0'))
users++;
}
printf(", %u users", users);
diff --git a/release/src/router/busybox/procps/watch.c b/release/src/router/busybox/procps/watch.c
index 36af1cca7c..97aa04767b 100644
--- a/release/src/router/busybox/procps/watch.c
+++ b/release/src/router/busybox/procps/watch.c
@@ -69,20 +69,22 @@ int watch_main(int argc UNUSED_PARAM, char **argv)
printf("\033[H""\033[J");
if (!(opt & 0x2)) { // no -t
const unsigned time_len = sizeof("1234-67-90 23:56:89");
- time_t t;
// STDERR_FILENO is procps3 compat:
// "watch ls 2>/dev/null" does not detect tty size
- get_terminal_width_height(STDERR_FILENO, &new_width, NULL);
+ new_width = get_terminal_width(STDERR_FILENO);
if (new_width != width) {
width = new_width;
free(header);
header = xasprintf("Every %us: %-*s", period, (int)width, cmd);
}
- time(&t);
- if (time_len < width)
- strftime(header + width - time_len, time_len,
- "%Y-%m-%d %H:%M:%S", localtime(&t));
+ if (time_len < width) {
+ strftime_YYYYMMDDHHMMSS(
+ header + width - time_len,
+ time_len,
+ /*time_t*:*/ NULL
+ );
+ }
// compat: empty line between header and cmd output
printf("%s\n\n", header);
diff --git a/release/src/router/busybox/qemu_multiarch_testing/README b/release/src/router/busybox/qemu_multiarch_testing/README
new file mode 100644
index 0000000000..ecb63f9ef6
--- /dev/null
+++ b/release/src/router/busybox/qemu_multiarch_testing/README
@@ -0,0 +1,63 @@
+How to test build using Aboriginal Linux system images.
+
+* Put a source tree into hdc.dir/.
+For example, this should work:
+git clone git://busybox.net/var/lib/git/busybox.git
+
+* Run ./make-hdc-img.sh: it will generate ext2 image file,
+hdc.img, from hdc.dir/* data. This requires root for loop mount.
+
+* Download and unpack, or build from source and unpack
+one or more system-image-ARCH directories into this directory
+(the one which contains this README).
+
+* Install qemu-system-ARCH. The arch names may differ from
+system-image-ARCH: for example, all ARM flavors (armv4l...armv6l)
+are served by the same qemu - qemu-system-arm. On my machine,
+I needed to install qemu-system-{arm,mips,x86,ppc,sparc,m68k,sh4}.
+
+* Run: ./parallel-build-hdc-img.sh system-image-DIR1 system-image-DIR2...
+(background it if you don't want to see "Waiting to finish" thing).
+This runs build in several qemu virtual machines in parallel.
+
+* Observe system-image-*.log file(s) with growing log of the build.
+
+There is no automated detection of errors for now: you need to examine
+logs yourself.
+
+Log files will also contain uuencoded (or if all else fails, od -tx1'ed)
+binary, if build was successful.
+
+To debug a build problem in one of the sandboxes, change keep_hdb
+to "keep_hdb=true" in parallel-build-hdc-img.sh
+- this preserves system-image-ARCH/hdb.img after the build,
+so you can go into system-image-ARCH and run
+"HDB=hdb.img ./dev-environment.sh" to debug the problem.
+
+You can also run "./parallel-build-hdc-img.sh -s system-image-ARCH"
+- single mode, output is to screen and serial input is from keyboard.
+
+If hdc.dir/bin/busybox-$ARCH exists, it will be used during build
+to supply additional tools (dir with all applets appended to $PATH).
+
+For me, the following system images worked:
+system-image-armv4l
+system-image-armv4tl
+system-image-armv5l
+ od is buggy on arm*:
+ # echo Hello-hello-hello-hello | od -b
+ 0000000 110 145 154 154 157 055 150 145 154 154 157 055 150 145 154 154
+ 0000000 157 055 150 145 154 154 157 012 <= WRONG OFFSET
+ 0000000 (can also be even more bogus like 17767153361)
+system-image-i686
+system-image-mips - od is buggy
+system-image-mipsel - od is buggy
+system-image-x86_64
+system-image-powerpc - qemu 1.2.2 didn't work, 2.4.0 worked; od is buggy
+system-image-sparc - qemu 1.2.2 didn't work, 2.4.0 worked; od is buggy
+
+And these did not:
+system-image-armv6l - hang on "Uncompressing Linux... done, booting the kernel"
+system-image-m68k - my qemu doesn't like "-M q800"
+system-image-mips64 - init dies "Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000a"
+system-image-sh4 - qemu segfaults early in kernel boot
diff --git a/release/src/router/busybox/qemu_multiarch_testing/extract_od_binary.sh b/release/src/router/busybox/qemu_multiarch_testing/extract_od_binary.sh
new file mode 100755
index 0000000000..1006e51532
--- /dev/null
+++ b/release/src/router/busybox/qemu_multiarch_testing/extract_od_binary.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# Converts textual result of "od -tx1 <FILE"
+# back into a binary FILE
+
+grep -a '^[0-7][0-7][0-7][0-7][0-7][0-7][0-7][0-7]* [0-9a-f][0-9a-f] [0-9a-f][0-9a-f] [0-9a-f][0-9a-f] [0-9a-f][0-9a-f]' | busybox hexdump -R
diff --git a/release/src/router/busybox/qemu_multiarch_testing/hdc.dir/build b/release/src/router/busybox/qemu_multiarch_testing/hdc.dir/build
new file mode 100755
index 0000000000..a9981864a9
--- /dev/null
+++ b/release/src/router/busybox/qemu_multiarch_testing/hdc.dir/build
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+umount /mnt # optional
+
+test -x "bin/busybox-$HOST" && {
+ echo "Found bin/busybox-$HOST, using it"
+ cp -a "bin/busybox-$HOST" bin/busybox
+ bin/busybox --install -s bin/
+ # Supply missing stuff (e.g. bzip2):
+ PATH="$PATH:$PWD/bin"
+ # Override known-buggy host binaries:
+ cp -af bin/od `which od`
+}
+
+(
+ #set -e -x
+ cd busybox
+
+ make defconfig
+ # Want static build
+ sed 's/^.*CONFIG_STATIC.*$/CONFIG_STATIC=y/' -i .config
+ bzip2 </dev/null >/dev/null || {
+ # Drats, newer Aboriginal Linux has no bzip2
+ sed 's/^.*CONFIG_FEATURE_COMPRESS_USAGE.*$/# CONFIG_FEATURE_COMPRESS_USAGE is not set/' -i .config
+ }
+ test x"`uname -m`" = x"mips" && {
+ # Without this, I get MIPS-I binary instead of MIPS32.
+ # No idea what's the difference, but my router wants MIPS32.
+ sed 's/^.*CONFIG_EXTRA_CFLAGS.*$/CONFIG_EXTRA_CFLAGS="-mips32"/' -i .config
+ }
+ # These won't build because of toolchain/libc breakage:
+ sed 's/^.*CONFIG_FEATURE_SYNC_FANCY.*$/# CONFIG_FEATURE_SYNC_FANCY is not set/' -i .config # no syncfs()
+ sed 's/^.*CONFIG_FEATURE_WTMP.*$/# CONFIG_FEATURE_WTMP is not set/' -i .config
+ sed 's/^.*CONFIG_FEATURE_UTMP.*$/# CONFIG_FEATURE_UTMP is not set/' -i .config
+ sed 's/^.*CONFIG_FEATURE_INETD_RPC.*$/# CONFIG_FEATURE_INETD_RPC is not set/' -i .config
+
+ make #V=1 || sh
+ size busybox
+ ./busybox || echo "Exit code: $?"
+ if uuencode TEST </dev/null >/dev/null && bzip2 </dev/null >/dev/null; then
+ bzip2 <busybox | uuencode busybox.bz2
+ else
+ od -v -tx1 <busybox
+ fi
+ #test "x$FTP_PORT" = x ||
+ # ftpput -P "$FTP_PORT" "$FTP_SERVER" strace
+) 2>&1 | tee build.log
+mount -o remount,ro /home
+sync
+sleep 1
diff --git a/release/src/router/busybox/qemu_multiarch_testing/hdc.dir/init b/release/src/router/busybox/qemu_multiarch_testing/hdc.dir/init
new file mode 100755
index 0000000000..692371db66
--- /dev/null
+++ b/release/src/router/busybox/qemu_multiarch_testing/hdc.dir/init
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# Emit a msg to let user know this place was reached
+echo "Copying to /home"
+# Had a case where cp SEGVs, let's have diagnostics for it
+cp -a /mnt /home || { echo "cp: $?"; exit 1; }
+cd /home/mnt || { echo "cd: $?"; exit 1; }
+exec ./build
+echo "Failed to exec ./build"
diff --git a/release/src/router/busybox/qemu_multiarch_testing/make-hdc-img.sh b/release/src/router/busybox/qemu_multiarch_testing/make-hdc-img.sh
new file mode 100755
index 0000000000..3c35f4eadb
--- /dev/null
+++ b/release/src/router/busybox/qemu_multiarch_testing/make-hdc-img.sh
@@ -0,0 +1,30 @@
+#!/bin/sh -ex
+
+mountpoint -q /
+[ ! -e hdc.img.dir ]
+
+cleanup()
+{
+ trap - EXIT
+ if mountpoint -q hdc.img.dir; then
+ umount -d hdc.img.dir
+ fi
+ mountpoint -q hdc.img.dir ||
+ rm -rf hdc.img.dir
+ exit $@
+}
+
+trap 'cleanup $?' EXIT
+trap 'cleanup 1' HUP PIPE INT QUIT TERM
+
+size=$(du -ks hdc.dir | sed -rn 's/^([0-9]+).*/\1/p')
+[ "$size" -gt 0 ]
+
+rm -f hdc.img
+dd if=/dev/zero of=hdc.img count=1 bs=1024 seek=$(($size*2))
+mkfs.ext3 -q -F -b 1024 -i 4096 hdc.img
+tune2fs -c 0 -i 0 hdc.img
+mkdir hdc.img.dir
+mount -o loop hdc.img hdc.img.dir
+cp -a hdc.dir/* hdc.img.dir/
+umount -d hdc.img.dir
diff --git a/release/src/router/busybox/qemu_multiarch_testing/parallel-build-hdc-img.sh b/release/src/router/busybox/qemu_multiarch_testing/parallel-build-hdc-img.sh
new file mode 100755
index 0000000000..9ee54ebb8b
--- /dev/null
+++ b/release/src/router/busybox/qemu_multiarch_testing/parallel-build-hdc-img.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+export HDBMEGS=100
+keep_hdb=false
+
+build_in_dir()
+{
+ cd "$1" || exit 1
+ rm -f hdb.img
+ nice -n10 time ./native-build.sh ../hdc.img
+ $keep_hdb || rm -f hdb.img
+ echo >&3 "Finished: $1"
+}
+
+test "$1" = "-s" && {
+ dir="$2"
+ # single mode: build one directory, show output
+ test -d "$dir" || exit 1
+ test -e "$dir/native-build.sh" || exit 1
+ build_in_dir "$dir"
+ exit $?
+}
+
+started=false
+for dir; do
+ test -d "$dir" || continue
+ test -e "$dir/native-build.sh" || continue
+ echo "Starting: $dir"
+ build_in_dir "$dir" 3>&1 </dev/null >"$dir.log" 2>&1 &
+ started=true
+done
+
+$started || {
+ echo "Give me system-image-ARCH directories on command line"
+ exit 1
+}
+
+echo "Waiting to finish"
+wait
+echo "Done, check the logs"
diff --git a/release/src/router/busybox/runit/Config.src b/release/src/router/busybox/runit/Config.src
index 9db9740022..8cde89680b 100644
--- a/release/src/router/busybox/runit/Config.src
+++ b/release/src/router/busybox/runit/Config.src
@@ -7,83 +7,4 @@ menu "Runit Utilities"
INSERT
-config RUNSV
- bool "runsv"
- default y
- help
- runsv starts and monitors a service and optionally an appendant log
- service.
-
-config RUNSVDIR
- bool "runsvdir"
- default y
- help
- runsvdir starts a runsv process for each subdirectory, or symlink to
- a directory, in the services directory dir, up to a limit of 1000
- subdirectories, and restarts a runsv process if it terminates.
-
-config FEATURE_RUNSVDIR_LOG
- bool "Enable scrolling argument log"
- depends on RUNSVDIR
- default n
- help
- Enable feature where second parameter of runsvdir holds last error
- message (viewable via top/ps). Otherwise (feature is off
- or no parameter), error messages go to stderr only.
-
-config SV
- bool "sv"
- default y
- help
- sv reports the current status and controls the state of services
- monitored by the runsv supervisor.
-
-config SV_DEFAULT_SERVICE_DIR
- string "Default directory for services"
- default "/var/service"
- depends on SV
- help
- Default directory for services.
- Defaults to "/var/service"
-
-config SVLOGD
- bool "svlogd"
- default y
- help
- svlogd continuously reads log data from its standard input, optionally
- filters log messages, and writes the data to one or more automatically
- rotated logs.
-
-config CHPST
- bool "chpst"
- default y
- help
- chpst changes the process state according to the given options, and
- execs specified program.
-
-config SETUIDGID
- bool "setuidgid"
- default y
- help
- Sets soft resource limits as specified by options
-
-config ENVUIDGID
- bool "envuidgid"
- default y
- help
- Sets $UID to account's uid and $GID to account's gid
-
-config ENVDIR
- bool "envdir"
- default y
- help
- Sets various environment variables as specified by files
- in the given directory
-
-config SOFTLIMIT
- bool "softlimit"
- default y
- help
- Sets soft resource limits as specified by options
-
endmenu
diff --git a/release/src/router/busybox/runit/Kbuild.src b/release/src/router/busybox/runit/Kbuild.src
index 0fce95507a..6b4fb74700 100644
--- a/release/src/router/busybox/runit/Kbuild.src
+++ b/release/src/router/busybox/runit/Kbuild.src
@@ -7,14 +7,3 @@
lib-y:=
INSERT
-
-lib-$(CONFIG_RUNSV) += runsv.o
-lib-$(CONFIG_RUNSVDIR) += runsvdir.o
-lib-$(CONFIG_SV) += sv.o
-lib-$(CONFIG_SVLOGD) += svlogd.o
-lib-$(CONFIG_CHPST) += chpst.o
-
-lib-$(CONFIG_ENVDIR) += chpst.o
-lib-$(CONFIG_ENVUIDGID) += chpst.o
-lib-$(CONFIG_SETUIDGID) += chpst.o
-lib-$(CONFIG_SOFTLIMIT) += chpst.o
diff --git a/release/src/router/busybox/runit/chpst.c b/release/src/router/busybox/runit/chpst.c
index ac296babf2..7fe5151db6 100644
--- a/release/src/router/busybox/runit/chpst.c
+++ b/release/src/router/busybox/runit/chpst.c
@@ -26,7 +26,50 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
-/* Dependencies on runit_lib.c removed */
+
+//config:config CHPST
+//config: bool "chpst"
+//config: default y
+//config: help
+//config: chpst changes the process state according to the given options, and
+//config: execs specified program.
+//config:
+//config:config SETUIDGID
+//config: bool "setuidgid"
+//config: default y
+//config: help
+//config: Sets soft resource limits as specified by options
+//config:
+//config:config ENVUIDGID
+//config: bool "envuidgid"
+//config: default y
+//config: help
+//config: Sets $UID to account's uid and $GID to account's gid
+//config:
+//config:config ENVDIR
+//config: bool "envdir"
+//config: default y
+//config: help
+//config: Sets various environment variables as specified by files
+//config: in the given directory
+//config:
+//config:config SOFTLIMIT
+//config: bool "softlimit"
+//config: default y
+//config: help
+//config: Sets soft resource limits as specified by options
+
+//applet:IF_CHPST(APPLET(chpst, BB_DIR_USR_BIN, BB_SUID_DROP))
+//applet:IF_ENVDIR(APPLET_ODDNAME(envdir, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, envdir))
+//applet:IF_ENVUIDGID(APPLET_ODDNAME(envuidgid, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, envuidgid))
+//applet:IF_SETUIDGID(APPLET_ODDNAME(setuidgid, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, setuidgid))
+//applet:IF_SOFTLIMIT(APPLET_ODDNAME(softlimit, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, softlimit))
+
+//kbuild:lib-$(CONFIG_CHPST) += chpst.o
+//kbuild:lib-$(CONFIG_ENVDIR) += chpst.o
+//kbuild:lib-$(CONFIG_ENVUIDGID) += chpst.o
+//kbuild:lib-$(CONFIG_SETUIDGID) += chpst.o
+//kbuild:lib-$(CONFIG_SOFTLIMIT) += chpst.o
//usage:#define chpst_trivial_usage
//usage: "[-vP012] [-u USER[:GRP]] [-U USER[:GRP]] [-e DIR]\n"
@@ -91,6 +134,7 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//usage: "\n a SIGXCPU after N seconds"
#include "libbb.h"
+#include <sys/resource.h> /* getrlimit */
/*
Five applets here: chpst, envdir, envuidgid, setuidgid, softlimit.
@@ -211,8 +255,7 @@ static NOINLINE void edir(const char *directory_name)
xsetenv(d->d_name, buf);
}
closedir(dir);
- if (fchdir(wdir) == -1)
- bb_perror_msg_and_die("fchdir");
+ xfchdir(wdir);
close(wdir);
}
@@ -235,7 +278,6 @@ int chpst_main(int argc UNUSED_PARAM, char **argv)
{
struct bb_uidgid_t ugid;
char *set_user = set_user; /* for compiler */
- char *env_user = env_user;
char *env_dir = env_dir;
char *root;
char *nicestr;
@@ -263,7 +305,7 @@ int chpst_main(int argc UNUSED_PARAM, char **argv)
IF_CHPST("/:n:vP012"),
&limita, &limitc, &limitd, &limitf, &limitl,
&limitm, &limito, &limitp, &limitr, &limits, &limitt,
- &set_user, &env_user, &env_dir
+ &set_user, &set_user, &env_dir
IF_CHPST(, &root, &nicestr));
argv += optind;
if (opt & OPT_m) { // -m means -asld
@@ -291,7 +333,7 @@ int chpst_main(int argc UNUSED_PARAM, char **argv)
// envuidgid?
if (ENABLE_ENVUIDGID && applet_name[0] == 'e' && applet_name[3] == 'u') {
- env_user = *argv++;
+ set_user = *argv++;
opt |= OPT_U;
}
diff --git a/release/src/router/busybox/runit/runsv.c b/release/src/router/busybox/runit/runsv.c
index ad8d84f74e..e0e31508a4 100644
--- a/release/src/router/busybox/runit/runsv.c
+++ b/release/src/router/busybox/runit/runsv.c
@@ -26,16 +26,26 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
-/* TODO: depends on runit_lib.c - review and reduce/eliminate */
+
+//config:config RUNSV
+//config: bool "runsv"
+//config: default y
+//config: help
+//config: runsv starts and monitors a service and optionally an appendant log
+//config: service.
+
+//applet:IF_RUNSV(APPLET(runsv, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_RUNSV) += runsv.o
//usage:#define runsv_trivial_usage
//usage: "DIR"
//usage:#define runsv_full_usage "\n\n"
//usage: "Start and monitor a service and optionally an appendant log service"
-#include <sys/poll.h>
#include <sys/file.h>
#include "libbb.h"
+#include "common_bufsiz.h"
#include "runit_lib.h"
#if ENABLE_MONOTONIC_SYSCALL
@@ -50,16 +60,11 @@ static void gettimeofday_ns(struct timespec *ts)
#else
static void gettimeofday_ns(struct timespec *ts)
{
- if (sizeof(struct timeval) == sizeof(struct timespec)
- && sizeof(((struct timeval*)ts)->tv_usec) == sizeof(ts->tv_nsec)
- ) {
- /* Cheat */
- gettimeofday((void*)ts, NULL);
- ts->tv_nsec *= 1000;
- } else {
- extern void BUG_need_to_implement_gettimeofday_ns(void);
- BUG_need_to_implement_gettimeofday_ns();
- }
+ BUILD_BUG_ON(sizeof(struct timeval) != sizeof(struct timespec));
+ BUILD_BUG_ON(sizeof(((struct timeval*)ts)->tv_usec) != sizeof(ts->tv_nsec));
+ /* Cheat */
+ gettimeofday((void*)ts, NULL);
+ ts->tv_nsec *= 1000;
}
#endif
@@ -101,7 +106,7 @@ struct globals {
char *dir;
struct svdir svd[2];
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define haslog (G.haslog )
#define sigterm (G.sigterm )
#define pidchanged (G.pidchanged )
@@ -110,12 +115,13 @@ struct globals {
#define dir (G.dir )
#define svd (G.svd )
#define INIT_G() do { \
+ setup_common_bufsiz(); \
pidchanged = 1; \
} while (0)
static void fatal2_cannot(const char *m1, const char *m2)
{
- bb_perror_msg_and_die("%s: fatal: cannot %s%s", dir, m1, m2);
+ bb_perror_msg_and_die("%s: fatal: can't %s%s", dir, m1, m2);
/* was exiting 111 */
}
static void fatal_cannot(const char *m)
@@ -125,7 +131,7 @@ static void fatal_cannot(const char *m)
}
static void fatal2x_cannot(const char *m1, const char *m2)
{
- bb_error_msg_and_die("%s: fatal: cannot %s%s", dir, m1, m2);
+ bb_error_msg_and_die("%s: fatal: can't %s%s", dir, m1, m2);
/* was exiting 111 */
}
static void warn_cannot(const char *m)
@@ -172,7 +178,7 @@ static void update_status(struct svdir *s)
}
close(fd);
if (rename_or_warn("supervise/pid.new",
- s->islog ? "log/supervise/pid" : "log/supervise/pid"+4))
+ s->islog ? "log/supervise/pid" : "log/supervise/pid"+4))
return;
pidchanged = 0;
}
diff --git a/release/src/router/busybox/runit/runsvdir.c b/release/src/router/busybox/runit/runsvdir.c
index 32526cf4ca..2b7927542a 100644
--- a/release/src/router/busybox/runit/runsvdir.c
+++ b/release/src/router/busybox/runit/runsvdir.c
@@ -26,7 +26,27 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
-/* TODO: depends on runit_lib.c - review and reduce/eliminate */
+
+//config:config RUNSVDIR
+//config: bool "runsvdir"
+//config: default y
+//config: help
+//config: runsvdir starts a runsv process for each subdirectory, or symlink to
+//config: a directory, in the services directory dir, up to a limit of 1000
+//config: subdirectories, and restarts a runsv process if it terminates.
+//config:
+//config:config FEATURE_RUNSVDIR_LOG
+//config: bool "Enable scrolling argument log"
+//config: depends on RUNSVDIR
+//config: default n
+//config: help
+//config: Enable feature where second parameter of runsvdir holds last error
+//config: message (viewable via top/ps). Otherwise (feature is off
+//config: or no parameter), error messages go to stderr only.
+
+//applet:IF_RUNSVDIR(APPLET(runsvdir, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_RUNSVDIR) += runsvdir.o
//usage:#define runsvdir_trivial_usage
//usage: "[-P] [-s SCRIPT] DIR"
@@ -35,9 +55,9 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//usage: "\n -P Put each runsv in a new session"
//usage: "\n -s SCRIPT Run SCRIPT <signo> after signal is processed"
-#include <sys/poll.h>
#include <sys/file.h>
#include "libbb.h"
+#include "common_bufsiz.h"
#include "runit_lib.h"
#define MAXSERVICES 1000
@@ -60,22 +80,20 @@ struct globals {
int svnum;
#if ENABLE_FEATURE_RUNSVDIR_LOG
char *rplog;
- int rploglen;
struct fd_pair logpipe;
struct pollfd pfd[1];
unsigned stamplog;
#endif
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define sv (G.sv )
#define svdir (G.svdir )
#define svnum (G.svnum )
#define rplog (G.rplog )
-#define rploglen (G.rploglen )
#define logpipe (G.logpipe )
#define pfd (G.pfd )
#define stamplog (G.stamplog )
-#define INIT_G() do { } while (0)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
static void fatal2_cannot(const char *m1, const char *m2)
{
@@ -220,15 +238,12 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
struct stat s;
dev_t last_dev = last_dev; /* for gcc */
ino_t last_ino = last_ino; /* for gcc */
- time_t last_mtime = 0;
- int wstat;
+ time_t last_mtime;
int curdir;
- pid_t pid;
- unsigned deadline;
- unsigned now;
unsigned stampcheck;
int i;
- int need_rescan = 1;
+ int need_rescan;
+ bool i_am_init;
char *opt_s_argv[3];
INIT_G();
@@ -239,18 +254,21 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
getopt32(argv, "Ps:", &opt_s_argv[0]);
argv += optind;
+ i_am_init = (getpid() == 1);
bb_signals(0
| (1 << SIGTERM)
| (1 << SIGHUP)
/* For busybox's init, SIGTERM == reboot,
- * SIGUSR1 == halt
- * SIGUSR2 == poweroff
- * so we need to intercept SIGUSRn too.
+ * SIGUSR1 == halt,
+ * SIGUSR2 == poweroff,
+ * Ctlr-ALt-Del sends SIGINT to init,
+ * so we need to intercept SIGUSRn and SIGINT too.
* Note that we do not implement actual reboot
* (killall(TERM) + umount, etc), we just pause
* respawing and avoid exiting (-> making kernel oops).
- * The user is responsible for the rest. */
- | (getpid() == 1 ? ((1 << SIGUSR1) | (1 << SIGUSR2)) : 0)
+ * The user is responsible for the rest.
+ */
+ | (i_am_init ? ((1 << SIGUSR1) | (1 << SIGUSR2) | (1 << SIGINT)) : 0)
, record_signo);
svdir = *argv++;
@@ -258,8 +276,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
/* setup log */
if (*argv) {
rplog = *argv;
- rploglen = strlen(rplog);
- if (rploglen < 7) {
+ if (strlen(rplog) < 7) {
warnx("log must have at least seven characters");
} else if (piped_pair(logpipe)) {
warnx("can't create pipe for log");
@@ -288,11 +305,16 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
close_on_exec_on(curdir);
stampcheck = monotonic_sec();
+ need_rescan = 1;
+ last_mtime = 0;
for (;;) {
+ unsigned now;
+ unsigned sig;
+
/* collect children */
for (;;) {
- pid = wait_any_nohang(&wstat);
+ pid_t pid = wait_any_nohang(NULL);
if (pid <= 0)
break;
for (i = 0; i < svnum; i++) {
@@ -346,15 +368,15 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
}
pfd[0].revents = 0;
#endif
- deadline = (need_rescan ? 1 : 5);
- sig_block(SIGCHLD);
+ {
+ unsigned deadline = (need_rescan ? 1 : 5);
#if ENABLE_FEATURE_RUNSVDIR_LOG
- if (rplog)
- poll(pfd, 1, deadline*1000);
- else
+ if (rplog)
+ poll(pfd, 1, deadline*1000);
+ else
#endif
- sleep(deadline);
- sig_unblock(SIGCHLD);
+ sleep(deadline);
+ }
#if ENABLE_FEATURE_RUNSVDIR_LOG
if (pfd[0].revents & POLLIN) {
@@ -362,21 +384,25 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
while (read(logpipe.rd, &ch, 1) > 0) {
if (ch < ' ')
ch = ' ';
- for (i = 6; i < rploglen; i++)
+ for (i = 6; rplog[i] != '\0'; i++)
rplog[i-1] = rplog[i];
- rplog[rploglen-1] = ch;
+ rplog[i-1] = ch;
}
}
#endif
- if (!bb_got_signal)
+ sig = bb_got_signal;
+ if (!sig)
continue;
+ bb_got_signal = 0;
/* -s SCRIPT: useful if we are init.
* In this case typically script never returns,
* it halts/powers off/reboots the system. */
if (opt_s_argv[0]) {
+ pid_t pid;
+
/* Single parameter: signal# */
- opt_s_argv[1] = utoa(bb_got_signal);
+ opt_s_argv[1] = utoa(sig);
pid = spawn(opt_s_argv);
if (pid > 0) {
/* Remembering to wait for _any_ children,
@@ -386,17 +412,16 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
}
}
- if (bb_got_signal == SIGHUP) {
+ if (sig == SIGHUP) {
for (i = 0; i < svnum; i++)
if (sv[i].pid)
kill(sv[i].pid, SIGTERM);
}
/* SIGHUP or SIGTERM (or SIGUSRn if we are init) */
/* Exit unless we are init */
- if (getpid() != 1)
- return (SIGHUP == bb_got_signal) ? 111 : EXIT_SUCCESS;
+ if (!i_am_init)
+ return (SIGHUP == sig) ? 111 : EXIT_SUCCESS;
/* init continues to monitor services forever */
- bb_got_signal = 0;
} /* for (;;) */
}
diff --git a/release/src/router/busybox/runit/sv.c b/release/src/router/busybox/runit/sv.c
index 5b01c875c1..2a256a6b40 100644
--- a/release/src/router/busybox/runit/sv.c
+++ b/release/src/router/busybox/runit/sv.c
@@ -151,7 +151,25 @@ Exit Codes
*/
/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
-/* TODO: depends on runit_lib.c - review and reduce/eliminate */
+
+//config:config SV
+//config: bool "sv"
+//config: default y
+//config: help
+//config: sv reports the current status and controls the state of services
+//config: monitored by the runsv supervisor.
+//config:
+//config:config SV_DEFAULT_SERVICE_DIR
+//config: string "Default directory for services"
+//config: default "/var/service"
+//config: depends on SV
+//config: help
+//config: Default directory for services.
+//config: Defaults to "/var/service"
+
+//applet:IF_SV(APPLET(sv, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_SV) += sv.o
//usage:#define sv_trivial_usage
//usage: "[-v] [-w SEC] CMD SERVICE_DIR..."
@@ -169,9 +187,9 @@ Exit Codes
//usage: "pause, cont, hup, alarm, interrupt, quit, 1, 2, term, kill: send\n"
//usage: "STOP, CONT, HUP, ALRM, INT, QUIT, USR1, USR2, TERM, KILL signal to service"
-#include <sys/poll.h>
#include <sys/file.h>
#include "libbb.h"
+#include "common_bufsiz.h"
#include "runit_lib.h"
struct globals {
@@ -182,14 +200,14 @@ struct globals {
uint64_t tstart, tnow;
svstatus_t svstatus;
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define acts (G.acts )
#define service (G.service )
#define rc (G.rc )
#define tstart (G.tstart )
#define tnow (G.tnow )
#define svstatus (G.svstatus )
-#define INIT_G() do { } while (0)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
#define str_equal(s,t) (!strcmp((s), (t)))
diff --git a/release/src/router/busybox/runit/svlogd.c b/release/src/router/busybox/runit/svlogd.c
index b0ba21bb63..7cae81cb2c 100644
--- a/release/src/router/busybox/runit/svlogd.c
+++ b/release/src/router/busybox/runit/svlogd.c
@@ -26,7 +26,6 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
-/* TODO: depends on runit_lib.c - review and reduce/eliminate */
/*
Config files
@@ -125,6 +124,18 @@ log message, you can use a pattern like this instead
-*: *: pid *
*/
+//config:config SVLOGD
+//config: bool "svlogd"
+//config: default y
+//config: help
+//config: svlogd continuously reads log data from its standard input, optionally
+//config: filters log messages, and writes the data to one or more automatically
+//config: rotated logs.
+
+//applet:IF_SVLOGD(APPLET(svlogd, BB_DIR_USR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_SVLOGD) += svlogd.o
+
//usage:#define svlogd_trivial_usage
//usage: "[-ttv] [-r C] [-R CHARS] [-l MATCHLEN] [-b BUFLEN] DIR..."
//usage:#define svlogd_full_usage "\n\n"
@@ -142,9 +153,9 @@ log message, you can use a pattern like this instead
//usage: "\n""+,-PATTERN - (de)select line for logging"
//usage: "\n""E,ePATTERN - (de)select line for stderr"
-#include <sys/poll.h>
#include <sys/file.h>
#include "libbb.h"
+#include "common_bufsiz.h"
#include "runit_lib.h"
#define LESS(a,b) ((int)((unsigned)(b) - (unsigned)(a)) > 0)
@@ -223,7 +234,9 @@ struct globals {
#define blocked_sigset (G.blocked_sigset)
#define fl_flag_0 (G.fl_flag_0 )
#define dirn (G.dirn )
+#define line bb_common_bufsiz1
#define INIT_G() do { \
+ setup_common_bufsiz(); \
SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
linemax = 1000; \
/*buflen = 1024;*/ \
@@ -231,8 +244,6 @@ struct globals {
replace = ""; \
} while (0)
-#define line bb_common_bufsiz1
-
#define FATAL "fatal: "
#define WARNING "warning: "
@@ -601,12 +612,12 @@ static int buffer_pwrite(int n, char *s, unsigned len)
while (fchdir(ld->fddir) == -1)
pause2cannot("change directory, want remove old logfile",
- ld->name);
+ ld->name);
oldest[0] = 'A';
oldest[1] = oldest[27] = '\0';
while (!(d = opendir(".")))
pause2cannot("open directory, want remove old logfile",
- ld->name);
+ ld->name);
errno = 0;
while ((f = readdir(d)))
if ((f->d_name[0] == '@') && (strlen(f->d_name) == 27)) {
@@ -745,11 +756,6 @@ static NOINLINE unsigned logdir_open(struct logdir *ld, const char *fn)
ld->inst = new;
break;
case 's': {
- static const struct suffix_mult km_suffixes[] = {
- { "k", 1024 },
- { "m", 1024*1024 },
- { "", 0 }
- };
ld->sizemax = xatou_sfx(&s[1], km_suffixes);
break;
}
@@ -1040,9 +1046,9 @@ int svlogd_main(int argc, char **argv)
}
if (opt & 2) if (!repl) repl = '_'; // -R
if (opt & 4) { // -l
- linemax = xatou_range(l, 0, BUFSIZ-26);
+ linemax = xatou_range(l, 0, COMMON_BUFSIZE-26);
if (linemax == 0)
- linemax = BUFSIZ-26;
+ linemax = COMMON_BUFSIZE-26;
if (linemax < 256)
linemax = 256;
}
diff --git a/release/src/router/busybox/scripts/Makefile.build b/release/src/router/busybox/scripts/Makefile.build
index 5685b5bcc5..5eac45f91f 100644
--- a/release/src/router/busybox/scripts/Makefile.build
+++ b/release/src/router/busybox/scripts/Makefile.build
@@ -255,8 +255,9 @@ $(sort $(subdir-obj-y)): $(subdir-ym) ;
ifdef builtin-target
quiet_cmd_link_o_target = LD $@
# If the list of objects to link is empty, just create an empty built-in.o
+# -nostdlib is added to make "make LD=gcc ..." work (some people use that)
cmd_link_o_target = $(if $(strip $(obj-y)),\
- $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^),\
+ $(LD) -nostdlib $(ld_flags) -r -o $@ $(filter $(obj-y), $^),\
rm -f $@; $(AR) rcs $@)
$(builtin-target): $(obj-y) FORCE
diff --git a/release/src/router/busybox/scripts/basic/docproc.c b/release/src/router/busybox/scripts/basic/docproc.c
index b125698321..720098a23d 100644
--- a/release/src/router/busybox/scripts/basic/docproc.c
+++ b/release/src/router/busybox/scripts/basic/docproc.c
@@ -39,7 +39,7 @@
#include <limits.h>
#include <sys/types.h>
#include <sys/wait.h>
-#include <alloca.h>
+//bbox disabled: #include <alloca.h>
/* exitstatus is used to keep track of any failing calls to kernel-doc,
* but execution continues. */
@@ -264,7 +264,7 @@ void singfunc(char * filename, char * line)
vec[idx++] = KERNELDOC;
vec[idx++] = DOCBOOK;
- /* Split line up in individual parameters preceeded by FUNCTION */
+ /* Split line up in individual parameters preceded by FUNCTION */
for (i=0; line[i]; i++) {
if (isspace(line[i])) {
line[i] = '\0';
diff --git a/release/src/router/busybox/scripts/basic/fixdep.c b/release/src/router/busybox/scripts/basic/fixdep.c
index 165a8c39dc..19f82df093 100644
--- a/release/src/router/busybox/scripts/basic/fixdep.c
+++ b/release/src/router/busybox/scripts/basic/fixdep.c
@@ -113,7 +113,7 @@
#include <limits.h>
#include <ctype.h>
#include <arpa/inet.h>
-#include <alloca.h>
+//bbox disabled: #include <alloca.h>
/* bbox: not needed
#define INT_CONF ntohl(0x434f4e46)
diff --git a/release/src/router/busybox/scripts/bloat-o-meter b/release/src/router/busybox/scripts/bloat-o-meter
index 6db2a5e58c..cb861b8e92 100755
--- a/release/src/router/busybox/scripts/bloat-o-meter
+++ b/release/src/router/busybox/scripts/bloat-o-meter
@@ -7,11 +7,14 @@
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
-import sys, os#, re
+import sys, os
def usage():
- sys.stderr.write("usage: %s [-t] file1 file2\n" % sys.argv[0])
- sys.exit(-1)
+ sys.stderr.write("usage: %s [-t] file1 file2 [-- <readelf options>]\n"
+ % sys.argv[0])
+ sys.stderr.write("\t-t\tShow time spent on parsing/processing\n")
+ sys.stderr.write("\t--\tPass additional parameters to readelf\n")
+ sys.exit(1)
f1, f2 = (None, None)
flag_timing, dashes = (False, False)
@@ -31,6 +34,8 @@ for f in sys.argv[1:]:
f1 = f
elif f2 is None:
f2 = f
+ else:
+ usage()
if flag_timing:
import time
if f1 is None or f2 is None:
diff --git a/release/src/router/busybox/scripts/gen_build_files.sh b/release/src/router/busybox/scripts/gen_build_files.sh
index 0989b2fe5e..ebee17c641 100755
--- a/release/src/router/busybox/scripts/gen_build_files.sh
+++ b/release/src/router/busybox/scripts/gen_build_files.sh
@@ -31,7 +31,12 @@ generate()
# copy stdin to stdout
cat
# print everything after INSERT line
- sed -n '/^INSERT$/ { :l; n; p; bl }' "${src}"
+ sed -n '/^INSERT$/ {
+ :l
+ n
+ p
+ bl
+ }' "${src}"
} >"${dst}.tmp"
if ! cmp -s "${dst}" "${dst}.tmp"; then
gen "${dst}"
@@ -52,7 +57,12 @@ sed -n 's@^//applet:@@p' "$srctree"/*/*.c "$srctree"/*/*/*.c \
# We add line continuation backslash after each line,
# and insert empty line before each line which doesn't start
# with space or tab
-sed -n -e 's@^//usage:\([ \t].*\)$@\1 \\@p' -e 's@^//usage:\([^ \t].*\)$@\n\1 \\@p' \
+TAB="$(printf '\tX')"
+TAB="${TAB%X}"
+LF="$(printf '\nX')"
+LF="${LF%X}"
+sed -n -e 's@^//usage:\([ '"$TAB"'].*\)$@\1 \\@p' \
+ -e 's@^//usage:\([^ '"$TAB"'].*\)$@\'"$LF"'\1 \\@p' \
"$srctree"/*/*.c "$srctree"/*/*/*.c \
| generate \
"$srctree/include/usage.src.h" \
@@ -61,7 +71,7 @@ sed -n -e 's@^//usage:\([ \t].*\)$@\1 \\@p' -e 's@^//usage:\([^ \t].*\)$@\n\1 \\
# (Re)generate */Kbuild and */Config.in
# We skip .dotdirs - makes git/svn/etc users happier
-{ cd -- "$srctree" && find . -type d -not '(' -name '.?*' -prune ')'; } \
+{ cd -- "$srctree" && find . -type d ! '(' -name '.?*' -prune ')'; } \
| while read -r d; do
d="${d#./}"
diff --git a/release/src/router/busybox/scripts/generate_BUFSIZ.sh b/release/src/router/busybox/scripts/generate_BUFSIZ.sh
new file mode 100755
index 0000000000..844261906c
--- /dev/null
+++ b/release/src/router/busybox/scripts/generate_BUFSIZ.sh
@@ -0,0 +1,181 @@
+#!/bin/sh
+# Called from top-level directory a-la
+#
+# scripts/generate_BUFSIZ.sh include/common_bufsiz.h
+
+. ./.config || exit 1
+
+debug=false
+#debug=true
+
+postcompile=false
+test x"$1" = x"--post" && { postcompile=true; shift; }
+
+common_bufsiz_h=$1
+
+test x"$NM" = x"" && NM="${CONFIG_CROSS_COMPILER_PREFIX}nm"
+test x"$CC" = x"" && CC="${CONFIG_CROSS_COMPILER_PREFIX}gcc"
+
+exitcmd="exit 0"
+
+regenerate() {
+ cat >"$1.$$"
+ test -f "$1" && diff "$1.$$" "$1" >/dev/null && rm "$1.$$" && return
+ mv "$1.$$" "$1"
+}
+
+generate_std_and_exit() {
+ $debug && echo "Configuring: bb_common_bufsiz1[] in bss"
+ {
+ echo "enum { COMMON_BUFSIZE = 1024 };"
+ echo "extern char bb_common_bufsiz1[];"
+ echo "#define setup_common_bufsiz() ((void)0)"
+ } | regenerate "$common_bufsiz_h"
+ echo "std" >"$common_bufsiz_h.method"
+ $exitcmd
+}
+
+generate_big_and_exit() {
+ $debug && echo "Configuring: bb_common_bufsiz1[] in _end[], COMMON_BUFSIZE = $1"
+ {
+ echo "enum { COMMON_BUFSIZE = $1 };"
+ echo "extern char _end[]; /* linker-provided label */"
+ echo "#define bb_common_bufsiz1 _end"
+ echo "#define setup_common_bufsiz() ((void)0)"
+ } | regenerate "$common_bufsiz_h"
+ echo "$2" >"$common_bufsiz_h.method"
+ $exitcmd
+}
+
+generate_1k_and_exit() {
+ generate_big_and_exit 1024 "1k"
+}
+
+
+generate_malloc_and_exit() {
+ $debug && echo "Configuring: bb_common_bufsiz1[] is malloced"
+ {
+ echo "enum { COMMON_BUFSIZE = 1024 };"
+ echo "extern char *const bb_common_bufsiz1;"
+ echo "void setup_common_bufsiz(void);"
+ } | regenerate "$common_bufsiz_h"
+ echo "malloc" >"$common_bufsiz_h.method"
+ $exitcmd
+}
+
+round_down_COMMON_BUFSIZE() {
+ COMMON_BUFSIZE=$(( ($1-32) & 0xfffffe0 ))
+ COMMON_BUFSIZE=$(( COMMON_BUFSIZE < 1024 ? 1024 : COMMON_BUFSIZE ))
+}
+
+# User does not want any funky stuff?
+test x"$CONFIG_FEATURE_USE_BSS_TAIL" = x"y" || generate_std_and_exit
+
+# The script is run two times: before compilation, when it needs to
+# (re)generate $common_bufsiz_h, and directly after successful build,
+# when it needs to assess whether the build is ok to use at all (not buggy),
+# and (re)generate $common_bufsiz_h for a future build.
+
+if $postcompile; then
+ # Postcompile needs to create/delete OK/FAIL files
+
+ test -f busybox_unstripped || exit 1
+ test -f "$common_bufsiz_h.method" || exit 1
+
+ # How the build was done?
+ method=`cat -- "$common_bufsiz_h.method"`
+
+ # Get _end address
+ END=`$NM busybox_unstripped | grep ' . _end$'| cut -d' ' -f1`
+ test x"$END" = x"" && generate_std_and_exit
+ $debug && echo "END:0x$END $((0x$END))"
+ END=$((0x$END))
+
+ # Get PAGE_SIZE
+ {
+ echo "#include <sys/user.h>"
+ echo "#if defined(PAGE_SIZE) && PAGE_SIZE > 0"
+ echo "char page_size[PAGE_SIZE];"
+ echo "#endif"
+ } >page_size_$$.c
+ $CC -c "page_size_$$.c" || exit 1
+ PAGE_SIZE=`$NM --size-sort "page_size_$$.o" | cut -d' ' -f1`
+ rm "page_size_$$.c" "page_size_$$.o"
+ test x"$PAGE_SIZE" = x"" && exit 1
+ $debug && echo "PAGE_SIZE:0x$PAGE_SIZE $((0x$PAGE_SIZE))"
+ PAGE_SIZE=$((0x$PAGE_SIZE))
+ test $PAGE_SIZE -lt 512 && exit 1
+
+ # How much space between _end[] and next page?
+ PAGE_MASK=$((PAGE_SIZE-1))
+ TAIL_SIZE=$(( (-END) & PAGE_MASK ))
+ $debug && echo "TAIL_SIZE:$TAIL_SIZE bytes"
+
+ if test x"$method" = x"1k" || test x"$method" = x"big"; then
+ if test $TAIL_SIZE -lt 1024; then
+ # _end[] has no enough space for bb_common_bufsiz1[]
+ echo "Warning! Space in _end[] is too small ($TAIL_SIZE bytes)!"
+ echo "Rerun make to build a binary which doesn't use it!"
+ rm -- "$common_bufsiz_h.1k.OK" 2>/dev/null
+ { md5sum <.config | cut -d' ' -f1; stat -c "%Y" .config; } >"$common_bufsiz_h.1k.FAIL"
+ rm busybox_unstripped busybox 2>/dev/null
+# Note: here we can do either a "malloc" or "std" build.
+# "malloc" gives a bit bigger code:
+# text bss filename
+# 804355 5385 busybox.std
+# 804618 4361 busybox.malloc
+# but may have a smaller .bss (not guaranteed!). Use "pmap -x" to verify.
+ exitcmd="exit 1"
+ generate_malloc_and_exit
+ else
+ PREV_SIZE=1024
+ test x"$method" = x"big" && PREV_SIZE=`cat -- "$common_bufsiz_h.1k.OK"`
+ round_down_COMMON_BUFSIZE $PREV_SIZE
+ PREV_BUFSIZE=$COMMON_BUFSIZE
+
+ rm -- "$common_bufsiz_h.1k.FAIL" 2>/dev/null
+ echo $TAIL_SIZE >"$common_bufsiz_h.1k.OK"
+ round_down_COMMON_BUFSIZE $TAIL_SIZE
+ # emit message only if COMMON_BUFSIZE is indeed larger
+ test $COMMON_BUFSIZE -gt $PREV_BUFSIZE \
+ && echo "Rerun make to use larger COMMON_BUFSIZE ($COMMON_BUFSIZE)"
+#TODO: test $PREV_BUFSIZE -lt $TAIL_SIZE && PANIC!!!
+#Code size with COMMON_BUFSIZE > 1024 may be bigger than code with COMMON_BUFSIZE = 1024!
+#(currently we just hope "-32 and round down to 32" saves us)
+
+ test $COMMON_BUFSIZE = 1024 && generate_1k_and_exit
+ generate_big_and_exit $COMMON_BUFSIZE "big"
+ fi
+ fi
+fi
+
+# Based on past success/fail of 1k build, decide next build type
+
+if test -f "$common_bufsiz_h.1k.OK"; then
+ # Previous build succeeded fitting 1k into _end[].
+ # Try bigger COMMON_BUFSIZE if possible.
+ TAIL_SIZE=`cat -- "$common_bufsiz_h.1k.OK"`
+ round_down_COMMON_BUFSIZE $TAIL_SIZE
+ test $COMMON_BUFSIZE = 1024 && generate_1k_and_exit
+ generate_big_and_exit $COMMON_BUFSIZE "big"
+fi
+
+if test -f "$common_bufsiz_h.1k.FAIL"; then
+ # Previous build FAILED to fit 1k into _end[].
+ # Was it with same .config?
+ oldcfg=`cat -- "$common_bufsiz_h.1k.FAIL"`
+ curcfg=`md5sum <.config | cut -d' ' -f1; stat -c "%Y" .config`
+ # If yes, then build a "malloced" version
+ if test x"$oldcfg" = x"$curcfg"; then
+ echo "Will not try 1k build, it failed before. Touch .config to override"
+# Note: here we can do either a "malloc" or "std" build.
+ generate_malloc_and_exit
+ fi
+ # else: try 1k version
+ echo "New .config, will try 1k build"
+ rm -- "$common_bufsiz_h.1k.FAIL"
+ generate_1k_and_exit
+fi
+
+# There was no 1k build yet. Try it.
+generate_1k_and_exit
diff --git a/release/src/router/busybox/scripts/kconfig/Makefile b/release/src/router/busybox/scripts/kconfig/Makefile
index 1651390a68..38bae809a8 100644
--- a/release/src/router/busybox/scripts/kconfig/Makefile
+++ b/release/src/router/busybox/scripts/kconfig/Makefile
@@ -150,7 +150,7 @@ HOSTCFLAGS_zconf.tab.o := -I$(src)
HOSTLOADLIBES_qconf = $(KC_QT_LIBS) -ldl
HOSTCXXFLAGS_qconf.o = $(KC_QT_CFLAGS) -D LKC_DIRECT_LINK
-HOSTLOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0`
+HOSTLOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0` -ldl
HOSTCFLAGS_gconf.o = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \
-D LKC_DIRECT_LINK
diff --git a/release/src/router/busybox/scripts/kconfig/confdata.c b/release/src/router/busybox/scripts/kconfig/confdata.c
index bd2d70e19e..8f4ecbd337 100644
--- a/release/src/router/busybox/scripts/kconfig/confdata.c
+++ b/release/src/router/busybox/scripts/kconfig/confdata.c
@@ -124,8 +124,7 @@ int conf_read_simple(const char *name)
case S_INT:
case S_HEX:
case S_STRING:
- if (sym->user.val)
- free(sym->user.val);
+ free(sym->user.val);
default:
sym->user.val = NULL;
sym->user.tri = no;
@@ -474,7 +473,11 @@ int conf_write(const char *name)
fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
/* bbox */
fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
- fprintf(out_h, "#define IF_%s(...) __VA_ARGS__\n", sym->name);
+ fprintf(out_h, "#ifdef MAKE_SUID\n");
+ fprintf(out_h, "# define IF_%s(...) __VA_ARGS__ \"CONFIG_%s\"\n", sym->name, sym->name);
+ fprintf(out_h, "#else\n");
+ fprintf(out_h, "# define IF_%s(...) __VA_ARGS__\n", sym->name);
+ fprintf(out_h, "#endif\n");
fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name);
}
break;
@@ -506,7 +509,11 @@ int conf_write(const char *name)
fputs("\"\n", out_h);
/* bbox */
fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
- fprintf(out_h, "#define IF_%s(...) __VA_ARGS__\n", sym->name);
+ fprintf(out_h, "#ifdef MAKE_SUID\n");
+ fprintf(out_h, "# define IF_%s(...) __VA_ARGS__ \"CONFIG_%s\"\n", sym->name, sym->name);
+ fprintf(out_h, "#else\n");
+ fprintf(out_h, "# define IF_%s(...) __VA_ARGS__\n", sym->name);
+ fprintf(out_h, "#endif\n");
fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name);
}
break;
@@ -518,7 +525,11 @@ int conf_write(const char *name)
fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
/* bbox */
fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
- fprintf(out_h, "#define IF_%s(...) __VA_ARGS__\n", sym->name);
+ fprintf(out_h, "#ifdef MAKE_SUID\n");
+ fprintf(out_h, "# define IF_%s(...) __VA_ARGS__ \"CONFIG_%s\"\n", sym->name, sym->name);
+ fprintf(out_h, "#else\n");
+ fprintf(out_h, "# define IF_%s(...) __VA_ARGS__\n", sym->name);
+ fprintf(out_h, "#endif\n");
fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name);
}
break;
@@ -532,7 +543,11 @@ int conf_write(const char *name)
fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
/* bbox */
fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
- fprintf(out_h, "#define IF_%s(...) __VA_ARGS__\n", sym->name);
+ fprintf(out_h, "#ifdef MAKE_SUID\n");
+ fprintf(out_h, "# define IF_%s(...) __VA_ARGS__ \"CONFIG_%s\"\n", sym->name, sym->name);
+ fprintf(out_h, "#else\n");
+ fprintf(out_h, "# define IF_%s(...) __VA_ARGS__\n", sym->name);
+ fprintf(out_h, "#endif\n");
fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name);
}
break;
diff --git a/release/src/router/busybox/scripts/kconfig/lxdialog/check-lxdialog.sh b/release/src/router/busybox/scripts/kconfig/lxdialog/check-lxdialog.sh
index d34dfd46d9..5075ebf2d3 100644..100755
--- a/release/src/router/busybox/scripts/kconfig/lxdialog/check-lxdialog.sh
+++ b/release/src/router/busybox/scripts/kconfig/lxdialog/check-lxdialog.sh
@@ -4,7 +4,9 @@
# What library to link
ldflags()
{
- for ext in so a dylib ; do
+ pkg-config --libs ncursesw 2>/dev/null && exit
+ pkg-config --libs ncurses 2>/dev/null && exit
+ for ext in so a dll.a dylib ; do
for lib in ncursesw ncurses curses ; do
$cc -print-file-name=lib${lib}.${ext} | grep -q /
if [ $? -eq 0 ]; then
@@ -19,14 +21,17 @@ ldflags()
# Where is ncurses.h?
ccflags()
{
- if [ -f /usr/include/ncursesw/ncurses.h ]; then
- echo '-I/usr/include/ncursesw -DCURSES_LOC="<ncurses.h>"'
+ if pkg-config --cflags ncursesw 2>/dev/null; then
+ echo '-DCURSES_LOC="<ncurses.h>" -DNCURSES_WIDECHAR=1'
+ elif pkg-config --cflags ncurses 2>/dev/null; then
+ echo '-DCURSES_LOC="<ncurses.h>"'
elif [ -f /usr/include/ncursesw/curses.h ]; then
- echo '-I/usr/include/ncursesw -DCURSES_LOC="<ncursesw/curses.h>"'
+ echo '-I/usr/include/ncursesw -DCURSES_LOC="<curses.h>"'
+ echo ' -DNCURSES_WIDECHAR=1'
elif [ -f /usr/include/ncurses/ncurses.h ]; then
echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"'
elif [ -f /usr/include/ncurses/curses.h ]; then
- echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"'
+ echo '-I/usr/include/ncurses -DCURSES_LOC="<curses.h>"'
elif [ -f /usr/include/ncurses.h ]; then
echo '-DCURSES_LOC="<ncurses.h>"'
else
@@ -40,7 +45,7 @@ trap "rm -f $tmp" 0 1 2 3 15
# Check if we can link to ncurses
check() {
- $cc -xc - -o $tmp 2>/dev/null <<'EOF'
+ $cc -x c - -o $tmp 2>/dev/null <<'EOF'
#include CURSES_LOC
main() {}
EOF
diff --git a/release/src/router/busybox/scripts/kconfig/mconf.c b/release/src/router/busybox/scripts/kconfig/mconf.c
index d3f69f8f5a..006d037088 100644
--- a/release/src/router/busybox/scripts/kconfig/mconf.c
+++ b/release/src/router/busybox/scripts/kconfig/mconf.c
@@ -9,6 +9,8 @@
*/
#define _XOPEN_SOURCE 700
+/* On Darwin, this may be needed to get SIGWINCH: */
+#define _DARWIN_C_SOURCE 1
#include <sys/ioctl.h>
#include <sys/wait.h>
@@ -443,6 +445,7 @@ static struct gstr get_relations_str(struct symbol **sym_arr)
pid_t pid;
+#ifdef SIGWINCH
static void winch_handler(int sig)
{
if (!do_resize) {
@@ -450,11 +453,11 @@ static void winch_handler(int sig)
do_resize = 1;
}
}
+#endif
static int exec_conf(void)
{
int pipefd[2], stat, size;
- struct sigaction sa;
sigset_t sset, osset;
sigemptyset(&sset);
@@ -463,10 +466,15 @@ static int exec_conf(void)
signal(SIGINT, SIG_DFL);
- sa.sa_handler = winch_handler;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_RESTART;
- sigaction(SIGWINCH, &sa, NULL);
+#ifdef SIGWINCH
+ {
+ struct sigaction sa;
+ sa.sa_handler = winch_handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ sigaction(SIGWINCH, &sa, NULL);
+ }
+#endif
*argptr++ = NULL;
diff --git a/release/src/router/busybox/scripts/kconfig/util.c b/release/src/router/busybox/scripts/kconfig/util.c
index 2630919457..13369e6a17 100644
--- a/release/src/router/busybox/scripts/kconfig/util.c
+++ b/release/src/router/busybox/scripts/kconfig/util.c
@@ -79,8 +79,7 @@ struct gstr str_assign(const char *s)
/* Free storage for growable string */
void str_free(struct gstr *gs)
{
- if (gs->s)
- free(gs->s);
+ free(gs->s);
gs->s = NULL;
gs->len = 0;
}
diff --git a/release/src/router/busybox/scripts/kconfig/zconf.hash.c_shipped b/release/src/router/busybox/scripts/kconfig/zconf.hash.c_shipped
index d39cf189ae..29d9cf6cc9 100644
--- a/release/src/router/busybox/scripts/kconfig/zconf.hash.c_shipped
+++ b/release/src/router/busybox/scripts/kconfig/zconf.hash.c_shipped
@@ -32,14 +32,7 @@
struct kconf_id;
/* maximum key range = 45, duplicates = 0 */
-#ifdef __GNUC__
-__inline
-#else
-#ifdef __cplusplus
-inline
-#endif
-#endif
-static unsigned int
+unsigned int
kconf_id_hash (register const char *str, register unsigned int len)
{
static unsigned char asso_values[] =
@@ -119,7 +112,7 @@ struct kconf_id_strings_t
char kconf_id_strings_str41[sizeof("choice")];
char kconf_id_strings_str46[sizeof("prompt")];
};
-static struct kconf_id_strings_t kconf_id_strings_contents =
+struct kconf_id_strings_t kconf_id_strings_contents =
{
"if",
"int",
@@ -153,9 +146,6 @@ static struct kconf_id_strings_t kconf_id_strings_contents =
"prompt"
};
#define kconf_id_strings ((const char *) &kconf_id_strings_contents)
-#ifdef __GNUC__
-__inline
-#endif
struct kconf_id *
kconf_id_lookup (register const char *str, register unsigned int len)
{
diff --git a/release/src/router/busybox/scripts/mkconfigs b/release/src/router/busybox/scripts/mkconfigs
index db94fcc442..6a26fe1dd2 100755
--- a/release/src/router/busybox/scripts/mkconfigs
+++ b/release/src/router/busybox/scripts/mkconfigs
@@ -65,11 +65,11 @@ static const char bbconfig_config_bz2[] ALIGN1 = {"
grep -e '^# CONFIG_' -e '^CONFIG_' "$config" \
| bzip2 -1 | dd bs=2 skip=1 2>/dev/null \
-| od -v -t x1 \
+| od -v -b \
| sed -e 's/^[^ ]*//' \
-e 's/ //g' \
-e '/^$/d' \
- -e 's/\(..\)/0x\1,/g'
+ -e 's/\(...\)/0\1,/g'
echo "};"
echo "#endif"
diff --git a/release/src/router/busybox/scripts/randomtest b/release/src/router/busybox/scripts/randomtest
index a102593d32..287f1c7717 100755
--- a/release/src/router/busybox/scripts/randomtest
+++ b/release/src/router/busybox/scripts/randomtest
@@ -52,9 +52,18 @@ echo '# CONFIG_RFKILL is not set' >>.config
if test x"$LIBC" = x"glibc"; then
cat .config \
| grep -v CONFIG_STATIC \
+ \
+ | grep -v CONFIG_FEATURE_2_4_MODULES \
+ | grep -v CONFIG_FEATURE_USE_BSS_TAIL \
+ | grep -v CONFIG_DEBUG_SANITIZE \
>.config.new
mv .config.new .config
echo '# CONFIG_STATIC is not set' >>.config
+ # newer glibc (at least 2.23) no longer supply query_module() ABI.
+ # People who target 2.4 kernels would likely use older glibc (and older bbox).
+ echo '# CONFIG_FEATURE_2_4_MODULES is not set' >>.config
+ echo '# CONFIG_FEATURE_USE_BSS_TAIL is not set' >>.config
+ echo '# CONFIG_DEBUG_SANITIZE is not set' >>.config
fi
# If uclibc, build static, and remove some things
@@ -66,12 +75,27 @@ if test x"$LIBC" = x"uclibc"; then
| grep -v CONFIG_PIE \
\
| grep -v CONFIG_FEATURE_2_4_MODULES \
+ | grep -v CONFIG_FEATURE_SYNC_FANCY \
+ | grep -v CONFIG_FEATURE_TOUCH_NODEREF \
+ | grep -v CONFIG_NANDWRITE \
+ | grep -v CONFIG_NANDDUMP \
+ | grep -v CONFIG_BLKDISCARD \
+ | grep -v CONFIG_NSENTER \
+ | grep -v CONFIG_UNSHARE \
>.config.new
mv .config.new .config
echo 'CONFIG_STATIC=y' >>.config
echo '# CONFIG_BUILD_LIBBUSYBOX is not set' >>.config
echo '# CONFIG_PIE is not set' >>.config
echo '# CONFIG_FEATURE_2_4_MODULES is not set' >>.config
+ echo '# CONFIG_FEATURE_SYNC_FANCY is not set' >>.config
+ echo '# CONFIG_FEATURE_TOUCH_NODEREF is not set' >>.config
+ # My uclibc installation does not support some needed APIs...
+ echo '# CONFIG_NANDWRITE is not set' >>.config
+ echo '# CONFIG_NANDDUMP is not set' >>.config
+ echo '# CONFIG_BLKDISCARD is not set' >>.config
+ echo '# CONFIG_NSENTER is not set' >>.config
+ echo '# CONFIG_UNSHARE is not set' >>.config
fi
# If STATIC, remove some things.
@@ -91,6 +115,8 @@ fi
# Build!
nice -n 10 make $MAKEOPTS 2>&1 | tee make.log
+grep 'Rerun make' make.log \
+&& nice -n 10 make $MAKEOPTS 2>&1 | tee -a make.log
# Return exitcode 1 if busybox executable does not exist
test -x busybox
diff --git a/release/src/router/busybox/scripts/trylink b/release/src/router/busybox/scripts/trylink
index a8b0b2e034..145df99590 100755
--- a/release/src/router/busybox/scripts/trylink
+++ b/release/src/router/busybox/scripts/trylink
@@ -46,19 +46,23 @@ try() {
}
check_cc() {
- local tempname="/tmp/temp.$$.$RANDOM"
+ local tempname="$(mktemp)"
+ local r
+ echo "int main(int argc,char**argv){return argv?argc:0;}" >"$tempname".c
# Can use "-o /dev/null", but older gcc tend to *unlink it* on failure! :(
- # "-xc": C language. "/dev/null" is an empty source file.
- if $CC $1 -shared -xc /dev/null -o "$tempname".o >/dev/null 2>&1; then
- echo "$1";
- else
- echo "$2";
- fi
- rm "$tempname".o 2>/dev/null
+ # Was using "-xc /dev/null", but we need a valid C program.
+ # "eval" may be needed if CFLAGS can contain
+ # '... -D"BB_VER=KBUILD_STR(1.N.M)" ...'
+ # and we need shell to process quotes!
+ $CC $CFLAGS $LDFLAGS $1 "$tempname".c -o "$tempname" >/dev/null 2>&1
+ r=$?
+ rm -f "$tempname" "$tempname".c "$tempname".o
+ return $r
}
check_libc_is_glibc() {
- local tempname="/tmp/temp.$$.$RANDOM"
+ local tempname="$(mktemp)"
+ local r
echo "\
#include <stdlib.h>
/* Apparently uclibc defines __GLIBC__ (compat trick?). Oh well. */
@@ -66,12 +70,10 @@ check_libc_is_glibc() {
syntax error here
#endif
" >"$tempname".c
- if $CC "$tempname".c -c -o "$tempname".o >/dev/null 2>&1; then
- echo "$2";
- else
- echo "$1";
- fi
- rm "$tempname".c "$tempname".o 2>/dev/null
+ ! $CC $CFLAGS "$tempname".c -c -o "$tempname".o >/dev/null 2>&1
+ r=$?
+ rm -f "$tempname" "$tempname".c "$tempname".o
+ return $r
}
EXE="$1"
@@ -83,32 +85,41 @@ A_FILES="$6"
LDLIBS="$7"
# The --sort-section option is not supported by older versions of ld
-SORT_SECTION=`check_cc "-Wl,--sort-section,alignment" ""`
+SORT_SECTION="-Wl,--sort-section,alignment"
+if ! check_cc "-Wl,--sort-section,alignment"; then
+ echo "Your linker does not support --sort-section,alignment"
+ SORT_SECTION=""
+fi
START_GROUP="-Wl,--start-group"
END_GROUP="-Wl,--end-group"
INFO_OPTS="-Wl,--warn-common -Wl,-Map,$EXE.map -Wl,--verbose"
# gold may not support --sort-common (yet)
-SORT_COMMON=`check_cc "-Wl,--sort-common" ""`
+SORT_COMMON="-Wl,--sort-common"
+if ! check_cc "-Wl,--sort-common"; then
+ echo "Your linker does not support --sort-common"
+ SORT_COMMON=""
+fi
# Static linking against glibc produces buggy executables
# (glibc does not cope well with ld --gc-sections).
# See sources.redhat.com/bugzilla/show_bug.cgi?id=3400
# Note that glibc is unsuitable for static linking anyway.
# We are removing -Wl,--gc-sections from link command line.
-GC_SECTIONS=`(
-. ./.config
-if test x"$CONFIG_STATIC" = x"y"; then
- check_libc_is_glibc "" "-Wl,--gc-sections"
-else
- echo "-Wl,--gc-sections"
+GC_SECTIONS="-Wl,--gc-sections"
+if (. ./.config && test x"$CONFIG_STATIC" = x"y") then
+ if check_libc_is_glibc; then
+ echo "Static linking against glibc, can't use --gc-sections"
+ GC_SECTIONS=""
+ fi
fi
-)`
-
# The --gc-sections option is not supported by older versions of ld
if test -n "$GC_SECTIONS"; then
- GC_SECTIONS=`check_cc "$GC_SECTIONS" ""`
+ if ! check_cc "$GC_SECTIONS"; then
+ echo "Your linker does not support $GC_SECTIONS"
+ GC_SECTIONS=""
+ fi
fi
# Sanitize lib list (dups, extra spaces etc)
@@ -117,7 +128,7 @@ LDLIBS=`echo "$LDLIBS" | xargs -n1 | sort | uniq | xargs`
# First link with all libs. If it fails, bail out
echo "Trying libraries: $LDLIBS"
# "lib1 lib2 lib3" -> "-llib1 -llib2 -llib3"
-l_list=`echo "$LDLIBS" | sed -e 's/ / -l/g' -e 's/^/-l/' -e 's/^-l$//'`
+l_list=`echo " $LDLIBS " | sed -e 's: \([^- ][^ ]*\): -l\1:g'`
test "x$l_list" != "x" && l_list="$START_GROUP $l_list $END_GROUP"
try $CC $CFLAGS $LDFLAGS \
-o $EXE \
@@ -129,6 +140,8 @@ try $CC $CFLAGS $LDFLAGS \
|| {
echo "Failed: $l_list"
cat $EXE.out
+ echo 'Note: if build needs additional libraries, put them in CONFIG_EXTRA_LDLIBS.'
+ echo 'Example: CONFIG_EXTRA_LDLIBS="pthread dl tirpc audit pam"'
exit 1
}
@@ -141,7 +154,7 @@ while test "$LDLIBS"; do
for one in $LDLIBS; do
without_one=`echo " $LDLIBS " | sed "s/ $one / /g" | xargs`
# "lib1 lib2 lib3" -> "-llib1 -llib2 -llib3"
- l_list=`echo "$without_one" | sed -e 's/ / -l/g' -e 's/^/-l/' -e 's/^-l$//'`
+ l_list=`echo " $without_one " | sed -e 's: \([^- ][^ ]*\): -l\1:g'`
test x"$l_list" != x"" && l_list="$START_GROUP $l_list $END_GROUP"
$debug && echo "Trying -l options: '$l_list'"
try $CC $CFLAGS $LDFLAGS \
@@ -172,7 +185,7 @@ done
# Make the binary with final, minimal list of libs
echo "Final link with: ${LDLIBS:-<none>}"
-l_list=`echo "$LDLIBS" | sed -e 's/ / -l/g' -e 's/^/-l/' -e 's/^-l$//'`
+l_list=`echo " $LDLIBS " | sed -e 's: \([^- ][^ ]*\): -l\1:g'`
test "x$l_list" != "x" && l_list="$START_GROUP $l_list $END_GROUP"
# --verbose gives us gobs of info to stdout (e.g. linker script used)
if ! test -f busybox_ldscript; then
@@ -196,6 +209,16 @@ else
# *(.bss SORT_BY_ALIGNMENT(.bss.*) .gnu.linkonce.b.*)
# This will eliminate most of the padding (~3kb).
# Hmm, "ld --sort-section alignment" should do it too.
+ #
+ # There is a ld hack which is meant to decrease disk usage
+ # at the cost of more RAM usage (??!!) in standard ld script:
+ # /* Adjust the address for the data segment. We want to adjust up to
+ # the same address within the page on the next page up. */
+ # . = ALIGN (0x1000) - ((0x1000 - .) & (0x1000 - 1)); . = DATA_SEGMENT_ALIGN (0x1000, 0x1000);
+ # Replace it with:
+ # . = ALIGN (0x1000); . = DATA_SEGMENT_ALIGN (0x1000, 0x1000);
+ # to unconditionally align .data to the next page boundary,
+ # instead of "next page, plus current offset in this page"
try $CC $CFLAGS $LDFLAGS \
-o $EXE \
$SORT_COMMON \
@@ -268,9 +291,9 @@ fi
if test "$CONFIG_FEATURE_INDIVIDUAL" = y; then
echo "Linking individual applets against libbusybox (see $sharedlib_dir/*)"
- gcc -DNAME_MAIN_CNAME -E -include include/autoconf.h include/applets.h \
+ gcc -DNAME_MAIN -E -include include/autoconf.h include/applets.h \
| grep -v "^#" \
- | grep -v "^$" \
+ | grep -v "^ *$" \
> applet_lst.tmp
while read name main junk; do
@@ -300,6 +323,8 @@ int main(int argc, char **argv)
}
rm -- "$sharedlib_dir/applet.c" $EXE.out
$STRIP -s --remove-section=.note --remove-section=.comment $EXE
+ # Let user see that we do something - list the names of created binaries:
+ echo "$EXE"
done <applet_lst.tmp
fi
diff --git a/release/src/router/busybox/selinux/Config.src b/release/src/router/busybox/selinux/Config.src
index 47d15b6afd..d4701f60b2 100644
--- a/release/src/router/busybox/selinux/Config.src
+++ b/release/src/router/busybox/selinux/Config.src
@@ -64,7 +64,7 @@ config RUNCON
default n
depends on SELINUX
help
- Enable support to run command in speficied security context.
+ Enable support to run command in specified security context.
config FEATURE_RUNCON_LONG_OPTIONS
bool "Enable long options"
diff --git a/release/src/router/busybox/selinux/chcon.c b/release/src/router/busybox/selinux/chcon.c
index 88d0cfec61..f947c2c128 100644
--- a/release/src/router/busybox/selinux/chcon.c
+++ b/release/src/router/busybox/selinux/chcon.c
@@ -92,7 +92,7 @@ static int FAST_FUNC change_filedir_context(
if (specified_context == NULL) {
context = set_security_context_component(file_context,
- user, role, type, range);
+ user, role, type, range);
if (!context) {
bb_error_msg("can't compute security context from %s", file_context);
goto skip;
@@ -121,15 +121,15 @@ static int FAST_FUNC change_filedir_context(
}
if ((option_mask32 & OPT_VERBOSE) || ((option_mask32 & OPT_CHANHES) && !fail)) {
printf(!fail
- ? "context of %s changed to %s\n"
- : "can't change context of %s to %s\n",
- fname, context_string);
+ ? "context of %s changed to %s\n"
+ : "can't change context of %s to %s\n",
+ fname, context_string);
}
if (!fail) {
rc = TRUE;
} else if ((option_mask32 & OPT_QUIET) == 0) {
bb_error_msg("can't change context of %s to %s",
- fname, context_string);
+ fname, context_string);
}
} else if (option_mask32 & OPT_VERBOSE) {
printf("context of %s retained as %s\n", fname, context_string);
@@ -181,7 +181,7 @@ int chcon_main(int argc UNUSED_PARAM, char **argv)
#if ENABLE_FEATURE_CHCON_LONG_OPTIONS
if (option_mask32 & OPT_REFERENCE) {
/* FIXME: lgetfilecon() should be used when '-h' is specified.
- But current implementation follows the original one. */
+ * But current implementation follows the original one. */
if (getfilecon(reference_file, &specified_context) < 0)
bb_perror_msg_and_die("getfilecon('%s') failed", reference_file);
} else
@@ -201,10 +201,10 @@ int chcon_main(int argc UNUSED_PARAM, char **argv)
fname[fname_len] = '\0';
if (recursive_action(fname,
- 1<<option_mask32 & OPT_RECURSIVE,
- change_filedir_context,
- change_filedir_context,
- NULL, 0) != TRUE)
+ 1<<option_mask32 & OPT_RECURSIVE,
+ change_filedir_context,
+ change_filedir_context,
+ NULL, 0) != TRUE)
errors = 1;
}
return errors;
diff --git a/release/src/router/busybox/selinux/runcon.c b/release/src/router/busybox/selinux/runcon.c
index 3183a2274e..27f2be3a90 100644
--- a/release/src/router/busybox/selinux/runcon.c
+++ b/release/src/router/busybox/selinux/runcon.c
@@ -56,7 +56,7 @@
#include "libbb.h"
static context_t runcon_compute_new_context(char *user, char *role, char *type, char *range,
- char *command, int compute_trans)
+ char *command, int compute_trans)
{
context_t con;
security_context_t cur_context;
@@ -69,9 +69,9 @@ static context_t runcon_compute_new_context(char *user, char *role, char *type,
if (getfilecon(command, &file_context) < 0)
bb_error_msg_and_die("can't retrieve attributes of '%s'",
- command);
+ command);
if (security_compute_create(cur_context, file_context,
- SECCLASS_PROCESS, &new_context))
+ SECCLASS_PROCESS, &new_context))
bb_error_msg_and_die("unable to compute a new context");
cur_context = new_context;
}
@@ -147,11 +147,11 @@ int runcon_main(int argc UNUSED_PARAM, char **argv)
if (security_check_context(context_str(con)))
bb_error_msg_and_die("'%s' is not a valid context",
- context_str(con));
+ context_str(con));
if (setexeccon(context_str(con)))
bb_error_msg_and_die("can't set up security context '%s'",
- context_str(con));
+ context_str(con));
BB_EXECVP_or_die(argv);
}
diff --git a/release/src/router/busybox/selinux/sestatus.c b/release/src/router/busybox/selinux/sestatus.c
index 0bd1a0dda3..e594318736 100644
--- a/release/src/router/busybox/selinux/sestatus.c
+++ b/release/src/router/busybox/selinux/sestatus.c
@@ -41,7 +41,7 @@ static void display_boolean(void)
if (pending < 0)
goto skip;
printf(COL_FMT "%s",
- bools[i], active == 0 ? "off" : "on");
+ bools[i], active == 0 ? "off" : "on");
if (active != pending)
printf(" (%sactivate pending)", pending == 0 ? "in" : "");
bb_putchar('\n');
diff --git a/release/src/router/busybox/selinux/setfiles.c b/release/src/router/busybox/selinux/setfiles.c
index ca3fd93618..51a7e63bd7 100644
--- a/release/src/router/busybox/selinux/setfiles.c
+++ b/release/src/router/busybox/selinux/setfiles.c
@@ -17,6 +17,7 @@
//usage: )
//usage: "\n -d Show which specification matched each file"
//usage: "\n -l Log changes in file labels to syslog"
+//TODO: log to syslog is not yet implemented, it goes to stdout only now
//usage: "\n -n Don't change any file labels"
//usage: "\n -q Suppress warnings"
//usage: "\n -r DIR Use an alternate root path"
@@ -76,9 +77,10 @@ struct globals {
int nerr;
struct edir excludeArray[MAX_EXCLUDES];
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
void BUG_setfiles_globals_too_big(void);
#define INIT_G() do { \
+ setup_common_bufsiz(); \
if (sizeof(G) > COMMON_BUFSIZE) \
BUG_setfiles_globals_too_big(); \
/* memset(&G, 0, sizeof(G)); - already is */ \
@@ -251,7 +253,6 @@ static int match(const char *name, struct stat *sb, char **con)
name = path;
if (excludeCtr > 0 && exclude(name))
goto err;
-
} else {
char *p;
p = realpath(name, path);
@@ -384,16 +385,16 @@ static int restore(const char *file)
* the user has changed but the role and type are the
* same. For "-vv", emit everything. */
if (verbose > 1 || !user_only_changed) {
- bb_info_msg("%s: reset %s context %s->%s",
+ printf("%s: reset %s context %s->%s\n",
applet_name, my_file, context ? context : "", newcon);
}
}
if (FLAG_l_take_log && !user_only_changed) {
if (context)
- bb_info_msg("relabeling %s from %s to %s", my_file, context, newcon);
+ printf("relabeling %s from %s to %s\n", my_file, context, newcon);
else
- bb_info_msg("labeling %s to %s", my_file, newcon);
+ printf("labeling %s to %s\n", my_file, newcon);
}
if (outfile && !user_only_changed)
@@ -498,10 +499,11 @@ static int process_one(char *name)
if (S_ISDIR(sb.st_mode) && recurse) {
if (recursive_action(name,
- ACTION_RECURSE,
- apply_spec,
- apply_spec,
- NULL, 0) != TRUE) {
+ ACTION_RECURSE,
+ apply_spec,
+ apply_spec,
+ NULL, 0) != TRUE
+ ) {
bb_error_msg("error while labeling %s", name);
goto err;
}
@@ -584,7 +586,7 @@ int setfiles_main(int argc UNUSED_PARAM, char **argv)
flags = getopt32(argv, "de:f:ilnpqr:svo:FW"
IF_FEATURE_SETFILES_CHECK_OPTION("c:"),
&exclude_dir, &input_filename, &rootpath, &out_filename,
- IF_FEATURE_SETFILES_CHECK_OPTION(&policyfile,)
+ IF_FEATURE_SETFILES_CHECK_OPTION(&policyfile,)
&verbose);
}
argv += optind;
@@ -600,8 +602,8 @@ int setfiles_main(int argc UNUSED_PARAM, char **argv)
fclose(policystream);
/* Only process the specified file_contexts file, not
- any .homedirs or .local files, and do not perform
- context translations. */
+ * any .homedirs or .local files, and do not perform
+ * context translations. */
set_matchpathcon_flags(MATCHPATHCON_BASEONLY |
MATCHPATHCON_NOTRANS |
MATCHPATHCON_VALIDATE);
@@ -631,8 +633,8 @@ int setfiles_main(int argc UNUSED_PARAM, char **argv)
if (applet_name[0] == 's') { /* setfiles */
/* Use our own invalid context checking function so that
- we can support either checking against the active policy or
- checking against a binary policy file. */
+ * we can support either checking against the active policy or
+ * checking against a binary policy file. */
set_matchpathcon_canoncon(&canoncon);
if (!argv[0])
bb_show_usage();
diff --git a/release/src/router/busybox/shell/ash.c b/release/src/router/busybox/shell/ash.c
index 773d5e4d42..faa45a8dc6 100644
--- a/release/src/router/busybox/shell/ash.c
+++ b/release/src/router/busybox/shell/ash.c
@@ -23,8 +23,9 @@
* define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
* define DEBUG=2 to compile in and turn on debugging.
*
- * When debugging is on, debugging info will be written to ./trace and
- * a quit signal will generate a core dump.
+ * When debugging is on (DEBUG is 1 and "set -o debug" was executed),
+ * debugging info will be written to ./trace and a quit signal
+ * will generate a core dump.
*/
#define DEBUG 0
/* Tweak debug output verbosity here */
@@ -36,10 +37,10 @@
#define JOBS ENABLE_ASH_JOB_CONTROL
-#include <paths.h>
#include <setjmp.h>
#include <fnmatch.h>
#include <sys/times.h>
+#include <sys/utsname.h> /* for setting $HOSTNAME */
#include "busybox.h" /* for applet_names */
#include "unicode.h"
@@ -141,6 +142,13 @@
//config: help
//config: Enable support for test builtin in ash.
//config:
+//config:config ASH_HELP
+//config: bool "help builtin"
+//config: default y
+//config: depends on ASH
+//config: help
+//config: Enable help builtin in ash.
+//config:
//config:config ASH_CMDCMD
//config: bool "'command' command to override shell builtins"
//config: default y
@@ -384,6 +392,9 @@ static void trace_vprintf(const char *fmt, va_list va);
/* ============ Utility functions */
#define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0)
+#define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
+#define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
+
static int isdigit_str9(const char *str)
{
int maxlen = 9 + 1; /* max 9 digits: 999999999 */
@@ -525,11 +536,12 @@ flush_stdout_stderr(void)
INT_ON;
}
+/* Was called outcslow(c,FILE*), but c was always '\n' */
static void
-outcslow(int c, FILE *dest)
+newline_and_flush(FILE *dest)
{
INT_OFF;
- putc(c, dest);
+ putc('\n', dest);
fflush(dest);
INT_ON;
}
@@ -586,8 +598,6 @@ out2str(const char *p)
#define CTLVAR ((unsigned char)'\202') /* variable defn */
#define CTLENDVAR ((unsigned char)'\203')
#define CTLBACKQ ((unsigned char)'\204')
-#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
-/* CTLBACKQ | CTLQUOTE == '\205' */
#define CTLARI ((unsigned char)'\206') /* arithmetic expression */
#define CTLENDARI ((unsigned char)'\207')
#define CTLQUOTEMARK ((unsigned char)'\210')
@@ -596,7 +606,6 @@ out2str(const char *p)
/* variable substitution byte (follows CTLVAR) */
#define VSTYPE 0x0f /* type of variable substitution */
#define VSNUL 0x10 /* colon--treat the empty string as unset */
-#define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
/* values of VSTYPE field */
#define VSNORMAL 0x1 /* normal variable: $var or ${var} */
@@ -616,8 +625,9 @@ out2str(const char *p)
#endif
static const char dolatstr[] ALIGN1 = {
- CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'
+ CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
};
+#define DOLATSTRLEN 6
#define NCMD 0
#define NPIPE 1
@@ -853,9 +863,7 @@ trace_puts_quoted(char *s)
case '\\': c = '\\'; goto backslash;
case CTLESC: c = 'e'; goto backslash;
case CTLVAR: c = 'v'; goto backslash;
- case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
case CTLBACKQ: c = 'q'; goto backslash;
- case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
backslash:
putc('\\', tracefile);
putc(c, tracefile);
@@ -1018,7 +1026,6 @@ sharg(union node *arg, FILE *fp)
putc('}', fp);
break;
case CTLBACKQ:
- case CTLBACKQ|CTLQUOTE:
putc('$', fp);
putc('(', fp);
shtree(bqlist->n, -1, NULL, fp);
@@ -1195,7 +1202,7 @@ ash_vmsg(const char *msg, va_list ap)
fprintf(stderr, "line %d: ", startlinno);
}
vfprintf(stderr, msg, ap);
- outcslow('\n', stderr);
+ newline_and_flush(stderr);
}
/*
@@ -1899,6 +1906,10 @@ static const struct {
const char *var_text;
void (*var_func)(const char *) FAST_FUNC;
} varinit_data[] = {
+ /*
+ * Note: VEXPORT would not work correctly here for NOFORK applets:
+ * some environment strings may be constant.
+ */
{ VSTRFIXED|VTEXTFIXED , defifsvar , NULL },
#if ENABLE_ASH_MAIL
{ VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL" , changemail },
@@ -2003,27 +2014,6 @@ getoptsreset(const char *value)
}
#endif
-/* math.h has these, otherwise define our private copies */
-#if !ENABLE_SH_MATH_SUPPORT
-#define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
-#define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
-/*
- * Return the pointer to the first char which is not part of a legal variable name
- * (a letter or underscore followed by letters, underscores, and digits).
- */
-static const char*
-endofname(const char *name)
-{
- if (!is_name(*name))
- return name;
- while (*++name) {
- if (!is_in_name(*name))
- break;
- }
- return name;
-}
-#endif
-
/*
* Compares two strings up to the first = or '\0'. The first
* string must be terminated by '='; the second may be terminated by
@@ -2035,7 +2025,7 @@ varcmp(const char *p, const char *q)
int c, d;
while ((c = *p) == (d = *q)) {
- if (!c || c == '=')
+ if (c == '\0' || c == '=')
goto out;
p++;
q++;
@@ -2133,6 +2123,22 @@ lookupvar(const char *name)
return NULL;
}
+static void reinit_unicode_for_ash(void)
+{
+ /* Unicode support should be activated even if LANG is set
+ * _during_ shell execution, not only if it was set when
+ * shell was started. Therefore, re-check LANG every time:
+ */
+ if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
+ || ENABLE_UNICODE_USING_LOCALE
+ ) {
+ const char *s = lookupvar("LC_ALL");
+ if (!s) s = lookupvar("LC_CTYPE");
+ if (!s) s = lookupvar("LANG");
+ reinit_unicode(s);
+ }
+}
+
/*
* Search the environment of a builtin command.
*/
@@ -2236,7 +2242,7 @@ setvar(const char *name, const char *val, int flags)
}
static void FAST_FUNC
-setvar2(const char *name, const char *val)
+setvar0(const char *name, const char *val)
{
setvar(name, val, 0);
}
@@ -2299,7 +2305,7 @@ unsetvar(const char *s)
free(vp);
INT_ON;
} else {
- setvar(s, 0, 0);
+ setvar0(s, NULL);
vp->flags &= ~VEXPORT;
}
ok:
@@ -2549,7 +2555,7 @@ updatepwd(const char *dir)
new = stack_putstr(p, new);
USTPUTC('/', new);
}
- p = strtok(0, "/");
+ p = strtok(NULL, "/");
}
if (new > lim)
STUNPUTC(new);
@@ -2744,7 +2750,7 @@ pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
#else
# define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
#endif
-static const uint16_t S_I_T[] = {
+static const uint16_t S_I_T[] ALIGN2 = {
#if ENABLE_ASH_ALIAS
SIT_ITEM(CSPCL , CIGN , CIGN , CIGN ), /* 0, PEOA */
#endif
@@ -2846,7 +2852,7 @@ SIT(int c, int syntax)
#else /* !USE_SIT_FUNCTION */
-static const uint8_t syntax_index_table[] = {
+static const uint8_t syntax_index_table[] ALIGN1 = {
/* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
/* 0 */ CWORD_CWORD_CWORD_CWORD,
/* 1 */ CWORD_CWORD_CWORD_CWORD,
@@ -3330,6 +3336,7 @@ unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
#define SHOW_ONLY_PGID 0x01 /* show only pgid (jobs -p) */
#define SHOW_PIDS 0x02 /* show individual pids, not just one line per job */
#define SHOW_CHANGED 0x04 /* only jobs whose state has changed */
+#define SHOW_STDERR 0x08 /* print to stderr (else stdout) */
/*
* A job structure contains information about a job. A job is either a
@@ -3559,7 +3566,8 @@ set_curjob(struct job *jp, unsigned mode)
break;
case CUR_RUNNING:
/* newly created job or backgrounded job,
- put after all stopped jobs. */
+ * put after all stopped jobs.
+ */
while (1) {
jp1 = *jpp;
#if JOBS
@@ -3635,7 +3643,7 @@ getjob(const char *name, int getctl)
if (is_number(p)) {
num = atoi(p);
- if (num < njobs) {
+ if (num <= njobs) {
jp = jobtab + num - 1;
if (jp->used)
goto gotit;
@@ -3843,7 +3851,7 @@ showpipe(struct job *jp /*, FILE *out*/)
psend = jp->ps + jp->nprocs;
for (ps = jp->ps + 1; ps < psend; ps++)
printf(" | %s", ps->ps_cmd);
- outcslow('\n', stdout);
+ newline_and_flush(stdout);
flush_stdout_stderr();
}
@@ -3903,39 +3911,33 @@ fg_bgcmd(int argc UNUSED_PARAM, char **argv)
#endif
static int
-sprint_status(char *s, int status, int sigonly)
+sprint_status48(char *s, int status, int sigonly)
{
int col;
int st;
col = 0;
if (!WIFEXITED(status)) {
-#if JOBS
- if (WIFSTOPPED(status))
+ if (JOBS && WIFSTOPPED(status))
st = WSTOPSIG(status);
else
-#endif
st = WTERMSIG(status);
if (sigonly) {
if (st == SIGINT || st == SIGPIPE)
goto out;
-#if JOBS
- if (WIFSTOPPED(status))
+ if (JOBS && WIFSTOPPED(status))
goto out;
-#endif
}
st &= 0x7f;
//TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
col = fmtstr(s, 32, strsignal(st));
if (WCOREDUMP(status)) {
- col += fmtstr(s + col, 16, " (core dumped)");
+ strcpy(s + col, " (core dumped)");
+ col += sizeof(" (core dumped)")-1;
}
} else if (!sigonly) {
st = WEXITSTATUS(status);
- if (st)
- col = fmtstr(s, 16, "Done(%d)", st);
- else
- col = fmtstr(s, 16, "Done");
+ col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
}
out:
return col;
@@ -3948,7 +3950,6 @@ dowait(int wait_flags, struct job *job)
int status;
struct job *jp;
struct job *thisjob;
- int state;
TRACE(("dowait(0x%x) called\n", wait_flags));
@@ -3966,11 +3967,12 @@ dowait(int wait_flags, struct job *job)
INT_OFF;
thisjob = NULL;
for (jp = curjob; jp; jp = jp->prev_job) {
+ int jobstate;
struct procstat *ps;
struct procstat *psend;
if (jp->state == JOBDONE)
continue;
- state = JOBDONE;
+ jobstate = JOBDONE;
ps = jp->ps;
psend = ps + jp->nprocs;
do {
@@ -3982,41 +3984,41 @@ dowait(int wait_flags, struct job *job)
thisjob = jp;
}
if (ps->ps_status == -1)
- state = JOBRUNNING;
+ jobstate = JOBRUNNING;
#if JOBS
- if (state == JOBRUNNING)
+ if (jobstate == JOBRUNNING)
continue;
if (WIFSTOPPED(ps->ps_status)) {
jp->stopstatus = ps->ps_status;
- state = JOBSTOPPED;
+ jobstate = JOBSTOPPED;
}
#endif
} while (++ps < psend);
- if (thisjob)
- goto gotjob;
- }
-#if JOBS
- if (!WIFSTOPPED(status))
-#endif
- jobless--;
- goto out;
-
- gotjob:
- if (state != JOBRUNNING) {
- thisjob->changed = 1;
+ if (!thisjob)
+ continue;
- if (thisjob->state != state) {
- TRACE(("Job %d: changing state from %d to %d\n",
- jobno(thisjob), thisjob->state, state));
- thisjob->state = state;
+ /* Found the job where one of its processes changed its state.
+ * Is there at least one live and running process in this job? */
+ if (jobstate != JOBRUNNING) {
+ /* No. All live processes in the job are stopped
+ * (JOBSTOPPED) or there are no live processes (JOBDONE)
+ */
+ thisjob->changed = 1;
+ if (thisjob->state != jobstate) {
+ TRACE(("Job %d: changing state from %d to %d\n",
+ jobno(thisjob), thisjob->state, jobstate));
+ thisjob->state = jobstate;
#if JOBS
- if (state == JOBSTOPPED) {
- set_curjob(thisjob, CUR_STOPPED);
- }
+ if (jobstate == JOBSTOPPED)
+ set_curjob(thisjob, CUR_STOPPED);
#endif
+ }
}
+ goto out;
}
-
+ /* The process wasn't found in job list */
+ if (JOBS && !WIFSTOPPED(status))
+ jobless--;
out:
INT_ON;
@@ -4024,7 +4026,7 @@ dowait(int wait_flags, struct job *job)
char s[48 + 1];
int len;
- len = sprint_status(s, status, 1);
+ len = sprint_status48(s, status, 1);
if (len) {
s[len] = '\n';
s[len + 1] = '\0';
@@ -4045,13 +4047,14 @@ blocking_wait_with_raise_on_sig(void)
#if JOBS
static void
-showjob(FILE *out, struct job *jp, int mode)
+showjob(struct job *jp, int mode)
{
struct procstat *ps;
struct procstat *psend;
int col;
int indent_col;
- char s[80];
+ char s[16 + 16 + 48];
+ FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
ps = jp->ps;
@@ -4081,7 +4084,7 @@ showjob(FILE *out, struct job *jp, int mode)
int status = psend[-1].ps_status;
if (jp->state == JOBSTOPPED)
status = jp->stopstatus;
- col += sprint_status(s + col, status, 0);
+ col += sprint_status48(s + col, status, 0);
}
/* By now, "[JOBID]* [maybe PID] STATUS" is printed */
@@ -4108,7 +4111,7 @@ showjob(FILE *out, struct job *jp, int mode)
ps->ps_cmd
);
} while (++ps != psend);
- outcslow('\n', out);
+ newline_and_flush(out);
jp->changed = 0;
@@ -4123,7 +4126,7 @@ showjob(FILE *out, struct job *jp, int mode)
* statuses have changed since the last call to showjobs.
*/
static void
-showjobs(FILE *out, int mode)
+showjobs(int mode)
{
struct job *jp;
@@ -4135,7 +4138,7 @@ showjobs(FILE *out, int mode)
for (jp = curjob; jp; jp = jp->prev_job) {
if (!(mode & SHOW_CHANGED) || jp->changed) {
- showjob(out, jp, mode);
+ showjob(jp, mode);
}
}
}
@@ -4156,10 +4159,10 @@ jobscmd(int argc UNUSED_PARAM, char **argv)
argv = argptr;
if (*argv) {
do
- showjob(stdout, getjob(*argv, 0), mode);
+ showjob(getjob(*argv, 0), mode);
while (*++argv);
} else {
- showjobs(stdout, mode);
+ showjobs(mode);
}
return 0;
@@ -4401,11 +4404,7 @@ cmdputs(const char *s)
str = "${#";
else
str = "${";
- if (!(subtype & VSQUOTE) == !(quoted & 1))
- goto dostr;
- quoted ^= 1;
- c = '"';
- break;
+ goto dostr;
case CTLENDVAR:
str = "\"}" + !(quoted & 1);
quoted >>= 1;
@@ -4414,9 +4413,6 @@ cmdputs(const char *s)
case CTLBACKQ:
str = "$(...)";
goto dostr;
- case CTLBACKQ+CTLQUOTE:
- str = "\"$(...)\"";
- goto dostr;
#if ENABLE_SH_MATH_SUPPORT
case CTLARI:
str = "$((";
@@ -4751,7 +4747,7 @@ forkchild(struct job *jp, union node *n, int mode)
* Our solution: ONLY bare $(trap) or `trap` is special.
*/
/* Save trap handler strings for trap builtin to print */
- trap_ptr = memcpy(xmalloc(sizeof(trap)), trap, sizeof(trap));
+ trap_ptr = xmemdup(trap, sizeof(trap));
/* Fall through into clearing traps */
}
clear_traps();
@@ -5105,15 +5101,14 @@ openredirect(union node *redir)
char *fname;
int f;
+ fname = redir->nfile.expfname;
switch (redir->nfile.type) {
case NFROM:
- fname = redir->nfile.expfname;
f = open(fname, O_RDONLY);
if (f < 0)
goto eopen;
break;
case NFROMTO:
- fname = redir->nfile.expfname;
f = open(fname, O_RDWR|O_CREAT, 0666);
if (f < 0)
goto ecreate;
@@ -5124,7 +5119,6 @@ openredirect(union node *redir)
#endif
/* Take care of noclobber mode. */
if (Cflag) {
- fname = redir->nfile.expfname;
f = noclobberopen(fname);
if (f < 0)
goto ecreate;
@@ -5132,13 +5126,11 @@ openredirect(union node *redir)
}
/* FALLTHROUGH */
case NCLOBBER:
- fname = redir->nfile.expfname;
f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
if (f < 0)
goto ecreate;
break;
case NAPPEND:
- fname = redir->nfile.expfname;
f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
if (f < 0)
goto ecreate;
@@ -5416,7 +5408,7 @@ popredir(int drop, int restore)
struct redirtab *rp;
int i;
- if (--g_nullredirs >= 0)
+ if (--g_nullredirs >= 0 || redirlist == NULL)
return;
INT_OFF;
rp = redirlist;
@@ -5497,7 +5489,7 @@ ash_arith(const char *s)
arith_t result;
math_state.lookupvar = lookupvar;
- math_state.setvar = setvar2;
+ math_state.setvar = setvar0;
//math_state.endofname = endofname;
INT_OFF;
@@ -5518,18 +5510,23 @@ ash_arith(const char *s)
#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
#define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
-#define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
+#define EXP_QPAT 0x20 /* pattern in quoted parameter expansion */
#define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
#define EXP_WORD 0x80 /* expand word in parameter expansion */
-#define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
+#define EXP_QUOTED 0x100 /* expand word in double quotes */
/*
* rmescape() flags
*/
#define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
#define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
-#define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
#define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
#define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
+#define RMESCAPE_SLASH 0x20 /* Stop globbing after slash */
+
+/* Add CTLESC when necessary. */
+#define QUOTES_ESC (EXP_FULL | EXP_CASE | EXP_QPAT | EXP_REDIR)
+/* Do not skip NUL characters. */
+#define QUOTES_KEEPNUL EXP_TILDE
/*
* Structure specifying which parts of the string should be searched
@@ -5571,8 +5568,8 @@ cvtnum(arith_t num)
{
int len;
- expdest = makestrspace(32, expdest);
- len = fmtstr(expdest, 32, ARITH_FMT, num);
+ expdest = makestrspace(sizeof(arith_t)*3 + 2, expdest);
+ len = fmtstr(expdest, sizeof(arith_t)*3 + 2, ARITH_FMT, num);
STADJUST(len, expdest);
return len;
}
@@ -5594,14 +5591,16 @@ esclen(const char *start, const char *p)
static char *
rmescapes(char *str, int flag)
{
- static const char qchars[] ALIGN1 = { CTLESC, CTLQUOTEMARK, '\0' };
+ static const char qchars[] ALIGN1 = {
+ IF_ASH_BASH_COMPAT('/',) CTLESC, CTLQUOTEMARK, '\0' };
char *p, *q, *r;
unsigned inquotes;
unsigned protect_against_glob;
unsigned globbing;
+ IF_ASH_BASH_COMPAT(unsigned slash = flag & RMESCAPE_SLASH;)
- p = strpbrk(str, qchars);
+ p = strpbrk(str, qchars IF_ASH_BASH_COMPAT(+ !slash));
if (!p)
return str;
@@ -5628,13 +5627,11 @@ rmescapes(char *str, int flag)
}
}
- inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
+ inquotes = 0;
globbing = flag & RMESCAPE_GLOB;
protect_against_glob = globbing;
while (*p) {
if ((unsigned char)*p == CTLQUOTEMARK) {
-// TODO: if no RMESCAPE_QUOTED in flags, inquotes never becomes 0
-// (alternates between RMESCAPE_QUOTED and ~RMESCAPE_QUOTED). Is it ok?
// Note: both inquotes and protect_against_glob only affect whether
// CTLESC,<ch> gets converted to <ch> or to \<ch>
inquotes = ~inquotes;
@@ -5642,17 +5639,23 @@ rmescapes(char *str, int flag)
protect_against_glob = globbing;
continue;
}
- if (*p == '\\') {
- /* naked back slash */
- protect_against_glob = 0;
- goto copy;
- }
if ((unsigned char)*p == CTLESC) {
p++;
- if (protect_against_glob && inquotes && *p != '/') {
+ if (protect_against_glob) {
*q++ = '\\';
}
+ } else if (*p == '\\' && !inquotes) {
+ /* naked back slash */
+ protect_against_glob = 0;
+ goto copy;
+ }
+#if ENABLE_ASH_BASH_COMPAT
+ else if (*p == '/' && slash) {
+ /* stop handling globbing and mark location of slash */
+ globbing = slash = 0;
+ *p = CTLESC;
}
+#endif
protect_against_glob = globbing;
copy:
*q++ = *p++;
@@ -5672,13 +5675,9 @@ rmescapes(char *str, int flag)
* Returns an stalloced string.
*/
static char *
-preglob(const char *pattern, int quoted, int flag)
+preglob(const char *pattern, int flag)
{
- flag |= RMESCAPE_GLOB;
- if (quoted) {
- flag |= RMESCAPE_QUOTED;
- }
- return rmescapes((char *)pattern, flag);
+ return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
}
/*
@@ -5687,29 +5686,36 @@ preglob(const char *pattern, int quoted, int flag)
static void
memtodest(const char *p, size_t len, int syntax, int quotes)
{
- char *q = expdest;
+ char *q;
+
+ if (!len)
+ return;
- q = makestrspace(quotes ? len * 2 : len, q);
+ q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
- while (len--) {
+ do {
unsigned char c = *p++;
- if (c == '\0')
- continue;
- if (quotes) {
+ if (c) {
int n = SIT(c, syntax);
- if (n == CCTL || n == CBACK)
+ if ((quotes & QUOTES_ESC) &&
+ ((n == CCTL) ||
+ (((quotes & EXP_FULL) || syntax != BASESYNTAX) &&
+ n == CBACK)))
USTPUTC(CTLESC, q);
- }
+ } else if (!(quotes & QUOTES_KEEPNUL))
+ continue;
USTPUTC(c, q);
- }
+ } while (--len);
expdest = q;
}
-static void
+static size_t
strtodest(const char *p, int syntax, int quotes)
{
- memtodest(p, strlen(p), syntax, quotes);
+ size_t len = strlen(p);
+ memtodest(p, len, syntax, quotes);
+ return len;
}
/*
@@ -5782,8 +5788,7 @@ exptilde(char *startp, char *p, int flags)
char *name;
struct passwd *pw;
const char *home;
- int quotes = flags & (EXP_FULL | EXP_CASE | EXP_REDIR);
- int startloc;
+ int quotes = flags & QUOTES_ESC;
name = p + 1;
@@ -5815,9 +5820,7 @@ exptilde(char *startp, char *p, int flags)
if (!home || !*home)
goto lose;
*p = c;
- startloc = expdest - (char *)stackblock();
strtodest(home, SQSYNTAX, quotes);
- recordregion(startloc, expdest - (char *)stackblock(), 0);
return p;
lose:
*p = c;
@@ -5890,7 +5893,7 @@ evalbackcmd(union node *n, struct backcmd *result)
* Expand stuff in backwards quotes.
*/
static void
-expbackq(union node *cmd, int quoted, int quotes)
+expbackq(union node *cmd, int flag)
{
struct backcmd in;
int i;
@@ -5898,7 +5901,7 @@ expbackq(union node *cmd, int quoted, int quotes)
char *p;
char *dest;
int startloc;
- int syntax = quoted ? DQSYNTAX : BASESYNTAX;
+ int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
struct stackmark smark;
INT_OFF;
@@ -5914,11 +5917,11 @@ expbackq(union node *cmd, int quoted, int quotes)
if (i == 0)
goto read;
for (;;) {
- memtodest(p, i, syntax, quotes);
+ memtodest(p, i, syntax, flag & QUOTES_ESC);
read:
if (in.fd < 0)
break;
- i = nonblock_immune_read(in.fd, buf, sizeof(buf), /*loop_on_EINTR:*/ 1);
+ i = nonblock_immune_read(in.fd, buf, sizeof(buf));
TRACE(("expbackq: read returns %d\n", i));
if (i <= 0)
break;
@@ -5938,7 +5941,7 @@ expbackq(union node *cmd, int quoted, int quotes)
STUNPUTC(dest);
expdest = dest;
- if (quoted == 0)
+ if (!(flag & EXP_QUOTED))
recordregion(startloc, dest - (char *)stackblock(), 0);
TRACE(("evalbackq: size:%d:'%.*s'\n",
(int)((dest - (char *)stackblock()) - startloc),
@@ -5952,11 +5955,10 @@ expbackq(union node *cmd, int quoted, int quotes)
* evaluate, place result in (backed up) result, adjust string position.
*/
static void
-expari(int quotes)
+expari(int flag)
{
char *p, *start;
int begoff;
- int flag;
int len;
/* ifsfree(); */
@@ -5994,16 +5996,14 @@ expari(int quotes)
removerecordregions(begoff);
- flag = p[1];
-
expdest = p;
- if (quotes)
- rmescapes(p + 2, 0);
+ if (flag & QUOTES_ESC)
+ rmescapes(p + 1, 0);
- len = cvtnum(ash_arith(p + 2));
+ len = cvtnum(ash_arith(p + 1));
- if (flag != '"')
+ if (!(flag & EXP_QUOTED))
recordregion(begoff, begoff + len, 0);
}
#endif
@@ -6031,15 +6031,13 @@ argstr(char *p, int flags, struct strlist *var_str_list)
CTLESC,
CTLVAR,
CTLBACKQ,
- CTLBACKQ | CTLQUOTE,
#if ENABLE_SH_MATH_SUPPORT
CTLENDARI,
#endif
'\0'
};
const char *reject = spclchars;
- int quotes = flags & (EXP_FULL | EXP_CASE | EXP_REDIR); /* do CTLESC */
- int breakall = flags & EXP_WORD;
+ int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
int inquotes;
size_t length;
int startloc;
@@ -6057,8 +6055,6 @@ argstr(char *p, int flags, struct strlist *var_str_list)
flags &= ~EXP_TILDE;
tilde:
q = p;
- if ((unsigned char)*q == CTLESC && (flags & EXP_QWORD))
- q++;
if (*q == '~')
p = exptilde(p, q, flags);
}
@@ -6115,19 +6111,14 @@ argstr(char *p, int flags, struct strlist *var_str_list)
case CTLENDVAR: /* ??? */
goto breakloop;
case CTLQUOTEMARK:
+ inquotes ^= EXP_QUOTED;
/* "$@" syntax adherence hack */
- if (!inquotes
- && memcmp(p, dolatstr, 4) == 0
- && ( p[4] == (char)CTLQUOTEMARK
- || (p[4] == (char)CTLENDVAR && p[5] == (char)CTLQUOTEMARK)
- )
- ) {
- p = evalvar(p + 1, flags, /* var_str_list: */ NULL) + 1;
+ if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
+ p = evalvar(p + 1, flags | inquotes, /* var_str_list: */ NULL) + 1;
goto start;
}
- inquotes = !inquotes;
addquote:
- if (quotes) {
+ if (flags & QUOTES_ESC) {
p--;
length++;
startloc++;
@@ -6136,20 +6127,30 @@ argstr(char *p, int flags, struct strlist *var_str_list)
case CTLESC:
startloc++;
length++;
+
+ /*
+ * Quoted parameter expansion pattern: remove quote
+ * unless inside inner quotes or we have a literal
+ * backslash.
+ */
+ if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
+ EXP_QPAT && *p != '\\')
+ break;
+
goto addquote;
case CTLVAR:
- p = evalvar(p, flags, var_str_list);
+ TRACE(("argstr: evalvar('%s')\n", p));
+ p = evalvar(p, flags | inquotes, var_str_list);
+ TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
goto start;
case CTLBACKQ:
- c = '\0';
- case CTLBACKQ|CTLQUOTE:
- expbackq(argbackq->n, c, quotes);
+ expbackq(argbackq->n, flags | inquotes);
argbackq = argbackq->next;
goto start;
#if ENABLE_SH_MATH_SUPPORT
case CTLENDARI:
p--;
- expari(quotes);
+ expari(flags | inquotes);
goto start;
#endif
}
@@ -6279,63 +6280,21 @@ varunset(const char *end, const char *var, const char *umsg, int varflags)
ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
}
-#if ENABLE_ASH_BASH_COMPAT
-static char *
-parse_sub_pattern(char *arg, int varflags)
-{
- char *idx, *repl = NULL;
- unsigned char c;
-
- //char *org_arg = arg;
- //bb_error_msg("arg:'%s' varflags:%x", arg, varflags);
- idx = arg;
- while (1) {
- c = *arg;
- if (!c)
- break;
- if (c == '/') {
- /* Only the first '/' seen is our separator */
- if (!repl) {
- repl = idx + 1;
- c = '\0';
- }
- }
- *idx++ = c;
- arg++;
- /*
- * Example: v='ab\c'; echo ${v/\\b/_\\_\z_}
- * The result is a_\_z_c (not a\_\_z_c)!
- *
- * Enable debug prints in this function and you'll see:
- * ash: arg:'\\b/_\\_z_' varflags:d
- * ash: pattern:'\\b' repl:'_\_z_'
- * That is, \\b is interpreted as \\b, but \\_ as \_!
- * IOW: search pattern and replace string treat backslashes
- * differently! That is the reason why we check repl below:
- */
- if (c == '\\' && *arg == '\\' && repl && !(varflags & VSQUOTE))
- arg++; /* skip both '\', not just first one */
- }
- *idx = c; /* NUL */
- //bb_error_msg("pattern:'%s' repl:'%s'", org_arg, repl);
-
- return repl;
-}
-#endif /* ENABLE_ASH_BASH_COMPAT */
-
static const char *
subevalvar(char *p, char *varname, int strloc, int subtype,
- int startloc, int varflags, int quotes, struct strlist *var_str_list)
+ int startloc, int varflags, int flag, struct strlist *var_str_list)
{
struct nodelist *saveargbackq = argbackq;
+ int quotes = flag & QUOTES_ESC;
char *startp;
char *loc;
char *rmesc, *rmescend;
char *str;
- IF_ASH_BASH_COMPAT(const char *repl = NULL;)
+ IF_ASH_BASH_COMPAT(char *repl = NULL;)
IF_ASH_BASH_COMPAT(int pos, len, orig_len;)
int saveherefd = herefd;
- int amount, workloc, resetloc;
+ int amount, resetloc;
+ IF_ASH_BASH_COMPAT(int workloc;)
int zero;
char *(*scan)(char*, char*, char*, char*, int, int);
@@ -6343,7 +6302,8 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
// p, varname, strloc, subtype, startloc, varflags, quotes);
herefd = -1;
- argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
+ argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
+ (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0),
var_str_list);
STPUTC('\0', expdest);
herefd = saveherefd;
@@ -6352,7 +6312,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
switch (subtype) {
case VSASSIGN:
- setvar(varname, startp, 0);
+ setvar0(varname, startp);
amount = startp - expdest;
STADJUST(amount, expdest);
return startp;
@@ -6400,7 +6360,15 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
len = number(loc);
}
}
- if (pos >= orig_len) {
+ if (pos < 0) {
+ /* ${VAR:$((-n)):l} starts n chars from the end */
+ pos = orig_len + pos;
+ }
+ if ((unsigned)pos >= orig_len) {
+ /* apart from obvious ${VAR:999999:l},
+ * covers ${VAR:$((-9999999)):l} - result is ""
+ * (bash-compat)
+ */
pos = 0;
len = 0;
}
@@ -6447,19 +6415,30 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
}
rmescend--;
str = (char *)stackblock() + strloc;
- preglob(str, varflags & VSQUOTE, 0);
- workloc = expdest - (char *)stackblock();
+ /*
+ * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
+ * The result is a_\_z_c (not a\_\_z_c)!
+ *
+ * The search pattern and replace string treat backslashes differently!
+ * RMESCAPE_SLASH causes preglob to work differently on the pattern
+ * and string. It's only used on the first call.
+ */
+ preglob(str, IF_ASH_BASH_COMPAT(
+ (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
+ RMESCAPE_SLASH :) 0);
#if ENABLE_ASH_BASH_COMPAT
+ workloc = expdest - (char *)stackblock();
if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
char *idx, *end;
if (!repl) {
- repl = parse_sub_pattern(str, varflags);
- //bb_error_msg("repl:'%s'", repl);
- if (!repl)
+ if ((repl=strchr(str, CTLESC)))
+ *repl++ = '\0';
+ else
repl = nullstr;
}
+ //bb_error_msg("str:'%s' repl:'%s'", str, repl);
/* If there's no pattern to match, return the expansion unmolested */
if (str[0] == '\0')
@@ -6592,13 +6571,16 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
const char *p;
int num;
int i;
- int sepq = 0;
ssize_t len = 0;
+ int sep;
+ int quoted = flags & EXP_QUOTED;
int subtype = varflags & VSTYPE;
- int quotes = flags & (EXP_FULL | EXP_CASE | EXP_REDIR);
- int quoted = varflags & VSQUOTE;
+ int discard = subtype == VSPLUS || subtype == VSLENGTH;
+ int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
int syntax = quoted ? DQSYNTAX : BASESYNTAX;
+ sep = quoted ? ((flags & EXP_FULL) << CHAR_BIT) : 0;
+
switch (*name) {
case '$':
num = rootpid;
@@ -6633,7 +6615,7 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
break;
case '@': {
char **ap;
- int sep;
+ char sepc;
if (quoted && (flags & EXP_FULL)) {
/* note: this is not meant as PEOF value */
@@ -6643,39 +6625,20 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
/* fall through */
case '*':
sep = ifsset() ? (unsigned char)(ifsval()[0]) : ' ';
- i = SIT(sep, syntax);
- if (quotes && (i == CCTL || i == CBACK))
- sepq = 1;
param:
ap = shellparam.p;
+ sepc = sep;
if (!ap)
return -1;
while ((p = *ap++) != NULL) {
- size_t partlen;
-
- partlen = strlen(p);
- len += partlen;
-
- if (!(subtype == VSPLUS || subtype == VSLENGTH))
- memtodest(p, partlen, syntax, quotes);
+ len += strtodest(p, syntax, quotes);
if (*ap && sep) {
- char *q;
-
len++;
- if (subtype == VSPLUS || subtype == VSLENGTH) {
- continue;
- }
- q = expdest;
- if (sepq)
- STPUTC(CTLESC, q);
- /* note: may put NUL despite sep != 0
- * (see sep = 1 << CHAR_BIT above) */
- STPUTC(sep, q);
- expdest = q;
+ memtodest(&sepc, 1, syntax, quotes);
}
}
- return len;
+ break;
} /* case '@' and '*' */
case '0':
case '1':
@@ -6724,13 +6687,21 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
if (!p)
return -1;
- len = strlen(p);
- if (!(subtype == VSPLUS || subtype == VSLENGTH))
- memtodest(p, len, syntax, quotes);
- return len;
+ len = strtodest(p, syntax, quotes);
+#if ENABLE_UNICODE_SUPPORT
+ if (subtype == VSLENGTH && len > 0) {
+ reinit_unicode_for_ash();
+ if (unicode_status == UNICODE_ON) {
+ STADJUST(-len, expdest);
+ discard = 0;
+ len = unicode_strlen(p);
+ }
+ }
+#endif
+ break;
}
- if (subtype == VSPLUS || subtype == VSLENGTH)
+ if (discard)
STADJUST(-len, expdest);
return len;
}
@@ -6744,7 +6715,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list)
{
char varflags;
char subtype;
- char quoted;
+ int quoted;
char easy;
char *var;
int patloc;
@@ -6753,7 +6724,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list)
varflags = (unsigned char) *p++;
subtype = varflags & VSTYPE;
- quoted = varflags & VSQUOTE;
+ quoted = flags & EXP_QUOTED;
var = p;
easy = (!quoted || (*var == '@' && shellparam.nparam));
startloc = expdest - (char *)stackblock();
@@ -6774,7 +6745,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list)
if (varlen < 0) {
argstr(
p,
- flags | (quoted ? EXP_TILDE|EXP_QWORD : EXP_TILDE|EXP_WORD),
+ flags | EXP_TILDE | EXP_WORD,
var_str_list
);
goto end;
@@ -6788,7 +6759,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list)
if (varlen < 0) {
if (subevalvar(p, var, /* strloc: */ 0,
subtype, startloc, varflags,
- /* quotes: */ 0,
+ /* quotes: */ flags & ~QUOTES_ESC,
var_str_list)
) {
varflags &= ~VSNUL;
@@ -6845,10 +6816,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list)
STPUTC('\0', expdest);
patloc = expdest - (char *)stackblock();
if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
- startloc, varflags,
- /* quotes: */ flags & (EXP_FULL | EXP_CASE | EXP_REDIR),
- var_str_list)
- ) {
+ startloc, varflags, flags, var_str_list)) {
int amount = expdest - (
(char *)stackblock() + patloc - 1
);
@@ -6867,7 +6835,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list)
unsigned char c = *p++;
if (c == CTLESC)
p++;
- else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
+ else if (c == CTLBACKQ) {
if (varlen >= 0)
argbackq = argbackq->next;
} else if (c == CTLVAR) {
@@ -7022,10 +6990,11 @@ expmeta(char *expdir, char *enddir, char *name)
struct dirent *dp;
int atend;
int matchdot;
+ int esc;
metaflag = 0;
start = name;
- for (p = name; *p; p++) {
+ for (p = name; esc = 0, *p; p += esc + 1) {
if (*p == '*' || *p == '?')
metaflag = 1;
else if (*p == '[') {
@@ -7042,15 +7011,16 @@ expmeta(char *expdir, char *enddir, char *name)
break;
}
}
- } else if (*p == '\\')
- p++;
- else if (*p == '/') {
- if (metaflag)
- goto out;
- start = p + 1;
+ } else {
+ if (*p == '\\')
+ esc++;
+ if (p[esc] == '/') {
+ if (metaflag)
+ break;
+ start = p + esc + 1;
+ }
}
}
- out:
if (metaflag == 0) { /* we've reached the end of the file name */
if (enddir != expdir)
metaflag++;
@@ -7090,7 +7060,8 @@ expmeta(char *expdir, char *enddir, char *name)
atend = 1;
} else {
atend = 0;
- *endname++ = '\0';
+ *endname = '\0';
+ endname += esc + 1;
}
matchdot = 0;
p = start;
@@ -7115,7 +7086,7 @@ expmeta(char *expdir, char *enddir, char *name)
}
closedir(dirp);
if (!atend)
- endname[-1] = '/';
+ endname[-esc - 1] = esc ? '\\' : '/';
}
static struct strlist *
@@ -7203,7 +7174,7 @@ expandmeta(struct strlist *str /*, int flag*/)
savelastp = exparg.lastp;
INT_OFF;
- p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
+ p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
{
int i = strlen(str->text);
expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
@@ -7248,6 +7219,7 @@ expandarg(union node *arg, struct arglist *arglist, int flag)
STARTSTACKSTR(expdest);
ifsfirst.next = NULL;
ifslastp = NULL;
+ TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
argstr(arg->narg.text, flag,
/* var_str_list: */ arglist ? arglist->list : NULL);
p = _STPUTC('\0', expdest);
@@ -7256,6 +7228,7 @@ expandarg(union node *arg, struct arglist *arglist, int flag)
return; /* here document expanded */
}
p = grabstackstr(p);
+ TRACE(("expandarg: p:'%s'\n", p));
exparg.lastp = &exparg.list;
/*
* TODO - EXP_REDIR
@@ -7266,8 +7239,10 @@ expandarg(union node *arg, struct arglist *arglist, int flag)
exparg.lastp = &exparg.list;
expandmeta(exparg.list /*, flag*/);
} else {
- if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
+ if (flag & EXP_REDIR) { /*XXX - for now, just remove escapes */
rmescapes(p, 0);
+ TRACE(("expandarg: rmescapes:'%s'\n", p));
+ }
sp = stzalloc(sizeof(*sp));
sp->text = p;
*exparg.lastp = sp;
@@ -7289,7 +7264,7 @@ static void
expandhere(union node *arg, int fd)
{
herefd = fd;
- expandarg(arg, (struct arglist *)NULL, 0);
+ expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
full_write(fd, stackblock(), expdest - (char *)stackblock());
}
@@ -7299,7 +7274,7 @@ expandhere(union node *arg, int fd)
static int
patmatch(char *pattern, const char *string)
{
- return pmatch(preglob(pattern, 0, 0), string);
+ return pmatch(preglob(pattern, 0), string);
}
/*
@@ -7752,36 +7727,40 @@ changepath(const char *new)
clearcmdentry(firstchange);
builtinloc = idx_bltin;
}
-
-#define TEOF 0
-#define TNL 1
-#define TREDIR 2
-#define TWORD 3
-#define TSEMI 4
-#define TBACKGND 5
-#define TAND 6
-#define TOR 7
-#define TPIPE 8
-#define TLP 9
-#define TRP 10
-#define TENDCASE 11
-#define TENDBQUOTE 12
-#define TNOT 13
-#define TCASE 14
-#define TDO 15
-#define TDONE 16
-#define TELIF 17
-#define TELSE 18
-#define TESAC 19
-#define TFI 20
-#define TFOR 21
-#define TIF 22
-#define TIN 23
-#define TTHEN 24
-#define TUNTIL 25
-#define TWHILE 26
-#define TBEGIN 27
-#define TEND 28
+enum {
+ TEOF,
+ TNL,
+ TREDIR,
+ TWORD,
+ TSEMI,
+ TBACKGND,
+ TAND,
+ TOR,
+ TPIPE,
+ TLP,
+ TRP,
+ TENDCASE,
+ TENDBQUOTE,
+ TNOT,
+ TCASE,
+ TDO,
+ TDONE,
+ TELIF,
+ TELSE,
+ TESAC,
+ TFI,
+ TFOR,
+#if ENABLE_ASH_BASH_COMPAT
+ TFUNCTION,
+#endif
+ TIF,
+ TIN,
+ TTHEN,
+ TUNTIL,
+ TWHILE,
+ TBEGIN,
+ TEND
+};
typedef smallint token_id_t;
/* first char is indicating which tokens mark the end of a list */
@@ -7810,6 +7789,9 @@ static const char *const tokname_array[] = {
"\1esac",
"\1fi",
"\0for",
+#if ENABLE_ASH_BASH_COMPAT
+ "\0function",
+#endif
"\0if",
"\0in",
"\1then",
@@ -7838,14 +7820,15 @@ findkwd(const char *s)
* Locate and print what a word is...
*/
static int
-describe_command(char *command, int describe_command_verbose)
+describe_command(char *command, const char *path, int describe_command_verbose)
{
struct cmdentry entry;
struct tblentry *cmdp;
#if ENABLE_ASH_ALIAS
const struct alias *ap;
#endif
- const char *path = pathval();
+
+ path = path ? path : pathval();
if (describe_command_verbose) {
out1str(command);
@@ -7945,7 +7928,7 @@ typecmd(int argc UNUSED_PARAM, char **argv)
verbose = 0;
}
while (argv[i]) {
- err |= describe_command(argv[i++], verbose);
+ err |= describe_command(argv[i++], NULL, verbose);
}
return err;
}
@@ -7959,6 +7942,7 @@ commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
VERIFY_BRIEF = 1,
VERIFY_VERBOSE = 2,
} verify = 0;
+ const char *path = NULL;
while ((c = nextopt("pvV")) != '\0')
if (c == 'V')
@@ -7969,9 +7953,11 @@ commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
else if (c != 'p')
abort();
#endif
+ else
+ path = bb_default_path;
/* Mimic bash: just "command -v" doesn't complain, it's a nop */
if (verify && (*argptr != NULL)) {
- return describe_command(*argptr, verify - VERIFY_BRIEF);
+ return describe_command(*argptr, path, verify - VERIFY_BRIEF);
}
return 0;
@@ -7991,7 +7977,7 @@ static char *funcstring; /* block to allocate strings from */
#define EV_TESTED 02 /* exit status is checked; ignore -e flag */
#define EV_BACKCMD 04 /* command executing within back quotes */
-static const uint8_t nodesize[N_NUMBER] = {
+static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
[NCMD ] = SHELL_ALIGN(sizeof(struct ncmd)),
[NPIPE ] = SHELL_ALIGN(sizeof(struct npipe)),
[NREDIR ] = SHELL_ALIGN(sizeof(struct nredir)),
@@ -8444,7 +8430,7 @@ evaltree(union node *n, int flags)
n->nbinary.ch1,
(flags | ((is_or >> 1) - 1)) & EV_TESTED
);
- if (!exitstatus == is_or)
+ if ((!exitstatus) == is_or)
break;
if (!evalskip) {
n = n->nbinary.ch2;
@@ -8552,7 +8538,7 @@ evalfor(union node *n, int flags)
arglist.list = NULL;
arglist.lastp = &arglist.list;
for (argp = n->nfor.args; argp; argp = argp->narg.next) {
- expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
+ expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
/* XXX */
if (evalskip)
goto out;
@@ -8563,7 +8549,7 @@ evalfor(union node *n, int flags)
loopnest++;
flags &= EV_TESTED;
for (sp = arglist.list; sp; sp = sp->next) {
- setvar(n->nfor.var, sp->text, 0);
+ setvar0(n->nfor.var, sp->text);
evaltree(n->nfor.body, flags);
if (evalskip) {
if (evalskip == SKIPCONT && --skipcount <= 0) {
@@ -8664,9 +8650,21 @@ expredir(union node *n)
case NCLOBBER:
case NAPPEND:
expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
+ TRACE(("expredir expanded to '%s'\n", fn.list->text));
#if ENABLE_ASH_BASH_COMPAT
store_expfname:
#endif
+#if 0
+// By the design of stack allocator, the loop of this kind:
+// while true; do while true; do break; done </dev/null; done
+// will look like a memory leak: ash plans to free expfname's
+// of "/dev/null" as soon as it finishes running the loop
+// (in this case, never).
+// This "fix" is wrong:
+ if (redir->nfile.expfname)
+ stunalloc(redir->nfile.expfname);
+// It results in corrupted state of stacked allocations.
+#endif
redir->nfile.expfname = fn.list->text;
break;
case NFROMFD:
@@ -8776,8 +8774,8 @@ setinteractive(int on)
if (!did_banner) {
/* note: ash and hush share this string */
out1fmt("\n\n%s %s\n"
- "Enter 'help' for a list of built-in commands."
- "\n\n",
+ IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
+ "\n",
bb_banner,
"built-in shell (ash)"
);
@@ -8892,14 +8890,15 @@ parse_command_args(char **argv, const char **path)
for (;;) {
cp = *++argv;
if (!cp)
- return 0;
+ return NULL;
if (*cp++ != '-')
break;
c = *cp++;
if (!c)
break;
if (c == '-' && !*cp) {
- argv++;
+ if (!*++argv)
+ return NULL;
break;
}
do {
@@ -8909,7 +8908,7 @@ parse_command_args(char **argv, const char **path)
break;
default:
/* run 'typecmd' for other options */
- return 0;
+ return NULL;
}
c = *cp++;
} while (c);
@@ -8922,7 +8921,8 @@ parse_command_args(char **argv, const char **path)
* Make a variable a local variable. When a variable is made local, it's
* value and flags are saved in a localvar structure. The saved values
* will be restored when the shell function returns. We handle the name
- * "-" as a special case.
+ * "-" as a special case: it makes changes to "set +-options" local
+ * (options will be restored on return from the function).
*/
static void
mklocal(char *name)
@@ -8930,21 +8930,37 @@ mklocal(char *name)
struct localvar *lvp;
struct var **vpp;
struct var *vp;
+ char *eq = strchr(name, '=');
INT_OFF;
- lvp = ckzalloc(sizeof(struct localvar));
+ /* Cater for duplicate "local". Examples:
+ * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
+ * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
+ */
+ lvp = localvars;
+ while (lvp) {
+ if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
+ if (eq)
+ setvareq(name, 0);
+ /* else:
+ * it's a duplicate "local VAR" declaration, do nothing
+ */
+ return;
+ }
+ lvp = lvp->next;
+ }
+
+ lvp = ckzalloc(sizeof(*lvp));
if (LONE_DASH(name)) {
char *p;
p = ckmalloc(sizeof(optlist));
lvp->text = memcpy(p, optlist, sizeof(optlist));
vp = NULL;
} else {
- char *eq;
-
vpp = hashvar(name);
vp = *findvar(vpp, name);
- eq = strchr(name, '=');
if (vp == NULL) {
+ /* variable did not exist yet */
if (eq)
setvareq(name, VSTRFIXED);
else
@@ -8954,9 +8970,15 @@ mklocal(char *name)
} else {
lvp->text = vp->var_text;
lvp->flags = vp->flags;
+ /* make sure neither "struct var" nor string gets freed
+ * during (un)setting:
+ */
vp->flags |= VSTRFIXED|VTEXTFIXED;
if (eq)
setvareq(name, 0);
+ else
+ /* "local VAR" unsets VAR: */
+ setvar0(name, NULL);
}
}
lvp->vp = vp;
@@ -8973,6 +8995,9 @@ localcmd(int argc UNUSED_PARAM, char **argv)
{
char *name;
+ if (!funcnest)
+ ash_msg_and_raise_error("not in a function");
+
argv = argptr;
while ((name = *argv++) != NULL) {
mklocal(name);
@@ -9027,9 +9052,12 @@ static int exportcmd(int, char **) FAST_FUNC;
#if ENABLE_ASH_GETOPTS
static int getoptscmd(int, char **) FAST_FUNC;
#endif
-#if !ENABLE_FEATURE_SH_EXTRA_QUIET
+#if ENABLE_ASH_HELP
static int helpcmd(int, char **) FAST_FUNC;
#endif
+#if MAX_HISTORY
+static int historycmd(int, char **) FAST_FUNC;
+#endif
#if ENABLE_SH_MATH_SUPPORT
static int letcmd(int, char **) FAST_FUNC;
#endif
@@ -9100,9 +9128,12 @@ static const struct builtincmd builtintab[] = {
{ BUILTIN_REGULAR "getopts" , getoptscmd },
#endif
{ BUILTIN_NOSPEC "hash" , hashcmd },
-#if !ENABLE_FEATURE_SH_EXTRA_QUIET
+#if ENABLE_ASH_HELP
{ BUILTIN_NOSPEC "help" , helpcmd },
#endif
+#if MAX_HISTORY
+ { BUILTIN_NOSPEC "history" , historycmd },
+#endif
#if JOBS
{ BUILTIN_REGULAR "jobs" , jobscmd },
{ BUILTIN_REGULAR "kill" , killcmd },
@@ -9302,11 +9333,11 @@ evalcommand(union node *cmd, int flags)
/* Now locate the command. */
if (argc) {
- const char *oldpath;
int cmd_flag = DO_ERR;
-
+#if ENABLE_ASH_CMDCMD
+ const char *oldpath = path + 5;
+#endif
path += 5;
- oldpath = path;
for (;;) {
find_command(argv[0], &cmdentry, cmd_flag, path);
if (cmdentry.cmdtype == CMDUNKNOWN) {
@@ -9409,7 +9440,7 @@ evalcommand(union node *cmd, int flags)
if (evalbltin(cmdentry.u.cmd, argc, argv)) {
int exit_status;
int i = exception_type;
- if (i == EXEXIT)
+ if (i == EXEXIT || i == EXEXEC)
goto raise;
exit_status = 2;
if (i == EXINT)
@@ -9432,7 +9463,6 @@ evalcommand(union node *cmd, int flags)
if (evalfun(cmdentry.u.func, argc, argv, flags))
goto raise;
break;
-
} /* switch */
out:
@@ -9442,7 +9472,7 @@ evalcommand(union node *cmd, int flags)
* '_' in 'vi' command mode during line editing...
* However I implemented that within libedit itself.
*/
- setvar("_", lastarg, 0);
+ setvar0("_", lastarg);
}
popstackmark(&smark);
}
@@ -9628,7 +9658,7 @@ preadfd(void)
#if ENABLE_FEATURE_EDITING
retry:
if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
- nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1, /*loop_on_EINTR:*/ 1);
+ nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
else {
int timeout = -1;
# if ENABLE_ASH_IDLE_TIMEOUT
@@ -9644,11 +9674,7 @@ preadfd(void)
# if ENABLE_FEATURE_TAB_COMPLETION
line_input_state->path_lookup = pathval();
# endif
- /* Unicode support should be activated even if LANG is set
- * _during_ shell execution, not only if it was set when
- * shell was started. Therefore, re-check LANG every time:
- */
- reinit_unicode(lookupvar("LANG"));
+ reinit_unicode_for_ash();
nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
if (nr == 0) {
/* Ctrl+C pressed */
@@ -9667,14 +9693,14 @@ preadfd(void)
}
# if ENABLE_ASH_IDLE_TIMEOUT
else if (errno == EAGAIN && timeout > 0) {
- printf("\007timed out waiting for input: auto-logout\n");
+ puts("\007timed out waiting for input: auto-logout");
exitshell();
}
# endif
}
}
#else
- nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1, /*loop_on_EINTR:*/ 1);
+ nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
#endif
#if 0 /* disabled: nonblock_immune_read() handles this problem */
@@ -10019,10 +10045,8 @@ setinputstring(char *string)
#if ENABLE_ASH_MAIL
-#define MAXMBOXES 10
-
-/* times of mailboxes */
-static time_t mailtime[MAXMBOXES];
+/* Hash of mtimes of mailboxes */
+static unsigned mailtime_hash;
/* Set if MAIL or MAILPATH is changed. */
static smallint mail_var_path_changed;
@@ -10038,13 +10062,14 @@ chkmail(void)
const char *mpath;
char *p;
char *q;
- time_t *mtp;
+ unsigned new_hash;
struct stackmark smark;
struct stat statb;
setstackmark(&smark);
mpath = mpathset() ? mpathval() : mailval();
- for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
+ new_hash = 0;
+ for (;;) {
p = path_advance(&mpath, nullstr);
if (p == NULL)
break;
@@ -10058,16 +10083,15 @@ chkmail(void)
#endif
q[-1] = '\0'; /* delete trailing '/' */
if (stat(p, &statb) < 0) {
- *mtp = 0;
continue;
}
- if (!mail_var_path_changed && statb.st_mtime != *mtp) {
- fprintf(
- stderr, "%s\n",
- pathopt ? pathopt : "you have mail"
- );
- }
- *mtp = statb.st_mtime;
+ /* Very simplistic "hash": just a sum of all mtimes */
+ new_hash += (unsigned)statb.st_mtime;
+ }
+ if (!mail_var_path_changed && mailtime_hash != new_hash) {
+ if (mailtime_hash != 0)
+ out2str("you have mail\n");
+ mailtime_hash = new_hash;
}
mail_var_path_changed = 0;
popstackmark(&smark);
@@ -10339,9 +10363,11 @@ getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *opt
char c = '?';
int done = 0;
int err = 0;
- char s[12];
+ char sbuf[2];
char **optnext;
+ sbuf[1] = '\0';
+
if (*param_optind < 1)
return 1;
optnext = optfirst + *param_optind - 1;
@@ -10368,9 +10394,9 @@ getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *opt
for (q = optstr; *q != c;) {
if (*q == '\0') {
if (optstr[0] == ':') {
- s[0] = c;
- s[1] = '\0';
- err |= setvarsafe("OPTARG", s, 0);
+ sbuf[0] = c;
+ /*sbuf[1] = '\0'; - already is */
+ err |= setvarsafe("OPTARG", sbuf, 0);
} else {
fprintf(stderr, "Illegal option -%c\n", c);
unsetvar("OPTARG");
@@ -10385,9 +10411,9 @@ getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *opt
if (*++q == ':') {
if (*p == '\0' && (p = *optnext) == NULL) {
if (optstr[0] == ':') {
- s[0] = c;
- s[1] = '\0';
- err |= setvarsafe("OPTARG", s, 0);
+ sbuf[0] = c;
+ /*sbuf[1] = '\0'; - already is */
+ err |= setvarsafe("OPTARG", sbuf, 0);
c = ':';
} else {
fprintf(stderr, "No arg for -%c option\n", c);
@@ -10406,11 +10432,10 @@ getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *opt
out:
*optoff = p ? p - *(optnext - 1) : -1;
*param_optind = optnext - optfirst + 1;
- fmtstr(s, sizeof(s), "%d", *param_optind);
- err |= setvarsafe("OPTIND", s, VNOFUNC);
- s[0] = c;
- s[1] = '\0';
- err |= setvarsafe(optvar, s, 0);
+ err |= setvarsafe("OPTIND", itoa(*param_optind), VNOFUNC);
+ sbuf[0] = c;
+ /*sbuf[1] = '\0'; - already is */
+ err |= setvarsafe(optvar, sbuf, 0);
if (err) {
*param_optind = 1;
*optoff = -1;
@@ -10463,7 +10488,6 @@ struct heredoc {
};
static smallint tokpushback; /* last token pushed back */
-static smallint parsebackquote; /* nonzero if we are inside backquotes */
static smallint quoteflag; /* set if (part of) last token was quoted */
static token_id_t lasttoken; /* last token read (integer id Txxx) */
static struct heredoc *heredoclist; /* list of here documents to read */
@@ -10508,7 +10532,7 @@ static union node *andor(void);
static union node *pipeline(void);
static union node *parse_command(void);
static void parseheredoc(void);
-static char peektoken(void);
+static int peektoken(void);
static int readtoken(void);
static union node *
@@ -10517,11 +10541,27 @@ list(int nlflag)
union node *n1, *n2, *n3;
int tok;
- checkkwd = CHKNL | CHKKWD | CHKALIAS;
- if (nlflag == 2 && peektoken())
- return NULL;
n1 = NULL;
for (;;) {
+ switch (peektoken()) {
+ case TNL:
+ if (!(nlflag & 1))
+ break;
+ parseheredoc();
+ return n1;
+
+ case TEOF:
+ if (!n1 && (nlflag & 1))
+ n1 = NODE_EOF;
+ parseheredoc();
+ return n1;
+ }
+
+ checkkwd = CHKNL | CHKKWD | CHKALIAS;
+ if (nlflag == 2 && tokname_array[peektoken()][0])
+ return n1;
+ nlflag |= 2;
+
n2 = andor();
tok = readtoken();
if (tok == TBACKGND) {
@@ -10547,30 +10587,15 @@ list(int nlflag)
n1 = n3;
}
switch (tok) {
+ case TNL:
+ case TEOF:
+ tokpushback = 1;
+ /* fall through */
case TBACKGND:
case TSEMI:
- tok = readtoken();
- /* fall through */
- case TNL:
- if (tok == TNL) {
- parseheredoc();
- if (nlflag == 1)
- return n1;
- } else {
- tokpushback = 1;
- }
- checkkwd = CHKNL | CHKKWD | CHKALIAS;
- if (peektoken())
- return n1;
break;
- case TEOF:
- if (heredoclist)
- parseheredoc();
- else
- pungetc(); /* push back EOF on input */
- return n1;
default:
- if (nlflag == 1)
+ if ((nlflag & 1))
raise_error_unexpected_syntax(-1);
tokpushback = 1;
return n1;
@@ -10745,6 +10770,7 @@ simplecmd(void)
int savecheckkwd;
#if ENABLE_ASH_BASH_COMPAT
smallint double_brackets_flag = 0;
+ smallint function_flag = 0;
#endif
args = NULL;
@@ -10761,6 +10787,11 @@ simplecmd(void)
t = readtoken();
switch (t) {
#if ENABLE_ASH_BASH_COMPAT
+ case TFUNCTION:
+ if (peektoken() != TWORD)
+ raise_error_unexpected_syntax(TWORD);
+ function_flag = 1;
+ break;
case TAND: /* "&&" */
case TOR: /* "||" */
if (!double_brackets_flag) {
@@ -10789,6 +10820,29 @@ simplecmd(void)
app = &n->narg.next;
savecheckkwd = 0;
}
+#if ENABLE_ASH_BASH_COMPAT
+ if (function_flag) {
+ checkkwd = CHKNL | CHKKWD;
+ switch (peektoken()) {
+ case TBEGIN:
+ case TIF:
+ case TCASE:
+ case TUNTIL:
+ case TWHILE:
+ case TFOR:
+ goto do_func;
+ case TLP:
+ function_flag = 0;
+ break;
+ case TWORD:
+ if (strcmp("[[", wordtext) == 0)
+ goto do_func;
+ /* fall through */
+ default:
+ raise_error_unexpected_syntax(-1);
+ }
+ }
+#endif
break;
case TREDIR:
*rpp = n = redirnode;
@@ -10796,6 +10850,7 @@ simplecmd(void)
parsefname(); /* read name of redirection file */
break;
case TLP:
+ IF_ASH_BASH_COMPAT(do_func:)
if (args && app == &args->narg.next
&& !vars && !redir
) {
@@ -10803,7 +10858,7 @@ simplecmd(void)
const char *name;
/* We have a function */
- if (readtoken() != TRP)
+ if (IF_ASH_BASH_COMPAT(!function_flag &&) readtoken() != TRP)
raise_error_unexpected_syntax(TRP);
name = n->narg.text;
if (!goodname(name)
@@ -10816,6 +10871,7 @@ simplecmd(void)
n->narg.next = parse_command();
return n;
}
+ IF_ASH_BASH_COMPAT(function_flag = 0;)
/* fall through */
default:
tokpushback = 1;
@@ -10898,7 +10954,7 @@ parse_command(void)
n1 = stzalloc(sizeof(struct nfor));
n1->type = NFOR;
n1->nfor.var = wordtext;
- checkkwd = CHKKWD | CHKALIAS;
+ checkkwd = CHKNL | CHKKWD | CHKALIAS;
if (readtoken() == TIN) {
app = &ap;
while (readtoken() == TWORD) {
@@ -10925,7 +10981,7 @@ parse_command(void)
* Newline or semicolon here is optional (but note
* that the original Bourne shell only allowed NL).
*/
- if (lasttoken != TNL && lasttoken != TSEMI)
+ if (lasttoken != TSEMI)
tokpushback = 1;
}
checkkwd = CHKNL | CHKKWD | CHKALIAS;
@@ -10944,10 +11000,8 @@ parse_command(void)
/*n2->narg.next = NULL; - stzalloc did it */
n2->narg.text = wordtext;
n2->narg.backquote = backquotelist;
- do {
- checkkwd = CHKKWD | CHKALIAS;
- } while (readtoken() == TNL);
- if (lasttoken != TIN)
+ checkkwd = CHKNL | CHKKWD | CHKALIAS;
+ if (readtoken() != TIN)
raise_error_unexpected_syntax(TIN);
cpp = &n1->ncase.cases;
next_case:
@@ -10998,6 +11052,7 @@ parse_command(void)
n1 = list(0);
t = TEND;
break;
+ IF_ASH_BASH_COMPAT(case TFUNCTION:)
case TWORD:
case TREDIR:
tokpushback = 1;
@@ -11116,19 +11171,6 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
IF_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
-#if __GNUC__
- /* Avoid longjmp clobbering */
- (void) &out;
- (void) &quotef;
- (void) &dblquote;
- (void) &varnest;
- (void) &arinest;
- (void) &parenlevel;
- (void) &dqvarnest;
- (void) &oldstyle;
- (void) &prevsyntax;
- (void) &syntax;
-#endif
startlinno = g_parsefile->linno;
bqlist = NULL;
quotef = 0;
@@ -11198,11 +11240,9 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
&& c != '$'
&& (c != '"' || eofmark != NULL)
) {
- USTPUTC(CTLESC, out);
USTPUTC('\\', out);
}
- if (SIT(c, SQSYNTAX) == CCTL)
- USTPUTC(CTLESC, out);
+ USTPUTC(CTLESC, out);
USTPUTC(c, out);
quotef = 1;
}
@@ -11220,9 +11260,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
goto quotemark;
case CENDQUOTE:
IF_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
- if (eofmark != NULL && arinest == 0
- && varnest == 0
- ) {
+ if (eofmark != NULL && varnest == 0) {
USTPUTC(c, out);
} else {
if (dqvarnest == 0) {
@@ -11256,10 +11294,9 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
parenlevel--;
} else {
if (pgetc() == ')') {
+ c = CTLENDARI;
if (--arinest == 0) {
syntax = prevsyntax;
- dblquote = (syntax == DQSYNTAX);
- c = CTLENDARI;
}
} else {
/*
@@ -11301,7 +11338,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
if (syntax == ARISYNTAX)
raise_error_syntax("missing '))'");
#endif
- if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
+ if (syntax != BASESYNTAX && eofmark == NULL)
raise_error_syntax("unterminated quoted string");
if (varnest != 0) {
startlinno = g_parsefile->linno;
@@ -11463,7 +11500,7 @@ parsesub: {
|| (c != '(' && c != '{' && !is_name(c) && !is_special(c))
) {
#if ENABLE_ASH_BASH_COMPAT
- if (c == '\'')
+ if (syntax != DQSYNTAX && c == '\'')
bash_dollar_squote = 1;
else
#endif
@@ -11578,12 +11615,10 @@ parsesub: {
do_pungetc:
pungetc();
}
- if (dblquote || arinest)
- flags |= VSQUOTE;
((unsigned char *)stackblock())[typeloc] = subtype | flags;
if (subtype != VSNORMAL) {
varnest++;
- if (dblquote || arinest) {
+ if (dblquote) {
dqvarnest++;
}
}
@@ -11599,38 +11634,22 @@ parsesub: {
*/
parsebackq: {
struct nodelist **nlpp;
- smallint savepbq;
union node *n;
- char *volatile str;
- struct jmploc jmploc;
- struct jmploc *volatile savehandler;
+ char *str;
size_t savelen;
smallint saveprompt = 0;
-#ifdef __GNUC__
- (void) &saveprompt;
-#endif
- savepbq = parsebackquote;
- if (setjmp(jmploc.loc)) {
- free(str);
- parsebackquote = 0;
- exception_handler = savehandler;
- longjmp(exception_handler->loc, 1);
- }
- INT_OFF;
str = NULL;
savelen = out - (char *)stackblock();
if (savelen > 0) {
- str = ckmalloc(savelen);
+ str = alloca(savelen);
memcpy(str, stackblock(), savelen);
}
- savehandler = exception_handler;
- exception_handler = &jmploc;
- INT_ON;
if (oldstyle) {
/* We must read until the closing backquote, giving special
- treatment to some slashes, and then push the string and
- reread it as input, interpreting it normally. */
+ * treatment to some slashes, and then push the string and
+ * reread it as input, interpreting it normally.
+ */
char *pout;
size_t psavelen;
char *pstr;
@@ -11696,7 +11715,6 @@ parsebackq: {
nlpp = &(*nlpp)->next;
*nlpp = stzalloc(sizeof(**nlpp));
/* (*nlpp)->next = NULL; - stzalloc did it */
- parsebackquote = oldstyle;
if (oldstyle) {
saveprompt = doprompt;
@@ -11725,17 +11743,8 @@ parsebackq: {
if (str) {
memcpy(out, str, savelen);
STADJUST(savelen, out);
- INT_OFF;
- free(str);
- str = NULL;
- INT_ON;
}
- parsebackquote = savepbq;
- exception_handler = savehandler;
- if (arinest || dblquote)
- USTPUTC(CTLBACKQ | CTLQUOTE, out);
- else
- USTPUTC(CTLBACKQ, out);
+ USTPUTC(CTLBACKQ, out);
if (oldstyle)
goto parsebackq_oldreturn;
goto parsebackq_newreturn;
@@ -11749,22 +11758,11 @@ parsearith: {
if (++arinest == 1) {
prevsyntax = syntax;
syntax = ARISYNTAX;
- USTPUTC(CTLARI, out);
- if (dblquote)
- USTPUTC('"', out);
- else
- USTPUTC(' ', out);
- } else {
- /*
- * we collapse embedded arithmetic expansion to
- * parenthesis, which should be equivalent
- */
- USTPUTC('(', out);
}
+ USTPUTC(CTLARI, out);
goto parsearith_return;
}
#endif
-
} /* end of readtoken */
/*
@@ -11935,6 +11933,7 @@ static int
readtoken(void)
{
int t;
+ int kwd = checkkwd;
#if DEBUG
smallint alreadyseen = tokpushback;
#endif
@@ -11948,7 +11947,7 @@ readtoken(void)
/*
* eat newlines
*/
- if (checkkwd & CHKNL) {
+ if (kwd & CHKNL) {
while (t == TNL) {
parseheredoc();
t = xxreadtoken();
@@ -11962,7 +11961,7 @@ readtoken(void)
/*
* check for keywords
*/
- if (checkkwd & CHKKWD) {
+ if (kwd & CHKKWD) {
const char *const *pp;
pp = findkwd(wordtext);
@@ -11996,14 +11995,14 @@ readtoken(void)
return t;
}
-static char
+static int
peektoken(void)
{
int t;
t = readtoken();
tokpushback = 1;
- return tokname_array[t][0];
+ return t;
}
/*
@@ -12013,18 +12012,12 @@ peektoken(void)
static union node *
parsecmd(int interact)
{
- int t;
-
tokpushback = 0;
+ checkkwd = 0;
+ heredoclist = 0;
doprompt = interact;
setprompt_if(doprompt, doprompt);
needprompt = 0;
- t = readtoken();
- if (t == TEOF)
- return NODE_EOF;
- if (t == TNL)
- return NULL;
- tokpushback = 1;
return list(1);
}
@@ -12075,7 +12068,7 @@ expandstr(const char *ps)
n.narg.text = wordtext;
n.narg.backquote = backquotelist;
- expandarg(&n, NULL, 0);
+ expandarg(&n, NULL, EXP_QUOTED);
return stackblock();
}
#endif
@@ -12157,7 +12150,7 @@ cmdloop(int top)
setstackmark(&smark);
#if JOBS
if (doing_jobctl)
- showjobs(stderr, SHOW_CHANGED);
+ showjobs(SHOW_CHANGED|SHOW_STDERR);
#endif
inter = 0;
if (iflag && top) {
@@ -12254,8 +12247,10 @@ dotcmd(int argc, char **argv)
/* "false; . empty_file; echo $?" should print 0, not 1: */
exitstatus = 0;
+ /* This aborts if file isn't found, which is POSIXly correct.
+ * bash returns exitcode 1 instead.
+ */
fullname = find_dot_file(argv[1]);
-
argv += 2;
argc -= 2;
if (argc) { /* argc > 0, argv[0] != NULL */
@@ -12265,6 +12260,9 @@ dotcmd(int argc, char **argv)
shellparam.p = argv;
};
+ /* This aborts if file can't be opened, which is POSIXly correct.
+ * bash returns exitcode 1 instead.
+ */
setinputfile(fullname, INPUT_PUSH_FILE);
commandname = fullname;
cmdloop(0);
@@ -12572,10 +12570,7 @@ trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
/* ============ Builtins */
-#if !ENABLE_FEATURE_SH_EXTRA_QUIET
-/*
- * Lists available builtins
- */
+#if ENABLE_ASH_HELP
static int FAST_FUNC
helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
{
@@ -12593,7 +12588,7 @@ helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
col = 0;
}
}
-#if ENABLE_FEATURE_SH_STANDALONE
+# if ENABLE_FEATURE_SH_STANDALONE
{
const char *a = applet_names;
while (*a) {
@@ -12602,14 +12597,24 @@ helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
out1fmt("\n");
col = 0;
}
- a += strlen(a) + 1;
+ while (*a++ != '\0')
+ continue;
}
}
-#endif
+# endif
out1fmt("\n\n");
return EXIT_SUCCESS;
}
-#endif /* FEATURE_SH_EXTRA_QUIET */
+#endif
+
+#if MAX_HISTORY
+static int FAST_FUNC
+historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
+{
+ show_history(line_input_state);
+ return EXIT_SUCCESS;
+}
+#endif
/*
* The export and readonly commands.
@@ -12621,18 +12626,27 @@ exportcmd(int argc UNUSED_PARAM, char **argv)
char *name;
const char *p;
char **aptr;
- int flag = argv[0][0] == 'r' ? VREADONLY : VEXPORT;
- int mask = ~0;
- int nopt;
- while ((nopt = nextopt("np"))) {
- if (nopt == 'n') {
- mask = ~flag;
- } else { /* p */
- break;
- }
+ char opt;
+ int flag;
+ int flag_off;
+
+ /* "readonly" in bash accepts, but ignores -n.
+ * We do the same: it saves a conditional in nextopt's param.
+ */
+ flag_off = 0;
+ while ((opt = nextopt("np")) != '\0') {
+ if (opt == 'n')
+ flag_off = VEXPORT;
}
+ flag = VEXPORT;
+ if (argv[0][0] == 'r') {
+ flag = VREADONLY;
+ flag_off = 0; /* readonly ignores -n */
+ }
+ flag_off = ~flag_off;
- if (nopt != 'p') {
+ /*if (opt_p_not_specified) - bash doesnt check this. Try "export -p NAME" */
+ {
aptr = argptr;
name = *aptr;
if (name) {
@@ -12643,17 +12657,19 @@ exportcmd(int argc UNUSED_PARAM, char **argv)
} else {
vp = *findvar(hashvar(name), name);
if (vp) {
- vp->flags |= flag;
- vp->flags &= mask;
+ vp->flags = ((vp->flags | flag) & flag_off);
continue;
}
}
- setvar(name, p, flag);
- setvar(name, p, flag & mask);
+ setvar(name, p, (flag & flag_off));
} while ((name = *++aptr) != NULL);
return 0;
}
}
+
+ /* No arguments. Show the list of exported or readonly vars.
+ * -n is ignored.
+ */
showvars(argv[0], flag, 0);
return 0;
}
@@ -12715,7 +12731,7 @@ timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
const unsigned char *p;
struct tms buf;
- clk_tck = sysconf(_SC_CLK_TCK);
+ clk_tck = bb_clk_tck();
times(&buf);
p = timescmd_str;
@@ -12810,7 +12826,7 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
* to jump out of it.
*/
INT_OFF;
- r = shell_builtin_read(setvar2,
+ r = shell_builtin_read(setvar0,
argptr,
bltinlookup("IFS"), /* can be NULL */
read_flags,
@@ -12828,21 +12844,11 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
}
static int FAST_FUNC
-umaskcmd(int argc UNUSED_PARAM, char **argv)
-{
- static const char permuser[3] ALIGN1 = "ugo";
- static const char permmode[3] ALIGN1 = "rwx";
- static const short permmask[] ALIGN2 = {
- S_IRUSR, S_IWUSR, S_IXUSR,
- S_IRGRP, S_IWGRP, S_IXGRP,
- S_IROTH, S_IWOTH, S_IXOTH
- };
-
- /* TODO: use bb_parse_mode() instead */
+umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
+{
+ static const char permuser[3] ALIGN1 = "ogu";
- char *ap;
mode_t mask;
- int i;
int symbolic_mode = 0;
while (nextopt("S") != '\0') {
@@ -12854,45 +12860,43 @@ umaskcmd(int argc UNUSED_PARAM, char **argv)
umask(mask);
INT_ON;
- ap = *argptr;
- if (ap == NULL) {
+ if (*argptr == NULL) {
if (symbolic_mode) {
- char buf[18];
+ char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
char *p = buf;
+ int i;
- for (i = 0; i < 3; i++) {
- int j;
-
+ i = 2;
+ for (;;) {
+ *p++ = ',';
*p++ = permuser[i];
*p++ = '=';
- for (j = 0; j < 3; j++) {
- if ((mask & permmask[3 * i + j]) == 0) {
- *p++ = permmode[j];
- }
- }
- *p++ = ',';
+ /* mask is 0..0uuugggooo. i=2 selects uuu bits */
+ if (!(mask & 0400)) *p++ = 'r';
+ if (!(mask & 0200)) *p++ = 'w';
+ if (!(mask & 0100)) *p++ = 'x';
+ mask <<= 3;
+ if (--i < 0)
+ break;
}
- *--p = 0;
- puts(buf);
+ *p = '\0';
+ puts(buf + 1);
} else {
- out1fmt("%.4o\n", mask);
+ out1fmt("%04o\n", mask);
}
} else {
- if (isdigit((unsigned char) *ap)) {
- mask = 0;
- do {
- if (*ap >= '8' || *ap < '0')
- ash_msg_and_raise_error(msg_illnum, argv[1]);
- mask = (mask << 3) + (*ap - '0');
- } while (*++ap != '\0');
- umask(mask);
- } else {
- mask = ~mask & 0777;
- if (!bb_parse_mode(ap, &mask)) {
- ash_msg_and_raise_error("illegal mode: %s", ap);
- }
- umask(~mask & 0777);
- }
+ char *modestr = *argptr;
+ /* numeric umasks are taken as-is */
+ /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
+ if (!isdigit(modestr[0]))
+ mask ^= 0777;
+ mask = bb_parse_mode(modestr, mask);
+ if ((unsigned)mask > 0777) {
+ ash_msg_and_raise_error("illegal mode: %s", modestr);
+ }
+ if (!isdigit(modestr[0]))
+ mask ^= 0777;
+ umask(mask);
}
return 0;
}
@@ -12971,8 +12975,16 @@ init(void)
}
}
- setvar("PPID", utoa(getppid()), 0);
-
+ setvar0("PPID", utoa(getppid()));
+#if ENABLE_ASH_BASH_COMPAT
+ p = lookupvar("SHLVL");
+ setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
+ if (!lookupvar("HOSTNAME")) {
+ struct utsname uts;
+ uname(&uts);
+ setvar0("HOSTNAME", uts.nodename);
+ }
+#endif
p = lookupvar("PWD");
if (p) {
if (*p != '/' || stat(p, &st1) || stat(".", &st2)
@@ -13151,7 +13163,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
exitshell();
}
if (e == EXINT) {
- outcslow('\n', stderr);
+ newline_and_flush(stderr);
}
popstackmark(&smark);
@@ -13176,27 +13188,21 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
setstackmark(&smark);
procargs(argv);
-#if ENABLE_FEATURE_EDITING_SAVEHISTORY
- if (iflag) {
- const char *hp = lookupvar("HISTFILE");
- if (!hp) {
- hp = lookupvar("HOME");
- if (hp) {
- char *defhp = concat_path_file(hp, ".ash_history");
- setvar("HISTFILE", defhp, 0);
- free(defhp);
- }
- }
- }
-#endif
if (argv[0] && argv[0][0] == '-')
isloginsh = 1;
if (isloginsh) {
+ const char *hp;
+
state = 1;
read_profile("/etc/profile");
state1:
state = 2;
- read_profile(".profile");
+ hp = lookupvar("HOME");
+ if (hp) {
+ hp = concat_path_file(hp, ".profile");
+ read_profile(hp);
+ free((char*)hp);
+ }
}
state2:
state = 3;
@@ -13228,6 +13234,15 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
#if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
if (iflag) {
const char *hp = lookupvar("HISTFILE");
+ if (!hp) {
+ hp = lookupvar("HOME");
+ if (hp) {
+ hp = concat_path_file(hp, ".ash_history");
+ setvar0("HISTFILE", hp);
+ free((char*)hp);
+ hp = lookupvar("HISTFILE");
+ }
+ }
if (hp)
line_input_state->hist_file = hp;
# if ENABLE_FEATURE_SH_HISTFILESIZE
diff --git a/release/src/router/busybox/shell/ash_test/.gitignore b/release/src/router/busybox/shell/ash_test/.gitignore
new file mode 100644
index 0000000000..a1f937cdd5
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/.gitignore
@@ -0,0 +1,7 @@
+/ash
+/printenv
+/recho
+/zecho
+
+/*.fail
+*.xx
diff --git a/release/src/router/busybox/shell/ash_test/ash-glob/glob1.right b/release/src/router/busybox/shell/ash_test/ash-glob/glob1.right
new file mode 100644
index 0000000000..f29ab4e654
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-glob/glob1.right
@@ -0,0 +1,2 @@
+glob1.tests
+glob1.tests
diff --git a/release/src/router/busybox/shell/ash_test/ash-glob/glob1.tests b/release/src/router/busybox/shell/ash_test/ash-glob/glob1.tests
new file mode 100755
index 0000000000..f980ce0647
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-glob/glob1.tests
@@ -0,0 +1,2 @@
+echo *glob1?t[e]sts*
+echo "glob1"?'t'[e]s*
diff --git a/release/src/router/busybox/shell/ash_test/ash-glob/glob2.right b/release/src/router/busybox/shell/ash_test/ash-glob/glob2.right
new file mode 100644
index 0000000000..7a70c22633
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-glob/glob2.right
@@ -0,0 +1,18 @@
+Expected Actual
+Z\* : Z\*
+Z* : Z*
+Z\f : Z\f
+Z\* : Z\*
+
+Z\z : Z\z
+Zz : Zz
+Z\z : Z\z
+Z\z : Z\z
+
+Z\ : Z\
+Z\ : Z\
+
+Z\f Zf : Z\f Zf
+Z\f Zf : Z\f Zf
+
+Done: 0
diff --git a/release/src/router/busybox/shell/ash_test/ash-glob/glob2.tests b/release/src/router/busybox/shell/ash_test/ash-glob/glob2.tests
new file mode 100755
index 0000000000..00618b9db3
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-glob/glob2.tests
@@ -0,0 +1,27 @@
+# This test demonstrates that in unquoted $v, backslashes expand by this rule:
+# \z -> \\\z; \<eol> -> \\<eol> (for any z, special or not),
+# and subsequently globbing converts \\ to \ and treats \z as literal z
+# even if it is a special char.
+
+>'Zf'
+>'Z\f'
+ echo 'Expected' 'Actual'
+v='\*'; echo 'Z\* :' Z$v # ash is buggy here: prints 'Z\f'
+ echo 'Z* :' Z\*
+ echo 'Z\f :' Z\\*
+ echo 'Z\* :' Z\\\* # NB! only this matches Z$v output
+echo
+v='\z'; echo 'Z\z :' Z$v
+ echo 'Zz :' Z\z
+ echo 'Z\z :' Z\\z
+ echo 'Z\z :' Z\\\z
+echo
+v='\'; echo 'Z\ :' Z$v
+ echo 'Z\ :' Z\\
+echo
+v='*'; echo 'Z\f Zf :' Z$v
+ echo 'Z\f Zf :' Z*
+echo
+
+rm 'Z\f' 'Zf'
+echo Done: $?
diff --git a/release/src/router/busybox/shell/ash_test/ash-glob/glob3.right b/release/src/router/busybox/shell/ash_test/ash-glob/glob3.right
new file mode 100644
index 0000000000..161b589e02
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-glob/glob3.right
@@ -0,0 +1,2 @@
+glob3.tests
+./glob3.tests
diff --git a/release/src/router/busybox/shell/ash_test/ash-glob/glob3.tests b/release/src/router/busybox/shell/ash_test/ash-glob/glob3.tests
new file mode 100755
index 0000000000..bdf54001e9
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-glob/glob3.tests
@@ -0,0 +1,2 @@
+echo "glob3.test"*
+echo "./glob3.test"*
diff --git a/release/src/router/busybox/shell/ash_test/ash-glob/glob_and_assign.right b/release/src/router/busybox/shell/ash_test/ash-glob/glob_and_assign.right
new file mode 100644
index 0000000000..d46e443631
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-glob/glob_and_assign.right
@@ -0,0 +1,6 @@
+ZVAR=z.tmp ZVAR=*.tmp ZVAR=[z].tmp
+ZVAR=z.tmp ZVAR=*.tmp ZVAR=[z].tmp
+*.tmp
+ZVAR=z.tmp z.tmp
+ZVAR=z.tmp ZVAR=*.tmp ZVAR=[z].tmp
+ZVAR=z.tmp ZVAR=*.tmp ZVAR=[z].tmp
diff --git a/release/src/router/busybox/shell/ash_test/ash-glob/glob_and_assign.tests b/release/src/router/busybox/shell/ash_test/ash-glob/glob_and_assign.tests
new file mode 100755
index 0000000000..0b158f20f2
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-glob/glob_and_assign.tests
@@ -0,0 +1,10 @@
+>ZVAR=z.tmp
+>z.tmp
+ZVAR=*.tmp echo ZVAR=*.tmp "ZVAR=*.tmp" "ZVAR=[z].tmp"
+ZVAR=*.tmp /bin/echo ZVAR=*.tmp "ZVAR=*.tmp" "ZVAR=[z].tmp"
+ZVAR=*.tmp
+echo "$ZVAR"
+echo $ZVAR
+echo ZVAR=*.tmp "ZVAR=*.tmp" "ZVAR=[z].tmp"
+/bin/echo ZVAR=*.tmp "ZVAR=*.tmp" "ZVAR=[z].tmp"
+rm ZVAR=z.tmp z.tmp
diff --git a/release/src/router/busybox/shell/ash_test/ash-glob/glob_redir.right b/release/src/router/busybox/shell/ash_test/ash-glob/glob_redir.right
new file mode 100644
index 0000000000..fbd0309b0d
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-glob/glob_redir.right
@@ -0,0 +1,2 @@
+z.tmp:
+?.tmp: TEST
diff --git a/release/src/router/busybox/shell/ash_test/ash-glob/glob_redir.tests b/release/src/router/busybox/shell/ash_test/ash-glob/glob_redir.tests
new file mode 100755
index 0000000000..621d12017b
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-glob/glob_redir.tests
@@ -0,0 +1,9 @@
+# Redirections are not globbed.
+# bash:
+# if run as "sh", they are not globbed, but
+# if run as "bash", they are!
+>z.tmp
+echo TEST >?.tmp
+echo 'z.tmp:' `cat 'z.tmp'`
+echo '?.tmp:' `cat '?.tmp'`
+rm 'z.tmp' '?.tmp'
diff --git a/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc1.right b/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc1.right
new file mode 100644
index 0000000000..40aa5a5fe3
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc1.right
@@ -0,0 +1 @@
+./heredoc1.tests: line 3: syntax error: unexpected "then"
diff --git a/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc1.tests b/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc1.tests
new file mode 100755
index 0000000000..a912a67c7f
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc1.tests
@@ -0,0 +1,3 @@
+# We used to SEGV on this:
+
+<<EOF; then <W
diff --git a/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc2.right b/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc2.right
new file mode 100644
index 0000000000..a486f1ac47
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc2.right
@@ -0,0 +1,2 @@
+bar
+bar
diff --git a/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc2.tests b/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc2.tests
new file mode 100755
index 0000000000..6d9ccb6cc1
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc2.tests
@@ -0,0 +1,7 @@
+foo () {
+cat <<EOF && { echo "$1" ; }
+$1
+EOF
+}
+
+foo "bar"
diff --git a/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc3.right b/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc3.right
new file mode 100644
index 0000000000..ce01362503
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc3.right
@@ -0,0 +1 @@
+hello
diff --git a/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc3.tests b/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc3.tests
new file mode 100755
index 0000000000..96c227cc14
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc3.tests
@@ -0,0 +1,9 @@
+echo hello >greeting
+cat <<EOF &&
+$(cat greeting)
+EOF
+{
+ echo $?
+ cat greeting
+} >/dev/null
+rm greeting
diff --git a/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc4.right b/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc4.right
new file mode 100644
index 0000000000..371b092e21
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc4.right
@@ -0,0 +1 @@
+'$'
diff --git a/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc4.tests b/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc4.tests
new file mode 100755
index 0000000000..642ddb324d
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-heredoc/heredoc4.tests
@@ -0,0 +1,3 @@
+cat <<EOF
+'$'
+EOF
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/command.right b/release/src/router/busybox/shell/ash_test/ash-misc/command.right
new file mode 100644
index 0000000000..7f746d9c47
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/command.right
@@ -0,0 +1 @@
+recho: not found
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/command.tests b/release/src/router/busybox/shell/ash_test/ash-misc/command.tests
new file mode 100755
index 0000000000..5d445af514
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/command.tests
@@ -0,0 +1 @@
+command -p -V recho
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/command2.right b/release/src/router/busybox/shell/ash_test/ash-misc/command2.right
new file mode 100644
index 0000000000..8d2165f694
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/command2.right
@@ -0,0 +1,2 @@
+test1
+./command2.tests: ./test1.sh: line 1: ./test2.sh: Permission denied
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/command2.tests b/release/src/router/busybox/shell/ash_test/ash-misc/command2.tests
new file mode 100755
index 0000000000..9d9de9a89b
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/command2.tests
@@ -0,0 +1,6 @@
+echo "echo test1; ./test2.sh" >test1.sh
+echo "echo test2" >test2.sh
+
+command . ./test1.sh
+
+rm -f test1.sh test2.sh
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/echo_write_error.tests b/release/src/router/busybox/shell/ash_test/ash-misc/echo_write_error.tests
index 0a40c9ff73..0a40c9ff73 100644..100755
--- a/release/src/router/busybox/shell/ash_test/ash-misc/echo_write_error.tests
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/echo_write_error.tests
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/exec.right b/release/src/router/busybox/shell/ash_test/ash-misc/exec.right
new file mode 100644
index 0000000000..1741a38dd7
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/exec.right
@@ -0,0 +1,2 @@
+./exec.tests: exec: line 2: ./test1.sh: not found
+127
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/exec.tests b/release/src/router/busybox/shell/ash_test/ash-misc/exec.tests
new file mode 100755
index 0000000000..624915de16
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/exec.tests
@@ -0,0 +1,3 @@
+rm -f test1.sh
+(exec ./test1.sh)
+echo $?
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/for.right b/release/src/router/busybox/shell/ash_test/ash-misc/for.right
new file mode 100644
index 0000000000..d86bac9de5
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/for.right
@@ -0,0 +1 @@
+OK
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/for.tests b/release/src/router/busybox/shell/ash_test/ash-misc/for.tests
new file mode 100755
index 0000000000..4889a9f2db
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/for.tests
@@ -0,0 +1,5 @@
+for i
+in OK
+do
+ echo $i
+done
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/func1.right b/release/src/router/busybox/shell/ash_test/ash-misc/func1.right
new file mode 100644
index 0000000000..e21665aafa
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/func1.right
@@ -0,0 +1,6 @@
+Hello
+Zero: 0
+One: 1 Param1: World
+Zero: 0 Param1: Restored
+Multi line function
+One: 1
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/func1.tests b/release/src/router/busybox/shell/ash_test/ash-misc/func1.tests
new file mode 100755
index 0000000000..ffb269fadc
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/func1.tests
@@ -0,0 +1,16 @@
+f() { echo Hello; }
+g () { echo One: $# Param1: $1; }
+h ( )
+{
+ echo -n 'Multi ' && echo -n 'line '
+ echo function
+ false
+}
+
+f
+echo Zero: $?
+set -- Restored
+{ g World; }
+echo Zero: $? Param1: $1
+( h )
+echo One: $?
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/func2.right b/release/src/router/busybox/shell/ash_test/ash-misc/func2.right
new file mode 100644
index 0000000000..f2a041da7b
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/func2.right
@@ -0,0 +1,5 @@
+First 0
+Second 0
+First 1
+Second 1
+Done
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/func2.tests b/release/src/router/busybox/shell/ash_test/ash-misc/func2.tests
new file mode 100755
index 0000000000..763203f15a
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/func2.tests
@@ -0,0 +1,9 @@
+i=0
+while test $i != 2; do
+ f() { echo First $i; }
+ f
+ f() { echo Second $i; }
+ f
+ : $((i++))
+done
+echo Done
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/func3.right b/release/src/router/busybox/shell/ash_test/ash-misc/func3.right
new file mode 100644
index 0000000000..b6d73459a8
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/func3.right
@@ -0,0 +1,4 @@
+One:1
+Zero:0
+One:1
+Five:5
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/func3.tests b/release/src/router/busybox/shell/ash_test/ash-misc/func3.tests
new file mode 100755
index 0000000000..fa6f26a231
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/func3.tests
@@ -0,0 +1,8 @@
+f() { false; return; echo BAD; };
+{ f; echo One:$?; }; echo Zero:$?
+
+f() { false; return; };
+f; echo One:$?
+
+f() { return 5; };
+f; echo Five:$?
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/func4.right b/release/src/router/busybox/shell/ash_test/ash-misc/func4.right
new file mode 100644
index 0000000000..0c87e316aa
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/func4.right
@@ -0,0 +1,2 @@
+24
+Done
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/func4.tests b/release/src/router/busybox/shell/ash_test/ash-misc/func4.tests
new file mode 100755
index 0000000000..74c1b9a469
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/func4.tests
@@ -0,0 +1,7 @@
+func() {
+ eval "echo \"\${val_${1}}\""
+}
+
+val_x=24
+(func x)
+echo Done
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/func5.right b/release/src/router/busybox/shell/ash_test/ash-misc/func5.right
new file mode 100644
index 0000000000..2c9d316b3d
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/func5.right
@@ -0,0 +1,6 @@
+1
+2
+3
+1
+2
+3
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/func5.tests b/release/src/router/busybox/shell/ash_test/ash-misc/func5.tests
new file mode 100755
index 0000000000..e967208cc9
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/func5.tests
@@ -0,0 +1,13 @@
+f() { echo $1; }
+f 1
+
+f() ( echo $1; )
+f 2
+
+f() ( echo $1 )
+f 3
+
+f() for i in 1 2 3; do
+ echo $i
+done
+f
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/func_args1.right b/release/src/router/busybox/shell/ash_test/ash-misc/func_args1.right
new file mode 100644
index 0000000000..2dfb9629b3
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/func_args1.right
@@ -0,0 +1,5 @@
+params: a b c
+'f 1 2 3' called
+params: a b c
+'f 1 2 3' called
+params: a b c
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/func_args1.tests b/release/src/router/busybox/shell/ash_test/ash-misc/func_args1.tests
new file mode 100755
index 0000000000..d394c637f9
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/func_args1.tests
@@ -0,0 +1,8 @@
+f() { echo "'f $1 $2 $3' called"; }
+
+set -- a b c
+echo "params: $1 $2 $3"
+f 1 2 3
+echo "params: $1 $2 $3"
+true | f 1 2 3
+echo "params: $1 $2 $3"
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/func_bash1.right b/release/src/router/busybox/shell/ash_test/ash-misc/func_bash1.right
new file mode 100644
index 0000000000..41bf8828cd
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/func_bash1.right
@@ -0,0 +1,12 @@
+1
+2
+3
+1
+2
+3
+1
+2
+3
+1
+2
+3
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/func_bash1.tests b/release/src/router/busybox/shell/ash_test/ash-misc/func_bash1.tests
new file mode 100755
index 0000000000..2cc0970e87
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/func_bash1.tests
@@ -0,0 +1,28 @@
+function f() { echo $1; }
+f 1
+
+function f() ( echo $1; )
+f 2
+
+function f() ( echo $1 )
+f 3
+
+function f() for i in 1 2 3; do
+ echo $i
+done
+f
+
+function f { echo $1; }
+f 1
+
+# the next two don't work
+#function f ( echo $1; )
+f 2
+
+#function f ( echo $1 )
+f 3
+
+function f for i in 1 2 3; do
+ echo $i
+done
+f
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/func_local1.right b/release/src/router/busybox/shell/ash_test/ash-misc/func_local1.right
new file mode 100644
index 0000000000..3121783663
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/func_local1.right
@@ -0,0 +1,3 @@
+z=a
+z=z
+Done
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/func_local1.tests b/release/src/router/busybox/shell/ash_test/ash-misc/func_local1.tests
new file mode 100755
index 0000000000..1d594e20c8
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/func_local1.tests
@@ -0,0 +1,5 @@
+export z=z
+f() { local z=a; env | grep ^z; }
+f
+env | grep ^z
+echo Done
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/func_local2.right b/release/src/router/busybox/shell/ash_test/ash-misc/func_local2.right
new file mode 100644
index 0000000000..fe9343ac8e
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/func_local2.right
@@ -0,0 +1,14 @@
+1
+2
+1
+2
+1
+1
+2
+2
+3
+2
+2
+3
+1
+Done
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/func_local2.tests b/release/src/router/busybox/shell/ash_test/ash-misc/func_local2.tests
new file mode 100755
index 0000000000..1a9ae559d1
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/func_local2.tests
@@ -0,0 +1,7 @@
+x=1
+f() { echo $x; local x=$((x+1)); echo $x; }
+g() { f; echo $x; f; local x=$((x+1)); f; echo $x; f; }
+f
+g
+echo $x
+echo Done
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/local1.right b/release/src/router/busybox/shell/ash_test/ash-misc/local1.right
new file mode 100644
index 0000000000..a2d121df6c
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/local1.right
@@ -0,0 +1,4 @@
+A1:'A'
+A2:''
+A3:''
+A4:'A'
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/local1.tests b/release/src/router/busybox/shell/ash_test/ash-misc/local1.tests
new file mode 100755
index 0000000000..b1e6750597
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/local1.tests
@@ -0,0 +1,11 @@
+a=A
+f() {
+ local a
+ # the above line unsets $a
+ echo "A2:'$a'"
+ unset a
+ echo "A3:'$a'"
+}
+echo "A1:'$a'"
+f
+echo "A4:'$a'"
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/local2.right b/release/src/router/busybox/shell/ash_test/ash-misc/local2.right
new file mode 100644
index 0000000000..630ef79796
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/local2.right
@@ -0,0 +1 @@
+./local2.tests: local: line 1: not in a function
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/local2.tests b/release/src/router/busybox/shell/ash_test/ash-misc/local2.tests
new file mode 100755
index 0000000000..8e14037c58
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/local2.tests
@@ -0,0 +1 @@
+local x=1
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/tickquote1.right b/release/src/router/busybox/shell/ash_test/ash-misc/tickquote1.right
new file mode 100644
index 0000000000..2e661bfe33
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/tickquote1.right
@@ -0,0 +1 @@
+./tickquote1.tests: line 1: syntax error: unterminated quoted string
diff --git a/release/src/router/busybox/shell/ash_test/ash-misc/tickquote1.tests b/release/src/router/busybox/shell/ash_test/ash-misc/tickquote1.tests
new file mode 100755
index 0000000000..90d5bbc9b2
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-misc/tickquote1.tests
@@ -0,0 +1 @@
+echo `"pwd`
diff --git a/release/src/router/busybox/shell/ash_test/ash-quoting/dollar_squote_bash1.right b/release/src/router/busybox/shell/ash_test/ash-quoting/dollar_squote_bash1.right
index 57536b1d94..9f4e25efa6 100644
--- a/release/src/router/busybox/shell/ash_test/ash-quoting/dollar_squote_bash1.right
+++ b/release/src/router/busybox/shell/ash_test/ash-quoting/dollar_squote_bash1.right
@@ -1,4 +1,5 @@
a b
+$'a\tb'
a
b c
def
diff --git a/release/src/router/busybox/shell/ash_test/ash-quoting/dollar_squote_bash1.tests b/release/src/router/busybox/shell/ash_test/ash-quoting/dollar_squote_bash1.tests
index 93a56cac3a..6fc411b938 100755
--- a/release/src/router/busybox/shell/ash_test/ash-quoting/dollar_squote_bash1.tests
+++ b/release/src/router/busybox/shell/ash_test/ash-quoting/dollar_squote_bash1.tests
@@ -1,4 +1,5 @@
echo $'a\tb'
+echo "$'a\tb'"
echo $'a\nb' $'c\nd''ef'
echo $'a\'b' $'c\"d' $'e\\f'
echo $'a\63b' $'c\063b' $'e\0633f'
diff --git a/release/src/router/busybox/shell/ash_test/ash-redir/redirA.right b/release/src/router/busybox/shell/ash_test/ash-redir/redirA.right
new file mode 100644
index 0000000000..31406e336b
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-redir/redirA.right
@@ -0,0 +1,2 @@
+tmp11
+tmp11
diff --git a/release/src/router/busybox/shell/ash_test/ash-redir/redirA.tests b/release/src/router/busybox/shell/ash_test/ash-redir/redirA.tests
new file mode 100755
index 0000000000..56833f9386
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-redir/redirA.tests
@@ -0,0 +1,11 @@
+x="tmp11:tmp22"
+
+# Bug was incorrectly expanding variables in >redir
+echo "${x%:*}" >"${x%:*}"
+echo tmp1*
+rm tmp1*
+
+# Also try unquoted
+echo "${x%:*}" >${x%:*}
+echo tmp1*
+rm tmp1*
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.right b/release/src/router/busybox/shell/ash_test/ash-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.right
new file mode 100644
index 0000000000..81a15855ca
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.right
@@ -0,0 +1,2 @@
+12
+9
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.tests b/release/src/router/busybox/shell/ash_test/ash-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.tests
new file mode 100755
index 0000000000..e97a08a57b
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.tests
@@ -0,0 +1,3 @@
+unset a
+echo $((3 + ${a:=$((4 + 5))}))
+echo $a
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.right b/release/src/router/busybox/shell/ash_test/ash-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.right
new file mode 100644
index 0000000000..4b9b4f0380
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.right
@@ -0,0 +1 @@
+~root
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.tests b/release/src/router/busybox/shell/ash_test/ash-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.tests
new file mode 100755
index 0000000000..d8eb8fc1be
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.tests
@@ -0,0 +1,2 @@
+unset a
+echo "${a:-~root}"
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.right b/release/src/router/busybox/shell/ash_test/ash-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.right
new file mode 100644
index 0000000000..030ebdeb61
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.right
@@ -0,0 +1 @@
+/b/c/
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.tests b/release/src/router/busybox/shell/ash_test/ash-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.tests
new file mode 100755
index 0000000000..fb93714677
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.tests
@@ -0,0 +1,3 @@
+a=/b/c/*
+b=\\
+echo ${a%$b*}
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var-expand-tilde-in-parameter-expansion.right b/release/src/router/busybox/shell/ash_test/ash-vars/var-expand-tilde-in-parameter-expansion.right
new file mode 100644
index 0000000000..2357750c55
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var-expand-tilde-in-parameter-expansion.right
@@ -0,0 +1 @@
+:/root
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var-expand-tilde-in-parameter-expansion.tests b/release/src/router/busybox/shell/ash_test/ash-vars/var-expand-tilde-in-parameter-expansion.tests
new file mode 100755
index 0000000000..6605315d04
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var-expand-tilde-in-parameter-expansion.tests
@@ -0,0 +1,2 @@
+a=~root:~root
+echo ${a#~root}
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-1.right b/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-1.right
new file mode 100644
index 0000000000..2da3272220
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-1.right
@@ -0,0 +1 @@
+a_\_z_c
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-1.tests b/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-1.tests
new file mode 100755
index 0000000000..e4529c6314
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-1.tests
@@ -0,0 +1,2 @@
+v="a\bc"
+echo ${v/\\b/_\\_\z_}
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-2.right b/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-2.right
new file mode 100644
index 0000000000..7447c0a04f
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-2.right
@@ -0,0 +1 @@
+ax/yc
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-2.tests b/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-2.tests
new file mode 100755
index 0000000000..2db1db8979
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-2.tests
@@ -0,0 +1,2 @@
+v="abc"
+echo ${v/b/x/y}
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-3.right b/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-3.right
new file mode 100644
index 0000000000..5ea5ff892a
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-3.right
@@ -0,0 +1 @@
+axcabc
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-3.tests b/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-3.tests
new file mode 100755
index 0000000000..0935e45098
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-3.tests
@@ -0,0 +1,2 @@
+v="abcabc"
+echo ${v/b/x}
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-4.right b/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-4.right
new file mode 100644
index 0000000000..46dd750c14
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-4.right
@@ -0,0 +1 @@
+axcaxc
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-4.tests b/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-4.tests
new file mode 100755
index 0000000000..d8de843477
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-4.tests
@@ -0,0 +1,2 @@
+v="abcabc"
+echo ${v//b/x}
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-5.right b/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-5.right
new file mode 100644
index 0000000000..699b27b0c1
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-5.right
@@ -0,0 +1 @@
+axc
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-5.tests b/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-5.tests
new file mode 100755
index 0000000000..5523888771
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-5.tests
@@ -0,0 +1,2 @@
+v="ab/c"
+echo ${v/b\//x}
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var-runtime-quote-detection.right b/release/src/router/busybox/shell/ash_test/ash-vars/var-runtime-quote-detection.right
new file mode 100644
index 0000000000..b554d9e46a
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var-runtime-quote-detection.right
@@ -0,0 +1 @@
+<>
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var-runtime-quote-detection.tests b/release/src/router/busybox/shell/ash_test/ash-vars/var-runtime-quote-detection.tests
new file mode 100755
index 0000000000..e570631fdd
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var-runtime-quote-detection.tests
@@ -0,0 +1 @@
+foo=\\ echo "<${foo#[\\]}>"
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var-utf8-length.right b/release/src/router/busybox/shell/ash_test/ash-vars/var-utf8-length.right
new file mode 100644
index 0000000000..6f4247a625
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var-utf8-length.right
@@ -0,0 +1 @@
+26
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var-utf8-length.tests b/release/src/router/busybox/shell/ash_test/ash-vars/var-utf8-length.tests
new file mode 100755
index 0000000000..d04b2cbb66
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var-utf8-length.tests
@@ -0,0 +1,2 @@
+X=abcdÉfghÍjklmnÓpqrstÚvwcyz
+echo ${#X}
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var3.right b/release/src/router/busybox/shell/ash_test/ash-vars/var3.right
new file mode 100644
index 0000000000..8eb0e33372
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var3.right
@@ -0,0 +1,5 @@
+1
+1
+
+
+0
diff --git a/release/src/router/busybox/shell/ash_test/ash-vars/var3.tests b/release/src/router/busybox/shell/ash_test/ash-vars/var3.tests
new file mode 100755
index 0000000000..97b102cbed
--- /dev/null
+++ b/release/src/router/busybox/shell/ash_test/ash-vars/var3.tests
@@ -0,0 +1 @@
+x=0; f() { local x=1; echo $x; local x; echo $x; unset x; echo $x; local x; echo $x; }; f; echo $x
diff --git a/release/src/router/busybox/shell/ash_test/printenv.c b/release/src/router/busybox/shell/ash_test/printenv.c
index c4ccda8a64..c0c5e197c9 100644
--- a/release/src/router/busybox/shell/ash_test/printenv.c
+++ b/release/src/router/busybox/shell/ash_test/printenv.c
@@ -24,6 +24,7 @@
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/release/src/router/busybox/shell/ash_test/run-all b/release/src/router/busybox/shell/ash_test/run-all
index ad93e251d0..354cc1fcf0 100755
--- a/release/src/router/busybox/shell/ash_test/run-all
+++ b/release/src/router/busybox/shell/ash_test/run-all
@@ -31,8 +31,9 @@ do_test()
*.orig|*~) ;;
#*) echo $x ; sh $x ;;
*)
+ echo -n "$1/$x: "
sh "$x" >"$TOPDIR/$noslash-$x.fail" 2>&1 && \
- { echo "$1/$x: ok"; rm "$TOPDIR/$noslash-$x.fail"; } || echo "$1/$x: fail";
+ { echo "ok"; rm "$TOPDIR/$noslash-$x.fail"; } || echo "fail";
;;
esac
done
@@ -42,11 +43,12 @@ do_test()
test -x "$x" || continue
name="${x%%.tests}"
test -f "$name.right" || continue
+ echo -n "$1/$x: "
{
"$THIS_SH" "./$x" >"$name.xx" 2>&1
diff -u "$name.xx" "$name.right" >"$TOPDIR/$noslash-$x.fail" \
&& rm -f "$name.xx" "$TOPDIR/$noslash-$x.fail"
- } && echo "$1/$x: ok" || echo "$1/$x: fail"
+ } && echo "ok" || echo "fail"
done
)
}
diff --git a/release/src/router/busybox/shell/hush.c b/release/src/router/busybox/shell/hush.c
index 51d38d3aef..dfbbb4122e 100644
--- a/release/src/router/busybox/shell/hush.c
+++ b/release/src/router/busybox/shell/hush.c
@@ -91,6 +91,7 @@
#if ENABLE_HUSH_CASE
# include <fnmatch.h>
#endif
+#include <sys/utsname.h> /* for setting $HOSTNAME */
#include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */
#include "unicode.h"
@@ -106,10 +107,6 @@
# define PIPE_BUF 4096 /* amount of buffering in a pipe */
#endif
-/* Not every libc has sighandler_t. Fix it */
-typedef void (*hush_sighandler_t)(int);
-#define sighandler_t hush_sighandler_t
-
//config:config HUSH
//config: bool "hush"
//config: default y
@@ -445,7 +442,7 @@ enum {
MAYBE_ASSIGNMENT = 0,
DEFINITELY_ASSIGNMENT = 1,
NOT_ASSIGNMENT = 2,
- /* Not an assigment, but next word may be: "if v=xyz cmd;" */
+ /* Not an assignment, but next word may be: "if v=xyz cmd;" */
WORD_IS_KEYWORD = 3,
};
/* Used for initialization: o_string foo = NULL_O_STRING; */
@@ -854,6 +851,9 @@ static int builtin_jobs(char **argv) FAST_FUNC;
#if ENABLE_HUSH_HELP
static int builtin_help(char **argv) FAST_FUNC;
#endif
+#if MAX_HISTORY && ENABLE_FEATURE_EDITING
+static int builtin_history(char **argv) FAST_FUNC;
+#endif
#if ENABLE_HUSH_LOCAL
static int builtin_local(char **argv) FAST_FUNC;
#endif
@@ -923,6 +923,9 @@ static const struct built_in_command bltins1[] = {
#if ENABLE_HUSH_HELP
BLTIN("help" , builtin_help , NULL),
#endif
+#if MAX_HISTORY && ENABLE_FEATURE_EDITING
+ BLTIN("history" , builtin_history , "Show command history"),
+#endif
#if ENABLE_HUSH_JOB
BLTIN("jobs" , builtin_jobs , "List jobs"),
#endif
@@ -942,6 +945,7 @@ static const struct built_in_command bltins1[] = {
BLTIN("source" , builtin_source , "Run commands in a file"),
#endif
BLTIN("trap" , builtin_trap , "Trap signals"),
+ BLTIN("true" , builtin_true , NULL),
BLTIN("type" , builtin_type , "Show command type"),
BLTIN("ulimit" , shell_builtin_ulimit , "Control resource limits"),
BLTIN("umask" , builtin_umask , "Set file creation mask"),
@@ -1308,7 +1312,7 @@ static void restore_G_args(save_arg_t *sv, char **argv)
* backgrounds (i.e. stops) or kills all members of currently running
* pipe.
*
- * Wait builtin in interruptible by signals for which user trap is set
+ * Wait builtin is interruptible by signals for which user trap is set
* or by SIGINT in interactive shell.
*
* Trap handlers will execute even within trap handlers. (right?)
@@ -1387,7 +1391,7 @@ static void restore_G_args(save_arg_t *sv, char **argv)
* are set to '' (ignore) are NOT reset to defaults. We do the same.
*
* Problem: the above approach makes it unwieldy to catch signals while
- * we are in read builtin, of while we read commands from stdin:
+ * we are in read builtin, or while we read commands from stdin:
* masked signals are not visible!
*
* New implementation
@@ -1396,7 +1400,7 @@ static void restore_G_args(save_arg_t *sv, char **argv)
* for them - a bit like emulating kernel pending signal mask in userspace.
* We are interested in: signals which need to have special handling
* as described above, and all signals which have traps set.
- * Signals are rocorded in pending_set.
+ * Signals are recorded in pending_set.
* After each pipe execution, we extract any pending signals
* and act on them.
*
@@ -1473,18 +1477,50 @@ static sighandler_t install_sighandler(int sig, sighandler_t handler)
return old_sa.sa_handler;
}
+static void hush_exit(int exitcode) NORETURN;
+static void fflush_and__exit(void) NORETURN;
+static void restore_ttypgrp_and__exit(void) NORETURN;
+
+static void restore_ttypgrp_and__exit(void)
+{
+ /* xfunc has failed! die die die */
+ /* no EXIT traps, this is an escape hatch! */
+ G.exiting = 1;
+ hush_exit(xfunc_error_retval);
+}
+
+/* Needed only on some libc:
+ * It was observed that on exit(), fgetc'ed buffered data
+ * gets "unwound" via lseek(fd, -NUM, SEEK_CUR).
+ * With the net effect that even after fork(), not vfork(),
+ * exit() in NOEXECed applet in "sh SCRIPT":
+ * noexec_applet_here
+ * echo END_OF_SCRIPT
+ * lseeks fd in input FILE object from EOF to "e" in "echo END_OF_SCRIPT".
+ * This makes "echo END_OF_SCRIPT" executed twice.
+ * Similar problems can be seen with die_if_script() -> xfunc_die()
+ * and in `cmd` handling.
+ * If set as die_func(), this makes xfunc_die() exit via _exit(), not exit():
+ */
+static void fflush_and__exit(void)
+{
+ fflush_all();
+ _exit(xfunc_error_retval);
+}
+
#if ENABLE_HUSH_JOB
/* After [v]fork, in child: do not restore tty pgrp on xfunc death */
-# define disable_restore_tty_pgrp_on_exit() (die_sleep = 0)
+# define disable_restore_tty_pgrp_on_exit() (die_func = fflush_and__exit)
/* After [v]fork, in parent: restore tty pgrp on xfunc death */
-# define enable_restore_tty_pgrp_on_exit() (die_sleep = -1)
+# define enable_restore_tty_pgrp_on_exit() (die_func = restore_ttypgrp_and__exit)
/* Restores tty foreground process group, and exits.
* May be called as signal handler for fatal signal
* (will resend signal to itself, producing correct exit state)
* or called directly with -EXITCODE.
- * We also call it if xfunc is exiting. */
+ * We also call it if xfunc is exiting.
+ */
static void sigexit(int sig) NORETURN;
static void sigexit(int sig)
{
@@ -1539,7 +1575,6 @@ static sighandler_t pick_sighandler(unsigned sig)
}
/* Restores tty foreground process group, and exits. */
-static void hush_exit(int exitcode) NORETURN;
static void hush_exit(int exitcode)
{
#if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
@@ -1575,11 +1610,11 @@ static void hush_exit(int exitcode)
}
#endif
-#if ENABLE_HUSH_JOB
fflush_all();
+#if ENABLE_HUSH_JOB
sigexit(- (exitcode & 0xff));
#else
- exit(exitcode);
+ _exit(exitcode);
#endif
}
@@ -1752,6 +1787,7 @@ static int set_local_var(char *str, int flg_export, int local_lvl, int flg_read_
{
struct variable **var_pp;
struct variable *cur;
+ char *free_me = NULL;
char *eq_sign;
int name_len;
@@ -1768,6 +1804,7 @@ static int set_local_var(char *str, int flg_export, int local_lvl, int flg_read_
var_pp = &cur->next;
continue;
}
+
/* We found an existing var with this name */
if (cur->flg_read_only) {
#if !BB_MMU
@@ -1816,12 +1853,17 @@ static int set_local_var(char *str, int flg_export, int local_lvl, int flg_read_
strcpy(cur->varstr, str);
goto free_and_exp;
}
- } else {
- /* max_len == 0 signifies "malloced" var, which we can
- * (and has to) free */
- free(cur->varstr);
- }
- cur->max_len = 0;
+ /* Can't reuse */
+ cur->max_len = 0;
+ goto set_str_and_exp;
+ }
+ /* max_len == 0 signifies "malloced" var, which we can
+ * (and have to) free. But we can't free(cur->varstr) here:
+ * if cur->flg_export is 1, it is in the environment.
+ * We should either unsetenv+free, or wait until putenv,
+ * then putenv(new)+free(old).
+ */
+ free_me = cur->varstr;
goto set_str_and_exp;
}
@@ -1848,10 +1890,15 @@ static int set_local_var(char *str, int flg_export, int local_lvl, int flg_read_
cur->flg_export = 0;
/* unsetenv was already done */
} else {
+ int i;
debug_printf_env("%s: putenv '%s'\n", __func__, cur->varstr);
- return putenv(cur->varstr);
+ i = putenv(cur->varstr);
+ /* only now we can free old exported malloced string */
+ free(free_me);
+ return i;
}
}
+ free(free_me);
return 0;
}
@@ -1973,6 +2020,26 @@ static struct variable *set_vars_and_save_old(char **strings)
/*
+ * Unicode helper
+ */
+static void reinit_unicode_for_hush(void)
+{
+ /* Unicode support should be activated even if LANG is set
+ * _during_ shell execution, not only if it was set when
+ * shell was started. Therefore, re-check LANG every time:
+ */
+ if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
+ || ENABLE_UNICODE_USING_LOCALE
+ ) {
+ const char *s = get_local_var_value("LC_ALL");
+ if (!s) s = get_local_var_value("LC_CTYPE");
+ if (!s) s = get_local_var_value("LANG");
+ reinit_unicode(s);
+ }
+}
+
+
+/*
* in_str support
*/
static int FAST_FUNC static_get(struct in_str *i)
@@ -2038,12 +2105,7 @@ static void get_user_input(struct in_str *i)
/* Enable command line editing only while a command line
* is actually being read */
do {
- /* Unicode support should be activated even if LANG is set
- * _during_ shell execution, not only if it was set when
- * shell was started. Therefore, re-check LANG every time:
- */
- reinit_unicode(get_local_var_value("LANG"));
-
+ reinit_unicode_for_hush();
G.flag_SIGINT = 0;
/* buglet: SIGINT will not make new prompt to appear _at once_,
* only after <Enter>. (^C will work) */
@@ -3142,11 +3204,29 @@ static int reserved_word(o_string *word, struct parse_context *ctx)
old->command->group = ctx->list_head;
old->command->cmd_type = CMD_NORMAL;
# if !BB_MMU
- o_addstr(&old->as_string, ctx->as_string.data);
- o_free_unsafe(&ctx->as_string);
- old->command->group_as_string = xstrdup(old->as_string.data);
- debug_printf_parse("pop, remembering as:'%s'\n",
- old->command->group_as_string);
+ /* At this point, the compound command's string is in
+ * ctx->as_string... except for the leading keyword!
+ * Consider this example: "echo a | if true; then echo a; fi"
+ * ctx->as_string will contain "true; then echo a; fi",
+ * with "if " remaining in old->as_string!
+ */
+ {
+ char *str;
+ int len = old->as_string.length;
+ /* Concatenate halves */
+ o_addstr(&old->as_string, ctx->as_string.data);
+ o_free_unsafe(&ctx->as_string);
+ /* Find where leading keyword starts in first half */
+ str = old->as_string.data + len;
+ if (str > old->as_string.data)
+ str--; /* skip whitespace after keyword */
+ while (str > old->as_string.data && isalpha(str[-1]))
+ str--;
+ /* Ugh, we're done with this horrid hack */
+ old->command->group_as_string = xstrdup(str);
+ debug_printf_parse("pop, remembering as:'%s'\n",
+ old->command->group_as_string);
+ }
# endif
*ctx = *old; /* physical copy */
free(old);
@@ -4223,13 +4303,13 @@ static struct pipe *parse_stream(char **pstring,
/* (this makes bare "&" cmd a no-op.
* bash says: "syntax error near unexpected token '&'") */
if (pi->num_cmds == 0
- IF_HAS_KEYWORDS( && pi->res_word == RES_NONE)
+ IF_HAS_KEYWORDS(&& pi->res_word == RES_NONE)
) {
free_pipe_list(pi);
pi = NULL;
}
#if !BB_MMU
- debug_printf_parse("as_string '%s'\n", ctx.as_string.data);
+ debug_printf_parse("as_string1 '%s'\n", ctx.as_string.data);
if (pstring)
*pstring = ctx.as_string.data;
else
@@ -4376,11 +4456,11 @@ static struct pipe *parse_stream(char **pstring,
debug_printf_parse("dest.o_assignment='%s'\n", assignment_flag[dest.o_assignment]);
/* Do we sit outside of any if's, loops or case's? */
if (!HAS_KEYWORDS
- IF_HAS_KEYWORDS(|| (ctx.ctx_res_w == RES_NONE && ctx.old_flag == 0))
+ IF_HAS_KEYWORDS(|| (ctx.ctx_res_w == RES_NONE && ctx.old_flag == 0))
) {
o_free(&dest);
#if !BB_MMU
- debug_printf_parse("as_string '%s'\n", ctx.as_string.data);
+ debug_printf_parse("as_string2 '%s'\n", ctx.as_string.data);
if (pstring)
*pstring = ctx.as_string.data;
else
@@ -4620,9 +4700,6 @@ static struct pipe *parse_stream(char **pstring,
* with redirect_opt_num(), but bash doesn't do it.
* "echo foo 2| cat" yields "foo 2". */
done_command(&ctx);
-#if !BB_MMU
- o_reset_to_empty_unquoted(&ctx.as_string);
-#endif
}
goto new_cmd;
case '(':
@@ -5021,8 +5098,9 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
/* Handle any expansions */
if (exp_op == 'L') {
+ reinit_unicode_for_hush();
debug_printf_expand("expand: length(%s)=", val);
- val = utoa(val ? strlen(val) : 0);
+ val = utoa(val ? unicode_strlen(val) : 0);
debug_printf_expand("%s\n", val);
} else if (exp_op) {
if (exp_op == '%' || exp_op == '#') {
@@ -5370,7 +5448,6 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
!!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
}
break;
-
} /* switch (char after <SPECIAL_VAR_SYMBOL>) */
if (val && val[0]) {
@@ -5864,12 +5941,13 @@ static FILE *generate_stream_from_string(const char *s, pid_t *pid_p)
* Our solution: ONLY bare $(trap) or `trap` is special.
*/
s = skip_whitespace(s);
- if (strncmp(s, "trap", 4) == 0
+ if (is_prefixed_with(s, "trap")
&& skip_whitespace(s + 4)[0] == '\0'
) {
static const char *const argv[] = { NULL, NULL };
builtin_trap((char**)argv);
- exit(0); /* not _exit() - we need to fflush */
+ fflush_all(); /* important */
+ _exit(0);
}
# if BB_MMU
reset_traps_to_defaults();
@@ -6422,7 +6500,8 @@ static void dump_cmd_in_x_mode(char **argv)
* Never returns.
* Don't exit() here. If you don't exec, use _exit instead.
* The at_exit handlers apparently confuse the calling process,
- * in particular stdin handling. Not sure why? -- because of vfork! (vda) */
+ * in particular stdin handling. Not sure why? -- because of vfork! (vda)
+ */
static void pseudo_exec_argv(nommu_save_t *nommu_save,
char **argv, int assignment_cnt,
char **argv_expanded) NORETURN;
@@ -6760,7 +6839,7 @@ static int checkjobs(struct pipe *fg_pipe)
int sig = WTERMSIG(status);
if (i == fg_pipe->num_cmds-1)
/* TODO: use strsignal() instead for bash compat? but that's bloat... */
- printf("%s\n", sig == SIGINT || sig == SIGPIPE ? "" : get_signame(sig));
+ puts(sig == SIGINT || sig == SIGPIPE ? "" : get_signame(sig));
/* TODO: if (WCOREDUMP(status)) + " (core dumped)"; */
/* TODO: MIPS has 128 sigs (1..128), what if sig==128 here?
* Maybe we need to use sig | 128? */
@@ -7358,7 +7437,7 @@ static int run_list(struct pipe *pi)
* and we should not execute CMD */
debug_printf_exec("skipped cmd because of || or &&\n");
last_followup = pi->followup;
- continue;
+ goto dont_check_jobs_but_continue;
}
}
last_followup = pi->followup;
@@ -7497,8 +7576,10 @@ static int run_list(struct pipe *pi)
G.flag_break_continue = 0;
/* else: e.g. "continue 2" should *break* once, *then* continue */
} /* else: "while... do... { we are here (innermost list is not a loop!) };...done" */
- if (G.depth_break_continue != 0 || fbc == BC_BREAK)
- goto check_jobs_and_break;
+ if (G.depth_break_continue != 0 || fbc == BC_BREAK) {
+ checkjobs(NULL);
+ break;
+ }
/* "continue": simulate end of loop */
rword = RES_DONE;
continue;
@@ -7506,7 +7587,6 @@ static int run_list(struct pipe *pi)
#endif
#if ENABLE_HUSH_FUNCTIONS
if (G.flag_return_in_progress == 1) {
- /* same as "goto check_jobs_and_break" */
checkjobs(NULL);
break;
}
@@ -7548,6 +7628,9 @@ static int run_list(struct pipe *pi)
if (rword == RES_IF || rword == RES_ELIF)
cond_code = rcode;
#endif
+ check_jobs_and_continue:
+ checkjobs(NULL);
+ dont_check_jobs_but_continue: ;
#if ENABLE_HUSH_LOOPS
/* Beware of "while false; true; do ..."! */
if (pi->next
@@ -7559,22 +7642,17 @@ static int run_list(struct pipe *pi)
/* "while false; do...done" - exitcode 0 */
G.last_exitcode = rcode = EXIT_SUCCESS;
debug_printf_exec(": while expr is false: breaking (exitcode:EXIT_SUCCESS)\n");
- goto check_jobs_and_break;
+ break;
}
}
if (rword == RES_UNTIL) {
if (!rcode) {
debug_printf_exec(": until expr is true: breaking\n");
- check_jobs_and_break:
- checkjobs(NULL);
break;
}
}
}
#endif
-
- check_jobs_and_continue:
- checkjobs(NULL);
} /* for (pi) */
#if ENABLE_HUSH_JOB
@@ -7744,6 +7822,7 @@ int hush_main(int argc, char **argv)
INIT_G();
if (EXIT_SUCCESS != 0) /* if EXIT_SUCCESS == 0, it is already done */
G.last_exitcode = EXIT_SUCCESS;
+
#if ENABLE_HUSH_FAST
G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */
#endif
@@ -7781,6 +7860,14 @@ int hush_main(int argc, char **argv)
/* Export PWD */
set_pwd_var(/*exp:*/ 1);
+
+#if ENABLE_HUSH_BASH_COMPAT
+ /* Set (but not export) HOSTNAME unless already set */
+ if (!get_local_var_value("HOSTNAME")) {
+ struct utsname uts;
+ uname(&uts);
+ set_local_var_from_halves("HOSTNAME", uts.nodename);
+ }
/* bash also exports SHLVL and _,
* and sets (but doesn't export) the following variables:
* BASH=/bin/bash
@@ -7789,7 +7876,6 @@ int hush_main(int argc, char **argv)
* HOSTTYPE=i386
* MACHTYPE=i386-pc-linux-gnu
* OSTYPE=linux-gnu
- * HOSTNAME=<xxxxxxxxxx>
* PPID=<NNNNN> - we also do it elsewhere
* EUID=<NNNNN>
* UID=<NNNNN>
@@ -7817,6 +7903,7 @@ int hush_main(int argc, char **argv)
* PS2='> '
* PS4='+ '
*/
+#endif
#if ENABLE_FEATURE_EDITING
G.line_input_state = new_line_input_t(FOR_SHELL);
@@ -7825,12 +7912,7 @@ int hush_main(int argc, char **argv)
/* Initialize some more globals to non-zero values */
cmdedit_update_prompt();
- if (setjmp(die_jmp)) {
- /* xfunc has failed! die die die */
- /* no EXIT traps, this is an escape hatch! */
- G.exiting = 1;
- hush_exit(xfunc_error_retval);
- }
+ die_func = restore_ttypgrp_and__exit;
/* Shell is non-interactive at first. We need to call
* install_special_sighandlers() if we are going to execute "sh <script>",
@@ -8088,9 +8170,7 @@ int hush_main(int argc, char **argv)
/* Grab control of the terminal */
tcsetpgrp(G_interactive_fd, getpid());
}
- /* -1 is special - makes xfuncs longjmp, not exit
- * (we reset die_sleep = 0 whereever we [v]fork) */
- enable_restore_tty_pgrp_on_exit(); /* sets die_sleep = -1 */
+ enable_restore_tty_pgrp_on_exit();
# if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0
{
@@ -8285,7 +8365,7 @@ static int FAST_FUNC builtin_exit(char **argv)
* (if there are _stopped_ jobs, running ones don't count)
* # exit
* exit
- # EEE (then bash exits)
+ * EEE (then bash exits)
*
* TODO: we can use G.exiting = -1 as indicator "last cmd was exit"
*/
@@ -8632,6 +8712,14 @@ static int FAST_FUNC builtin_help(char **argv UNUSED_PARAM)
}
#endif
+#if MAX_HISTORY && ENABLE_FEATURE_EDITING
+static int FAST_FUNC builtin_history(char **argv UNUSED_PARAM)
+{
+ show_history(G.line_input_state);
+ return EXIT_SUCCESS;
+}
+#endif
+
#if ENABLE_HUSH_JOB
static int FAST_FUNC builtin_jobs(char **argv UNUSED_PARAM)
{
@@ -8884,6 +8972,9 @@ static int FAST_FUNC builtin_source(char **argv)
free(arg_path);
if (!input) {
/* bb_perror_msg("%s", *argv); - done by fopen_or_warn */
+ /* POSIX: non-interactive shell should abort here,
+ * not merely fail. So far no one complained :)
+ */
return EXIT_FAILURE;
}
close_on_exec_on(fileno(input));
@@ -8893,12 +8984,14 @@ static int FAST_FUNC builtin_source(char **argv)
/* "we are inside sourced file, ok to use return" */
G.flag_return_in_progress = -1;
#endif
- save_and_replace_G_args(&sv, argv);
+ if (argv[1])
+ save_and_replace_G_args(&sv, argv);
parse_and_run_file(input);
fclose(input);
- restore_G_args(&sv, argv);
+ if (argv[1])
+ restore_G_args(&sv, argv);
#if ENABLE_HUSH_FUNCTIONS
G.flag_return_in_progress = sv_flg;
#endif
@@ -8911,24 +9004,29 @@ static int FAST_FUNC builtin_umask(char **argv)
int rc;
mode_t mask;
+ rc = 1;
mask = umask(0);
argv = skip_dash_dash(argv);
if (argv[0]) {
mode_t old_mask = mask;
- mask ^= 0777;
- rc = bb_parse_mode(argv[0], &mask);
- mask ^= 0777;
- if (rc == 0) {
+ /* numeric umasks are taken as-is */
+ /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
+ if (!isdigit(argv[0][0]))
+ mask ^= 0777;
+ mask = bb_parse_mode(argv[0], mask);
+ if (!isdigit(argv[0][0]))
+ mask ^= 0777;
+ if ((unsigned)mask > 0777) {
mask = old_mask;
/* bash messages:
* bash: umask: 'q': invalid symbolic mode operator
* bash: umask: 999: octal number out of range
*/
bb_error_msg("%s: invalid mode '%s'", "umask", argv[0]);
+ rc = 0;
}
} else {
- rc = 1;
/* Mimic bash */
printf("%04o\n", (unsigned) mask);
/* fall through and restore mask which we set to 0 */
@@ -9058,12 +9156,9 @@ static int FAST_FUNC builtin_wait(char **argv)
return EXIT_FAILURE;
}
if (waitpid(pid, &status, 0) == pid) {
+ ret = WEXITSTATUS(status);
if (WIFSIGNALED(status))
ret = 128 + WTERMSIG(status);
- else if (WIFEXITED(status))
- ret = WEXITSTATUS(status);
- else /* wtf? */
- ret = EXIT_FAILURE;
} else {
bb_perror_msg("wait %s", *argv);
ret = 127;
diff --git a/release/src/router/busybox/shell/hush_test/hush-bugs/var3.right b/release/src/router/busybox/shell/hush_test/hush-bugs/var3.right
new file mode 100644
index 0000000000..8eb0e33372
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-bugs/var3.right
@@ -0,0 +1,5 @@
+1
+1
+
+
+0
diff --git a/release/src/router/busybox/shell/hush_test/hush-bugs/var3.tests b/release/src/router/busybox/shell/hush_test/hush-bugs/var3.tests
new file mode 100755
index 0000000000..97b102cbed
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-bugs/var3.tests
@@ -0,0 +1 @@
+x=0; f() { local x=1; echo $x; local x; echo $x; unset x; echo $x; local x; echo $x; }; f; echo $x
diff --git a/release/src/router/busybox/shell/hush_test/hush-glob/glob3.right b/release/src/router/busybox/shell/hush_test/hush-glob/glob3.right
new file mode 100644
index 0000000000..161b589e02
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-glob/glob3.right
@@ -0,0 +1,2 @@
+glob3.tests
+./glob3.tests
diff --git a/release/src/router/busybox/shell/hush_test/hush-glob/glob3.tests b/release/src/router/busybox/shell/hush_test/hush-glob/glob3.tests
new file mode 100755
index 0000000000..bdf54001e9
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-glob/glob3.tests
@@ -0,0 +1,2 @@
+echo "glob3.test"*
+echo "./glob3.test"*
diff --git a/release/src/router/busybox/shell/hush_test/hush-misc/for.right b/release/src/router/busybox/shell/hush_test/hush-misc/for.right
new file mode 100644
index 0000000000..d86bac9de5
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-misc/for.right
@@ -0,0 +1 @@
+OK
diff --git a/release/src/router/busybox/shell/hush_test/hush-misc/for.tests b/release/src/router/busybox/shell/hush_test/hush-misc/for.tests
new file mode 100755
index 0000000000..4889a9f2db
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-misc/for.tests
@@ -0,0 +1,5 @@
+for i
+in OK
+do
+ echo $i
+done
diff --git a/release/src/router/busybox/shell/hush_test/hush-misc/func_args1.tests b/release/src/router/busybox/shell/hush_test/hush-misc/func_args1.tests
index 157921fb14..d394c637f9 100755
--- a/release/src/router/busybox/shell/hush_test/hush-misc/func_args1.tests
+++ b/release/src/router/busybox/shell/hush_test/hush-misc/func_args1.tests
@@ -1,5 +1,3 @@
-# UNFIXED BUG
-
f() { echo "'f $1 $2 $3' called"; }
set -- a b c
diff --git a/release/src/router/busybox/shell/hush_test/hush-misc/nommu3.right b/release/src/router/busybox/shell/hush_test/hush-misc/nommu3.right
new file mode 100644
index 0000000000..da1534befd
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-misc/nommu3.right
@@ -0,0 +1,2 @@
+Ok
+0
diff --git a/release/src/router/busybox/shell/hush_test/hush-misc/nommu3.tests b/release/src/router/busybox/shell/hush_test/hush-misc/nommu3.tests
new file mode 100755
index 0000000000..ac82a6a115
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-misc/nommu3.tests
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+func()
+{
+ while read p; do echo "$p"; done
+}
+
+pipe_to_func()
+{
+ # We had a NOMMU bug which caused "echo Ok |" part to be lost
+ echo Ok | func
+}
+
+pipe_to_func | cat
+echo $?
diff --git a/release/src/router/busybox/shell/hush_test/hush-misc/source2.right b/release/src/router/busybox/shell/hush_test/hush-misc/source2.right
new file mode 100644
index 0000000000..0587bad677
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-misc/source2.right
@@ -0,0 +1,4 @@
+0:arg0 1:arg1 2:arg2
+Ok1:0
+0:arg0 1:q 2:w
+Ok2:0
diff --git a/release/src/router/busybox/shell/hush_test/hush-misc/source2.tests b/release/src/router/busybox/shell/hush_test/hush-misc/source2.tests
new file mode 100755
index 0000000000..40b6b83cdb
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-misc/source2.tests
@@ -0,0 +1,8 @@
+echo 'echo "0:$0 1:$1 2:$2"' >sourced1
+set -- 1 2 3
+"$THIS_SH" -c '. ./sourced1' arg0 arg1 arg2
+echo Ok1:$?
+"$THIS_SH" -c '. ./sourced1 q w e' arg0 arg1 arg2
+echo Ok2:$?
+
+rm sourced1
diff --git a/release/src/router/busybox/shell/hush_test/hush-misc/unicode1.right b/release/src/router/busybox/shell/hush_test/hush-misc/unicode1.right
new file mode 100644
index 0000000000..d3bbbf697a
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-misc/unicode1.right
@@ -0,0 +1,3 @@
+1
+1
+Ok
diff --git a/release/src/router/busybox/shell/hush_test/hush-misc/unicode1.tests b/release/src/router/busybox/shell/hush_test/hush-misc/unicode1.tests
new file mode 100755
index 0000000000..8788ba9104
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-misc/unicode1.tests
@@ -0,0 +1,13 @@
+LANG=en_US.UTF-8
+
+# A combining character U+300
+a=`printf "\xcc\x80"`
+# Should print 1
+echo ${#a}
+
+# A Japanese katakana charachter U+30a3
+a=`printf "\xe3\x82\xa3"`
+# Should print 1
+echo ${#a}
+
+echo Ok
diff --git a/release/src/router/busybox/shell/hush_test/hush-misc/while4.right b/release/src/router/busybox/shell/hush_test/hush-misc/while4.right
new file mode 100644
index 0000000000..7b24a35fff
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-misc/while4.right
@@ -0,0 +1 @@
+Ok:0
diff --git a/release/src/router/busybox/shell/hush_test/hush-misc/while4.tests b/release/src/router/busybox/shell/hush_test/hush-misc/while4.tests
new file mode 100755
index 0000000000..ba80e603a2
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-misc/while4.tests
@@ -0,0 +1,6 @@
+false
+while false && echo Not reached; do
+ echo BUG
+ break
+done
+echo Ok:$?
diff --git a/release/src/router/busybox/shell/hush_test/hush-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.right b/release/src/router/busybox/shell/hush_test/hush-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.right
new file mode 100644
index 0000000000..81a15855ca
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.right
@@ -0,0 +1,2 @@
+12
+9
diff --git a/release/src/router/busybox/shell/hush_test/hush-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.tests b/release/src/router/busybox/shell/hush_test/hush-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.tests
new file mode 100755
index 0000000000..e97a08a57b
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.tests
@@ -0,0 +1,3 @@
+unset a
+echo $((3 + ${a:=$((4 + 5))}))
+echo $a
diff --git a/release/src/router/busybox/shell/hush_test/hush-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.right b/release/src/router/busybox/shell/hush_test/hush-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.right
new file mode 100644
index 0000000000..4b9b4f0380
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.right
@@ -0,0 +1 @@
+~root
diff --git a/release/src/router/busybox/shell/hush_test/hush-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.tests b/release/src/router/busybox/shell/hush_test/hush-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.tests
new file mode 100755
index 0000000000..d8eb8fc1be
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.tests
@@ -0,0 +1,2 @@
+unset a
+echo "${a:-~root}"
diff --git a/release/src/router/busybox/shell/hush_test/hush-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.right b/release/src/router/busybox/shell/hush_test/hush-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.right
new file mode 100644
index 0000000000..030ebdeb61
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.right
@@ -0,0 +1 @@
+/b/c/
diff --git a/release/src/router/busybox/shell/hush_test/hush-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.tests b/release/src/router/busybox/shell/hush_test/hush-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.tests
new file mode 100755
index 0000000000..fb93714677
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.tests
@@ -0,0 +1,3 @@
+a=/b/c/*
+b=\\
+echo ${a%$b*}
diff --git a/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-1.right b/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-1.right
new file mode 100644
index 0000000000..2da3272220
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-1.right
@@ -0,0 +1 @@
+a_\_z_c
diff --git a/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-1.tests b/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-1.tests
new file mode 100755
index 0000000000..e4529c6314
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-1.tests
@@ -0,0 +1,2 @@
+v="a\bc"
+echo ${v/\\b/_\\_\z_}
diff --git a/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-2.right b/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-2.right
new file mode 100644
index 0000000000..7447c0a04f
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-2.right
@@ -0,0 +1 @@
+ax/yc
diff --git a/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-2.tests b/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-2.tests
new file mode 100755
index 0000000000..2db1db8979
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-2.tests
@@ -0,0 +1,2 @@
+v="abc"
+echo ${v/b/x/y}
diff --git a/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-3.right b/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-3.right
new file mode 100644
index 0000000000..5ea5ff892a
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-3.right
@@ -0,0 +1 @@
+axcabc
diff --git a/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-3.tests b/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-3.tests
new file mode 100755
index 0000000000..0935e45098
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-3.tests
@@ -0,0 +1,2 @@
+v="abcabc"
+echo ${v/b/x}
diff --git a/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-4.right b/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-4.right
new file mode 100644
index 0000000000..46dd750c14
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-4.right
@@ -0,0 +1 @@
+axcaxc
diff --git a/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-4.tests b/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-4.tests
new file mode 100755
index 0000000000..d8de843477
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-4.tests
@@ -0,0 +1,2 @@
+v="abcabc"
+echo ${v//b/x}
diff --git a/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-5.right b/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-5.right
new file mode 100644
index 0000000000..699b27b0c1
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-5.right
@@ -0,0 +1 @@
+axc
diff --git a/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-5.tests b/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-5.tests
new file mode 100755
index 0000000000..5523888771
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-5.tests
@@ -0,0 +1,2 @@
+v="ab/c"
+echo ${v/b\//x}
diff --git a/release/src/router/busybox/shell/hush_test/hush-vars/var-runtime-quote-detection.right b/release/src/router/busybox/shell/hush_test/hush-vars/var-runtime-quote-detection.right
new file mode 100644
index 0000000000..b554d9e46a
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-vars/var-runtime-quote-detection.right
@@ -0,0 +1 @@
+<>
diff --git a/release/src/router/busybox/shell/hush_test/hush-vars/var-runtime-quote-detection.tests b/release/src/router/busybox/shell/hush_test/hush-vars/var-runtime-quote-detection.tests
new file mode 100755
index 0000000000..e570631fdd
--- /dev/null
+++ b/release/src/router/busybox/shell/hush_test/hush-vars/var-runtime-quote-detection.tests
@@ -0,0 +1 @@
+foo=\\ echo "<${foo#[\\]}>"
diff --git a/release/src/router/busybox/shell/math.c b/release/src/router/busybox/shell/math.c
index 760645d0f9..006221b6a4 100644
--- a/release/src/router/busybox/shell/math.c
+++ b/release/src/router/busybox/shell/math.c
@@ -410,15 +410,34 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_
return "exponent less than 0";
c = 1;
while (--right_side_val >= 0)
- c *= rez;
+ c *= rez;
rez = c;
}
else if (right_side_val == 0)
return "divide by zero";
- else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
- rez /= right_side_val;
- else if (op == TOK_REM || op == TOK_REM_ASSIGN)
- rez %= right_side_val;
+ else if (op == TOK_DIV || op == TOK_DIV_ASSIGN
+ || op == TOK_REM || op == TOK_REM_ASSIGN) {
+ /*
+ * bash 4.2.45 x86 64bit: SEGV on 'echo $((2**63 / -1))'
+ *
+ * MAX_NEGATIVE_INT / -1 = MAX_POSITIVE_INT+1
+ * and thus is not representable.
+ * Some CPUs segfault trying such op.
+ * Others overflow MAX_POSITIVE_INT+1 to
+ * MAX_NEGATIVE_INT (0x7fff+1 = 0x8000).
+ * Make sure to at least not SEGV here:
+ */
+ if (right_side_val == -1
+ && rez << 1 == 0 /* MAX_NEGATIVE_INT or 0 */
+ ) {
+ right_side_val = 1;
+ }
+ if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
+ rez /= right_side_val;
+ else {
+ rez %= right_side_val;
+ }
+ }
}
if (is_assign_op(op)) {
@@ -494,18 +513,6 @@ static const char op_tokens[] ALIGN1 = {
};
#define ptr_to_rparen (&op_tokens[sizeof(op_tokens)-7])
-const char* FAST_FUNC
-endofname(const char *name)
-{
- if (!is_name(*name))
- return name;
- while (*++name) {
- if (!is_in_name(*name))
- break;
- }
- return name;
-}
-
static arith_t FAST_FUNC
evaluate_string(arith_state_t *math_state, const char *expr)
{
diff --git a/release/src/router/busybox/shell/math.h b/release/src/router/busybox/shell/math.h
index 2d305eb129..864bee691a 100644
--- a/release/src/router/busybox/shell/math.h
+++ b/release/src/router/busybox/shell/math.h
@@ -73,11 +73,6 @@ typedef long arith_t;
#define strto_arith_t strtoul
#endif
-/* ash's and hush's endofname is the same, so... */
-# define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
-# define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
-const char* FAST_FUNC endofname(const char *name);
-
typedef const char* FAST_FUNC (*arith_var_lookup_t)(const char *name);
typedef void FAST_FUNC (*arith_var_set_t)(const char *name, const char *val);
//typedef const char* FAST_FUNC (*arith_var_endofname_t)(const char *name);
diff --git a/release/src/router/busybox/shell/random.c b/release/src/router/busybox/shell/random.c
index 853ab085a2..5d3620516a 100644
--- a/release/src/router/busybox/shell/random.c
+++ b/release/src/router/busybox/shell/random.c
@@ -6,17 +6,51 @@
*
* Licensed under GPLv2, see file LICENSE in this source tree.
*/
-#include "libbb.h"
-#include "random.h"
+
+/* For testing against dieharder, you need only random.{c,h}
+ * Howto:
+ * gcc -O2 -Wall -DRANDTEST random.c -o random
+ * ./random | dieharder -g 200 -a
+ */
+
+#if !defined RANDTEST
+
+# include "libbb.h"
+# include "random.h"
+# define RAND_BASH_MASK 0x7fff
+
+#else
+# include <stdint.h>
+# include <unistd.h>
+# include <stdio.h>
+# include <time.h>
+# define FAST_FUNC /* nothing */
+# define PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN /* nothing */
+# define POP_SAVED_FUNCTION_VISIBILITY /* nothing */
+# define monotonic_us() time(NULL)
+# include "random.h"
+# define RAND_BASH_MASK 0xffffffff /* off */
+#endif
uint32_t FAST_FUNC
next_random(random_t *rnd)
{
- /* Galois LFSR parameter */
- /* Taps at 32 31 29 1: */
+ /* Galois LFSR parameter:
+ * Taps at 32 31 29 1:
+ */
enum { MASK = 0x8000000b };
/* Another example - taps at 32 31 30 10: */
- /* MASK = 0x00400007 */
+ /* enum { MASK = 0x00400007 }; */
+
+ /* Xorshift parameters:
+ * Choices for a,b,c: 10,13,10; 8,9,22; 2,7,3; 23,3,24
+ * (given by algorithm author)
+ */
+ enum {
+ a = 2,
+ b = 7,
+ c = 3,
+ };
uint32_t t;
@@ -27,18 +61,100 @@ next_random(random_t *rnd)
INIT_RANDOM_T(rnd, getpid(), monotonic_us());
}
- /* LCG has period of 2^32 and alternating lowest bit */
+ /* LCG: period of 2^32, but quite weak:
+ * bit 0 alternates beetween 0 and 1 (pattern of length 2)
+ * bit 1 has a repeating pattern of length 4
+ * bit 2 has a repeating pattern of length 8
+ * etc...
+ */
rnd->LCG = 1664525 * rnd->LCG + 1013904223;
- /* Galois LFSR has period of 2^32-1 = 3 * 5 * 17 * 257 * 65537 */
+
+ /* Galois LFSR:
+ * period of 2^32-1 = 3 * 5 * 17 * 257 * 65537.
+ * Successive values are right-shifted one bit
+ * and possibly xored with a sparse constant.
+ */
t = (rnd->galois_LFSR << 1);
if (rnd->galois_LFSR < 0) /* if we just shifted 1 out of msb... */
t ^= MASK;
rnd->galois_LFSR = t;
- /* Both are weak, combining them gives better randomness
- * and ~2^64 period. & 0x7fff is probably bash compat
- * for $RANDOM range. Combining with subtraction is
- * just for fun. + and ^ would work equally well. */
- t = (t - rnd->LCG) & 0x7fff;
- return t;
+ /* http://en.wikipedia.org/wiki/Xorshift
+ * Moderately good statistical properties:
+ * fails the following "dieharder -g 200 -a" tests:
+ * diehard_operm5| 0
+ * diehard_oqso| 0
+ * diehard_count_1s_byt| 0
+ * diehard_3dsphere| 3
+ * diehard_squeeze| 0
+ * diehard_runs| 0
+ * diehard_runs| 0
+ * diehard_craps| 0
+ * diehard_craps| 0
+ * rgb_minimum_distance| 3
+ * rgb_minimum_distance| 4
+ * rgb_minimum_distance| 5
+ * rgb_permutations| 3
+ * rgb_permutations| 4
+ * rgb_permutations| 5
+ * dab_filltree| 32
+ * dab_filltree| 32
+ * dab_monobit2| 12
+ */
+ again:
+ t = rnd->xs64_x ^ (rnd->xs64_x << a);
+ rnd->xs64_x = rnd->xs64_y;
+ rnd->xs64_y = rnd->xs64_y ^ (rnd->xs64_y >> c) ^ t ^ (t >> b);
+ /*
+ * Period 2^64-1 = 2^32+1 * 2^32-1 has a common divisor with Galois LFSR.
+ * By skipping two possible states (0x1 and 0x2) we reduce period to
+ * 2^64-3 = 13 * 3889 * 364870227143809 which has no common divisors:
+ */
+ if (rnd->xs64_y == 0 && rnd->xs64_x <= 2)
+ goto again;
+
+ /* Combined LCG + Galois LFSR rng has 2^32 * 2^32-1 period.
+ * Strength:
+ * individually, both are extremely weak cryptographycally;
+ * when combined, they fail the following "dieharder -g 200 -a" tests:
+ * diehard_rank_6x8| 0
+ * diehard_oqso| 0
+ * diehard_dna| 0
+ * diehard_count_1s_byt| 0
+ * rgb_bitdist| 2
+ * dab_monobit2| 12
+ *
+ * Combining them with xorshift-64 increases period to
+ * 2^32 * 2^32-1 * 2^64-3
+ * which is about 2^128, or in base 10 ~3.40*10^38.
+ * Strength of the combination:
+ * passes all "dieharder -g 200 -a" tests.
+ *
+ * Combining with subtraction and addition is just for fun.
+ * It does not add meaningful strength, could use xor operation instead.
+ */
+ t = rnd->galois_LFSR - rnd->LCG + rnd->xs64_y;
+
+ /* bash compat $RANDOM range: */
+ return t & RAND_BASH_MASK;
}
+
+#ifdef RANDTEST
+static random_t rnd;
+
+int main(int argc, char **argv)
+{
+ int i;
+ uint32_t buf[4096];
+
+ for (;;) {
+ for (i = 0; i < sizeof(buf) / sizeof(buf[0]); i++) {
+ buf[i] = next_random(&rnd);
+ }
+ write(1, buf, sizeof(buf));
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/release/src/router/busybox/shell/random.h b/release/src/router/busybox/shell/random.h
index 180c48abbf..c4eb44c133 100644
--- a/release/src/router/busybox/shell/random.h
+++ b/release/src/router/busybox/shell/random.h
@@ -12,16 +12,24 @@
PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
typedef struct random_t {
- /* Random number generators */
- int32_t galois_LFSR; /* Galois LFSR (fast but weak). signed! */
- uint32_t LCG; /* LCG (fast but weak) */
+ /* State of random number generators: */
+
+ /* Galois LFSR (fast but weak) */
+ int32_t galois_LFSR; /* must be signed! */
+
+ /* LCG (fast but weak) */
+ uint32_t LCG;
+
+ /* 64-bit xorshift (fast, moderate strength) */
+ uint32_t xs64_x;
+ uint32_t xs64_y;
} random_t;
#define UNINITED_RANDOM_T(rnd) \
((rnd)->galois_LFSR == 0)
#define INIT_RANDOM_T(rnd, nonzero, v) \
- ((rnd)->galois_LFSR = (nonzero), (rnd)->LCG = (v))
+ ((rnd)->galois_LFSR = (rnd)->xs64_x = (nonzero), (rnd)->LCG = (rnd)->xs64_y = (v))
#define CLEAR_RANDOM_T(rnd) \
((rnd)->galois_LFSR = 0)
diff --git a/release/src/router/busybox/shell/shell_common.c b/release/src/router/busybox/shell/shell_common.c
index 4879524b13..14eeaafcc6 100644
--- a/release/src/router/busybox/shell/shell_common.c
+++ b/release/src/router/busybox/shell/shell_common.c
@@ -18,6 +18,7 @@
*/
#include "libbb.h"
#include "shell_common.h"
+#include <sys/resource.h> /* getrlimit */
const char defifsvar[] ALIGN1 = "IFS= \t\n";
@@ -36,7 +37,7 @@ int FAST_FUNC is_well_formed_var_name(const char *s, char terminator)
/* read builtin */
-/* Needs to be interruptible: shell mush handle traps and shell-special signals
+/* Needs to be interruptible: shell must handle traps and shell-special signals
* while inside read. To implement this, be sure to not loop on EINTR
* and return errno == EINTR reliably.
*/
@@ -327,7 +328,7 @@ enum {
};
/* "-": treat args as parameters of option with ASCII code 1 */
-static const char ulimit_opt_string[] = "-HSa"
+static const char ulimit_opt_string[] ALIGN1 = "-HSa"
#ifdef RLIMIT_FSIZE
"f::"
#endif
@@ -379,7 +380,7 @@ static void printlim(unsigned opts, const struct rlimit *limit,
val = limit->rlim_cur;
if (val == RLIM_INFINITY)
- printf("unlimited\n");
+ puts("unlimited");
else {
val >>= l->factor_shift;
printf("%llu\n", (long long) val);
@@ -492,7 +493,6 @@ shell_builtin_ulimit(char **argv)
/* bad option. getopt already complained. */
break;
}
-
} /* while (there are options) */
return 0;
diff --git a/release/src/router/busybox/shell/shell_common.h b/release/src/router/busybox/shell/shell_common.h
index f06bc41208..993ed59511 100644
--- a/release/src/router/busybox/shell/shell_common.h
+++ b/release/src/router/busybox/shell/shell_common.h
@@ -21,7 +21,7 @@
PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
-extern const char defifsvar[]; /* "IFS= \t\n" */
+extern const char defifsvar[] ALIGN1; /* "IFS= \t\n" */
#define defifs (defifsvar + 4)
int FAST_FUNC is_well_formed_var_name(const char *s, char terminator);
diff --git a/release/src/router/busybox/sysklogd/Config.src b/release/src/router/busybox/sysklogd/Config.src
index b7a494eff0..684e7d4140 100644
--- a/release/src/router/busybox/sysklogd/Config.src
+++ b/release/src/router/busybox/sysklogd/Config.src
@@ -7,147 +7,4 @@ menu "System Logging Utilities"
INSERT
-config SYSLOGD
- bool "syslogd"
- default y
- help
- The syslogd utility is used to record logs of all the
- significant events that occur on a system. Every
- message that is logged records the date and time of the
- event, and will generally also record the name of the
- application that generated the message. When used in
- conjunction with klogd, messages from the Linux kernel
- can also be recorded. This is terribly useful,
- especially for finding what happened when something goes
- wrong. And something almost always will go wrong if
- you wait long enough....
-
-config FEATURE_ROTATE_LOGFILE
- bool "Rotate message files"
- default y
- depends on SYSLOGD
- help
- This enables syslogd to rotate the message files
- on his own. No need to use an external rotatescript.
-
-config FEATURE_REMOTE_LOG
- bool "Remote Log support"
- default y
- depends on SYSLOGD
- help
- When you enable this feature, the syslogd utility can
- be used to send system log messages to another system
- connected via a network. This allows the remote
- machine to log all the system messages, which can be
- terribly useful for reducing the number of serial
- cables you use. It can also be a very good security
- measure to prevent system logs from being tampered with
- by an intruder.
-
-config FEATURE_SYSLOGD_DUP
- bool "Support -D (drop dups) option"
- default y
- depends on SYSLOGD
- help
- Option -D instructs syslogd to drop consecutive messages
- which are totally the same.
-
-config FEATURE_SYSLOGD_CFG
- bool "Support syslog.conf"
- default y
- depends on SYSLOGD
- help
- Supports restricted syslogd config. See docs/syslog.conf.txt
-
-config FEATURE_SYSLOGD_READ_BUFFER_SIZE
- int "Read buffer size in bytes"
- default 256
- range 256 20000
- depends on SYSLOGD
- help
- This option sets the size of the syslog read buffer.
- Actual memory usage increases around five times the
- change done here.
-
-config FEATURE_IPC_SYSLOG
- bool "Circular Buffer support"
- default y
- depends on SYSLOGD
- help
- When you enable this feature, the syslogd utility will
- use a circular buffer to record system log messages.
- When the buffer is filled it will continue to overwrite
- the oldest messages. This can be very useful for
- systems with little or no permanent storage, since
- otherwise system logs can eventually fill up your
- entire filesystem, which may cause your system to
- break badly.
-
-config FEATURE_IPC_SYSLOG_BUFFER_SIZE
- int "Circular buffer size in Kbytes (minimum 4KB)"
- default 16
- range 4 2147483647
- depends on FEATURE_IPC_SYSLOG
- help
- This option sets the size of the circular buffer
- used to record system log messages.
-
-config LOGREAD
- bool "logread"
- default y
- depends on FEATURE_IPC_SYSLOG
- help
- If you enabled Circular Buffer support, you almost
- certainly want to enable this feature as well. This
- utility will allow you to read the messages that are
- stored in the syslogd circular buffer.
-
-config FEATURE_LOGREAD_REDUCED_LOCKING
- bool "Double buffering"
- default y
- depends on LOGREAD
- help
- 'logread' ouput to slow serial terminals can have
- side effects on syslog because of the semaphore.
- This option make logread to double buffer copy
- from circular buffer, minimizing semaphore
- contention at some minor memory expense.
-
-config KLOGD
- bool "klogd"
- default y
- help
- klogd is a utility which intercepts and logs all
- messages from the Linux kernel and sends the messages
- out to the 'syslogd' utility so they can be logged. If
- you wish to record the messages produced by the kernel,
- you should enable this option.
-
-config FEATURE_KLOGD_KLOGCTL
- bool "Use the klogctl() interface"
- default y
- depends on KLOGD
- select PLATFORM_LINUX
- help
- The klogd applet supports two interfaces for reading
- kernel messages. Linux provides the klogctl() interface
- which allows reading messages from the kernel ring buffer
- independently from the file system.
-
- If you answer 'N' here, klogd will use the more portable
- approach of reading them from /proc or a device node.
- However, this method requires the file to be available.
-
- If in doubt, say 'Y'.
-
-config LOGGER
- bool "logger"
- default y
- select FEATURE_SYSLOG
- help
- The logger utility allows you to send arbitrary text
- messages to the system log (i.e. the 'syslogd' utility) so
- they can be logged. This is generally used to help locate
- problems that occur within programs and scripts.
-
endmenu
diff --git a/release/src/router/busybox/sysklogd/Kbuild.src b/release/src/router/busybox/sysklogd/Kbuild.src
index d386cc2912..6b4fb74700 100644
--- a/release/src/router/busybox/sysklogd/Kbuild.src
+++ b/release/src/router/busybox/sysklogd/Kbuild.src
@@ -7,7 +7,3 @@
lib-y:=
INSERT
-lib-$(CONFIG_KLOGD) += klogd.o
-lib-$(CONFIG_LOGGER) += syslogd_and_logger.o
-lib-$(CONFIG_LOGREAD) += logread.o
-lib-$(CONFIG_SYSLOGD) += syslogd_and_logger.o
diff --git a/release/src/router/busybox/sysklogd/klogd.c b/release/src/router/busybox/sysklogd/klogd.c
index 894633b084..4db72110d9 100644
--- a/release/src/router/busybox/sysklogd/klogd.c
+++ b/release/src/router/busybox/sysklogd/klogd.c
@@ -16,6 +16,39 @@
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//config:config KLOGD
+//config: bool "klogd"
+//config: default y
+//config: help
+//config: klogd is a utility which intercepts and logs all
+//config: messages from the Linux kernel and sends the messages
+//config: out to the 'syslogd' utility so they can be logged. If
+//config: you wish to record the messages produced by the kernel,
+//config: you should enable this option.
+//config:
+//config:comment "klogd should not be used together with syslog to kernel printk buffer"
+//config: depends on KLOGD && FEATURE_KMSG_SYSLOG
+//config:
+//config:config FEATURE_KLOGD_KLOGCTL
+//config: bool "Use the klogctl() interface"
+//config: default y
+//config: depends on KLOGD
+//config: select PLATFORM_LINUX
+//config: help
+//config: The klogd applet supports two interfaces for reading
+//config: kernel messages. Linux provides the klogctl() interface
+//config: which allows reading messages from the kernel ring buffer
+//config: independently from the file system.
+//config:
+//config: If you answer 'N' here, klogd will use the more portable
+//config: approach of reading them from /proc or a device node.
+//config: However, this method requires the file to be available.
+//config:
+//config: If in doubt, say 'Y'.
+
+//applet:IF_KLOGD(APPLET(klogd, BB_DIR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_KLOGD) += klogd.o
//usage:#define klogd_trivial_usage
//usage: "[-c N] [-n]"
@@ -25,6 +58,7 @@
//usage: "\n -n Run in foreground"
#include "libbb.h"
+#include "common_bufsiz.h"
#include <syslog.h>
@@ -65,7 +99,6 @@ static void klogd_close(void)
#else
-# include <paths.h>
# ifndef _PATH_KLOG
# ifdef __GNU__
# define _PATH_KLOG "/dev/klog"
@@ -113,9 +146,9 @@ static void klogd_close(void)
#endif
-char log_buffer[6 * 1024 + 1]; /* Big enough to not lose msgs at bootup */
+#define log_buffer bb_common_bufsiz1
enum {
- KLOGD_LOGBUF_SIZE = sizeof(log_buffer),
+ KLOGD_LOGBUF_SIZE = COMMON_BUFSIZE,
OPT_LEVEL = (1 << 0),
OPT_FOREGROUND = (1 << 1),
};
@@ -140,7 +173,8 @@ int klogd_main(int argc UNUSED_PARAM, char **argv)
char *opt_c;
int opt;
int used;
- unsigned int cnt;
+
+ setup_common_bufsiz();
opt = getopt32(argv, "c:n", &opt_c);
if (opt & OPT_LEVEL) {
@@ -196,13 +230,13 @@ int klogd_main(int argc UNUSED_PARAM, char **argv)
syslog(LOG_NOTICE, "klogd started: %s", bb_banner);
+ write_pidfile(CONFIG_PID_FILE_PATH "/klogd.pid");
+
used = 0;
- cnt = 0;
while (!bb_got_signal) {
int n;
int priority;
char *start;
- char *eor;
/* "2 -- Read from the log." */
start = log_buffer + used;
@@ -214,7 +248,6 @@ int klogd_main(int argc UNUSED_PARAM, char **argv)
break;
}
start[n] = '\0';
- eor = &start[n];
/* Process each newline-terminated line in the buffer */
start = log_buffer;
@@ -242,22 +275,14 @@ int klogd_main(int argc UNUSED_PARAM, char **argv)
priority = LOG_INFO;
if (*start == '<') {
start++;
- if (*start) {
- /* kernel never generates multi-digit prios */
- priority = (*start - '0');
- start++;
- }
+ if (*start)
+ priority = strtoul(start, &start, 10);
if (*start == '>')
start++;
}
/* Log (only non-empty lines) */
- if (*start) {
- syslog(priority, "%s", start);
- /* give syslog time to catch up */
- ++cnt;
- if ((cnt & 0x07) == 0 && (cnt < 300 || (eor - start) > 200))
- usleep(50 * 1000);
- }
+ if (*start)
+ syslog(priority, "%s", start);
if (!newline)
break;
@@ -267,6 +292,7 @@ int klogd_main(int argc UNUSED_PARAM, char **argv)
klogd_close();
syslog(LOG_NOTICE, "klogd: exiting");
+ remove_pidfile(CONFIG_PID_FILE_PATH "/klogd.pid");
if (bb_got_signal)
kill_myself_with_sig(bb_got_signal);
return EXIT_FAILURE;
diff --git a/release/src/router/busybox/sysklogd/logger.c b/release/src/router/busybox/sysklogd/logger.c
index c68b98e36a..81bc1a0105 100644
--- a/release/src/router/busybox/sysklogd/logger.c
+++ b/release/src/router/busybox/sysklogd/logger.c
@@ -6,12 +6,26 @@
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//config:config LOGGER
+//config: bool "logger"
+//config: default y
+//config: select FEATURE_SYSLOG
+//config: help
+//config: The logger utility allows you to send arbitrary text
+//config: messages to the system log (i.e. the 'syslogd' utility) so
+//config: they can be logged. This is generally used to help locate
+//config: problems that occur within programs and scripts.
+
+//applet:IF_LOGGER(APPLET(logger, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_LOGGER) += syslogd_and_logger.o
//usage:#define logger_trivial_usage
//usage: "[OPTIONS] [MESSAGE]"
//usage:#define logger_full_usage "\n\n"
//usage: "Write MESSAGE (or stdin) to syslog\n"
//usage: "\n -s Log to stderr as well as the system log"
+//usage: "\n -c Log to console as well as the system log"
//usage: "\n -t TAG Log using the specified tag (defaults to user name)"
//usage: "\n -p PRIO Priority (numeric or facility.level pair)"
//usage:
@@ -85,7 +99,9 @@ int logger_main(int argc UNUSED_PARAM, char **argv)
char *str_p, *str_t;
int opt;
int i = 0;
- FILE *f = NULL;
+ int fd = -1;
+
+ setup_common_bufsiz();
/* Fill out the name string early (may be overwritten later) */
str_t = uid2uname_utoa(geteuid());
@@ -95,13 +111,13 @@ int logger_main(int argc UNUSED_PARAM, char **argv)
if (opt & 0x2) /* -s */
i |= LOG_PERROR;
- if (opt & 0x8) { /* -c */
- f = fopen_for_write(DEV_CONSOLE);
- if (!f)
- bb_error_msg("can't open console: %d %s\n", errno, strerror(errno));
- }
//if (opt & 0x4) /* -t */
openlog(str_t, i, 0);
+ if (opt & 0x8) { /* -c */
+ fd = device_open(DEV_CONSOLE, O_WRONLY | O_NOCTTY | O_NONBLOCK);
+ if (fd < 0)
+ bb_error_msg("can't open console");
+ }
i = LOG_USER | LOG_WARNING;
if (opt & 0x1) /* -p */
i = pencode(str_p);
@@ -114,8 +130,10 @@ int logger_main(int argc UNUSED_PARAM, char **argv)
) {
/* Neither "" nor "\n" */
syslog(i, "%s", strbuf);
- if (f)
- fprintf(f, "%s", strbuf);
+ if (fd >= 0) {
+ fdprintf(fd, "%s: %s%s", str_t, strbuf,
+ strchr(strbuf, '\n') ? "" : "\n");
+ }
}
}
} else {
@@ -129,13 +147,15 @@ int logger_main(int argc UNUSED_PARAM, char **argv)
pos = len;
} while (*++argv);
syslog(i, "%s", message + 1); /* skip leading " " */
- if (f)
- fprintf(f, "%s", message + 1);
+ if (fd >= 0 && len) {
+ fdprintf(fd, "%s:%s%s", str_t, message,
+ message[len - 1] == '\n' ? "" : "\n");
+ }
}
closelog();
- if (f)
- fclose(f);
+ if (fd >= 0)
+ close(fd);
return EXIT_SUCCESS;
}
diff --git a/release/src/router/busybox/sysklogd/logread.c b/release/src/router/busybox/sysklogd/logread.c
index 9939569040..5b999730ae 100644
--- a/release/src/router/busybox/sysklogd/logread.c
+++ b/release/src/router/busybox/sysklogd/logread.c
@@ -8,14 +8,41 @@
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//config:config LOGREAD
+//config: bool "logread"
+//config: default y
+//config: depends on FEATURE_IPC_SYSLOG
+//config: help
+//config: If you enabled Circular Buffer support, you almost
+//config: certainly want to enable this feature as well. This
+//config: utility will allow you to read the messages that are
+//config: stored in the syslogd circular buffer.
+//config:
+//config:config FEATURE_LOGREAD_REDUCED_LOCKING
+//config: bool "Double buffering"
+//config: default y
+//config: depends on LOGREAD
+//config: help
+//config: 'logread' ouput to slow serial terminals can have
+//config: side effects on syslog because of the semaphore.
+//config: This option make logread to double buffer copy
+//config: from circular buffer, minimizing semaphore
+//config: contention at some minor memory expense.
+//config:
+
+//applet:IF_LOGREAD(APPLET(logread, BB_DIR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_LOGREAD) += logread.o
//usage:#define logread_trivial_usage
-//usage: "[-f]"
+//usage: "[-fF]"
//usage:#define logread_full_usage "\n\n"
//usage: "Show messages in syslogd's circular buffer\n"
//usage: "\n -f Output data as log grows"
+//usage: "\n -F Same as -f, but dump buffer first"
#include "libbb.h"
+#include "common_bufsiz.h"
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
@@ -41,21 +68,27 @@ struct globals {
struct sembuf SMrdn[2]; // {1, 0}, {0, +1, SEM_UNDO}
struct shbuf_ds *shbuf;
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define SMrup (G.SMrup)
#define SMrdn (G.SMrdn)
#define shbuf (G.shbuf)
#define INIT_G() do { \
+ setup_common_bufsiz(); \
memcpy(SMrup, init_sem, sizeof(init_sem)); \
} while (0)
+#if 0
static void error_exit(const char *str) NORETURN;
static void error_exit(const char *str)
{
- //release all acquired resources
+ /* Release all acquired resources */
shmdt(shbuf);
bb_perror_msg_and_die(str);
}
+#else
+/* On Linux, shmdt is not mandatory on exit */
+# define error_exit(str) bb_perror_msg_and_die(str)
+#endif
/*
* sem_up - up()'s a semaphore.
@@ -66,11 +99,10 @@ static void sem_up(int semid)
error_exit("semop[SMrup]");
}
-static void interrupted(int sig UNUSED_PARAM)
+static void interrupted(int sig)
{
- signal(SIGINT, SIG_IGN);
- shmdt(shbuf);
- exit(EXIT_SUCCESS);
+ /* shmdt(shbuf); - on Linux, shmdt is not mandatory on exit */
+ kill_myself_with_sig(sig);
}
int logread_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -79,30 +111,30 @@ int logread_main(int argc UNUSED_PARAM, char **argv)
unsigned cur;
int log_semid; /* ipc semaphore id */
int log_shmid; /* ipc shared memory id */
- smallint follow = getopt32(argv, "f");
+ int follow = getopt32(argv, "fF");
INIT_G();
log_shmid = shmget(KEY_ID, 0, 0);
if (log_shmid == -1)
- bb_perror_msg_and_die("can't find syslogd buffer");
+ bb_perror_msg_and_die("can't %s syslogd buffer", "find");
/* Attach shared memory to our char* */
shbuf = shmat(log_shmid, NULL, SHM_RDONLY);
if (shbuf == NULL)
- bb_perror_msg_and_die("can't access syslogd buffer");
+ bb_perror_msg_and_die("can't %s syslogd buffer", "access");
log_semid = semget(KEY_ID, 0, 0);
if (log_semid == -1)
error_exit("can't get access to semaphores for syslogd buffer");
- signal(SIGINT, interrupted);
+ bb_signals(BB_FATAL_SIGS, interrupted);
/* Suppose atomic memory read */
/* Max possible value for tail is shbuf->size - 1 */
cur = shbuf->tail;
- /* Loop for logread -f, one pass if there was no -f */
+ /* Loop for -f or -F, one pass otherwise */
do {
unsigned shbuf_size;
unsigned shbuf_tail;
@@ -122,10 +154,15 @@ int logread_main(int argc UNUSED_PARAM, char **argv)
shbuf_data = shbuf->data; /* pointer! */
if (DEBUG)
- printf("cur:%d tail:%i size:%i\n",
+ printf("cur:%u tail:%u size:%u\n",
cur, shbuf_tail, shbuf_size);
- if (!follow) {
+ if (!(follow & 1)) { /* not -f */
+ /* if -F, "convert" it to -f, so that we dont
+ * dump the entire buffer on each iteration
+ */
+ follow >>= 1;
+
/* advance to oldest complete message */
/* find NUL */
cur += strlen(shbuf_data + cur);
@@ -138,7 +175,7 @@ int logread_main(int argc UNUSED_PARAM, char **argv)
cur++;
if (cur >= shbuf_size) /* last byte in buffer? */
cur = 0;
- } else { /* logread -f */
+ } else { /* -f */
if (cur == shbuf_tail) {
sem_up(log_semid);
fflush_all();
@@ -183,9 +220,10 @@ int logread_main(int argc UNUSED_PARAM, char **argv)
}
free(copy);
#endif
+ fflush_all();
} while (follow);
- shmdt(shbuf);
+ /* shmdt(shbuf); - on Linux, shmdt is not mandatory on exit */
fflush_stdout_and_exit(EXIT_SUCCESS);
}
diff --git a/release/src/router/busybox/sysklogd/syslogd.c b/release/src/router/busybox/sysklogd/syslogd.c
index f302d5f053..4bd0ada4cd 100644
--- a/release/src/router/busybox/sysklogd/syslogd.c
+++ b/release/src/router/busybox/sysklogd/syslogd.c
@@ -12,6 +12,107 @@
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//config:config SYSLOGD
+//config: bool "syslogd"
+//config: default y
+//config: help
+//config: The syslogd utility is used to record logs of all the
+//config: significant events that occur on a system. Every
+//config: message that is logged records the date and time of the
+//config: event, and will generally also record the name of the
+//config: application that generated the message. When used in
+//config: conjunction with klogd, messages from the Linux kernel
+//config: can also be recorded. This is terribly useful,
+//config: especially for finding what happened when something goes
+//config: wrong. And something almost always will go wrong if
+//config: you wait long enough....
+//config:
+//config:config FEATURE_ROTATE_LOGFILE
+//config: bool "Rotate message files"
+//config: default y
+//config: depends on SYSLOGD
+//config: help
+//config: This enables syslogd to rotate the message files
+//config: on his own. No need to use an external rotate script.
+//config:
+//config:config FEATURE_REMOTE_LOG
+//config: bool "Remote Log support"
+//config: default y
+//config: depends on SYSLOGD
+//config: help
+//config: When you enable this feature, the syslogd utility can
+//config: be used to send system log messages to another system
+//config: connected via a network. This allows the remote
+//config: machine to log all the system messages, which can be
+//config: terribly useful for reducing the number of serial
+//config: cables you use. It can also be a very good security
+//config: measure to prevent system logs from being tampered with
+//config: by an intruder.
+//config:
+//config:config FEATURE_SYSLOGD_DUP
+//config: bool "Support -D (drop dups) option"
+//config: default y
+//config: depends on SYSLOGD
+//config: help
+//config: Option -D instructs syslogd to drop consecutive messages
+//config: which are totally the same.
+//config:
+//config:config FEATURE_SYSLOGD_CFG
+//config: bool "Support syslog.conf"
+//config: default y
+//config: depends on SYSLOGD
+//config: help
+//config: Supports restricted syslogd config. See docs/syslog.conf.txt
+//config:
+//config:config FEATURE_SYSLOGD_READ_BUFFER_SIZE
+//config: int "Read buffer size in bytes"
+//config: default 256
+//config: range 256 20000
+//config: depends on SYSLOGD
+//config: help
+//config: This option sets the size of the syslog read buffer.
+//config: Actual memory usage increases around five times the
+//config: change done here.
+//config:
+//config:config FEATURE_IPC_SYSLOG
+//config: bool "Circular Buffer support"
+//config: default y
+//config: depends on SYSLOGD
+//config: help
+//config: When you enable this feature, the syslogd utility will
+//config: use a circular buffer to record system log messages.
+//config: When the buffer is filled it will continue to overwrite
+//config: the oldest messages. This can be very useful for
+//config: systems with little or no permanent storage, since
+//config: otherwise system logs can eventually fill up your
+//config: entire filesystem, which may cause your system to
+//config: break badly.
+//config:
+//config:config FEATURE_IPC_SYSLOG_BUFFER_SIZE
+//config: int "Circular buffer size in Kbytes (minimum 4KB)"
+//config: default 16
+//config: range 4 2147483647
+//config: depends on FEATURE_IPC_SYSLOG
+//config: help
+//config: This option sets the size of the circular buffer
+//config: used to record system log messages.
+//config:
+//config:config FEATURE_KMSG_SYSLOG
+//config: bool "Linux kernel printk buffer support"
+//config: default y
+//config: depends on SYSLOGD
+//config: select PLATFORM_LINUX
+//config: help
+//config: When you enable this feature, the syslogd utility will
+//config: write system log message to the Linux kernel's printk buffer.
+//config: This can be used as a smaller alternative to the syslogd IPC
+//config: support, as klogd and logread aren't needed.
+//config:
+//config: NOTICE: Syslog facilities in log entries needs kernel 3.5+.
+
+//applet:IF_SYSLOGD(APPLET(syslogd, BB_DIR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_SYSLOGD) += syslogd_and_logger.o
//usage:#define syslogd_trivial_usage
//usage: "[OPTIONS]"
@@ -21,24 +122,27 @@
//usage: "(this version of syslogd ignores /etc/syslog.conf)\n"
//usage: )
//usage: "\n -n Run in foreground"
-//usage: "\n -O FILE Log to FILE (default:/var/log/messages)"
-//usage: "\n -l N Log only messages more urgent than prio N (1-8)"
-//usage: "\n -S Smaller output"
-//usage: IF_FEATURE_ROTATE_LOGFILE(
-//usage: "\n -s SIZE Max size (KB) before rotation (default:200KB, 0=off)"
-//usage: "\n -b N N rotated logs to keep (default:1, max=99, 0=purge)"
-//usage: )
//usage: IF_FEATURE_REMOTE_LOG(
-//usage: "\n -R HOST[:PORT] Log to IP or hostname on PORT (default PORT=514/UDP)"
+//usage: "\n -R HOST[:PORT] Log to HOST:PORT (default PORT:514)"
//usage: "\n -L Log locally and via network (default is network only if -R)"
//usage: )
-//usage: IF_FEATURE_SYSLOGD_DUP(
-//usage: "\n -D Drop duplicates"
-//usage: )
//usage: IF_FEATURE_IPC_SYSLOG(
/* NB: -Csize shouldn't have space (because size is optional) */
//usage: "\n -C[size_kb] Log to shared mem buffer (use logread to read it)"
//usage: )
+//usage: IF_FEATURE_KMSG_SYSLOG(
+//usage: "\n -K Log to kernel printk buffer (use dmesg to read it)"
+//usage: )
+//usage: "\n -O FILE Log to FILE (default: /var/log/messages, stdout if -)"
+//usage: IF_FEATURE_ROTATE_LOGFILE(
+//usage: "\n -s SIZE Max size (KB) before rotation (default:200KB, 0=off)"
+//usage: "\n -b N N rotated logs to keep (default:1, max=99, 0=purge)"
+//usage: )
+//usage: "\n -l N Log only messages more urgent than prio N (1-8)"
+//usage: "\n -S Smaller output"
+//usage: IF_FEATURE_SYSLOGD_DUP(
+//usage: "\n -D Drop duplicates"
+//usage: )
//usage: IF_FEATURE_SYSLOGD_CFG(
//usage: "\n -f FILE Use FILE as config (default:/etc/syslog.conf)"
//usage: )
@@ -55,6 +159,9 @@
#define SYSLOG_NAMES_CONST
#include <syslog.h>
*/
+#ifndef _PATH_LOG
+#define _PATH_LOG "/dev/log"
+#endif
#include <sys/un.h>
#include <sys/uio.h>
@@ -104,6 +211,7 @@ typedef struct {
typedef struct logFile_t {
const char *path;
int fd;
+ time_t last_log_time;
#if ENABLE_FEATURE_ROTATE_LOGFILE
unsigned size;
uint8_t isRegular;
@@ -140,6 +248,10 @@ IF_FEATURE_IPC_SYSLOG( \
) \
IF_FEATURE_SYSLOGD_CFG( \
logRule_t *log_rules; \
+) \
+IF_FEATURE_KMSG_SYSLOG( \
+ int kmsgfd; \
+ int primask; \
)
struct init_globals {
@@ -155,7 +267,6 @@ struct globals {
#if ENABLE_FEATURE_IPC_SYSLOG
struct shbuf_ds *shbuf;
#endif
- time_t last_log_time;
/* localhost's name. We print only first 64 chars */
char *hostname;
@@ -212,6 +323,7 @@ enum {
IF_FEATURE_IPC_SYSLOG( OPTBIT_circularlog,) // -C
IF_FEATURE_SYSLOGD_DUP( OPTBIT_dup ,) // -D
IF_FEATURE_SYSLOGD_CFG( OPTBIT_cfg ,) // -f
+ IF_FEATURE_KMSG_SYSLOG( OPTBIT_kmsg ,) // -K
OPT_mark = 1 << OPTBIT_mark ,
OPT_nofork = 1 << OPTBIT_nofork ,
@@ -225,6 +337,7 @@ enum {
OPT_circularlog = IF_FEATURE_IPC_SYSLOG( (1 << OPTBIT_circularlog)) + 0,
OPT_dup = IF_FEATURE_SYSLOGD_DUP( (1 << OPTBIT_dup )) + 0,
OPT_cfg = IF_FEATURE_SYSLOGD_CFG( (1 << OPTBIT_cfg )) + 0,
+ OPT_kmsg = IF_FEATURE_KMSG_SYSLOG( (1 << OPTBIT_kmsg )) + 0,
};
#define OPTION_STR "m:nO:l:S" \
IF_FEATURE_ROTATE_LOGFILE("s:" ) \
@@ -233,7 +346,8 @@ enum {
IF_FEATURE_REMOTE_LOG( "L" ) \
IF_FEATURE_IPC_SYSLOG( "C::") \
IF_FEATURE_SYSLOGD_DUP( "D" ) \
- IF_FEATURE_SYSLOGD_CFG( "f:" )
+ IF_FEATURE_SYSLOGD_CFG( "f:" ) \
+ IF_FEATURE_KMSG_SYSLOG( "K" )
#define OPTION_DECL *opt_m, *opt_l \
IF_FEATURE_ROTATE_LOGFILE(,*opt_s) \
IF_FEATURE_ROTATE_LOGFILE(,*opt_b) \
@@ -242,7 +356,7 @@ enum {
#define OPTION_PARAM &opt_m, &(G.logFile.path), &opt_l \
IF_FEATURE_ROTATE_LOGFILE(,&opt_s) \
IF_FEATURE_ROTATE_LOGFILE(,&opt_b) \
- IF_FEATURE_REMOTE_LOG( ,&remoteAddrList) \
+ IF_FEATURE_REMOTE_LOG( ,&remoteAddrList) \
IF_FEATURE_IPC_SYSLOG( ,&opt_C) \
IF_FEATURE_SYSLOGD_CFG( ,&opt_f)
@@ -418,7 +532,9 @@ static void parse_syslogdcfg(const char *file)
return;
cfgerr:
- bb_error_msg_and_die("error in '%s' at line %d", file, parser->lineno);
+ bb_error_msg_and_die("error in '%s' at line %d",
+ file ? file : "/etc/syslog.conf",
+ parser->lineno);
}
#endif
@@ -518,11 +634,49 @@ static void log_to_shmem(const char *msg)
printf("tail:%d\n", G.shbuf->tail);
}
#else
-void ipcsyslog_cleanup(void);
-void ipcsyslog_init(void);
+static void ipcsyslog_cleanup(void) {}
+static void ipcsyslog_init(void) {}
void log_to_shmem(const char *msg);
#endif /* FEATURE_IPC_SYSLOG */
+#if ENABLE_FEATURE_KMSG_SYSLOG
+static void kmsg_init(void)
+{
+ G.kmsgfd = xopen("/dev/kmsg", O_WRONLY);
+
+ /*
+ * kernel < 3.5 expects single char printk KERN_* priority prefix,
+ * from 3.5 onwards the full syslog facility/priority format is supported
+ */
+ if (get_linux_version_code() < KERNEL_VERSION(3,5,0))
+ G.primask = LOG_PRIMASK;
+ else
+ G.primask = -1;
+}
+
+static void kmsg_cleanup(void)
+{
+ if (ENABLE_FEATURE_CLEAN_UP)
+ close(G.kmsgfd);
+}
+
+/* Write message to /dev/kmsg */
+static void log_to_kmsg(int pri, const char *msg)
+{
+ /*
+ * kernel < 3.5 expects single char printk KERN_* priority prefix,
+ * from 3.5 onwards the full syslog facility/priority format is supported
+ */
+ pri &= G.primask;
+
+ full_write(G.kmsgfd, G.printbuf, sprintf(G.printbuf, "<%d>%s\n", pri, msg));
+}
+#else
+static void kmsg_init(void) {}
+static void kmsg_cleanup(void) {}
+static void log_to_kmsg(int pri UNUSED_PARAM, const char *msg UNUSED_PARAM) {}
+#endif /* FEATURE_KMSG_SYSLOG */
+
/* Print a message to the log file. */
static void log_locally(time_t now, char *msg, logFile_t *log_file)
{
@@ -531,42 +685,54 @@ static void log_locally(time_t now, char *msg, logFile_t *log_file)
#endif
int len = strlen(msg);
- if (log_file->fd >= 0) {
- /* Reopen log file every second. This allows admin
- * to delete the file and not worry about restarting us.
+ /* fd can't be 0 (we connect fd 0 to /dev/log socket) */
+ /* fd is 1 if "-O -" is in use */
+ if (log_file->fd > 1) {
+ /* Reopen log files every second. This allows admin
+ * to delete the files and not worry about restarting us.
* This costs almost nothing since it happens
- * _at most_ once a second.
+ * _at most_ once a second for each file, and happens
+ * only when each file is actually written.
*/
if (!now)
now = time(NULL);
- if (G.last_log_time != now) {
- G.last_log_time = now;
+ if (log_file->last_log_time != now) {
+ log_file->last_log_time = now;
close(log_file->fd);
goto reopen;
}
- } else {
+ }
+ else if (log_file->fd == 1) {
+ /* We are logging to stdout: do nothing */
+ }
+ else {
+ if (LONE_DASH(log_file->path)) {
+ log_file->fd = 1;
+ /* log_file->isRegular = 0; - already is */
+ } else {
reopen:
- log_file->fd = open(log_file->path, O_WRONLY | O_CREAT
+ log_file->fd = open(log_file->path, O_WRONLY | O_CREAT
| O_NOCTTY | O_APPEND | O_NONBLOCK,
0666);
- if (log_file->fd < 0) {
- /* cannot open logfile? - print to /dev/console then */
- int fd = device_open(DEV_CONSOLE, O_WRONLY | O_NOCTTY | O_NONBLOCK);
- if (fd < 0)
- fd = 2; /* then stderr, dammit */
- full_write(fd, msg, len);
- if (fd != 2)
- close(fd);
- return;
- }
+ if (log_file->fd < 0) {
+ /* cannot open logfile? - print to /dev/console then */
+ int fd = device_open(DEV_CONSOLE, O_WRONLY | O_NOCTTY | O_NONBLOCK);
+ if (fd < 0)
+ fd = 2; /* then stderr, dammit */
+ full_write(fd, msg, len);
+ if (fd != 2)
+ close(fd);
+ return;
+ }
#if ENABLE_FEATURE_ROTATE_LOGFILE
- {
- struct stat statf;
- log_file->isRegular = (fstat(log_file->fd, &statf) == 0 && S_ISREG(statf.st_mode));
- /* bug (mostly harmless): can wrap around if file > 4gb */
- log_file->size = statf.st_size;
- }
+ {
+ struct stat statf;
+ log_file->isRegular = (fstat(log_file->fd, &statf) == 0 && S_ISREG(statf.st_mode));
+ /* bug (mostly harmless): can wrap around if file > 4gb */
+ log_file->size = statf.st_size;
+ }
#endif
+ }
}
#ifdef SYSLOGD_WRLOCK
@@ -579,26 +745,58 @@ static void log_locally(time_t now, char *msg, logFile_t *log_file)
#if ENABLE_FEATURE_ROTATE_LOGFILE
if (G.logFileSize && log_file->isRegular && log_file->size > G.logFileSize) {
- if (G.logFileRotate) { /* always 0..1 */
+ if (G.logFileRotate) { /* always 0..99 */
int i = strlen(log_file->path) + 3 + 1;
char oldFile[i];
+ char newFile[i];
+#if 1 /* ASUS legacy */
+ i = G.logFileRotate;
+#else
+ i = G.logFileRotate - 1;
+#endif
+ /* rename: f.8 -> f.9; f.7 -> f.8; ... */
+ while (1) {
+#if 1 /* ASUS legacy */
+ sprintf(newFile, "%s-%d", log_file->path, i);
+ if (i == 1) break;
+ sprintf(oldFile, "%s-%d", log_file->path, --i);
+#else
+ sprintf(newFile, "%s.%d", log_file->path, i);
+ if (i == 0) break;
+ sprintf(oldFile, "%s.%d", log_file->path, --i);
+#endif
+ /* ignore errors - file might be missing */
+ rename(oldFile, newFile);
+ }
+ /* newFile == "f.0" now */
+ rename(log_file->path, newFile);
+ }
- sprintf(oldFile, "%s-1", log_file->path);
- unlink(oldFile);
- rename(log_file->path, oldFile);
-
+ /* We may or may not have just renamed the file away;
+ * if we didn't rename because we aren't keeping any backlog,
+ * then it's time to clobber the file. If we did rename it...,
+ * incredibly, if F and F.0 are hardlinks, POSIX _demands_
+ * that rename returns 0 but does not remove F!!!
+ * (hardlinked F/F.0 pair was observed after
+ * power failure during rename()).
+ * So ensure old file is gone in any case:
+ */
+ unlink(log_file->path);
#ifdef SYSLOGD_WRLOCK
- fl.l_type = F_UNLCK;
- fcntl(log_file->fd, F_SETLKW, &fl);
+ fl.l_type = F_UNLCK;
+ fcntl(log_file->fd, F_SETLKW, &fl);
#endif
- close(log_file->fd);
- goto reopen;
- }
- ftruncate(log_file->fd, 0);
+ close(log_file->fd);
+ goto reopen;
}
- log_file->size +=
+/* TODO: what to do on write errors ("disk full")? */
+ len = full_write(log_file->fd, msg, len);
+ if (len > 0)
+ log_file->size += len;
+#else
+ full_write(log_file->fd, msg, len);
#endif
- full_write(log_file->fd, msg, len);
+
#ifdef SYSLOGD_WRLOCK
fl.l_type = F_UNLCK;
fcntl(log_file->fd, F_SETLKW, &fl);
@@ -642,6 +840,11 @@ static void timestamp_and_log(int pri, char *msg, int len)
}
timestamp[15] = '\0';
+ if (option_mask32 & OPT_kmsg) {
+ log_to_kmsg(pri, msg);
+ return;
+ }
+
if (option_mask32 & OPT_small)
sprintf(G.printbuf, "%s %s\n", timestamp, msg);
else {
@@ -743,18 +946,13 @@ static NOINLINE int create_socket(void)
int sock_fd;
char *dev_log_name;
-#if ENABLE_FEATURE_SYSTEMD
- if (sd_listen_fds() == 1)
- return SD_LISTEN_FDS_START;
-#endif
-
memset(&sunx, 0, sizeof(sunx));
sunx.sun_family = AF_UNIX;
/* Unlink old /dev/log or object it points to. */
/* (if it exists, bind will fail) */
- strcpy(sunx.sun_path, "/dev/log");
- dev_log_name = xmalloc_follow_symlinks("/dev/log");
+ strcpy(sunx.sun_path, _PATH_LOG);
+ dev_log_name = xmalloc_follow_symlinks(_PATH_LOG);
if (dev_log_name) {
safe_strncpy(sunx.sun_path, dev_log_name, sizeof(sunx.sun_path));
free(dev_log_name);
@@ -763,7 +961,7 @@ static NOINLINE int create_socket(void)
sock_fd = xsocket(AF_UNIX, SOCK_DGRAM, 0);
xbind(sock_fd, (struct sockaddr *) &sunx, sizeof(sunx));
- chmod("/dev/log", 0666);
+ chmod(_PATH_LOG, 0666);
return sock_fd;
}
@@ -789,7 +987,6 @@ static int try_to_resolve_remote(remoteHost_t *rh)
static void do_syslogd(void) NORETURN;
static void do_syslogd(void)
{
- int sock_fd;
#if ENABLE_FEATURE_REMOTE_LOG
llist_t *item;
#endif
@@ -810,11 +1007,13 @@ static void do_syslogd(void)
signal(SIGALRM, do_mark);
alarm(G.markInterval);
#endif
- sock_fd = create_socket();
+ xmove_fd(create_socket(), STDIN_FILENO);
- if (ENABLE_FEATURE_IPC_SYSLOG && (option_mask32 & OPT_circularlog)) {
+ if (option_mask32 & OPT_circularlog)
ipcsyslog_init();
- }
+
+ if (option_mask32 & OPT_kmsg)
+ kmsg_init();
timestamp_and_log_internal("syslogd started: BusyBox v" BB_VER);
@@ -829,10 +1028,10 @@ static void do_syslogd(void)
recvbuf = G.recvbuf;
#endif
read_again:
- sz = read(sock_fd, recvbuf, MAX_READ - 1);
+ sz = read(STDIN_FILENO, recvbuf, MAX_READ - 1);
if (sz < 0) {
if (!bb_got_signal)
- bb_perror_msg("read from /dev/log");
+ bb_perror_msg("read from %s", _PATH_LOG);
break;
}
@@ -900,9 +1099,10 @@ static void do_syslogd(void)
} /* while (!bb_got_signal) */
timestamp_and_log_internal("syslogd exiting");
- puts("syslogd exiting");
- if (ENABLE_FEATURE_IPC_SYSLOG)
- ipcsyslog_cleanup();
+ remove_pidfile(CONFIG_PID_FILE_PATH "/syslogd.pid");
+ ipcsyslog_cleanup();
+ if (option_mask32 & OPT_kmsg)
+ kmsg_cleanup();
kill_myself_with_sig(bb_got_signal);
#undef recvbuf
}
@@ -939,13 +1139,12 @@ int syslogd_main(int argc UNUSED_PARAM, char **argv)
//if (opts & OPT_outfile) // -O
if (opts & OPT_loglevel) // -l
G.logLevel = xatou_range(opt_l, 1, 8);
- if (opts & OPT_small) // -S
- option_mask32 |= OPT_small; // make syslog smaller.
+ //if (opts & OPT_small) // -S
#if ENABLE_FEATURE_ROTATE_LOGFILE
if (opts & OPT_filesize) // -s
G.logFileSize = xatou_range(opt_s, 0, INT_MAX/1024) * 1024;
if (opts & OPT_rotatecnt) // -b
- G.logFileRotate = xatou_range(opt_b, 0, 1);
+ G.logFileRotate = xatou_range(opt_b, 0, 99);
#endif
#if ENABLE_FEATURE_IPC_SYSLOG
if (opt_C) // -Cn
@@ -965,8 +1164,10 @@ int syslogd_main(int argc UNUSED_PARAM, char **argv)
if (!(opts & OPT_nofork)) {
bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv);
}
+
//umask(0); - why??
- write_pidfile("/var/run/syslogd.pid");
+ write_pidfile(CONFIG_PID_FILE_PATH "/syslogd.pid");
+
do_syslogd();
/* return EXIT_SUCCESS; */
}
diff --git a/release/src/router/busybox/sysklogd/syslogd_and_logger.c b/release/src/router/busybox/sysklogd/syslogd_and_logger.c
index 0964f239cb..6458a9332c 100644
--- a/release/src/router/busybox/sysklogd/syslogd_and_logger.c
+++ b/release/src/router/busybox/sysklogd/syslogd_and_logger.c
@@ -8,6 +8,7 @@
*/
#include "libbb.h"
+#include "common_bufsiz.h"
#define SYSLOG_NAMES
#define SYSLOG_NAMES_CONST
#include <syslog.h>
diff --git a/release/src/router/busybox/testsuite/ar.tests b/release/src/router/busybox/testsuite/ar.tests
index 0a8eb9b324..ad7b8fe5fa 100755
--- a/release/src/router/busybox/testsuite/ar.tests
+++ b/release/src/router/busybox/testsuite/ar.tests
@@ -15,7 +15,7 @@ testing "ar creates archives" \
"$(md5sum <README)\n" \
"" \
""
-rm test.a
+rm test.a 2>/dev/null
testing "ar replaces things in archives" \
"echo 'blah!' >file1 && echo 'blast!' >file2 && ar cr test.a README file1 file2 && mv file2 file1 && ar cr test.a file1 && ar p test.a file1" \
diff --git a/release/src/router/busybox/testsuite/awk.tests b/release/src/router/busybox/testsuite/awk.tests
index 5a323047db..adab4ae1ec 100755
--- a/release/src/router/busybox/testsuite/awk.tests
+++ b/release/src/router/busybox/testsuite/awk.tests
@@ -16,11 +16,65 @@ testing "awk -F case 5" "awk -F '[#]' '{ print NF }'" "4\n" "" "#abc##zz\n"
testing "awk -F case 6" "awk -F '[#]' '{ print NF }'" "4\n" "" "z#abc##zz\n"
testing "awk -F case 7" "awk -F '[#]' '{ print NF }'" "5\n" "" "z##abc##zz\n"
+# conditions and operators
+testing "awk if operator == " "awk 'BEGIN{if(23==23) print \"foo\"}'" "foo\n" "" ""
+testing "awk if operator != " "awk 'BEGIN{if(23!=23) print \"bar\"}'" "" "" ""
+testing "awk if operator >= " "awk 'BEGIN{if(23>=23) print \"foo\"}'" "foo\n" "" ""
+testing "awk if operator < " "awk 'BEGIN{if(2 < 13) print \"foo\"}'" "foo\n" "" ""
+testing "awk if string == " "awk 'BEGIN{if(\"a\"==\"ab\") print \"bar\"}'" "" "" ""
+
# 4294967295 = 0xffffffff
-testing "awk bitwise op" "awk '{ print or(4294967295,1) }'" "4.29497e+09\n" "" "\n"
+testing "awk bitwise op" "awk '{ print or(4294967295,1) }'" "4294967295\n" "" "\n"
+
+# we were testing for a non-empty body when deciding if a function was
+# defined or not. The testcase below caused:
+# awk: cmd. line:8: Call to undefined function
+prg='
+function empty_fun(count) {
+ # empty
+}
+END {
+ i=1
+ print "L" i "\n"
+ empty_fun(i + i + ++i)
+ print "L" i "\n"
+}'
+testing "awk handles empty function f(arg){}" \
+ "awk '$prg'" \
+ "L1\n\nL2\n\n" \
+ "" ""
+
+prg='
+function outer_fun() {
+ return 1
+}
+END {
+ i=1
+ print "L" i "\n"
+ i += outer_fun()
+ print "L" i "\n"
+}'
+testing "awk properly handles function from other scope" \
+ "awk '$prg'" \
+ "L1\n\nL2\n\n" \
+ "" ""
+
+prg='
+END {
+ i=1
+ print "L" i "\n"
+ i + trigger_error_fun()
+ print "L" i "\n"
+}'
+testing "awk properly handles undefined function" \
+ "awk '$prg' 2>&1" \
+ "L1\n\nawk: cmd. line:5: Call to undefined function\n" \
+ "" ""
+
+
optional DESKTOP
-testing "awk hex const 1" "awk '{ print or(0xffffffff,1) }'" "4.29497e+09\n" "" "\n"
-testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2.14748e+09\n" "" "\n"
+testing "awk hex const 1" "awk '{ print or(0xffffffff,1) }'" "4294967295\n" "" "\n"
+testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2147483649\n" "" "\n"
testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n"
SKIP=
@@ -36,6 +90,11 @@ testing "awk long field sep" "awk -F-- '{ print NF, length(\$NF), \$NF }'" \
"" \
"a--\na--b--\na--b--c--\na--b--c--d--"
+testing "awk -F handles escapes" "awk -F'\\x21' '{print \$1}'" \
+ "a\n" \
+ "" \
+ "a!b\n"
+
# '@(samp|code|file)\{' is an invalid extended regex (unmatched '{'),
# but gawk 3.1.5 does not bail out on it.
testing "awk gsub falls back to non-extended-regex" \
@@ -205,4 +264,58 @@ end d
testing "awk handles empty ()" \
"awk 'BEGIN {print()}' 2>&1" "awk: cmd. line:1: Empty sequence\n" "" ""
+testing "awk FS assignment" "awk '{FS=\":\"; print \$1}'" \
+ "a:b\ne\n" \
+ "" \
+ "a:b c:d\ne:f g:h"
+
+optional FEATURE_AWK_LIBM
+testing "awk large integer" \
+ "awk 'BEGIN{n=(2^31)-1; print n, int(n), n%1, ++n, int(n), n%1}'" \
+ "2147483647 2147483647 0 2147483648 2147483648 0\n" \
+ "" ""
+SKIP=
+
+testing "awk length(array)" \
+ "awk 'BEGIN{ A[1]=2; A[\"qwe\"]=\"asd\"; print length(A)}'" \
+ "2\n" \
+ "" ""
+
+testing "awk length()" \
+ "awk '{print length; print length(); print length(\"qwe\"); print length(99+9)}'" \
+ "3\n3\n3\n3\n" \
+ "" "qwe"
+
+testing "awk -f and ARGC" \
+ "awk -f - input" \
+ "re\n2\n" \
+ "do re mi\n" \
+ '{print $2; print ARGC;}' \
+
+optional FEATURE_AWK_GNU_EXTENSIONS
+testing "awk -e and ARGC" \
+ "awk -e '{print \$2; print ARGC;}' input" \
+ "re\n2\n" \
+ "do re mi\n" \
+ ""
+SKIP=
+
+# The examples are in fact not valid awk programs (break/continue
+# can only be used inside loops).
+# But we do accept them outside of loops.
+# We had a bug with misparsing "break ; else" sequence.
+# Test that *that* bug is fixed, using simplest possible scripts:
+testing "awk break" \
+ "awk -f - 2>&1; echo \$?" \
+ "0\n" \
+ "" \
+ 'BEGIN { if (1) break; else a = 1 }'
+testing "awk continue" \
+ "awk -f - 2>&1; echo \$?" \
+ "0\n" \
+ "" \
+ 'BEGIN { if (1) continue; else a = 1 }'
+
+# testing "description" "command" "result" "infile" "stdin"
+
exit $FAILCOUNT
diff --git a/release/src/router/busybox/testsuite/busybox.tests b/release/src/router/busybox/testsuite/busybox.tests
index 04fea3ea24..545cad5c0a 100755
--- a/release/src/router/busybox/testsuite/busybox.tests
+++ b/release/src/router/busybox/testsuite/busybox.tests
@@ -6,6 +6,16 @@
. ./testing.sh
+ln -s `which busybox` unknown
+
+testing "busybox as unknown name" "./unknown 2>&1" \
+ "unknown: applet not found\n" "" ""
+rm unknown
+
+# We need busybox --help to be enabled for the rest of tests
+test x"$CONFIG_BUSYBOX" = x"y" \
+|| { echo "SKIPPED: busybox --help"; exit 0; }
+
HELPDUMP=`true | busybox 2>&1 | cat`
# We need to test under calling the binary under other names.
@@ -38,10 +48,4 @@ do
done
rm busybox-suffix
-ln -s `which busybox` unknown
-
-testing "busybox as unknown name" "./unknown 2>&1" \
- "unknown: applet not found\n" "" ""
-rm unknown
-
exit $FAILCOUNT
diff --git a/release/src/router/busybox/testsuite/bzcat.tests b/release/src/router/busybox/testsuite/bzcat.tests
index 1c1fd65631..0ae530dc70 100755
--- a/release/src/router/busybox/testsuite/bzcat.tests
+++ b/release/src/router/busybox/testsuite/bzcat.tests
@@ -2,8 +2,6 @@
FAILCOUNT=0
-ext=bz2
-
bb="busybox "
unset LC_ALL
@@ -11,6 +9,11 @@ unset LC_MESSAGES
unset LANG
unset LANGUAGE
+hello_Z() {
+ # Compressed "HELLO\n"
+ $ECHO -ne "\x1f\x9d\x90\x48\x8a\x30\x61\xf2\x44\x01"
+}
+
hello_gz() {
# Gzipped "HELLO\n"
#_________________________ vvv vvv vvv vvv - mtime
@@ -25,32 +28,38 @@ hello_bz2() {
$ECHO -ne "\x17\x72\x45\x38\x50\x90\x5b\xb8\xe8\xa3"
}
-prep() {
- rm -f t*
- hello_$ext >t1.$ext
- hello_$ext >t2.$ext
-}
-
-check() {
- eval $2 >t_actual 2>&1
- if $ECHO -ne "$expected" | cmp - t_actual; then
- echo "PASS: $1"
- else
- echo "FAIL: $1"
- FAILCOUNT=$((FAILCOUNT + 1))
- fi
-}
-
-mkdir testdir 2>/dev/null
-(
-cd testdir || { echo "cannot cd testdir!"; exit 1; }
-
-expected="HELLO\nok\n"
-prep; check "bzcat: dont delete src" "${bb}bzcat t2.bz2; test -f t2.bz2 && echo ok"
-
-)
-rm -rf testdir
-
+for ext in \
+ `test x"$CONFIG_GUNZIP" = x"y" && echo gz` \
+ `test x"$CONFIG_BUNZIP2" = x"y" && echo bz2` \
+ `test x"$CONFIG_UNCOMPRESS" = x"y" && echo Z`
+do
+ prep() {
+ rm -f t1.$ext t2.$ext t_actual
+ hello_$ext >t1.$ext
+ hello_$ext >t2.$ext
+ }
+
+ check() {
+ eval $2 >t_actual 2>&1
+ if $ECHO -ne "$expected" | cmp - t_actual; then
+ echo "PASS: $1"
+ else
+ echo "FAIL: $1"
+ FAILCOUNT=$((FAILCOUNT + 1))
+ fi
+ }
+
+ mkdir testdir 2>/dev/null
+ (
+ cd testdir || { echo "cannot cd testdir!"; exit 1; }
+ expected="HELLO\nok\n"
+ prep
+ check "zcat: dont delete $ext src" "${bb}zcat t2.$ext; test -f t2.$ext && echo ok"
+ exit $FAILCOUNT
+ )
+ FAILCOUNT=$?
+ rm -rf testdir
+done
# Copyright 2011 by Denys Vlasenko
@@ -60,6 +69,8 @@ rm -rf testdir
# testing "test name" "command" "expected result" "file input" "stdin"
+## bzip algorithm
+
# "input" file is bzipped file with "a\n" data
testing "bzcat can print many files" \
"$ECHO -ne '$hexdump' | bzcat input input; echo \$?" \
@@ -79,6 +90,27 @@ testing "bzcat can handle compressed zero-length bzip2 files" \
"0\n" \
"\x42\x5a\x68\x39\x17\x72\x45\x38\x50\x90\x00\x00\x00\x00" ""
+## compress algorithm
+
+# "input" file is compressed (.Z) file with "a\n" data
+test x"$CONFIG_UNCOMPRESS" = x"y" && \
+testing "zcat can print many files" \
+"$ECHO -ne '$hexdump' | zcat input input; echo \$?" \
+"\
+a
+a
+0
+" "\
+\x1f\x9d\x90\x61\x14\x00\
+" ""
+
+# "input" file is compressed (.Z) zero byte file
+test x"$CONFIG_UNCOMPRESS" = x"y" && \
+testing "zcat can handle compressed zero-length (.Z) files" \
+"$ECHO -ne '$hexdump' | zcat input input; echo \$?" \
+"0\n" \
+"\x1f\x9d\x90\x00" ""
+
exit $((FAILCOUNT <= 255 ? FAILCOUNT : 255))
diff --git a/release/src/router/busybox/testsuite/date/date-works b/release/src/router/busybox/testsuite/date/date-works
index 901c485ecc..35c24686c1 100644
--- a/release/src/router/busybox/testsuite/date/date-works
+++ b/release/src/router/busybox/testsuite/date/date-works
@@ -31,9 +31,11 @@ dt=`busybox date -d '1999-1-2 3:4:5'`
dt=`echo "$dt" | cut -b1-19`
test x"$dt" = x"Sat Jan 2 03:04:05"
-dt=`busybox date -d 01231133`
-dt=`echo "$dt" | cut -b5-19`
-test x"$dt" = x"Jan 23 11:33:00"
+# date (GNU coreutils) 8.17 doesn't accept 01231133 either:
+# date: invalid date '01231133'
+#dt=`busybox date -d 01231133`
+#dt=`echo "$dt" | cut -b5-19`
+#test x"$dt" = x"Jan 23 11:33:00"
dt=`busybox date -d 200001231133`
dt=`echo "$dt" | cut -b1-19`
diff --git a/release/src/router/busybox/testsuite/date/date-works-1 b/release/src/router/busybox/testsuite/date/date-works-1
index cb5cea2c53..4f53939ee2 100644
--- a/release/src/router/busybox/testsuite/date/date-works-1
+++ b/release/src/router/busybox/testsuite/date/date-works-1
@@ -41,9 +41,9 @@ test x"$hdt" = x"$dt"
# Avoiding using week day in this evaluation, as it's mostly different every year
# date (GNU coreutils) 6.10 reports:
# date: invalid date '01231133'
-dt=`busybox date -d 01231133 +%c`
-dt=`echo "$dt" | cut -b5-19`
-test x"$dt" = x"Jan 23 11:33:00"
+#dt=`busybox date -d 01231133 +%c`
+#dt=`echo "$dt" | cut -b5-19`
+#test x"$dt" = x"Jan 23 11:33:00"
# date (GNU coreutils) 6.10 reports:
# date: invalid date '012311332000'
diff --git a/release/src/router/busybox/testsuite/dc.tests b/release/src/router/busybox/testsuite/dc.tests
new file mode 100755
index 0000000000..a5da5372dd
--- /dev/null
+++ b/release/src/router/busybox/testsuite/dc.tests
@@ -0,0 +1,56 @@
+#!/bin/sh
+# Copyright 2015 by Bernhard Reutner-Fischer
+# Licensed under GPLv2 or later, see file LICENSE in this source tree.
+
+. ./testing.sh
+
+# testing "test name" "command" "expected result" "file input" "stdin"
+
+testing "dc basic syntax (stdin, multiple args)" \
+ "dc" \
+ "30\n" \
+ "" "10 20+p"
+
+testing "dc basic syntax (argv, single arg)" \
+ "dc '10 20+p'" \
+ "30\n" \
+ "" ""
+
+testing "dc basic syntax (argv, multiple args)" \
+ "dc 10 20+p" \
+ "30\n" \
+ "" ""
+
+testing "dc complex with spaces (single arg)" \
+ "dc '8 8 * 2 2 + / p'" \
+ "16\n" \
+ "" ""
+
+testing "dc complex without spaces (single arg)" \
+ "dc '8 8*2 2+/p'" \
+ "16\n" \
+ "" ""
+
+testing "dc complex with spaces (multiple args)" \
+ "dc 8 8 \* 2 2 + / p" \
+ "16\n" \
+ "" ""
+
+testing "dc complex without spaces (multiple args)" \
+ "dc 8 8\*2 2+/p" \
+ "16\n" \
+ "" ""
+
+exit $FAILCOUNT
+
+# we do not support arguments
+testing "dc -e <exprs>" \
+ "dc -e '10 2+f'" \
+ "12\n" \
+ "" ""
+
+testing "dc -f <exprs-from-given-file>" \
+ "dc -f input" \
+ "12\n" \
+ "10 2+f" ""
+
diff --git a/release/src/router/busybox/testsuite/diff.tests b/release/src/router/busybox/testsuite/diff.tests
index 6de46483bb..0ced0f248f 100755
--- a/release/src/router/busybox/testsuite/diff.tests
+++ b/release/src/router/busybox/testsuite/diff.tests
@@ -44,6 +44,17 @@ testing "diff of stdin, twice" \
"" \
"stdin"
+testing "diff of empty file against stdin" \
+ "diff -u - input | $TRIM_TAB" \
+"\
+--- -
++++ input
+@@ -1 +0,0 @@
+-a
+" \
+ "" \
+ "a\n"
+
testing "diff of empty file against nonempty one" \
"diff -u - input | $TRIM_TAB" \
"\
@@ -87,6 +98,18 @@ testing "diff -B does not ignore changes whose lines are not all blank" \
"a\n" \
"\nb\n\n"
+testing "diff -B ignores blank single line change" \
+ 'diff -qB - input; echo $?' \
+ "0\n" \
+ "\n1\n" \
+ "1\n"
+
+testing "diff -B does not ignore non-blank single line change" \
+ 'diff -qB - input; echo $?' \
+ "Files - and input differ\n1\n" \
+ "0\n" \
+ "1\n"
+
testing "diff always takes context from old file" \
"diff -ub - input | $TRIM_TAB" \
"\
diff --git a/release/src/router/busybox/testsuite/du/du-k-works b/release/src/router/busybox/testsuite/du/du-k-works
index 229a948ee0..213e9ba991 100644
--- a/release/src/router/busybox/testsuite/du/du-k-works
+++ b/release/src/router/busybox/testsuite/du/du-k-works
@@ -2,5 +2,12 @@ mkdir du.testdir
cd du.testdir
dd if=/dev/zero of=file1 bs=1k count=64 2>/dev/null
dd if=/dev/zero of=file2 bs=1k count=16 2>/dev/null
+# ext4 on images <512M gives 81kb
+# ext3 on images <512M gives 83kb
+# a bsd system reportedly gives 82kb
test x"`busybox du -k .`" = x"80 ." \
+ -o x"`busybox du -k .`" = x"81 ." \
+ -o x"`busybox du -k .`" = x"82 ." \
+ -o x"`busybox du -k .`" = x"83 ." \
+ -o x"`busybox du -k .`" = x"84 ." \
-o x"`busybox du -k .`" = x"88 ."
diff --git a/release/src/router/busybox/testsuite/du/du-l-works b/release/src/router/busybox/testsuite/du/du-l-works
index 426ee891b9..af87345dbd 100644
--- a/release/src/router/busybox/testsuite/du/du-l-works
+++ b/release/src/router/busybox/testsuite/du/du-l-works
@@ -6,6 +6,7 @@ dd if=/dev/zero of=file1 bs=1k count=64 2>/dev/null
ln file1 file1.1
dd if=/dev/zero of=file2 bs=1k count=16 2>/dev/null
test x"`busybox du -l .`" = x"144 ." \
+ -o x"`busybox du -l .`" = x"146 ." \
-o x"`busybox du -l .`" = x"148 ." \
-o x"`busybox du -l .`" = x"152 ." \
-o x"`busybox du -l .`" = x"156 ."
diff --git a/release/src/router/busybox/testsuite/du/du-m-works b/release/src/router/busybox/testsuite/du/du-m-works
index 9fa7437ace..d9693c7bf8 100644
--- a/release/src/router/busybox/testsuite/du/du-m-works
+++ b/release/src/router/busybox/testsuite/du/du-m-works
@@ -1,4 +1,4 @@
# FEATURE: CONFIG_FEATURE_HUMAN_READABLE
dd if=/dev/zero of=file bs=1M count=1 2>/dev/null
-test x"`busybox du -m .`" = x"1 ."
+test x"`busybox du -m file`" = x"1 file"
diff --git a/release/src/router/busybox/testsuite/find.tests b/release/src/router/busybox/testsuite/find.tests
new file mode 100755
index 0000000000..78dfa12303
--- /dev/null
+++ b/release/src/router/busybox/testsuite/find.tests
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+# Copyright 2014 by Denys Vlasenko <vda.linux@googlemail.com>
+# Licensed under GPLv2, see file LICENSE in this source tree.
+
+. ./testing.sh
+
+# testing "description" "command" "result" "infile" "stdin"
+
+mkdir -p find.tempdir
+touch find.tempdir/testfile
+
+optional FEATURE_FIND_TYPE
+testing "find -type f" \
+ "cd find.tempdir && find -type f 2>&1" \
+ "./testfile\n" \
+ "" ""
+SKIP=
+optional FEATURE_FIND_EXEC
+testing "find -exec exitcode 1" \
+ "cd find.tempdir && find testfile -exec true {} \; 2>&1; echo \$?" \
+ "0\n" \
+ "" ""
+SKIP=
+optional FEATURE_FIND_EXEC_PLUS
+testing "find -exec exitcode 2" \
+ "cd find.tempdir && find testfile -exec true {} + 2>&1; echo \$?" \
+ "0\n" \
+ "" ""
+SKIP=
+# Surprisingly, "-exec false ;" results in exitcode 0! "-exec false +" is different!!!
+optional FEATURE_FIND_EXEC
+testing "find -exec exitcode 3" \
+ "cd find.tempdir && find testfile -exec false {} \; 2>&1; echo \$?" \
+ "0\n" \
+ "" ""
+SKIP=
+optional FEATURE_FIND_EXEC_PLUS
+testing "find -exec exitcode 4" \
+ "cd find.tempdir && find testfile -exec false {} + 2>&1; echo \$?" \
+ "1\n" \
+ "" ""
+SKIP=
+
+# testing "description" "command" "result" "infile" "stdin"
+
+rm -rf find.tempdir
+
+exit $FAILCOUNT
diff --git a/release/src/router/busybox/testsuite/grep.tests b/release/src/router/busybox/testsuite/grep.tests
index 006a215e1b..f6d9f21052 100755
--- a/release/src/router/busybox/testsuite/grep.tests
+++ b/release/src/router/busybox/testsuite/grep.tests
@@ -82,6 +82,20 @@ testing "grep -F handles -i" "grep -F -i foo input ; echo \$?" \
testing "grep can read regexps from stdin" "grep -f - input ; echo \$?" \
"two\nthree\n0\n" "tw\ntwo\nthree\n" "tw.\nthr\n"
+# -x (whole line match)
+testing "grep -x (full match)" "grep -x foo input ; echo \$?" \
+ "foo\n0\n" "foo\n" ""
+testing "grep -x (partial match 1)" "grep -x foo input ; echo \$?" \
+ "1\n" "foo bar\n" ""
+testing "grep -x (partial match 2)" "grep -x foo input ; echo \$?" \
+ "1\n" "bar foo\n" ""
+testing "grep -x -F (full match)" "grep -x -F foo input ; echo \$?" \
+ "foo\n0\n" "foo\n" ""
+testing "grep -x -F (partial match 1)" "grep -x -F foo input ; echo \$?" \
+ "1\n" "foo bar\n" ""
+testing "grep -x -F (partial match 2)" "grep -x -F foo input ; echo \$?" \
+ "1\n" "bar foo\n" ""
+
optional FEATURE_GREP_EGREP_ALIAS
testing "grep -E supports extended regexps" "grep -E fo+" "foo\n" "" \
"b\ar\nfoo\nbaz"
@@ -115,6 +129,68 @@ testing "grep -v -f EMPTY_FILE" \
"" \
"test\n"
+testing "grep -Fw matches only words" \
+ "grep -Fw foo input" \
+ "" \
+ "foop\n" \
+ ""
+
+testing "grep -Fw doesn't stop on 1st mismatch" \
+ "grep -Fw foo input" \
+ "foop foo\n" \
+ "foop foo\n" \
+ ""
+
+testing "grep -w doesn't stop on 1st mismatch" \
+ "grep -w foo input" \
+ "foop foo\n" \
+ "foop foo\n" \
+ ""
+
+testing "grep -w ^str doesn't match str not at the beginning" \
+ "grep -w ^str input" \
+ "" \
+ "strstr\n" \
+ ""
+
+testing "grep -w ^ doesn't hang" \
+ "grep -w ^ input" \
+ "" \
+ "anything\n" \
+ ""
+
+testing "grep -w word doesn't match wordword" \
+ "grep -w word input" \
+ "" \
+ "wordword\n" \
+ ""
+
+testing "grep -w word match second word" \
+ "grep -w word input" \
+ "bword,word\n""wordb,word\n""bwordb,word\n" \
+ "bword,word\n""wordb,word\n""bwordb,word\n" \
+ ""
+
+# -r on symlink to dir should recurse into dir
+mkdir -p grep.testdir/foo
+echo bar > grep.testdir/foo/file
+ln -s foo grep.testdir/symfoo
+testing "grep -r on symlink to dir" \
+ "grep -r . grep.testdir/symfoo" \
+ "grep.testdir/symfoo/file:bar\n" \
+ "" ""
+rm -Rf grep.testdir
+
+# But -r on dir/symlink_to_dir should not recurse into symlink_to_dir
+mkdir -p grep.testdir/foo
+echo bar > grep.testdir/foo/file
+ln -s foo grep.testdir/symfoo
+testing "grep -r on dir/symlink to dir" \
+ "grep -r . grep.testdir" \
+ "grep.testdir/foo/file:bar\n" \
+ "" ""
+rm -Rf grep.testdir
+
# testing "test name" "commands" "expected result" "file input" "stdin"
# file input will be file called "input"
# test can create a file "actual" instead of writing to stdout
diff --git a/release/src/router/busybox/testsuite/hostid/hostid-works b/release/src/router/busybox/testsuite/hostid/hostid-works
index bcfd717af4..8c20bdfcc6 100644
--- a/release/src/router/busybox/testsuite/hostid/hostid-works
+++ b/release/src/router/busybox/testsuite/hostid/hostid-works
@@ -1,8 +1,6 @@
h=x$(busybox hostid)
# Is $h a sequence of hex numbers?
-x="${h//[0123456789abcdef]/x}"
-x="${x//xxx/x}"
-x="${x//xxx/x}"
-x="${x//xxx/x}"
-x="${x//xx/x}"
-test x"$x" = x"x"
+case "$h" in
+ x*[!0-9a-f]*) false;;
+ *) true;;
+esac
diff --git a/release/src/router/busybox/testsuite/makedevs.tests b/release/src/router/busybox/testsuite/makedevs.tests
index fd12460ec7..b51fe07984 100755
--- a/release/src/router/busybox/testsuite/makedevs.tests
+++ b/release/src/router/busybox/testsuite/makedevs.tests
@@ -25,7 +25,7 @@ FILTER_LS2="sed -e 's/, */,/g' -e 's/ */ /g' | cut -d' ' -f 1-4,9-"
rm -rf makedevs.testdir
mkdir makedevs.testdir
-optional FEATURE_MAKEDEVS_TABLE FEATURE_FIND_NOT FEATURE_FIND_TYPE FEATURE_LS_RECURSIVE FEATURE_LS_SORTFILES
+optional FEATURE_MAKEDEVS_TABLE FEATURE_FIND_NOT FEATURE_FIND_TYPE FEATURE_LS_RECURSIVE FEATURE_LS_SORTFILES FEATURE_LS_TIMESTAMPS
testing "makedevs -d ../makedevs.device_table.txt ." \
"(cd makedevs.testdir && makedevs -d ../makedevs.device_table.txt . 2>&1);
find makedevs.testdir ! -type d | sort | xargs ls -lnR | $FILTER_LS" \
diff --git a/release/src/router/busybox/testsuite/md5sum.tests b/release/src/router/busybox/testsuite/md5sum.tests
index 1068b083f5..6c75b6d1c1 100755
--- a/release/src/router/busybox/testsuite/md5sum.tests
+++ b/release/src/router/busybox/testsuite/md5sum.tests
@@ -30,13 +30,13 @@ result=`(
n=0
while test $n -le 999; do
echo "$text" | head -c $n | "$sum"
- : $((n++))
+ n=$(($n+1))
done | "$sum"
)`
if test x"$result" = x"$expected -"; then
- echo "PASS: $sum"
- exit 0
+ echo "PASS: $sum"
+ exit 0
fi
echo "FAIL: $sum (r:$result exp:$expected)"
diff --git a/release/src/router/busybox/testsuite/mdev.tests b/release/src/router/busybox/testsuite/mdev.tests
index 48d3dcc2c3..59873011a0 100755
--- a/release/src/router/busybox/testsuite/mdev.tests
+++ b/release/src/router/busybox/testsuite/mdev.tests
@@ -168,7 +168,7 @@ SKIP=
# continuing to use directory structure from prev test
rm -rf mdev.testdir/dev/*
echo "sda 0:0 644 @echo @echo TEST" >mdev.testdir/etc/mdev.conf
-optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_EXEC FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME FEATURE_SH_IS_ASH
+optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_EXEC FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME FEATURE_SH_IS_ASH ASH_BUILTIN_ECHO
testing "mdev command" \
"env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1;
ls -lnR mdev.testdir/dev | $FILTER_LS" \
diff --git a/release/src/router/busybox/testsuite/mkfs.minix.tests b/release/src/router/busybox/testsuite/mkfs.minix.tests
index 8a33c16813..324eaafced 100755
--- a/release/src/router/busybox/testsuite/mkfs.minix.tests
+++ b/release/src/router/busybox/testsuite/mkfs.minix.tests
@@ -8,6 +8,14 @@
# testing "test name" "options" "expected result" "file input" "stdin"
+# '\n' produces 10 on little endian, but not on big endian
+cr=`echo | od -i | sed 's/ *$//g;s/.* //g;2d'`
+if [ x"$cr" = x"10" ]; then
+ hash=4f35f7afeba07d56055bed1f29ae20b7
+else
+ hash=5adbc1b3ccd20ca5d0ab5bc1e13ac3fc
+fi
+
testing "mkfs.minix" \
"dd if=/dev/zero of=input bs=1k count=1024 2>/dev/null; mkfs.minix input; md5sum <input" \
"352 inodes\n"\
@@ -15,7 +23,7 @@ testing "mkfs.minix" \
"Firstdatazone=15 (15)\n"\
"Zonesize=1024\n"\
"Maxsize=268966912\n"\
-"4f35f7afeba07d56055bed1f29ae20b7 -\n" \
+"$hash -\n" \
"" \
""
diff --git a/release/src/router/busybox/testsuite/mount.tests b/release/src/router/busybox/testsuite/mount.tests
index c5891be836..a0bc508886 100755
--- a/release/src/router/busybox/testsuite/mount.tests
+++ b/release/src/router/busybox/testsuite/mount.tests
@@ -36,7 +36,8 @@ testing "mount -o remount,mand" \
"mount -o loop mount.image1m $testdir "\
"&& grep -Fc $testdir </proc/mounts "\
"&& mount -o remount,mand $testdir "\
-"&& grep -F $testdir </proc/mounts | grep -c '[, ]mand[, ]'" \
+"&& grep -F $testdir </proc/mounts | grep -c '[, ]mand[, ]'"\
+"|| grep -F $testdir </proc/mounts" \
"1\n""1\n" \
"" ""
@@ -83,4 +84,28 @@ b
"" ""
SKIP=
+
+testing "mount RO loop" "\
+exec 2>&1
+umount -d mount.dir 2>/dev/null
+rmdir mount.dir 2>/dev/null
+mkdir -p mount.dir
+(
+cd mount.dir || { echo 'cd error'; exit 1; }
+mkdir z1 z2 || { echo 'mkdir error'; exit 1; }
+mount -t tmpfs tmpfs z1 || { echo 'mount tmpfs error'; exit 1; }
+dd if=/dev/zero of=z1/e2img count=10 bs=1M 2>/dev/null || { echo 'dd error'; exit 1; }
+mke2fs -F z1/e2img 2>/dev/null >&2 || { echo 'mke2fs error'; exit 1; }
+mount -r -o loop -t ext2 z1/e2img z2 || { echo 'mount -r -o loop error'; exit 1; }
+mount -o remount,ro z1 || { echo 'mount -o remount,ro error'; exit 1; }
+)
+umount -d mount.dir/z2
+##losetup -d /dev/loop*
+umount -d mount.dir/z1
+rm -rf mount.dir
+echo DONE
+" \
+"DONE\n" "" ""
+
+
exit $FAILCOUNT
diff --git a/release/src/router/busybox/testsuite/pwd/pwd-prints-working-directory b/release/src/router/busybox/testsuite/pwd/pwd-prints-working-directory
index 8575347d6c..971adb5a62 100644
--- a/release/src/router/busybox/testsuite/pwd/pwd-prints-working-directory
+++ b/release/src/router/busybox/testsuite/pwd/pwd-prints-working-directory
@@ -1 +1,4 @@
-test $(pwd) = $(busybox pwd)
+# shell's $PWD may leave symlinks unresolved.
+# "pwd" may be a built-in and have the same problem.
+# External pwd _can't_ have that problem (current dir on Unix is physical).
+test $(`which pwd`) = $(busybox pwd)
diff --git a/release/src/router/busybox/testsuite/readlink.tests b/release/src/router/busybox/testsuite/readlink.tests
index c7fc8adf00..e9d8da0fc8 100755
--- a/release/src/router/busybox/testsuite/readlink.tests
+++ b/release/src/router/busybox/testsuite/readlink.tests
@@ -21,10 +21,15 @@ testing "readlink on a link" "readlink ./$TESTLINK" "./$TESTFILE\n" "" ""
optional FEATURE_READLINK_FOLLOW
-testing "readlink -f on a file" "readlink -f ./$TESTFILE" "$PWD/$TESTFILE\n" "" ""
-testing "readlink -f on a link" "readlink -f ./$TESTLINK" "$PWD/$TESTFILE\n" "" ""
+# shell's $PWD may leave symlinks unresolved.
+# "pwd" may be a built-in and have the same problem.
+# External pwd _can't_ have that problem (current dir on Unix is physical).
+pwd=`which pwd`
+pwd=`$pwd`
+testing "readlink -f on a file" "readlink -f ./$TESTFILE" "$pwd/$TESTFILE\n" "" ""
+testing "readlink -f on a link" "readlink -f ./$TESTLINK" "$pwd/$TESTFILE\n" "" ""
testing "readlink -f on an invalid link" "readlink -f ./$FAILLINK" "" "" ""
-testing "readlink -f on a wierd dir" "readlink -f $TESTDIR/../$TESTFILE" "$PWD/$TESTFILE\n" "" ""
+testing "readlink -f on a wierd dir" "readlink -f $TESTDIR/../$TESTFILE" "$pwd/$TESTFILE\n" "" ""
# clean up
diff --git a/release/src/router/busybox/testsuite/sed.tests b/release/src/router/busybox/testsuite/sed.tests
index 2a05975227..a71f8b1f00 100755
--- a/release/src/router/busybox/testsuite/sed.tests
+++ b/release/src/router/busybox/testsuite/sed.tests
@@ -48,6 +48,7 @@ testing "sed accepts multiple -e" "sed -e 'i\' -e '1' -e 'a\' -e '3'" \
# substitutions
testing "sed -n" "sed -n -e s/foo/bar/ -e s/bar/baz/" "" "" "foo\n"
+testing "sed with empty match" "sed 's/z*//g'" "string\n" "" "string\n"
testing "sed s//p" "sed -e s/foo/bar/p -e s/bar/baz/p" "bar\nbaz\nbaz\n" \
"" "foo\n"
testing "sed -n s//p" "sed -ne s/abc/def/p" "def\n" "" "abc\n"
@@ -134,10 +135,12 @@ testing "sed empty file plus cat" "sed -e 's/nohit//' input -" "one\ntwo" \
"" "one\ntwo"
testing "sed cat plus empty file" "sed -e 's/nohit//' input -" "one\ntwo" \
"one\ntwo" ""
-test x"$SKIP_KNOWN_BUGS" = x"" && {
testing "sed append autoinserts newline" "sed -e '/woot/a woo' -" \
"woot\nwoo\n" "" "woot"
-}
+testing "sed append autoinserts newline 2" "sed -e '/oot/a woo' - input" \
+ "woot\nwoo\nboot\nwoo\n" "boot" "woot"
+testing "sed append autoinserts newline 3" "sed -e '/oot/a woo' -i input && cat input" \
+ "boot\nwoo\n" "boot" ""
testing "sed insert doesn't autoinsert newline" "sed -e '/woot/i woo' -" \
"woo\nwoot" "" "woot"
testing "sed print autoinsert newlines" "sed -e 'p' -" "one\none" "" "one"
@@ -153,11 +156,9 @@ testing "sed selective matches insert newline" \
testing "sed selective matches noinsert newline" \
"sed -ne 's/woo/bang/p' input -" "a bang\nb bang" "a woo\nb woo" \
"c no\nd no"
-test x"$SKIP_KNOWN_BUGS" = x"" && {
testing "sed clusternewline" \
"sed -e '/one/a 111' -e '/two/i 222' -e p input -" \
"one\none\n111\n222\ntwo\ntwo" "one" "two"
-}
testing "sed subst+write" \
"sed -e 's/i/z/' -e 'woutputw' input -; $ECHO -n X; cat outputw" \
"thzngy\nagaznXthzngy\nagazn" "thingy" "again"
@@ -276,6 +277,24 @@ testing "sed a cmd ended by double backslash" \
| two \\
'
+testing "sed a cmd understands \\n,\\t,\\r" \
+ "sed '/1/a\\\\t\\rzero\\none\\\\ntwo\\\\\\nthree'" \
+"\
+line1
+\t\rzero
+one\\\\ntwo\\
+three
+" "" "line1\n"
+
+testing "sed i cmd understands \\n,\\t,\\r" \
+ "sed '/1/i\\\\t\\rzero\\none\\\\ntwo\\\\\\nthree'" \
+"\
+\t\rzero
+one\\\\ntwo\\
+three
+line1
+" "" "line1\n"
+
# first three lines are deleted; 4th line is matched and printed by "2,3" and by "4" ranges
testing "sed with N skipping lines past ranges on next cmds" \
"sed -n '1{N;N;d};1p;2,3p;3p;4p'" \
@@ -309,6 +328,69 @@ testing "sed zero chars match/replace logic must not falsely trigger here 2" \
"sed 's/ *$/_/g'" \
"qwerty_\n" "" "qwerty\n"
+testing "sed /\$_in_regex/ should not match newlines, only end-of-line" \
+ "sed ': testcont; /\\\\$/{ =; N; b testcont }'" \
+ "\
+this is a regular line
+2
+line with \\
+continuation
+more regular lines
+5
+line with \\
+continuation
+" \
+ "" "\
+this is a regular line
+line with \\
+continuation
+more regular lines
+line with \\
+continuation
+"
+
+testing "sed s///NUM test" \
+ "sed -e 's/a/b/2; s/a/c/g'" \
+ "cb\n" "" "aa\n"
+
+testing "sed /regex/,N{...} addresses work" \
+ "sed /^2/,2{d}" \
+ "1\n3\n4\n5\n" \
+ "" \
+ "1\n2\n3\n4\n5\n"
+
+testing "sed /regex/,+N{...} addresses work" \
+ "sed /^2/,+2{d}" \
+ "1\n5\n" \
+ "" \
+ "1\n2\n3\n4\n5\n"
+
+testing "sed /regex/,+N{...} -i works" \
+ "cat - >input2; sed /^4/,+2{d} -i input input2; echo \$?; cat input input2; rm input2" \
+ "0\n""1\n2\n3\n7\n8\n""1\n2\n7\n8\n" \
+ "1\n2\n3\n4\n5\n6\n7\n8\n" \
+ "1\n2\n4\n5\n6\n7\n8\n" \
+
+# GNU sed 4.2.1 would also accept "/^4/,+{d}" with the same meaning, we don't
+testing "sed /regex/,+0{...} -i works" \
+ "cat - >input2; sed /^4/,+0{d} -i input input2; echo \$?; cat input input2; rm input2" \
+ "0\n""1\n2\n3\n5\n6\n7\n8\n""1\n2\n5\n6\n7\n8\n" \
+ "1\n2\n3\n4\n5\n6\n7\n8\n" \
+ "1\n2\n4\n5\n6\n7\n8\n" \
+
+# GNU sed 4.2.1 would also accept "/^4/,+d" with the same meaning, we don't
+testing "sed /regex/,+0<cmd> -i works" \
+ "cat - >input2; sed /^4/,+0d -i input input2; echo \$?; cat input input2; rm input2" \
+ "0\n""1\n2\n3\n5\n6\n7\n8\n""1\n2\n5\n6\n7\n8\n" \
+ "1\n2\n3\n4\n5\n6\n7\n8\n" \
+ "1\n2\n4\n5\n6\n7\n8\n" \
+
+testing "sed 's///w FILE'" \
+ "sed 's/qwe/ZZZ/wz'; cat z; rm z" \
+ "123\nZZZ\nasd\n""ZZZ\n" \
+ "" \
+ "123\nqwe\nasd\n"
+
# testing "description" "commands" "result" "infile" "stdin"
exit $FAILCOUNT
diff --git a/release/src/router/busybox/testsuite/sha3sum.tests b/release/src/router/busybox/testsuite/sha3sum.tests
new file mode 100755
index 0000000000..82fada633f
--- /dev/null
+++ b/release/src/router/busybox/testsuite/sha3sum.tests
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+. ./md5sum.tests sha3sum c29d77bc548fa2b20a04c861400a5360879c52156e2a54a3415b99a9a3123e1d5f36714a24eca8c1f05a8e2d8ba859c930d41141f64a255c6794436fc99c486a
diff --git a/release/src/router/busybox/testsuite/sort.tests b/release/src/router/busybox/testsuite/sort.tests
index 91b282ea06..c51a8e475b 100755
--- a/release/src/router/busybox/testsuite/sort.tests
+++ b/release/src/router/busybox/testsuite/sort.tests
@@ -47,8 +47,6 @@ egg 1 2 papyrus
999 3 0 algebra
" "$data" ""
-test x"$SKIP_KNOWN_BUGS" = x"" && {
-# Busybox is definitely doing these wrong. FIXME
testing "sort key range with numeric option and global reverse" \
"sort -k2,3n -r input" \
"egg 1 2 papyrus
@@ -65,7 +63,6 @@ testing "sort key range with multiple options" "sort -k2,3rn input" \
42 1 3 woot
egg 1 2 papyrus
" "$data" ""
-}
testing "sort key range with two -k options" "sort -k 2,2n -k 1,1r input" "\
d 2
@@ -101,6 +98,58 @@ testing "sort with non-default leading delim 3" "sort -n -k3 -t/ input" "\
//b/1
" ""
+testing "sort with non-default leading delim 4" "sort -t: -k1,1 input" "\
+a:b
+a/a:a
+" "\
+a/a:a
+a:b
+" ""
+
+testing "sort with ENDCHAR" "sort -t. -k1,1.1 -k2 input" "\
+ab.1
+aa.2
+" "\
+aa.2
+ab.1
+" ""
+
+testing "glibc build sort" "sort -t. -k 1,1 -k 2n,2n -k 3 input" "\
+GLIBC_2.1
+GLIBC_2.1.1
+GLIBC_2.2
+GLIBC_2.2.1
+GLIBC_2.10
+GLIBC_2.20
+GLIBC_2.21
+" "\
+GLIBC_2.21
+GLIBC_2.1.1
+GLIBC_2.2.1
+GLIBC_2.2
+GLIBC_2.20
+GLIBC_2.10
+GLIBC_2.1
+" ""
+
+testing "glibc build sort unique" "sort -u -t. -k 1,1 -k 2n,2n -k 3 input" "\
+GLIBC_2.1
+GLIBC_2.1.1
+GLIBC_2.2
+GLIBC_2.2.1
+GLIBC_2.10
+GLIBC_2.20
+GLIBC_2.21
+" "\
+GLIBC_2.10
+GLIBC_2.2.1
+GLIBC_2.1.1
+GLIBC_2.20
+GLIBC_2.2
+GLIBC_2.1
+GLIBC_2.21
+" ""
+
testing "sort -u should consider field only when discarding" "sort -u -k2 input" "\
a c
" "\
diff --git a/release/src/router/busybox/testsuite/tar.tests b/release/src/router/busybox/testsuite/tar.tests
index 7927020c11..c44b7ad070 100755
--- a/release/src/router/busybox/testsuite/tar.tests
+++ b/release/src/router/busybox/testsuite/tar.tests
@@ -15,6 +15,53 @@ mkdir tar.tempdir && cd tar.tempdir || exit 1
# testing "test name" "script" "expected result" "file input" "stdin"
+testing "Empty file is not a tarball" '\
+tar xvf - 2>&1; echo $?
+' "\
+tar: short read
+1
+" \
+"" ""
+SKIP=
+
+optional FEATURE_SEAMLESS_GZ GUNZIP
+# In NOMMU case, "invalid magic" message comes from gunzip child process.
+# Otherwise, it comes from tar.
+# Need to fix output up to avoid false positive.
+testing "Empty file is not a tarball.tar.gz" '\
+{ tar xvzf - 2>&1; echo $?; } | grep -Fv "invalid magic"
+' "\
+tar: short read
+1
+" \
+"" ""
+SKIP=
+
+testing "Two zeroed blocks is a ('truncated') empty tarball" '\
+dd if=/dev/zero bs=512 count=2 2>/dev/null | tar xvf - 2>&1; echo $?
+' "\
+0
+" \
+"" ""
+SKIP=
+
+testing "Twenty zeroed blocks is an empty tarball" '\
+dd if=/dev/zero bs=512 count=20 2>/dev/null | tar xvf - 2>&1; echo $?
+' "\
+0
+" \
+"" ""
+SKIP=
+
+# "tar cf test.tar input input_dir/ input_hard1 input_hard2 input_hard1 input_dir/ input":
+# GNU tar 1.26 records as hardlinks:
+# input_hard2 -> input_hard1
+# input_hard1 -> input_hard1 (!!!)
+# input_dir/file -> input_dir/file
+# input -> input
+# As of 1.24.0, we don't record last two: for them, nlink==1
+# and we check for "hardlink"ness only files with nlink!=1
+# We also don't use "hrw-r--r--" notation for hardlinks in "tar tv" listing.
optional FEATURE_TAR_CREATE FEATURE_LS_SORTFILES
testing "tar hardlinks and repeated files" '\
rm -rf input_* test.tar 2>/dev/null
@@ -26,6 +73,7 @@ chmod -R 644 *
chmod 755 input_dir
tar cf test.tar input input_dir/ input_hard1 input_hard2 input_hard1 input_dir/ input
tar tvf test.tar | sed "s/.*[0-9] input/input/"
+rm -rf input_dir
tar xf test.tar 2>&1
echo Ok: $?
ls -l . input_dir/* | grep input_ | sed "s/\\(^[^ ]*\\) .* input/\\1 input/"
@@ -156,7 +204,7 @@ SKIP=
# Had a bug where on extract autodetect first "switched off" -z
# and then failed to recognize .tgz extension
-optional FEATURE_TAR_CREATE FEATURE_SEAMLESS_GZ
+optional FEATURE_TAR_CREATE FEATURE_SEAMLESS_GZ GUNZIP
testing "tar extract tgz" "\
dd count=1 bs=1M if=/dev/zero of=F0 2>/dev/null
tar -czf F0.tgz F0
@@ -208,6 +256,49 @@ Ok
"" ""
SKIP=
+# attack.tar.bz2 has symlink pointing to a system file
+# followed by a regular file with the same name
+# containing "root::0:0::/root:/bin/sh":
+# lrwxrwxrwx root/root passwd -> /tmp/passwd
+# -rw-r--r-- root/root passwd
+# naive tar implementation may end up creating the symlink
+# and then writing into it.
+# The correct implementation unlinks target before
+# creating the second file.
+# We test that /tmp/passwd remains empty:
+optional UUDECODE FEATURE_TAR_AUTODETECT FEATURE_SEAMLESS_BZ2
+testing "tar does not extract into symlinks" "\
+>>/tmp/passwd && uudecode -o input && tar xf input 2>&1 && rm passwd; cat /tmp/passwd; echo \$?
+" "\
+0
+" \
+"" "\
+begin-base64 644 attack.tar.bz2
+QlpoOTFBWSZTWRVn/bIAAKt7hMqwAEBAAP2QAhB0Y96AAACACCAAlISgpqe0
+po0DIaDynqAkpDRP1ANAhiYNSPR8VchKhAz0AK59+DA6FcMKBggOARIJdVHL
+DGllrjs20ATUgR1HmccBX3EhoMnpMJaNyggmxgLDMz54lBnBTJO/1L1lbMS4
+l4/V8LDoe90yiWJhOJvIypgEfxdyRThQkBVn/bI=
+====
+"
+SKIP=
+# And same with -k
+optional UUDECODE FEATURE_TAR_AUTODETECT FEATURE_SEAMLESS_BZ2
+testing "tar -k does not extract into symlinks" "\
+>>/tmp/passwd && uudecode -o input && tar xf input -k 2>&1 && rm passwd; cat /tmp/passwd; echo \$?
+" "\
+tar: can't open 'passwd': File exists
+0
+" \
+"" "\
+begin-base64 644 attack.tar.bz2
+QlpoOTFBWSZTWRVn/bIAAKt7hMqwAEBAAP2QAhB0Y96AAACACCAAlISgpqe0
+po0DIaDynqAkpDRP1ANAhiYNSPR8VchKhAz0AK59+DA6FcMKBggOARIJdVHL
+DGllrjs20ATUgR1HmccBX3EhoMnpMJaNyggmxgLDMz54lBnBTJO/1L1lbMS4
+l4/V8LDoe90yiWJhOJvIypgEfxdyRThQkBVn/bI=
+====
+"
+SKIP=
+
cd .. && rm -rf tar.tempdir || exit 1
diff --git a/release/src/router/busybox/testsuite/test.tests b/release/src/router/busybox/testsuite/test.tests
index 2c92e34ba8..1c2edaf627 100755
--- a/release/src/router/busybox/testsuite/test.tests
+++ b/release/src/router/busybox/testsuite/test.tests
@@ -76,4 +76,24 @@ testing "test ! a = b -a ! c = d: should be true (0)" \
"0\n" \
"" ""
+testing "test '!' = '!': should be true (0)" \
+ "busybox test '!' = '!'; echo \$?" \
+ "0\n" \
+ "" ""
+
+testing "test '(' = '(': should be true (0)" \
+ "busybox test '(' = '('; echo \$?" \
+ "0\n" \
+ "" ""
+
+testing "test '!' '!' = '!': should be false (1)" \
+ "busybox test '!' '!' = '!'; echo \$?" \
+ "1\n" \
+ "" ""
+
+testing "test '!' '(' = '(': should be false (1)" \
+ "busybox test '!' '(' = '('; echo \$?" \
+ "1\n" \
+ "" ""
+
exit $FAILCOUNT
diff --git a/release/src/router/busybox/testsuite/testing.sh b/release/src/router/busybox/testsuite/testing.sh
index e7e64e58b6..f5b7569477 100644
--- a/release/src/router/busybox/testsuite/testing.sh
+++ b/release/src/router/busybox/testsuite/testing.sh
@@ -56,10 +56,10 @@ optional()
{
SKIP=
while test "$1"; do
- if test x"${OPTIONFLAGS/*:$1:*/y}" != x"y"; then
- SKIP=1
- return
- fi
+ case "${OPTIONFLAGS}" in
+ *:$1:*) ;;
+ *) SKIP=1; return ;;
+ esac
shift
done
}
diff --git a/release/src/router/busybox/testsuite/unzip.tests b/release/src/router/busybox/testsuite/unzip.tests
index 8677a03062..d8738a3bdc 100755
--- a/release/src/router/busybox/testsuite/unzip.tests
+++ b/release/src/router/busybox/testsuite/unzip.tests
@@ -7,7 +7,7 @@
. ./testing.sh
-# testing "test name" "options" "expected result" "file input" "stdin"
+# testing "test name" "commands" "expected result" "file input" "stdin"
# file input will be file called "input"
# test can create a file "actual" instead of writing to stdout
@@ -30,6 +30,28 @@ testing "unzip (subdir only)" "unzip -q foo.zip foo/ && test -d foo && test ! -f
rmdir foo
rm foo.zip
+# File containing some damaged encrypted stream
+testing "unzip (bad archive)" "uudecode; unzip bad.zip 2>&1; echo \$?" \
+"Archive: bad.zip
+ inflating: ]3j½r«IK-%Ix
+unzip: corrupted data
+unzip: inflate error
+1
+" \
+"" "\
+begin-base64 644 bad.zip
+UEsDBBQAAgkIAAAAIQA5AAAANwAAADwAAAAQAAcAXTNqwr1ywqtJGxJLLSVJ
+eCkBD0AdKBk8JzQsIj01JC0/ORJQSwMEFAECCAAAAAAhADoAAAAPAAAANgAA
+AAwAAQASw73Ct1DCokohPXQiNjoUNTUiHRwgLT4WHlBLAQIQABQAAggIAAAA
+oQA5AAAANwAAADwAAAAQQAcADAAAACwAMgCAAAAAAABdM2rCvXLCq0kbEkst
+JUl4KQEPQB0oGSY4Cz4QNgEnJSYIPVBLAQIAABQAAggAAAAAIQAqAAAADwAA
+BDYAAAAMAAEADQAAADIADQAAAEEAAAASw73Ct1DKokohPXQiNzA+FAI1HCcW
+NzITNFBLBQUKAC4JAA04Cw0EOhZQSwUGAQAABAIAAgCZAAAAeQAAAAIALhM=
+====
+"
+
+rm *
+
# Clean up scratch directory.
cd ..
diff --git a/release/src/router/busybox/testsuite/which/which-uses-default-path b/release/src/router/busybox/testsuite/which/which-uses-default-path
index 63ceb9f8f2..92b6018c9d 100644
--- a/release/src/router/busybox/testsuite/which/which-uses-default-path
+++ b/release/src/router/busybox/testsuite/which/which-uses-default-path
@@ -1,4 +1,4 @@
-BUSYBOX=$(type -p busybox)
+BUSYBOX=$(command -v busybox)
SAVED_PATH=$PATH
unset PATH
$BUSYBOX which ls
diff --git a/release/src/router/busybox/util-linux/Config.src b/release/src/router/busybox/util-linux/Config.src
index 32a9c18b03..922cabdb83 100644
--- a/release/src/router/busybox/util-linux/Config.src
+++ b/release/src/router/busybox/util-linux/Config.src
@@ -434,94 +434,6 @@ config MORE
you will probably find this utility very helpful. If you don't have
any need to reading text files, you can leave this disabled.
-config MOUNT
- bool "mount"
- default y
- select PLATFORM_LINUX
- help
- All files and filesystems in Unix are arranged into one big directory
- tree. The 'mount' utility is used to graft a filesystem onto a
- particular part of the tree. A filesystem can either live on a block
- device, or it can be accessible over the network, as is the case with
- NFS filesystems. Most people using BusyBox will also want to enable
- the 'mount' utility.
-
-config FEATURE_MOUNT_FAKE
- bool "Support option -f"
- default y
- depends on MOUNT
- help
- Enable support for faking a file system mount.
-
-config FEATURE_MOUNT_VERBOSE
- bool "Support option -v"
- default y
- depends on MOUNT
- help
- Enable multi-level -v[vv...] verbose messages. Useful if you
- debug mount problems and want to see what is exactly passed
- to the kernel.
-
-config FEATURE_MOUNT_HELPERS
- bool "Support mount helpers"
- default n
- depends on MOUNT
- help
- Enable mounting of virtual file systems via external helpers.
- E.g. "mount obexfs#-b00.11.22.33.44.55 /mnt" will in effect call
- "obexfs -b00.11.22.33.44.55 /mnt"
- Also "mount -t sometype [-o opts] fs /mnt" will try
- "sometype [-o opts] fs /mnt" if simple mount syscall fails.
- The idea is to use such virtual filesystems in /etc/fstab.
-
-config FEATURE_MOUNT_LABEL
- bool "Support specifying devices by label or UUID"
- default y
- depends on MOUNT
- select VOLUMEID
- help
- This allows for specifying a device by label or uuid, rather than by
- name. This feature utilizes the same functionality as blkid/findfs.
- This also enables label or uuid support for swapon.
-
-config FEATURE_MOUNT_NFS
- bool "Support mounting NFS file systems on Linux < 2.6.23"
- default n
- depends on MOUNT
- select FEATURE_HAVE_RPC
- select FEATURE_SYSLOG
- help
- Enable mounting of NFS file systems on Linux kernels prior
- to version 2.6.23. Note that in this case mounting of NFS
- over IPv6 will not be possible.
-
- Note that this option links in RPC support from libc,
- which is rather large (~10 kbytes on uclibc).
-
-config FEATURE_MOUNT_CIFS
- bool "Support mounting CIFS/SMB file systems"
- default y
- depends on MOUNT
- help
- Enable support for samba mounts.
-
-config FEATURE_MOUNT_FLAGS
- depends on MOUNT
- bool "Support lots of -o flags in mount"
- default y
- help
- Without this, mount only supports ro/rw/remount. With this, it
- supports nosuid, suid, dev, nodev, exec, noexec, sync, async, atime,
- noatime, diratime, nodiratime, loud, bind, move, shared, slave,
- private, unbindable, rshared, rslave, rprivate, and runbindable.
-
-config FEATURE_MOUNT_FSTAB
- depends on MOUNT
- bool "Support /etc/fstab and -a"
- default y
- help
- Support mount all and looking for files in /etc/fstab.
-
config PIVOT_ROOT
bool "pivot_root"
default y
@@ -577,16 +489,6 @@ config SCRIPTREPLAY
This program replays a typescript, using timing information
given by script -t.
-config SETARCH
- bool "setarch"
- default y
- select PLATFORM_LINUX
- help
- The linux32 utility is used to create a 32bit environment for the
- specified program (usually a shell). It only makes sense to have
- this util on a system that supports both 64bit and 32bit userland
- (like amd64/x86, ppc64/ppc, sparc64/sparc, etc...).
-
config SWAPONOFF
bool "swaponoff"
default y
@@ -599,6 +501,15 @@ config SWAPONOFF
space. If you are not using any swap space, you can leave this
option disabled.
+config FEATURE_SWAPON_DISCARD
+ bool "Support discard option -d"
+ default y
+ depends on SWAPONOFF
+ help
+ Enable support for discarding swap area blocks at swapon and/or as
+ the kernel frees them. This option enables both the -d option on
+ 'swapon' and the 'discard' option for swap entries in /etc/fstab.
+
config FEATURE_SWAPON_PRI
bool "Support priority option -p"
default y
@@ -699,233 +610,6 @@ config FEATURE_MTAB_SUPPORT
About the only reason to use this is if you've removed /proc from
your kernel.
-config VOLUMEID
- bool #No description makes it a hidden option
- default n
-
-menu "Filesystem/Volume identification"
- depends on VOLUMEID
-
-config FEATURE_VOLUMEID_EXT
- bool "Ext filesystem"
- default y
- depends on VOLUMEID
- help
- TODO
-
-config FEATURE_VOLUMEID_BTRFS
- bool "btrfs filesystem"
- default y
- depends on VOLUMEID
- help
- TODO
-
-config FEATURE_VOLUMEID_REISERFS
- bool "Reiser filesystem"
- default y
- depends on VOLUMEID
- help
- TODO
-
-config FEATURE_VOLUMEID_FAT
- bool "fat filesystem"
- default y
- depends on VOLUMEID
- help
- TODO
-
-config FEATURE_VOLUMEID_EXFAT
- bool "exFAT filesystem"
- default y
- depends on VOLUMEID
- help
- exFAT (extended FAT) is a proprietary file system designed especially
- for flash drives. It has many features from NTFS, but with less
- overhead. exFAT is used on most SDXC cards for consumer electronics.
-
-config FEATURE_VOLUMEID_HFS
- bool "hfs filesystem"
- default y
- depends on VOLUMEID
- help
- TODO
-
-config FEATURE_VOLUMEID_JFS
- bool "jfs filesystem"
- default y
- depends on VOLUMEID
- help
- TODO
-
-### config FEATURE_VOLUMEID_UFS
-### bool "ufs filesystem"
-### default y
-### depends on VOLUMEID
-### help
-### TODO
-
-config FEATURE_VOLUMEID_XFS
- bool "xfs filesystem"
- default y
- depends on VOLUMEID
- help
- TODO
-
-config FEATURE_VOLUMEID_NTFS
- bool "ntfs filesystem"
- default y
- depends on VOLUMEID
- help
- TODO
-
-config FEATURE_VOLUMEID_ISO9660
- bool "iso9660 filesystem"
- default y
- depends on VOLUMEID
- help
- TODO
-
-config FEATURE_VOLUMEID_UDF
- bool "udf filesystem"
- default y
- depends on VOLUMEID
- help
- TODO
-
-config FEATURE_VOLUMEID_LUKS
- bool "luks filesystem"
- default y
- depends on VOLUMEID
- help
- TODO
-
-config FEATURE_VOLUMEID_LINUXSWAP
- bool "linux swap filesystem"
- default y
- depends on VOLUMEID
- help
- TODO
-
-### config FEATURE_VOLUMEID_LVM
-### bool "lvm"
-### default y
-### depends on VOLUMEID
-### help
-### TODO
-
-config FEATURE_VOLUMEID_CRAMFS
- bool "cramfs filesystem"
- default y
- depends on VOLUMEID
- help
- TODO
-
-### config FEATURE_VOLUMEID_HPFS
-### bool "hpfs filesystem"
-### default y
-### depends on VOLUMEID
-### help
-### TODO
-
-config FEATURE_VOLUMEID_ROMFS
- bool "romfs filesystem"
- default y
- depends on VOLUMEID
- help
- TODO
-
-config FEATURE_VOLUMEID_SYSV
- bool "sysv filesystem"
- default y
- depends on VOLUMEID
- help
- TODO
-
-### config FEATURE_VOLUMEID_MINIX
-### bool "minix filesystem"
-### default y
-### depends on VOLUMEID
-### help
-### TODO
-
-### These only detect partition tables - not used (yet?)
-### config FEATURE_VOLUMEID_MAC
-### bool "mac filesystem"
-### default y
-### depends on VOLUMEID
-### help
-### TODO
-###
-### config FEATURE_VOLUMEID_MSDOS
-### bool "msdos filesystem"
-### default y
-### depends on VOLUMEID
-### help
-### TODO
-
-config FEATURE_VOLUMEID_OCFS2
- bool "ocfs2 filesystem"
- default y
- depends on VOLUMEID
- help
- TODO
-
-### config FEATURE_VOLUMEID_HIGHPOINTRAID
-### bool "highpoint raid"
-### default y
-### depends on VOLUMEID
-### help
-### TODO
-
-### config FEATURE_VOLUMEID_ISWRAID
-### bool "intel raid"
-### default y
-### depends on VOLUMEID
-### help
-### TODO
-
-### config FEATURE_VOLUMEID_LSIRAID
-### bool "lsi raid"
-### default y
-### depends on VOLUMEID
-### help
-### TODO
-
-### config FEATURE_VOLUMEID_VIARAID
-### bool "via raid"
-### default y
-### depends on VOLUMEID
-### help
-### TODO
-
-### config FEATURE_VOLUMEID_SILICONRAID
-### bool "silicon raid"
-### default y
-### depends on VOLUMEID
-### help
-### TODO
-
-### config FEATURE_VOLUMEID_NVIDIARAID
-### bool "nvidia raid"
-### default y
-### depends on VOLUMEID
-### help
-### TODO
-
-### config FEATURE_VOLUMEID_PROMISERAID
-### bool "promise raid"
-### default y
-### depends on VOLUMEID
-### help
-### TODO
-
-config FEATURE_VOLUMEID_LINUXRAID
- bool "linuxraid"
- default y
- depends on VOLUMEID
- help
- TODO
-
-endmenu
+source util-linux/volume_id/Config.in
endmenu
diff --git a/release/src/router/busybox/util-linux/Kbuild.src b/release/src/router/busybox/util-linux/Kbuild.src
index 468fc6bc12..0b87c52aca 100644
--- a/release/src/router/busybox/util-linux/Kbuild.src
+++ b/release/src/router/busybox/util-linux/Kbuild.src
@@ -40,7 +40,6 @@ lib-$(CONFIG_READPROFILE) += readprofile.o
lib-$(CONFIG_RTCWAKE) += rtcwake.o
lib-$(CONFIG_SCRIPT) += script.o
lib-$(CONFIG_SCRIPTREPLAY) += scriptreplay.o
-lib-$(CONFIG_SETARCH) += setarch.o
lib-$(CONFIG_SWAPONOFF) += swaponoff.o
lib-$(CONFIG_SWITCH_ROOT) += switch_root.o
lib-$(CONFIG_UMOUNT) += umount.o
diff --git a/release/src/router/busybox/util-linux/acpid.c b/release/src/router/busybox/util-linux/acpid.c
index 1b22f3a01c..0f2cb6bdc5 100644
--- a/release/src/router/busybox/util-linux/acpid.c
+++ b/release/src/router/busybox/util-linux/acpid.c
@@ -75,6 +75,7 @@ struct acpi_event {
static const struct acpi_event f_evt_tab[] = {
{ "EV_KEY", 0x01, "KEY_POWER", 116, 1, "button/power PWRF 00000080" },
{ "EV_KEY", 0x01, "KEY_POWER", 116, 1, "button/power PWRB 00000080" },
+ { "EV_SW", 0x05, "SW_LID", 0x00, 1, "button/lid LID0 00000080" },
};
struct acpi_action {
@@ -120,10 +121,8 @@ static void process_event(const char *event)
char *handler = xasprintf("./%s", event);
const char *args[] = { "run-parts", handler, NULL };
- // debug info
- if (option_mask32 & OPT_d) {
- bb_error_msg("%s", event);
- }
+ // log the event
+ bb_error_msg("%s", event);
// spawn handler
// N.B. run-parts would require scripts to have #!/bin/sh
@@ -152,7 +151,7 @@ static const char *find_action(struct input_event *ev, const char *buf)
}
if (buf) {
- if (strncmp(buf, evt_tab[i].desc, strlen(buf)) == 0) {
+ if (is_prefixed_with(evt_tab[i].desc, buf)) {
action = evt_tab[i].desc;
break;
}
@@ -234,7 +233,7 @@ int acpid_main(int argc UNUSED_PARAM, char **argv)
const char *opt_action = "/etc/acpid.conf";
const char *opt_map = "/etc/acpi.map";
#if ENABLE_FEATURE_PIDFILE
- const char *opt_pidfile = "/var/run/acpid.pid";
+ const char *opt_pidfile = CONFIG_PID_FILE_PATH "/acpid.pid";
#endif
INIT_G();
@@ -255,7 +254,7 @@ int acpid_main(int argc UNUSED_PARAM, char **argv)
/* No -d "Debug", we log to log file.
* This includes any output from children.
*/
- xmove_fd(xopen(opt_logfile, O_WRONLY | O_CREAT | O_TRUNC), STDOUT_FILENO);
+ xmove_fd(xopen(opt_logfile, O_WRONLY | O_CREAT | O_APPEND), STDOUT_FILENO);
xdup2(STDOUT_FILENO, STDERR_FILENO);
/* Also, acpid's messages (but not children) will go to syslog too */
openlog(applet_name, LOG_PID, LOG_DAEMON);
diff --git a/release/src/router/busybox/util-linux/blkdiscard.c b/release/src/router/busybox/util-linux/blkdiscard.c
new file mode 100644
index 0000000000..ace88a1f0a
--- /dev/null
+++ b/release/src/router/busybox/util-linux/blkdiscard.c
@@ -0,0 +1,83 @@
+/*
+ * Mini blkdiscard implementation for busybox
+ *
+ * Copyright (C) 2015 by Ari Sundholm <ari@tuxera.com> and Tuxera Inc.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+//config:config BLKDISCARD
+//config: bool "blkdiscard"
+//config: default y
+//config: help
+//config: blkdiscard discards sectors on a given device.
+
+//kbuild:lib-$(CONFIG_BLKDISCARD) += blkdiscard.o
+//applet:IF_BLKDISCARD(APPLET(blkdiscard, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//usage:#define blkdiscard_trivial_usage
+//usage: "[-o OFS] [-l LEN] [-s] DEVICE"
+//usage:#define blkdiscard_full_usage "\n\n"
+//usage: "Discard sectors on DEVICE\n"
+//usage: "\n -o OFS Byte offset into device"
+//usage: "\n -l LEN Number of bytes to discard"
+//usage: "\n -s Perform a secure discard"
+//usage:
+//usage:#define blkdiscard_example_usage
+//usage: "$ blkdiscard -o 0 -l 1G /dev/sdb"
+
+#include "libbb.h"
+#include <linux/fs.h>
+
+int blkdiscard_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int blkdiscard_main(int argc UNUSED_PARAM, char **argv)
+{
+ unsigned opts;
+ const char *offset_str = "0";
+ const char *length_str;
+ uint64_t offset; /* Leaving these two variables out does not */
+ uint64_t length; /* shrink code size and hampers readability. */
+ uint64_t range[2];
+// struct stat st;
+ int fd;
+
+ enum {
+ OPT_OFFSET = (1 << 0),
+ OPT_LENGTH = (1 << 1),
+ OPT_SECURE = (1 << 2),
+ };
+
+ opt_complementary = "=1";
+ opts = getopt32(argv, "o:l:s", &offset_str, &length_str);
+ argv += optind;
+
+ fd = xopen(argv[0], O_RDWR|O_EXCL);
+//Why bother, BLK[SEC]DISCARD will fail on non-blockdevs anyway?
+// xfstat(fd, &st);
+// if (!S_ISBLK(st.st_mode))
+// bb_error_msg_and_die("%s: not a block device", argv[0]);
+
+ offset = xatoull_sfx(offset_str, kMG_suffixes);
+
+ if (opts & OPT_LENGTH)
+ length = xatoull_sfx(length_str, kMG_suffixes);
+ else {
+ xioctl(fd, BLKGETSIZE64, &length);
+ length -= offset;
+ }
+
+ range[0] = offset;
+ range[1] = length;
+ ioctl_or_perror_and_die(fd,
+ (opts & OPT_SECURE) ? BLKSECDISCARD : BLKDISCARD,
+ &range,
+ "%s: %s failed",
+ argv[0],
+ (opts & OPT_SECURE) ? "BLKSECDISCARD" : "BLKDISCARD"
+ );
+
+ if (ENABLE_FEATURE_CLEAN_UP)
+ close(fd);
+
+ return EXIT_SUCCESS;
+}
diff --git a/release/src/router/busybox/util-linux/blkid.c b/release/src/router/busybox/util-linux/blkid.c
index 697c445e07..1bbc803112 100644
--- a/release/src/router/busybox/util-linux/blkid.c
+++ b/release/src/router/busybox/util-linux/blkid.c
@@ -22,7 +22,7 @@ int blkid_main(int argc UNUSED_PARAM, char **argv)
while (*++argv) {
/* Note: bogus device names don't cause any error messages */
- add_to_uuid_cache(*argv, 0);
+ add_to_uuid_cache(*argv);
scan_devices = 0;
}
diff --git a/release/src/router/busybox/util-linux/dmesg.c b/release/src/router/busybox/util-linux/dmesg.c
index 6505da54bc..e543446c11 100644
--- a/release/src/router/busybox/util-linux/dmesg.c
+++ b/release/src/router/busybox/util-linux/dmesg.c
@@ -16,6 +16,7 @@
//usage: "\n -c Clear ring buffer after printing"
//usage: "\n -n LEVEL Set console logging level"
//usage: "\n -s SIZE Buffer size"
+//usage: "\n -r Print raw message buffer"
#include <sys/klog.h>
#include "libbb.h"
@@ -29,11 +30,12 @@ int dmesg_main(int argc UNUSED_PARAM, char **argv)
enum {
OPT_c = 1 << 0,
OPT_s = 1 << 1,
- OPT_n = 1 << 2
+ OPT_n = 1 << 2,
+ OPT_r = 1 << 3
};
opt_complementary = "s+:n+"; /* numeric */
- opts = getopt32(argv, "cs:n:", &len, &level);
+ opts = getopt32(argv, "cs:n:r", &len, &level);
if (opts & OPT_n) {
if (klogctl(8, NULL, (long) level))
bb_perror_msg_and_die("klogctl");
@@ -55,20 +57,19 @@ int dmesg_main(int argc UNUSED_PARAM, char **argv)
return EXIT_SUCCESS;
- if (ENABLE_FEATURE_DMESG_PRETTY) {
+ if (ENABLE_FEATURE_DMESG_PRETTY && !(opts & OPT_r)) {
int last = '\n';
int in = 0;
- /* Skip <#> at the start of lines */
+ /* Skip <[0-9]+> at the start of lines */
while (1) {
if (last == '\n' && buf[in] == '<') {
- in += 3;
- if (in >= len)
- break;
+ while (buf[in++] != '>' && in < len)
+ ;
+ } else {
+ last = buf[in++];
+ putchar(last);
}
- last = buf[in];
- putchar(last);
- in++;
if (in >= len)
break;
}
diff --git a/release/src/router/busybox/util-linux/fatattr.c b/release/src/router/busybox/util-linux/fatattr.c
new file mode 100644
index 0000000000..6dca24a73d
--- /dev/null
+++ b/release/src/router/busybox/util-linux/fatattr.c
@@ -0,0 +1,104 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Display or change file attributes on a fat file system
+ *
+ * Copyright 2005 H. Peter Anvin
+ * Busybox'ed (2014) by Pascal Bellard <pascal.bellard@ads-lu.com>
+ *
+ * This file can be redistributed under the terms of the GNU General
+ * Public License
+ */
+//config:config FATATTR
+//config: bool "fatattr"
+//config: default y
+//config: select PLATFORM_LINUX
+//config: help
+//config: fatattr lists or changes the file attributes on a fat file system.
+
+//applet:IF_FATATTR(APPLET(fatattr, BB_DIR_BIN, BB_SUID_DROP))
+//kbuild:lib-$(CONFIG_FATATTR) += fatattr.o
+
+//usage:#define fatattr_trivial_usage
+//usage: "[-+rhsvda] FILE..."
+//usage:#define fatattr_full_usage "\n\n"
+//usage: "Change file attributes on FAT filesystem\n"
+//usage: "\n - Clear attributes"
+//usage: "\n + Set attributes"
+//usage: "\n r Read only"
+//usage: "\n h Hidden"
+//usage: "\n s System"
+//usage: "\n v Volume label"
+//usage: "\n d Directory"
+//usage: "\n a Archive"
+
+#include "libbb.h"
+/* linux/msdos_fs.h says: */
+#ifndef FAT_IOCTL_GET_ATTRIBUTES
+# define FAT_IOCTL_GET_ATTRIBUTES _IOR('r', 0x10, uint32_t)
+# define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, uint32_t)
+#endif
+
+/* Currently supports only the FAT flags, not the NTFS ones.
+ * Extra space at the end is a hack to print space separator in file listing.
+ * Let's hope no one ever passes space as an option char :)
+ */
+static const char bit_to_char[] ALIGN1 = "rhsvda67 ";
+
+static inline unsigned long get_flag(char c)
+{
+ const char *fp = strchr(bit_to_char, c);
+ if (!fp)
+ bb_error_msg_and_die("invalid character '%c'", c);
+ return 1 << (fp - bit_to_char);
+}
+
+static unsigned decode_arg(const char *arg)
+{
+ unsigned fl = 0;
+ while (*++arg)
+ fl |= get_flag(*arg);
+ return fl;
+}
+
+int fatattr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int fatattr_main(int argc UNUSED_PARAM, char **argv)
+{
+ unsigned set_mask = 0;
+ unsigned clear_mask = 0;
+
+ for (;;) {
+ unsigned fl;
+ char *arg = *++argv;
+
+ if (!arg)
+ bb_show_usage();
+ if (arg[0] != '-' && arg[0] != '+')
+ break;
+ fl = decode_arg(arg);
+ if (arg[0] == '+')
+ set_mask |= fl;
+ else
+ clear_mask |= fl;
+ }
+
+ do {
+ int fd, i;
+ uint32_t attr;
+
+ fd = xopen(*argv, O_RDONLY);
+ xioctl(fd, FAT_IOCTL_GET_ATTRIBUTES, &attr);
+ attr = (attr | set_mask) & ~clear_mask;
+ if (set_mask | clear_mask)
+ xioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr);
+ else {
+ for (i = 0; bit_to_char[i]; i++) {
+ bb_putchar((attr & 1) ? bit_to_char[i] : ' ');
+ attr >>= 1;
+ }
+ puts(*argv);
+ }
+ close(fd);
+ } while (*++argv);
+
+ return EXIT_SUCCESS;
+}
diff --git a/release/src/router/busybox/util-linux/fbset.c b/release/src/router/busybox/util-linux/fbset.c
index 196c2aa24b..b75ec1921f 100644
--- a/release/src/router/busybox/util-linux/fbset.c
+++ b/release/src/router/busybox/util-linux/fbset.c
@@ -164,6 +164,7 @@ static const struct cmdoptions_t {
const unsigned char code;
} g_cmdoptions[] = {
/*"12345678" + NUL */
+//TODO: convert to index_in_strings()
{ "fb" , 1, CMD_FB },
{ "db" , 1, CMD_DB },
{ "a" , 0, CMD_ALL },
@@ -248,12 +249,12 @@ static int read_mode_db(struct fb_var_screeninfo *base, const char *fn,
if (!p)
continue;
s = p + strlen(mode);
- //bb_info_msg("CHECK[%s][%s][%d]", mode, p-1, *s);
+ //bb_error_msg("CHECK[%s][%s][%d]", mode, p-1, *s);
/* exact match? */
if (((!*s || isspace(*s)) && '"' != s[-1]) /* end-of-token */
|| ('"' == *s && '"' == p[-1]) /* ends with " but starts with " too! */
) {
- //bb_info_msg("FOUND[%s][%s][%s][%d]", token[1], p, mode, isspace(*s));
+ //bb_error_msg("FOUND[%s][%s][%s][%d]", token[1], p, mode, isspace(*s));
break;
}
}
@@ -264,14 +265,14 @@ static int read_mode_db(struct fb_var_screeninfo *base, const char *fn,
while (config_read(parser, token, 2, 1, "# \t", PARSE_NORMAL)) {
int i;
-//bb_info_msg("???[%s][%s]", token[0], token[1]);
+//bb_error_msg("???[%s][%s]", token[0], token[1]);
if (strcmp(token[0], "endmode") == 0) {
-//bb_info_msg("OK[%s]", mode);
+//bb_error_msg("OK[%s]", mode);
return 1;
}
p = token[1];
i = index_in_strings(
- "geometry\0timings\0interlaced\0double\0vsync\0hsync\0csync\0extsync\0",
+ "geometry\0timings\0interlaced\0double\0vsync\0hsync\0csync\0extsync\0rgba\0",
token[0]);
switch (i) {
case 0:
@@ -294,7 +295,7 @@ static int read_mode_db(struct fb_var_screeninfo *base, const char *fn,
base->yres_virtual = base_yres_virtual;
base->bits_per_pixel = base_bits_per_pixel;
}
-//bb_info_msg("GEO[%s]", p);
+//bb_error_msg("GEO[%s]", p);
break;
case 1:
if (sizeof(int) == sizeof(base->xres)) {
@@ -321,13 +322,13 @@ static int read_mode_db(struct fb_var_screeninfo *base, const char *fn,
base->hsync_len = base_hsync_len;
base->vsync_len = base_vsync_len;
}
-//bb_info_msg("TIM[%s]", p);
+//bb_error_msg("TIM[%s]", p);
break;
case 2:
case 3: {
static const uint32_t syncs[] = {FB_VMODE_INTERLACED, FB_VMODE_DOUBLE};
ss(&base->vmode, syncs[i-2], p, "false");
-//bb_info_msg("VMODE[%s]", p);
+//bb_error_msg("VMODE[%s]", p);
break;
}
case 4:
@@ -335,13 +336,37 @@ static int read_mode_db(struct fb_var_screeninfo *base, const char *fn,
case 6: {
static const uint32_t syncs[] = {FB_SYNC_VERT_HIGH_ACT, FB_SYNC_HOR_HIGH_ACT, FB_SYNC_COMP_HIGH_ACT};
ss(&base->sync, syncs[i-4], p, "low");
-//bb_info_msg("SYNC[%s]", p);
+//bb_error_msg("SYNC[%s]", p);
break;
}
case 7:
ss(&base->sync, FB_SYNC_EXT, p, "false");
-//bb_info_msg("EXTSYNC[%s]", p);
+//bb_error_msg("EXTSYNC[%s]", p);
break;
+ case 8: {
+ int red_offset, red_length;
+ int green_offset, green_length;
+ int blue_offset, blue_length;
+ int transp_offset, transp_length;
+
+ sscanf(p, "%d/%d,%d/%d,%d/%d,%d/%d",
+ &red_length, &red_offset,
+ &green_length, &green_offset,
+ &blue_length, &blue_offset,
+ &transp_length, &transp_offset);
+ base->red.offset = red_offset;
+ base->red.length = red_length;
+ base->red.msb_right = 0;
+ base->green.offset = green_offset;
+ base->green.length = green_length;
+ base->green.msb_right = 0;
+ base->blue.offset = blue_offset;
+ base->blue.length = blue_length;
+ base->blue.msb_right = 0;
+ base->transp.offset = transp_offset;
+ base->transp.length = transp_length;
+ base->transp.msb_right = 0;
+ }
}
}
return 0;
@@ -392,7 +417,7 @@ int fbset_main(int argc, char **argv)
unsigned options = 0;
const char *fbdev = DEFAULTFBDEV;
- const char *modefile = DEFAULTFBMODE;
+ IF_FEATURE_FBSET_READMODE(const char *modefile = DEFAULTFBMODE;)
char *thisarg;
char *mode = mode; /* for compiler */
@@ -420,7 +445,7 @@ int fbset_main(int argc, char **argv)
fbdev = argv[1];
break;
case CMD_DB:
- modefile = argv[1];
+ IF_FEATURE_FBSET_READMODE(modefile = argv[1];)
break;
case CMD_ALL:
options |= OPT_ALL;
diff --git a/release/src/router/busybox/util-linux/fdformat.c b/release/src/router/busybox/util-linux/fdformat.c
index 2f0854a303..6ef6445e6d 100644
--- a/release/src/router/busybox/util-linux/fdformat.c
+++ b/release/src/router/busybox/util-linux/fdformat.c
@@ -72,7 +72,7 @@ int fdformat_main(int argc UNUSED_PARAM, char **argv)
/* original message was: "Could not determine current format type" */
xioctl(fd, FDGETPRM, &param);
- printf("%s-sided, %d tracks, %d sec/track. Total capacity %d kB\n",
+ printf("%s-sided, %u tracks, %u sec/track. Total capacity %d kB\n",
(param.head == 2) ? "Double" : "Single",
param.track, param.sect, param.size >> 1);
@@ -93,7 +93,7 @@ int fdformat_main(int argc UNUSED_PARAM, char **argv)
}
xioctl(fd, FDFMTEND, NULL);
- printf("done\n");
+ puts("Done");
/* VERIFY */
if (verify) {
@@ -116,7 +116,7 @@ int fdformat_main(int argc UNUSED_PARAM, char **argv)
/* Check backwards so we don't need a counter */
while (--read_bytes >= 0) {
if (data[read_bytes] != FD_FILL_BYTE) {
- printf("bad data in cyl %d\nContinuing... ", cyl);
+ printf("bad data in cyl %d\nContinuing... ", cyl);
}
}
}
@@ -126,7 +126,7 @@ int fdformat_main(int argc UNUSED_PARAM, char **argv)
if (ENABLE_FEATURE_CLEAN_UP) free(data);
- printf("done\n");
+ puts("Done");
}
if (ENABLE_FEATURE_CLEAN_UP) close(fd);
diff --git a/release/src/router/busybox/util-linux/fdisk.c b/release/src/router/busybox/util-linux/fdisk.c
index 0d6bad6fa4..6eeab0b8f9 100644
--- a/release/src/router/busybox/util-linux/fdisk.c
+++ b/release/src/router/busybox/util-linux/fdisk.c
@@ -1102,11 +1102,11 @@ warn_geometry(void)
printf(" sectors");
if (!g_cylinders)
printf(" cylinders");
- printf(
#if ENABLE_FEATURE_FDISK_WRITABLE
- " (settable in the extra functions menu)"
+ puts(" (settable in the extra functions menu)");
+#else
+ bb_putchar('\n');
#endif
- "\n");
return 1;
}
@@ -1150,7 +1150,7 @@ read_extended(int ext)
p = pex->part_table;
if (!get_start_sect(p)) {
- printf("Bad offset in primary extended partition\n");
+ puts("Bad offset in primary extended partition");
return;
}
@@ -1447,8 +1447,8 @@ static int get_boot(void)
current_label_type = LABEL_OSF;
return 0;
}
- printf("This disk has both DOS and BSD magic.\n"
- "Give the 'b' command to go to BSD mode.\n");
+ puts("This disk has both DOS and BSD magic.\n"
+ "Give the 'b' command to go to BSD mode.");
}
#endif
@@ -1458,9 +1458,9 @@ static int get_boot(void)
#else
if (!valid_part_table_flag(MBRbuffer)) {
if (what == OPEN_MAIN) {
- printf("Device contains neither a valid DOS "
- "partition table, nor Sun, SGI, OSF or GPT "
- "disklabel\n");
+ puts("Device contains neither a valid DOS "
+ "partition table, nor Sun, SGI, OSF or GPT "
+ "disklabel");
#ifdef __sparc__
IF_FEATURE_SUN_LABEL(create_sunlabel();)
#else
@@ -1593,7 +1593,7 @@ read_int(sector_t low, sector_t dflt, sector_t high, sector_t base, const char *
}
if (value >= low && value <= high)
break;
- printf("Value is out of range\n");
+ puts("Value is out of range");
}
return value;
}
@@ -1638,7 +1638,7 @@ get_existing_partition(int warn, unsigned max)
printf("Selected partition %u\n", pno+1);
return pno;
}
- printf("No partition is defined yet!\n");
+ puts("No partition is defined yet!");
return -1;
not_unique:
@@ -1665,7 +1665,7 @@ get_nonexisting_partition(int warn, unsigned max)
printf("Selected partition %u\n", pno+1);
return pno;
}
- printf("All primary partitions have been defined already!\n");
+ puts("All primary partitions have been defined already!");
return -1;
not_unique:
@@ -1700,10 +1700,10 @@ toggle_dos_compatibility_flag(void)
dos_compatible_flag = 1 - dos_compatible_flag;
if (dos_compatible_flag) {
sector_offset = g_sectors;
- printf("DOS Compatibility flag is set\n");
+ printf("DOS Compatibility flag is %sset\n", "");
} else {
sector_offset = 1;
- printf("DOS Compatibility flag is not set\n");
+ printf("DOS Compatibility flag is %sset\n", "not ");
}
}
@@ -1810,16 +1810,16 @@ change_sysid(void)
sys = read_hex(get_sys_types());
if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN) {
- printf("Type 0 means free space to many systems\n"
- "(but not to Linux). Having partitions of\n"
- "type 0 is probably unwise.\n");
+ puts("Type 0 means free space to many systems\n"
+ "(but not to Linux). Having partitions of\n"
+ "type 0 is probably unwise.");
/* break; */
}
if (!LABEL_IS_SUN && !LABEL_IS_SGI) {
if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
- printf("You cannot change a partition into"
- " an extended one or vice versa\n");
+ puts("You cannot change a partition into"
+ " an extended one or vice versa");
break;
}
}
@@ -1827,10 +1827,10 @@ change_sysid(void)
if (sys < 256) {
#if ENABLE_FEATURE_SUN_LABEL
if (LABEL_IS_SUN && i == 2 && sys != SUN_WHOLE_DISK)
- printf("Consider leaving partition 3 "
- "as Whole disk (5),\n"
- "as SunOS/Solaris expects it and "
- "even Linux likes it\n\n");
+ puts("Consider leaving partition 3 "
+ "as Whole disk (5),\n"
+ "as SunOS/Solaris expects it and "
+ "even Linux likes it\n");
#endif
#if ENABLE_FEATURE_SGI_LABEL
if (LABEL_IS_SGI &&
@@ -1839,10 +1839,10 @@ change_sysid(void)
(i == 8 && sys != 0)
)
) {
- printf("Consider leaving partition 9 "
- "as volume header (0),\nand "
- "partition 11 as entire volume (6)"
- "as IRIX expects it\n\n");
+ puts("Consider leaving partition 9 "
+ "as volume header (0),\nand "
+ "partition 11 as entire volume (6)"
+ "as IRIX expects it\n");
}
#endif
if (sys == origsys)
@@ -2064,7 +2064,7 @@ fix_partition_table_order(void)
int i,k;
if (!wrong_p_order(NULL)) {
- printf("Ordering is already correct\n\n");
+ puts("Ordering is already correct\n");
return;
}
@@ -2092,7 +2092,7 @@ fix_partition_table_order(void)
if (i)
fix_chain_of_logicals();
- printf("Done.\n");
+ puts("Done");
}
#endif
@@ -2175,7 +2175,7 @@ list_table(int xtra)
* if this is a sgi, sun or aix labeled disk... */
if (LABEL_IS_DOS && wrong_p_order(NULL)) {
/* FIXME */
- printf("\nPartition table entries are not in disk order\n");
+ puts("\nPartition table entries are not in disk order");
}
}
@@ -2189,7 +2189,7 @@ x_list_table(int extend)
printf("\nDisk %s: %u heads, %u sectors, %u cylinders\n\n",
disk_device, g_heads, g_sectors, g_cylinders);
- printf("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n");
+ puts("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID");
for (i = 0; i < g_partitions; i++) {
pe = &ptes[i];
p = (extend ? pe->ext_pointer : pe->part_table);
@@ -2416,7 +2416,7 @@ add_partition(int n, int sys)
limit = first[i] - 1;
}
if (start > limit) {
- printf("No free sectors available\n");
+ puts("No free sectors available");
if (n > 4)
g_partitions--;
return;
@@ -2487,9 +2487,9 @@ new_partition(void)
return;
}
if (LABEL_IS_AIX) {
- printf("Sorry - this fdisk cannot handle AIX disk labels.\n"
+ puts("Sorry - this fdisk cannot handle AIX disk labels.\n"
"If you want to add DOS-type partitions, create a new empty DOS partition\n"
-"table first (use 'o'). This will destroy the present disk contents.\n");
+"table first (use 'o'). This will destroy the present disk contents.");
return;
}
@@ -2497,7 +2497,7 @@ new_partition(void)
free_primary += !ptes[i].part_table->sys_ind;
if (!free_primary && g_partitions >= MAXIMUM_PARTS) {
- printf("The maximum number of partitions has been created\n");
+ puts("The maximum number of partitions has been created");
return;
}
@@ -2505,8 +2505,8 @@ new_partition(void)
if (extended_offset)
add_logical();
else
- printf("You must delete some partition and add "
- "an extended partition first\n");
+ puts("You must delete some partition and add "
+ "an extended partition first");
} else {
char c, line[80];
snprintf(line, sizeof(line),
@@ -2544,7 +2544,7 @@ reread_partition_table(int leave)
{
int i;
- printf("Calling ioctl() to re-read partition table\n");
+ puts("Calling ioctl() to re-read partition table");
sync();
/* Users with slow external USB disks on a 320MHz ARM system (year 2011)
* report that sleep is needed, otherwise BLKRRPART may fail with -EIO:
@@ -2555,10 +2555,10 @@ reread_partition_table(int leave)
"failed, kernel still uses old table");
#if 0
if (dos_changed)
- printf(
+ puts(
"\nWARNING: If you have created or modified any DOS 6.x\n"
"partitions, please see the fdisk manual page for additional\n"
- "information\n");
+ "information");
#endif
if (leave) {
@@ -2586,7 +2586,7 @@ write_table(void)
}
}
else if (LABEL_IS_SGI) {
- /* no test on change? the printf below might be mistaken */
+ /* no test on change? the "altered" msg below might be mistaken */
sgi_write_table();
}
else if (LABEL_IS_SUN) {
@@ -2598,7 +2598,7 @@ write_table(void)
}
}
- printf("The partition table has been altered.\n");
+ puts("The partition table has been altered.");
reread_partition_table(1);
}
#endif /* FEATURE_FDISK_WRITABLE */
@@ -2741,8 +2741,8 @@ xselect(void)
user_sectors = g_sectors = read_int(1, g_sectors, 63, 0, "Number of sectors");
if (dos_compatible_flag) {
sector_offset = g_sectors;
- printf("Warning: setting sector offset for DOS "
- "compatiblity\n");
+ puts("Warning: setting sector offset for DOS "
+ "compatiblity");
}
update_units();
break;
@@ -2778,14 +2778,14 @@ is_ide_cdrom_or_tape(const char *device)
the process hangs on the attempt to read a music CD.
So try to be careful. This only works since 2.1.73. */
- if (strncmp("/dev/hd", device, 7))
+ if (!is_prefixed_with(device, "/dev/hd"))
return 0;
snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
procf = fopen_for_read(buf);
if (procf != NULL && fgets(buf, sizeof(buf), procf))
- is_ide = (!strncmp(buf, "cdrom", 5) ||
- !strncmp(buf, "tape", 4));
+ is_ide = (is_prefixed_with(buf, "cdrom") ||
+ is_prefixed_with(buf, "tape"));
else
/* Now when this proc file does not exist, skip the
device when it is read-only. */
@@ -3020,8 +3020,8 @@ int fdisk_main(int argc UNUSED_PARAM, char **argv)
printf("\nThe current boot file is: %s\n",
sgi_get_bootfile());
if (read_maybe_empty("Please enter the name of the "
- "new boot file: ") == '\n')
- printf("Boot file unchanged\n");
+ "new boot file: ") == '\n')
+ puts("Boot file unchanged");
else
sgi_set_bootfile(line_ptr);
}
@@ -3103,8 +3103,8 @@ int fdisk_main(int argc UNUSED_PARAM, char **argv)
#if ENABLE_FEATURE_FDISK_ADVANCED
case 'x':
if (LABEL_IS_SGI) {
- printf("\n\tSorry, no experts menu for SGI "
- "partition tables available\n\n");
+ puts("\n\tSorry, no experts menu for SGI "
+ "partition tables available\n");
} else
xselect();
break;
diff --git a/release/src/router/busybox/util-linux/fdisk_gpt.c b/release/src/router/busybox/util-linux/fdisk_gpt.c
index 43fa2b3fc0..895795ce51 100644
--- a/release/src/router/busybox/util-linux/fdisk_gpt.c
+++ b/release/src/router/busybox/util-linux/fdisk_gpt.c
@@ -93,10 +93,8 @@ gpt_list_table(int xtra UNUSED_PARAM)
int i;
char numstr6[6];
- numstr6[5] = '\0';
-
smart_ulltoa5((unsigned long long)total_number_of_sectors * sector_size,
- numstr6, " KMGTPEZY");
+ numstr6, " KMGTPEZY")[0] = '\0';
printf("Disk %s: %llu sectors, %s\n", disk_device,
(unsigned long long)total_number_of_sectors,
numstr6);
@@ -109,13 +107,12 @@ gpt_list_table(int xtra UNUSED_PARAM)
(unsigned long long)SWAP_LE64(gpt_hdr->first_usable_lba),
(unsigned long long)SWAP_LE64(gpt_hdr->last_usable_lba));
- printf("Number Start (sector) End (sector) Size Code Name\n");
+ puts("Number Start (sector) End (sector) Size Code Name");
for (i = 0; i < n_parts; i++) {
gpt_partition *p = gpt_part(i);
if (p->lba_start) {
- smart_ulltoa5((1 + SWAP_LE64(p->lba_end)
- - SWAP_LE64(p->lba_start)) * sector_size,
- numstr6, " KMGTPEZY");
+ smart_ulltoa5((1 + SWAP_LE64(p->lba_end) - SWAP_LE64(p->lba_start)) * sector_size,
+ numstr6, " KMGTPEZY")[0] = '\0';
printf("%4u %15llu %15llu %11s %04x ",
i + 1,
(unsigned long long)SWAP_LE64(p->lba_start),
@@ -123,7 +120,7 @@ gpt_list_table(int xtra UNUSED_PARAM)
numstr6,
0x0700 /* FIXME */);
gpt_print_wide(p->name, 18);
- printf("\n");
+ bb_putchar('\n');
}
}
}
diff --git a/release/src/router/busybox/util-linux/fdisk_osf.c b/release/src/router/busybox/util-linux/fdisk_osf.c
index 65e6bd7c4f..89f1f323c7 100644
--- a/release/src/router/busybox/util-linux/fdisk_osf.c
+++ b/release/src/router/busybox/util-linux/fdisk_osf.c
@@ -366,10 +366,11 @@ bsd_select(void)
}
printf("Reading disklabel of %s at sector %u\n",
partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
- if (xbsd_readlabel(xbsd_part) == 0)
+ if (xbsd_readlabel(xbsd_part) == 0) {
if (xbsd_create_disklabel() == 0)
return;
break;
+ }
}
}
@@ -854,7 +855,7 @@ xbsd_initlabel(struct partition *p)
d->d_magic = BSD_DISKMAGIC;
- if (strncmp(disk_device, "/dev/sd", 7) == 0)
+ if (is_prefixed_with(disk_device, "/dev/sd"))
d->d_type = BSD_DTYPE_SCSI;
else
d->d_type = BSD_DTYPE_ST506;
@@ -898,8 +899,7 @@ xbsd_initlabel(struct partition *p)
pp->p_fstype = BSD_FS_UNUSED;
#else
d->d_npartitions = 3;
- pp = &d->d_partitions[2]; /* Partition C should be
- the whole disk */
+ pp = &d->d_partitions[2]; /* Partition C should be the whole disk */
pp->p_offset = 0;
pp->p_size = d->d_secperunit;
pp->p_fstype = BSD_FS_UNUSED;
@@ -935,7 +935,7 @@ xbsd_readlabel(struct partition *p)
fdisk_fatal(unable_to_read);
memmove(d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
- sizeof(struct xbsd_disklabel));
+ sizeof(struct xbsd_disklabel));
if (d->d_magic != BSD_DISKMAGIC || d->d_magic2 != BSD_DISKMAGIC)
return 0;
diff --git a/release/src/router/busybox/util-linux/fdisk_sgi.c b/release/src/router/busybox/util-linux/fdisk_sgi.c
index 785fc661b2..30def09c63 100644
--- a/release/src/router/busybox/util-linux/fdisk_sgi.c
+++ b/release/src/router/busybox/util-linux/fdisk_sgi.c
@@ -440,7 +440,7 @@ sgi_write_table(void)
(unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
write_sector(0, sgilabel);
- if (!strncmp((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
+ if (is_prefixed_with((char*)sgilabel->directory[0].vol_file_name, "sgilabel")) {
/*
* keep this habit of first writing the "sgilabel".
* I never tested whether it works without (AN 981002).
@@ -504,17 +504,19 @@ verify_sgi(int verbose)
if (sgi_get_sysid(Index[0]) == SGI_ENTIRE_DISK) {
if ((Index[0] != 10) && verbose)
printf("IRIX likes when Partition 11 covers the entire disk\n");
- if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
+ if ((sgi_get_start_sector(Index[0]) != 0) && verbose) {
printf("The entire disk partition should start "
"at block 0,\n"
"not at diskblock %u\n",
sgi_get_start_sector(Index[0]));
- if (SGI_DEBUG) /* I do not understand how some disks fulfil it */
+ }
+ if (SGI_DEBUG) { /* I do not understand how some disks fulfil it */
if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
printf("The entire disk partition is only %u diskblock large,\n"
"but the disk is %u diskblocks long\n",
sgi_get_num_sectors(Index[0]), lastblock);
lastblock = sgi_get_num_sectors(Index[0]);
+ }
} else {
if (verbose)
printf("One Partition (#11) should cover the entire disk\n");
@@ -669,16 +671,17 @@ sgi_set_volhdr(void)
int n;
for (n = 8; n < g_partitions; n++) {
- if (!sgi_get_num_sectors(n)) {
- /*
- * 5 cylinders is an arbitrary value I like
- * IRIX 5.3 stored files in the volume header
- * (like sash, symmon, fx, ide) with ca. 3200
- * sectors.
- */
- if (g_heads * g_sectors * 5 < sgi_get_lastblock())
- sgi_set_partition(n, 0, g_heads * g_sectors * 5, SGI_VOLHDR);
- break;
+ if (!sgi_get_num_sectors(n)) {
+ /*
+ * 5 cylinders is an arbitrary value I like
+ * IRIX 5.3 stored files in the volume header
+ * (like sash, symmon, fx, ide) with ca. 3200
+ * sectors.
+ */
+ if (g_heads * g_sectors * 5 < sgi_get_lastblock()) {
+ sgi_set_partition(n, 0, g_heads * g_sectors * 5, SGI_VOLHDR);
+ break;
+ }
}
}
}
diff --git a/release/src/router/busybox/util-linux/fdisk_sun.c b/release/src/router/busybox/util-linux/fdisk_sun.c
index e7fcc067cd..e32740dea4 100644
--- a/release/src/router/busybox/util-linux/fdisk_sun.c
+++ b/release/src/router/busybox/util-linux/fdisk_sun.c
@@ -348,6 +348,7 @@ create_sunlabel(void)
set_all_unchanged();
set_changed(0);
+ check_sun_label();
get_boot(CREATE_EMPTY_SUN);
}
@@ -497,11 +498,14 @@ add_sun_partition(int n, int sys)
else
first = read_int(scround(start), scround(stop)+1,
scround(stop), 0, mesg);
- if (display_in_cyl_units)
+ if (display_in_cyl_units) {
first *= units_per_sector;
- else
+ } else {
/* Starting sector has to be properly aligned */
- first = (first + g_heads * g_sectors - 1) / (g_heads * g_sectors);
+ first = (first + g_heads * g_sectors - 1) /
+ (g_heads * g_sectors);
+ first *= g_heads * g_sectors;
+ }
if (n == 2 && first != 0)
printf("\
It is highly recommended that the third partition covers the whole disk\n\
diff --git a/release/src/router/busybox/util-linux/findfs.c b/release/src/router/busybox/util-linux/findfs.c
index 49e8979acf..07734f3592 100644
--- a/release/src/router/busybox/util-linux/findfs.c
+++ b/release/src/router/busybox/util-linux/findfs.c
@@ -27,7 +27,7 @@ int findfs_main(int argc UNUSED_PARAM, char **argv)
if (!dev)
bb_show_usage();
- if (strncmp(dev, "/dev/", 5) == 0) {
+ if (is_prefixed_with(dev, "/dev/")) {
/* Just pass any /dev/xxx name right through.
* This might aid in some scripts being able
* to call this unconditionally */
diff --git a/release/src/router/busybox/util-linux/flock.c b/release/src/router/busybox/util-linux/flock.c
index e9be4eee98..1f7ade7c4c 100644
--- a/release/src/router/busybox/util-linux/flock.c
+++ b/release/src/router/busybox/util-linux/flock.c
@@ -45,7 +45,7 @@ int flock_main(int argc UNUSED_PARAM, char **argv)
if (argv[1]) {
fd = open(argv[0], O_RDONLY|O_NOCTTY|O_CREAT, 0666);
if (fd < 0 && errno == EISDIR)
- fd = open(argv[0], O_RDONLY|O_NOCTTY);
+ fd = open(argv[0], O_RDONLY|O_NOCTTY);
if (fd < 0)
bb_perror_msg_and_die("can't open '%s'", argv[0]);
//TODO? close_on_exec_on(fd);
@@ -57,7 +57,6 @@ int flock_main(int argc UNUSED_PARAM, char **argv)
/* If it is "flock FILE -c PROG", then -c isn't caught by getopt32:
* we use "+" in order to support "flock -opt FILE PROG -with-opts",
* we need to remove -c by hand.
- * TODO: in upstream, -c 'PROG ARGS' means "run sh -c 'PROG ARGS'"
*/
if (argv[0]
&& argv[0][0] == '-'
@@ -66,6 +65,9 @@ int flock_main(int argc UNUSED_PARAM, char **argv)
)
) {
argv++;
+ if (argv[1])
+ bb_error_msg_and_die("-c takes only one argument");
+ opt |= OPT_c;
}
if (OPT_s == LOCK_SH && OPT_x == LOCK_EX && OPT_n == LOCK_NB && OPT_u == LOCK_UN) {
@@ -90,8 +92,21 @@ int flock_main(int argc UNUSED_PARAM, char **argv)
bb_perror_nomsg_and_die();
}
- if (argv[0])
- return spawn_and_wait(argv);
+ if (argv[0]) {
+ int rc;
+ if (opt & OPT_c) {
+ /* -c 'PROG ARGS' means "run sh -c 'PROG ARGS'" */
+ argv -= 2;
+ argv[0] = (char*)get_shell_name();
+ argv[1] = (char*)"-c";
+ /* argv[2] = "PROG ARGS"; */
+ /* argv[3] = NULL; */
+ }
+ rc = spawn_and_wait(argv);
+ if (rc < 0)
+ bb_simple_perror_msg(argv[0]);
+ return rc;
+ }
return EXIT_SUCCESS;
}
diff --git a/release/src/router/busybox/util-linux/fsck_minix.c b/release/src/router/busybox/util-linux/fsck_minix.c
index 1508ecb033..d2f3524b46 100644
--- a/release/src/router/busybox/util-linux/fsck_minix.c
+++ b/release/src/router/busybox/util-linux/fsck_minix.c
@@ -13,7 +13,7 @@
* 10.11.91 - updated, does checking, no repairs yet.
* Sent out to the mailing-list for testing.
*
- * 14.11.91 - Testing seems to have gone well. Added some
+ * 14.11.91 - Testing seems to have gone well. Added some
* correction-code, and changed some functions.
*
* 15.11.91 - More correction code. Hopefully it notices most
@@ -22,11 +22,10 @@
* 16.11.91 - More corrections (thanks to Mika Jalava). Most
* things seem to work now. Yeah, sure.
*
- *
- * 19.04.92 - Had to start over again from this old version, as a
+ * 19.04.92 - Had to start over again from this old version, as a
* kernel bug ate my enhanced fsck in february.
*
- * 28.02.93 - added support for different directory entry sizes..
+ * 28.02.93 - added support for different directory entry sizes..
*
* Sat Mar 6 18:59:42 1993, faith@cs.unc.edu: Output namelen with
* superblock information
@@ -35,31 +34,31 @@
* to that required by fsutil
*
* Mon Jan 3 11:06:52 1994 - Dr. Wettstein (greg%wind.uucp@plains.nodak.edu)
- * Added support for file system valid flag. Also
- * added program_version variable and output of
- * program name and version number when program
- * is executed.
+ * Added support for file system valid flag. Also
+ * added program_version variable and output of
+ * program name and version number when program
+ * is executed.
*
- * 30.10.94 - added support for v2 filesystem
- * (Andreas Schwab, schwab@issan.informatik.uni-dortmund.de)
+ * 30.10.94 - added support for v2 filesystem
+ * (Andreas Schwab, schwab@issan.informatik.uni-dortmund.de)
*
- * 10.12.94 - added test to prevent checking of mounted fs adapted
- * from Theodore Ts'o's (tytso@athena.mit.edu) e2fsck
- * program. (Daniel Quinlan, quinlan@yggdrasil.com)
+ * 10.12.94 - added test to prevent checking of mounted fs adapted
+ * from Theodore Ts'o's (tytso@athena.mit.edu) e2fsck
+ * program. (Daniel Quinlan, quinlan@yggdrasil.com)
*
* 01.07.96 - Fixed the v2 fs stuff to use the right #defines and such
- * for modern libcs (janl@math.uio.no, Nicolai Langfeldt)
+ * for modern libcs (janl@math.uio.no, Nicolai Langfeldt)
*
* 02.07.96 - Added C bit fiddling routines from rmk@ecs.soton.ac.uk
* (Russell King). He made them for ARM. It would seem
- * that the ARM is powerful enough to do this in C whereas
+ * that the ARM is powerful enough to do this in C whereas
* i386 and m64k must use assembly to get it fast >:-)
- * This should make minix fsck system-independent.
- * (janl@math.uio.no, Nicolai Langfeldt)
+ * This should make minix fsck system-independent.
+ * (janl@math.uio.no, Nicolai Langfeldt)
*
* 04.11.96 - Added minor fixes from Andreas Schwab to avoid compiler
* warnings. Added mc68k bitops from
- * Joerg Dorchain <dorchain@mpi-sb.mpg.de>.
+ * Joerg Dorchain <dorchain@mpi-sb.mpg.de>.
*
* 06.11.96 - Added v2 code submitted by Joerg Dorchain, but written by
* Andreas Schwab.
@@ -372,9 +371,9 @@ static int ask(const char *string, int def)
}
}
if (def)
- printf("y\n");
+ puts("y");
else {
- printf("n\n");
+ puts("n");
errors_uncorrected = 1;
}
return def;
@@ -406,7 +405,7 @@ static void check_mount(void)
if (isatty(0) && isatty(1))
cont = ask("Do you really want to continue", 0);
if (!cont) {
- printf("Check aborted\n");
+ puts("Check aborted");
exit(EXIT_SUCCESS);
}
}
@@ -471,8 +470,8 @@ static void write_block(unsigned nr, void *addr)
if (!nr)
return;
if (nr < FIRSTZONE || nr >= ZONES) {
- printf("Internal error: trying to write bad block\n"
- "Write request ignored\n");
+ puts("Internal error: trying to write bad block\n"
+ "Write request ignored");
errors_uncorrected = 1;
return;
}
@@ -660,7 +659,7 @@ static void read_tables(void)
if (INODE_BUFFER_SIZE != read(dev_fd, inode_buffer, INODE_BUFFER_SIZE))
die("can't read inodes");
if (NORM_FIRSTZONE != FIRSTZONE) {
- printf("warning: firstzone!=norm_firstzone\n");
+ puts("warning: firstzone!=norm_firstzone");
errors_uncorrected = 1;
}
get_dirsize();
@@ -687,7 +686,7 @@ static void get_inode_common(unsigned nr, uint16_t i_mode)
total++;
if (!inode_count[nr]) {
if (!inode_in_use(nr)) {
- printf("Inode %d is marked as 'unused', but it is used "
+ printf("Inode %u is marked as 'unused', but it is used "
"for file '%s'\n", nr, current_name);
if (OPT_repair) {
if (ask("Mark as 'in use'", 1))
@@ -714,7 +713,7 @@ static void get_inode_common(unsigned nr, uint16_t i_mode)
} else
links++;
if (!++inode_count[nr]) {
- printf("Warning: inode count too big\n");
+ puts("Warning: inode count too big");
inode_count[nr]--;
errors_uncorrected = 1;
}
@@ -1131,7 +1130,7 @@ static void check_counts(void)
continue;
}
printf("Zone %d: %sin use, counted=%d\n",
- i, zone_in_use(i) ? "" : "not ", zone_count[i]);
+ i, zone_in_use(i) ? "" : "not ", zone_count[i]);
}
}
@@ -1183,7 +1182,7 @@ static void check_counts2(void)
continue;
}
printf("Zone %d: %sin use, counted=%d\n",
- i, zone_in_use(i) ? "" : "not ", zone_count[i]);
+ i, zone_in_use(i) ? "" : "not ", zone_count[i]);
}
}
#endif
@@ -1253,7 +1252,7 @@ int fsck_minix_main(int argc UNUSED_PARAM, char **argv)
printf("Forcing filesystem check on %s\n", device_name);
else if (OPT_repair)
printf("Filesystem on %s is dirty, needs checking\n",
- device_name);
+ device_name);
read_tables();
@@ -1280,27 +1279,27 @@ int fsck_minix_main(int argc UNUSED_PARAM, char **argv)
if (!inode_in_use(i))
free_cnt++;
printf("\n%6u inodes used (%u%%)\n", (INODES - free_cnt),
- 100 * (INODES - free_cnt) / INODES);
+ 100 * (INODES - free_cnt) / INODES);
for (i = FIRSTZONE, free_cnt = 0; i < ZONES; i++)
if (!zone_in_use(i))
free_cnt++;
printf("%6u zones used (%u%%)\n\n"
- "%6u regular files\n"
- "%6u directories\n"
- "%6u character device files\n"
- "%6u block device files\n"
- "%6u links\n"
- "%6u symbolic links\n"
- "------\n"
- "%6u files\n",
- (ZONES - free_cnt), 100 * (ZONES - free_cnt) / ZONES,
- regular, directory, chardev, blockdev,
- links - 2 * directory + 1, symlinks,
- total - 2 * directory + 1);
+ "%6u regular files\n"
+ "%6u directories\n"
+ "%6u character device files\n"
+ "%6u block device files\n"
+ "%6u links\n"
+ "%6u symbolic links\n"
+ "------\n"
+ "%6u files\n",
+ (ZONES - free_cnt), 100 * (ZONES - free_cnt) / ZONES,
+ regular, directory, chardev, blockdev,
+ links - 2 * directory + 1, symlinks,
+ total - 2 * directory + 1);
}
if (changed) {
write_tables();
- printf("FILE SYSTEM HAS BEEN CHANGED\n");
+ puts("FILE SYSTEM HAS BEEN CHANGED");
sync();
} else if (OPT_repair)
write_superblock();
diff --git a/release/src/router/busybox/util-linux/fstrim.c b/release/src/router/busybox/util-linux/fstrim.c
new file mode 100644
index 0000000000..51400ef0b0
--- /dev/null
+++ b/release/src/router/busybox/util-linux/fstrim.c
@@ -0,0 +1,119 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * fstrim.c - discard the part (or whole) of mounted filesystem.
+ *
+ * 03 March 2012 - Malek Degachi <malek-degachi@laposte.net>
+ * Adapted for busybox from util-linux-2.12a.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+//config:config FSTRIM
+//config: bool "fstrim"
+//config: default y
+//config: select PLATFORM_LINUX
+//config: help
+//config: Discard unused blocks on a mounted filesystem.
+
+//applet:IF_FSTRIM(APPLET(fstrim, BB_DIR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_FSTRIM) += fstrim.o
+
+//usage:#define fstrim_trivial_usage
+//usage: "[OPTIONS] MOUNTPOINT"
+//usage:#define fstrim_full_usage "\n\n"
+//usage: IF_LONG_OPTS(
+//usage: " -o,--offset=OFFSET Offset in bytes to discard from"
+//usage: "\n -l,--length=LEN Bytes to discard"
+//usage: "\n -m,--minimum=MIN Minimum extent length"
+//usage: "\n -v,--verbose Print number of discarded bytes"
+//usage: )
+//usage: IF_NOT_LONG_OPTS(
+//usage: " -o OFFSET Offset in bytes to discard from"
+//usage: "\n -l LEN Bytes to discard"
+//usage: "\n -m MIN Minimum extent length"
+//usage: "\n -v Print number of discarded bytes"
+//usage: )
+
+#include "libbb.h"
+#include <linux/fs.h>
+
+#ifndef FITRIM
+struct fstrim_range {
+ uint64_t start;
+ uint64_t len;
+ uint64_t minlen;
+};
+#define FITRIM _IOWR('X', 121, struct fstrim_range)
+#endif
+
+static const struct suffix_mult fstrim_sfx[] = {
+ { "KiB", 1024 },
+ { "kiB", 1024 },
+ { "K", 1024 },
+ { "k", 1024 },
+ { "MiB", 1048576 },
+ { "miB", 1048576 },
+ { "M", 1048576 },
+ { "m", 1048576 },
+ { "GiB", 1073741824 },
+ { "giB", 1073741824 },
+ { "G", 1073741824 },
+ { "g", 1073741824 },
+ { "KB", 1000 },
+ { "MB", 1000000 },
+ { "GB", 1000000000 },
+ { "", 0 }
+};
+
+int fstrim_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int fstrim_main(int argc UNUSED_PARAM, char **argv)
+{
+ struct fstrim_range range;
+ char *arg_o, *arg_l, *arg_m, *mp;
+ unsigned opts;
+ int fd;
+
+ enum {
+ OPT_o = (1 << 0),
+ OPT_l = (1 << 1),
+ OPT_m = (1 << 2),
+ OPT_v = (1 << 3),
+ };
+
+#if ENABLE_LONG_OPTS
+ static const char getopt_longopts[] ALIGN1 =
+ "offset\0" Required_argument "o"
+ "length\0" Required_argument "l"
+ "minimum\0" Required_argument "m"
+ "verbose\0" No_argument "v"
+ ;
+ applet_long_options = getopt_longopts;
+#endif
+
+ opt_complementary = "=1"; /* exactly one non-option arg: the mountpoint */
+ opts = getopt32(argv, "o:l:m:v", &arg_o, &arg_l, &arg_m);
+
+ memset(&range, 0, sizeof(range));
+ range.len = ULLONG_MAX;
+
+ if (opts & OPT_o)
+ range.start = xatoull_sfx(arg_o, fstrim_sfx);
+ if (opts & OPT_l)
+ range.len = xatoull_sfx(arg_l, fstrim_sfx);
+ if (opts & OPT_m)
+ range.minlen = xatoull_sfx(arg_m, fstrim_sfx);
+
+ mp = argv[optind];
+ if (find_block_device(mp)) {
+ fd = xopen_nonblocking(mp);
+ xioctl(fd, FITRIM, &range);
+ if (ENABLE_FEATURE_CLEAN_UP)
+ close(fd);
+
+ if (opts & OPT_v)
+ printf("%s: %llu bytes trimmed\n", mp, (unsigned long long)range.len);
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
+}
diff --git a/release/src/router/busybox/util-linux/getopt.c b/release/src/router/busybox/util-linux/getopt.c
index d662c813ae..b9dadf13c1 100644
--- a/release/src/router/busybox/util-linux/getopt.c
+++ b/release/src/router/busybox/util-linux/getopt.c
@@ -35,27 +35,32 @@
//usage: "[OPTIONS] [--] OPTSTRING PARAMS"
//usage:#define getopt_full_usage "\n\n"
//usage: IF_LONG_OPTS(
-//usage: " -a,--alternative Allow long options starting with single -"
-//usage: "\n -l,--longoptions=LOPT[,...] Long options to be recognized"
-//usage: "\n -n,--name=PROGNAME The name under which errors are reported"
-//usage: "\n -o,--options=OPTSTRING Short options to be recognized"
-//usage: "\n -q,--quiet Disable error reporting by getopt(3)"
+//usage: IF_FEATURE_GETOPT_LONG(
+//usage: " -a,--alternative Allow long options starting with single -\n"
+//usage: " -l,--longoptions=LOPT[,...] Long options to recognize\n"
+//usage: )
+//usage: " -n,--name=PROGNAME The name under which errors are reported"
+//usage: "\n -o,--options=OPTSTRING Short options to recognize"
+//usage: "\n -q,--quiet No error messages on unrecognized options"
//usage: "\n -Q,--quiet-output No normal output"
//usage: "\n -s,--shell=SHELL Set shell quoting conventions"
-//usage: "\n -T,--test Test for getopt(1) version"
-//usage: "\n -u,--unquoted Don't quote the output"
+//usage: "\n -T,--test Version test (exits with 4)"
+//usage: "\n -u,--unquoted Don't quote output"
//usage: )
//usage: IF_NOT_LONG_OPTS(
-//usage: " -a Allow long options starting with single -"
-//usage: "\n -l LOPT[,...] Long options to be recognized"
-//usage: "\n -n PROGNAME The name under which errors are reported"
-//usage: "\n -o OPTSTRING Short options to be recognized"
-//usage: "\n -q Disable error reporting by getopt(3)"
+//usage: IF_FEATURE_GETOPT_LONG(
+//usage: " -a Allow long options starting with single -\n"
+//usage: " -l LOPT[,...] Long options to recognize\n"
+//usage: )
+//usage: " -n PROGNAME The name under which errors are reported"
+//usage: "\n -o OPTSTRING Short options to recognize"
+//usage: "\n -q No error messages on unrecognized options"
//usage: "\n -Q No normal output"
//usage: "\n -s SHELL Set shell quoting conventions"
-//usage: "\n -T Test for getopt(1) version"
-//usage: "\n -u Don't quote the output"
+//usage: "\n -T Version test (exits with 4)"
+//usage: "\n -u Don't quote output"
//usage: )
+//usage: IF_FEATURE_GETOPT_LONG( /* example uses -l, needs FEATURE_GETOPT_LONG */
//usage: "\n"
//usage: "\nExample:"
//usage: "\n"
@@ -73,6 +78,7 @@
//usage: "\n *) echo Error; exit 1;;"
//usage: "\n esac"
//usage: "\ndone"
+//usage: )
//usage:
//usage:#define getopt_example_usage
//usage: "$ cat getopt.test\n"
@@ -214,11 +220,6 @@ static const char *normalize(const char *arg)
static int generate_output(char **argv, int argc, const char *optstr, const struct option *longopts)
{
int exit_code = 0; /* We assume everything will be OK */
- int opt;
-#if ENABLE_FEATURE_GETOPT_LONG
- int longindex;
-#endif
- const char *charptr;
if (quiet_errors) /* No error reporting from getopt(3) */
opterr = 0;
@@ -233,13 +234,14 @@ static int generate_output(char **argv, int argc, const char *optstr, const stru
#endif
while (1) {
- opt =
#if ENABLE_FEATURE_GETOPT_LONG
- alternative ?
- getopt_long_only(argc, argv, optstr, longopts, &longindex) :
- getopt_long(argc, argv, optstr, longopts, &longindex);
+ int longindex;
+ int opt = alternative
+ ? getopt_long_only(argc, argv, optstr, longopts, &longindex)
+ : getopt_long(argc, argv, optstr, longopts, &longindex)
+ ;
#else
- getopt(argc, argv, optstr);
+ int opt = getopt(argc, argv, optstr);
#endif
if (opt == -1)
break;
@@ -257,9 +259,10 @@ static int generate_output(char **argv, int argc, const char *optstr, const stru
if (opt == NON_OPT)
printf(" %s", normalize(optarg));
else {
+ const char *charptr;
printf(" -%c", opt);
charptr = strchr(optstr, opt);
- if (charptr != NULL && *++charptr == ':')
+ if (charptr && *++charptr == ':')
printf(" %s",
normalize(optarg ? optarg : ""));
}
@@ -267,9 +270,11 @@ static int generate_output(char **argv, int argc, const char *optstr, const stru
}
if (!quiet_output) {
+ unsigned idx;
printf(" --");
- while (optind < argc)
- printf(" %s", normalize(argv[optind++]));
+ idx = optind;
+ while (argv[idx])
+ printf(" %s", normalize(argv[idx++]));
bb_putchar('\n');
}
return exit_code;
@@ -372,8 +377,8 @@ int getopt_main(int argc, char **argv)
if (!argv[1]) {
if (compatible) {
/* For some reason, the original getopt gave no error
- when there were no arguments. */
- printf(" --\n");
+ * when there were no arguments. */
+ puts(" --");
return 0;
}
bb_error_msg_and_die("missing optstring argument");
diff --git a/release/src/router/busybox/util-linux/hexdump.c b/release/src/router/busybox/util-linux/hexdump.c
index 9a312f95c6..ac7e24ff88 100644
--- a/release/src/router/busybox/util-linux/hexdump.c
+++ b/release/src/router/busybox/util-linux/hexdump.c
@@ -66,13 +66,6 @@ static const char add_first[] ALIGN1 = "\"%07.7_Ax\n\"";
static const char hexdump_opts[] ALIGN1 = "bcdoxCe:f:n:s:v" IF_FEATURE_HEXDUMP_REVERSE("R");
-static const struct suffix_mult suffixes[] = {
- { "b", 512 },
- { "k", 1024 },
- { "m", 1024*1024 },
- { "", 0 }
-};
-
int hexdump_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int hexdump_main(int argc, char **argv)
{
@@ -116,7 +109,12 @@ int hexdump_main(int argc, char **argv)
dumper->dump_length = xatoi_positive(optarg);
} /* else */
if (ch == 's') { /* compat: -s accepts hex numbers too */
- dumper->dump_skip = xstrtoul_range_sfx(optarg, /*base:*/ 0, /*lo:*/ 0, /*hi:*/ LONG_MAX, suffixes);
+ dumper->dump_skip = xstrtoull_range_sfx(
+ optarg,
+ /*base:*/ 0,
+ /*lo:*/ 0, /*hi:*/ OFF_T_MAX,
+ bkm_suffixes
+ );
} /* else */
if (ch == 'v') {
dumper->dump_vflag = ALL;
diff --git a/release/src/router/busybox/util-linux/hwclock.c b/release/src/router/busybox/util-linux/hwclock.c
index 379eeb2537..6c99977cff 100644
--- a/release/src/router/busybox/util-linux/hwclock.c
+++ b/release/src/router/busybox/util-linux/hwclock.c
@@ -69,7 +69,7 @@ static void show_clock(const char **pp_rtcname, int utc)
strftime(cp, sizeof(cp), "%c", ptm);
#else
char *cp = ctime(&t);
- strchrnul(cp, '\n')[0] = '\0';
+ chomp(cp);
#endif
#if !SHOW_HWCLOCK_DIFF
@@ -97,7 +97,11 @@ static void to_sys_clock(const char **pp_rtcname, int utc)
struct timeval tv;
struct timezone tz;
- tz.tz_minuteswest = timezone/60 - 60*daylight;
+ tz.tz_minuteswest = timezone/60;
+ /* ^^^ used to also subtract 60*daylight, but it's wrong:
+ * daylight!=0 means "this timezone has some DST
+ * during the year", not "DST is in effect now".
+ */
tz.tz_dsttime = 0;
tv.tv_sec = read_rtc(pp_rtcname, NULL, utc);
@@ -248,7 +252,7 @@ static void set_system_clock_timezone(int utc)
gettimeofday(&tv, NULL);
broken = localtime(&tv.tv_sec);
tz.tz_minuteswest = timezone / 60;
- if (broken->tm_isdst)
+ if (broken->tm_isdst > 0)
tz.tz_minuteswest -= 60;
tz.tz_dsttime = 0;
gettimeofday(&tv, NULL);
@@ -305,6 +309,10 @@ int hwclock_main(int argc UNUSED_PARAM, char **argv)
;
applet_long_options = hwclock_longopts;
#endif
+
+ /* Initialize "timezone" (libc global variable) */
+ tzset();
+
opt_complementary = "r--wst:w--rst:s--wrt:t--rsw:l--u:u--l";
opt = getopt32(argv, "lurswtf:", &rtcname);
diff --git a/release/src/router/busybox/util-linux/ipcrm.c b/release/src/router/busybox/util-linux/ipcrm.c
index 274050cdf2..38d81af509 100644
--- a/release/src/router/busybox/util-linux/ipcrm.c
+++ b/release/src/router/busybox/util-linux/ipcrm.c
@@ -119,7 +119,7 @@ int ipcrm_main(int argc, char **argv)
if (remove_ids(what, &argv[2]))
fflush_stdout_and_exit(EXIT_FAILURE);
- printf("resource(s) deleted\n");
+ puts("resource(s) deleted");
return 0;
}
}
@@ -160,7 +160,7 @@ int ipcrm_main(int argc, char **argv)
/* convert key to id */
id = ((c == 'q') ? msgget(key, 0) :
- (c == 'm') ? shmget(key, 0, 0) : semget(key, 0, 0));
+ (c == 'm') ? shmget(key, 0, 0) : semget(key, 0, 0));
if (id < 0) {
const char *errmsg;
@@ -189,8 +189,8 @@ int ipcrm_main(int argc, char **argv)
}
result = ((c == 'q') ? msgctl(id, IPC_RMID, NULL) :
- (c == 'm') ? shmctl(id, IPC_RMID, NULL) :
- semctl(id, 0, IPC_RMID, arg));
+ (c == 'm') ? shmctl(id, IPC_RMID, NULL) :
+ semctl(id, 0, IPC_RMID, arg));
if (result) {
const char *errmsg;
diff --git a/release/src/router/busybox/util-linux/ipcs.c b/release/src/router/busybox/util-linux/ipcs.c
index ee7df5e336..67a25a8ef2 100644
--- a/release/src/router/busybox/util-linux/ipcs.c
+++ b/release/src/router/busybox/util-linux/ipcs.c
@@ -152,54 +152,54 @@ static NOINLINE void do_shm(void)
if ((shmctl(0, IPC_INFO, (struct shmid_ds *) (void *) &shminfo)) < 0)
return;
/* glibc 2.1.3 and all earlier libc's have ints as fields
- of struct shminfo; glibc 2.1.91 has unsigned long; ach */
+ * of struct shminfo; glibc 2.1.91 has unsigned long; ach */
printf("max number of segments = %lu\n"
- "max seg size (kbytes) = %lu\n"
- "max total shared memory (pages) = %lu\n"
- "min seg size (bytes) = %lu\n",
- (unsigned long) shminfo.shmmni,
- (unsigned long) (shminfo.shmmax >> 10),
- (unsigned long) shminfo.shmall,
- (unsigned long) shminfo.shmmin);
+ "max seg size (kbytes) = %lu\n"
+ "max total shared memory (pages) = %lu\n"
+ "min seg size (bytes) = %lu\n",
+ (unsigned long) shminfo.shmmni,
+ (unsigned long) (shminfo.shmmax >> 10),
+ (unsigned long) shminfo.shmall,
+ (unsigned long) shminfo.shmmin);
return;
case STATUS:
printf("------ Shared Memory %s --------\n", "Status");
- printf( "segments allocated %d\n"
- "pages allocated %ld\n"
- "pages resident %ld\n"
- "pages swapped %ld\n"
- "Swap performance: %ld attempts\t%ld successes\n",
- shm_info.used_ids,
- shm_info.shm_tot,
- shm_info.shm_rss,
- shm_info.shm_swp,
- shm_info.swap_attempts, shm_info.swap_successes);
+ printf("segments allocated %d\n"
+ "pages allocated %lu\n"
+ "pages resident %lu\n"
+ "pages swapped %lu\n"
+ "Swap performance: %lu attempts\t%lu successes\n",
+ shm_info.used_ids,
+ shm_info.shm_tot,
+ shm_info.shm_rss,
+ shm_info.shm_swp,
+ shm_info.swap_attempts, shm_info.swap_successes);
return;
case CREATOR:
printf("------ Shared Memory %s --------\n", "Segment Creators/Owners");
- printf( "%-10s %-10s %-10s %-10s %-10s %-10s\n",
- "shmid", "perms", "cuid", "cgid", "uid", "gid");
+ printf("%-10s %-10s %-10s %-10s %-10s %-10s\n",
+ "shmid", "perms", "cuid", "cgid", "uid", "gid");
break;
case TIME:
printf("------ Shared Memory %s --------\n", "Attach/Detach/Change Times");
- printf( "%-10s %-10s %-20s %-20s %-20s\n",
- "shmid", "owner", "attached", "detached", "changed");
+ printf("%-10s %-10s %-20s %-20s %-20s\n",
+ "shmid", "owner", "attached", "detached", "changed");
break;
case PID:
printf("------ Shared Memory %s --------\n", "Creator/Last-op");
- printf( "%-10s %-10s %-10s %-10s\n",
- "shmid", "owner", "cpid", "lpid");
+ printf("%-10s %-10s %-10s %-10s\n",
+ "shmid", "owner", "cpid", "lpid");
break;
default:
printf("------ Shared Memory %s --------\n", "Segments");
- printf( "%-10s %-10s %-10s %-10s %-10s %-10s %-12s\n",
- "key", "shmid", "owner", "perms", "bytes", "nattch",
- "status");
+ printf("%-10s %-10s %-10s %-10s %-10s %-10s %-12s\n",
+ "key", "shmid", "owner", "perms", "bytes", "nattch",
+ "status");
break;
}
@@ -220,11 +220,11 @@ static NOINLINE void do_shm(void)
printf("%-10d %-10d", shmid, ipcp->uid);
/* ctime uses static buffer: use separate calls */
printf(" %-20.16s", shmseg.shm_atime
- ? ctime(&shmseg.shm_atime) + 4 : "Not set");
+ ? ctime(&shmseg.shm_atime) + 4 : "Not set");
printf(" %-20.16s", shmseg.shm_dtime
- ? ctime(&shmseg.shm_dtime) + 4 : "Not set");
+ ? ctime(&shmseg.shm_dtime) + 4 : "Not set");
printf(" %-20.16s\n", shmseg.shm_ctime
- ? ctime(&shmseg.shm_ctime) + 4 : "Not set");
+ ? ctime(&shmseg.shm_ctime) + 4 : "Not set");
break;
case PID:
if (pw)
@@ -241,17 +241,17 @@ static NOINLINE void do_shm(void)
else
printf("%-10d %-10d", shmid, ipcp->uid);
printf(" %-10o %-10lu %-10ld %-6s %-6s\n", ipcp->mode & 0777,
- /*
- * earlier: int, Austin has size_t
- */
- (unsigned long) shmseg.shm_segsz,
- /*
- * glibc-2.1.3 and earlier has unsigned short;
- * Austin has shmatt_t
- */
- (long) shmseg.shm_nattch,
- ipcp->mode & SHM_DEST ? "dest" : " ",
- ipcp->mode & SHM_LOCKED ? "locked" : " ");
+ /*
+ * earlier: int, Austin has size_t
+ */
+ (unsigned long) shmseg.shm_segsz,
+ /*
+ * glibc-2.1.3 and earlier has unsigned short;
+ * Austin has shmatt_t
+ */
+ (long) shmseg.shm_nattch,
+ ipcp->mode & SHM_DEST ? "dest" : " ",
+ ipcp->mode & SHM_LOCKED ? "locked" : " ");
break;
}
}
@@ -281,32 +281,32 @@ static NOINLINE void do_sem(void)
if ((semctl(0, 0, IPC_INFO, arg)) < 0)
return;
printf("max number of arrays = %d\n"
- "max semaphores per array = %d\n"
- "max semaphores system wide = %d\n"
- "max ops per semop call = %d\n"
- "semaphore max value = %d\n",
- seminfo.semmni,
- seminfo.semmsl,
- seminfo.semmns, seminfo.semopm, seminfo.semvmx);
+ "max semaphores per array = %d\n"
+ "max semaphores system wide = %d\n"
+ "max ops per semop call = %d\n"
+ "semaphore max value = %d\n",
+ seminfo.semmni,
+ seminfo.semmsl,
+ seminfo.semmns, seminfo.semopm, seminfo.semvmx);
return;
case STATUS:
printf("------ Semaphore %s --------\n", "Status");
- printf( "used arrays = %d\n"
- "allocated semaphores = %d\n",
- seminfo.semusz, seminfo.semaem);
+ printf("used arrays = %d\n"
+ "allocated semaphores = %d\n",
+ seminfo.semusz, seminfo.semaem);
return;
case CREATOR:
printf("------ Semaphore %s --------\n", "Arrays Creators/Owners");
- printf( "%-10s %-10s %-10s %-10s %-10s %-10s\n",
- "semid", "perms", "cuid", "cgid", "uid", "gid");
+ printf("%-10s %-10s %-10s %-10s %-10s %-10s\n",
+ "semid", "perms", "cuid", "cgid", "uid", "gid");
break;
case TIME:
printf("------ Shared Memory %s --------\n", "Operation/Change Times");
- printf( "%-8s %-10s %-26.24s %-26.24s\n",
- "shmid", "owner", "last-op", "last-changed");
+ printf("%-8s %-10s %-26.24s %-26.24s\n",
+ "shmid", "owner", "last-op", "last-changed");
break;
case PID:
@@ -314,8 +314,8 @@ static NOINLINE void do_sem(void)
default:
printf("------ Semaphore %s --------\n", "Arrays");
- printf( "%-10s %-10s %-10s %-10s %-10s\n",
- "key", "semid", "owner", "perms", "nsems");
+ printf("%-10s %-10s %-10s %-10s %-10s\n",
+ "key", "semid", "owner", "perms", "nsems");
break;
}
@@ -337,9 +337,9 @@ static NOINLINE void do_sem(void)
printf("%-8d %-10d", semid, ipcp->uid);
/* ctime uses static buffer: use separate calls */
printf(" %-26.24s", semary.sem_otime
- ? ctime(&semary.sem_otime) : "Not set");
+ ? ctime(&semary.sem_otime) : "Not set");
printf(" %-26.24s\n", semary.sem_ctime
- ? ctime(&semary.sem_ctime) : "Not set");
+ ? ctime(&semary.sem_ctime) : "Not set");
break;
case PID:
break;
@@ -351,13 +351,13 @@ static NOINLINE void do_sem(void)
else
printf("%-10d %-9d", semid, ipcp->uid);
printf(" %-10o %-10ld\n", ipcp->mode & 0777,
- /*
- * glibc-2.1.3 and earlier has unsigned short;
- * glibc-2.1.91 has variation between
- * unsigned short and unsigned long
- * Austin prescribes unsigned short.
- */
- (long) semary.sem_nsems);
+ /*
+ * glibc-2.1.3 and earlier has unsigned short;
+ * glibc-2.1.91 has variation between
+ * unsigned short and unsigned long
+ * Austin prescribes unsigned short.
+ */
+ (long) semary.sem_nsems);
break;
}
}
@@ -383,42 +383,42 @@ static NOINLINE void do_msg(void)
if ((msgctl(0, IPC_INFO, (struct msqid_ds *) (void *) &msginfo)) < 0)
return;
printf("------ Message%s --------\n", "s: Limits");
- printf( "max queues system wide = %d\n"
- "max size of message (bytes) = %d\n"
- "default max size of queue (bytes) = %d\n",
- msginfo.msgmni, msginfo.msgmax, msginfo.msgmnb);
+ printf("max queues system wide = %d\n"
+ "max size of message (bytes) = %d\n"
+ "default max size of queue (bytes) = %d\n",
+ msginfo.msgmni, msginfo.msgmax, msginfo.msgmnb);
return;
case STATUS:
printf("------ Message%s --------\n", "s: Status");
- printf( "allocated queues = %d\n"
- "used headers = %d\n"
- "used space = %d bytes\n",
- msginfo.msgpool, msginfo.msgmap, msginfo.msgtql);
+ printf("allocated queues = %d\n"
+ "used headers = %d\n"
+ "used space = %d bytes\n",
+ msginfo.msgpool, msginfo.msgmap, msginfo.msgtql);
return;
case CREATOR:
printf("------ Message%s --------\n", " Queues: Creators/Owners");
- printf( "%-10s %-10s %-10s %-10s %-10s %-10s\n",
- "msqid", "perms", "cuid", "cgid", "uid", "gid");
+ printf("%-10s %-10s %-10s %-10s %-10s %-10s\n",
+ "msqid", "perms", "cuid", "cgid", "uid", "gid");
break;
case TIME:
printf("------ Message%s --------\n", " Queues Send/Recv/Change Times");
- printf( "%-8s %-10s %-20s %-20s %-20s\n",
- "msqid", "owner", "send", "recv", "change");
+ printf("%-8s %-10s %-20s %-20s %-20s\n",
+ "msqid", "owner", "send", "recv", "change");
break;
case PID:
printf("------ Message%s --------\n", " Queues PIDs");
- printf( "%-10s %-10s %-10s %-10s\n",
- "msqid", "owner", "lspid", "lrpid");
+ printf("%-10s %-10s %-10s %-10s\n",
+ "msqid", "owner", "lspid", "lrpid");
break;
default:
printf("------ Message%s --------\n", " Queues");
- printf( "%-10s %-10s %-10s %-10s %-12s %-12s\n",
- "key", "msqid", "owner", "perms", "used-bytes", "messages");
+ printf("%-10s %-10s %-10s %-10s %-12s %-12s\n",
+ "key", "msqid", "owner", "perms", "used-bytes", "messages");
break;
}
@@ -438,11 +438,11 @@ static NOINLINE void do_msg(void)
else
printf("%-8d %-10d", msqid, ipcp->uid);
printf(" %-20.16s", msgque.msg_stime
- ? ctime(&msgque.msg_stime) + 4 : "Not set");
+ ? ctime(&msgque.msg_stime) + 4 : "Not set");
printf(" %-20.16s", msgque.msg_rtime
- ? ctime(&msgque.msg_rtime) + 4 : "Not set");
+ ? ctime(&msgque.msg_rtime) + 4 : "Not set");
printf(" %-20.16s\n", msgque.msg_ctime
- ? ctime(&msgque.msg_ctime) + 4 : "Not set");
+ ? ctime(&msgque.msg_ctime) + 4 : "Not set");
break;
case PID:
if (pw)
@@ -459,13 +459,13 @@ static NOINLINE void do_msg(void)
else
printf("%-10d %-10d", msqid, ipcp->uid);
printf(" %-10o %-12ld %-12ld\n", ipcp->mode & 0777,
- /*
- * glibc-2.1.3 and earlier has unsigned short;
- * glibc-2.1.91 has variation between
- * unsigned short, unsigned long
- * Austin has msgqnum_t
- */
- (long) msgque.msg_cbytes, (long) msgque.msg_qnum);
+ /*
+ * glibc-2.1.3 and earlier has unsigned short;
+ * glibc-2.1.91 has variation between
+ * unsigned short, unsigned long
+ * Austin has msgqnum_t
+ */
+ (long) msgque.msg_cbytes, (long) msgque.msg_qnum);
break;
}
}
@@ -483,18 +483,18 @@ static void print_shm(int shmid)
}
printf("\nShared memory Segment shmid=%d\n"
- "uid=%d\tgid=%d\tcuid=%d\tcgid=%d\n"
- "mode=%#o\taccess_perms=%#o\n"
- "bytes=%ld\tlpid=%d\tcpid=%d\tnattch=%ld\n",
- shmid,
- ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid,
- ipcp->mode, ipcp->mode & 0777,
- (long) shmds.shm_segsz, shmds.shm_lpid, shmds.shm_cpid,
- (long) shmds.shm_nattch);
+ "uid=%d\tgid=%d\tcuid=%d\tcgid=%d\n"
+ "mode=%#o\taccess_perms=%#o\n"
+ "bytes=%ld\tlpid=%d\tcpid=%d\tnattch=%ld\n",
+ shmid,
+ ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid,
+ ipcp->mode, ipcp->mode & 0777,
+ (long) shmds.shm_segsz, shmds.shm_lpid, shmds.shm_cpid,
+ (long) shmds.shm_nattch);
printf("att_time=%-26.24s\n",
- shmds.shm_atime ? ctime(&shmds.shm_atime) : "Not set");
+ shmds.shm_atime ? ctime(&shmds.shm_atime) : "Not set");
printf("det_time=%-26.24s\n",
- shmds.shm_dtime ? ctime(&shmds.shm_dtime) : "Not set");
+ shmds.shm_dtime ? ctime(&shmds.shm_dtime) : "Not set");
printf("change_time=%-26.24s\n\n", ctime(&shmds.shm_ctime));
}
@@ -510,24 +510,24 @@ static void print_msg(int msqid)
}
printf("\nMessage Queue msqid=%d\n"
- "uid=%d\tgid=%d\tcuid=%d\tcgid=%d\tmode=%#o\n"
- "cbytes=%ld\tqbytes=%ld\tqnum=%ld\tlspid=%d\tlrpid=%d\n",
- msqid, ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid, ipcp->mode,
- /*
- * glibc-2.1.3 and earlier has unsigned short;
- * glibc-2.1.91 has variation between
- * unsigned short, unsigned long
- * Austin has msgqnum_t (for msg_qbytes)
- */
- (long) buf.msg_cbytes, (long) buf.msg_qbytes,
- (long) buf.msg_qnum, buf.msg_lspid, buf.msg_lrpid);
+ "uid=%d\tgid=%d\tcuid=%d\tcgid=%d\tmode=%#o\n"
+ "cbytes=%ld\tqbytes=%ld\tqnum=%ld\tlspid=%d\tlrpid=%d\n",
+ msqid, ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid, ipcp->mode,
+ /*
+ * glibc-2.1.3 and earlier has unsigned short;
+ * glibc-2.1.91 has variation between
+ * unsigned short, unsigned long
+ * Austin has msgqnum_t (for msg_qbytes)
+ */
+ (long) buf.msg_cbytes, (long) buf.msg_qbytes,
+ (long) buf.msg_qnum, buf.msg_lspid, buf.msg_lrpid);
printf("send_time=%-26.24s\n",
- buf.msg_stime ? ctime(&buf.msg_stime) : "Not set");
+ buf.msg_stime ? ctime(&buf.msg_stime) : "Not set");
printf("rcv_time=%-26.24s\n",
- buf.msg_rtime ? ctime(&buf.msg_rtime) : "Not set");
+ buf.msg_rtime ? ctime(&buf.msg_rtime) : "Not set");
printf("change_time=%-26.24s\n\n",
- buf.msg_ctime ? ctime(&buf.msg_ctime) : "Not set");
+ buf.msg_ctime ? ctime(&buf.msg_ctime) : "Not set");
}
static void print_sem(int semid)
@@ -544,19 +544,19 @@ static void print_sem(int semid)
}
printf("\nSemaphore Array semid=%d\n"
- "uid=%d\t gid=%d\t cuid=%d\t cgid=%d\n"
- "mode=%#o, access_perms=%#o\n"
- "nsems = %ld\n"
- "otime = %-26.24s\n",
- semid,
- ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid,
- ipcp->mode, ipcp->mode & 0777,
- (long) semds.sem_nsems,
- semds.sem_otime ? ctime(&semds.sem_otime) : "Not set");
+ "uid=%d\t gid=%d\t cuid=%d\t cgid=%d\n"
+ "mode=%#o, access_perms=%#o\n"
+ "nsems = %ld\n"
+ "otime = %-26.24s\n",
+ semid,
+ ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid,
+ ipcp->mode, ipcp->mode & 0777,
+ (long) semds.sem_nsems,
+ semds.sem_otime ? ctime(&semds.sem_otime) : "Not set");
printf("ctime = %-26.24s\n"
- "%-10s %-10s %-10s %-10s %-10s\n",
- ctime(&semds.sem_ctime),
- "semnum", "value", "ncount", "zcount", "pid");
+ "%-10s %-10s %-10s %-10s %-10s\n",
+ ctime(&semds.sem_ctime),
+ "semnum", "value", "ncount", "zcount", "pid");
arg.val = 0;
for (i = 0; i < semds.sem_nsems; i++) {
@@ -569,7 +569,7 @@ static void print_sem(int semid)
if (val < 0 || ncnt < 0 || zcnt < 0 || pid < 0) {
bb_perror_msg_and_die("semctl");
}
- printf("%-10d %-10d %-10d %-10d %-10d\n", i, val, ncnt, zcnt, pid);
+ printf("%-10u %-10d %-10d %-10d %-10d\n", i, val, ncnt, zcnt, pid);
}
bb_putchar('\n');
}
diff --git a/release/src/router/busybox/util-linux/losetup.c b/release/src/router/busybox/util-linux/losetup.c
index 21108d0bfb..d450b5a782 100644
--- a/release/src/router/busybox/util-linux/losetup.c
+++ b/release/src/router/busybox/util-linux/losetup.c
@@ -8,16 +8,16 @@
*/
//usage:#define losetup_trivial_usage
-//usage: "[-r] [-o OFS] LOOPDEV FILE - associate loop devices\n"
+//usage: "[-r] [-o OFS] {-f|LOOPDEV} FILE - associate loop devices\n"
//usage: " losetup -d LOOPDEV - disassociate\n"
-//usage: " losetup [-f] - show"
+//usage: " losetup -a - show status\n"
+//usage: " losetup -f - show next free loop device"
//usage:#define losetup_full_usage "\n\n"
//usage: " -o OFS Start OFS bytes into FILE"
//usage: "\n -r Read-only"
-//usage: "\n -f Show first free loop device"
+//usage: "\n -f Show/use next free loop device"
//usage:
//usage:#define losetup_notes_usage
-//usage: "No arguments will display all current associations.\n"
//usage: "One argument (losetup /dev/loop1) will display the current association\n"
//usage: "(if any), or disassociate it (with -d). The display shows the offset\n"
//usage: "and filename of the file the loop device is currently bound to.\n\n"
@@ -27,50 +27,32 @@
#include "libbb.h"
+/* 1048575 is a max possible minor number in Linux circa 2010 */
+/* for now use something less extreme */
+#define MAX_LOOP_NUM 1023
+
int losetup_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int losetup_main(int argc UNUSED_PARAM, char **argv)
{
unsigned opt;
- int n;
char *opt_o;
- unsigned long long offset = 0;
+ char dev[LOOP_NAMESIZE];
enum {
OPT_d = (1 << 0),
OPT_o = (1 << 1),
OPT_f = (1 << 2),
- OPT_r = (1 << 3), /* must be last */
+ OPT_a = (1 << 3),
+ OPT_r = (1 << 4), /* must be last */
};
- /* max 2 args, -d,-o,-f opts are mutually exclusive */
- opt_complementary = "?2:d--of:o--df:f--do";
- opt = getopt32(argv, "do:fr", &opt_o);
+ opt_complementary = "?2:d--ofar:a--ofr";
+ opt = getopt32(argv, "do:far", &opt_o);
argv += optind;
- if (opt == OPT_o)
- offset = xatoull(opt_o);
-
- if (opt == OPT_d) {
- /* -d BLOCKDEV */
- if (!argv[0] || argv[1])
- bb_show_usage();
- if (del_loop(argv[0]))
- bb_simple_perror_msg_and_die(argv[0]);
- return EXIT_SUCCESS;
- }
-
- if (argv[0]) {
+ /* LOOPDEV */
+ if (!opt && argv[0] && !argv[1]) {
char *s;
- if (opt == OPT_f) /* -f should not have arguments */
- bb_show_usage();
-
- if (argv[1]) {
- /* [-r] [-o OFS] BLOCKDEV FILE */
- if (set_loop(&argv[0], argv[1], offset, (opt / OPT_r)) < 0)
- bb_simple_perror_msg_and_die(argv[0]);
- return EXIT_SUCCESS;
- }
- /* [-r] [-o OFS] BLOCKDEV */
s = query_loop(argv[0]);
if (!s)
bb_simple_perror_msg_and_die(argv[0]);
@@ -80,28 +62,65 @@ int losetup_main(int argc UNUSED_PARAM, char **argv)
return EXIT_SUCCESS;
}
- /* [-r] [-o OFS|-f] with no params */
- n = 0;
- while (1) {
- char *s;
- char dev[LOOP_NAMESIZE];
-
- sprintf(dev, LOOP_FORMAT, n);
- s = query_loop(dev);
- n++;
- if (!s) {
- if (n > 9 && errno && errno != ENXIO)
- return EXIT_SUCCESS;
- if (opt == OPT_f) {
- puts(dev);
- return EXIT_SUCCESS;
- }
- } else {
- if (opt != OPT_f)
+ /* -d LOOPDEV */
+ if (opt == OPT_d && argv[0]) {
+ if (del_loop(argv[0]))
+ bb_simple_perror_msg_and_die(argv[0]);
+ return EXIT_SUCCESS;
+ }
+
+ /* -a */
+ if (opt == OPT_a) {
+ int n;
+ for (n = 0; n < MAX_LOOP_NUM; n++) {
+ char *s;
+
+ sprintf(dev, LOOP_FORMAT, n);
+ s = query_loop(dev);
+ if (s) {
printf("%s: %s\n", dev, s);
- if (ENABLE_FEATURE_CLEAN_UP)
free(s);
+ }
+ }
+ return EXIT_SUCCESS;
+ }
+
+ /* contains -f */
+ if (opt & OPT_f) {
+ char *s;
+ int n = 0;
+
+ do {
+ if (n > MAX_LOOP_NUM)
+ bb_error_msg_and_die("no free loop devices");
+ sprintf(dev, LOOP_FORMAT, n++);
+ s = query_loop(dev);
+ free(s);
+ } while (s);
+ /* now: dev is next free "/dev/loopN" */
+ if ((opt == OPT_f) && !argv[0]) {
+ puts(dev);
+ return EXIT_SUCCESS;
}
}
- return EXIT_SUCCESS;
+
+ /* [-r] [-o OFS] {-f|LOOPDEV} FILE */
+ if (argv[0] && ((opt & OPT_f) || argv[1])) {
+ unsigned long long offset = 0;
+ char *d = dev;
+
+ if (opt & OPT_o)
+ offset = xatoull(opt_o);
+ if (!(opt & OPT_f))
+ d = *argv++;
+
+ if (argv[0]) {
+ if (set_loop(&d, argv[0], offset, (opt & OPT_r)) < 0)
+ bb_simple_perror_msg_and_die(argv[0]);
+ return EXIT_SUCCESS;
+ }
+ }
+
+ bb_show_usage(); /* does not return */
+ /*return EXIT_FAILURE;*/
}
diff --git a/release/src/router/busybox/util-linux/lspci.c b/release/src/router/busybox/util-linux/lspci.c
index 5184858d18..514678afd3 100644
--- a/release/src/router/busybox/util-linux/lspci.c
+++ b/release/src/router/busybox/util-linux/lspci.c
@@ -74,11 +74,11 @@ static int FAST_FUNC fileAction(
if (option_mask32 & OPT_m) {
printf("%s \"Class %04x\" \"%04x\" \"%04x\" \"%04x\" \"%04x\"",
- pci_slot_name, pci_class, pci_vid, pci_did,
- pci_subsys_vid, pci_subsys_did);
+ pci_slot_name, pci_class, pci_vid, pci_did,
+ pci_subsys_vid, pci_subsys_did);
} else {
printf("%s Class %04x: %04x:%04x",
- pci_slot_name, pci_class, pci_vid, pci_did);
+ pci_slot_name, pci_class, pci_vid, pci_did);
}
if ((option_mask32 & OPT_k) && driver) {
diff --git a/release/src/router/busybox/util-linux/mdev.c b/release/src/router/busybox/util-linux/mdev.c
index d7b7d806ac..37514eb542 100644
--- a/release/src/router/busybox/util-linux/mdev.c
+++ b/release/src/router/busybox/util-linux/mdev.c
@@ -80,7 +80,7 @@
//usage: IF_FEATURE_MDEV_CONF(
//usage: "\n"
//usage: "It uses /etc/mdev.conf with lines\n"
-//usage: " [-]DEVNAME UID:GID PERM"
+//usage: " [-][ENV=regex;]...DEVNAME UID:GID PERM"
//usage: IF_FEATURE_MDEV_RENAME(" [>|=PATH]|[!]")
//usage: IF_FEATURE_MDEV_EXEC(" [@|$|*PROG]")
//usage: "\n"
@@ -92,9 +92,12 @@
//usage: "\n"
//usage: "If /dev/mdev.seq file exists, mdev will wait for its value\n"
//usage: "to match $SEQNUM variable. This prevents plug/unplug races.\n"
-//usage: "To activate this feature, create empty /dev/mdev.seq at boot."
+//usage: "To activate this feature, create empty /dev/mdev.seq at boot.\n"
+//usage: "\n"
+//usage: "If /dev/mdev.log file exists, debug log will be appended to it."
#include "libbb.h"
+#include "common_bufsiz.h"
#include "xregex.h"
/* "mdev -s" scans /sys/class/xxx, looking for directories which have dev
@@ -139,10 +142,126 @@
* This happens regardless of /sys/class/.../dev existence.
*/
+/* Kernel's hotplug environment constantly changes.
+ * Here are new cases I observed on 3.1.0:
+ *
+ * Case with $DEVNAME and $DEVICE, not just $DEVPATH:
+ * ACTION=add
+ * BUSNUM=001
+ * DEVICE=/proc/bus/usb/001/003
+ * DEVNAME=bus/usb/001/003
+ * DEVNUM=003
+ * DEVPATH=/devices/pci0000:00/0000:00:02.1/usb1/1-5
+ * DEVTYPE=usb_device
+ * MAJOR=189
+ * MINOR=2
+ * PRODUCT=18d1/4e12/227
+ * SUBSYSTEM=usb
+ * TYPE=0/0/0
+ *
+ * Case with $DEVICE, but no $DEVNAME - apparenty, usb iface notification?
+ * "Please load me a module" thing?
+ * ACTION=add
+ * DEVICE=/proc/bus/usb/001/003
+ * DEVPATH=/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0
+ * DEVTYPE=usb_interface
+ * INTERFACE=8/6/80
+ * MODALIAS=usb:v18D1p4E12d0227dc00dsc00dp00ic08isc06ip50
+ * PRODUCT=18d1/4e12/227
+ * SUBSYSTEM=usb
+ * TYPE=0/0/0
+ *
+ * ACTION=add
+ * DEVPATH=/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0/host5
+ * DEVTYPE=scsi_host
+ * SUBSYSTEM=scsi
+ *
+ * ACTION=add
+ * DEVPATH=/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0/host5/scsi_host/host5
+ * SUBSYSTEM=scsi_host
+ *
+ * ACTION=add
+ * DEVPATH=/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0/host5/target5:0:0
+ * DEVTYPE=scsi_target
+ * SUBSYSTEM=scsi
+ *
+ * Case with strange $MODALIAS:
+ * ACTION=add
+ * DEVPATH=/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0/host5/target5:0:0/5:0:0:0
+ * DEVTYPE=scsi_device
+ * MODALIAS=scsi:t-0x00
+ * SUBSYSTEM=scsi
+ *
+ * ACTION=add
+ * DEVPATH=/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0/host5/target5:0:0/5:0:0:0/scsi_disk/5:0:0:0
+ * SUBSYSTEM=scsi_disk
+ *
+ * ACTION=add
+ * DEVPATH=/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0/host5/target5:0:0/5:0:0:0/scsi_device/5:0:0:0
+ * SUBSYSTEM=scsi_device
+ *
+ * Case with explicit $MAJOR/$MINOR (no need to read /sys/$DEVPATH/dev?):
+ * ACTION=add
+ * DEVNAME=bsg/5:0:0:0
+ * DEVPATH=/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0/host5/target5:0:0/5:0:0:0/bsg/5:0:0:0
+ * MAJOR=253
+ * MINOR=1
+ * SUBSYSTEM=bsg
+ *
+ * ACTION=add
+ * DEVPATH=/devices/virtual/bdi/8:16
+ * SUBSYSTEM=bdi
+ *
+ * ACTION=add
+ * DEVNAME=sdb
+ * DEVPATH=/block/sdb
+ * DEVTYPE=disk
+ * MAJOR=8
+ * MINOR=16
+ * SUBSYSTEM=block
+ *
+ * Case with ACTION=change:
+ * ACTION=change
+ * DEVNAME=sdb
+ * DEVPATH=/block/sdb
+ * DEVTYPE=disk
+ * DISK_MEDIA_CHANGE=1
+ * MAJOR=8
+ * MINOR=16
+ * SUBSYSTEM=block
+ */
+
+#define DEBUG_LVL 2
+
+#if DEBUG_LVL >= 1
+# define dbg1(...) do { if (G.verbose) bb_error_msg(__VA_ARGS__); } while(0)
+#else
+# define dbg1(...) ((void)0)
+#endif
+#if DEBUG_LVL >= 2
+# define dbg2(...) do { if (G.verbose >= 2) bb_error_msg(__VA_ARGS__); } while(0)
+#else
+# define dbg2(...) ((void)0)
+#endif
+#if DEBUG_LVL >= 3
+# define dbg3(...) do { if (G.verbose >= 3) bb_error_msg(__VA_ARGS__); } while(0)
+#else
+# define dbg3(...) ((void)0)
+#endif
+
+
+static const char keywords[] ALIGN1 = "add\0remove\0"; // "change\0"
+enum { OP_add, OP_remove };
+
+struct envmatch {
+ struct envmatch *next;
+ char *envname;
+ regex_t match;
+};
+
struct rule {
bool keep_matching;
bool regex_compiled;
- bool regex_has_slash;
mode_t mode;
int maj, min0, min1;
struct bb_uidgid_t ugid;
@@ -150,11 +269,14 @@ struct rule {
char *ren_mov;
IF_FEATURE_MDEV_EXEC(char *r_cmd;)
regex_t match;
+ struct envmatch *envmatch;
};
struct globals {
int root_major, root_minor;
+ smallint verbose;
char *subsystem;
+ char *subsys_env; /* for putenv("SUBSYSTEM=subsystem") */
#if ENABLE_FEATURE_MDEV_CONF
const char *filename;
parser_t *parser;
@@ -162,9 +284,11 @@ struct globals {
unsigned rule_idx;
#endif
struct rule cur_rule;
+ char timestr[sizeof("HH:MM:SS.123456")];
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define INIT_G() do { \
+ setup_common_bufsiz(); \
IF_NOT_FEATURE_MDEV_CONF(G.cur_rule.maj = -1;) \
IF_NOT_FEATURE_MDEV_CONF(G.cur_rule.mode = 0660;) \
} while (0)
@@ -173,15 +297,8 @@ struct globals {
/* Prevent infinite loops in /sys symlinks */
#define MAX_SYSFS_DEPTH 3
-/* We use additional 64+ bytes in make_device() */
-#define SCRATCH_SIZE 80
-
-#if 0
-# define dbg(...) bb_error_msg(__VA_ARGS__)
-#else
-# define dbg(...) ((void)0)
-#endif
-
+/* We use additional bytes in make_device() */
+#define SCRATCH_SIZE 128
#if ENABLE_FEATURE_MDEV_CONF
@@ -194,14 +311,48 @@ static void make_default_cur_rule(void)
static void clean_up_cur_rule(void)
{
+ struct envmatch *e;
+
free(G.cur_rule.envvar);
+ free(G.cur_rule.ren_mov);
if (G.cur_rule.regex_compiled)
regfree(&G.cur_rule.match);
- free(G.cur_rule.ren_mov);
IF_FEATURE_MDEV_EXEC(free(G.cur_rule.r_cmd);)
+ e = G.cur_rule.envmatch;
+ while (e) {
+ free(e->envname);
+ regfree(&e->match);
+ e = e->next;
+ }
make_default_cur_rule();
}
+static char *parse_envmatch_pfx(char *val)
+{
+ struct envmatch **nextp = &G.cur_rule.envmatch;
+
+ for (;;) {
+ struct envmatch *e;
+ char *semicolon;
+ char *eq = strchr(val, '=');
+ if (!eq /* || eq == val? */)
+ return val;
+ if (endofname(val) != eq)
+ return val;
+ semicolon = strchr(eq, ';');
+ if (!semicolon)
+ return val;
+ /* ENVVAR=regex;... */
+ *nextp = e = xzalloc(sizeof(*e));
+ nextp = &e->next;
+ e->envname = xstrndup(val, eq - val);
+ *semicolon = '\0';
+ xregcomp(&e->match, eq + 1, REG_EXTENDED);
+ *semicolon = ';';
+ val = semicolon + 1;
+ }
+}
+
static void parse_next_rule(void)
{
/* Note: on entry, G.cur_rule is set to default */
@@ -214,12 +365,13 @@ static void parse_next_rule(void)
break;
/* Fields: [-]regex uid:gid mode [alias] [cmd] */
- dbg("token1:'%s'", tokens[1]);
+ dbg3("token1:'%s'", tokens[1]);
/* 1st field */
val = tokens[0];
G.cur_rule.keep_matching = ('-' == val[0]);
val += G.cur_rule.keep_matching; /* swallow leading dash */
+ val = parse_envmatch_pfx(val);
if (val[0] == '@') {
/* @major,minor[-minor2] */
/* (useful when name is ambiguous:
@@ -234,8 +386,10 @@ static void parse_next_rule(void)
if (sc == 2)
G.cur_rule.min1 = G.cur_rule.min0;
} else {
+ char *eq = strchr(val, '=');
if (val[0] == '$') {
- char *eq = strchr(++val, '=');
+ /* $ENVVAR=regex ... */
+ val++;
if (!eq) {
bb_error_msg("bad $envvar=regex on line %d", G.parser->lineno);
goto next_rule;
@@ -245,17 +399,16 @@ static void parse_next_rule(void)
}
xregcomp(&G.cur_rule.match, val, REG_EXTENDED);
G.cur_rule.regex_compiled = 1;
- G.cur_rule.regex_has_slash = (strchr(val, '/') != NULL);
}
/* 2nd field: uid:gid - device ownership */
- if (get_uidgid(&G.cur_rule.ugid, tokens[1], /*allow_numeric:*/ 1) == 0) {
+ if (get_uidgid(&G.cur_rule.ugid, tokens[1]) == 0) {
bb_error_msg("unknown user/group '%s' on line %d", tokens[1], G.parser->lineno);
goto next_rule;
}
/* 3rd field: mode - device permissions */
- bb_parse_mode(tokens[2], &G.cur_rule.mode);
+ G.cur_rule.mode = bb_parse_mode(tokens[2], G.cur_rule.mode);
/* 4th field (opt): ">|=alias" or "!" to not create the node */
val = tokens[3];
@@ -280,7 +433,7 @@ static void parse_next_rule(void)
clean_up_cur_rule();
} /* while (config_read) */
- dbg("config_close(G.parser)");
+ dbg3("config_close(G.parser)");
config_close(G.parser);
G.parser = NULL;
@@ -297,7 +450,7 @@ static const struct rule *next_rule(void)
/* Open conf file if we didn't do it yet */
if (!G.parser && G.filename) {
- dbg("config_open('%s')", G.filename);
+ dbg3("config_open('%s')", G.filename);
G.parser = config_open2(G.filename, fopen_for_read);
G.filename = NULL;
}
@@ -306,7 +459,7 @@ static const struct rule *next_rule(void)
/* mdev -s */
/* Do we have rule parsed already? */
if (G.rule_vec[G.rule_idx]) {
- dbg("< G.rule_vec[G.rule_idx:%d]=%p", G.rule_idx, G.rule_vec[G.rule_idx]);
+ dbg3("< G.rule_vec[G.rule_idx:%d]=%p", G.rule_idx, G.rule_vec[G.rule_idx]);
return G.rule_vec[G.rule_idx++];
}
make_default_cur_rule();
@@ -320,16 +473,31 @@ static const struct rule *next_rule(void)
if (G.parser) {
parse_next_rule();
if (G.rule_vec) { /* mdev -s */
- rule = memcpy(xmalloc(sizeof(G.cur_rule)), &G.cur_rule, sizeof(G.cur_rule));
+ rule = xmemdup(&G.cur_rule, sizeof(G.cur_rule));
G.rule_vec = xrealloc_vector(G.rule_vec, 4, G.rule_idx);
G.rule_vec[G.rule_idx++] = rule;
- dbg("> G.rule_vec[G.rule_idx:%d]=%p", G.rule_idx, G.rule_vec[G.rule_idx]);
+ dbg3("> G.rule_vec[G.rule_idx:%d]=%p", G.rule_idx, G.rule_vec[G.rule_idx]);
}
}
return rule;
}
+static int env_matches(struct envmatch *e)
+{
+ while (e) {
+ int r;
+ char *val = getenv(e->envname);
+ if (!val)
+ return 0;
+ r = regexec(&e->match, val, /*size*/ 0, /*range[]*/ NULL, /*eflags*/ 0);
+ if (r != 0) /* no match */
+ return 0;
+ e = e->next;
+ }
+ return 1;
+}
+
#else
# define next_rule() (&G.cur_rule)
@@ -375,16 +543,17 @@ static char *build_alias(char *alias, const char *device_name)
/* mknod in /dev based on a path like "/sys/block/hda/hda1"
* NB1: path parameter needs to have SCRATCH_SIZE scratch bytes
- * after NUL, but we promise to not mangle (IOW: to restore if needed)
+ * after NUL, but we promise to not mangle (IOW: to restore NUL if needed)
* path string.
* NB2: "mdev -s" may call us many times, do not leak memory/fds!
+ *
+ * device_name = $DEVNAME (may be NULL)
+ * path = /sys/$DEVPATH
*/
-static void make_device(char *path, int delete)
+static void make_device(char *device_name, char *path, int operation)
{
- char *device_name, *subsystem_slash_devname;
int major, minor, type, len;
-
- dbg("%s('%s', delete:%d)", __func__, path, delete);
+ char *path_end = path + strlen(path);
/* Try to read major/minor string. Note that the kernel puts \n after
* the data, so we don't need to worry about null terminating the string
@@ -392,51 +561,60 @@ static void make_device(char *path, int delete)
* We also depend on path having writeable space after it.
*/
major = -1;
- if (!delete) {
- char *dev_maj_min = path + strlen(path);
-
- strcpy(dev_maj_min, "/dev");
- len = open_read_close(path, dev_maj_min + 1, 64);
- *dev_maj_min = '\0';
+ if (operation == OP_add) {
+ strcpy(path_end, "/dev");
+ len = open_read_close(path, path_end + 1, SCRATCH_SIZE - 1);
+ *path_end = '\0';
if (len < 1) {
if (!ENABLE_FEATURE_MDEV_EXEC)
return;
/* no "dev" file, but we can still run scripts
* based on device name */
- } else if (sscanf(++dev_maj_min, "%u:%u", &major, &minor) != 2) {
+ } else if (sscanf(path_end + 1, "%u:%u", &major, &minor) == 2) {
+ dbg1("dev %u,%u", major, minor);
+ } else {
major = -1;
}
}
/* else: for delete, -1 still deletes the node, but < -1 suppresses that */
- /* Determine device name, type, major and minor */
- device_name = (char*) bb_basename(path);
- /* http://kernel.org/doc/pending/hotplug.txt says that only
+ /* Determine device name */
+ if (!device_name) {
+ /*
+ * There was no $DEVNAME envvar (for example, mdev -s never has).
+ * But it is very useful: it contains the *path*, not only basename,
+ * Thankfully, uevent file has it.
+ * Example of .../sound/card0/controlC0/uevent file on Linux-3.7.7:
+ * MAJOR=116
+ * MINOR=7
+ * DEVNAME=snd/controlC0
+ */
+ strcpy(path_end, "/uevent");
+ len = open_read_close(path, path_end + 1, SCRATCH_SIZE - 1);
+ if (len < 0)
+ len = 0;
+ *path_end = '\0';
+ path_end[1 + len] = '\0';
+ device_name = strstr(path_end + 1, "\nDEVNAME=");
+ if (device_name) {
+ device_name += sizeof("\nDEVNAME=")-1;
+ strchrnul(device_name, '\n')[0] = '\0';
+ } else {
+ /* Fall back to just basename */
+ device_name = (char*) bb_basename(path);
+ }
+ }
+ /* Determine device type */
+ /*
+ * http://kernel.org/doc/pending/hotplug.txt says that only
* "/sys/block/..." is for block devices. "/sys/bus" etc is not.
* But since 2.6.25 block devices are also in /sys/class/block.
- * We use strstr("/block/") to forestall future surprises. */
+ * We use strstr("/block/") to forestall future surprises.
+ */
type = S_IFCHR;
- if (strstr(path, "/block/") || (G.subsystem && strncmp(G.subsystem, "block", 5) == 0))
+ if (strstr(path, "/block/") || (G.subsystem && is_prefixed_with(G.subsystem, "block")))
type = S_IFBLK;
- /* Make path point to "subsystem/device_name" */
- subsystem_slash_devname = NULL;
- /* Check for coldplug invocations first */
- if (strncmp(path, "/sys/block/", 11) == 0) /* legacy case */
- path += sizeof("/sys/") - 1;
- else if (strncmp(path, "/sys/class/", 11) == 0)
- path += sizeof("/sys/class/") - 1;
- else {
- /* Example of a hotplug invocation:
- * SUBSYSTEM="block"
- * DEVPATH="/sys" + "/devices/virtual/mtd/mtd3/mtdblock3"
- * ("/sys" is added by mdev_main)
- * - path does not contain subsystem
- */
- subsystem_slash_devname = concat_path_file(G.subsystem, device_name);
- path = subsystem_slash_devname;
- }
-
#if ENABLE_FEATURE_MDEV_CONF
G.rule_idx = 0; /* restart from the beginning (think mdev -s) */
#endif
@@ -446,14 +624,16 @@ static void make_device(char *path, int delete)
char *command;
char *alias;
char aliaslink = aliaslink; /* for compiler */
- const char *node_name;
+ char *node_name;
const struct rule *rule;
- str_to_match = "";
+ str_to_match = device_name;
rule = next_rule();
#if ENABLE_FEATURE_MDEV_CONF
+ if (!env_matches(rule->envmatch))
+ continue;
if (rule->maj >= 0) { /* @maj,min rule */
if (major != rule->maj)
continue;
@@ -464,17 +644,15 @@ static void make_device(char *path, int delete)
}
if (rule->envvar) { /* $envvar=regex rule */
str_to_match = getenv(rule->envvar);
- dbg("getenv('%s'):'%s'", rule->envvar, str_to_match);
+ dbg3("getenv('%s'):'%s'", rule->envvar, str_to_match);
if (!str_to_match)
continue;
- } else {
- /* regex to match [subsystem/]device_name */
- str_to_match = (rule->regex_has_slash ? path : device_name);
}
+ /* else: str_to_match = device_name */
if (rule->regex_compiled) {
int regex_match = regexec(&rule->match, str_to_match, ARRAY_SIZE(off), off, 0);
- dbg("regex_match for '%s':%d", str_to_match, regex_match);
+ dbg3("regex_match for '%s':%d", str_to_match, regex_match);
//bb_error_msg("matches:");
//for (int i = 0; i < ARRAY_SIZE(off); i++) {
// if (off[i].rm_so < 0) continue;
@@ -493,9 +671,8 @@ static void make_device(char *path, int delete)
}
/* else: it's final implicit "match-all" rule */
rule_matches:
+ dbg2("rule matched, line %d", G.parser ? G.parser->lineno : -1);
#endif
- dbg("rule matched");
-
/* Build alias name */
alias = NULL;
if (ENABLE_FEATURE_MDEV_RENAME && rule->ren_mov) {
@@ -538,51 +715,64 @@ static void make_device(char *path, int delete)
}
}
}
- dbg("alias:'%s'", alias);
+ dbg3("alias:'%s'", alias);
command = NULL;
IF_FEATURE_MDEV_EXEC(command = rule->r_cmd;)
if (command) {
- const char *s = "$@*";
- const char *s2 = strchr(s, command[0]);
-
/* Are we running this command now?
- * Run $cmd on delete, @cmd on create, *cmd on both
+ * Run @cmd on create, $cmd on delete, *cmd on any
*/
- if (s2 - s != delete) {
- /* We are here if: '*',
- * or: '@' and delete = 0,
- * or: '$' and delete = 1
- */
+ if ((command[0] == '@' && operation == OP_add)
+ || (command[0] == '$' && operation == OP_remove)
+ || (command[0] == '*')
+ ) {
command++;
} else {
command = NULL;
}
}
- dbg("command:'%s'", command);
+ dbg3("command:'%s'", command);
/* "Execute" the line we found */
node_name = device_name;
if (ENABLE_FEATURE_MDEV_RENAME && alias) {
node_name = alias = build_alias(alias, device_name);
- dbg("alias2:'%s'", alias);
+ dbg3("alias2:'%s'", alias);
}
- if (!delete && major >= 0) {
- dbg("mknod('%s',%o,(%d,%d))", node_name, rule->mode | type, major, minor);
+ if (operation == OP_add && major >= 0) {
+ char *slash = strrchr(node_name, '/');
+ if (slash) {
+ *slash = '\0';
+ mkdir_recursive(node_name);
+ *slash = '/';
+ }
+ if (ENABLE_FEATURE_MDEV_CONF) {
+ dbg1("mknod %s (%d,%d) %o"
+ " %u:%u",
+ node_name, major, minor, rule->mode | type,
+ rule->ugid.uid, rule->ugid.gid
+ );
+ } else {
+ dbg1("mknod %s (%d,%d) %o",
+ node_name, major, minor, rule->mode | type
+ );
+ }
if (mknod(node_name, rule->mode | type, makedev(major, minor)) && errno != EEXIST)
bb_perror_msg("can't create '%s'", node_name);
- if (major == G.root_major && minor == G.root_minor)
- symlink(node_name, "root");
if (ENABLE_FEATURE_MDEV_CONF) {
chmod(node_name, rule->mode);
chown(node_name, rule->ugid.uid, rule->ugid.gid);
}
+ if (major == G.root_major && minor == G.root_minor)
+ symlink(node_name, "root");
if (ENABLE_FEATURE_MDEV_RENAME && alias) {
if (aliaslink == '>') {
//TODO: on devtmpfs, device_name already exists and symlink() fails.
//End result is that instead of symlink, we have two nodes.
//What should be done?
+ dbg1("symlink: %s", device_name);
symlink(node_name, device_name);
}
}
@@ -591,20 +781,21 @@ static void make_device(char *path, int delete)
if (ENABLE_FEATURE_MDEV_EXEC && command) {
/* setenv will leak memory, use putenv/unsetenv/free */
char *s = xasprintf("%s=%s", "MDEV", node_name);
- char *s1 = xasprintf("%s=%s", "SUBSYSTEM", G.subsystem);
putenv(s);
- putenv(s1);
+ dbg1("running: %s", command);
if (system(command) == -1)
bb_perror_msg("can't run '%s'", command);
- bb_unsetenv_and_free(s1);
bb_unsetenv_and_free(s);
}
- if (delete && major >= -1) {
+ if (operation == OP_remove && major >= -1) {
if (ENABLE_FEATURE_MDEV_RENAME && alias) {
- if (aliaslink == '>')
+ if (aliaslink == '>') {
+ dbg1("unlink: %s", device_name);
unlink(device_name);
+ }
}
+ dbg1("unlink: %s", node_name);
unlink(node_name);
}
@@ -617,8 +808,6 @@ static void make_device(char *path, int delete)
if (!ENABLE_FEATURE_MDEV_CONF || !rule->keep_matching)
break;
} /* for (;;) */
-
- free(subsystem_slash_devname);
}
/* File callback for /sys/ traversal */
@@ -636,7 +825,7 @@ static int FAST_FUNC fileAction(const char *fileName,
strcpy(scratch, fileName);
scratch[len] = '\0';
- make_device(scratch, /*delete:*/ 0);
+ make_device(/*DEVNAME:*/ NULL, scratch, OP_add);
return TRUE;
}
@@ -651,9 +840,16 @@ static int FAST_FUNC dirAction(const char *fileName UNUSED_PARAM,
* under /sys/class/ */
if (1 == depth) {
free(G.subsystem);
+ if (G.subsys_env) {
+ bb_unsetenv_and_free(G.subsys_env);
+ G.subsys_env = NULL;
+ }
G.subsystem = strrchr(fileName, '/');
- if (G.subsystem)
+ if (G.subsystem) {
G.subsystem = xstrdup(G.subsystem + 1);
+ G.subsys_env = xasprintf("%s=%s", "SUBSYSTEM", G.subsystem);
+ putenv(G.subsys_env);
+ }
}
return (depth >= MAX_SYSFS_DEPTH ? SKIP : TRUE);
@@ -708,7 +904,7 @@ static void load_firmware(const char *firmware, const char *sysfs_path)
}
/* Tell kernel result by "echo [0|-1] > /sys/$DEVPATH/loading"
- * Note: we emit -1 if firmware file wasn't found.
+ * Note: we emit -1 also if firmware file wasn't found.
* There are cases when otherwise kernel would wait for minutes
* before timing out.
*/
@@ -718,12 +914,121 @@ static void load_firmware(const char *firmware, const char *sysfs_path)
full_write(loading_fd, "-1", 2);
out:
+ xchdir("/dev");
if (ENABLE_FEATURE_CLEAN_UP) {
close(firmware_fd);
close(loading_fd);
}
}
+static char *curtime(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ sprintf(
+ strftime_HHMMSS(G.timestr, sizeof(G.timestr), &tv.tv_sec),
+ ".%06u",
+ (unsigned)tv.tv_usec
+ );
+ return G.timestr;
+}
+
+static void open_mdev_log(const char *seq, unsigned my_pid)
+{
+ int logfd = open("mdev.log", O_WRONLY | O_APPEND);
+ if (logfd >= 0) {
+ xmove_fd(logfd, STDERR_FILENO);
+ G.verbose = 2;
+ applet_name = xasprintf("%s[%s]", applet_name, seq ? seq : utoa(my_pid));
+ }
+}
+
+/* If it exists, does /dev/mdev.seq match $SEQNUM?
+ * If it does not match, earlier mdev is running
+ * in parallel, and we need to wait.
+ * Active mdev pokes us with SIGCHLD to check the new file.
+ */
+static int
+wait_for_seqfile(unsigned expected_seq)
+{
+ /* We time out after 2 sec */
+ static const struct timespec ts = { 0, 32*1000*1000 };
+ int timeout = 2000 / 32;
+ int seq_fd = -1;
+ int do_once = 1;
+ sigset_t set_CHLD;
+
+ sigemptyset(&set_CHLD);
+ sigaddset(&set_CHLD, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &set_CHLD, NULL);
+
+ for (;;) {
+ int seqlen;
+ char seqbuf[sizeof(long)*3 + 2];
+ unsigned seqbufnum;
+
+ if (seq_fd < 0) {
+ seq_fd = open("mdev.seq", O_RDWR);
+ if (seq_fd < 0)
+ break;
+ close_on_exec_on(seq_fd);
+ }
+ seqlen = pread(seq_fd, seqbuf, sizeof(seqbuf) - 1, 0);
+ if (seqlen < 0) {
+ close(seq_fd);
+ seq_fd = -1;
+ break;
+ }
+ seqbuf[seqlen] = '\0';
+ if (seqbuf[0] == '\n' || seqbuf[0] == '\0') {
+ /* seed file: write out seq ASAP */
+ xwrite_str(seq_fd, utoa(expected_seq));
+ xlseek(seq_fd, 0, SEEK_SET);
+ dbg2("first seq written");
+ break;
+ }
+ seqbufnum = atoll(seqbuf);
+ if (seqbufnum == expected_seq) {
+ /* correct idx */
+ break;
+ }
+ if (seqbufnum > expected_seq) {
+ /* a later mdev runs already (this was seen by users to happen) */
+ /* do not overwrite seqfile on exit */
+ close(seq_fd);
+ seq_fd = -1;
+ break;
+ }
+ if (do_once) {
+ dbg2("%s mdev.seq='%s', need '%u'", curtime(), seqbuf, expected_seq);
+ do_once = 0;
+ }
+ if (sigtimedwait(&set_CHLD, NULL, &ts) >= 0) {
+ dbg3("woken up");
+ continue; /* don't decrement timeout! */
+ }
+ if (--timeout == 0) {
+ dbg1("%s mdev.seq='%s'", "timed out", seqbuf);
+ break;
+ }
+ }
+ sigprocmask(SIG_UNBLOCK, &set_CHLD, NULL);
+ return seq_fd;
+}
+
+static void signal_mdevs(unsigned my_pid)
+{
+ procps_status_t* p = NULL;
+ while ((p = procps_scan(p, PSSCAN_ARGV0)) != NULL) {
+ if (p->pid != my_pid
+ && p->argv0
+ && strcmp(bb_basename(p->argv0), "mdev") == 0
+ ) {
+ kill(p->pid, SIGCHLD);
+ }
+ }
+}
+
int mdev_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int mdev_main(int argc UNUSED_PARAM, char **argv)
{
@@ -745,8 +1050,8 @@ int mdev_main(int argc UNUSED_PARAM, char **argv)
xchdir("/dev");
if (argv[1] && strcmp(argv[1], "-s") == 0) {
- /* Scan:
- * mdev -s
+ /*
+ * Scan: mdev -s
*/
struct stat st;
@@ -758,6 +1063,8 @@ int mdev_main(int argc UNUSED_PARAM, char **argv)
G.root_major = major(st.st_dev);
G.root_minor = minor(st.st_dev);
+ putenv((char*)"ACTION=add");
+
/* ACTION_FOLLOWLINKS is needed since in newer kernels
* /sys/block/loop* (for example) are symlinks to dirs,
* not real directories.
@@ -781,66 +1088,65 @@ int mdev_main(int argc UNUSED_PARAM, char **argv)
char *fw;
char *seq;
char *action;
- char *env_path;
- static const char keywords[] ALIGN1 = "remove\0add\0";
- enum { OP_remove = 0, OP_add };
+ char *env_devname;
+ char *env_devpath;
+ unsigned my_pid;
+ unsigned seqnum = seqnum; /* for compiler */
+ int seq_fd;
smalluint op;
/* Hotplug:
* env ACTION=... DEVPATH=... SUBSYSTEM=... [SEQNUM=...] mdev
- * ACTION can be "add" or "remove"
+ * ACTION can be "add", "remove", "change"
* DEVPATH is like "/block/sda" or "/class/input/mice"
*/
- action = getenv("ACTION");
- env_path = getenv("DEVPATH");
+ env_devname = getenv("DEVNAME"); /* can be NULL */
G.subsystem = getenv("SUBSYSTEM");
- if (!action || !env_path /*|| !G.subsystem*/)
+ action = getenv("ACTION");
+ env_devpath = getenv("DEVPATH");
+ if (!action || !env_devpath /*|| !G.subsystem*/)
bb_show_usage();
fw = getenv("FIRMWARE");
- op = index_in_strings(keywords, action);
- /* If it exists, does /dev/mdev.seq match $SEQNUM?
- * If it does not match, earlier mdev is running
- * in parallel, and we need to wait */
seq = getenv("SEQNUM");
+ op = index_in_strings(keywords, action);
+
+ my_pid = getpid();
+ open_mdev_log(seq, my_pid);
+
+ seq_fd = -1;
if (seq) {
- int timeout = 2000 / 32; /* 2000 msec */
- do {
- int seqlen;
- char seqbuf[sizeof(int)*3 + 2];
-
- seqlen = open_read_close("mdev.seq", seqbuf, sizeof(seqbuf) - 1);
- if (seqlen < 0) {
- seq = NULL;
- break;
- }
- seqbuf[seqlen] = '\0';
- if (seqbuf[0] == '\n' /* seed file? */
- || strcmp(seq, seqbuf) == 0 /* correct idx? */
- ) {
- break;
- }
- usleep(32*1000);
- } while (--timeout);
+ seqnum = atoll(seq);
+ seq_fd = wait_for_seqfile(seqnum);
}
- snprintf(temp, PATH_MAX, "/sys%s", env_path);
+ dbg1("%s "
+ "ACTION:%s SUBSYSTEM:%s DEVNAME:%s DEVPATH:%s"
+ "%s%s",
+ curtime(),
+ action, G.subsystem, env_devname, env_devpath,
+ fw ? " FW:" : "", fw ? fw : ""
+ );
+
+ snprintf(temp, PATH_MAX, "/sys%s", env_devpath);
if (op == OP_remove) {
/* Ignoring "remove firmware". It was reported
* to happen and to cause erroneous deletion
* of device nodes. */
if (!fw)
- make_device(temp, /*delete:*/ 1);
+ make_device(env_devname, temp, op);
}
- else if (op == OP_add) {
- make_device(temp, /*delete:*/ 0);
+ else {
+ make_device(env_devname, temp, op);
if (ENABLE_FEATURE_MDEV_LOAD_FIRMWARE) {
- if (fw)
+ if (op == OP_add && fw)
load_firmware(fw, temp);
}
}
- if (seq) {
- xopen_xwrite_close("mdev.seq", utoa(xatou(seq) + 1));
+ dbg1("%s exiting", curtime());
+ if (seq_fd >= 0) {
+ xwrite_str(seq_fd, utoa(seqnum + 1));
+ signal_mdevs(my_pid);
}
}
diff --git a/release/src/router/busybox/util-linux/minix.h b/release/src/router/busybox/util-linux/minix.h
index e0fbcf7612..83ffe6da57 100644
--- a/release/src/router/busybox/util-linux/minix.h
+++ b/release/src/router/busybox/util-linux/minix.h
@@ -61,9 +61,14 @@ enum {
MINIX_ROOT_INO = 1,
MINIX_BAD_INO = 2,
+#undef MINIX1_SUPER_MAGIC
MINIX1_SUPER_MAGIC = 0x137F, /* original minix fs */
+#undef MINIX1_SUPER_MAGIC2
MINIX1_SUPER_MAGIC2 = 0x138F, /* minix fs, 30 char names */
+/* bionic has this define */
+#undef MINIX2_SUPER_MAGIC
MINIX2_SUPER_MAGIC = 0x2468, /* minix V2 fs */
+#undef MINIX2_SUPER_MAGIC2
MINIX2_SUPER_MAGIC2 = 0x2478, /* minix V2 fs, 30 char names */
MINIX_VALID_FS = 0x0001, /* clean fs */
MINIX_ERROR_FS = 0x0002, /* fs has errors */
diff --git a/release/src/router/busybox/util-linux/mkfs_ext2.c b/release/src/router/busybox/util-linux/mkfs_ext2.c
index f8c4630803..f91a0b4bf3 100644
--- a/release/src/router/busybox/util-linux/mkfs_ext2.c
+++ b/release/src/router/busybox/util-linux/mkfs_ext2.c
@@ -8,7 +8,7 @@
* Licensed under GPLv2, see file LICENSE in this source tree.
*/
-//usage:#define mkfs_ext2_trivial_usage_NO
+//usage:#define mkfs_ext2_trivial_usage
//usage: "[-Fn] "
/* //usage: "[-c|-l filename] " */
//usage: "[-b BLK_SIZE] "
@@ -21,7 +21,7 @@
//usage: "[-L LABEL] "
/* //usage: "[-M last-mounted-directory] [-S] [-T filesystem-type] " */
//usage: "BLOCKDEV [KBYTES]"
-//usage:#define mkfs_ext2_full_usage_NO "\n\n"
+//usage:#define mkfs_ext2_full_usage "\n\n"
//usage: " -b BLK_SIZE Block size, bytes"
/* //usage: "\n -c Check device for bad blocks" */
/* //usage: "\n -E opts Set extended options" */
@@ -116,7 +116,7 @@ static void allocate(uint8_t *bitmap, uint32_t blocksize, uint32_t start, uint32
{
uint32_t i;
-//bb_info_msg("ALLOC: [%u][%u][%u]: [%u-%u]:=[%x],[%x]", blocksize, start, end, start/8, blocksize - end/8 - 1, (1 << (start & 7)) - 1, (uint8_t)(0xFF00 >> (end & 7)));
+//bb_error_msg("ALLOC: [%u][%u][%u]: [%u-%u]:=[%x],[%x]", blocksize, start, end, start/8, blocksize - end/8 - 1, (1 << (start & 7)) - 1, (uint8_t)(0xFF00 >> (end & 7)));
memset(bitmap, 0, blocksize);
i = start / 8;
memset(bitmap, 0xFF, i);
@@ -151,7 +151,7 @@ static uint32_t has_super(uint32_t x)
static void PUT(uint64_t off, void *buf, uint32_t size)
{
-// bb_info_msg("PUT[%llu]:[%u]", off, size);
+ //bb_error_msg("PUT[%llu]:[%u]", off, size);
xlseek(fd, off, SEEK_SET);
xwrite(fd, buf, size);
}
@@ -412,7 +412,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
// (a bit after 8M image size), but it works for two->three groups
// transition (at 16M).
if (remainder && (remainder < overhead + 50)) {
-//bb_info_msg("CHOP[%u]", remainder);
+//bb_error_msg("CHOP[%u]", remainder);
nblocks -= remainder;
goto retry;
}
@@ -568,7 +568,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
free_blocks = (n < blocks_per_group ? n : blocks_per_group) - overhead;
// mark preallocated blocks as allocated
-//bb_info_msg("ALLOC: [%u][%u][%u]", blocksize, overhead, blocks_per_group - (free_blocks + overhead));
+//bb_error_msg("ALLOC: [%u][%u][%u]", blocksize, overhead, blocks_per_group - (free_blocks + overhead));
allocate(buf, blocksize,
// reserve "overhead" blocks
overhead,
@@ -647,7 +647,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
n = FETCH_LE32(inode->i_block[0]) + 1;
for (i = 0; i < lost_and_found_blocks; ++i)
STORE_LE(inode->i_block[i], i + n); // use next block
-//bb_info_msg("LAST BLOCK USED[%u]", i + n);
+//bb_error_msg("LAST BLOCK USED[%u]", i + n);
PUT(((uint64_t)FETCH_LE32(gd[0].bg_inode_table) * blocksize) + (EXT2_GOOD_OLD_FIRST_INO-1) * inodesize,
buf, inodesize);
diff --git a/release/src/router/busybox/util-linux/mkfs_minix.c b/release/src/router/busybox/util-linux/mkfs_minix.c
index 59d7d23d40..88d797584c 100644
--- a/release/src/router/busybox/util-linux/mkfs_minix.c
+++ b/release/src/router/busybox/util-linux/mkfs_minix.c
@@ -196,54 +196,6 @@ static void minix_clrbit(char *a, unsigned i)
# define BLKGETSIZE _IO(0x12,96) /* return device size */
#endif
-
-static long valid_offset(int fd, int offset)
-{
- char ch;
-
- if (lseek(fd, offset, SEEK_SET) < 0)
- return 0;
- if (read(fd, &ch, 1) < 1)
- return 0;
- return 1;
-}
-
-static int count_blocks(int fd)
-{
- int high, low;
-
- low = 0;
- for (high = 1; valid_offset(fd, high); high *= 2)
- low = high;
-
- while (low < high - 1) {
- const int mid = (low + high) / 2;
-
- if (valid_offset(fd, mid))
- low = mid;
- else
- high = mid;
- }
- valid_offset(fd, 0);
- return (low + 1);
-}
-
-static int get_size(const char *file)
-{
- int fd;
- long size;
-
- fd = xopen(file, O_RDWR);
- if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
- close(fd);
- return (size * 512);
- }
-
- size = count_blocks(fd);
- close(fd);
- return size;
-}
-
static void write_tables(void)
{
/* Mark the superblock valid. */
@@ -553,7 +505,7 @@ static void get_list_blocks(char *filename)
listfile = xfopen_for_read(filename);
while (!feof(listfile)) {
- fscanf(listfile, "%ld\n", &blockno);
+ fscanf(listfile, "%lu\n", &blockno);
mark_zone(blockno);
G.badblocks++;
}
@@ -624,11 +576,11 @@ static void setup_tables(void)
for (i = MINIX_ROOT_INO; i <= SB_INODES; i++)
unmark_inode(i);
G.inode_buffer = xzalloc(INODE_BUFFER_SIZE);
- printf("%ld inodes\n", (long)SB_INODES);
- printf("%ld blocks\n", (long)SB_ZONES);
- printf("Firstdatazone=%ld (%ld)\n", (long)SB_FIRSTZONE, (long)norm_firstzone);
- printf("Zonesize=%d\n", BLOCK_SIZE << SB_ZONE_SIZE);
- printf("Maxsize=%ld\n", (long)SB_MAXSIZE);
+ printf("%lu inodes\n", (unsigned long)SB_INODES);
+ printf("%lu blocks\n", (unsigned long)SB_ZONES);
+ printf("Firstdatazone=%lu (%lu)\n", (unsigned long)SB_FIRSTZONE, (unsigned long)norm_firstzone);
+ printf("Zonesize=%u\n", BLOCK_SIZE << SB_ZONE_SIZE);
+ printf("Maxsize=%lu\n", (unsigned long)SB_MAXSIZE);
}
int mkfs_minix_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -636,7 +588,6 @@ int mkfs_minix_main(int argc UNUSED_PARAM, char **argv)
{
unsigned opt;
char *tmp;
- struct stat statbuf;
char *str_i;
char *listfile = NULL;
@@ -673,13 +624,17 @@ int mkfs_minix_main(int argc UNUSED_PARAM, char **argv)
#endif
}
- G.device_name = *argv++;
+ G.device_name = argv[0];
if (!G.device_name)
bb_show_usage();
- if (*argv)
- G.total_blocks = xatou32(*argv);
- else
- G.total_blocks = get_size(G.device_name) / 1024;
+
+ /* Check if it is mounted */
+ if (find_mount_point(G.device_name, 0))
+ bb_error_msg_and_die("can't format mounted filesystem");
+
+ xmove_fd(xopen(G.device_name, O_RDWR), dev_fd);
+
+ G.total_blocks = get_volume_size_in_bytes(dev_fd, argv[1], 1024, /*extend:*/ 1) / 1024;
if (G.total_blocks < 10)
bb_error_msg_and_die("must have at least 10 blocks");
@@ -690,25 +645,21 @@ int mkfs_minix_main(int argc UNUSED_PARAM, char **argv)
G.magic = MINIX2_SUPER_MAGIC;
} else if (G.total_blocks > 65535)
G.total_blocks = 65535;
-
- /* Check if it is mounted */
- if (find_mount_point(G.device_name, 0))
- bb_error_msg_and_die("can't format mounted filesystem");
-
- xmove_fd(xopen(G.device_name, O_RDWR), dev_fd);
+#if 0
+ struct stat statbuf;
xfstat(dev_fd, &statbuf, G.device_name);
+/* why? */
if (!S_ISBLK(statbuf.st_mode))
opt &= ~1; // clear -c (check)
-
+#if 0
/* I don't know why someone has special code to prevent mkfs.minix
* on IDE devices. Why IDE but not SCSI, etc?... */
-#if 0
else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
/* what is this? */
bb_error_msg_and_die("will not try "
"to make filesystem on '%s'", G.device_name);
#endif
-
+#endif
tmp = G.root_block;
*(short *) tmp = 1;
strcpy(tmp + 2, ".");
diff --git a/release/src/router/busybox/util-linux/mkfs_reiser.c b/release/src/router/busybox/util-linux/mkfs_reiser.c
index b4efb9e9f4..56c8f0ab52 100644
--- a/release/src/router/busybox/util-linux/mkfs_reiser.c
+++ b/release/src/router/busybox/util-linux/mkfs_reiser.c
@@ -66,7 +66,7 @@ struct reiserfs_super_block {
char s_magic[10]; /* 52 "ReIsErFs" or "ReIsEr2Fs" or "ReIsEr3Fs" */
uint16_t sb_fs_state; /* 62 it is set to used by fsck to mark which phase of rebuilding is done (used for fsck debugging) */
- uint32_t sb_hash_function_code; /* 64 code of fuction which was/is/will be used to sort names in a directory. See codes in above */
+ uint32_t sb_hash_function_code; /* 64 code of function which was/is/will be used to sort names in a directory. See codes in above */
uint16_t sb_tree_height; /* 68 height of filesytem tree. Tree consisting of only one root block has 2 here */
uint16_t sb_bmap_nr; /* 70 amount of bitmap blocks needed to address each block of file system */
uint16_t sb_version; /* 72 this field is only reliable on filesystem with non-standard journal */
@@ -224,8 +224,8 @@ int mkfs_reiser_main(int argc UNUSED_PARAM, char **argv)
jp = &sb->sb_journal;
STORE_LE(jp->jp_journal_1st_block, REISERFS_DISK_OFFSET_IN_BYTES / blocksize + 1/*sb*/ + 1/*bmp#0*/);
timestamp = time(NULL);
- srandom(timestamp);
- STORE_LE(jp->jp_journal_magic, random());
+ srand(timestamp);
+ STORE_LE(jp->jp_journal_magic, rand());
STORE_LE(jp->jp_journal_size, journal_blocks);
STORE_LE(jp->jp_journal_trans_max, JOURNAL_TRANS_MAX);
STORE_LE(jp->jp_journal_max_batch, JOURNAL_MAX_BATCH);
diff --git a/release/src/router/busybox/util-linux/mkfs_vfat.c b/release/src/router/busybox/util-linux/mkfs_vfat.c
index 7d81ed06d8..d53c751eba 100644
--- a/release/src/router/busybox/util-linux/mkfs_vfat.c
+++ b/release/src/router/busybox/util-linux/mkfs_vfat.c
@@ -578,7 +578,7 @@ int mkfs_vfat_main(int argc UNUSED_PARAM, char **argv)
start_data_sector = (reserved_sect + NUM_FATS * sect_per_fat) * (bytes_per_sect / SECTOR_SIZE);
start_data_block = (start_data_sector + SECTORS_PER_BLOCK - 1) / SECTORS_PER_BLOCK;
- bb_info_msg("searching for bad blocks ");
+ bb_error_msg("searching for bad blocks");
currently_testing = 0;
try = TEST_BUFFER_BLOCKS;
while (currently_testing < volume_size_blocks) {
@@ -616,7 +616,7 @@ int mkfs_vfat_main(int argc UNUSED_PARAM, char **argv)
}
free(blkbuf);
if (badblocks)
- bb_info_msg("%d bad block(s)", badblocks);
+ bb_error_msg("%d bad block(s)", badblocks);
}
#endif
diff --git a/release/src/router/busybox/util-linux/mkswap.c b/release/src/router/busybox/util-linux/mkswap.c
index 68bdff9467..dcb53f0087 100644
--- a/release/src/router/busybox/util-linux/mkswap.c
+++ b/release/src/router/busybox/util-linux/mkswap.c
@@ -13,6 +13,7 @@
//usage: "\n -L LBL Label"
#include "libbb.h"
+#include "common_bufsiz.h"
#if ENABLE_SELINUX
static void mkswap_selinux_setcontext(int fd, const char *path)
@@ -66,7 +67,7 @@ struct swap_header_v1 {
uint32_t version; /* second kbyte, word 0 */
uint32_t last_page; /* 1 */
uint32_t nr_badpages; /* 2 */
- uint8_t sws_uuid[16]; /* 3,4,5,6 */
+ char sws_uuid[16]; /* 3,4,5,6 */
char sws_volume[16]; /* 7,8,9,10 */
uint32_t padding[117]; /* 11..127 */
uint32_t badpages[1]; /* 128 */
@@ -75,6 +76,7 @@ struct swap_header_v1 {
#define NWORDS 129
#define hdr ((struct swap_header_v1*)bb_common_bufsiz1)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
struct BUG_sizes {
char swap_header_v1_wrong[sizeof(*hdr) != (NWORDS * 4) ? -1 : 1];
@@ -92,6 +94,8 @@ int mkswap_main(int argc UNUSED_PARAM, char **argv)
off_t len;
const char *label = "";
+ INIT_G();
+
opt_complementary = "-1"; /* at least one param */
/* TODO: -p PAGESZ, -U UUID */
getopt32(argv, "L:", &label);
@@ -121,9 +125,17 @@ int mkswap_main(int argc UNUSED_PARAM, char **argv)
hdr->last_page = (uoff_t)len / pagesize;
if (ENABLE_FEATURE_MKSWAP_UUID) {
- char uuid_string[37];
+ char uuid_string[32];
generate_uuid((void*)hdr->sws_uuid);
- printf("UUID=%s\n", unparse_uuid(hdr->sws_uuid, uuid_string));
+ bin2hex(uuid_string, hdr->sws_uuid, 16);
+ /* f.e. UUID=dfd9c173-be52-4d27-99a5-c34c6c2ff55f */
+ printf("UUID=%.8s" "-%.4s-%.4s-%.4s-%.12s\n",
+ uuid_string,
+ uuid_string+8,
+ uuid_string+8+4,
+ uuid_string+8+4+4,
+ uuid_string+8+4+4+4
+ );
}
safe_strncpy(hdr->sws_volume, label, 16);
diff --git a/release/src/router/busybox/util-linux/more.c b/release/src/router/busybox/util-linux/more.c
index 3595713971..95cbdd994b 100644
--- a/release/src/router/busybox/util-linux/more.c
+++ b/release/src/router/busybox/util-linux/more.c
@@ -23,6 +23,7 @@
//usage: "$ dmesg | more\n"
#include "libbb.h"
+#include "common_bufsiz.h"
/* Support for FEATURE_USE_TERMIOS */
@@ -32,10 +33,10 @@ struct globals {
struct termios new_settings;
} FIX_ALIASING;
#define G (*(struct globals*)bb_common_bufsiz1)
-#define INIT_G() ((void)0)
#define initial_settings (G.initial_settings)
#define new_settings (G.new_settings )
#define cin_fileno (G.cin_fileno )
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
#define setTermSettings(fd, argp) \
do { \
diff --git a/release/src/router/busybox/util-linux/mount.c b/release/src/router/busybox/util-linux/mount.c
index f1da30facc..cef4f74159 100644
--- a/release/src/router/busybox/util-linux/mount.c
+++ b/release/src/router/busybox/util-linux/mount.c
@@ -17,8 +17,103 @@
// mount_it_now() does the actual mount.
//
+//config:config MOUNT
+//config: bool "mount"
+//config: default y
+//config: select PLATFORM_LINUX
+//config: help
+//config: All files and filesystems in Unix are arranged into one big directory
+//config: tree. The 'mount' utility is used to graft a filesystem onto a
+//config: particular part of the tree. A filesystem can either live on a block
+//config: device, or it can be accessible over the network, as is the case with
+//config: NFS filesystems. Most people using BusyBox will also want to enable
+//config: the 'mount' utility.
+//config:
+//config:config FEATURE_MOUNT_FAKE
+//config: bool "Support option -f"
+//config: default y
+//config: depends on MOUNT
+//config: help
+//config: Enable support for faking a file system mount.
+//config:
+//config:config FEATURE_MOUNT_VERBOSE
+//config: bool "Support option -v"
+//config: default y
+//config: depends on MOUNT
+//config: help
+//config: Enable multi-level -v[vv...] verbose messages. Useful if you
+//config: debug mount problems and want to see what is exactly passed
+//config: to the kernel.
+//config:
+//config:config FEATURE_MOUNT_HELPERS
+//config: bool "Support mount helpers"
+//config: default n
+//config: depends on MOUNT
+//config: help
+//config: Enable mounting of virtual file systems via external helpers.
+//config: E.g. "mount obexfs#-b00.11.22.33.44.55 /mnt" will in effect call
+//config: "obexfs -b00.11.22.33.44.55 /mnt"
+//config: Also "mount -t sometype [-o opts] fs /mnt" will try
+//config: "sometype [-o opts] fs /mnt" if simple mount syscall fails.
+//config: The idea is to use such virtual filesystems in /etc/fstab.
+//config:
+//config:config FEATURE_MOUNT_LABEL
+//config: bool "Support specifying devices by label or UUID"
+//config: default y
+//config: depends on MOUNT
+//config: select VOLUMEID
+//config: help
+//config: This allows for specifying a device by label or uuid, rather than by
+//config: name. This feature utilizes the same functionality as blkid/findfs.
+//config: This also enables label or uuid support for swapon.
+//config:
+//config:config FEATURE_MOUNT_NFS
+//config: bool "Support mounting NFS file systems on Linux < 2.6.23"
+//config: default n
+//config: depends on MOUNT
+//config: select FEATURE_HAVE_RPC
+//config: select FEATURE_SYSLOG
+//config: help
+//config: Enable mounting of NFS file systems on Linux kernels prior
+//config: to version 2.6.23. Note that in this case mounting of NFS
+//config: over IPv6 will not be possible.
+//config:
+//config: Note that this option links in RPC support from libc,
+//config: which is rather large (~10 kbytes on uclibc).
+//config:
+//config:config FEATURE_MOUNT_CIFS
+//config: bool "Support mounting CIFS/SMB file systems"
+//config: default y
+//config: depends on MOUNT
+//config: help
+//config: Enable support for samba mounts.
+//config:
+//config:config FEATURE_MOUNT_FLAGS
+//config: depends on MOUNT
+//config: bool "Support lots of -o flags in mount"
+//config: default y
+//config: help
+//config: Without this, mount only supports ro/rw/remount. With this, it
+//config: supports nosuid, suid, dev, nodev, exec, noexec, sync, async, atime,
+//config: noatime, diratime, nodiratime, loud, bind, move, shared, slave,
+//config: private, unbindable, rshared, rslave, rprivate, and runbindable.
+//config:
+//config:config FEATURE_MOUNT_FSTAB
+//config: depends on MOUNT
+//config: bool "Support /etc/fstab and -a"
+//config: default y
+//config: help
+//config: Support mount all and looking for files in /etc/fstab.
+//config:
+//config:config FEATURE_MOUNT_OTHERTAB
+//config: depends on FEATURE_MOUNT_FSTAB
+//config: bool "Support -T <alt_fstab>"
+//config: default y
+//config: help
+//config: Support mount -T (specifying an alternate fstab)
+
//usage:#define mount_trivial_usage
-//usage: "[OPTIONS] [-o OPTS] DEVICE NODE"
+//usage: "[OPTIONS] [-o OPT] DEVICE NODE"
//usage:#define mount_full_usage "\n\n"
//usage: "Mount a filesystem. Filesystem autodetection requires /proc.\n"
//usage: "\n -a Mount all filesystems in fstab"
@@ -36,9 +131,16 @@
//usage: IF_FEATURE_MTAB_SUPPORT(
//usage: "\n -n Don't update /etc/mtab"
//usage: )
+//usage: IF_FEATURE_MOUNT_VERBOSE(
+//usage: "\n -v Verbose"
+//usage: )
+////usage: "\n -s Sloppy (ignored)"
//usage: "\n -r Read-only mount"
-//usage: "\n -w Read-write mount (default)"
+////usage: "\n -w Read-write mount (default)"
//usage: "\n -t FSTYPE[,...] Filesystem type(s)"
+//usage: IF_FEATURE_MOUNT_OTHERTAB(
+//usage: "\n -T FILE Read FILE instead of /etc/fstab"
+//usage: )
//usage: "\n -O OPT Mount only filesystems with option OPT (-a only)"
//usage: "\n-o OPT:"
//usage: IF_FEATURE_MOUNT_LOOP(
@@ -60,7 +162,7 @@
//usage: "\n move Relocate an existing mount point"
//usage: )
//usage: "\n remount Remount a mounted filesystem, changing flags"
-//usage: "\n ro/rw Same as -r/-w"
+//usage: "\n ro Same as -r"
//usage: "\n"
//usage: "\nThere are filesystem-specific -o flags."
//usage:
@@ -113,8 +215,15 @@
#ifndef MS_RELATIME
# define MS_RELATIME (1 << 21)
#endif
+#ifndef MS_STRICTATIME
+# define MS_STRICTATIME (1 << 24)
+#endif
+
+/* Any ~MS_FOO value has this bit set: */
+#define BB_MS_INVERTED_VALUE (1u << 31)
#include "libbb.h"
+#include "common_bufsiz.h"
#if ENABLE_FEATURE_MOUNT_LABEL
# include "volume_id.h"
#else
@@ -151,13 +260,15 @@ static struct mntent *getmntent_r(FILE* stream, struct mntent* result,
// Not real flags, but we want to be able to check for this.
enum {
- MOUNT_USERS = (1 << 28) * ENABLE_DESKTOP,
+ MOUNT_USERS = (1 << 27) * ENABLE_DESKTOP,
+ MOUNT_NOFAIL = (1 << 28) * ENABLE_DESKTOP,
MOUNT_NOAUTO = (1 << 29),
MOUNT_SWAP = (1 << 30),
+ MOUNT_FAKEFLAGS = MOUNT_USERS | MOUNT_NOFAIL | MOUNT_NOAUTO | MOUNT_SWAP
};
-#define OPTION_STR "o:t:rwanfvsiO:"
+#define OPTION_STR "o:t:rwanfvsiO:" IF_FEATURE_MOUNT_OTHERTAB("T:")
enum {
OPT_o = (1 << 0),
OPT_t = (1 << 1),
@@ -170,6 +281,7 @@ enum {
OPT_s = (1 << 8),
OPT_i = (1 << 9),
OPT_O = (1 << 10),
+ OPT_T = (1 << 11),
};
#if ENABLE_FEATURE_MTAB_SUPPORT
@@ -217,7 +329,9 @@ static const int32_t mount_options[] = {
/* "swap" */ MOUNT_SWAP,
IF_DESKTOP(/* "user" */ MOUNT_USERS,)
IF_DESKTOP(/* "users" */ MOUNT_USERS,)
+ IF_DESKTOP(/* "nofail" */ MOUNT_NOFAIL,)
/* "_netdev" */ 0,
+ IF_DESKTOP(/* "comment=" */ 0,) /* systemd uses this in fstab */
)
IF_FEATURE_MOUNT_FLAGS(
@@ -239,6 +353,7 @@ static const int32_t mount_options[] = {
/* "nomand" */ ~MS_MANDLOCK,
/* "relatime" */ MS_RELATIME,
/* "norelatime" */ ~MS_RELATIME,
+ /* "strictatime" */ MS_STRICTATIME,
/* "loud" */ ~MS_SILENT,
/* "rbind" */ MS_BIND|MS_RECURSIVE,
@@ -262,7 +377,7 @@ static const int32_t mount_options[] = {
/* "remount" */ MS_REMOUNT // action flag
};
-static const char mount_option_str[] =
+static const char mount_option_str[] ALIGN1 =
IF_FEATURE_MOUNT_LOOP(
"loop\0"
)
@@ -274,7 +389,9 @@ static const char mount_option_str[] =
"swap\0"
IF_DESKTOP("user\0")
IF_DESKTOP("users\0")
+ IF_DESKTOP("nofail\0")
"_netdev\0"
+ IF_DESKTOP("comment=\0") /* systemd uses this in fstab */
)
IF_FEATURE_MOUNT_FLAGS(
// vfs flags
@@ -295,6 +412,7 @@ static const char mount_option_str[] =
"nomand\0"
"relatime\0"
"norelatime\0"
+ "strictatime\0"
"loud\0"
"rbind\0"
@@ -330,7 +448,7 @@ struct globals {
char getmntent_buf[1];
} FIX_ALIASING;
enum { GETMNTENT_BUFSIZE = COMMON_BUFSIZE - offsetof(struct globals, getmntent_buf) };
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define nfs_mount_version (G.nfs_mount_version)
#if ENABLE_FEATURE_MOUNT_VERBOSE
#define verbose (G.verbose )
@@ -339,7 +457,7 @@ enum { GETMNTENT_BUFSIZE = COMMON_BUFSIZE - offsetof(struct globals, getmntent_b
#endif
#define fslist (G.fslist )
#define getmntent_buf (G.getmntent_buf )
-#define INIT_G() do { } while (0)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
#if ENABLE_FEATURE_MTAB_SUPPORT
/*
@@ -450,9 +568,9 @@ static void append_mount_options(char **oldopts, const char *newopts)
// Use the mount_options list to parse options into flags.
// Also update list of unrecognized options if unrecognized != NULL
-static long parse_mount_options(char *options, char **unrecognized)
+static unsigned long parse_mount_options(char *options, char **unrecognized)
{
- long flags = MS_SILENT;
+ unsigned long flags = MS_SILENT;
// Loop through options
for (;;) {
@@ -465,15 +583,22 @@ static long parse_mount_options(char *options, char **unrecognized)
// FIXME: use hasmntopt()
// Find this option in mount_options
for (i = 0; i < ARRAY_SIZE(mount_options); i++) {
- if (strcasecmp(option_str, options) == 0) {
- long fl = mount_options[i];
- if (fl < 0)
+ unsigned opt_len = strlen(option_str);
+
+ if (strncasecmp(option_str, options, opt_len) == 0
+ && (options[opt_len] == '\0'
+ /* or is it "comment=" thingy in fstab? */
+ IF_FEATURE_MOUNT_FSTAB(IF_DESKTOP( || option_str[opt_len-1] == '=' ))
+ )
+ ) {
+ unsigned long fl = mount_options[i];
+ if (fl & BB_MS_INVERTED_VALUE)
flags &= fl;
else
flags |= fl;
goto found;
}
- option_str += strlen(option_str) + 1;
+ option_str += opt_len + 1;
}
// We did not recognize this option.
// If "unrecognized" is not NULL, append option there.
@@ -521,7 +646,7 @@ static llist_t *get_block_backed_filesystems(void)
if (!f) continue;
while ((buf = xmalloc_fgetline(f)) != NULL) {
- if (strncmp(buf, "nodev", 5) == 0 && isspace(buf[5]))
+ if (is_prefixed_with(buf, "nodev") && isspace(buf[5]))
goto next;
fs = skip_whitespace(buf);
if (*fs == '#' || *fs == '*' || !*fs)
@@ -548,10 +673,12 @@ void delete_block_backed_filesystems(void);
// Perform actual mount of specific filesystem at specific location.
// NB: mp->xxx fields may be trashed on exit
-static int mount_it_now(struct mntent *mp, long vfsflags, char *filteropts)
+static int mount_it_now(struct mntent *mp, unsigned long vfsflags, char *filteropts)
{
int rc = 0;
+ vfsflags &= ~(unsigned long)MOUNT_FAKEFLAGS;
+
if (FAKE_IT) {
if (verbose >= 2)
bb_error_msg("would do mount('%s','%s','%s',0x%08lx,'%s')",
@@ -876,7 +1003,7 @@ enum {
# define EDQUOT ENOSPC
#endif
/* Convert each NFSERR_BLAH into EBLAH */
-static const uint8_t nfs_err_stat[] = {
+static const uint8_t nfs_err_stat[] ALIGN1 = {
1, 2, 5, 6, 13, 17,
19, 20, 21, 22, 27, 28,
30, 63, 66, 69, 70, 71
@@ -889,7 +1016,7 @@ typedef uint8_t nfs_err_type;
#else
typedef uint16_t nfs_err_type;
#endif
-static const nfs_err_type nfs_err_errnum[] = {
+static const nfs_err_type nfs_err_errnum[] ALIGN2 = {
EPERM , ENOENT , EIO , ENXIO , EACCES, EEXIST,
ENODEV, ENOTDIR , EISDIR , EINVAL, EFBIG , ENOSPC,
EROFS , ENAMETOOLONG, ENOTEMPTY, EDQUOT, ESTALE, EREMOTE
@@ -913,7 +1040,7 @@ static bool_t xdr_fhandle(XDR *xdrs, fhandle objp)
static bool_t xdr_fhstatus(XDR *xdrs, fhstatus *objp)
{
if (!xdr_u_int(xdrs, &objp->fhs_status))
- return FALSE;
+ return FALSE;
if (objp->fhs_status == 0)
return xdr_fhandle(xdrs, objp->fhstatus_u.fhs_fhandle);
return TRUE;
@@ -927,8 +1054,8 @@ static bool_t xdr_dirpath(XDR *xdrs, dirpath *objp)
static bool_t xdr_fhandle3(XDR *xdrs, fhandle3 *objp)
{
return xdr_bytes(xdrs, (char **)&objp->fhandle3_val,
- (unsigned int *) &objp->fhandle3_len,
- FHSIZE3);
+ (unsigned int *) &objp->fhandle3_len,
+ FHSIZE3);
}
static bool_t xdr_mountres3_ok(XDR *xdrs, mountres3_ok *objp)
@@ -936,10 +1063,10 @@ static bool_t xdr_mountres3_ok(XDR *xdrs, mountres3_ok *objp)
if (!xdr_fhandle3(xdrs, &objp->fhandle))
return FALSE;
return xdr_array(xdrs, &(objp->auth_flavours.auth_flavours_val),
- &(objp->auth_flavours.auth_flavours_len),
- ~0,
- sizeof(int),
- (xdrproc_t) xdr_int);
+ &(objp->auth_flavours.auth_flavours_len),
+ ~0,
+ sizeof(int),
+ (xdrproc_t) xdr_int);
}
static bool_t xdr_mountstat3(XDR *xdrs, mountstat3 *objp)
@@ -1080,7 +1207,7 @@ static void error_msg_rpc(const char *msg)
}
/* NB: mp->xxx fields may be trashed on exit */
-static NOINLINE int nfsmount(struct mntent *mp, long vfsflags, char *filteropts)
+static NOINLINE int nfsmount(struct mntent *mp, unsigned long vfsflags, char *filteropts)
{
CLIENT *mclient;
char *hostname;
@@ -1244,9 +1371,9 @@ static NOINLINE int nfsmount(struct mntent *mp, long vfsflags, char *filteropts)
strcspn(opteq, " \t\n\r,"));
continue;
case 18: // "proto"
- if (!strncmp(opteq, "tcp", 3))
+ if (is_prefixed_with(opteq, "tcp"))
tcp = 1;
- else if (!strncmp(opteq, "udp", 3))
+ else if (is_prefixed_with(opteq, "udp"))
tcp = 0;
else
bb_error_msg("warning: unrecognized proto= option");
@@ -1339,7 +1466,7 @@ static NOINLINE int nfsmount(struct mntent *mp, long vfsflags, char *filteropts)
"rdirplus\0"
"acl\0";
int val = 1;
- if (!strncmp(opt, "no", 2)) {
+ if (is_prefixed_with(opt, "no")) {
val = 0;
opt += 2;
}
@@ -1508,19 +1635,19 @@ static NOINLINE int nfsmount(struct mntent *mp, long vfsflags, char *filteropts)
switch (pm_mnt.pm_prot) {
case IPPROTO_UDP:
mclient = clntudp_create(&mount_server_addr,
- pm_mnt.pm_prog,
- pm_mnt.pm_vers,
- retry_timeout,
- &msock);
+ pm_mnt.pm_prog,
+ pm_mnt.pm_vers,
+ retry_timeout,
+ &msock);
if (mclient)
break;
mount_server_addr.sin_port = htons(pm_mnt.pm_port);
msock = RPC_ANYSOCK;
case IPPROTO_TCP:
mclient = clnttcp_create(&mount_server_addr,
- pm_mnt.pm_prog,
- pm_mnt.pm_vers,
- &msock, 0, 0);
+ pm_mnt.pm_prog,
+ pm_mnt.pm_vers,
+ &msock, 0, 0);
break;
default:
mclient = NULL;
@@ -1541,18 +1668,18 @@ static NOINLINE int nfsmount(struct mntent *mp, long vfsflags, char *filteropts)
if (pm_mnt.pm_vers == 3)
clnt_stat = clnt_call(mclient, MOUNTPROC3_MNT,
- (xdrproc_t) xdr_dirpath,
- (caddr_t) &pathname,
- (xdrproc_t) xdr_mountres3,
- (caddr_t) &status,
- total_timeout);
+ (xdrproc_t) xdr_dirpath,
+ (caddr_t) &pathname,
+ (xdrproc_t) xdr_mountres3,
+ (caddr_t) &status,
+ total_timeout);
else
clnt_stat = clnt_call(mclient, MOUNTPROC_MNT,
- (xdrproc_t) xdr_dirpath,
- (caddr_t) &pathname,
- (xdrproc_t) xdr_fhstatus,
- (caddr_t) &status,
- total_timeout);
+ (xdrproc_t) xdr_dirpath,
+ (caddr_t) &pathname,
+ (xdrproc_t) xdr_fhstatus,
+ (caddr_t) &status,
+ total_timeout);
if (clnt_stat == RPC_SUCCESS)
goto prepare_kernel_data; /* we're done */
@@ -1711,7 +1838,7 @@ static NOINLINE int nfsmount(struct mntent *mp, long vfsflags, char *filteropts)
* For older kernels, you must build busybox with ENABLE_FEATURE_MOUNT_NFS.
* (However, note that then you lose any chances that NFS over IPv6 would work).
*/
-static int nfsmount(struct mntent *mp, long vfsflags, char *filteropts)
+static int nfsmount(struct mntent *mp, unsigned long vfsflags, char *filteropts)
{
len_and_sockaddr *lsa;
char *opts;
@@ -1753,7 +1880,7 @@ static int nfsmount(struct mntent *mp, long vfsflags, char *filteropts)
static int singlemount(struct mntent *mp, int ignore_busy)
{
int rc = -1;
- long vfsflags;
+ unsigned long vfsflags;
char *loopFile = NULL, *filteropts = NULL;
llist_t *fl = NULL;
struct stat st;
@@ -1803,17 +1930,44 @@ static int singlemount(struct mntent *mp, int ignore_busy)
) {
int len;
char c;
+ char *hostname, *share;
+ char *dotted, *ip;
len_and_sockaddr *lsa;
- char *hostname, *dotted, *ip;
+
+ // Parse mp->mnt_fsname of the form "//hostname/share[/dir1/dir2]"
hostname = mp->mnt_fsname + 2;
len = strcspn(hostname, "/\\");
- if (len == 0 || hostname[len] == '\0')
+ share = hostname + len + 1;
+ if (len == 0 // 3rd char is a [back]slash (IOW: empty hostname)
+ || share[-1] == '\0' // no [back]slash after hostname
+ || share[0] == '\0' // empty share name
+ ) {
goto report_error;
- c = hostname[len];
- hostname[len] = '\0';
+ }
+ c = share[-1];
+ share[-1] = '\0';
+ len = strcspn(share, "/\\");
+
+ // "unc=\\hostname\share" option is mandatory
+ // after CIFS option parsing was rewritten in Linux 3.4.
+ // Must use backslashes.
+ // If /dir1/dir2 is present, also add "prefixpath=dir1/dir2"
+ {
+ char *unc = xasprintf(
+ share[len] != '\0' /* "/dir1/dir2" exists? */
+ ? "unc=\\\\%s\\%.*s,prefixpath=%s"
+ : "unc=\\\\%s\\%.*s",
+ hostname,
+ len, share,
+ share + len + 1 /* "dir1/dir2" */
+ );
+ parse_mount_options(unc, &filteropts);
+ if (ENABLE_FEATURE_CLEAN_UP) free(unc);
+ }
+
lsa = host2sockaddr(hostname, 0);
- hostname[len] = c;
+ share[-1] = c;
if (!lsa)
goto report_error;
@@ -1825,8 +1979,6 @@ static int singlemount(struct mntent *mp, int ignore_busy)
parse_mount_options(ip, &filteropts);
if (ENABLE_FEATURE_CLEAN_UP) free(ip);
- // "-o mand" is required [why?]
- vfsflags |= MS_MANDLOCK;
mp->mnt_type = (char*)"cifs";
rc = mount_it_now(mp, vfsflags, filteropts);
@@ -1834,7 +1986,7 @@ static int singlemount(struct mntent *mp, int ignore_busy)
}
// Might this be an NFS filesystem?
- if ((!mp->mnt_type || strncmp(mp->mnt_type, "nfs", 3) == 0)
+ if ((!mp->mnt_type || is_prefixed_with(mp->mnt_type, "nfs"))
&& strchr(mp->mnt_fsname, ':') != NULL
) {
if (!mp->mnt_type)
@@ -1854,7 +2006,7 @@ static int singlemount(struct mntent *mp, int ignore_busy)
if (ENABLE_FEATURE_MOUNT_LOOP && S_ISREG(st.st_mode)) {
loopFile = bb_simplify_path(mp->mnt_fsname);
mp->mnt_fsname = NULL; // will receive malloced loop dev name
- if (set_loop(&mp->mnt_fsname, loopFile, 0, /*ro:*/ 0) < 0) {
+ if (set_loop(&mp->mnt_fsname, loopFile, 0, /*ro:*/ (vfsflags & MS_RDONLY)) < 0) {
if (errno == EPERM || errno == EACCES)
bb_error_msg(bb_msg_perm_denied_are_you_root);
else
@@ -1906,7 +2058,7 @@ static int singlemount(struct mntent *mp, int ignore_busy)
del_loop(mp->mnt_fsname);
if (ENABLE_FEATURE_CLEAN_UP) {
free(loopFile);
- free(mp->mnt_fsname);
+ /* No, "rc != 0" needs it: free(mp->mnt_fsname); */
}
}
@@ -1916,6 +2068,8 @@ static int singlemount(struct mntent *mp, int ignore_busy)
if (errno == EBUSY && ignore_busy)
return 0;
+ if (errno == ENOENT && (vfsflags & MOUNT_NOFAIL))
+ return 0;
if (rc != 0)
bb_perror_msg("mounting %s on %s failed", mp->mnt_fsname, mp->mnt_dir);
return rc;
@@ -1988,10 +2142,11 @@ int mount_main(int argc UNUSED_PARAM, char **argv)
char *O_optmatch = NULL;
char *storage_path;
llist_t *lst_o = NULL;
- const char *fstabname;
+ const char *fstabname = "/etc/fstab";
FILE *fstab;
int i, j;
int rc = EXIT_SUCCESS;
+ unsigned long cmdopt_flags;
unsigned opt;
struct mntent mtpair[2], *mtcur = mtpair;
IF_NOT_DESKTOP(const int nonroot = 0;)
@@ -2014,6 +2169,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv)
// Max 2 params; -o is a list, -v is a counter
opt_complementary = "?2o::" IF_FEATURE_MOUNT_VERBOSE("vv");
opt = getopt32(argv, OPTION_STR, &lst_o, &fstype, &O_optmatch
+ IF_FEATURE_MOUNT_OTHERTAB(, &fstabname)
IF_FEATURE_MOUNT_VERBOSE(, &verbose));
while (lst_o) append_mount_options(&cmdopts, llist_pop(&lst_o)); // -o
if (opt & OPT_r) append_mount_options(&cmdopts, "ro"); // -r
@@ -2066,24 +2222,26 @@ int mount_main(int argc UNUSED_PARAM, char **argv)
// Past this point, we are handling either "mount -a [opts]"
// or "mount [opts] single_param"
- i = parse_mount_options(cmdopts, NULL); // FIXME: should be "long", not "int"
- if (nonroot && (i & ~MS_SILENT)) // Non-root users cannot specify flags
+ cmdopt_flags = parse_mount_options(cmdopts, NULL);
+ if (nonroot && (cmdopt_flags & ~MS_SILENT)) // Non-root users cannot specify flags
bb_error_msg_and_die(bb_msg_you_must_be_root);
// If we have a shared subtree flag, don't worry about fstab or mtab.
if (ENABLE_FEATURE_MOUNT_FLAGS
- && (i & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
+ && (cmdopt_flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
) {
// verbose_mount(source, target, type, flags, data)
- rc = verbose_mount("", argv[0], "", i, "");
+ rc = verbose_mount("", argv[0], "", cmdopt_flags, "");
if (rc)
bb_simple_perror_msg_and_die(argv[0]);
return rc;
}
+ // A malicious user could overmount /usr without this.
+ if (ENABLE_FEATURE_MOUNT_OTHERTAB && nonroot)
+ fstabname = "/etc/fstab";
// Open either fstab or mtab
- fstabname = "/etc/fstab";
- if (i & MS_REMOUNT) {
+ if (cmdopt_flags & MS_REMOUNT) {
// WARNING. I am not sure this matches util-linux's
// behavior. It's possible util-linux does not
// take -o opts from mtab (takes only mount source).
@@ -2182,7 +2340,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv)
// End of fstab/mtab is reached.
// Were we looking for something specific?
if (argv[0]) { // yes
- long l;
+ unsigned long l;
// If we didn't find anything, complain
if (!mtcur->mnt_fsname)
diff --git a/release/src/router/busybox/util-linux/nsenter.c b/release/src/router/busybox/util-linux/nsenter.c
new file mode 100644
index 0000000000..6834292dad
--- /dev/null
+++ b/release/src/router/busybox/util-linux/nsenter.c
@@ -0,0 +1,291 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini nsenter implementation for busybox.
+ *
+ * Copyright (C) 2016 by Bartosz Golaszewski <bartekgola@gmail.com>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+//config:config NSENTER
+//config: bool "nsenter"
+//config: default y
+//config: select PLATFORM_LINUX
+//config: help
+//config: Run program with namespaces of other processes.
+//config:
+//config:config FEATURE_NSENTER_LONG_OPTS
+//config: bool "Enable long options"
+//config: default y
+//config: depends on NSENTER && LONG_OPTS
+//config: help
+//config: Support long options for the nsenter applet. This makes
+//config: the busybox implementation more compatible with upstream.
+
+//applet:IF_NSENTER(APPLET(nsenter, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_NSENTER) += nsenter.o
+
+//usage:#define nsenter_trivial_usage
+//usage: "[OPTIONS] [PROG [ARGS]]"
+//usage:#if ENABLE_FEATURE_NSENTER_LONG_OPTS
+//usage:#define nsenter_full_usage "\n"
+//usage: "\n -t, --target=PID Target process to get namespaces from"
+//usage: "\n -m, --mount[=FILE] Enter mount namespace"
+//usage: "\n -u, --uts[=FILE] Enter UTS namespace (hostname etc)"
+//usage: "\n -i, --ipc[=FILE] Enter System V IPC namespace"
+//usage: "\n -n, --net[=FILE] Enter network namespace"
+//usage: "\n -p, --pid[=FILE] Enter pid namespace"
+//usage: "\n -U, --user[=FILE] Enter user namespace"
+//usage: "\n -S, --setuid=UID Set uid in entered namespace"
+//usage: "\n -G, --setgid=GID Set gid in entered namespace"
+//usage: "\n --preserve-credentials Don't touch uids or gids"
+//usage: "\n -r, --root[=DIR] Set root directory"
+//usage: "\n -w, --wd[=DIR] Set working directory"
+//usage: "\n -F, --no-fork Don't fork before exec'ing PROG"
+//usage:#else
+//usage:#define nsenter_full_usage "\n"
+//usage: "\n -t PID Target process to get namespaces from"
+//usage: "\n -m[FILE] Enter mount namespace"
+//usage: "\n -u[FILE] Enter UTS namespace (hostname etc)"
+//usage: "\n -i[FILE] Enter System V IPC namespace"
+//usage: "\n -n[FILE] Enter network namespace"
+//usage: "\n -p[FILE] Enter pid namespace"
+//usage: "\n -U[FILE] Enter user namespace"
+//usage: "\n -S UID Set uid in entered namespace"
+//usage: "\n -G GID Set gid in entered namespace"
+//usage: "\n -r[DIR] Set root directory"
+//usage: "\n -w[DIR] Set working directory"
+//usage: "\n -F Don't fork before exec'ing PROG"
+//usage:#endif
+
+#include <sched.h>
+#ifndef CLONE_NEWUTS
+# define CLONE_NEWUTS 0x04000000
+#endif
+#ifndef CLONE_NEWIPC
+# define CLONE_NEWIPC 0x08000000
+#endif
+#ifndef CLONE_NEWUSER
+# define CLONE_NEWUSER 0x10000000
+#endif
+#ifndef CLONE_NEWPID
+# define CLONE_NEWPID 0x20000000
+#endif
+#ifndef CLONE_NEWNET
+# define CLONE_NEWNET 0x40000000
+#endif
+
+#include "libbb.h"
+
+struct namespace_descr {
+ int flag; /* value passed to setns() */
+ char ns_nsfile8[8]; /* "ns/" + namespace file in process' procfs entry */
+};
+
+struct namespace_ctx {
+ char *path; /* optional path to a custom ns file */
+ int fd; /* opened namespace file descriptor */
+};
+
+enum {
+ OPT_user = 1 << 0,
+ OPT_ipc = 1 << 1,
+ OPT_uts = 1 << 2,
+ OPT_network = 1 << 3,
+ OPT_pid = 1 << 4,
+ OPT_mount = 1 << 5,
+ OPT_target = 1 << 6,
+ OPT_setuid = 1 << 7,
+ OPT_setgid = 1 << 8,
+ OPT_root = 1 << 9,
+ OPT_wd = 1 << 10,
+ OPT_nofork = 1 << 11,
+ OPT_prescred = (1 << 12) * ENABLE_FEATURE_NSENTER_LONG_OPTS,
+};
+enum {
+ NS_USR_POS = 0,
+ NS_IPC_POS,
+ NS_UTS_POS,
+ NS_NET_POS,
+ NS_PID_POS,
+ NS_MNT_POS,
+ NS_COUNT,
+};
+/*
+ * The order is significant in nsenter.
+ * The user namespace comes first, so that it is entered first.
+ * This gives an unprivileged user the potential to enter other namespaces.
+ */
+static const struct namespace_descr ns_list[] = {
+ { CLONE_NEWUSER, "ns/user", },
+ { CLONE_NEWIPC, "ns/ipc", },
+ { CLONE_NEWUTS, "ns/uts", },
+ { CLONE_NEWNET, "ns/net", },
+ { CLONE_NEWPID, "ns/pid", },
+ { CLONE_NEWNS, "ns/mnt", },
+};
+/*
+ * Upstream nsenter doesn't support the short option for --preserve-credentials
+ */
+static const char opt_str[] ALIGN1 = "U::i::u::n::p::m::""t+S+G+r::w::F";
+
+#if ENABLE_FEATURE_NSENTER_LONG_OPTS
+static const char nsenter_longopts[] ALIGN1 =
+ "user\0" Optional_argument "U"
+ "ipc\0" Optional_argument "i"
+ "uts\0" Optional_argument "u"
+ "network\0" Optional_argument "n"
+ "pid\0" Optional_argument "p"
+ "mount\0" Optional_argument "m"
+ "target\0" Required_argument "t"
+ "setuid\0" Required_argument "S"
+ "setgid\0" Required_argument "G"
+ "root\0" Optional_argument "r"
+ "wd\0" Optional_argument "w"
+ "no-fork\0" No_argument "F"
+ "preserve-credentials\0" No_argument "\xff"
+ ;
+#endif
+
+/*
+ * Open a file and return the new descriptor. If a full path is provided in
+ * fs_path, then the file to which it points is opened. Otherwise (fd_path is
+ * NULL) the routine builds a path to a procfs file using the following
+ * template: '/proc/<target_pid>/<target_file>'.
+ */
+static int open_by_path_or_target(const char *path,
+ pid_t target_pid, const char *target_file)
+{
+ char proc_path_buf[sizeof("/proc/%u/1234567890") + sizeof(int)*3];
+
+ if (!path) {
+ if (target_pid == 0) {
+ /* Example:
+ * "nsenter -p PROG" - neither -pFILE nor -tPID given.
+ */
+ bb_show_usage();
+ }
+ snprintf(proc_path_buf, sizeof(proc_path_buf),
+ "/proc/%u/%s", (unsigned)target_pid, target_file);
+ path = proc_path_buf;
+ }
+
+ return xopen(path, O_RDONLY);
+}
+
+int nsenter_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int nsenter_main(int argc UNUSED_PARAM, char **argv)
+{
+ int i;
+ unsigned int opts;
+ const char *root_dir_str = NULL;
+ const char *wd_str = NULL;
+ struct namespace_ctx ns_ctx_list[NS_COUNT];
+ int setgroups_failed;
+ int root_fd, wd_fd;
+ int target_pid = 0;
+ int uid = 0;
+ int gid = 0;
+
+ memset(ns_ctx_list, 0, sizeof(ns_ctx_list));
+
+ IF_FEATURE_NSENTER_LONG_OPTS(applet_long_options = nsenter_longopts);
+ opts = getopt32(argv, opt_str,
+ &ns_ctx_list[NS_USR_POS].path,
+ &ns_ctx_list[NS_IPC_POS].path,
+ &ns_ctx_list[NS_UTS_POS].path,
+ &ns_ctx_list[NS_NET_POS].path,
+ &ns_ctx_list[NS_PID_POS].path,
+ &ns_ctx_list[NS_MNT_POS].path,
+ &target_pid, &uid, &gid,
+ &root_dir_str, &wd_str
+ );
+ argv += optind;
+
+ root_fd = wd_fd = -1;
+ if (opts & OPT_root)
+ root_fd = open_by_path_or_target(root_dir_str,
+ target_pid, "root");
+ if (opts & OPT_wd)
+ wd_fd = open_by_path_or_target(wd_str, target_pid, "cwd");
+
+ for (i = 0; i < NS_COUNT; i++) {
+ const struct namespace_descr *ns = &ns_list[i];
+ struct namespace_ctx *ns_ctx = &ns_ctx_list[i];
+
+ ns_ctx->fd = -1;
+ if (opts & (1 << i))
+ ns_ctx->fd = open_by_path_or_target(ns_ctx->path,
+ target_pid, ns->ns_nsfile8);
+ }
+
+ /*
+ * Entering the user namespace without --preserve-credentials implies
+ * --setuid & --setgid and clearing root's groups.
+ */
+ setgroups_failed = 0;
+ if ((opts & OPT_user) && !(opts & OPT_prescred)) {
+ opts |= (OPT_setuid | OPT_setgid);
+ /*
+ * We call setgroups() before and after setns() and only
+ * bail-out if it fails twice.
+ */
+ setgroups_failed = (setgroups(0, NULL) < 0);
+ }
+
+ for (i = 0; i < NS_COUNT; i++) {
+ const struct namespace_descr *ns = &ns_list[i];
+ struct namespace_ctx *ns_ctx = &ns_ctx_list[i];
+
+ if (ns_ctx->fd < 0)
+ continue;
+ if (setns(ns_ctx->fd, ns->flag)) {
+ bb_perror_msg_and_die(
+ "setns(): can't reassociate to namespace '%s'",
+ ns->ns_nsfile8 + 3 /* skip over "ns/" */
+ );
+ }
+ close(ns_ctx->fd); /* should close fds, to not confuse exec'ed PROG */
+ /*ns_ctx->fd = -1;*/
+ }
+
+ if (root_fd >= 0) {
+ if (wd_fd < 0) {
+ /*
+ * Save the current working directory if we're not
+ * changing it.
+ */
+ wd_fd = xopen(".", O_RDONLY);
+ }
+ xfchdir(root_fd);
+ xchroot(".");
+ close(root_fd);
+ /*root_fd = -1;*/
+ }
+
+ if (wd_fd >= 0) {
+ xfchdir(wd_fd);
+ close(wd_fd);
+ /*wd_fd = -1;*/
+ }
+
+ /*
+ * Entering the pid namespace implies forking unless it's been
+ * explicitly requested by the user not to.
+ */
+ if (!(opts & OPT_nofork) && (opts & OPT_pid)) {
+ xvfork_parent_waits_and_exits();
+ /* Child continues */
+ }
+
+ if (opts & OPT_setgid) {
+ if (setgroups(0, NULL) < 0 && setgroups_failed)
+ bb_perror_msg_and_die("setgroups");
+ xsetgid(gid);
+ }
+ if (opts & OPT_setuid)
+ xsetuid(uid);
+
+ exec_prog_or_SHELL(argv);
+}
diff --git a/release/src/router/busybox/util-linux/rdate.c b/release/src/router/busybox/util-linux/rdate.c
index 1f36d8f37b..8075ef6af2 100644
--- a/release/src/router/busybox/util-linux/rdate.c
+++ b/release/src/router/busybox/util-linux/rdate.c
@@ -1,7 +1,7 @@
/* vi: set sw=4 ts=4: */
/*
* The Rdate command will ask a time server for the RFC 868 time
- * and optionally set the system time.
+ * and optionally set the system time.
*
* by Sterling Huxley <sterling@europa.com>
*
@@ -11,9 +11,9 @@
//usage:#define rdate_trivial_usage
//usage: "[-sp] HOST"
//usage:#define rdate_full_usage "\n\n"
-//usage: "Get and possibly set the system date and time from a remote HOST\n"
-//usage: "\n -s Set the system date and time (default)"
-//usage: "\n -p Print the date and time"
+//usage: "Get and possibly set system time from a remote HOST\n"
+//usage: "\n -s Set system time (default)"
+//usage: "\n -p Print time"
#include "libbb.h"
@@ -35,15 +35,16 @@ static time_t askremotedate(const char *host)
fd = create_and_connect_stream_or_die(host, bb_lookup_port("time", "tcp", 37));
- if (safe_read(fd, (void *)&nett, 4) != 4) /* read time from server */
- bb_error_msg_and_die("%s did not send the complete time", host);
- close(fd);
+ if (safe_read(fd, &nett, 4) != 4) /* read time from server */
+ bb_error_msg_and_die("%s: %s", host, "short read");
+ if (ENABLE_FEATURE_CLEAN_UP)
+ close(fd);
- /* convert from network byte order to local byte order.
+ /* Convert from network byte order to local byte order.
* RFC 868 time is the number of seconds
* since 00:00 (midnight) 1 January 1900 GMT
* the RFC 868 time 2,208,988,800 corresponds to 00:00 1 Jan 1970 GMT
- * Subtract the RFC 868 time to get Linux epoch
+ * Subtract the RFC 868 time to get Linux epoch.
*/
return ntohl(nett) - RFC_868_BIAS;
@@ -53,14 +54,14 @@ int rdate_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int rdate_main(int argc UNUSED_PARAM, char **argv)
{
time_t remote_time;
- unsigned long flags;
+ unsigned flags;
opt_complementary = "-1";
flags = getopt32(argv, "sp");
remote_time = askremotedate(argv[optind]);
- if ((flags & 2) == 0) {
+ if (!(flags & 2)) { /* no -p (-s may be present) */
time_t current_time;
time(&current_time);
@@ -71,7 +72,7 @@ int rdate_main(int argc UNUSED_PARAM, char **argv)
bb_perror_msg_and_die("can't set time of day");
}
- if ((flags & 1) == 0)
+ if (flags != 1) /* not lone -s */
printf("%s", ctime(&remote_time));
return EXIT_SUCCESS;
diff --git a/release/src/router/busybox/util-linux/readprofile.c b/release/src/router/busybox/util-linux/readprofile.c
index 4ed8011377..a645404643 100644
--- a/release/src/router/busybox/util-linux/readprofile.c
+++ b/release/src/router/busybox/util-linux/readprofile.c
@@ -152,7 +152,7 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv)
step = buf[0];
if (optInfo) {
- printf("Sampling_step: %i\n", step);
+ printf("Sampling_step: %u\n", step);
return EXIT_SUCCESS;
}
@@ -163,7 +163,7 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv)
while (fgets(mapline, S_LEN, map)) {
if (sscanf(mapline, "%llx %s %s", &fn_add, mode, fn_name) != 3)
bb_error_msg_and_die("%s(%i): wrong map line",
- mapFile, maplineno);
+ mapFile, maplineno);
if (!strcmp(fn_name, "_stext")) /* only elf works like this */ {
add0 = fn_add;
@@ -198,7 +198,7 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv)
if (indx >= len / sizeof(*buf))
bb_error_msg_and_die("profile address out of range. "
- "Wrong map file?");
+ "Wrong map file?");
while (indx < (next_add-add0)/step) {
if (optBins && (buf[indx] || optAll)) {
@@ -219,11 +219,11 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv)
&& (fn_len = next_add-fn_add) != 0
) {
if (optVerbose)
- printf("%016llx %-40s %6i %8.4f\n", fn_add,
- fn_name, this, this/(double)fn_len);
+ printf("%016llx %-40s %6u %8.4f\n", fn_add,
+ fn_name, this, this/(double)fn_len);
else
- printf("%6i %-40s %8.4f\n",
- this, fn_name, this/(double)fn_len);
+ printf("%6u %-40s %8.4f\n",
+ this, fn_name, this/(double)fn_len);
if (optSub) {
unsigned long long scan;
@@ -233,8 +233,8 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv)
addr = (scan - 1)*step + add0;
printf("\t%#llx\t%s+%#llx\t%u\n",
- addr, fn_name, addr - fn_add,
- buf[scan]);
+ addr, fn_name, addr - fn_add,
+ buf[scan]);
}
}
}
@@ -246,15 +246,15 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv)
}
/* clock ticks, out of kernel text - probably modules */
- printf("%6i %s\n", buf[len/sizeof(*buf)-1], "*unknown*");
+ printf("%6u %s\n", buf[len/sizeof(*buf)-1], "*unknown*");
/* trailer */
if (optVerbose)
- printf("%016x %-40s %6i %8.4f\n",
- 0, "total", total, total/(double)(fn_add-add0));
+ printf("%016x %-40s %6u %8.4f\n",
+ 0, "total", total, total/(double)(fn_add-add0));
else
- printf("%6i %-40s %8.4f\n",
- total, "total", total/(double)(fn_add-add0));
+ printf("%6u %-40s %8.4f\n",
+ total, "total", total/(double)(fn_add-add0));
fclose(map);
free(buf);
diff --git a/release/src/router/busybox/util-linux/rtcwake.c b/release/src/router/busybox/util-linux/rtcwake.c
index 735a298223..8aee0cfcbd 100644
--- a/release/src/router/busybox/util-linux/rtcwake.c
+++ b/release/src/router/busybox/util-linux/rtcwake.c
@@ -32,18 +32,18 @@
//usage: "\n -l,--local Clock is set to local time"
//usage: "\n -u,--utc Clock is set to UTC time"
//usage: "\n -d,--device=DEV Specify the RTC device"
-//usage: "\n -m,--mode=MODE Set the sleep state (default: standby)"
-//usage: "\n -s,--seconds=SEC Set the timeout in SEC seconds from now"
-//usage: "\n -t,--time=TIME Set the timeout to TIME seconds from epoch"
+//usage: "\n -m,--mode=MODE Set sleep state (default: standby)"
+//usage: "\n -s,--seconds=SEC Set timeout in SEC seconds from now"
+//usage: "\n -t,--time=TIME Set timeout to TIME seconds from epoch"
//usage: )
//usage: IF_NOT_LONG_OPTS(
//usage: "\n -a Read clock mode from adjtime"
//usage: "\n -l Clock is set to local time"
//usage: "\n -u Clock is set to UTC time"
//usage: "\n -d DEV Specify the RTC device"
-//usage: "\n -m MODE Set the sleep state (default: standby)"
-//usage: "\n -s SEC Set the timeout in SEC seconds from now"
-//usage: "\n -t TIME Set the timeout to TIME seconds from epoch"
+//usage: "\n -m MODE Set sleep state (default: standby)"
+//usage: "\n -s SEC Set timeout in SEC seconds from now"
+//usage: "\n -t TIME Set timeout to TIME seconds from epoch"
//usage: )
#include "libbb.h"
@@ -51,7 +51,6 @@
#define SYS_RTC_PATH "/sys/class/rtc/%s/device/power/wakeup"
#define SYS_POWER_PATH "/sys/power/state"
-#define DEFAULT_MODE "standby"
static NOINLINE bool may_wakeup(const char *rtcname)
{
@@ -67,7 +66,7 @@ static NOINLINE bool may_wakeup(const char *rtcname)
return false;
/* wakeup events could be disabled or not supported */
- return strncmp(buf, "enabled\n", 8) == 0;
+ return is_prefixed_with(buf, "enabled\n") != NULL;
}
static NOINLINE void setup_alarm(int fd, time_t *wakeup, time_t rtc_time)
@@ -122,17 +121,16 @@ static NOINLINE void setup_alarm(int fd, time_t *wakeup, time_t rtc_time)
int rtcwake_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int rtcwake_main(int argc UNUSED_PARAM, char **argv)
{
- time_t rtc_time;
-
unsigned opt;
const char *rtcname = NULL;
- const char *suspend;
+ const char *suspend = "standby";
const char *opt_seconds;
const char *opt_time;
+ time_t rtc_time;
time_t sys_time;
- time_t alarm_time = 0;
- unsigned seconds = 0;
+ time_t alarm_time = alarm_time;
+ unsigned seconds = seconds; /* for compiler */
int utc = -1;
int fd;
@@ -148,6 +146,8 @@ int rtcwake_main(int argc UNUSED_PARAM, char **argv)
;
applet_long_options = rtcwake_longopts;
#endif
+ /* Must have -s or -t, exclusive */
+ opt_complementary = "s:t:s--t:t--s";
opt = getopt32(argv, "alud:m:s:t:", &rtcname, &suspend, &opt_seconds, &opt_time);
/* this is the default
@@ -156,17 +156,17 @@ int rtcwake_main(int argc UNUSED_PARAM, char **argv)
*/
if (opt & (RTCWAKE_OPT_UTC | RTCWAKE_OPT_LOCAL))
utc = opt & RTCWAKE_OPT_UTC;
- if (!(opt & RTCWAKE_OPT_SUSPEND_MODE))
- suspend = DEFAULT_MODE;
- if (opt & RTCWAKE_OPT_SECONDS)
+ if (opt & RTCWAKE_OPT_SECONDS) {
/* alarm time, seconds-to-sleep (relative) */
- seconds = xatoi(opt_seconds);
- if (opt & RTCWAKE_OPT_TIME)
+ seconds = xatou(opt_seconds);
+ } else {
+ /* RTCWAKE_OPT_TIME */
/* alarm time, time_t (absolute, seconds since 1/1 1970 UTC) */
- alarm_time = xatol(opt_time);
-
- if (!alarm_time && !seconds)
- bb_error_msg_and_die("must provide wake time");
+ if (sizeof(alarm_time) <= sizeof(long))
+ alarm_time = xatol(opt_time);
+ else
+ alarm_time = xatoll(opt_time);
+ }
if (utc == -1)
utc = rtc_adjtime_is_utc();
@@ -177,8 +177,9 @@ int rtcwake_main(int argc UNUSED_PARAM, char **argv)
/* this RTC must exist and (if we'll sleep) be wakeup-enabled */
fd = rtc_xopen(&rtcname, O_RDONLY);
- if (strcmp(suspend, "on") && !may_wakeup(rtcname))
- bb_error_msg_and_die("%s not enabled for wakeup events", rtcname);
+ if (strcmp(suspend, "on") != 0)
+ if (!may_wakeup(rtcname))
+ bb_error_msg_and_die("%s not enabled for wakeup events", rtcname);
/* relative or absolute alarm time, normalized to time_t */
sys_time = time(NULL);
@@ -188,21 +189,29 @@ int rtcwake_main(int argc UNUSED_PARAM, char **argv)
rtc_time = rtc_tm2time(&tm_time, utc);
}
-
- if (alarm_time) {
- if (alarm_time < sys_time)
+ if (opt & RTCWAKE_OPT_TIME) {
+ /* Correct for RTC<->system clock difference */
+ alarm_time += rtc_time - sys_time;
+ if (alarm_time < rtc_time)
+ /*
+ * Compat message text.
+ * I'd say "RTC time is already ahead of ..." instead.
+ */
bb_error_msg_and_die("time doesn't go backward to %s", ctime(&alarm_time));
- alarm_time += sys_time - rtc_time;
} else
alarm_time = rtc_time + seconds + 1;
- setup_alarm(fd, &alarm_time, rtc_time);
+ setup_alarm(fd, &alarm_time, rtc_time);
sync();
+#if 0 /*debug*/
+ printf("sys_time: %s", ctime(&sys_time));
+ printf("rtc_time: %s", ctime(&rtc_time));
+#endif
printf("wakeup from \"%s\" at %s", suspend, ctime(&alarm_time));
fflush_all();
usleep(10 * 1000);
- if (strcmp(suspend, "on"))
+ if (strcmp(suspend, "on") != 0)
xopen_xwrite_close(SYS_POWER_PATH, suspend);
else {
/* "fake" suspend ... we'll do the delay ourselves */
diff --git a/release/src/router/busybox/util-linux/script.c b/release/src/router/busybox/util-linux/script.c
index 8fb991d15f..86475c1f14 100644
--- a/release/src/router/busybox/util-linux/script.c
+++ b/release/src/router/busybox/util-linux/script.c
@@ -23,6 +23,7 @@
//usage: )
#include "libbb.h"
+#include "common_bufsiz.h"
int script_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int script_main(int argc UNUSED_PARAM, char **argv)
@@ -77,8 +78,15 @@ int script_main(int argc UNUSED_PARAM, char **argv)
if (!(opt & OPT_q)) {
printf("Script started, file is %s\n", fname);
}
+
shell = get_shell_name();
+ /* Some people run "script ... 0>&-".
+ * Our code assumes that STDIN_FILENO != pty.
+ * Ensure STDIN_FILENO is not closed:
+ */
+ bb_sanitize_stdio();
+
pty = xgetpty(pty_line);
/* get current stdin's tty params */
@@ -101,11 +109,12 @@ int script_main(int argc UNUSED_PARAM, char **argv)
if (child_pid) {
/* parent */
-#define buf bb_common_bufsiz1
struct pollfd pfd[2];
int outfd, count, loop;
double oldtime = ENABLE_SCRIPTREPLAY ? time(NULL) : 0;
smallint fd_count = 2;
+#define buf bb_common_bufsiz1
+ setup_common_bufsiz();
outfd = xopen(fname, mode);
pfd[0].fd = pty;
@@ -127,7 +136,7 @@ int script_main(int argc UNUSED_PARAM, char **argv)
}
if (pfd[0].revents) {
errno = 0;
- count = safe_read(pty, buf, sizeof(buf));
+ count = safe_read(pty, buf, COMMON_BUFSIZE);
if (count <= 0 && errno != EAGAIN) {
/* err/eof from pty: exit */
goto restore;
@@ -150,7 +159,7 @@ int script_main(int argc UNUSED_PARAM, char **argv)
}
}
if (pfd[1].revents) {
- count = safe_read(STDIN_FILENO, buf, sizeof(buf));
+ count = safe_read(STDIN_FILENO, buf, COMMON_BUFSIZE);
if (count <= 0) {
/* err/eof from stdin: don't read stdin anymore */
pfd[1].revents = 0;
@@ -169,7 +178,7 @@ int script_main(int argc UNUSED_PARAM, char **argv)
* (util-linux's script doesn't do this. buggy :) */
loop = 999;
/* pty is in O_NONBLOCK mode, we exit as soon as buffer is empty */
- while (--loop && (count = safe_read(pty, buf, sizeof(buf))) > 0) {
+ while (--loop && (count = safe_read(pty, buf, COMMON_BUFSIZE)) > 0) {
full_write(STDOUT_FILENO, buf, count);
full_write(outfd, buf, count);
}
diff --git a/release/src/router/busybox/util-linux/setarch.c b/release/src/router/busybox/util-linux/setarch.c
index 7b9421af1e..2e989ec2af 100644
--- a/release/src/router/busybox/util-linux/setarch.c
+++ b/release/src/router/busybox/util-linux/setarch.c
@@ -6,13 +6,30 @@
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//config:config SETARCH
+//config: bool "setarch"
+//config: default y
+//config: select PLATFORM_LINUX
+//config: help
+//config: The linux32 utility is used to create a 32bit environment for the
+//config: specified program (usually a shell). It only makes sense to have
+//config: this util on a system that supports both 64bit and 32bit userland
+//config: (like amd64/x86, ppc64/ppc, sparc64/sparc, etc...).
+
+//applet:IF_SETARCH(APPLET(setarch, BB_DIR_BIN, BB_SUID_DROP))
+//applet:IF_SETARCH(APPLET_ODDNAME(linux32, setarch, BB_DIR_BIN, BB_SUID_DROP, linux32))
+//applet:IF_SETARCH(APPLET_ODDNAME(linux64, setarch, BB_DIR_BIN, BB_SUID_DROP, linux64))
+
+//kbuild:lib-$(CONFIG_SETARCH) += setarch.o
//usage:#define setarch_trivial_usage
-//usage: "personality PROG ARGS"
+//usage: "PERSONALITY [-R] PROG ARGS"
//usage:#define setarch_full_usage "\n\n"
-//usage: "Personality may be:\n"
-//usage: " linux32 Set 32bit uname emulation\n"
-//usage: " linux64 Set 64bit uname emulation"
+//usage: "PERSONALITY may be:"
+//usage: "\n"" linux32 Set 32bit uname emulation"
+//usage: "\n"" linux64 Set 64bit uname emulation"
+//usage: "\n"
+//usage: "\n"" -R Disable address space randomization"
//usage:
//usage:#define linux32_trivial_usage NOUSAGE_STR
//usage:#define linux32_full_usage ""
@@ -20,14 +37,18 @@
//usage:#define linux64_trivial_usage NOUSAGE_STR
//usage:#define linux64_full_usage ""
+#include "libbb.h"
#include <sys/personality.h>
-#include "libbb.h"
+#ifndef ADDR_NO_RANDOMIZE
+# define ADDR_NO_RANDOMIZE 0x0040000
+#endif
int setarch_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int setarch_main(int argc UNUSED_PARAM, char **argv)
{
- int pers;
+ unsigned opts;
+ unsigned long pers;
/* Figure out what personality we are supposed to switch to ...
* we can be invoked as either:
@@ -35,7 +56,7 @@ int setarch_main(int argc UNUSED_PARAM, char **argv)
* argv[0] == "personality"
*/
if (ENABLE_SETARCH && applet_name[0] == 's'
- && argv[1] && strncpy(argv[1], "linux", 5)
+ && argv[1] && is_prefixed_with(argv[1], "linux")
) {
applet_name = argv[1];
argv++;
@@ -47,15 +68,18 @@ int setarch_main(int argc UNUSED_PARAM, char **argv)
else
bb_show_usage();
- argv++;
- if (argv[0] == NULL)
- bb_show_usage();
+ opts = getopt32(argv, "+R"); /* '+': stop at first non-option */
+ if (opts)
+ pers |= ADDR_NO_RANDOMIZE;
/* Try to set personality */
- if (personality(pers) >= 0) {
- /* Try to execute the program */
- BB_EXECVP(argv[0], argv);
- }
+ if (personality(pers) < 0)
+ bb_perror_msg_and_die("personality(0x%lx)", pers);
+
+ argv += optind;
+ if (!argv[0])
+ (--argv)[0] = (char*)"/bin/sh";
- bb_simple_perror_msg_and_die(argv[0]);
+ /* Try to execute the program */
+ BB_EXECVP_or_die(argv);
}
diff --git a/release/src/router/busybox/util-linux/swaponoff.c b/release/src/router/busybox/util-linux/swaponoff.c
index 1562424fa4..6713852e51 100644
--- a/release/src/router/busybox/util-linux/swaponoff.c
+++ b/release/src/router/busybox/util-linux/swaponoff.c
@@ -8,10 +8,15 @@
*/
//usage:#define swapon_trivial_usage
-//usage: "[-a]" IF_FEATURE_SWAPON_PRI(" [-p PRI]") " [DEVICE]"
+//usage: "[-a] [-e]" IF_FEATURE_SWAPON_DISCARD(" [-d[POL]]") IF_FEATURE_SWAPON_PRI(" [-p PRI]") " [DEVICE]"
//usage:#define swapon_full_usage "\n\n"
//usage: "Start swapping on DEVICE\n"
//usage: "\n -a Start swapping on all swap devices"
+//usage: IF_FEATURE_SWAPON_DISCARD(
+//usage: "\n -d[POL] Discard blocks at swapon (POL=once),"
+//usage: "\n as freed (POL=pages), or both (POL omitted)"
+//usage: )
+//usage: "\n -e Silently skip devices that do not exist"
//usage: IF_FEATURE_SWAPON_PRI(
//usage: "\n -p PRI Set swap device priority"
//usage: )
@@ -23,6 +28,7 @@
//usage: "\n -a Stop swapping on all swap devices"
#include "libbb.h"
+#include "common_bufsiz.h"
#include <mntent.h>
#ifndef __BIONIC__
# include <sys/swap.h>
@@ -38,67 +44,168 @@
# define MNTTYPE_SWAP "swap"
#endif
-#if ENABLE_FEATURE_SWAPON_PRI
+#if ENABLE_FEATURE_SWAPON_DISCARD
+#ifndef SWAP_FLAG_DISCARD
+#define SWAP_FLAG_DISCARD 0x10000
+#endif
+#ifndef SWAP_FLAG_DISCARD_ONCE
+#define SWAP_FLAG_DISCARD_ONCE 0x20000
+#endif
+#ifndef SWAP_FLAG_DISCARD_PAGES
+#define SWAP_FLAG_DISCARD_PAGES 0x40000
+#endif
+#define SWAP_FLAG_DISCARD_MASK \
+ (SWAP_FLAG_DISCARD | SWAP_FLAG_DISCARD_ONCE | SWAP_FLAG_DISCARD_PAGES)
+#endif
+
+
+#if ENABLE_FEATURE_SWAPON_DISCARD || ENABLE_FEATURE_SWAPON_PRI
struct globals {
int flags;
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define g_flags (G.flags)
+#define save_g_flags() int save_g_flags = g_flags
+#define restore_g_flags() g_flags = save_g_flags
#else
#define g_flags 0
+#define save_g_flags() ((void)0)
+#define restore_g_flags() ((void)0)
#endif
-#define INIT_G() do { } while (0)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
+
+#define do_swapoff (applet_name[5] == 'f')
+
+/* Command line options */
+enum {
+ OPTBIT_a, /* -a all */
+ OPTBIT_e, /* -e ifexists */
+ IF_FEATURE_SWAPON_DISCARD( OPTBIT_d ,) /* -d discard */
+ IF_FEATURE_SWAPON_PRI ( OPTBIT_p ,) /* -p priority */
+ OPT_a = 1 << OPTBIT_a,
+ OPT_e = 1 << OPTBIT_e,
+ OPT_d = IF_FEATURE_SWAPON_DISCARD((1 << OPTBIT_d)) + 0,
+ OPT_p = IF_FEATURE_SWAPON_PRI ((1 << OPTBIT_p)) + 0,
+};
+
+#define OPT_ALL (option_mask32 & OPT_a)
+#define OPT_DISCARD (option_mask32 & OPT_d)
+#define OPT_IFEXISTS (option_mask32 & OPT_e)
+#define OPT_PRIO (option_mask32 & OPT_p)
static int swap_enable_disable(char *device)
{
- int status;
- struct stat st;
+ int err = 0;
+ int quiet = 0;
resolve_mount_spec(&device);
- if (stat(device, &st)) {
- bb_perror_msg("warning: can't stat '%s'", device);
+
+ if (do_swapoff) {
+ err = swapoff(device);
+ /* Don't complain on OPT_ALL if not a swap device or if it doesn't exist */
+ quiet = (OPT_ALL && (errno == EINVAL || errno == ENOENT));
+ } else {
+ /* swapon */
+ struct stat st;
+ err = stat(device, &st);
+ if (!err) {
+ if (ENABLE_DESKTOP && S_ISREG(st.st_mode)) {
+ if (st.st_blocks * (off_t)512 < st.st_size) {
+ bb_error_msg("%s: file has holes", device);
+ return 1;
+ }
+ }
+ err = swapon(device, g_flags);
+ /* Don't complain on swapon -a if device is already in use */
+ quiet = (OPT_ALL && errno == EBUSY);
+ }
+ /* Don't complain if file does not exist with -e option */
+ if (err && OPT_IFEXISTS && errno == ENOENT)
+ err = 0;
+ }
+
+ if (err && !quiet) {
+ bb_simple_perror_msg(device);
return 1;
}
+ return 0;
+}
-#if ENABLE_DESKTOP
- /* test for holes */
- if (S_ISREG(st.st_mode))
- if (st.st_blocks * (off_t)512 < st.st_size)
- bb_error_msg("warning: swap file has holes");
+#if ENABLE_FEATURE_SWAPON_DISCARD
+static void set_discard_flag(char *s)
+{
+ /* Unset the flag first to allow fstab options to override */
+ /* options set on the command line */
+ g_flags = (g_flags & ~SWAP_FLAG_DISCARD_MASK) | SWAP_FLAG_DISCARD;
+
+ if (!s) /* No optional policy value on the commandline */
+ return;
+ /* Skip prepended '=' */
+ if (*s == '=')
+ s++;
+ /* For fstab parsing: remove other appended options */
+ *strchrnul(s, ',') = '\0';
+
+ if (strcmp(s, "once") == 0)
+ g_flags |= SWAP_FLAG_DISCARD_ONCE;
+ if (strcmp(s, "pages") == 0)
+ g_flags |= SWAP_FLAG_DISCARD_PAGES;
+}
+#else
+#define set_discard_flag(s) ((void)0)
#endif
- if (applet_name[5] == 'n')
- status = swapon(device, g_flags);
- else
- status = swapoff(device);
+#if ENABLE_FEATURE_SWAPON_PRI
+static void set_priority_flag(char *s)
+{
+ unsigned prio;
- if (status != 0) {
- bb_simple_perror_msg(device);
- return 1;
+ /* For fstab parsing: remove other appended options */
+ *strchrnul(s, ',') = '\0';
+ /* Max allowed 32767 (== SWAP_FLAG_PRIO_MASK) */
+ prio = bb_strtou(s, NULL, 10);
+ if (!errno) {
+ /* Unset the flag first to allow fstab options to override */
+ /* options set on the command line */
+ g_flags = (g_flags & ~SWAP_FLAG_PRIO_MASK) | SWAP_FLAG_PREFER |
+ MIN(prio, SWAP_FLAG_PRIO_MASK);
}
-
- return 0;
}
+#else
+#define set_priority_flag(s) ((void)0)
+#endif
-static int do_em_all(void)
+static int do_em_all_in_fstab(void)
{
struct mntent *m;
- FILE *f;
- int err;
-
- f = setmntent("/etc/fstab", "r");
- if (f == NULL)
- bb_perror_msg_and_die("/etc/fstab");
+ int err = 0;
+ FILE *f = xfopen_for_read("/etc/fstab");
- err = 0;
while ((m = getmntent(f)) != NULL) {
if (strcmp(m->mnt_type, MNTTYPE_SWAP) == 0) {
/* swapon -a should ignore entries with noauto,
- * but swapoff -a should process them */
- if (applet_name[5] != 'n'
- || hasmntopt(m, MNTOPT_NOAUTO) == NULL
- ) {
- err += swap_enable_disable(m->mnt_fsname);
+ * but swapoff -a should process them
+ */
+ if (do_swapoff || hasmntopt(m, MNTOPT_NOAUTO) == NULL) {
+ /* each swap space might have different flags */
+ /* save global flags for the next round */
+ save_g_flags();
+ if (ENABLE_FEATURE_SWAPON_DISCARD) {
+ char *p = hasmntopt(m, "discard");
+ if (p) {
+ /* move to '=' or to end of string */
+ p += 7;
+ set_discard_flag(p);
+ }
+ }
+ if (ENABLE_FEATURE_SWAPON_PRI) {
+ char *p = hasmntopt(m, "pri");
+ if (p) {
+ set_priority_flag(p + 4);
+ }
+ }
+ err |= swap_enable_disable(m->mnt_fsname);
+ restore_g_flags();
}
}
}
@@ -109,38 +216,68 @@ static int do_em_all(void)
return err;
}
+static int do_all_in_proc_swaps(void)
+{
+ char *line;
+ int err = 0;
+ FILE *f = fopen_for_read("/proc/swaps");
+ /* Don't complain if missing */
+ if (f) {
+ while ((line = xmalloc_fgetline(f)) != NULL) {
+ if (line[0] == '/') {
+ *strchrnul(line, ' ') = '\0';
+ err |= swap_enable_disable(line);
+ }
+ free(line);
+ }
+ if (ENABLE_FEATURE_CLEAN_UP)
+ fclose(f);
+ }
+
+ return err;
+}
+
+#define OPTSTR_SWAPON "ae" \
+ IF_FEATURE_SWAPON_DISCARD("d::") \
+ IF_FEATURE_SWAPON_PRI("p:")
+
int swap_on_off_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int swap_on_off_main(int argc UNUSED_PARAM, char **argv)
{
- int ret;
+ IF_FEATURE_SWAPON_PRI(char *prio;)
+ IF_FEATURE_SWAPON_DISCARD(char *discard = NULL;)
+ int ret = 0;
INIT_G();
-#if !ENABLE_FEATURE_SWAPON_PRI
- ret = getopt32(argv, "a");
-#else
- if (applet_name[5] == 'n')
- opt_complementary = "p+";
- ret = getopt32(argv, (applet_name[5] == 'n') ? "ap:" : "a", &g_flags);
-
- if (ret & 2) { // -p
- g_flags = SWAP_FLAG_PREFER |
- ((g_flags & SWAP_FLAG_PRIO_MASK) << SWAP_FLAG_PRIO_SHIFT);
- ret &= 1;
- }
-#endif
-
- if (ret /* & 1: not needed */) // -a
- return do_em_all();
+ getopt32(argv, do_swapoff ? "ae" : OPTSTR_SWAPON
+ IF_FEATURE_SWAPON_DISCARD(, &discard)
+ IF_FEATURE_SWAPON_PRI(, &prio)
+ );
argv += optind;
- if (!*argv)
- bb_show_usage();
- /* ret = 0; redundant */
- do {
- ret += swap_enable_disable(*argv);
- } while (*++argv);
+ if (OPT_DISCARD) {
+ set_discard_flag(discard);
+ }
+ if (OPT_PRIO) {
+ set_priority_flag(prio);
+ }
+ if (OPT_ALL) {
+ /* swapoff -a does also /proc/swaps */
+ if (do_swapoff)
+ ret = do_all_in_proc_swaps();
+ ret |= do_em_all_in_fstab();
+ } else if (!*argv) {
+ /* if not -a we need at least one arg */
+ bb_show_usage();
+ }
+ /* Unset -a now to allow for more messages in swap_enable_disable */
+ option_mask32 = option_mask32 & ~OPT_a;
+ /* Now process devices on the commandline if any */
+ while (*argv) {
+ ret |= swap_enable_disable(*argv++);
+ }
return ret;
}
diff --git a/release/src/router/busybox/util-linux/switch_root.c b/release/src/router/busybox/util-linux/switch_root.c
index a301b365b8..7960b672c1 100644
--- a/release/src/router/busybox/util-linux/switch_root.c
+++ b/release/src/router/busybox/util-linux/switch_root.c
@@ -206,7 +206,7 @@ because they're what all paths your process uses would be relative to.
That's why the careful sequencing above: we cd into the new mount point before
we do the mount --move. Moving the mount point would otherwise make it
-totally inaccessible to is because cd-ing to the old path wouldn't give it to
+totally inaccessible to us because cd-ing to the old path wouldn't give it to
us anymore, and cd "/" just gives us the cached dentry from when the process
was created (in this case the old initramfs one). But the "." symlink gives
us the dentry of the filesystem we just moved, so we can then "chroot ." to
diff --git a/release/src/router/busybox/util-linux/uevent.c b/release/src/router/busybox/util-linux/uevent.c
new file mode 100644
index 0000000000..b98fe61608
--- /dev/null
+++ b/release/src/router/busybox/util-linux/uevent.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2015 Denys Vlasenko
+ *
+ * Licensed under GPLv2, see file LICENSE in this source tree.
+ */
+
+//config:config UEVENT
+//config: bool "uevent"
+//config: default y
+//config: select PLATFORM_LINUX
+//config: help
+//config: uevent is a netlink listener for kernel uevent notifications
+//config: sent via netlink. It is usually used for dynamic device creation.
+
+//applet:IF_UEVENT(APPLET(uevent, BB_DIR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_UEVENT) += uevent.o
+
+//usage:#define uevent_trivial_usage
+//usage: "[PROG [ARGS]]"
+//usage:#define uevent_full_usage "\n\n"
+//usage: "uevent runs PROG for every netlink notification."
+//usage: "\n""PROG's environment contains data passed from the kernel."
+//usage: "\n""Typical usage (daemon for dynamic device node creation):"
+//usage: "\n"" # uevent mdev & mdev -s"
+
+#include "libbb.h"
+#include "common_bufsiz.h"
+#include <linux/netlink.h>
+
+#define BUFFER_SIZE 16*1024
+
+#define env ((char **)bb_common_bufsiz1)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
+enum {
+ MAX_ENV = COMMON_BUFSIZE / sizeof(env[0]) - 1,
+};
+
+#ifndef SO_RCVBUFFORCE
+#define SO_RCVBUFFORCE 33
+#endif
+enum { RCVBUF = 2 * 1024 * 1024 };
+
+int uevent_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int uevent_main(int argc UNUSED_PARAM, char **argv)
+{
+ struct sockaddr_nl sa;
+ int fd;
+
+ INIT_G();
+
+ argv++;
+
+ // Subscribe for UEVENT kernel messages
+ sa.nl_family = AF_NETLINK;
+ sa.nl_pad = 0;
+ sa.nl_pid = getpid();
+ sa.nl_groups = 1 << 0;
+ fd = xsocket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
+ xbind(fd, (struct sockaddr *) &sa, sizeof(sa));
+ close_on_exec_on(fd);
+
+ // Without a sufficiently big RCVBUF, a ton of simultaneous events
+ // can trigger ENOBUFS on read, which is unrecoverable.
+ // Reproducer:
+ // uevent mdev &
+ // find /sys -name uevent -exec sh -c 'echo add >"{}"' ';'
+ //
+ // SO_RCVBUFFORCE (root only) can go above net.core.rmem_max sysctl
+ setsockopt_SOL_SOCKET_int(fd, SO_RCVBUF, RCVBUF);
+ setsockopt_SOL_SOCKET_int(fd, SO_RCVBUFFORCE, RCVBUF);
+ if (0) {
+ int z;
+ socklen_t zl = sizeof(z);
+ getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &z, &zl);
+ bb_error_msg("SO_RCVBUF:%d", z);
+ }
+
+ for (;;) {
+ char *netbuf;
+ char *s, *end;
+ ssize_t len;
+ int idx;
+
+ // In many cases, a system sits for *days* waiting
+ // for a new uevent notification to come in.
+ // We use a fresh mmap so that buffer is not allocated
+ // until kernel actually starts filling it.
+ netbuf = mmap(NULL, BUFFER_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON,
+ /* ignored: */ -1, 0);
+ if (netbuf == MAP_FAILED)
+ bb_perror_msg_and_die("mmap");
+
+ // Here we block, possibly for a very long time
+ len = safe_read(fd, netbuf, BUFFER_SIZE - 1);
+ if (len < 0)
+ bb_perror_msg_and_die("read");
+ end = netbuf + len;
+ *end = '\0';
+
+ // Each netlink message starts with "ACTION@/path"
+ // (which we currently ignore),
+ // followed by environment variables.
+ if (!argv[0])
+ putchar('\n');
+ idx = 0;
+ s = netbuf;
+ while (s < end) {
+ if (!argv[0])
+ puts(s);
+ if (strchr(s, '=') && idx < MAX_ENV)
+ env[idx++] = s;
+ s += strlen(s) + 1;
+ }
+ env[idx] = NULL;
+
+ idx = 0;
+ while (env[idx])
+ putenv(env[idx++]);
+ if (argv[0])
+ spawn_and_wait(argv);
+ idx = 0;
+ while (env[idx])
+ bb_unsetenv(env[idx++]);
+ munmap(netbuf, BUFFER_SIZE);
+ }
+
+ return 0; // not reached
+}
diff --git a/release/src/router/busybox/util-linux/umount.c b/release/src/router/busybox/util-linux/umount.c
index 4c2e8821e6..91da69674d 100644
--- a/release/src/router/busybox/util-linux/umount.c
+++ b/release/src/router/busybox/util-linux/umount.c
@@ -30,7 +30,11 @@
#include <mntent.h>
#include <sys/mount.h>
+#ifndef MNT_DETACH
+# define MNT_DETACH 0x00000002
+#endif
#include "libbb.h"
+#include "common_bufsiz.h"
#if defined(__dietlibc__)
// TODO: This does not belong here.
@@ -81,8 +85,9 @@ int umount_main(int argc UNUSED_PARAM, char **argv)
argv += optind;
// MNT_FORCE and MNT_DETACH (from linux/fs.h) must match
- // OPT_FORCE and OPT_LAZY, otherwise this trick won't work:
- doForce = MAX((opt & OPT_FORCE), (opt & OPT_LAZY));
+ // OPT_FORCE and OPT_LAZY.
+ BUILD_BUG_ON(OPT_FORCE != MNT_FORCE || OPT_LAZY != MNT_DETACH);
+ doForce = opt & (OPT_FORCE|OPT_LAZY);
/* Get a list of mount points from mtab. We read them all in now mostly
* for umount -a (so we don't have to worry about the list changing while
@@ -98,7 +103,8 @@ int umount_main(int argc UNUSED_PARAM, char **argv)
if (opt & OPT_ALL)
bb_error_msg_and_die("can't open '%s'", bb_path_mtab_file);
} else {
- while (getmntent_r(fp, &me, bb_common_bufsiz1, sizeof(bb_common_bufsiz1))) {
+ setup_common_bufsiz();
+ while (getmntent_r(fp, &me, bb_common_bufsiz1, COMMON_BUFSIZE)) {
/* Match fstype if passed */
if (!match_fstype(&me, fstype))
continue;
@@ -147,11 +153,18 @@ int umount_main(int argc UNUSED_PARAM, char **argv)
// umount the directory even if we were given the block device.
if (m) zapit = m->dir;
+// umount from util-linux 2.22.2 does not do this:
+// umount -f uses umount2(MNT_FORCE) immediately,
+// not trying umount() first.
+// (Strangely, umount -fl ignores -f: it is equivalent to umount -l.
+// We do pass both flags in this case)
+#if 0
// Let's ask the thing nicely to unmount.
curstat = umount(zapit);
- // Force the unmount, if necessary.
+ // Unmount with force and/or lazy flags, if necessary.
if (curstat && doForce)
+#endif
curstat = umount2(zapit, doForce);
// If still can't umount, maybe remount read-only?
@@ -168,7 +181,7 @@ int umount_main(int argc UNUSED_PARAM, char **argv)
bb_error_msg(msg, m->device);
} else {
status = EXIT_FAILURE;
- bb_perror_msg("can't %sumount %s", (doForce ? "forcibly " : ""), zapit);
+ bb_perror_msg("can't unmount %s", zapit);
}
} else {
// De-allocate the loop device. This ioctl should be ignored on
diff --git a/release/src/router/busybox/util-linux/unshare.c b/release/src/router/busybox/util-linux/unshare.c
new file mode 100644
index 0000000000..fa7086add2
--- /dev/null
+++ b/release/src/router/busybox/util-linux/unshare.c
@@ -0,0 +1,380 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini unshare implementation for busybox.
+ *
+ * Copyright (C) 2016 by Bartosz Golaszewski <bartekgola@gmail.com>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+//config:config UNSHARE
+//config: bool "unshare"
+//config: default y
+//config: depends on LONG_OPTS && !NOMMU
+//config: select PLATFORM_LINUX
+//config: help
+//config: Run program with some namespaces unshared from parent.
+
+// depends on LONG_OPTS: it is awkward to exclude code which handles --propagation
+// and --setgroups based on LONG_OPTS, so instead applet requires LONG_OPTS.
+// depends on !NOMMU: we need fork()
+
+//applet:IF_UNSHARE(APPLET(unshare, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_UNSHARE) += unshare.o
+
+//usage:#define unshare_trivial_usage
+//usage: "[OPTIONS] [PROG [ARGS]]"
+//usage:#define unshare_full_usage "\n"
+//usage: "\n -m, --mount[=FILE] Unshare mount namespace"
+//usage: "\n -u, --uts[=FILE] Unshare UTS namespace (hostname etc.)"
+//usage: "\n -i, --ipc[=FILE] Unshare System V IPC namespace"
+//usage: "\n -n, --net[=FILE] Unshare network namespace"
+//usage: "\n -p, --pid[=FILE] Unshare PID namespace"
+//usage: "\n -U, --user[=FILE} Unshare user namespace"
+//usage: "\n -f, --fork Fork before execing PROG"
+//usage: "\n -r, --map-root-user Map current user to root (implies -u)"
+//usage: "\n --mount-proc[=DIR] Mount /proc filesystem first (implies -m)"
+//usage: "\n --propagation slave|shared|private|unchanged"
+//usage: "\n Modify mount propagation in mount namespace"
+//usage: "\n --setgroups allow|deny Control the setgroups syscall in user namespaces"
+
+#include <sched.h>
+#ifndef CLONE_NEWUTS
+# define CLONE_NEWUTS 0x04000000
+#endif
+#ifndef CLONE_NEWIPC
+# define CLONE_NEWIPC 0x08000000
+#endif
+#ifndef CLONE_NEWUSER
+# define CLONE_NEWUSER 0x10000000
+#endif
+#ifndef CLONE_NEWPID
+# define CLONE_NEWPID 0x20000000
+#endif
+#ifndef CLONE_NEWNET
+# define CLONE_NEWNET 0x40000000
+#endif
+
+#include <sys/mount.h>
+#ifndef MS_REC
+# define MS_REC (1 << 14)
+#endif
+#ifndef MS_PRIVATE
+# define MS_PRIVATE (1 << 18)
+#endif
+#ifndef MS_SLAVE
+# define MS_SLAVE (1 << 19)
+#endif
+#ifndef MS_SHARED
+# define MS_SHARED (1 << 20)
+#endif
+
+#include "libbb.h"
+
+static void mount_or_die(const char *source, const char *target,
+ const char *fstype, unsigned long mountflags)
+{
+ if (mount(source, target, fstype, mountflags, NULL)) {
+ bb_perror_msg_and_die("can't mount %s on %s (flags:0x%lx)",
+ source, target, mountflags);
+ /* fstype is always either NULL or "proc".
+ * "proc" is only used to mount /proc.
+ * No need to clutter up error message with fstype,
+ * it is easily deductible.
+ */
+ }
+}
+
+#define PATH_PROC_SETGROUPS "/proc/self/setgroups"
+#define PATH_PROC_UIDMAP "/proc/self/uid_map"
+#define PATH_PROC_GIDMAP "/proc/self/gid_map"
+
+struct namespace_descr {
+ int flag;
+ const char nsfile4[4];
+};
+
+struct namespace_ctx {
+ char *path;
+};
+
+enum {
+ OPT_mount = 1 << 0,
+ OPT_uts = 1 << 1,
+ OPT_ipc = 1 << 2,
+ OPT_network = 1 << 3,
+ OPT_pid = 1 << 4,
+ OPT_user = 1 << 5, /* OPT_user, NS_USR_POS, and ns_list[] index must match! */
+ OPT_fork = 1 << 6,
+ OPT_map_root = 1 << 7,
+ OPT_mount_proc = 1 << 8,
+ OPT_propagation = 1 << 9,
+ OPT_setgroups = 1 << 10,
+};
+enum {
+ NS_MNT_POS = 0,
+ NS_UTS_POS,
+ NS_IPC_POS,
+ NS_NET_POS,
+ NS_PID_POS,
+ NS_USR_POS, /* OPT_user, NS_USR_POS, and ns_list[] index must match! */
+ NS_COUNT,
+};
+static const struct namespace_descr ns_list[] = {
+ { CLONE_NEWNS, "mnt" },
+ { CLONE_NEWUTS, "uts" },
+ { CLONE_NEWIPC, "ipc" },
+ { CLONE_NEWNET, "net" },
+ { CLONE_NEWPID, "pid" },
+ { CLONE_NEWUSER, "user" }, /* OPT_user, NS_USR_POS, and ns_list[] index must match! */
+};
+
+/*
+ * Upstream unshare doesn't support short options for --mount-proc,
+ * --propagation, --setgroups.
+ * Optional arguments (namespace mountpoints) exist only for long opts,
+ * we are forced to use "fake" letters for them.
+ * '+': stop at first non-option.
+ */
+static const char opt_str[] ALIGN1 = "+muinpU""fr""\xfd::""\xfe:""\xff:";
+static const char unshare_longopts[] ALIGN1 =
+ "mount\0" Optional_argument "\xf0"
+ "uts\0" Optional_argument "\xf1"
+ "ipc\0" Optional_argument "\xf2"
+ "network\0" Optional_argument "\xf3"
+ "pid\0" Optional_argument "\xf4"
+ "user\0" Optional_argument "\xf5"
+ "fork\0" No_argument "f"
+ "map-root-user\0" No_argument "r"
+ "mount-proc\0" Optional_argument "\xfd"
+ "propagation\0" Required_argument "\xfe"
+ "setgroups\0" Required_argument "\xff"
+;
+
+/* Ugly-looking string reuse trick */
+#define PRIVATE_STR "private\0""unchanged\0""shared\0""slave\0"
+#define PRIVATE_UNCHANGED_SHARED_SLAVE PRIVATE_STR
+
+static unsigned long parse_propagation(const char *prop_str)
+{
+ int i = index_in_strings(PRIVATE_UNCHANGED_SHARED_SLAVE, prop_str);
+ if (i < 0)
+ bb_error_msg_and_die("unrecognized: --%s=%s", "propagation", prop_str);
+ if (i == 0)
+ return MS_REC | MS_PRIVATE;
+ if (i == 1)
+ return 0;
+ if (i == 2)
+ return MS_REC | MS_SHARED;
+ return MS_REC | MS_SLAVE;
+}
+
+static void mount_namespaces(pid_t pid, struct namespace_ctx *ns_ctx_list)
+{
+ const struct namespace_descr *ns;
+ struct namespace_ctx *ns_ctx;
+ int i;
+
+ for (i = 0; i < NS_COUNT; i++) {
+ char nsf[sizeof("/proc/%u/ns/AAAA") + sizeof(int)*3];
+
+ ns = &ns_list[i];
+ ns_ctx = &ns_ctx_list[i];
+ if (!ns_ctx->path)
+ continue;
+ sprintf(nsf, "/proc/%u/ns/%.4s", (unsigned)pid, ns->nsfile4);
+ mount_or_die(nsf, ns_ctx->path, NULL, MS_BIND);
+ }
+}
+
+int unshare_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int unshare_main(int argc UNUSED_PARAM, char **argv)
+{
+ int i;
+ unsigned int opts;
+ int unsflags;
+ uintptr_t need_mount;
+ const char *proc_mnt_target;
+ const char *prop_str;
+ const char *setgrp_str;
+ unsigned long prop_flags;
+ uid_t reuid = geteuid();
+ gid_t regid = getegid();
+ struct fd_pair fdp;
+ pid_t child = child; /* for compiler */
+ struct namespace_ctx ns_ctx_list[NS_COUNT];
+
+ memset(ns_ctx_list, 0, sizeof(ns_ctx_list));
+ proc_mnt_target = "/proc";
+ prop_str = PRIVATE_STR;
+ setgrp_str = NULL;
+
+ opt_complementary =
+ "\xf0""m" /* long opts (via their "fake chars") imply short opts */
+ ":\xf1""u"
+ ":\xf2""i"
+ ":\xf3""n"
+ ":\xf4""p"
+ ":\xf5""U"
+ ":ru" /* --map-root-user or -r implies -u */
+ ":\xfd""m" /* --mount-proc implies -m */
+ ;
+ applet_long_options = unshare_longopts;
+ opts = getopt32(argv, opt_str,
+ &proc_mnt_target, &prop_str, &setgrp_str,
+ &ns_ctx_list[NS_MNT_POS].path,
+ &ns_ctx_list[NS_UTS_POS].path,
+ &ns_ctx_list[NS_IPC_POS].path,
+ &ns_ctx_list[NS_NET_POS].path,
+ &ns_ctx_list[NS_PID_POS].path,
+ &ns_ctx_list[NS_USR_POS].path
+ );
+ argv += optind;
+ //bb_error_msg("opts:0x%x", opts);
+ //bb_error_msg("mount:%s", ns_ctx_list[NS_MNT_POS].path);
+ //bb_error_msg("proc_mnt_target:%s", proc_mnt_target);
+ //bb_error_msg("prop_str:%s", prop_str);
+ //bb_error_msg("setgrp_str:%s", setgrp_str);
+ //exit(1);
+
+ if (setgrp_str) {
+ if (strcmp(setgrp_str, "allow") == 0) {
+ if (opts & OPT_map_root) {
+ bb_error_msg_and_die(
+ "--setgroups=allow and --map-root-user "
+ "are mutually exclusive"
+ );
+ }
+ } else {
+ /* It's not "allow", must be "deny" */
+ if (strcmp(setgrp_str, "deny") != 0)
+ bb_error_msg_and_die("unrecognized: --%s=%s",
+ "setgroups", setgrp_str);
+ }
+ }
+
+ unsflags = 0;
+ need_mount = 0;
+ for (i = 0; i < NS_COUNT; i++) {
+ const struct namespace_descr *ns = &ns_list[i];
+ struct namespace_ctx *ns_ctx = &ns_ctx_list[i];
+
+ if (opts & (1 << i))
+ unsflags |= ns->flag;
+
+ need_mount |= (uintptr_t)(ns_ctx->path);
+ }
+ /* need_mount != 0 if at least one FILE was given */
+
+ prop_flags = MS_REC | MS_PRIVATE;
+ /* Silently ignore --propagation if --mount is not requested. */
+ if (opts & OPT_mount)
+ prop_flags = parse_propagation(prop_str);
+
+ /*
+ * Special case: if we were requested to unshare the mount namespace
+ * AND to make any namespace persistent (by bind mounting it) we need
+ * to spawn a child process which will wait for the parent to call
+ * unshare(), then mount parent's namespaces while still in the
+ * previous namespace.
+ */
+ fdp.wr = -1;
+ if (need_mount && (opts & OPT_mount)) {
+ /*
+ * Can't use getppid() in child, as we can be unsharing the
+ * pid namespace.
+ */
+ pid_t ppid = getpid();
+
+ xpiped_pair(fdp);
+
+ child = xfork();
+ if (child == 0) {
+ /* Child */
+ close(fdp.wr);
+
+ /* Wait until parent calls unshare() */
+ read(fdp.rd, ns_ctx_list, 1); /* ...using bogus buffer */
+ /*close(fdp.rd);*/
+
+ /* Mount parent's unshared namespaces. */
+ mount_namespaces(ppid, ns_ctx_list);
+ return EXIT_SUCCESS;
+ }
+ /* Parent continues */
+ }
+
+ if (unshare(unsflags) != 0)
+ bb_perror_msg_and_die("unshare(0x%x)", unsflags);
+
+ if (fdp.wr >= 0) {
+ close(fdp.wr); /* Release child */
+ close(fdp.rd); /* should close fd, to not confuse exec'ed PROG */
+ }
+
+ if (need_mount) {
+ /* Wait for the child to finish mounting the namespaces. */
+ if (opts & OPT_mount) {
+ int exit_status = wait_for_exitstatus(child);
+ if (WIFEXITED(exit_status) &&
+ WEXITSTATUS(exit_status) != EXIT_SUCCESS)
+ return WEXITSTATUS(exit_status);
+ } else {
+ /*
+ * Regular way - we were requested to mount some other
+ * namespaces: mount them after the call to unshare().
+ */
+ mount_namespaces(getpid(), ns_ctx_list);
+ }
+ }
+
+ /*
+ * When we're unsharing the pid namespace, it's not the process that
+ * calls unshare() that is put into the new namespace, but its first
+ * child. The user may want to use this option to spawn a new process
+ * that'll become PID 1 in this new namespace.
+ */
+ if (opts & OPT_fork) {
+ xvfork_parent_waits_and_exits();
+ /* Child continues */
+ }
+
+ if (opts & OPT_map_root) {
+ char uidmap_buf[sizeof("%u 0 1") + sizeof(int)*3];
+
+ /*
+ * Since Linux 3.19 unprivileged writing of /proc/self/gid_map
+ * has been disabled unless /proc/self/setgroups is written
+ * first to permanently disable the ability to call setgroups
+ * in that user namespace.
+ */
+ xopen_xwrite_close(PATH_PROC_SETGROUPS, "deny");
+ sprintf(uidmap_buf, "%u 0 1", (unsigned)reuid);
+ xopen_xwrite_close(PATH_PROC_UIDMAP, uidmap_buf);
+ sprintf(uidmap_buf, "%u 0 1", (unsigned)regid);
+ xopen_xwrite_close(PATH_PROC_GIDMAP, uidmap_buf);
+ } else
+ if (setgrp_str) {
+ /* Write "allow" or "deny" */
+ xopen_xwrite_close(PATH_PROC_SETGROUPS, setgrp_str);
+ }
+
+ if (opts & OPT_mount) {
+ mount_or_die("none", "/", NULL, prop_flags);
+ }
+
+ if (opts & OPT_mount_proc) {
+ /*
+ * When creating a new pid namespace, we might want the pid
+ * subdirectories in /proc to remain consistent with the new
+ * process IDs. Without --mount-proc the pids in /proc would
+ * still reflect the old pid namespace. This is why we make
+ * /proc private here and then do a fresh mount.
+ */
+ mount_or_die("none", proc_mnt_target, NULL, MS_PRIVATE | MS_REC);
+ mount_or_die("proc", proc_mnt_target, "proc", MS_NOSUID | MS_NOEXEC | MS_NODEV);
+ }
+
+ exec_prog_or_SHELL(argv);
+}
diff --git a/release/src/router/busybox/util-linux/volume_id/Config.src b/release/src/router/busybox/util-linux/volume_id/Config.src
new file mode 100644
index 0000000000..ac208c9ccb
--- /dev/null
+++ b/release/src/router/busybox/util-linux/volume_id/Config.src
@@ -0,0 +1,15 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+config VOLUMEID
+ bool #No description makes it a hidden option
+ default n
+
+menu "Filesystem/Volume identification"
+ depends on VOLUMEID
+
+INSERT
+
+endmenu
diff --git a/release/src/router/busybox/util-linux/volume_id/Kbuild.src b/release/src/router/busybox/util-linux/volume_id/Kbuild.src
index 430d2a75d5..6b4fb74700 100644
--- a/release/src/router/busybox/util-linux/volume_id/Kbuild.src
+++ b/release/src/router/busybox/util-linux/volume_id/Kbuild.src
@@ -7,40 +7,3 @@
lib-y:=
INSERT
-
-lib-$(CONFIG_BLKID) += get_devname.o
-lib-$(CONFIG_FINDFS) += get_devname.o
-lib-$(CONFIG_FEATURE_MOUNT_LABEL) += get_devname.o
-
-lib-$(CONFIG_VOLUMEID) += volume_id.o util.o util2.o
-lib-$(CONFIG_FEATURE_VOLUMEID_BTRFS) += btrfs.o
-lib-$(CONFIG_FEATURE_VOLUMEID_EXT) += ext.o
-lib-$(CONFIG_FEATURE_VOLUMEID_FAT) += fat.o
-lib-$(CONFIG_FEATURE_VOLUMEID_HFS) += hfs.o
-### lib-$(CONFIG_FEATURE_VOLUMEID_HIGHPOINTRAID) += highpoint.o
-### lib-$(CONFIG_FEATURE_VOLUMEID_ISWRAID) += isw_raid.o
-### lib-$(CONFIG_FEATURE_VOLUMEID_LSIRAID) += lsi_raid.o
-### lib-$(CONFIG_FEATURE_VOLUMEID_VIARAID) += via_raid.o
-### lib-$(CONFIG_FEATURE_VOLUMEID_SILICONRAID) += silicon_raid.o
-### lib-$(CONFIG_FEATURE_VOLUMEID_NVIDIARAID) += nvidia_raid.o
-### lib-$(CONFIG_FEATURE_VOLUMEID_PROMISERAID) += promise_raid.o
-lib-$(CONFIG_FEATURE_VOLUMEID_ISO9660) += iso9660.o
-lib-$(CONFIG_FEATURE_VOLUMEID_JFS) += jfs.o
-lib-$(CONFIG_FEATURE_VOLUMEID_LINUXRAID) += linux_raid.o
-lib-$(CONFIG_FEATURE_VOLUMEID_LINUXSWAP) += linux_swap.o
-### lib-$(CONFIG_FEATURE_VOLUMEID_LVM) += lvm.o
-### lib-$(CONFIG_FEATURE_VOLUMEID_MAC) += mac.o
-### lib-$(CONFIG_FEATURE_VOLUMEID_MSDOS) += msdos.o
-lib-$(CONFIG_FEATURE_VOLUMEID_NTFS) += ntfs.o
-lib-$(CONFIG_FEATURE_VOLUMEID_EXFAT) += exfat.o
-lib-$(CONFIG_FEATURE_VOLUMEID_REISERFS) += reiserfs.o
-lib-$(CONFIG_FEATURE_VOLUMEID_UDF) += udf.o
-### lib-$(CONFIG_FEATURE_VOLUMEID_UFS) += ufs.o
-lib-$(CONFIG_FEATURE_VOLUMEID_XFS) += xfs.o
-lib-$(CONFIG_FEATURE_VOLUMEID_CRAMFS) += cramfs.o
-### lib-$(CONFIG_FEATURE_VOLUMEID_HPFS) += hpfs.o
-lib-$(CONFIG_FEATURE_VOLUMEID_ROMFS) += romfs.o
-lib-$(CONFIG_FEATURE_VOLUMEID_SYSV) += sysv.o
-### lib-$(CONFIG_FEATURE_VOLUMEID_MINIX) += minix.o
-lib-$(CONFIG_FEATURE_VOLUMEID_LUKS) += luks.o
-lib-$(CONFIG_FEATURE_VOLUMEID_OCFS2) += ocfs2.o
diff --git a/release/src/router/busybox/util-linux/volume_id/bcache.c b/release/src/router/busybox/util-linux/volume_id/bcache.c
new file mode 100644
index 0000000000..fd40eb0818
--- /dev/null
+++ b/release/src/router/busybox/util-linux/volume_id/bcache.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2013 Rolf Fokkens <rolf@fokkens.nl>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ *
+ * Based on code fragments from bcache-tools by Kent Overstreet:
+ * http://evilpiepirate.org/git/bcache-tools.git
+ */
+
+//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_BCACHE) += bcache.o
+
+//config:
+//config:config FEATURE_VOLUMEID_BCACHE
+//config: bool "bcache filesystem"
+//config: default y
+//config: depends on VOLUMEID
+//config: help
+//config: TODO
+//config:
+
+#include "volume_id_internal.h"
+
+#define SB_LABEL_SIZE 32
+#define SB_JOURNAL_BUCKETS 256U
+
+static const char bcache_magic[] ALIGN1 = {
+ 0xc6, 0x85, 0x73, 0xf6, 0x4e, 0x1a, 0x45, 0xca,
+ 0x82, 0x65, 0xf5, 0x7f, 0x48, 0xba, 0x6d, 0x81
+};
+
+struct bcache_super_block {
+ uint64_t csum;
+ uint64_t offset; /* sector where this sb was written */
+ uint64_t version;
+
+ uint8_t magic[16];
+
+ uint8_t uuid[16];
+ union {
+ uint8_t set_uuid[16];
+ uint64_t set_magic;
+ };
+ uint8_t label[SB_LABEL_SIZE];
+
+ uint64_t flags;
+ uint64_t seq;
+ uint64_t pad[8];
+
+ union {
+ struct {
+ /* Cache devices */
+ uint64_t nbuckets; /* device size */
+
+ uint16_t block_size; /* sectors */
+ uint16_t bucket_size; /* sectors */
+
+ uint16_t nr_in_set;
+ uint16_t nr_this_dev;
+ };
+ struct {
+ /* Backing devices */
+ uint64_t data_offset;
+
+ /*
+ * block_size from the cache device section is still used by
+ * backing devices, so don't add anything here until we fix
+ * things to not need it for backing devices anymore
+ */
+ };
+ };
+
+ uint32_t last_mount; /* time_t */
+
+ uint16_t first_bucket;
+ union {
+ uint16_t njournal_buckets;
+ uint16_t keys;
+ };
+ uint64_t d[SB_JOURNAL_BUCKETS]; /* journal buckets */
+};
+
+/* magic string */
+#define BCACHE_SB_MAGIC bcache_magic
+/* magic string len */
+#define BCACHE_SB_MAGIC_LEN sizeof (bcache_magic)
+/* super block offset */
+#define BCACHE_SB_OFF 0x1000
+/* supper block offset in kB */
+#define BCACHE_SB_KBOFF (BCACHE_SB_OFF >> 10)
+/* magic string offset within super block */
+#define BCACHE_SB_MAGIC_OFF offsetof (struct bcache_super_block, magic)
+
+int FAST_FUNC volume_id_probe_bcache(struct volume_id *id /*,uint64_t off*/)
+{
+ struct bcache_super_block *sb;
+
+ sb = volume_id_get_buffer(id, BCACHE_SB_OFF, sizeof(*sb));
+ if (sb == NULL)
+ return -1;
+
+ if (memcmp(sb->magic, BCACHE_SB_MAGIC, BCACHE_SB_MAGIC_LEN) != 0)
+ return -1;
+
+ volume_id_set_label_string(id, sb->label, SB_LABEL_SIZE);
+ volume_id_set_uuid(id, sb->uuid, UUID_DCE);
+ IF_FEATURE_BLKID_TYPE(id->type = "bcache";)
+
+ return 0;
+}
diff --git a/release/src/router/busybox/util-linux/volume_id/btrfs.c b/release/src/router/busybox/util-linux/volume_id/btrfs.c
index 777b809236..e4dddf26d5 100644
--- a/release/src/router/busybox/util-linux/volume_id/btrfs.c
+++ b/release/src/router/busybox/util-linux/volume_id/btrfs.c
@@ -19,6 +19,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_BTRFS) += btrfs.o
+
+//config:
+//config:config FEATURE_VOLUMEID_BTRFS
+//config: bool "btrfs filesystem"
+//config: default y
+//config: depends on VOLUMEID
+//config: help
+//config: TODO
+//config:
+
#include "volume_id_internal.h"
#define BTRFS_UUID_SIZE 16
@@ -102,6 +113,7 @@ int FAST_FUNC volume_id_probe_btrfs(struct volume_id *id /*,uint64_t off*/)
// N.B.: btrfs natively supports 256 (>VOLUME_ID_LABEL_SIZE) size labels
volume_id_set_label_string(id, sb->label, VOLUME_ID_LABEL_SIZE);
volume_id_set_uuid(id, sb->fsid, UUID_DCE);
+ IF_FEATURE_BLKID_TYPE(id->type = "btrfs";)
return 0;
}
diff --git a/release/src/router/busybox/util-linux/volume_id/cramfs.c b/release/src/router/busybox/util-linux/volume_id/cramfs.c
index 28e9970431..aeb7f20ac8 100644
--- a/release/src/router/busybox/util-linux/volume_id/cramfs.c
+++ b/release/src/router/busybox/util-linux/volume_id/cramfs.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_CRAMFS) += cramfs.o
+
+//config:
+//config:config FEATURE_VOLUMEID_CRAMFS
+//config: bool "cramfs filesystem"
+//config: default y
+//config: depends on VOLUMEID
+//config: help
+//config: TODO
+//config:
+
#include "volume_id_internal.h"
struct cramfs_super {
diff --git a/release/src/router/busybox/util-linux/volume_id/exfat.c b/release/src/router/busybox/util-linux/volume_id/exfat.c
index bd194a3fb1..c3aa368043 100644
--- a/release/src/router/busybox/util-linux/volume_id/exfat.c
+++ b/release/src/router/busybox/util-linux/volume_id/exfat.c
@@ -18,6 +18,19 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_EXFAT) += exfat.o
+
+//config:
+//config:config FEATURE_VOLUMEID_EXFAT
+//config: bool "exFAT filesystem"
+//config: default y
+//config: depends on VOLUMEID
+//config: help
+//config: exFAT (extended FAT) is a proprietary file system designed especially
+//config: for flash drives. It has many features from NTFS, but with less
+//config: overhead. exFAT is used on most SDXC cards for consumer electronics.
+//config:
+
#include "volume_id_internal.h"
#define EXFAT_SB_OFFSET 0
@@ -100,7 +113,7 @@ int FAST_FUNC volume_id_probe_exfat(struct volume_id *id /*,uint64_t off*/)
// The Root Directory may hold an unlimited number of entries,
// so we do not want to check all. Usually label and GUID
// are in the beginning, but there are no guarantees.
- need_lbl_guid = (1 << 0); /* check Volume Label Directory Entry only. */
+ need_lbl_guid = (1 << 0) | (1 << 1);
for (count = 0; count < EXFAT_MAX_DIR_ENTRIES; count++) {
de = volume_id_get_buffer(id, root_dir_off + (count * EXFAT_DIR_ENTRY_SZ), EXFAT_DIR_ENTRY_SZ);
if (de == NULL)
@@ -125,6 +138,6 @@ int FAST_FUNC volume_id_probe_exfat(struct volume_id *id /*,uint64_t off*/)
break;
}
- //IF_FEATURE_BLKID_TYPE(id->type = "exfat";)
+ IF_FEATURE_BLKID_TYPE(id->type = "exfat";)
return 0;
}
diff --git a/release/src/router/busybox/util-linux/volume_id/ext.c b/release/src/router/busybox/util-linux/volume_id/ext.c
index aa23d1ebf1..df39d93422 100644
--- a/release/src/router/busybox/util-linux/volume_id/ext.c
+++ b/release/src/router/busybox/util-linux/volume_id/ext.c
@@ -18,70 +18,21 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "volume_id_internal.h"
-
-struct ext2_super_block {
- uint32_t inodes_count;
- uint32_t blocks_count;
- uint32_t r_blocks_count;
- uint32_t free_blocks_count;
- uint32_t free_inodes_count;
- uint32_t first_data_block;
- uint32_t log_block_size;
- uint32_t dummy3[7];
- uint8_t magic[2];
- uint16_t state;
- uint32_t dummy5[8];
- uint32_t feature_compat;
- uint32_t feature_incompat;
- uint32_t feature_ro_compat;
- uint8_t uuid[16];
- uint8_t volume_name[16];
-} PACKED;
-
-#define EXT_SUPERBLOCK_OFFSET 0x400
-
-/* for s_flags */
-#define EXT2_FLAGS_TEST_FILESYS 0x0004
+//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_EXT) += ext.o
-/* for s_feature_compat */
-#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
+//config:
+//config:config FEATURE_VOLUMEID_EXT
+//config: bool "Ext filesystem"
+//config: default y
+//config: depends on VOLUMEID
+//config: help
+//config: TODO
+//config:
-/* for s_feature_ro_compat */
-#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
-#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
-#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
-#define EXT4_FEATURE_RO_COMPAT_HUGE_FILE 0x0008
-#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010
-#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020
-#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040
-
-/* for s_feature_incompat */
-#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
-#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004
-#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008
-#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010
-#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
-#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080
-#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
-#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
-
-#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
- EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
-#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \
- EXT2_FEATURE_INCOMPAT_META_BG)
-#define EXT2_FEATURE_INCOMPAT_UNSUPPORTED ~EXT2_FEATURE_INCOMPAT_SUPP
-#define EXT2_FEATURE_RO_COMPAT_UNSUPPORTED ~EXT2_FEATURE_RO_COMPAT_SUPP
+#include "volume_id_internal.h"
+#include "bb_e2fs_defs.h"
-#define EXT3_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
- EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
-#define EXT3_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \
- EXT3_FEATURE_INCOMPAT_RECOVER| \
- EXT2_FEATURE_INCOMPAT_META_BG)
-#define EXT3_FEATURE_INCOMPAT_UNSUPPORTED ~EXT3_FEATURE_INCOMPAT_SUPP
-#define EXT3_FEATURE_RO_COMPAT_UNSUPPORTED ~EXT3_FEATURE_RO_COMPAT_SUPP
+#define EXT_SUPERBLOCK_OFFSET 0x400
int FAST_FUNC volume_id_probe_ext(struct volume_id *id /*,uint64_t off*/)
{
@@ -94,24 +45,24 @@ int FAST_FUNC volume_id_probe_ext(struct volume_id *id /*,uint64_t off*/)
if (es == NULL)
return -1;
- if (es->magic[0] != 0123 || es->magic[1] != 0357) {
+ if (es->s_magic != cpu_to_le16(EXT2_SUPER_MAGIC)) {
dbg("ext: no magic found");
return -1;
}
// volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
// volume_id_set_label_raw(id, es->volume_name, 16);
- volume_id_set_label_string(id, es->volume_name, 16);
- volume_id_set_uuid(id, es->uuid, UUID_DCE);
+ volume_id_set_label_string(id, (void*)es->s_volume_name, 16);
+ volume_id_set_uuid(id, es->s_uuid, UUID_DCE);
dbg("ext: label '%s' uuid '%s'", id->label, id->uuid);
#if ENABLE_FEATURE_BLKID_TYPE
- if ((es->feature_ro_compat & cpu_to_le32(EXT4_FEATURE_RO_COMPAT_HUGE_FILE | EXT4_FEATURE_RO_COMPAT_DIR_NLINK))
- || (es->feature_incompat & cpu_to_le32(EXT4_FEATURE_INCOMPAT_EXTENTS | EXT4_FEATURE_INCOMPAT_64BIT))
+ if ((es->s_feature_ro_compat & cpu_to_le32(EXT4_FEATURE_RO_COMPAT_HUGE_FILE | EXT4_FEATURE_RO_COMPAT_DIR_NLINK))
+ || (es->s_feature_incompat & cpu_to_le32(EXT4_FEATURE_INCOMPAT_EXTENTS | EXT4_FEATURE_INCOMPAT_64BIT))
) {
id->type = "ext4";
}
- else if (es->feature_compat & cpu_to_le32(EXT3_FEATURE_COMPAT_HAS_JOURNAL))
+ else if (es->s_feature_compat & cpu_to_le32(EXT3_FEATURE_COMPAT_HAS_JOURNAL))
id->type = "ext3";
else
id->type = "ext2";
diff --git a/release/src/router/busybox/util-linux/volume_id/f2fs.c b/release/src/router/busybox/util-linux/volume_id/f2fs.c
new file mode 100644
index 0000000000..bf0b662784
--- /dev/null
+++ b/release/src/router/busybox/util-linux/volume_id/f2fs.c
@@ -0,0 +1,95 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2012 S-G Bergh <sgb@systemasis.org>
+ *
+ * Licensed under GPLv2, see file LICENSE in this source tree.
+ */
+
+//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_F2FS) += f2fs.o
+
+//config:
+//config:config FEATURE_VOLUMEID_F2FS
+//config: bool "f2fs filesystem"
+//config: default y
+//config: depends on VOLUMEID
+//config: help
+//config: F2FS (aka Flash-Friendly File System) is a log-structured file system,
+//config: which is adapted to newer forms of storage. F2FS also remedies some
+//config: known issues of the older log structured file systems, such as high
+//config: cleaning overhead.
+//config:
+
+#include "volume_id_internal.h"
+
+#define F2FS_MAGIC 0xF2F52010 // F2FS Magic Number
+#define F2FS_UUID_SIZE 16
+#define F2FS_LABEL_SIZE 512
+#define F2FS_LABEL_BYTES 1024
+#define F2FS_SB1_OFFSET 0x400 // offset for 1:st super block
+/*
+#define F2FS_SB2_OFFSET 0x1400 // offset for 2:nd super block
+*/
+
+struct f2fs_super_block { // According to version 1.1
+/* 0x00 */ uint32_t magic; // Magic Number
+/* 0x04 */ uint16_t major_ver; // Major Version
+/* 0x06 */ uint16_t minor_ver; // Minor Version
+/* 0x08 */ uint32_t log_sectorsize; // log2 sector size in bytes
+/* 0x0C */ uint32_t log_sectors_per_block; // log2 # of sectors per block
+/* 0x10 */ uint32_t log_blocksize; // log2 block size in bytes
+/* 0x14 */ uint32_t log_blocks_per_seg; // log2 # of blocks per segment
+/* 0x18 */ uint32_t segs_per_sec; // # of segments per section
+/* 0x1C */ uint32_t secs_per_zone; // # of sections per zone
+/* 0x20 */ uint32_t checksum_offset; // checksum offset inside super block
+/* 0x24 */ uint64_t block_count; // total # of user blocks
+/* 0x2C */ uint32_t section_count; // total # of sections
+/* 0x30 */ uint32_t segment_count; // total # of segments
+/* 0x34 */ uint32_t segment_count_ckpt; // # of segments for checkpoint
+/* 0x38 */ uint32_t segment_count_sit; // # of segments for SIT
+/* 0x3C */ uint32_t segment_count_nat; // # of segments for NAT
+/* 0x40 */ uint32_t segment_count_ssa; // # of segments for SSA
+/* 0x44 */ uint32_t segment_count_main; // # of segments for main area
+/* 0x48 */ uint32_t segment0_blkaddr; // start block address of segment 0
+/* 0x4C */ uint32_t cp_blkaddr; // start block address of checkpoint
+/* 0x50 */ uint32_t sit_blkaddr; // start block address of SIT
+/* 0x54 */ uint32_t nat_blkaddr; // start block address of NAT
+/* 0x58 */ uint32_t ssa_blkaddr; // start block address of SSA
+/* 0x5C */ uint32_t main_blkaddr; // start block address of main area
+/* 0x60 */ uint32_t root_ino; // root inode number
+/* 0x64 */ uint32_t node_ino; // node inode number
+/* 0x68 */ uint32_t meta_ino; // meta inode number
+/* 0x6C */ uint8_t uuid[F2FS_UUID_SIZE]; // 128-bit uuid for volume
+/* 0x7C */ uint16_t volume_name[F2FS_LABEL_SIZE]; // volume name
+// /* 0x47C */ uint32_t extension_count; // # of extensions below
+// /* 0x480 */ uint8_t extension_list[64][8]; // extension array
+} PACKED;
+
+
+int FAST_FUNC volume_id_probe_f2fs(struct volume_id *id /*,uint64_t off*/)
+{
+ struct f2fs_super_block *sb;
+
+ // Go for primary super block (ignore second sb)
+ dbg("f2fs: probing at offset 0x%x", F2FS_SB1_OFFSET);
+ sb = volume_id_get_buffer(id, F2FS_SB1_OFFSET, sizeof(*sb));
+
+ if (!sb)
+ return -1;
+
+ if (sb->magic != cpu_to_le32(F2FS_MAGIC))
+ return -1;
+
+ IF_FEATURE_BLKID_TYPE(id->type = "f2fs");
+
+ // For version 1.0 we don't know sb structure and can't set label/uuid
+ if (sb->major_ver == cpu_to_le16(1) && sb->minor_ver == cpu_to_le16(0))
+ return 0;
+
+ volume_id_set_label_unicode16(id, (uint8_t *)sb->volume_name,
+ LE, MIN(F2FS_LABEL_BYTES, VOLUME_ID_LABEL_SIZE));
+
+ volume_id_set_uuid(id, sb->uuid, UUID_DCE);
+
+ return 0;
+}
diff --git a/release/src/router/busybox/util-linux/volume_id/fat.c b/release/src/router/busybox/util-linux/volume_id/fat.c
index 904fbb201d..476d500a68 100644
--- a/release/src/router/busybox/util-linux/volume_id/fat.c
+++ b/release/src/router/busybox/util-linux/volume_id/fat.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_FAT) += fat.o
+
+//config:
+//config:config FEATURE_VOLUMEID_FAT
+//config: bool "fat filesystem"
+//config: default y
+//config: depends on VOLUMEID
+//config: help
+//config: TODO
+//config:
+
#include "volume_id_internal.h"
/* linux/msdos_fs.h says: */
diff --git a/release/src/router/busybox/util-linux/volume_id/get_devname.c b/release/src/router/busybox/util-linux/volume_id/get_devname.c
index 3390e7ec43..6b97df1138 100644
--- a/release/src/router/busybox/util-linux/volume_id/get_devname.c
+++ b/release/src/router/busybox/util-linux/volume_id/get_devname.c
@@ -7,6 +7,11 @@
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+
+//kbuild:lib-$(CONFIG_BLKID) += get_devname.o
+//kbuild:lib-$(CONFIG_FINDFS) += get_devname.o
+//kbuild:lib-$(CONFIG_FEATURE_MOUNT_LABEL) += get_devname.o
+
#include <sys/mount.h> /* BLKGETSIZE64 */
#if !defined(BLKGETSIZE64)
# define BLKGETSIZE64 _IOR(0x12,114,size_t)
@@ -15,7 +20,7 @@
static struct uuidCache_s {
struct uuidCache_s *next;
- dev_t devno;
+// int major, minor;
char *device;
char *label;
char *uc_uuid; /* prefix makes it easier to grep for */
@@ -25,8 +30,8 @@ static struct uuidCache_s {
#if !ENABLE_FEATURE_BLKID_TYPE
#define get_label_uuid(fd, label, uuid, type) \
get_label_uuid(fd, label, uuid)
-#define uuidcache_addentry(device, devno, label, uuid, type) \
- uuidcache_addentry(device, devno, label, uuid)
+#define uuidcache_addentry(device, label, uuid, type) \
+ uuidcache_addentry(device, label, uuid)
#endif
/* Returns !0 on error.
@@ -49,7 +54,11 @@ get_label_uuid(int fd, char **label, char **uuid, const char **type)
if (volume_id_probe_all(vid, /*0,*/ size) != 0)
goto ret;
- if (vid->label[0] != '\0' || vid->uuid[0] != '\0') {
+ if (vid->label[0] != '\0' || vid->uuid[0] != '\0'
+#if ENABLE_FEATURE_BLKID_TYPE
+ || vid->type != NULL
+#endif
+ ) {
*label = xstrndup(vid->label, sizeof(vid->label));
*uuid = xstrndup(vid->uuid, sizeof(vid->uuid));
#if ENABLE_FEATURE_BLKID_TYPE
@@ -67,7 +76,7 @@ get_label_uuid(int fd, char **label, char **uuid, const char **type)
/* NB: we take ownership of (malloc'ed) label and uuid */
static void
-uuidcache_addentry(char *device, dev_t devno, char *label, char *uuid, const char *type)
+uuidcache_addentry(char *device, /*int major, int minor,*/ char *label, char *uuid, const char *type)
{
struct uuidCache_s *last;
@@ -80,7 +89,8 @@ uuidcache_addentry(char *device, dev_t devno, char *label, char *uuid, const cha
last = last->next;
}
/*last->next = NULL; - xzalloc did it*/
- last->devno = devno;
+// last->major = major;
+// last->minor = minor;
last->device = device;
last->label = label;
last->uc_uuid = uuid;
@@ -108,7 +118,7 @@ uuidcache_check_device(const char *device,
if (major(statbuf->st_rdev) == 2)
return TRUE;
- add_to_uuid_cache(device, statbuf->st_rdev);
+ add_to_uuid_cache(device);
return TRUE;
}
@@ -142,10 +152,10 @@ uuidcache_init(int scan_devices)
#define UUID 1
#define VOL 2
-#define DEVNO 3
+#ifdef UNUSED
static char *
-get_spec_by_x(int n, const char *t, dev_t *devnoPtr)
+get_spec_by_x(int n, const char *t, int *majorPtr, int *minorPtr)
{
struct uuidCache_s *uc;
@@ -153,28 +163,65 @@ get_spec_by_x(int n, const char *t, dev_t *devnoPtr)
while (uc) {
switch (n) {
case UUID:
- /* case of hex numbers doesn't matter */
- if (strcasecmp(t, uc->uc_uuid) == 0)
- goto found;
+ if (strcmp(t, uc->uc_uuid) == 0) {
+ *majorPtr = uc->major;
+ *minorPtr = uc->minor;
+ return uc->device;
+ }
break;
case VOL:
- if (uc->label[0] && strcmp(t, uc->label) == 0)
- goto found;
- break;
- case DEVNO:
- if (uc->devno == (*devnoPtr))
- goto found;
+ if (strcmp(t, uc->label) == 0) {
+ *majorPtr = uc->major;
+ *minorPtr = uc->minor;
+ return uc->device;
+ }
break;
}
uc = uc->next;
}
return NULL;
+}
+
+static unsigned char
+fromhex(char c)
+{
+ if (isdigit(c))
+ return (c - '0');
+ return ((c|0x20) - 'a' + 10);
+}
+
+static char *
+get_spec_by_uuid(const char *s, int *major, int *minor)
+{
+ unsigned char uuid[16];
+ int i;
+
+ if (strlen(s) != 36 || s[8] != '-' || s[13] != '-'
+ || s[18] != '-' || s[23] != '-'
+ ) {
+ goto bad_uuid;
+ }
+ for (i = 0; i < 16; i++) {
+ if (*s == '-')
+ s++;
+ if (!isxdigit(s[0]) || !isxdigit(s[1]))
+ goto bad_uuid;
+ uuid[i] = ((fromhex(s[0]) << 4) | fromhex(s[1]));
+ s += 2;
+ }
+ return get_spec_by_x(UUID, (char *)uuid, major, minor);
-found:
- if (devnoPtr)
- *devnoPtr = uc->devno;
- return xstrdup(uc->device);
+ bad_uuid:
+ fprintf(stderr, _("mount: bad UUID"));
+ return 0;
+}
+
+static char *
+get_spec_by_volume_label(const char *s, int *major, int *minor)
+{
+ return get_spec_by_x(VOL, s, major, minor);
}
+#endif // UNUSED
/* Used by blkid */
void display_uuid_cache(int scan_devices)
@@ -197,7 +244,7 @@ void display_uuid_cache(int scan_devices)
}
}
-int add_to_uuid_cache(const char *device, dev_t devno)
+int add_to_uuid_cache(const char *device)
{
char *uuid = uuid; /* for compiler */
char *label = label;
@@ -213,46 +260,57 @@ int add_to_uuid_cache(const char *device, dev_t devno)
/* get_label_uuid() closes fd in all cases (success & failure) */
if (get_label_uuid(fd, &label, &uuid, &type) == 0) {
/* uuidcache_addentry() takes ownership of all four params */
- uuidcache_addentry(xstrdup(device), devno, label, uuid, type);
+ uuidcache_addentry(xstrdup(device), /*ma, mi,*/ label, uuid, type);
return 1;
}
return 0;
}
-/* Used by mount and findfs & old_e2fsprogs */
+/* Used by mount and findfs */
char *get_devname_from_label(const char *spec)
{
- return get_spec_by_x(VOL, spec, NULL);
+ struct uuidCache_s *uc;
+
+ uc = uuidcache_init(/*scan_devices:*/ 1);
+ while (uc) {
+ if (uc->label[0] && strcmp(spec, uc->label) == 0) {
+ return xstrdup(uc->device);
+ }
+ uc = uc->next;
+ }
+ return NULL;
}
char *get_devname_from_uuid(const char *spec)
{
- return get_spec_by_x(UUID, spec, NULL);
-}
+ struct uuidCache_s *uc;
-char *get_devname_from_device(dev_t dev)
-{
- return get_spec_by_x(DEVNO, NULL, &dev);
+ uc = uuidcache_init(/*scan_devices:*/ 1);
+ while (uc) {
+ /* case of hex numbers doesn't matter */
+ if (strcasecmp(spec, uc->uc_uuid) == 0) {
+ return xstrdup(uc->device);
+ }
+ uc = uc->next;
+ }
+ return NULL;
}
int resolve_mount_spec(char **fsname)
{
- char *tmp = NULL;
+ char *tmp = *fsname;
- if (strncmp(*fsname, "UUID=", 5) == 0)
+ if (is_prefixed_with(*fsname, "UUID="))
tmp = get_devname_from_uuid(*fsname + 5);
- else if (strncmp(*fsname, "LABEL=", 6) == 0)
+ else if (is_prefixed_with(*fsname, "LABEL="))
tmp = get_devname_from_label(*fsname + 6);
- else {
- *fsname = xstrdup(*fsname);
- return 0; /* no UUID= or LABEL= prefix found */
- }
- if (!tmp)
- return -2; /* device defined by UUID= or LABEL= wasn't found */
+ if (tmp == *fsname)
+ return 0; /* no UUID= or LABEL= prefix found */
- *fsname = tmp;
+ if (tmp)
+ *fsname = tmp;
return 1;
}
diff --git a/release/src/router/busybox/util-linux/volume_id/hfs.c b/release/src/router/busybox/util-linux/volume_id/hfs.c
index f3f19dba71..8d34aaf68d 100644
--- a/release/src/router/busybox/util-linux/volume_id/hfs.c
+++ b/release/src/router/busybox/util-linux/volume_id/hfs.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_HFS) += hfs.o
+
+//config:
+//config:config FEATURE_VOLUMEID_HFS
+//config: bool "hfs filesystem"
+//config: default y
+//config: depends on VOLUMEID
+//config: help
+//config: TODO
+//config:
+
#include "volume_id_internal.h"
struct hfs_finder_info{
@@ -131,6 +142,27 @@ struct hfsplus_vol_header {
#define HFS_NODE_LEAF 0xff
#define HFSPLUS_POR_CNID 1
+static void FAST_FUNC hfs_set_uuid(struct volume_id *id, const uint8_t *hfs_id)
+{
+#define hfs_id_len 8
+ md5_ctx_t md5c;
+ uint8_t uuid[16];
+ unsigned i;
+
+ for (i = 0; i < hfs_id_len; i++)
+ if (hfs_id[i] != 0)
+ goto do_md5;
+ return;
+ do_md5:
+ md5_begin(&md5c);
+ md5_hash(&md5c, "\263\342\17\71\362\222\21\326\227\244\0\60\145\103\354\254", 16);
+ md5_hash(&md5c, hfs_id, hfs_id_len);
+ md5_end(&md5c, uuid);
+ uuid[6] = 0x30 | (uuid[6] & 0x0f);
+ uuid[8] = 0x80 | (uuid[8] & 0x3f);
+ volume_id_set_uuid(id, uuid, UUID_DCE);
+}
+
int FAST_FUNC volume_id_probe_hfs_hfsplus(struct volume_id *id /*,uint64_t off*/)
{
uint64_t off = 0;
@@ -193,7 +225,7 @@ int FAST_FUNC volume_id_probe_hfs_hfsplus(struct volume_id *id /*,uint64_t off*/
volume_id_set_label_string(id, hfs->label, hfs->label_len) ;
}
- volume_id_set_uuid(id, hfs->finder_info.id, UUID_HFS);
+ hfs_set_uuid(id, hfs->finder_info.id);
// volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
IF_FEATURE_BLKID_TYPE(id->type = "hfs";)
@@ -207,7 +239,7 @@ int FAST_FUNC volume_id_probe_hfs_hfsplus(struct volume_id *id /*,uint64_t off*/
return -1;
hfsplus:
- volume_id_set_uuid(id, hfsplus->finder_info.id, UUID_HFS);
+ hfs_set_uuid(id, hfsplus->finder_info.id);
blocksize = be32_to_cpu(hfsplus->blocksize);
dbg("blocksize %u", blocksize);
@@ -286,7 +318,7 @@ int FAST_FUNC volume_id_probe_hfs_hfsplus(struct volume_id *id /*,uint64_t off*/
found:
// volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
-// id->type = "hfsplus";
+ IF_FEATURE_BLKID_TYPE(id->type = "hfsplus";)
return 0;
}
diff --git a/release/src/router/busybox/util-linux/volume_id/iso9660.c b/release/src/router/busybox/util-linux/volume_id/iso9660.c
index 1d7693a9c5..3848de4531 100644
--- a/release/src/router/busybox/util-linux/volume_id/iso9660.c
+++ b/release/src/router/busybox/util-linux/volume_id/iso9660.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_ISO9660) += iso9660.o
+
+//config:
+//config:config FEATURE_VOLUMEID_ISO9660
+//config: bool "iso9660 filesystem"
+//config: default y
+//config: depends on VOLUMEID
+//config: help
+//config: TODO
+//config:
+
#include "volume_id_internal.h"
#define ISO_SUPERBLOCK_OFFSET 0x8000
diff --git a/release/src/router/busybox/util-linux/volume_id/jfs.c b/release/src/router/busybox/util-linux/volume_id/jfs.c
index 5333af2c38..a6eaff45b3 100644
--- a/release/src/router/busybox/util-linux/volume_id/jfs.c
+++ b/release/src/router/busybox/util-linux/volume_id/jfs.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_JFS) += jfs.o
+
+//config:
+//config:config FEATURE_VOLUMEID_JFS
+//config: bool "jfs filesystem"
+//config: default y
+//config: depends on VOLUMEID
+//config: help
+//config: TODO
+//config:
+
#include "volume_id_internal.h"
struct jfs_super_block {
diff --git a/release/src/router/busybox/util-linux/volume_id/linux_raid.c b/release/src/router/busybox/util-linux/volume_id/linux_raid.c
index 761e54f9f3..f20823a6ed 100644
--- a/release/src/router/busybox/util-linux/volume_id/linux_raid.c
+++ b/release/src/router/busybox/util-linux/volume_id/linux_raid.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_LINUXRAID) += linux_raid.o
+
+//config:
+//config:config FEATURE_VOLUMEID_LINUXRAID
+//config: bool "linuxraid"
+//config: default y
+//config: depends on VOLUMEID
+//config: help
+//config: TODO
+//config:
+
#include "volume_id_internal.h"
struct mdp_super_block {
@@ -69,9 +80,9 @@ int FAST_FUNC volume_id_probe_linux_raid(struct volume_id *id /*,uint64_t off*/,
volume_id_set_uuid(id, uuid, UUID_DCE);
// snprintf(id->type_version, sizeof(id->type_version)-1, "%u.%u.%u",
-// le32_to_cpu(mdp->major_version),
-// le32_to_cpu(mdp->minor_version),
-// le32_to_cpu(mdp->patch_version));
+// le32_to_cpu(mdp->major_version),
+// le32_to_cpu(mdp->minor_version),
+// le32_to_cpu(mdp->patch_version));
dbg("found raid signature");
// volume_id_set_usage(id, VOLUME_ID_RAID);
diff --git a/release/src/router/busybox/util-linux/volume_id/linux_swap.c b/release/src/router/busybox/util-linux/volume_id/linux_swap.c
index 1ee534ab0e..39470d48c4 100644
--- a/release/src/router/busybox/util-linux/volume_id/linux_swap.c
+++ b/release/src/router/busybox/util-linux/volume_id/linux_swap.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_LINUXSWAP) += linux_swap.o
+
+//config:
+//config:config FEATURE_VOLUMEID_LINUXSWAP
+//config: bool "linux swap filesystem"
+//config: default y
+//config: depends on VOLUMEID
+//config: help
+//config: TODO
+//config:
+
#include "volume_id_internal.h"
struct swap_header_v1_2 {
diff --git a/release/src/router/busybox/util-linux/volume_id/luks.c b/release/src/router/busybox/util-linux/volume_id/luks.c
index f9b3766722..21cb26f511 100644
--- a/release/src/router/busybox/util-linux/volume_id/luks.c
+++ b/release/src/router/busybox/util-linux/volume_id/luks.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_LUKS) += luks.o
+
+//config:
+//config:config FEATURE_VOLUMEID_LUKS
+//config: bool "luks filesystem"
+//config: default y
+//config: depends on VOLUMEID
+//config: help
+//config: TODO
+//config:
+
#include "volume_id_internal.h"
#define LUKS_MAGIC_L 6
@@ -29,7 +40,7 @@
#define LUKS_SALTSIZE 32
#define LUKS_NUMKEYS 8
-static const uint8_t LUKS_MAGIC[] = { 'L','U','K','S', 0xba, 0xbe };
+static const uint8_t LUKS_MAGIC[] ALIGN1 = { 'L','U','K','S', 0xba, 0xbe };
struct luks_phdr {
uint8_t magic[LUKS_MAGIC_L];
diff --git a/release/src/router/busybox/util-linux/volume_id/nilfs.c b/release/src/router/busybox/util-linux/volume_id/nilfs.c
new file mode 100644
index 0000000000..f3a9ef58d6
--- /dev/null
+++ b/release/src/router/busybox/util-linux/volume_id/nilfs.c
@@ -0,0 +1,116 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2012 S-G Bergh <sgb@systemasis.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_NILFS) += nilfs.o
+
+//config:
+//config:config FEATURE_VOLUMEID_NILFS
+//config: bool "nilfs filesystem"
+//config: default y
+//config: depends on VOLUMEID
+//config: help
+//config: NILFS is a New Implementation of a Log-Structured File System (LFS)
+//config: that supports continuous snapshots. This provides features like
+//config: versioning of the entire filesystem, restoration of files that
+//config: were deleted a few minutes ago. NILFS keeps consistency like
+//config: conventional LFS, so it provides quick recovery after system crashes.
+//config:
+//config: The possible use of NILFS includes versioning, tamper detection,
+//config: SOX compliance logging, and so forth. It can serve as an alternative
+//config: filesystem for Linux desktop environment, or as a basis of advanced
+//config: storage appliances.
+//config:
+
+#include "volume_id_internal.h"
+
+#define NILFS_UUID_SIZE 16
+#define NILFS_LABEL_SIZE 80
+#define NILFS_SB1_OFFSET 0x400
+#define NILFS_SB2_OFFSET 0x1000
+#define NILFS_MAGIC 0x3434
+
+struct nilfs2_super_block {
+/* 0x00 */ uint32_t s_rev_level; // Major revision level.
+/* 0x04 */ uint16_t s_minor_rev_level; // Minor revision level.
+/* 0x06 */ uint16_t s_magic; // Magic signature.
+/* 0x08 */ uint16_t s_bytes;
+/* 0x0A */ uint16_t s_flags;
+/* 0x0C */ uint32_t s_crc_seed;
+/* 0x10 */ uint32_t s_sum;
+/* 0x14 */ uint32_t s_log_block_size;
+/* 0x18 */ uint64_t s_nsegments;
+/* 0x20 */ uint64_t s_dev_size; // Block device size in bytes.
+/* 0x28 */ uint64_t s_first_data_block;
+/* 0x30 */ uint32_t s_blocks_per_segment;
+/* 0x34 */ uint32_t s_r_segments_percentage;
+/* 0x38 */ uint64_t s_last_cno;
+/* 0x40 */ uint64_t s_last_pseg;
+/* 0x48 */ uint64_t s_last_seq;
+/* 0x50 */ uint64_t s_free_blocks_count;
+/* 0x58 */ uint64_t s_ctime;
+/* 0x60 */ uint64_t s_mtime;
+/* 0x68 */ uint64_t s_wtime;
+/* 0x70 */ uint16_t s_mnt_count;
+/* 0x72 */ uint16_t s_max_mnt_count;
+/* 0x74 */ uint16_t s_state;
+/* 0x76 */ uint16_t s_errors;
+/* 0x78 */ uint64_t s_lastcheck;
+/* 0x80 */ uint32_t s_checkinterval;
+/* 0x84 */ uint32_t s_creator_os;
+/* 0x88 */ uint16_t s_def_resuid;
+/* 0x8A */ uint16_t s_def_resgid;
+/* 0x8C */ uint32_t s_first_ino;
+/* 0x90 */ uint16_t s_inode_size;
+/* 0x92 */ uint16_t s_dat_entry_size;
+/* 0x94 */ uint16_t s_checkpoint_size;
+/* 0x96 */ uint16_t s_segment_usage_size;
+/* 0x98 */ uint8_t s_uuid[NILFS_UUID_SIZE]; // 128-bit UUID for volume.
+/* 0xA8 */ uint8_t s_volume_name[NILFS_LABEL_SIZE]; // Volume label.
+/* 0xF8 */ // ...
+} PACKED;
+
+int FAST_FUNC volume_id_probe_nilfs(struct volume_id *id /*,uint64_t off*/)
+{
+ struct nilfs2_super_block *sb;
+
+ // Primary super block
+ dbg("nilfs: probing at offset 0x%x", NILFS_SB1_OFFSET);
+
+ sb = volume_id_get_buffer(id, NILFS_SB1_OFFSET, sizeof(*sb));
+
+ if (sb == NULL)
+ return -1;
+
+ if (sb->s_magic != NILFS_MAGIC)
+ return -1;
+
+ // The secondary superblock is not always used, so ignore it for now.
+ // When used it is at 4K from the end of the partition (sb->s_dev_size - NILFS_SB2_OFFSET).
+
+ volume_id_set_label_string(id, sb->s_volume_name, NILFS_LABEL_SIZE < VOLUME_ID_LABEL_SIZE ?
+ NILFS_LABEL_SIZE : VOLUME_ID_LABEL_SIZE);
+ volume_id_set_uuid(id, sb->s_uuid, UUID_DCE);
+
+ if (sb->s_rev_level == 2)
+ IF_FEATURE_BLKID_TYPE(id->type = "nilfs2");
+
+ return 0;
+}
diff --git a/release/src/router/busybox/util-linux/volume_id/ntfs.c b/release/src/router/busybox/util-linux/volume_id/ntfs.c
index a1c244894f..46f687a564 100644
--- a/release/src/router/busybox/util-linux/volume_id/ntfs.c
+++ b/release/src/router/busybox/util-linux/volume_id/ntfs.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_NTFS) += ntfs.o
+
+//config:
+//config:config FEATURE_VOLUMEID_NTFS
+//config: bool "ntfs filesystem"
+//config: default y
+//config: depends on VOLUMEID
+//config: help
+//config: TODO
+//config:
+
#include "volume_id_internal.h"
struct ntfs_super_block {
@@ -132,7 +143,7 @@ int FAST_FUNC volume_id_probe_ntfs(struct volume_id *id /*,uint64_t off*/)
dbg("mft record size %i", mft_record_size);
buf = volume_id_get_buffer(id, off + mft_off + (MFT_RECORD_VOLUME * mft_record_size),
- mft_record_size);
+ mft_record_size);
if (buf == NULL)
goto found;
@@ -165,7 +176,7 @@ int FAST_FUNC volume_id_probe_ntfs(struct volume_id *id /*,uint64_t off*/)
break;
dbg("found attribute type 0x%x, len %i, at offset %i",
- attr_type, attr_len, attr_off);
+ attr_type, attr_len, attr_off);
// if (attr_type == MFT_RECORD_ATTR_VOLUME_INFO) {
// struct volume_info *info;
diff --git a/release/src/router/busybox/util-linux/volume_id/ocfs2.c b/release/src/router/busybox/util-linux/volume_id/ocfs2.c
index fcdb151927..415e0bf619 100644
--- a/release/src/router/busybox/util-linux/volume_id/ocfs2.c
+++ b/release/src/router/busybox/util-linux/volume_id/ocfs2.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_OCFS2) += ocfs2.o
+
+//config:
+//config:config FEATURE_VOLUMEID_OCFS2
+//config: bool "ocfs2 filesystem"
+//config: default y
+//config: depends on VOLUMEID
+//config: help
+//config: TODO
+//config:
+
#include "volume_id_internal.h"
/* All these values are taken from ocfs2-tools's ocfs2_fs.h */
diff --git a/release/src/router/busybox/util-linux/volume_id/reiserfs.c b/release/src/router/busybox/util-linux/volume_id/reiserfs.c
index 67b4a18774..24979fb1c6 100644
--- a/release/src/router/busybox/util-linux/volume_id/reiserfs.c
+++ b/release/src/router/busybox/util-linux/volume_id/reiserfs.c
@@ -19,6 +19,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_REISERFS) += reiserfs.o
+
+//config:
+//config:config FEATURE_VOLUMEID_REISERFS
+//config: bool "Reiser filesystem"
+//config: default y
+//config: depends on VOLUMEID
+//config: help
+//config: TODO
+//config:
+
#include "volume_id_internal.h"
struct reiserfs_super_block {
diff --git a/release/src/router/busybox/util-linux/volume_id/romfs.c b/release/src/router/busybox/util-linux/volume_id/romfs.c
index 15653bedfc..4754fdb37a 100644
--- a/release/src/router/busybox/util-linux/volume_id/romfs.c
+++ b/release/src/router/busybox/util-linux/volume_id/romfs.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_ROMFS) += romfs.o
+
+//config:
+//config:config FEATURE_VOLUMEID_ROMFS
+//config: bool "romfs filesystem"
+//config: default y
+//config: depends on VOLUMEID
+//config: help
+//config: TODO
+//config:
+
#include "volume_id_internal.h"
struct romfs_super {
diff --git a/release/src/router/busybox/util-linux/volume_id/squashfs.c b/release/src/router/busybox/util-linux/volume_id/squashfs.c
new file mode 100644
index 0000000000..079b6cc31a
--- /dev/null
+++ b/release/src/router/busybox/util-linux/volume_id/squashfs.c
@@ -0,0 +1,61 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2012 S-G Bergh <sgb@systemasis.org>
+ *
+ * Licensed under GPLv2, see file LICENSE in this source tree.
+ */
+
+//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_SQUASHFS) += squashfs.o
+
+//config:
+//config:config FEATURE_VOLUMEID_SQUASHFS
+//config: bool "SquashFS filesystem"
+//config: default y
+//config: depends on VOLUMEID && FEATURE_BLKID_TYPE
+//config: help
+//config: Squashfs is a compressed read-only filesystem for Linux. Squashfs is
+//config: intended for general read-only filesystem use and in constrained block
+//config: device/memory systems (e.g. embedded systems) where low overhead is
+//config: needed.
+//config:
+
+#include "volume_id_internal.h"
+
+struct squashfs_superblock {
+ uint32_t magic;
+/*
+ uint32_t dummy[6];
+ uint16_t major;
+ uint16_t minor;
+*/
+} PACKED;
+
+int FAST_FUNC volume_id_probe_squashfs(struct volume_id *id /*,uint64_t off*/)
+{
+#define off ((uint64_t)0)
+ struct squashfs_superblock *sb;
+
+ dbg("SquashFS: probing at offset 0x%llx", (unsigned long long) off);
+ sb = volume_id_get_buffer(id, off, 0x200);
+ if (!sb)
+ return -1;
+
+ // Old SquashFS (pre 4.0) can be both big and little endian, so test for both.
+ // Likewise, it is commonly used in firwmare with some non-standard signatures.
+#define pack(a,b,c,d) ( (uint32_t)((a * 256 + b) * 256 + c) * 256 + d )
+#define SIG1 pack('s','q','s','h')
+#define SIG2 pack('h','s','q','s')
+#define SIG3 pack('s','h','s','q')
+#define SIG4 pack('q','s','h','s')
+ if (sb->magic == SIG1
+ || sb->magic == SIG2
+ || sb->magic == SIG3
+ || sb->magic == SIG4
+ ) {
+ IF_FEATURE_BLKID_TYPE(id->type = "squashfs";)
+ return 0;
+ }
+
+ return -1;
+}
diff --git a/release/src/router/busybox/util-linux/volume_id/sysv.c b/release/src/router/busybox/util-linux/volume_id/sysv.c
index 6eb96464d0..7b4b5360b0 100644
--- a/release/src/router/busybox/util-linux/volume_id/sysv.c
+++ b/release/src/router/busybox/util-linux/volume_id/sysv.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_SYSV) += sysv.o
+
+//config:
+//config:config FEATURE_VOLUMEID_SYSV
+//config: bool "sysv filesystem"
+//config: default y
+//config: depends on VOLUMEID
+//config: help
+//config: TODO
+//config:
+
#include "volume_id_internal.h"
#define SYSV_NICINOD 100
diff --git a/release/src/router/busybox/util-linux/volume_id/udf.c b/release/src/router/busybox/util-linux/volume_id/udf.c
index cd63c8d8a7..921454503d 100644
--- a/release/src/router/busybox/util-linux/volume_id/udf.c
+++ b/release/src/router/busybox/util-linux/volume_id/udf.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_UDF) += udf.o
+
+//config:
+//config:config FEATURE_VOLUMEID_UDF
+//config: bool "udf filesystem"
+//config: default y
+//config: depends on VOLUMEID
+//config: help
+//config: TODO
+//config:
+
#include "volume_id_internal.h"
struct volume_descriptor {
@@ -109,7 +120,7 @@ nsr:
return -1;
dbg("vsd: %c%c%c%c%c",
- vsd->id[0], vsd->id[1], vsd->id[2], vsd->id[3], vsd->id[4]);
+ vsd->id[0], vsd->id[1], vsd->id[2], vsd->id[3], vsd->id[4]);
if (vsd->id[0] == '\0')
return -1;
diff --git a/release/src/router/busybox/util-linux/volume_id/unused_highpoint.c b/release/src/router/busybox/util-linux/volume_id/unused_highpoint.c
index 17b7b3291b..7231a1db27 100644
--- a/release/src/router/busybox/util-linux/volume_id/unused_highpoint.c
+++ b/release/src/router/busybox/util-linux/volume_id/unused_highpoint.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_HIGHPOINTRAID) += highpoint.o
+
+//config:
+//config:### config FEATURE_VOLUMEID_HIGHPOINTRAID
+//config:### bool "highpoint raid"
+//config:### default y
+//config:### depends on VOLUMEID
+//config:### help
+//config:### TODO
+//config:
+
#include "volume_id_internal.h"
struct hpt37x_meta {
diff --git a/release/src/router/busybox/util-linux/volume_id/unused_hpfs.c b/release/src/router/busybox/util-linux/volume_id/unused_hpfs.c
index 4429524642..a87c89fb3e 100644
--- a/release/src/router/busybox/util-linux/volume_id/unused_hpfs.c
+++ b/release/src/router/busybox/util-linux/volume_id/unused_hpfs.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_HPFS) += hpfs.o
+
+//config:
+//config:### config FEATURE_VOLUMEID_HPFS
+//config:### bool "hpfs filesystem"
+//config:### default y
+//config:### depends on VOLUMEID
+//config:### help
+//config:### TODO
+//config:
+
#include "volume_id_internal.h"
struct hpfs_super {
diff --git a/release/src/router/busybox/util-linux/volume_id/unused_isw_raid.c b/release/src/router/busybox/util-linux/volume_id/unused_isw_raid.c
index 7ab47b3a1f..851bd2f8f4 100644
--- a/release/src/router/busybox/util-linux/volume_id/unused_isw_raid.c
+++ b/release/src/router/busybox/util-linux/volume_id/unused_isw_raid.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_ISWRAID) += isw_raid.o
+
+//config:
+//config:### config FEATURE_VOLUMEID_ISWRAID
+//config:### bool "intel raid"
+//config:### default y
+//config:### depends on VOLUMEID
+//config:### help
+//config:### TODO
+//config:
+
#include "volume_id_internal.h"
struct isw_meta {
diff --git a/release/src/router/busybox/util-linux/volume_id/unused_lsi_raid.c b/release/src/router/busybox/util-linux/volume_id/unused_lsi_raid.c
index e6cc8edd3a..52d68deab1 100644
--- a/release/src/router/busybox/util-linux/volume_id/unused_lsi_raid.c
+++ b/release/src/router/busybox/util-linux/volume_id/unused_lsi_raid.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_LSIRAID) += lsi_raid.o
+
+//config:
+//config:### config FEATURE_VOLUMEID_LSIRAID
+//config:### bool "lsi raid"
+//config:### default y
+//config:### depends on VOLUMEID
+//config:### help
+//config:### TODO
+//config:
+
#include "volume_id_internal.h"
struct lsi_meta {
diff --git a/release/src/router/busybox/util-linux/volume_id/unused_lvm.c b/release/src/router/busybox/util-linux/volume_id/unused_lvm.c
index 2206498bf6..08fa05243d 100644
--- a/release/src/router/busybox/util-linux/volume_id/unused_lvm.c
+++ b/release/src/router/busybox/util-linux/volume_id/unused_lvm.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_LVM) += lvm.o
+
+//config:
+//config:### config FEATURE_VOLUMEID_LVM
+//config:### bool "lvm"
+//config:### default y
+//config:### depends on VOLUMEID
+//config:### help
+//config:### TODO
+//config:
+
#include "volume_id_internal.h"
struct lvm1_super_block {
diff --git a/release/src/router/busybox/util-linux/volume_id/unused_mac.c b/release/src/router/busybox/util-linux/volume_id/unused_mac.c
index e8deb97209..a1a53d1fb6 100644
--- a/release/src/router/busybox/util-linux/volume_id/unused_mac.c
+++ b/release/src/router/busybox/util-linux/volume_id/unused_mac.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_MAC) += mac.o
+
+//config:
+//config:### config FEATURE_VOLUMEID_MAC
+//config:### bool "mac filesystem"
+//config:### default y
+//config:### depends on VOLUMEID
+//config:### help
+//config:### TODO
+//config:
+
#include "volume_id_internal.h"
struct mac_driver_desc {
diff --git a/release/src/router/busybox/util-linux/volume_id/unused_minix.c b/release/src/router/busybox/util-linux/volume_id/unused_minix.c
index a3e1077b0f..50afd5c3eb 100644
--- a/release/src/router/busybox/util-linux/volume_id/unused_minix.c
+++ b/release/src/router/busybox/util-linux/volume_id/unused_minix.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_MINIX) += minix.o
+
+//config:
+//config:### config FEATURE_VOLUMEID_MINIX
+//config:### bool "minix filesystem"
+//config:### default y
+//config:### depends on VOLUMEID
+//config:### help
+//config:### TODO
+//config:
+
#include "volume_id_internal.h"
struct minix_super_block {
diff --git a/release/src/router/busybox/util-linux/volume_id/unused_msdos.c b/release/src/router/busybox/util-linux/volume_id/unused_msdos.c
index 65fb885017..5ebaa3eeff 100644
--- a/release/src/router/busybox/util-linux/volume_id/unused_msdos.c
+++ b/release/src/router/busybox/util-linux/volume_id/unused_msdos.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_MSDOS) += msdos.o
+
+//config:
+//config:### config FEATURE_VOLUMEID_MSDOS
+//config:### bool "msdos filesystem"
+//config:### default y
+//config:### depends on VOLUMEID
+//config:### help
+//config:### TODO
+//config:
+
#include "volume_id_internal.h"
struct msdos_partition_entry {
@@ -109,7 +120,7 @@ int FAST_FUNC volume_id_probe_msdos_part_table(struct volume_id *id, uint64_t of
extended = off + poff;
} else {
dbg("found 0x%x data partition at 0x%llx, len 0x%llx",
- part[i].sys_ind, (unsigned long long) poff, (unsigned long long) plen);
+ part[i].sys_ind, (unsigned long long) poff, (unsigned long long) plen);
// if (is_raid(part[i].sys_ind))
// volume_id_set_usage_part(p, VOLUME_ID_RAID);
@@ -165,7 +176,7 @@ int FAST_FUNC volume_id_probe_msdos_part_table(struct volume_id *id, uint64_t of
if (id->partition_count < 4)
id->partition_count = 4;
- p = &id->partitions[id->partition_count];
+// p = &id->partitions[id->partition_count];
// if (is_raid(part[i].sys_ind))
// volume_id_set_usage_part(p, VOLUME_ID_RAID);
diff --git a/release/src/router/busybox/util-linux/volume_id/unused_nvidia_raid.c b/release/src/router/busybox/util-linux/volume_id/unused_nvidia_raid.c
index 9e84729210..d99a108f3b 100644
--- a/release/src/router/busybox/util-linux/volume_id/unused_nvidia_raid.c
+++ b/release/src/router/busybox/util-linux/volume_id/unused_nvidia_raid.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_NVIDIARAID) += nvidia_raid.o
+
+//config:
+//config:### config FEATURE_VOLUMEID_NVIDIARAID
+//config:### bool "nvidia raid"
+//config:### default y
+//config:### depends on VOLUMEID
+//config:### help
+//config:### TODO
+//config:
+
#include "volume_id_internal.h"
struct nvidia_meta {
diff --git a/release/src/router/busybox/util-linux/volume_id/unused_promise_raid.c b/release/src/router/busybox/util-linux/volume_id/unused_promise_raid.c
index 0b0d0063c2..cebebe35f4 100644
--- a/release/src/router/busybox/util-linux/volume_id/unused_promise_raid.c
+++ b/release/src/router/busybox/util-linux/volume_id/unused_promise_raid.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_PROMISERAID) += promise_raid.o
+
+//config:
+//config:### config FEATURE_VOLUMEID_PROMISERAID
+//config:### bool "promise raid"
+//config:### default y
+//config:### depends on VOLUMEID
+//config:### help
+//config:### TODO
+//config:
+
#include "volume_id_internal.h"
struct promise_meta {
diff --git a/release/src/router/busybox/util-linux/volume_id/unused_silicon_raid.c b/release/src/router/busybox/util-linux/volume_id/unused_silicon_raid.c
index d1c439ecfe..40c8faa9e8 100644
--- a/release/src/router/busybox/util-linux/volume_id/unused_silicon_raid.c
+++ b/release/src/router/busybox/util-linux/volume_id/unused_silicon_raid.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_SILICONRAID) += silicon_raid.o
+
+//config:
+//config:### config FEATURE_VOLUMEID_SILICONRAID
+//config:### bool "silicon raid"
+//config:### default y
+//config:### depends on VOLUMEID
+//config:### help
+//config:### TODO
+//config:
+
#include "volume_id_internal.h"
struct silicon_meta {
@@ -62,7 +73,7 @@ int FAST_FUNC volume_id_probe_silicon_medley_raid(struct volume_id *id, uint64_t
// volume_id_set_usage(id, VOLUME_ID_RAID);
// snprintf(id->type_version, sizeof(id->type_version)-1, "%u.%u",
-// le16_to_cpu(sil->major_ver), le16_to_cpu(sil->minor_ver));
+// le16_to_cpu(sil->major_ver), le16_to_cpu(sil->minor_ver));
// id->type = "silicon_medley_raid_member";
return 0;
diff --git a/release/src/router/busybox/util-linux/volume_id/unused_ufs.c b/release/src/router/busybox/util-linux/volume_id/unused_ufs.c
index 9f925d983f..d33c10fc41 100644
--- a/release/src/router/busybox/util-linux/volume_id/unused_ufs.c
+++ b/release/src/router/busybox/util-linux/volume_id/unused_ufs.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_UFS) += ufs.o
+
+//config:
+//config:### config FEATURE_VOLUMEID_UFS
+//config:### bool "ufs filesystem"
+//config:### default y
+//config:### depends on VOLUMEID
+//config:### help
+//config:### TODO
+//config:
+
#include "volume_id_internal.h"
struct ufs_super_block {
diff --git a/release/src/router/busybox/util-linux/volume_id/unused_via_raid.c b/release/src/router/busybox/util-linux/volume_id/unused_via_raid.c
index a11eec13ad..258f93a4fc 100644
--- a/release/src/router/busybox/util-linux/volume_id/unused_via_raid.c
+++ b/release/src/router/busybox/util-linux/volume_id/unused_via_raid.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_VIARAID) += via_raid.o
+
+//config:
+//config:### config FEATURE_VOLUMEID_VIARAID
+//config:### bool "via raid"
+//config:### default y
+//config:### depends on VOLUMEID
+//config:### help
+//config:### TODO
+//config:
+
#include "volume_id_internal.h"
struct via_meta {
diff --git a/release/src/router/busybox/util-linux/volume_id/util.c b/release/src/router/busybox/util-linux/volume_id/util.c
index b083dfcb82..061545fde7 100644
--- a/release/src/router/busybox/util-linux/volume_id/util.c
+++ b/release/src/router/busybox/util-linux/volume_id/util.c
@@ -20,17 +20,6 @@
#include "volume_id_internal.h"
-#if !defined(BCMARM) && !defined(QCA)
-#define XMALLOC xmalloc
-#define XREALLOC xrealloc
-#define FULL_READ full_read
-#else
-#define XMALLOC malloc
-#define XREALLOC realloc
-#define FULL_READ read
-#endif
-
-#ifdef UTIL2
void volume_id_set_unicode16(char *str, size_t len, const uint8_t *buf, enum endian endianess, size_t count)
{
unsigned i, j;
@@ -42,31 +31,33 @@ void volume_id_set_unicode16(char *str, size_t len, const uint8_t *buf, enum end
c = (buf[i+1] << 8) | buf[i];
else
c = (buf[i] << 8) | buf[i+1];
- if (c == 0) {
- str[j] = '\0';
+ if (c == 0)
break;
- } else if (c < 0x80) {
- if (j+1 >= len)
- break;
- str[j++] = (uint8_t) c;
- } else if (c < 0x800) {
- if (j+2 >= len)
- break;
- str[j++] = (uint8_t) (0xc0 | (c >> 6));
- str[j++] = (uint8_t) (0x80 | (c & 0x3f));
+ if (j+1 >= len)
+ break;
+ if (c < 0x80) {
+ /* 0xxxxxxx */
} else {
- if (j+3 >= len)
+ uint8_t topbits = 0xc0;
+ if (j+2 >= len)
break;
- str[j++] = (uint8_t) (0xe0 | (c >> 12));
- str[j++] = (uint8_t) (0x80 | ((c >> 6) & 0x3f));
- str[j++] = (uint8_t) (0x80 | (c & 0x3f));
+ if (c < 0x800) {
+ /* 110yyyxx 10xxxxxx */
+ } else {
+ if (j+3 >= len)
+ break;
+ /* 1110yyyy 10yyyyxx 10xxxxxx */
+ str[j++] = (uint8_t) (0xe0 | (c >> 12));
+ topbits = 0x80;
+ }
+ str[j++] = (uint8_t) (topbits | ((c >> 6) & 0x3f));
+ c = 0x80 | (c & 0x3f);
}
+ str[j++] = (uint8_t) c;
}
str[j] = '\0';
}
-#endif
-#ifndef UTIL2
#ifdef UNUSED
static const char *usage_to_string(enum volume_id_usage usage_id)
{
@@ -121,9 +112,6 @@ static size_t strnlen(const char *s, size_t maxlen)
}
#endif
-#endif
-#ifdef UTIL2
-
void volume_id_set_label_string(struct volume_id *id, const uint8_t *buf, size_t count)
{
unsigned i;
@@ -141,30 +129,14 @@ void volume_id_set_label_string(struct volume_id *id, const uint8_t *buf, size_t
void volume_id_set_label_unicode16(struct volume_id *id, const uint8_t *buf, enum endian endianess, size_t count)
{
- volume_id_set_unicode16(id->label, sizeof(id->label), buf, endianess, count);
+ volume_id_set_unicode16(id->label, sizeof(id->label), buf, endianess, count);
}
void volume_id_set_uuid(struct volume_id *id, const uint8_t *buf, enum uuid_format format)
{
unsigned i;
- unsigned count = 0;
+ unsigned count = (format == UUID_DCE_STRING ? VOLUME_ID_UUID_SIZE : 4 << format);
- switch (format) {
- case UUID_DOS:
- count = 4;
- break;
- case UUID_NTFS:
- case UUID_HFS:
- count = 8;
- break;
- case UUID_DCE:
- count = 16;
- break;
- case UUID_DCE_STRING:
- /* 36 is ok, id->uuid has one extra byte for NUL */
- count = VOLUME_ID_UUID_SIZE;
- break;
- }
// memcpy(id->uuid_raw, buf, count);
// id->uuid_raw_len = count;
@@ -185,11 +157,6 @@ set:
buf[7], buf[6], buf[5], buf[4],
buf[3], buf[2], buf[1], buf[0]);
break;
- case UUID_HFS:
- sprintf(id->uuid, "%02X%02X%02X%02X%02X%02X%02X%02X",
- buf[0], buf[1], buf[2], buf[3],
- buf[4], buf[5], buf[6], buf[7]);
- break;
case UUID_DCE:
sprintf(id->uuid,
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
@@ -223,7 +190,7 @@ void *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len)
/* && off <= SB_BUFFER_SIZE - want this paranoid overflow check? */
) {
if (id->sbbuf == NULL) {
- id->sbbuf = XMALLOC(SB_BUFFER_SIZE);
+ id->sbbuf = xmalloc(SB_BUFFER_SIZE);
}
small_off = off;
dst = id->sbbuf;
@@ -244,6 +211,7 @@ void *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len)
return NULL;
}
dst = id->seekbuf;
+
/* check if we need to read */
if ((off >= id->seekbuf_off)
&& ((off + len) <= (id->seekbuf_off + id->seekbuf_len))
@@ -254,7 +222,7 @@ void *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len)
id->seekbuf_off = off;
id->seekbuf_len = len;
- id->seekbuf = XREALLOC(id->seekbuf, len);
+ id->seekbuf = xrealloc(id->seekbuf, len);
small_off = 0;
dst = id->seekbuf;
dbg("read seekbuf off:0x%llx len:0x%zx",
@@ -264,7 +232,7 @@ void *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len)
dbg("seek(0x%llx) failed", (unsigned long long) off);
goto err;
}
- read_len = FULL_READ(id->fd, dst, len);
+ read_len = full_read(id->fd, dst, len);
if (read_len != len) {
dbg("requested 0x%x bytes, got 0x%x bytes",
(unsigned) len, (unsigned) read_len);
@@ -295,4 +263,3 @@ void volume_id_free_buffer(struct volume_id *id)
id->seekbuf_len = 0;
id->seekbuf_off = 0; /* paranoia */
}
-#endif
diff --git a/release/src/router/busybox/util-linux/volume_id/util2.c b/release/src/router/busybox/util-linux/volume_id/util2.c
deleted file mode 100644
index f567d1e04c..0000000000
--- a/release/src/router/busybox/util-linux/volume_id/util2.c
+++ /dev/null
@@ -1,7 +0,0 @@
-/* util.c is now split apart, for the benefit of Tomato. So it can
- * pull in just enough busybox code to read disc labels, without
- * dragging in other un-needed stuff.
- * It would be better if Tomato could use "busybox.so", but busybox
- * can't currently build a shared .so configuration. */
-#define UTIL2
-#include "util.c"
diff --git a/release/src/router/busybox/util-linux/volume_id/volume_id.c b/release/src/router/busybox/util-linux/volume_id/volume_id.c
index 7c936a81db..3f71e00840 100644
--- a/release/src/router/busybox/util-linux/volume_id/volume_id.c
+++ b/release/src/router/busybox/util-linux/volume_id/volume_id.c
@@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:lib-$(CONFIG_VOLUMEID) += volume_id.o util.o
+
#include "volume_id_internal.h"
@@ -99,9 +101,15 @@ static const probe_fptr fs1[] = {
#if ENABLE_FEATURE_VOLUMEID_MAC
volume_id_probe_mac_partition_map,
#endif
+#if ENABLE_FEATURE_VOLUMEID_SQUASHFS
+ volume_id_probe_squashfs,
+#endif
#if ENABLE_FEATURE_VOLUMEID_XFS
volume_id_probe_xfs,
#endif
+#if ENABLE_FEATURE_VOLUMEID_BCACHE
+ volume_id_probe_bcache,
+#endif
};
/* fill buffer with maximum */
@@ -133,6 +141,12 @@ static const probe_fptr fs2[] = {
#if ENABLE_FEATURE_VOLUMEID_UFS
volume_id_probe_ufs,
#endif
+#if ENABLE_FEATURE_VOLUMEID_F2FS
+ volume_id_probe_f2fs,
+#endif
+#if ENABLE_FEATURE_VOLUMEID_NILFS
+ volume_id_probe_nilfs,
+#endif
#if ENABLE_FEATURE_VOLUMEID_NTFS
volume_id_probe_ntfs,
#endif
diff --git a/release/src/router/busybox/util-linux/volume_id/volume_id_internal.h b/release/src/router/busybox/util-linux/volume_id/volume_id_internal.h
index b38b3ea333..3061ac4d51 100644
--- a/release/src/router/busybox/util-linux/volume_id/volume_id_internal.h
+++ b/release/src/router/busybox/util-linux/volume_id/volume_id_internal.h
@@ -96,52 +96,35 @@ void FAST_FUNC free_volume_id(struct volume_id *id);
/* size of seek buffer, FAT cluster is 32k max */
#define SEEK_BUFFER_SIZE 0x10000
-#define bswap16(x) (uint16_t) ( \
- (((uint16_t)(x) & 0x00ffu) << 8) | \
- (((uint16_t)(x) & 0xff00u) >> 8))
-
-#define bswap32(x) (uint32_t) ( \
- (((uint32_t)(x) & 0xff000000u) >> 24) | \
- (((uint32_t)(x) & 0x00ff0000u) >> 8) | \
- (((uint32_t)(x) & 0x0000ff00u) << 8) | \
- (((uint32_t)(x) & 0x000000ffu) << 24))
-
-#define bswap64(x) (uint64_t) ( \
- (((uint64_t)(x) & 0xff00000000000000ull) >> 56) | \
- (((uint64_t)(x) & 0x00ff000000000000ull) >> 40) | \
- (((uint64_t)(x) & 0x0000ff0000000000ull) >> 24) | \
- (((uint64_t)(x) & 0x000000ff00000000ull) >> 8) | \
- (((uint64_t)(x) & 0x00000000ff000000ull) << 8) | \
- (((uint64_t)(x) & 0x0000000000ff0000ull) << 24) | \
- (((uint64_t)(x) & 0x000000000000ff00ull) << 40) | \
- (((uint64_t)(x) & 0x00000000000000ffull) << 56))
-
#if BB_LITTLE_ENDIAN
-#define le16_to_cpu(x) (x)
-#define le32_to_cpu(x) (x)
-#define le64_to_cpu(x) (x)
-#define be16_to_cpu(x) bswap16(x)
-#define be32_to_cpu(x) bswap32(x)
-#define cpu_to_le16(x) (x)
-#define cpu_to_le32(x) (x)
-#define cpu_to_be32(x) bswap32(x)
+# define le16_to_cpu(x) (uint16_t)(x)
+# define le32_to_cpu(x) (uint32_t)(x)
+# define le64_to_cpu(x) (uint64_t)(x)
+# define be16_to_cpu(x) (uint16_t)(bswap_16(x))
+# define be32_to_cpu(x) (uint32_t)(bswap_32(x))
+# define cpu_to_le16(x) (uint16_t)(x)
+# define cpu_to_le32(x) (uint32_t)(x)
+# define cpu_to_be32(x) (uint32_t)(bswap_32(x))
#else
-#define le16_to_cpu(x) bswap16(x)
-#define le32_to_cpu(x) bswap32(x)
-#define le64_to_cpu(x) bswap64(x)
-#define be16_to_cpu(x) (x)
-#define be32_to_cpu(x) (x)
-#define cpu_to_le16(x) bswap16(x)
-#define cpu_to_le32(x) bswap32(x)
-#define cpu_to_be32(x) (x)
+# define le16_to_cpu(x) (uint16_t)(bswap_16(x))
+# define le32_to_cpu(x) (uint32_t)(bswap_32(x))
+# define le64_to_cpu(x) (uint64_t)(bb_bswap_64(x))
+# define be16_to_cpu(x) (uint16_t)(x)
+# define be32_to_cpu(x) (uint32_t)(x)
+# define cpu_to_le16(x) (uint16_t)(bswap_16(x))
+# define cpu_to_le32(x) (uint32_t)(bswap_32(x))
+# define cpu_to_be32(x) (uint32_t)(x)
#endif
+/* volume_id_set_uuid(id,buf,fmt) assumes size of uuid buf
+ * by shifting: 4 << fmt, except for fmt == UUID_DCE_STRING.
+ * The constants below should match sizes.
+ */
enum uuid_format {
- UUID_DCE_STRING,
- UUID_DCE,
- UUID_DOS,
- UUID_NTFS,
- UUID_HFS,
+ UUID_DOS = 0, /* 4 bytes */
+ UUID_NTFS = 1, /* 8 bytes */
+ UUID_DCE = 2, /* 16 bytes */
+ UUID_DCE_STRING = 3, /* 36 bytes (VOLUME_ID_UUID_SIZE) */
};
enum endian {
@@ -186,6 +169,8 @@ int FAST_FUNC volume_id_probe_linux_raid(struct volume_id *id /*,uint64_t off*/,
/* FS */
+int FAST_FUNC volume_id_probe_bcache(struct volume_id *id /*,uint64_t off*/);
+
int FAST_FUNC volume_id_probe_btrfs(struct volume_id *id /*,uint64_t off*/);
int FAST_FUNC volume_id_probe_cramfs(struct volume_id *id /*,uint64_t off*/);
@@ -212,6 +197,10 @@ int FAST_FUNC volume_id_probe_luks(struct volume_id *id /*,uint64_t off*/);
//int FAST_FUNC volume_id_probe_msdos_part_table(struct volume_id *id /*,uint64_t off*/);
+int FAST_FUNC volume_id_probe_f2fs(struct volume_id *id /*,uint64_t off*/);
+
+int FAST_FUNC volume_id_probe_nilfs(struct volume_id *id /*,uint64_t off*/);
+
int FAST_FUNC volume_id_probe_ntfs(struct volume_id *id /*,uint64_t off*/);
int FAST_FUNC volume_id_probe_exfat(struct volume_id *id /*,uint64_t off*/);
@@ -222,6 +211,8 @@ int FAST_FUNC volume_id_probe_reiserfs(struct volume_id *id /*,uint64_t off*/);
int FAST_FUNC volume_id_probe_romfs(struct volume_id *id /*,uint64_t off*/);
+int FAST_FUNC volume_id_probe_squashfs(struct volume_id *id /*,uint64_t off*/);
+
int FAST_FUNC volume_id_probe_sysv(struct volume_id *id /*,uint64_t off*/);
int FAST_FUNC volume_id_probe_udf(struct volume_id *id /*,uint64_t off*/);
diff --git a/release/src/router/busybox/util-linux/volume_id/xfs.c b/release/src/router/busybox/util-linux/volume_id/xfs.c
index 84746020ee..5eefc201de 100644
--- a/release/src/router/busybox/util-linux/volume_id/xfs.c
+++ b/release/src/router/busybox/util-linux/volume_id/xfs.c
@@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_XFS) += xfs.o
+
+//config:
+//config:config FEATURE_VOLUMEID_XFS
+//config: bool "xfs filesystem"
+//config: default y
+//config: depends on VOLUMEID
+//config: help
+//config: TODO
+//config:
+
#include "volume_id_internal.h"
struct xfs_super_block {
diff --git a/release/src/router/ipset_arm/m4/pkg.m4 b/release/src/router/ipset_arm/m4/pkg.m4
new file mode 100644
index 0000000000..a8b3d06c81
--- /dev/null
+++ b/release/src/router/ipset_arm/m4/pkg.m4
@@ -0,0 +1,156 @@
+# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
+#
+# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=m4_default([$1], [0.9.0])
+ AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ PKG_CONFIG=""
+ fi
+
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists. Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+#
+# Similar to PKG_CHECK_MODULES, make sure that the first instance of
+# this or PKG_CHECK_MODULES is called, or make sure to call
+# PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+ m4_ifval([$2], [$2], [:])
+m4_ifvaln([$3], [else
+ $3])dnl
+fi])
+
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$PKG_CONFIG"; then
+ if test -n "$$1"; then
+ pkg_cv_[]$1="$$1"
+ else
+ PKG_CHECK_EXISTS([$3],
+ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
+ [pkg_failed=yes])
+ fi
+else
+ pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+ _PKG_SHORT_ERRORS_SUPPORTED
+ if test $_pkg_short_errors_supported = yes; then
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"`
+ else
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+ ifelse([$4], , [AC_MSG_ERROR(dnl
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT
+])],
+ [AC_MSG_RESULT([no])
+ $4])
+elif test $pkg_failed = untried; then
+ ifelse([$4], , [AC_MSG_FAILURE(dnl
+[The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://www.freedesktop.org/software/pkgconfig>.])],
+ [$4])
+else
+ $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+ $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+ AC_MSG_RESULT([yes])
+ ifelse([$3], , :, [$3])
+fi[]dnl
+])# PKG_CHECK_MODULES
diff --git a/release/src/router/libdisk/Makefile b/release/src/router/libdisk/Makefile
index 52bcc2868f..d5316d83a7 100644
--- a/release/src/router/libdisk/Makefile
+++ b/release/src/router/libdisk/Makefile
@@ -27,23 +27,12 @@ ifeq ($(RTCONFIG_QTN),y)
LDFLAGS += -L$(TOP)/libqcsapi_client -lqcsapi_client
endif
-CFLAGS += -I$(TOP)/busybox/include
-CFLAGS += -I$(TOP)/busybox/util-linux/volume_id
-
-ID_OBJS = $(TOP)/busybox/util-linux/volume_id/util2.o
-ID_OBJS += $(TOP)/busybox/util-linux/volume_id/linux_swap.o
-ID_OBJS += $(TOP)/busybox/util-linux/volume_id/ext.o
-ID_OBJS += $(TOP)/busybox/util-linux/volume_id/fat.o
-ID_OBJS += $(TOP)/busybox/util-linux/volume_id/ntfs.o
-ID_OBJS += $(TOP)/busybox/util-linux/volume_id/hfs.o
-#ID_OBJS += libbb_stub.o
-
#SHARE_STATIC=y
all: $(PROGS)
#libdisk.so: $(OBJS) $(TOP)/shared/shutils.o
-libdisk.so: $(OBJS) $(ID_OBJS)
+libdisk.so: $(OBJS)
$(LD) $(LDFLAGS_SO) -shared -o $@ $^
write_smb_conf: write_smb_conf.o libdisk.so
@@ -60,7 +49,7 @@ test_of_var_files: libdisk.so test_share
test_disk1: test_disk1.o libdisk.so
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
-test_disk2: test_disk2.o $(ID_OBJS)
+test_disk2: test_disk2.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
ifeq ($(SHARE_STATIC),y)
diff --git a/release/src/router/libdisk/disk_initial.c b/release/src/router/libdisk/disk_initial.c
index 77884a2595..9d6a1de499 100644
--- a/release/src/router/libdisk/disk_initial.c
+++ b/release/src/router/libdisk/disk_initial.c
@@ -24,9 +24,6 @@
#include <dirent.h>
#include <bcmnvram.h>
-// From BusyBox and get volume's label.
-#include <autoconf.h>
-#include <volume_id_internal.h>
#include <shared.h>
#include "usb_info.h"
@@ -603,57 +600,35 @@ extern int is_partition_name(const char *device_name, u32 *partition_order){
}
int find_partition_label(const char *dev_name, char *label){
- struct volume_id id;
char dev_path[128];
char usb_port[32];
char nvram_label[32], nvram_value[512];
+ int ret;
- if(label) *label = 0;
+ if (label) *label = 0;
memset(usb_port, 0, 32);
- if(get_usb_port_by_device(dev_name, usb_port, 32) == NULL)
+ if (get_usb_port_by_device(dev_name, usb_port, sizeof(usb_port)) == NULL)
return 0;
- memset(nvram_label, 0, 32);
- sprintf(nvram_label, "usb_path_%s_label", dev_name);
-
- memset(nvram_value, 0, 512);
- strncpy(nvram_value, nvram_safe_get(nvram_label), 512);
- if(strlen(nvram_value) > 0){
- strcpy(label, nvram_value);
-
- return (label && *label != 0);
- }
-
- memset(dev_path, 0, 128);
- sprintf(dev_path, "/dev/%s", dev_name);
+ snprintf(nvram_label, sizeof(nvram_label), "usb_path_%s_label", dev_name);
+ strlcpy(nvram_value, nvram_safe_get(nvram_label), sizeof(nvram_value));
+ if (*nvram_value)
+ goto ret;
- memset(&id, 0x00, sizeof(id));
- if((id.fd = open(dev_path, O_RDONLY)) < 0)
+ snprintf(dev_path, sizeof(dev_path), "/dev/%s", dev_name);
+ ret = find_label_or_uuid(dev_path, nvram_value, NULL);
+ if (ret < 0)
return 0;
- volume_id_get_buffer(&id, 0, SB_BUFFER_SIZE);
-
- if(volume_id_probe_linux_swap(&id) == 0 || id.error)
- goto ret;
- if(volume_id_probe_ext(&id) == 0 || id.error)
- goto ret;
- if(volume_id_probe_vfat(&id) == 0 || id.error)
- goto ret;
- if(volume_id_probe_ntfs(&id) == 0 || id.error)
- goto ret;
- if(volume_id_probe_hfs_hfsplus(&id) == 0 || id.error)
- goto ret;
+ if (ret == 0)
+ strcpy(nvram_value, " ");
+ nvram_set(nvram_label, nvram_value);
ret:
- volume_id_free_buffer(&id);
- if(label && (*id.label != 0))
- strcpy(label, id.label);
- else
- strcpy(label, " ");
- nvram_set(nvram_label, label);
- close(id.fd);
- return (label && *label != 0);
+ if (label)
+ strcpy(label, nvram_value);
+ return (label && *label);
}
extern partition_info_t *create_partition(const char *device_name, partition_info_t **new_part_info){
diff --git a/release/src/router/libdisk/libbb_stub.c b/release/src/router/libdisk/libbb_stub.c
deleted file mode 100644
index e6e5f287fc..0000000000
--- a/release/src/router/libdisk/libbb_stub.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/* copy-paste from BusyBox */
-
-#include <autoconf.h>
-#include <libbb.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <malloc.h>
-
-const char bb_msg_memory_exhausted[] ALIGN1 = "memory exhausted";
-int *const bb_errno;
-int xfunc_error_retval = EXIT_FAILURE;
-
-void FAST_FUNC xfunc_die(void)
-{
- exit(xfunc_error_retval);
-}
-
-void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr)
-{
- /* do nothing */
-}
-
-void FAST_FUNC bb_error_msg_and_die(const char *s, ...)
-{
- va_list p;
-
- va_start(p, s);
- bb_verror_msg(s, p, NULL);
- va_end(p);
- xfunc_die();
-}
-
-void FAST_FUNC bb_error_msg(const char *s, ...)
-{
- va_list p;
-
- va_start(p, s);
- bb_verror_msg(s, p, NULL);
- va_end(p);
-}
-
-/* All the functions starting with "x" call bb_error_msg_and_die() if they
- * fail, so callers never need to check for errors. If it returned, it
- * succeeded. */
-
-#ifndef DMALLOC
-/* dmalloc provides variants of these that do abort() on failure.
- * Since dmalloc's prototypes overwrite the impls here as they are
- * included after these prototypes in libbb.h, all is well.
- */
-// Die if we can't allocate size bytes of memory.
-void* FAST_FUNC xmalloc(size_t size)
-{
- void *ptr = malloc(size);
- if (ptr == NULL && size != 0)
- bb_error_msg_and_die(bb_msg_memory_exhausted);
- return ptr;
-}
-
-// Die if we can't resize previously allocated memory. (This returns a pointer
-// to the new memory, which may or may not be the same as the old memory.
-// It'll copy the contents to a new chunk and free the old one if necessary.)
-void* FAST_FUNC xrealloc(void *ptr, size_t size)
-{
- ptr = realloc(ptr, size);
- if (ptr == NULL && size != 0)
- bb_error_msg_and_die(bb_msg_memory_exhausted);
- return ptr;
-}
-#endif /* DMALLOC */
-
-ssize_t FAST_FUNC safe_read(int fd, void *buf, size_t count)
-{
- ssize_t n;
-
- do {
- n = read(fd, buf, count);
- } while (n < 0 && errno == EINTR);
-
- return n;
-}
-
-/*
- * Read all of the supplied buffer from a file.
- * This does multiple reads as necessary.
- * Returns the amount read, or -1 on an error.
- * A short read is returned on an end of file.
- */
-ssize_t FAST_FUNC full_read(int fd, void *buf, size_t len)
-{
- ssize_t cc;
- ssize_t total;
-
- total = 0;
-
- while (len) {
- cc = safe_read(fd, buf, len);
-
- if (cc < 0) {
- if (total) {
- /* we already have some! */
- /* user can do another read to know the error code */
- return total;
- }
- return cc; /* read() returns -1 on failure. */
- }
- if (cc == 0)
- break;
- buf = ((char *)buf) + cc;
- total += cc;
- len -= cc;
- }
-
- return total;
-}
diff --git a/release/src/router/libdisk/test_disk2.c b/release/src/router/libdisk/test_disk2.c
index ee2d0a6ddb..24d93ae429 100644
--- a/release/src/router/libdisk/test_disk2.c
+++ b/release/src/router/libdisk/test_disk2.c
@@ -28,9 +28,6 @@
#include <dirent.h>
#include <bcmnvram.h>
-// From BusyBox and get volume's label.
-#include <autoconf.h>
-#include <volume_id_internal.h>
#include <shared.h>
#include "disk_initial.h"
@@ -1085,57 +1082,35 @@ int is_partition_name(const char *device_name, u32 *partition_order){
}
int find_partition_label(const char *dev_name, char *label){
- struct volume_id id;
char dev_path[128];
char usb_port[32];
char nvram_label[32], nvram_value[512];
+ int ret;
- if(label) *label = 0;
+ if (label) *label = 0;
memset(usb_port, 0, 32);
- if(get_usb_port_by_device(dev_name, usb_port, 32) == NULL)
+ if (get_usb_port_by_device(dev_name, usb_port, sizeof(usb_port)) == NULL)
return 0;
- memset(nvram_label, 0, 32);
- sprintf(nvram_label, "usb_path_%s_label", dev_name);
-
- memset(nvram_value, 0, 512);
- strncpy(nvram_value, nvram_safe_get(nvram_label), 512);
- if(strlen(nvram_value) > 0){
- strcpy(label, nvram_value);
-
- return (label && *label != 0);
- }
-
- memset(dev_path, 0, 128);
- sprintf(dev_path, "/dev/%s", dev_name);
+ snprintf(nvram_label, sizeof(nvram_label), "usb_path_%s_label", dev_name);
+ strlcpy(nvram_value, nvram_safe_get(nvram_label), sizeof(nvram_value));
+ if (*nvram_value)
+ goto ret;
- memset(&id, 0x00, sizeof(id));
- if((id.fd = open(dev_path, O_RDONLY)) < 0)
+ snprintf(dev_path, sizeof(dev_path), "/dev/%s", dev_name);
+ ret = find_label_or_uuid(dev_path, nvram_value, NULL);
+ if (ret < 0)
return 0;
- volume_id_get_buffer(&id, 0, SB_BUFFER_SIZE);
-
- if(volume_id_probe_linux_swap(&id) == 0 || id.error)
- goto ret;
- if(volume_id_probe_ext(&id) == 0 || id.error)
- goto ret;
- if(volume_id_probe_vfat(&id) == 0 || id.error)
- goto ret;
- if(volume_id_probe_ntfs(&id) == 0 || id.error)
- goto ret;
- if(volume_id_probe_hfs_hfsplus(&id) == 0 || id.error)
- goto ret;
+ if (ret == 0)
+ strcpy(nvram_value, " ");
+ nvram_set(nvram_label, nvram_value);
ret:
- volume_id_free_buffer(&id);
- if(label && (*id.label != 0))
- strcpy(label, id.label);
- else
- strcpy(label, " ");
- nvram_set(nvram_label, label);
- close(id.fd);
- return (label && *label != 0);
+ if (label)
+ strcpy(label, nvram_value);
+ return (label && *label);
}
partition_info_t *create_partition(const char *device_name, partition_info_t **new_part_info){
diff --git a/release/src/router/nano/m4/pkg.m4 b/release/src/router/nano/m4/pkg.m4
new file mode 100644
index 0000000000..a8b3d06c81
--- /dev/null
+++ b/release/src/router/nano/m4/pkg.m4
@@ -0,0 +1,156 @@
+# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
+#
+# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=m4_default([$1], [0.9.0])
+ AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ PKG_CONFIG=""
+ fi
+
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists. Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+#
+# Similar to PKG_CHECK_MODULES, make sure that the first instance of
+# this or PKG_CHECK_MODULES is called, or make sure to call
+# PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+ m4_ifval([$2], [$2], [:])
+m4_ifvaln([$3], [else
+ $3])dnl
+fi])
+
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$PKG_CONFIG"; then
+ if test -n "$$1"; then
+ pkg_cv_[]$1="$$1"
+ else
+ PKG_CHECK_EXISTS([$3],
+ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
+ [pkg_failed=yes])
+ fi
+else
+ pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+ _PKG_SHORT_ERRORS_SUPPORTED
+ if test $_pkg_short_errors_supported = yes; then
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"`
+ else
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+ ifelse([$4], , [AC_MSG_ERROR(dnl
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT
+])],
+ [AC_MSG_RESULT([no])
+ $4])
+elif test $pkg_failed = untried; then
+ ifelse([$4], , [AC_MSG_FAILURE(dnl
+[The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://www.freedesktop.org/software/pkgconfig>.])],
+ [$4])
+else
+ $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+ $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+ AC_MSG_RESULT([yes])
+ ifelse([$3], , :, [$3])
+fi[]dnl
+])# PKG_CHECK_MODULES
diff --git a/release/src/router/shared/Makefile b/release/src/router/shared/Makefile
index 8637528061..acc3918f48 100644
--- a/release/src/router/shared/Makefile
+++ b/release/src/router/shared/Makefile
@@ -118,12 +118,24 @@ endif
ifeq ($(RTCONFIG_USB),y)
OBJS += usb.o
-OBJS += $(TOP)/busybox/util-linux/volume_id/ext.o
-OBJS += $(TOP)/busybox/util-linux/volume_id/util2.o
-OBJS += $(TOP)/busybox/util-linux/volume_id/fat.o
-OBJS += $(TOP)/busybox/util-linux/volume_id/ntfs.o
-OBJS += $(TOP)/busybox/util-linux/volume_id/linux_swap.o
-OBJS += $(if $(HFS),$(TOP)/busybox/util-linux/volume_id/hfs.o)
+
+ID_CFLAGS += -I$(TOP)/busybox/include
+ID_CFLAGS += -I$(TOP)/busybox/util-linux/volume_id
+ID_CFLAGS += -include $(TOP)/busybox/include/autoconf.h
+ID_CFLAGS += -D_GNU_SOURCE -DNDEBUG -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+#ID_CFLAGS += -fdata-sections -ffunction-sections
+ID_OBJS = $(TOP)/busybox/util-linux/volume_id/util.o
+ID_OBJS += $(TOP)/busybox/util-linux/volume_id/linux_swap.o
+ID_OBJS += $(TOP)/busybox/util-linux/volume_id/ext.o
+ID_OBJS += $(TOP)/busybox/util-linux/volume_id/fat.o
+ID_OBJS += $(TOP)/busybox/util-linux/volume_id/ntfs.o
+ID_OBJS += $(if $(HFS),$(TOP)/busybox/util-linux/volume_id/hfs.o)
+ID_OBJS += $(if $(HFS),$(patsubst %.c,%.o,$(wildcard $(TOP)/busybox/libbb/hash_md5.c)))
+ID_OBJS += $(if $(HFS),$(patsubst %.c,%.o,$(wildcard $(TOP)/busybox/libbb/bb_bswap_64.c)))
+ID_OBJS += volume_id.o
+#OBJS += volume_id.lib.o
+OBJS += $(notdir $(ID_OBJS))
+
ifeq ($(RTCONFIG_USB_MODEM),y)
OBJS += at_cmd.o
endif
@@ -201,6 +213,22 @@ clean:
@echo " [shared] cp $@"
@cp -f $< $@
+ifeq ($(RTCONFIG_USB),y)
+vpath %.c $(sort $(dir $(ID_OBJS)))
+
+$(notdir $(ID_OBJS)): %.o: %.c .%.depend
+ @echo " [shared] CC $@"
+ @$(CC) $(CFLAGS) $(ID_CFLAGS) -o $@ -c $<
+
+$(patsubst %.o,.%.depend,$(notdir $(ID_OBJS))): .%.depend: %.c
+ @$(CC) $(CFLAGS) $(ID_CFLAGS) -M $< > $@
+
+# ld -r --gc-sections is broken, so don't use it for now
+#volume_id.lib.o: $(notdir $(ID_OBJS))
+# @echo " [shared] LD $@"
+# @$(LD) -r -e find_label_or_uuid --gc-sections -o $@ $(notdir $(ID_OBJS))
+endif
+
%.o: %.c .%.depend
@echo " [shared] CC $@"
@$(CC) $(CFLAGS) -o $@ -c $<
diff --git a/release/src/router/shared/pids.c b/release/src/router/shared/pids.c
index 4dfbf3603d..ab611eec0b 100644
--- a/release/src/router/shared/pids.c
+++ b/release/src/router/shared/pids.c
@@ -87,13 +87,6 @@ static int read_to_buf(const char *filename, void *buf)
return ret;
}
-void* xzalloc(size_t size)
-{
- void *ptr = malloc(size);
- memset(ptr, 0, size);
- return ptr;
-}
-
typedef struct procps_status_t {
DIR *dir;
unsigned char shift_pages_to_bytes;
@@ -124,7 +117,7 @@ typedef struct procps_status_t {
static procps_status_t* alloc_procps_scan(void)
{
unsigned n = getpagesize();
- procps_status_t* sp = xzalloc(sizeof(procps_status_t));
+ procps_status_t* sp = calloc(1, sizeof(procps_status_t));
sp->dir = opendir("/proc");
while (1) {
n >>= 1;
@@ -190,21 +183,13 @@ unsigned long long bb_strtoull(const char *arg, char **endp, int base)
return handle_errors(v, endp, endptr);
}
-void* xrealloc(void *ptr, size_t size)
-{
- ptr = realloc(ptr, size);
- if (ptr == NULL && size != 0)
- perror("no memory");
- return ptr;
-}
-
void* xrealloc_vector_helper(void *vector, unsigned sizeof_and_shift, int idx)
{
int mask = 1 << (unsigned char)sizeof_and_shift;
if (!(idx & (mask - 1))) {
sizeof_and_shift >>= 8; /* sizeof(vector[0]) */
- vector = xrealloc(vector, sizeof_and_shift * (idx + mask + 1));
+ vector = realloc(vector, sizeof_and_shift * (idx + mask + 1));
memset((char*)vector + (sizeof_and_shift * idx), 0, sizeof_and_shift * (mask + 1));
}
return vector;
@@ -402,7 +387,7 @@ pid_t* find_pid_by_name(const char *procName)
int i = 0;
procps_status_t* p = NULL;
- pidList = xzalloc(sizeof(*pidList));
+ pidList = calloc(1, sizeof(*pidList));
while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_COMM|PSSCAN_ARGVN))) {
if (comm_match(p, procName)
/* or we require argv0 to match (essential for matching reexeced /proc/self/exe)*/
diff --git a/release/src/router/shared/usb.c b/release/src/router/shared/usb.c
index 5439ef60c7..b6c78b7edf 100644
--- a/release/src/router/shared/usb.c
+++ b/release/src/router/shared/usb.c
@@ -472,86 +472,3 @@ void add_remove_usbhost(char *host, int add)
unsetenv("SCSI_HOST");
unsetenv("ACTION");
}
-
-
-/****************************************************/
-/* Use busybox routines to get labels for fat & ext */
-/* Probe for label the same way that mount does. */
-/****************************************************/
-
-#define VOLUME_ID_LABEL_SIZE 64
-#define VOLUME_ID_UUID_SIZE 36
-#define SB_BUFFER_SIZE 0x11000
-
-struct volume_id {
- int fd;
- int error;
- size_t sbbuf_len;
- size_t seekbuf_len;
- uint8_t *sbbuf;
- uint8_t *seekbuf;
- uint64_t seekbuf_off;
- char label[VOLUME_ID_LABEL_SIZE+1];
- char uuid[VOLUME_ID_UUID_SIZE+1];
-};
-
-extern void volume_id_set_uuid();
-extern void *volume_id_get_buffer();
-extern void volume_id_free_buffer();
-extern int volume_id_probe_ext();
-extern int volume_id_probe_vfat();
-extern int volume_id_probe_ntfs();
-extern int volume_id_probe_linux_swap();
-extern int volume_id_probe_hfs_hfsplus(struct volume_id *id);
-
-/* Put the label in *label and uuid in *uuid.
- * Return 0 if no label/uuid found, NZ if there is a label or uuid.
- */
-int find_label_or_uuid(char *dev_name, char *label, char *uuid)
-{
- struct volume_id id;
-
- memset(&id, 0x00, sizeof(id));
- if (label) *label = 0;
- if (uuid) *uuid = 0;
- if ((id.fd = open(dev_name, O_RDONLY)) < 0)
- return 0;
-
- volume_id_get_buffer(&id, 0, SB_BUFFER_SIZE);
-
- if (volume_id_probe_linux_swap(&id) == 0 || id.error)
- goto ret;
- if (volume_id_probe_vfat(&id) == 0 || id.error)
- goto ret;
- if (volume_id_probe_ext(&id) == 0 || id.error)
- goto ret;
- if (volume_id_probe_ntfs(&id) == 0 || id.error)
- goto ret;
-#if defined(RTCONFIG_HFS)
- if(volume_id_probe_hfs_hfsplus(&id) == 0 || id.error)
- goto ret;
-#endif
-ret:
- volume_id_free_buffer(&id);
- if (label && (*id.label != 0))
- strcpy(label, id.label);
- if (uuid && (*id.uuid != 0))
- strcpy(uuid, id.uuid);
- close(id.fd);
- return (label && *label != 0) || (uuid && *uuid != 0);
-}
-
-void *xmalloc(size_t siz)
-{
- return (malloc(siz));
-}
-#if 0
-static void *xrealloc(void *old, size_t size)
-{
- return realloc(old, size);
-}
-#endif
-ssize_t full_read(int fd, void *buf, size_t len)
-{
- return read(fd, buf, len);
-}
diff --git a/release/src/router/shared/volume_id.c b/release/src/router/shared/volume_id.c
new file mode 100644
index 0000000000..310e4d1157
--- /dev/null
+++ b/release/src/router/shared/volume_id.c
@@ -0,0 +1,124 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <errno.h>
+
+/****************************************************/
+/* Use busybox routines to get labels for fat & ext */
+/* Probe for label the same way that mount does. */
+/****************************************************/
+#include "autoconf.h"
+#include "volume_id_internal.h"
+
+#ifdef __GLIBC__
+#undef errno
+#define errno (*__errno_location ())
+#endif
+
+#pragma GCC visibility push(hidden)
+
+#ifndef DMALLOC
+void* FAST_FUNC xmalloc(size_t size)
+{
+ return malloc(size);
+}
+
+void* FAST_FUNC xrealloc(void *ptr, size_t size)
+{
+ return realloc(ptr, size);
+}
+#endif /* DMALLOC */
+
+ssize_t FAST_FUNC safe_read(int fd, void *buf, size_t count)
+{
+ ssize_t n;
+
+ do {
+ n = read(fd, buf, count);
+ } while (n < 0 && errno == EINTR);
+
+ return n;
+}
+
+/*
+ * Read all of the supplied buffer from a file.
+ * This does multiple reads as necessary.
+ * Returns the amount read, or -1 on an error.
+ * A short read is returned on an end of file.
+ */
+ssize_t FAST_FUNC full_read(int fd, void *buf, size_t len)
+{
+ ssize_t cc;
+ ssize_t total;
+
+ total = 0;
+
+ while (len) {
+ cc = safe_read(fd, buf, len);
+
+ if (cc < 0) {
+ if (total) {
+ /* we already have some! */
+ /* user can do another read to know the error code */
+ return total;
+ }
+ return cc; /* read() returns -1 on failure. */
+ }
+ if (cc == 0)
+ break;
+ buf = ((char *)buf) + cc;
+ total += cc;
+ len -= cc;
+ }
+
+ return total;
+}
+
+#pragma GCC visibility pop
+
+/* Put the label in *label and uuid in *uuid.
+ * Return 0 if no label/uuid found, NZ if there is a label or uuid.
+ * Return -1 if no device found.
+ */
+int find_label_or_uuid(char *dev_name, char *label, char *uuid)
+{
+ struct volume_id id;
+
+ memset(&id, 0, sizeof(id));
+ if (label) *label = 0;
+ if (uuid) *uuid = 0;
+
+ if ((id.fd = open(dev_name, O_RDONLY)) < 0)
+ return -1;
+
+ volume_id_get_buffer(&id, 0, SB_BUFFER_SIZE);
+
+ if (volume_id_probe_linux_swap(&id) == 0 || id.error)
+ goto ret;
+ if (volume_id_probe_vfat(&id) == 0 || id.error)
+ goto ret;
+ if (volume_id_probe_ext(&id) == 0 || id.error)
+ goto ret;
+ if (volume_id_probe_ntfs(&id) == 0 || id.error)
+ goto ret;
+#if defined(RTCONFIG_HFS)
+ if (volume_id_probe_hfs_hfsplus(&id) == 0 || id.error)
+ goto ret;
+#endif
+ret:
+ volume_id_free_buffer(&id);
+
+ close(id.fd);
+
+ if (label && *id.label != 0)
+ strcpy(label, id.label);
+ if (uuid && *id.uuid != 0)
+ strcpy(uuid, id.uuid);
+
+ return (label && *label) || (uuid && *uuid);
+}