aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2015-08-04 09:46:24 +0100
committerRon Yorston <rmy@pobox.com>2015-08-04 09:46:24 +0100
commit64fde14d12cc5e6182f114ecaf4340ec1854c2f6 (patch)
tree4d2cabca7865dd74e2344834d89503c534fb502c
parent7aabb625005c642d6a30d6d97b51bf183429152e (diff)
parent16aa7a73c40ba5dfaabaedb8a5533619cb8b6cb6 (diff)
downloadbusybox-w32-64fde14d12cc5e6182f114ecaf4340ec1854c2f6.tar.gz
busybox-w32-64fde14d12cc5e6182f114ecaf4340ec1854c2f6.tar.bz2
busybox-w32-64fde14d12cc5e6182f114ecaf4340ec1854c2f6.zip
Merge branch 'busybox' into merge
-rw-r--r--coreutils/Config.src14
-rw-r--r--coreutils/Kbuild.src1
-rw-r--r--coreutils/echo.c2
-rw-r--r--coreutils/sync.c78
-rw-r--r--coreutils/uname.c10
-rw-r--r--e2fsprogs/old_e2fsprogs/Config.src69
-rw-r--r--e2fsprogs/old_e2fsprogs/Kbuild.src18
-rw-r--r--e2fsprogs/old_e2fsprogs/README3
-rw-r--r--e2fsprogs/old_e2fsprogs/blkid/Kbuild.src26
-rw-r--r--e2fsprogs/old_e2fsprogs/blkid/blkid.h104
-rw-r--r--e2fsprogs/old_e2fsprogs/blkid/blkidP.h182
-rw-r--r--e2fsprogs/old_e2fsprogs/blkid/blkid_getsize.c179
-rw-r--r--e2fsprogs/old_e2fsprogs/blkid/cache.c125
-rw-r--r--e2fsprogs/old_e2fsprogs/blkid/dev.c212
-rw-r--r--e2fsprogs/old_e2fsprogs/blkid/devname.c367
-rw-r--r--e2fsprogs/old_e2fsprogs/blkid/devno.c222
-rw-r--r--e2fsprogs/old_e2fsprogs/blkid/list.c110
-rw-r--r--e2fsprogs/old_e2fsprogs/blkid/list.h73
-rw-r--r--e2fsprogs/old_e2fsprogs/blkid/probe.c726
-rw-r--r--e2fsprogs/old_e2fsprogs/blkid/probe.h374
-rw-r--r--e2fsprogs/old_e2fsprogs/blkid/read.c459
-rw-r--r--e2fsprogs/old_e2fsprogs/blkid/resolve.c139
-rw-r--r--e2fsprogs/old_e2fsprogs/blkid/save.c189
-rw-r--r--e2fsprogs/old_e2fsprogs/blkid/tag.c431
-rw-r--r--e2fsprogs/old_e2fsprogs/chattr.c220
-rw-r--r--e2fsprogs/old_e2fsprogs/e2fsbb.h43
-rw-r--r--e2fsprogs/old_e2fsprogs/e2fsck.c13516
-rw-r--r--e2fsprogs/old_e2fsprogs/e2fsck.h638
-rw-r--r--e2fsprogs/old_e2fsprogs/e2p/Kbuild.src18
-rw-r--r--e2fsprogs/old_e2fsprogs/e2p/e2p.h64
-rw-r--r--e2fsprogs/old_e2fsprogs/e2p/feature.c187
-rw-r--r--e2fsprogs/old_e2fsprogs/e2p/fgetsetflags.c70
-rw-r--r--e2fsprogs/old_e2fsprogs/e2p/fgetsetversion.c70
-rw-r--r--e2fsprogs/old_e2fsprogs/e2p/hashstr.c70
-rw-r--r--e2fsprogs/old_e2fsprogs/e2p/iod.c52
-rw-r--r--e2fsprogs/old_e2fsprogs/e2p/ls.c273
-rw-r--r--e2fsprogs/old_e2fsprogs/e2p/mntopts.c134
-rw-r--r--e2fsprogs/old_e2fsprogs/e2p/ostype.c72
-rw-r--r--e2fsprogs/old_e2fsprogs/e2p/parse_num.c65
-rw-r--r--e2fsprogs/old_e2fsprogs/e2p/pe.c32
-rw-r--r--e2fsprogs/old_e2fsprogs/e2p/pf.c74
-rw-r--r--e2fsprogs/old_e2fsprogs/e2p/ps.c27
-rw-r--r--e2fsprogs/old_e2fsprogs/e2p/uuid.c78
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/Kbuild.src26
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/alloc.c173
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/alloc_sb.c58
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/alloc_stats.c53
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/alloc_tables.c114
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/badblocks.c328
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/bb_compat.c64
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/bb_inode.c262
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/bitmaps.c211
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/bitops.c90
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/bitops.h105
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/block.c437
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/bmap.c261
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/bmove.c155
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/brel.h86
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/brel_ma.c196
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/check_desc.c69
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/closefs.c380
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/cmp_bitmaps.c72
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/dblist.c260
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/dblist_dir.c76
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/dir_iterate.c219
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/dirblock.c132
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/dirhash.c234
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/dupfs.c95
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/e2image.h39
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/expanddir.c127
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/ext2_err.h116
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/ext2_ext_attr.h52
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/ext2_fs.h569
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/ext2_io.h112
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/ext2_types.h2
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/ext2fs.h922
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/ext2fsP.h87
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/ext2fs_inline.c365
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/ext_attr.c101
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/fileio.c377
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/finddev.c199
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/flushb.c83
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/freefs.c127
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/gen_bitmap.c49
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/get_pathname.c156
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/getsectsize.c58
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/getsize.c291
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/icount.c467
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/imager.c377
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/ind_block.c69
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/initialize.c388
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/inline.c32
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/inode.c766
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/inode_io.c270
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/io_manager.c70
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/irel.h115
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/irel_ma.c367
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/ismounted.c357
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/jfs_dat.h63
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/kernel-jbd.h235
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/kernel-list.h113
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/link.c135
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/lookup.c68
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/mkdir.c139
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/mkjournal.c426
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/namei.c204
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/newdir.c72
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/openfs.c330
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/read_bb.c96
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/read_bb_file.c96
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/res_gdt.c220
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/rs_bitmap.c106
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/rw_bitmaps.c294
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/sparse.c79
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/swapfs.c234
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/test_io.c380
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/unix_io.c703
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/unlink.c99
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/valid_blk.c57
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/version.c51
-rw-r--r--e2fsprogs/old_e2fsprogs/ext2fs/write_bb_file.c35
-rw-r--r--e2fsprogs/old_e2fsprogs/fsck.c1371
-rw-r--r--e2fsprogs/old_e2fsprogs/fsck.h16
-rw-r--r--e2fsprogs/old_e2fsprogs/lsattr.c129
-rw-r--r--e2fsprogs/old_e2fsprogs/mke2fs.c1333
-rw-r--r--e2fsprogs/old_e2fsprogs/tune2fs.c710
-rw-r--r--e2fsprogs/old_e2fsprogs/util.c263
-rw-r--r--e2fsprogs/old_e2fsprogs/util.h22
-rw-r--r--e2fsprogs/old_e2fsprogs/uuid/Kbuild.src16
-rw-r--r--e2fsprogs/old_e2fsprogs/uuid/compare.c55
-rw-r--r--e2fsprogs/old_e2fsprogs/uuid/gen_uuid.c304
-rw-r--r--e2fsprogs/old_e2fsprogs/uuid/pack.c69
-rw-r--r--e2fsprogs/old_e2fsprogs/uuid/parse.c80
-rw-r--r--e2fsprogs/old_e2fsprogs/uuid/unpack.c63
-rw-r--r--e2fsprogs/old_e2fsprogs/uuid/unparse.c77
-rw-r--r--e2fsprogs/old_e2fsprogs/uuid/uuid.h103
-rw-r--r--e2fsprogs/old_e2fsprogs/uuid/uuidP.h60
-rw-r--r--e2fsprogs/old_e2fsprogs/uuid/uuid_time.c161
-rw-r--r--editors/diff.c4
-rw-r--r--include/applets.src.h1
-rw-r--r--include/libbb.h1
-rw-r--r--libbb/procps.c3
-rw-r--r--libbb/xfuncs_printf.c5
-rw-r--r--miscutils/last_fancy.c4
-rw-r--r--miscutils/less.c324
-rw-r--r--networking/traceroute.c11
-rw-r--r--networking/udhcp/d6_dhcpc.c2
-rw-r--r--networking/udhcp/dhcpc.c4
-rw-r--r--networking/zcip.c235
-rw-r--r--shell/ash.c2
-rwxr-xr-xtestsuite/diff.tests12
-rw-r--r--util-linux/fbset.c8
-rw-r--r--util-linux/mdev.c2
153 files changed, 433 insertions, 40334 deletions
diff --git a/coreutils/Config.src b/coreutils/Config.src
index 68857b2cc..21b97d382 100644
--- a/coreutils/Config.src
+++ b/coreutils/Config.src
@@ -570,12 +570,6 @@ config SUM
570 help 570 help
571 checksum and count the blocks in a file 571 checksum and count the blocks in a file
572 572
573config SYNC
574 bool "sync"
575 default y
576 help
577 sync is used to flush filesystem buffers.
578
579config TAC 573config TAC
580 bool "tac" 574 bool "tac"
581 default y 575 default y
@@ -635,6 +629,14 @@ config UNAME
635 help 629 help
636 uname is used to print system information. 630 uname is used to print system information.
637 631
632config UNAME_OSNAME
633 string "Operating system name"
634 default "GNU/Linux"
635 depends on UNAME
636 help
637 Sets the operating system name reported by uname -o. The
638 default is "GNU/Linux".
639
638config UNEXPAND 640config UNEXPAND
639 bool "unexpand" 641 bool "unexpand"
640 default y 642 default y
diff --git a/coreutils/Kbuild.src b/coreutils/Kbuild.src
index ec4ef7df2..4ec075ac6 100644
--- a/coreutils/Kbuild.src
+++ b/coreutils/Kbuild.src
@@ -68,7 +68,6 @@ lib-$(CONFIG_SORT) += sort.o
68lib-$(CONFIG_STAT) += stat.o 68lib-$(CONFIG_STAT) += stat.o
69lib-$(CONFIG_STTY) += stty.o 69lib-$(CONFIG_STTY) += stty.o
70lib-$(CONFIG_SUM) += sum.o 70lib-$(CONFIG_SUM) += sum.o
71lib-$(CONFIG_SYNC) += sync.o
72lib-$(CONFIG_TAC) += tac.o 71lib-$(CONFIG_TAC) += tac.o
73lib-$(CONFIG_TEE) += tee.o 72lib-$(CONFIG_TEE) += tee.o
74lib-$(CONFIG_TRUE) += true.o 73lib-$(CONFIG_TRUE) += true.o
diff --git a/coreutils/echo.c b/coreutils/echo.c
index 9663894ec..1c4174559 100644
--- a/coreutils/echo.c
+++ b/coreutils/echo.c
@@ -72,7 +72,7 @@ int echo_main(int argc UNUSED_PARAM, char **argv)
72 unsigned buflen; 72 unsigned buflen;
73#if !ENABLE_FEATURE_FANCY_ECHO 73#if !ENABLE_FEATURE_FANCY_ECHO
74 enum { 74 enum {
75 eflag = '\\', 75 eflag = 0, /* 0 -- disable escape sequences */
76 nflag = 1, /* 1 -- print '\n' */ 76 nflag = 1, /* 1 -- print '\n' */
77 }; 77 };
78 78
diff --git a/coreutils/sync.c b/coreutils/sync.c
index 7d98a1e30..974e90452 100644
--- a/coreutils/sync.c
+++ b/coreutils/sync.c
@@ -3,16 +3,39 @@
3 * Mini sync implementation for busybox 3 * Mini sync implementation for busybox
4 * 4 *
5 * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>. 5 * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
6 * Copyright (C) 2015 by Ari Sundholm <ari@tuxera.com>
6 * 7 *
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 9 */
9 10
10/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */ 11/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
12//config:config SYNC
13//config: bool "sync"
14//config: default y
15//config: help
16//config: sync is used to flush filesystem buffers.
17//config:config FEATURE_SYNC_FANCY
18//config: bool "Enable -d and -f flags (requres syncfs(2) in libc)"
19//config: default y
20//config: depends on SYNC
21//config: help
22//config: sync -d FILE... executes fdatasync() on each FILE.
23//config: sync -f FILE... executes syncfs() on each FILE.
24
25//kbuild:lib-$(CONFIG_SYNC) += sync.o
26//applet:IF_SYNC(APPLET_NOFORK(sync, sync, BB_DIR_BIN, BB_SUID_DROP, sync))
11 27
12//usage:#define sync_trivial_usage 28//usage:#define sync_trivial_usage
13//usage: "" 29//usage: ""IF_FEATURE_SYNC_FANCY("[-df] [FILE]...")
14//usage:#define sync_full_usage "\n\n" 30//usage:#define sync_full_usage "\n\n"
31//usage: IF_NOT_FEATURE_SYNC_FANCY(
15//usage: "Write all buffered blocks to disk" 32//usage: "Write all buffered blocks to disk"
33//usage: )
34//usage: IF_FEATURE_SYNC_FANCY(
35//usage: "Write all buffered blocks (in FILEs) to disk"
36//usage: "\n -d Avoid syncing metadata"
37//usage: "\n -f Sync filesystems underlying FILEs"
38//usage: )
16 39
17#include "libbb.h" 40#include "libbb.h"
18 41
@@ -21,10 +44,59 @@
21int sync_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 44int sync_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
22int sync_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) 45int sync_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM))
23{ 46{
47#if !ENABLE_FEATURE_SYNC_FANCY
24 /* coreutils-6.9 compat */ 48 /* coreutils-6.9 compat */
25 bb_warn_ignoring_args(argv[1]); 49 bb_warn_ignoring_args(argv[1]);
26
27 sync(); 50 sync();
28
29 return EXIT_SUCCESS; 51 return EXIT_SUCCESS;
52#else
53 unsigned opts;
54 int ret = EXIT_SUCCESS;
55
56 enum {
57 OPT_DATASYNC = (1 << 0),
58 OPT_SYNCFS = (1 << 1),
59 };
60
61 opt_complementary = "d--f:f--d";
62 opts = getopt32(argv, "df");
63 argv += optind;
64
65 /* Handle the no-argument case. */
66 if (!argv[0])
67 sync();
68
69 while (*argv) {
70 int fd = open_or_warn(*argv, O_RDONLY);
71
72 if (fd < 0) {
73 ret = EXIT_FAILURE;
74 goto next;
75 }
76 if (opts & OPT_DATASYNC) {
77 if (fdatasync(fd))
78 goto err;
79 goto do_close;
80 }
81 if (opts & OPT_SYNCFS) {
82 /*
83 * syncfs is documented to only fail with EBADF,
84 * which can't happen here. So, no error checks.
85 */
86 syncfs(fd);
87 goto do_close;
88 }
89 if (fsync(fd)) {
90 err:
91 bb_simple_perror_msg(*argv);
92 ret = EXIT_FAILURE;
93 }
94 do_close:
95 close(fd);
96 next:
97 ++argv;
98 }
99
100 return ret;
101#endif
30} 102}
diff --git a/coreutils/uname.c b/coreutils/uname.c
index 56d985eb0..fd677d27c 100644
--- a/coreutils/uname.c
+++ b/coreutils/uname.c
@@ -70,17 +70,11 @@
70/* After libbb.h, since it needs sys/types.h on some systems */ 70/* After libbb.h, since it needs sys/types.h on some systems */
71#include <sys/utsname.h> 71#include <sys/utsname.h>
72 72
73#if ENABLE_PLATFORM_MINGW32
74# define OSNAME "MS/Windows"
75#else
76# define OSNAME "GNU/Linux"
77#endif
78
79typedef struct { 73typedef struct {
80 struct utsname name; 74 struct utsname name;
81 char processor[sizeof(((struct utsname*)NULL)->machine)]; 75 char processor[sizeof(((struct utsname*)NULL)->machine)];
82 char platform[sizeof(((struct utsname*)NULL)->machine)]; 76 char platform[sizeof(((struct utsname*)NULL)->machine)];
83 char os[sizeof(OSNAME)]; 77 char os[sizeof(CONFIG_UNAME_OSNAME)];
84} uname_info_t; 78} uname_info_t;
85 79
86static const char options[] ALIGN1 = "snrvmpioa"; 80static const char options[] ALIGN1 = "snrvmpioa";
@@ -147,7 +141,7 @@ int uname_main(int argc UNUSED_PARAM, char **argv)
147#endif 141#endif
148 strcpy(uname_info.processor, unknown_str); 142 strcpy(uname_info.processor, unknown_str);
149 strcpy(uname_info.platform, unknown_str); 143 strcpy(uname_info.platform, unknown_str);
150 strcpy(uname_info.os, OSNAME); 144 strcpy(uname_info.os, CONFIG_UNAME_OSNAME);
151#if 0 145#if 0
152 /* Fedora does something like this */ 146 /* Fedora does something like this */
153 strcpy(uname_info.processor, uname_info.name.machine); 147 strcpy(uname_info.processor, uname_info.name.machine);
diff --git a/e2fsprogs/old_e2fsprogs/Config.src b/e2fsprogs/old_e2fsprogs/Config.src
deleted file mode 100644
index bbec08e7e..000000000
--- a/e2fsprogs/old_e2fsprogs/Config.src
+++ /dev/null
@@ -1,69 +0,0 @@
1#
2# For a description of the syntax of this configuration file,
3# see scripts/kbuild/config-language.txt.
4#
5
6menu "Linux Ext2 FS Progs"
7
8INSERT
9
10config CHATTR
11 bool "chattr"
12 default n
13 help
14 chattr changes the file attributes on a second extended file system.
15
16config E2FSCK
17 bool "e2fsck"
18 default n
19 help
20 e2fsck is used to check Linux second extended file systems (ext2fs).
21 e2fsck also supports ext2 filesystems countaining a journal (ext3).
22 The normal compat symlinks 'fsck.ext2' and 'fsck.ext3' are also
23 provided.
24
25config FSCK
26 bool "fsck"
27 default n
28 help
29 fsck is used to check and optionally repair one or more filesystems.
30 In actuality, fsck is simply a front-end for the various file system
31 checkers (fsck.fstype) available under Linux.
32
33config LSATTR
34 bool "lsattr"
35 default n
36 help
37 lsattr lists the file attributes on a second extended file system.
38
39config MKE2FS
40 bool "mke2fs"
41 default n
42 help
43 mke2fs is used to create an ext2/ext3 filesystem. The normal compat
44 symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided.
45
46config TUNE2FS
47 bool "tune2fs"
48 default n
49 help
50 tune2fs allows the system administrator to adjust various tunable
51 filesystem parameters on Linux ext2/ext3 filesystems.
52
53config E2LABEL
54 bool "e2label"
55 default n
56 depends on TUNE2FS
57 help
58 e2label will display or change the filesystem label on the ext2
59 filesystem located on device.
60
61config FINDFS
62 bool "findfs"
63 default n
64 depends on TUNE2FS
65 help
66 findfs will search the disks in the system looking for a filesystem
67 which has a label matching label or a UUID equal to uuid.
68
69endmenu
diff --git a/e2fsprogs/old_e2fsprogs/Kbuild.src b/e2fsprogs/old_e2fsprogs/Kbuild.src
deleted file mode 100644
index fff1a0d6f..000000000
--- a/e2fsprogs/old_e2fsprogs/Kbuild.src
+++ /dev/null
@@ -1,18 +0,0 @@
1# Makefile for busybox
2#
3# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
4#
5# Licensed under GPLv2, see file LICENSE in this source tree.
6
7lib-y:=
8
9INSERT
10
11lib-$(CONFIG_CHATTR) += chattr.o
12lib-$(CONFIG_E2FSCK) += e2fsck.o util.o
13lib-$(CONFIG_FSCK) += fsck.o util.o
14lib-$(CONFIG_LSATTR) += lsattr.o
15lib-$(CONFIG_MKE2FS) += mke2fs.o util.o
16lib-$(CONFIG_TUNE2FS) += tune2fs.o util.o
17
18CFLAGS += -include $(srctree)/e2fsprogs/e2fsbb.h
diff --git a/e2fsprogs/old_e2fsprogs/README b/e2fsprogs/old_e2fsprogs/README
deleted file mode 100644
index fac090193..000000000
--- a/e2fsprogs/old_e2fsprogs/README
+++ /dev/null
@@ -1,3 +0,0 @@
1This is a pretty straight rip from the e2fsprogs pkg.
2
3See README's in subdirs for specific info.
diff --git a/e2fsprogs/old_e2fsprogs/blkid/Kbuild.src b/e2fsprogs/old_e2fsprogs/blkid/Kbuild.src
deleted file mode 100644
index 02b4d2496..000000000
--- a/e2fsprogs/old_e2fsprogs/blkid/Kbuild.src
+++ /dev/null
@@ -1,26 +0,0 @@
1# Makefile for busybox
2#
3# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
4#
5# Licensed under GPLv2, see file LICENSE in this source tree.
6
7NEEDED-$(CONFIG_E2FSCK) = y
8NEEDED-$(CONFIG_FSCK) = y
9NEEDED-$(CONFIG_MKE2FS) = y
10NEEDED-$(CONFIG_TUNE2FS) = y
11
12lib-y:=
13
14INSERT
15
16lib-$(NEEDED-y) += cache.o dev.o devname.o devno.o blkid_getsize.o \
17 probe.o read.o resolve.o save.o tag.o list.o
18
19CFLAGS_dev.o := -include $(srctree)/include/busybox.h
20CFLAGS_devname.o := -include $(srctree)/include/busybox.h
21CFLAGS_devno.o := -include $(srctree)/include/busybox.h
22CFLAGS_blkid_getsize.o := -include $(srctree)/include/busybox.h
23CFLAGS_probe.o := -include $(srctree)/include/busybox.h
24CFLAGS_save.o := -include $(srctree)/include/busybox.h
25CFLAGS_tag.o := -include $(srctree)/include/busybox.h
26CFLAGS_list.o := -include $(srctree)/include/busybox.h
diff --git a/e2fsprogs/old_e2fsprogs/blkid/blkid.h b/e2fsprogs/old_e2fsprogs/blkid/blkid.h
deleted file mode 100644
index 9a3c2afdb..000000000
--- a/e2fsprogs/old_e2fsprogs/blkid/blkid.h
+++ /dev/null
@@ -1,104 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * blkid.h - Interface for libblkid, a library to identify block devices
4 *
5 * Copyright (C) 2001 Andreas Dilger
6 * Copyright (C) 2003 Theodore Ts'o
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the
10 * GNU Lesser General Public License.
11 * %End-Header%
12 */
13#ifndef BLKID_BLKID_H
14#define BLKID_BLKID_H 1
15
16#include <sys/types.h>
17#include <linux/types.h>
18
19#ifdef __cplusplus
20extern "C" {
21#endif
22
23#define BLKID_VERSION "1.0.0"
24#define BLKID_DATE "12-Feb-2003"
25
26typedef struct blkid_struct_dev *blkid_dev;
27typedef struct blkid_struct_cache *blkid_cache;
28typedef __s64 blkid_loff_t;
29
30typedef struct blkid_struct_tag_iterate *blkid_tag_iterate;
31typedef struct blkid_struct_dev_iterate *blkid_dev_iterate;
32
33/*
34 * Flags for blkid_get_dev
35 *
36 * BLKID_DEV_CREATE Create an empty device structure if not found
37 * in the cache.
38 * BLKID_DEV_VERIFY Make sure the device structure corresponds
39 * with reality.
40 * BLKID_DEV_FIND Just look up a device entry, and return NULL
41 * if it is not found.
42 * BLKID_DEV_NORMAL Get a valid device structure, either from the
43 * cache or by probing the device.
44 */
45#define BLKID_DEV_FIND 0x0000
46#define BLKID_DEV_CREATE 0x0001
47#define BLKID_DEV_VERIFY 0x0002
48#define BLKID_DEV_NORMAL (BLKID_DEV_CREATE | BLKID_DEV_VERIFY)
49
50/* cache.c */
51extern void blkid_put_cache(blkid_cache cache);
52extern int blkid_get_cache(blkid_cache *cache, const char *filename);
53
54/* dev.c */
55extern const char *blkid_dev_devname(blkid_dev dev);
56
57extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache);
58extern int blkid_dev_set_search(blkid_dev_iterate iter,
59 char *search_type, char *search_value);
60extern int blkid_dev_next(blkid_dev_iterate iterate, blkid_dev *dev);
61extern void blkid_dev_iterate_end(blkid_dev_iterate iterate);
62
63/* devno.c */
64extern char *blkid_devno_to_devname(dev_t devno);
65
66/* devname.c */
67extern int blkid_probe_all(blkid_cache cache);
68extern int blkid_probe_all_new(blkid_cache cache);
69extern blkid_dev blkid_get_dev(blkid_cache cache, const char *devname,
70 int flags);
71
72/* getsize.c */
73extern blkid_loff_t blkid_get_dev_size(int fd);
74
75/* probe.c */
76int blkid_known_fstype(const char *fstype);
77extern blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev);
78
79/* read.c */
80
81/* resolve.c */
82extern char *blkid_get_tag_value(blkid_cache cache, const char *tagname,
83 const char *devname);
84extern char *blkid_get_devname(blkid_cache cache, const char *token,
85 const char *value);
86
87/* tag.c */
88extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev);
89extern int blkid_tag_next(blkid_tag_iterate iterate,
90 const char **type, const char **value);
91extern void blkid_tag_iterate_end(blkid_tag_iterate iterate);
92extern int blkid_dev_has_tag(blkid_dev dev, const char *type,
93 const char *value);
94extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
95 const char *type,
96 const char *value);
97extern int blkid_parse_tag_string(const char *token, char **ret_type,
98 char **ret_val);
99
100#ifdef __cplusplus
101}
102#endif
103
104#endif
diff --git a/e2fsprogs/old_e2fsprogs/blkid/blkidP.h b/e2fsprogs/old_e2fsprogs/blkid/blkidP.h
deleted file mode 100644
index bbadc8eb5..000000000
--- a/e2fsprogs/old_e2fsprogs/blkid/blkidP.h
+++ /dev/null
@@ -1,182 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * blkidP.h - Internal interfaces for libblkid
4 *
5 * Copyright (C) 2001 Andreas Dilger
6 * Copyright (C) 2003 Theodore Ts'o
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the
10 * GNU Lesser General Public License.
11 * %End-Header%
12 */
13#ifndef BLKID_BLKIDP_H
14#define BLKID_BLKIDP_H 1
15
16#include <sys/types.h>
17#include <stdio.h>
18
19#include "blkid.h"
20#include "list.h"
21
22#ifdef __GNUC__
23#define __BLKID_ATTR(x) __attribute__(x)
24#else
25#define __BLKID_ATTR(x)
26#endif
27
28
29/*
30 * This describes the attributes of a specific device.
31 * We can traverse all of the tags by bid_tags (linking to the tag bit_names).
32 * The bid_label and bid_uuid fields are shortcuts to the LABEL and UUID tag
33 * values, if they exist.
34 */
35struct blkid_struct_dev
36{
37 struct list_head bid_devs; /* All devices in the cache */
38 struct list_head bid_tags; /* All tags for this device */
39 blkid_cache bid_cache; /* Dev belongs to this cache */
40 char *bid_name; /* Device inode pathname */
41 char *bid_type; /* Preferred device TYPE */
42 int bid_pri; /* Device priority */
43 dev_t bid_devno; /* Device major/minor number */
44 time_t bid_time; /* Last update time of device */
45 unsigned int bid_flags; /* Device status bitflags */
46 char *bid_label; /* Shortcut to device LABEL */
47 char *bid_uuid; /* Shortcut to binary UUID */
48};
49
50#define BLKID_BID_FL_VERIFIED 0x0001 /* Device data validated from disk */
51#define BLKID_BID_FL_INVALID 0x0004 /* Device is invalid */
52
53/*
54 * Each tag defines a NAME=value pair for a particular device. The tags
55 * are linked via bit_names for a single device, so that traversing the
56 * names list will get you a list of all tags associated with a device.
57 * They are also linked via bit_values for all devices, so one can easily
58 * search all tags with a given NAME for a specific value.
59 */
60struct blkid_struct_tag
61{
62 struct list_head bit_tags; /* All tags for this device */
63 struct list_head bit_names; /* All tags with given NAME */
64 char *bit_name; /* NAME of tag (shared) */
65 char *bit_val; /* value of tag */
66 blkid_dev bit_dev; /* pointer to device */
67};
68typedef struct blkid_struct_tag *blkid_tag;
69
70/*
71 * Minimum number of seconds between device probes, even when reading
72 * from the cache. This is to avoid re-probing all devices which were
73 * just probed by another program that does not share the cache.
74 */
75#define BLKID_PROBE_MIN 2
76
77/*
78 * Time in seconds an entry remains verified in the in-memory cache
79 * before being reverified (in case of long-running processes that
80 * keep a cache in memory and continue to use it for a long time).
81 */
82#define BLKID_PROBE_INTERVAL 200
83
84/* This describes an entire blkid cache file and probed devices.
85 * We can traverse all of the found devices via bic_list.
86 * We can traverse all of the tag types by bic_tags, which hold empty tags
87 * for each tag type. Those tags can be used as list_heads for iterating
88 * through all devices with a specific tag type (e.g. LABEL).
89 */
90struct blkid_struct_cache
91{
92 struct list_head bic_devs; /* List head of all devices */
93 struct list_head bic_tags; /* List head of all tag types */
94 time_t bic_time; /* Last probe time */
95 time_t bic_ftime; /* Mod time of the cachefile */
96 unsigned int bic_flags; /* Status flags of the cache */
97 char *bic_filename; /* filename of cache */
98};
99
100#define BLKID_BIC_FL_PROBED 0x0002 /* We probed /proc/partition devices */
101#define BLKID_BIC_FL_CHANGED 0x0004 /* Cache has changed from disk */
102
103extern char *blkid_strdup(const char *s);
104extern char *blkid_strndup(const char *s, const int length);
105
106#define BLKID_CACHE_FILE "/etc/blkid.tab"
107extern const char *blkid_devdirs[];
108
109#define BLKID_ERR_IO 5
110#define BLKID_ERR_PROC 9
111#define BLKID_ERR_MEM 12
112#define BLKID_ERR_CACHE 14
113#define BLKID_ERR_DEV 19
114#define BLKID_ERR_PARAM 22
115#define BLKID_ERR_BIG 27
116
117/*
118 * Priority settings for different types of devices
119 */
120#define BLKID_PRI_EVMS 30
121#define BLKID_PRI_LVM 20
122#define BLKID_PRI_MD 10
123
124#if defined(TEST_PROGRAM) && !defined(CONFIG_BLKID_DEBUG)
125#define CONFIG_BLKID_DEBUG
126#endif
127
128#define DEBUG_CACHE 0x0001
129#define DEBUG_DUMP 0x0002
130#define DEBUG_DEV 0x0004
131#define DEBUG_DEVNAME 0x0008
132#define DEBUG_DEVNO 0x0010
133#define DEBUG_PROBE 0x0020
134#define DEBUG_READ 0x0040
135#define DEBUG_RESOLVE 0x0080
136#define DEBUG_SAVE 0x0100
137#define DEBUG_TAG 0x0200
138#define DEBUG_INIT 0x8000
139#define DEBUG_ALL 0xFFFF
140
141#ifdef CONFIG_BLKID_DEBUG
142#include <stdio.h>
143extern int blkid_debug_mask;
144#define DBG(m,x) if ((m) & blkid_debug_mask) x;
145#else
146#define DBG(m,x)
147#endif
148
149#ifdef CONFIG_BLKID_DEBUG
150extern void blkid_debug_dump_dev(blkid_dev dev);
151extern void blkid_debug_dump_tag(blkid_tag tag);
152#endif
153
154/* lseek.c */
155/* extern blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence); */
156#ifdef CONFIG_LFS
157# define blkid_llseek lseek64
158#else
159# define blkid_llseek lseek
160#endif
161
162/* read.c */
163extern void blkid_read_cache(blkid_cache cache);
164
165/* save.c */
166extern int blkid_flush_cache(blkid_cache cache);
167
168/*
169 * Functions to create and find a specific tag type: tag.c
170 */
171extern void blkid_free_tag(blkid_tag tag);
172extern blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type);
173extern int blkid_set_tag(blkid_dev dev, const char *name,
174 const char *value, const int vlength);
175
176/*
177 * Functions to create and find a specific tag type: dev.c
178 */
179extern blkid_dev blkid_new_dev(void);
180extern void blkid_free_dev(blkid_dev dev);
181
182#endif
diff --git a/e2fsprogs/old_e2fsprogs/blkid/blkid_getsize.c b/e2fsprogs/old_e2fsprogs/blkid/blkid_getsize.c
deleted file mode 100644
index e1f6ba6d2..000000000
--- a/e2fsprogs/old_e2fsprogs/blkid/blkid_getsize.c
+++ /dev/null
@@ -1,179 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * getsize.c --- get the size of a partition.
4 *
5 * Copyright (C) 1995, 1995 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the
9 * GNU Lesser General Public License.
10 * %End-Header%
11 */
12
13/* include this before sys/queues.h! */
14#include "blkidP.h"
15
16#include <stdio.h>
17#include <unistd.h>
18#ifdef HAVE_ERRNO_H
19#include <errno.h>
20#endif
21#include <fcntl.h>
22#ifdef HAVE_SYS_IOCTL_H
23#include <sys/ioctl.h>
24#endif
25#ifdef HAVE_LINUX_FD_H
26#include <linux/fd.h>
27#endif
28#ifdef HAVE_SYS_DISKLABEL_H
29#include <sys/disklabel.h>
30#include <sys/stat.h>
31#endif
32#ifdef HAVE_SYS_DISK_H
33#ifdef HAVE_SYS_QUEUE_H
34#include <sys/queue.h> /* for LIST_HEAD */
35#endif
36#include <sys/disk.h>
37#endif
38#ifdef __linux__
39#include <sys/utsname.h>
40#endif
41
42#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
43#define BLKGETSIZE _IO(0x12,96) /* return device size */
44#endif
45
46#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
47#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
48#endif
49
50#ifdef APPLE_DARWIN
51#define BLKGETSIZE DKIOCGETBLOCKCOUNT32
52#endif /* APPLE_DARWIN */
53
54static int valid_offset(int fd, blkid_loff_t offset)
55{
56 char ch;
57
58 if (blkid_llseek(fd, offset, 0) < 0)
59 return 0;
60 if (read(fd, &ch, 1) < 1)
61 return 0;
62 return 1;
63}
64
65/*
66 * Returns the number of blocks in a partition
67 */
68blkid_loff_t blkid_get_dev_size(int fd)
69{
70 int valid_blkgetsize64 = 1;
71#ifdef __linux__
72 struct utsname ut;
73#endif
74 unsigned long long size64;
75 unsigned long size;
76 blkid_loff_t high, low;
77#ifdef FDGETPRM
78 struct floppy_struct this_floppy;
79#endif
80#ifdef HAVE_SYS_DISKLABEL_H
81 int part = -1;
82 struct disklabel lab;
83 struct partition *pp;
84 char ch;
85 struct stat st;
86#endif /* HAVE_SYS_DISKLABEL_H */
87
88#ifdef DKIOCGETBLOCKCOUNT /* For Apple Darwin */
89 if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) {
90 if ((sizeof(blkid_loff_t) < sizeof(unsigned long long))
91 && (size64 << 9 > 0xFFFFFFFF))
92 return 0; /* EFBIG */
93 return (blkid_loff_t) size64 << 9;
94 }
95#endif
96
97#ifdef BLKGETSIZE64
98#ifdef __linux__
99 uname(&ut);
100 if ((ut.release[0] == '2') && (ut.release[1] == '.') &&
101 (ut.release[2] < '6') && (ut.release[3] == '.'))
102 valid_blkgetsize64 = 0;
103#endif
104 if (valid_blkgetsize64 &&
105 ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
106 if ((sizeof(blkid_loff_t) < sizeof(unsigned long long))
107 && ((size64) > 0xFFFFFFFF))
108 return 0; /* EFBIG */
109 return size64;
110 }
111#endif
112
113#ifdef BLKGETSIZE
114 if (ioctl(fd, BLKGETSIZE, &size) >= 0)
115 return (blkid_loff_t)size << 9;
116#endif
117
118#ifdef FDGETPRM
119 if (ioctl(fd, FDGETPRM, &this_floppy) >= 0)
120 return (blkid_loff_t)this_floppy.size << 9;
121#endif
122#ifdef HAVE_SYS_DISKLABEL_H
123#if 0
124 /*
125 * This should work in theory but I haven't tested it. Anyone
126 * on a BSD system want to test this for me? In the meantime,
127 * binary search mechanism should work just fine.
128 */
129 if ((fstat(fd, &st) >= 0) && S_ISBLK(st.st_mode))
130 part = st.st_rdev & 7;
131 if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
132 pp = &lab.d_partitions[part];
133 if (pp->p_size)
134 return pp->p_size << 9;
135 }
136#endif
137#endif /* HAVE_SYS_DISKLABEL_H */
138
139 /*
140 * OK, we couldn't figure it out by using a specialized ioctl,
141 * which is generally the best way. So do binary search to
142 * find the size of the partition.
143 */
144 low = 0;
145 for (high = 1024; valid_offset(fd, high); high *= 2)
146 low = high;
147 while (low < high - 1)
148 {
149 const blkid_loff_t mid = (low + high) / 2;
150
151 if (valid_offset(fd, mid))
152 low = mid;
153 else
154 high = mid;
155 }
156 return low + 1;
157}
158
159#ifdef TEST_PROGRAM
160int main(int argc, char **argv)
161{
162 blkid_loff_t bytes;
163 int fd;
164
165 if (argc < 2) {
166 fprintf(stderr, "Usage: %s device\n"
167 "Determine the size of a device\n", argv[0]);
168 return 1;
169 }
170
171 if ((fd = open(argv[1], O_RDONLY)) < 0)
172 perror(argv[0]);
173
174 bytes = blkid_get_dev_size(fd);
175 printf("Device %s has %lld 1k blocks.\n", argv[1], bytes >> 10);
176
177 return 0;
178}
179#endif
diff --git a/e2fsprogs/old_e2fsprogs/blkid/cache.c b/e2fsprogs/old_e2fsprogs/blkid/cache.c
deleted file mode 100644
index 251e49900..000000000
--- a/e2fsprogs/old_e2fsprogs/blkid/cache.c
+++ /dev/null
@@ -1,125 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * cache.c - allocation/initialization/free routines for cache
4 *
5 * Copyright (C) 2001 Andreas Dilger
6 * Copyright (C) 2003 Theodore Ts'o
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the
10 * GNU Lesser General Public License.
11 * %End-Header%
12 */
13
14#include <stdlib.h>
15#include <string.h>
16#include <unistd.h>
17#include "blkidP.h"
18
19int blkid_debug_mask = 0;
20
21int blkid_get_cache(blkid_cache *ret_cache, const char *filename)
22{
23 blkid_cache cache;
24
25#ifdef CONFIG_BLKID_DEBUG
26 if (!(blkid_debug_mask & DEBUG_INIT)) {
27 char *dstr = getenv("BLKID_DEBUG");
28
29 if (dstr)
30 blkid_debug_mask = strtoul(dstr, 0, 0);
31 blkid_debug_mask |= DEBUG_INIT;
32 }
33#endif
34
35 DBG(DEBUG_CACHE, printf("creating blkid cache (using %s)\n",
36 filename ? filename : "default cache"));
37
38 cache = xzalloc(sizeof(struct blkid_struct_cache));
39
40 INIT_LIST_HEAD(&cache->bic_devs);
41 INIT_LIST_HEAD(&cache->bic_tags);
42
43 if (filename && !strlen(filename))
44 filename = 0;
45 if (!filename && (getuid() == geteuid()))
46 filename = getenv("BLKID_FILE");
47 if (!filename)
48 filename = BLKID_CACHE_FILE;
49 cache->bic_filename = blkid_strdup(filename);
50
51 blkid_read_cache(cache);
52
53 *ret_cache = cache;
54 return 0;
55}
56
57void blkid_put_cache(blkid_cache cache)
58{
59 if (!cache)
60 return;
61
62 (void) blkid_flush_cache(cache);
63
64 DBG(DEBUG_CACHE, printf("freeing cache struct\n"));
65
66 /* DBG(DEBUG_CACHE, blkid_debug_dump_cache(cache)); */
67
68 while (!list_empty(&cache->bic_devs)) {
69 blkid_dev dev = list_entry(cache->bic_devs.next,
70 struct blkid_struct_dev,
71 bid_devs);
72 blkid_free_dev(dev);
73 }
74
75 while (!list_empty(&cache->bic_tags)) {
76 blkid_tag tag = list_entry(cache->bic_tags.next,
77 struct blkid_struct_tag,
78 bit_tags);
79
80 while (!list_empty(&tag->bit_names)) {
81 blkid_tag bad = list_entry(tag->bit_names.next,
82 struct blkid_struct_tag,
83 bit_names);
84
85 DBG(DEBUG_CACHE, printf("warning: unfreed tag %s=%s\n",
86 bad->bit_name, bad->bit_val));
87 blkid_free_tag(bad);
88 }
89 blkid_free_tag(tag);
90 }
91 free(cache->bic_filename);
92
93 free(cache);
94}
95
96#ifdef TEST_PROGRAM
97int main(int argc, char** argv)
98{
99 blkid_cache cache = NULL;
100 int ret;
101
102 blkid_debug_mask = DEBUG_ALL;
103 if ((argc > 2)) {
104 fprintf(stderr, "Usage: %s [filename]\n", argv[0]);
105 exit(1);
106 }
107
108 if ((ret = blkid_get_cache(&cache, argv[1])) < 0) {
109 fprintf(stderr, "error %d parsing cache file %s\n", ret,
110 argv[1] ? argv[1] : BLKID_CACHE_FILE);
111 exit(1);
112 }
113 if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
114 fprintf(stderr, "%s: error creating cache (%d)\n",
115 argv[0], ret);
116 exit(1);
117 }
118 if ((ret = blkid_probe_all(cache)) < 0)
119 fprintf(stderr, "error probing devices\n");
120
121 blkid_put_cache(cache);
122
123 return ret;
124}
125#endif
diff --git a/e2fsprogs/old_e2fsprogs/blkid/dev.c b/e2fsprogs/old_e2fsprogs/blkid/dev.c
deleted file mode 100644
index c2bbb06f3..000000000
--- a/e2fsprogs/old_e2fsprogs/blkid/dev.c
+++ /dev/null
@@ -1,212 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * dev.c - allocation/initialization/free routines for dev
4 *
5 * Copyright (C) 2001 Andreas Dilger
6 * Copyright (C) 2003 Theodore Ts'o
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the
10 * GNU Lesser General Public License.
11 * %End-Header%
12 */
13
14#include <stdlib.h>
15#include <string.h>
16
17#include "blkidP.h"
18
19blkid_dev blkid_new_dev(void)
20{
21 blkid_dev dev;
22
23 dev = xzalloc(sizeof(struct blkid_struct_dev));
24
25 INIT_LIST_HEAD(&dev->bid_devs);
26 INIT_LIST_HEAD(&dev->bid_tags);
27
28 return dev;
29}
30
31void blkid_free_dev(blkid_dev dev)
32{
33 if (!dev)
34 return;
35
36 DBG(DEBUG_DEV,
37 printf(" freeing dev %s (%s)\n", dev->bid_name, dev->bid_type));
38 DBG(DEBUG_DEV, blkid_debug_dump_dev(dev));
39
40 list_del(&dev->bid_devs);
41 while (!list_empty(&dev->bid_tags)) {
42 blkid_tag tag = list_entry(dev->bid_tags.next,
43 struct blkid_struct_tag,
44 bit_tags);
45 blkid_free_tag(tag);
46 }
47 free(dev->bid_name);
48 free(dev);
49}
50
51/*
52 * Given a blkid device, return its name
53 */
54const char *blkid_dev_devname(blkid_dev dev)
55{
56 return dev->bid_name;
57}
58
59#ifdef CONFIG_BLKID_DEBUG
60void blkid_debug_dump_dev(blkid_dev dev)
61{
62 struct list_head *p;
63
64 if (!dev) {
65 printf(" dev: NULL\n");
66 return;
67 }
68
69 printf(" dev: name = %s\n", dev->bid_name);
70 printf(" dev: DEVNO=\"0x%0llx\"\n", dev->bid_devno);
71 printf(" dev: TIME=\"%lu\"\n", dev->bid_time);
72 printf(" dev: PRI=\"%d\"\n", dev->bid_pri);
73 printf(" dev: flags = 0x%08X\n", dev->bid_flags);
74
75 list_for_each(p, &dev->bid_tags) {
76 blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
77 if (tag)
78 printf(" tag: %s=\"%s\"\n", tag->bit_name,
79 tag->bit_val);
80 else
81 printf(" tag: NULL\n");
82 }
83 bb_putchar('\n');
84}
85#endif
86
87/*
88 * dev iteration routines for the public libblkid interface.
89 *
90 * These routines do not expose the list.h implementation, which are a
91 * contamination of the namespace, and which force us to reveal far, far
92 * too much of our internal implementation. I'm not convinced I want
93 * to keep list.h in the long term, anyway. It's fine for kernel
94 * programming, but performance is not the #1 priority for this
95 * library, and I really don't like the tradeoff of type-safety for
96 * performance for this application. [tytso:20030125.2007EST]
97 */
98
99/*
100 * This series of functions iterate over all devices in a blkid cache
101 */
102#define DEV_ITERATE_MAGIC 0x01a5284c
103
104struct blkid_struct_dev_iterate {
105 int magic;
106 blkid_cache cache;
107 struct list_head *p;
108};
109
110blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache)
111{
112 blkid_dev_iterate iter;
113
114 iter = xmalloc(sizeof(struct blkid_struct_dev_iterate));
115 iter->magic = DEV_ITERATE_MAGIC;
116 iter->cache = cache;
117 iter->p = cache->bic_devs.next;
118 return iter;
119}
120
121/*
122 * Return 0 on success, -1 on error
123 */
124extern int blkid_dev_next(blkid_dev_iterate iter,
125 blkid_dev *dev)
126{
127 *dev = 0;
128 if (!iter || iter->magic != DEV_ITERATE_MAGIC ||
129 iter->p == &iter->cache->bic_devs)
130 return -1;
131 *dev = list_entry(iter->p, struct blkid_struct_dev, bid_devs);
132 iter->p = iter->p->next;
133 return 0;
134}
135
136void blkid_dev_iterate_end(blkid_dev_iterate iter)
137{
138 if (!iter || iter->magic != DEV_ITERATE_MAGIC)
139 return;
140 iter->magic = 0;
141 free(iter);
142}
143
144#ifdef TEST_PROGRAM
145#ifdef HAVE_GETOPT_H
146#include <getopt.h>
147#else
148extern char *optarg;
149extern int optind;
150#endif
151
152void usage(char *prog)
153{
154 fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask]\n", prog);
155 fprintf(stderr, "\tList all devices and exit\n");
156 exit(1);
157}
158
159int main(int argc, char **argv)
160{
161 blkid_dev_iterate iter;
162 blkid_cache cache = NULL;
163 blkid_dev dev;
164 int c, ret;
165 char *tmp;
166 char *file = NULL;
167 char *search_type = NULL;
168 char *search_value = NULL;
169
170 while ((c = getopt (argc, argv, "m:f:")) != EOF)
171 switch (c) {
172 case 'f':
173 file = optarg;
174 break;
175 case 'm':
176 blkid_debug_mask = strtoul (optarg, &tmp, 0);
177 if (*tmp) {
178 fprintf(stderr, "Invalid debug mask: %s\n",
179 optarg);
180 exit(1);
181 }
182 break;
183 case '?':
184 usage(argv[0]);
185 }
186 if (argc >= optind+2) {
187 search_type = argv[optind];
188 search_value = argv[optind+1];
189 optind += 2;
190 }
191 if (argc != optind)
192 usage(argv[0]);
193
194 if ((ret = blkid_get_cache(&cache, file)) != 0) {
195 fprintf(stderr, "%s: error creating cache (%d)\n",
196 argv[0], ret);
197 exit(1);
198 }
199
200 iter = blkid_dev_iterate_begin(cache);
201 if (search_type)
202 blkid_dev_set_search(iter, search_type, search_value);
203 while (blkid_dev_next(iter, &dev) == 0) {
204 printf("Device: %s\n", blkid_dev_devname(dev));
205 }
206 blkid_dev_iterate_end(iter);
207
208
209 blkid_put_cache(cache);
210 return 0;
211}
212#endif
diff --git a/e2fsprogs/old_e2fsprogs/blkid/devname.c b/e2fsprogs/old_e2fsprogs/blkid/devname.c
deleted file mode 100644
index fad92cb31..000000000
--- a/e2fsprogs/old_e2fsprogs/blkid/devname.c
+++ /dev/null
@@ -1,367 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * devname.c - get a dev by its device inode name
4 *
5 * Copyright (C) Andries Brouwer
6 * Copyright (C) 1999, 2000, 2001, 2002, 2003 Theodore Ts'o
7 * Copyright (C) 2001 Andreas Dilger
8 *
9 * %Begin-Header%
10 * This file may be redistributed under the terms of the
11 * GNU Lesser General Public License.
12 * %End-Header%
13 */
14
15#include <stdio.h>
16#include <string.h>
17#ifdef HAVE_UNISTD_H
18#include <unistd.h>
19#endif
20#include <stdlib.h>
21#include <string.h>
22#include <ctype.h>
23#ifdef HAVE_SYS_TYPES_H
24#include <sys/types.h>
25#endif
26#include <sys/stat.h>
27#ifdef HAVE_ERRNO_H
28#include <errno.h>
29#endif
30#ifdef HAVE_SYS_MKDEV_H
31#include <sys/mkdev.h>
32#endif
33#include <time.h>
34
35#include "blkidP.h"
36
37/*
38 * Find a dev struct in the cache by device name, if available.
39 *
40 * If there is no entry with the specified device name, and the create
41 * flag is set, then create an empty device entry.
42 */
43blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags)
44{
45 blkid_dev dev = NULL, tmp;
46 struct list_head *p;
47
48 if (!cache || !devname)
49 return NULL;
50
51 list_for_each(p, &cache->bic_devs) {
52 tmp = list_entry(p, struct blkid_struct_dev, bid_devs);
53 if (strcmp(tmp->bid_name, devname))
54 continue;
55
56 DBG(DEBUG_DEVNAME,
57 printf("found devname %s in cache\n", tmp->bid_name));
58 dev = tmp;
59 break;
60 }
61
62 if (!dev && (flags & BLKID_DEV_CREATE)) {
63 dev = blkid_new_dev();
64 if (!dev)
65 return NULL;
66 dev->bid_name = blkid_strdup(devname);
67 dev->bid_cache = cache;
68 list_add_tail(&dev->bid_devs, &cache->bic_devs);
69 cache->bic_flags |= BLKID_BIC_FL_CHANGED;
70 }
71
72 if (flags & BLKID_DEV_VERIFY)
73 dev = blkid_verify(cache, dev);
74 return dev;
75}
76
77/*
78 * Probe a single block device to add to the device cache.
79 */
80static void probe_one(blkid_cache cache, const char *ptname,
81 dev_t devno, int pri)
82{
83 blkid_dev dev = NULL;
84 struct list_head *p;
85 const char **dir;
86 char *devname = NULL;
87
88 /* See if we already have this device number in the cache. */
89 list_for_each(p, &cache->bic_devs) {
90 blkid_dev tmp = list_entry(p, struct blkid_struct_dev,
91 bid_devs);
92 if (tmp->bid_devno == devno) {
93 dev = blkid_verify(cache, tmp);
94 break;
95 }
96 }
97 if (dev && dev->bid_devno == devno)
98 goto set_pri;
99
100 /*
101 * Take a quick look at /dev/ptname for the device number. We check
102 * all of the likely device directories. If we don't find it, or if
103 * the stat information doesn't check out, use blkid_devno_to_devname()
104 * to find it via an exhaustive search for the device major/minor.
105 */
106 for (dir = blkid_devdirs; *dir; dir++) {
107 struct stat st;
108 char device[256];
109
110 sprintf(device, "%s/%s", *dir, ptname);
111 if ((dev = blkid_get_dev(cache, device, BLKID_DEV_FIND)) &&
112 dev->bid_devno == devno)
113 goto set_pri;
114
115 if (stat(device, &st) == 0 && S_ISBLK(st.st_mode) &&
116 st.st_rdev == devno) {
117 devname = blkid_strdup(device);
118 break;
119 }
120 }
121 if (!devname) {
122 devname = blkid_devno_to_devname(devno);
123 if (!devname)
124 return;
125 }
126 dev = blkid_get_dev(cache, devname, BLKID_DEV_NORMAL);
127 free(devname);
128
129set_pri:
130 if (!pri && !strncmp(ptname, "md", 2))
131 pri = BLKID_PRI_MD;
132 if (dev)
133 dev->bid_pri = pri;
134}
135
136#define PROC_PARTITIONS "/proc/partitions"
137#define VG_DIR "/proc/lvm/VGs"
138
139/*
140 * This function initializes the UUID cache with devices from the LVM
141 * proc hierarchy. We currently depend on the names of the LVM
142 * hierarchy giving us the device structure in /dev. (XXX is this a
143 * safe thing to do?)
144 */
145#ifdef VG_DIR
146#include <dirent.h>
147static dev_t lvm_get_devno(const char *lvm_device)
148{
149 FILE *lvf;
150 char buf[1024];
151 int ma, mi;
152 dev_t ret = 0;
153
154 DBG(DEBUG_DEVNAME, printf("opening %s\n", lvm_device));
155 if ((lvf = fopen_for_read(lvm_device)) == NULL) {
156 DBG(DEBUG_DEVNAME, printf("%s: (%d) %s\n", lvm_device, errno,
157 strerror(errno)));
158 return 0;
159 }
160
161 while (fgets(buf, sizeof(buf), lvf)) {
162 if (sscanf(buf, "device: %d:%d", &ma, &mi) == 2) {
163 ret = makedev(ma, mi);
164 break;
165 }
166 }
167 fclose(lvf);
168
169 return ret;
170}
171
172static void lvm_probe_all(blkid_cache cache)
173{
174 DIR *vg_list;
175 struct dirent *vg_iter;
176 int vg_len = strlen(VG_DIR);
177 dev_t dev;
178
179 if ((vg_list = opendir(VG_DIR)) == NULL)
180 return;
181
182 DBG(DEBUG_DEVNAME, printf("probing LVM devices under %s\n", VG_DIR));
183
184 while ((vg_iter = readdir(vg_list)) != NULL) {
185 DIR *lv_list;
186 char *vdirname;
187 char *vg_name;
188 struct dirent *lv_iter;
189
190 vg_name = vg_iter->d_name;
191 if (LONE_CHAR(vg_name, '.') || !strcmp(vg_name, ".."))
192 continue;
193 vdirname = xmalloc(vg_len + strlen(vg_name) + 8);
194 sprintf(vdirname, "%s/%s/LVs", VG_DIR, vg_name);
195
196 lv_list = opendir(vdirname);
197 free(vdirname);
198 if (lv_list == NULL)
199 continue;
200
201 while ((lv_iter = readdir(lv_list)) != NULL) {
202 char *lv_name, *lvm_device;
203
204 lv_name = lv_iter->d_name;
205 if (LONE_CHAR(lv_name, '.') || !strcmp(lv_name, ".."))
206 continue;
207
208 lvm_device = xmalloc(vg_len + strlen(vg_name) +
209 strlen(lv_name) + 8);
210 sprintf(lvm_device, "%s/%s/LVs/%s", VG_DIR, vg_name,
211 lv_name);
212 dev = lvm_get_devno(lvm_device);
213 sprintf(lvm_device, "%s/%s", vg_name, lv_name);
214 DBG(DEBUG_DEVNAME, printf("LVM dev %s: devno 0x%04X\n",
215 lvm_device,
216 (unsigned int) dev));
217 probe_one(cache, lvm_device, dev, BLKID_PRI_LVM);
218 free(lvm_device);
219 }
220 closedir(lv_list);
221 }
222 closedir(vg_list);
223}
224#endif
225
226#define PROC_EVMS_VOLUMES "/proc/evms/volumes"
227
228static int
229evms_probe_all(blkid_cache cache)
230{
231 char line[100];
232 int ma, mi, sz, num = 0;
233 FILE *procpt;
234 char device[110];
235
236 procpt = fopen_for_read(PROC_EVMS_VOLUMES);
237 if (!procpt)
238 return 0;
239 while (fgets(line, sizeof(line), procpt)) {
240 if (sscanf(line, " %d %d %d %*s %*s %[^\n ]",
241 &ma, &mi, &sz, device) != 4)
242 continue;
243
244 DBG(DEBUG_DEVNAME, printf("Checking partition %s (%d, %d)\n",
245 device, ma, mi));
246
247 probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS);
248 num++;
249 }
250 fclose(procpt);
251 return num;
252}
253
254/*
255 * Read the device data for all available block devices in the system.
256 */
257int blkid_probe_all(blkid_cache cache)
258{
259 FILE *proc;
260 char line[1024];
261 char ptname0[128], ptname1[128], *ptname = NULL;
262 char *ptnames[2];
263 dev_t devs[2];
264 int ma, mi;
265 unsigned long long sz;
266 int lens[2] = { 0, 0 };
267 int which = 0, last = 0;
268
269 ptnames[0] = ptname0;
270 ptnames[1] = ptname1;
271
272 if (!cache)
273 return -BLKID_ERR_PARAM;
274
275 if (cache->bic_flags & BLKID_BIC_FL_PROBED &&
276 time(NULL) - cache->bic_time < BLKID_PROBE_INTERVAL)
277 return 0;
278
279 blkid_read_cache(cache);
280 evms_probe_all(cache);
281#ifdef VG_DIR
282 lvm_probe_all(cache);
283#endif
284
285 proc = fopen_for_read(PROC_PARTITIONS);
286 if (!proc)
287 return -BLKID_ERR_PROC;
288
289 while (fgets(line, sizeof(line), proc)) {
290 last = which;
291 which ^= 1;
292 ptname = ptnames[which];
293
294 if (sscanf(line, " %d %d %llu %128[^\n ]",
295 &ma, &mi, &sz, ptname) != 4)
296 continue;
297 devs[which] = makedev(ma, mi);
298
299 DBG(DEBUG_DEVNAME, printf("read partition name %s\n", ptname));
300
301 /* Skip whole disk devs unless they have no partitions
302 * If we don't have a partition on this dev, also
303 * check previous dev to see if it didn't have a partn.
304 * heuristic: partition name ends in a digit.
305 *
306 * Skip extended partitions.
307 * heuristic: size is 1
308 *
309 * FIXME: skip /dev/{ida,cciss,rd} whole-disk devs
310 */
311
312 lens[which] = strlen(ptname);
313 if (isdigit(ptname[lens[which] - 1])) {
314 DBG(DEBUG_DEVNAME,
315 printf("partition dev %s, devno 0x%04X\n",
316 ptname, (unsigned int) devs[which]));
317
318 if (sz > 1)
319 probe_one(cache, ptname, devs[which], 0);
320 lens[which] = 0;
321 lens[last] = 0;
322 } else if (lens[last] && strncmp(ptnames[last], ptname,
323 lens[last])) {
324 DBG(DEBUG_DEVNAME,
325 printf("whole dev %s, devno 0x%04X\n",
326 ptnames[last], (unsigned int) devs[last]));
327 probe_one(cache, ptnames[last], devs[last], 0);
328 lens[last] = 0;
329 }
330 }
331
332 /* Handle the last device if it wasn't partitioned */
333 if (lens[which])
334 probe_one(cache, ptname, devs[which], 0);
335
336 fclose(proc);
337
338 cache->bic_time = time(NULL);
339 cache->bic_flags |= BLKID_BIC_FL_PROBED;
340 blkid_flush_cache(cache);
341 return 0;
342}
343
344#ifdef TEST_PROGRAM
345int main(int argc, char **argv)
346{
347 blkid_cache cache = NULL;
348 int ret;
349
350 blkid_debug_mask = DEBUG_ALL;
351 if (argc != 1) {
352 fprintf(stderr, "Usage: %s\n"
353 "Probe all devices and exit\n", argv[0]);
354 exit(1);
355 }
356 if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
357 fprintf(stderr, "%s: error creating cache (%d)\n",
358 argv[0], ret);
359 exit(1);
360 }
361 if (blkid_probe_all(cache) < 0)
362 printf("%s: error probing devices\n", argv[0]);
363
364 blkid_put_cache(cache);
365 return 0;
366}
367#endif
diff --git a/e2fsprogs/old_e2fsprogs/blkid/devno.c b/e2fsprogs/old_e2fsprogs/blkid/devno.c
deleted file mode 100644
index ae326f81a..000000000
--- a/e2fsprogs/old_e2fsprogs/blkid/devno.c
+++ /dev/null
@@ -1,222 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * devno.c - find a particular device by its device number (major/minor)
4 *
5 * Copyright (C) 2000, 2001, 2003 Theodore Ts'o
6 * Copyright (C) 2001 Andreas Dilger
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the
10 * GNU Lesser General Public License.
11 * %End-Header%
12 */
13
14#include <stdio.h>
15#include <string.h>
16#ifdef HAVE_UNISTD_H
17#include <unistd.h>
18#endif
19#include <stdlib.h>
20#include <string.h>
21#ifdef HAVE_SYS_TYPES_H
22#include <sys/types.h>
23#endif
24#include <sys/stat.h>
25#include <dirent.h>
26#ifdef HAVE_ERRNO_H
27#include <errno.h>
28#endif
29#ifdef HAVE_SYS_MKDEV_H
30#include <sys/mkdev.h>
31#endif
32
33#include "blkidP.h"
34
35struct dir_list {
36 char *name;
37 struct dir_list *next;
38};
39
40char *blkid_strndup(const char *s, int length)
41{
42 char *ret;
43
44 if (!s)
45 return NULL;
46
47 if (!length)
48 length = strlen(s);
49
50 ret = xmalloc(length + 1);
51 strncpy(ret, s, length);
52 ret[length] = '\0';
53 return ret;
54}
55
56char *blkid_strdup(const char *s)
57{
58 return blkid_strndup(s, 0);
59}
60
61/*
62 * This function adds an entry to the directory list
63 */
64static void add_to_dirlist(const char *name, struct dir_list **list)
65{
66 struct dir_list *dp;
67
68 dp = xmalloc(sizeof(struct dir_list));
69 dp->name = blkid_strdup(name);
70 dp->next = *list;
71 *list = dp;
72}
73
74/*
75 * This function frees a directory list
76 */
77static void free_dirlist(struct dir_list **list)
78{
79 struct dir_list *dp, *next;
80
81 for (dp = *list; dp; dp = next) {
82 next = dp->next;
83 free(dp->name);
84 free(dp);
85 }
86 *list = NULL;
87}
88
89static void scan_dir(char *dir_name, dev_t devno, struct dir_list **list,
90 char **devname)
91{
92 DIR *dir;
93 struct dirent *dp;
94 char path[1024];
95 int dirlen;
96 struct stat st;
97
98 if ((dir = opendir(dir_name)) == NULL)
99 return;
100 dirlen = strlen(dir_name) + 2;
101 while ((dp = readdir(dir)) != 0) {
102 if (dirlen + strlen(dp->d_name) >= sizeof(path))
103 continue;
104
105 if (dp->d_name[0] == '.' &&
106 ((dp->d_name[1] == 0) ||
107 ((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
108 continue;
109
110 sprintf(path, "%s/%s", dir_name, dp->d_name);
111 if (stat(path, &st) < 0)
112 continue;
113
114 if (S_ISDIR(st.st_mode))
115 add_to_dirlist(path, list);
116 else if (S_ISBLK(st.st_mode) && st.st_rdev == devno) {
117 *devname = blkid_strdup(path);
118 DBG(DEBUG_DEVNO,
119 printf("found 0x%llx at %s (%p)\n", devno,
120 path, *devname));
121 break;
122 }
123 }
124 closedir(dir);
125}
126
127/* Directories where we will try to search for device numbers */
128const char *blkid_devdirs[] = { "/devices", "/devfs", "/dev", NULL };
129
130/*
131 * This function finds the pathname to a block device with a given
132 * device number. It returns a pointer to allocated memory to the
133 * pathname on success, and NULL on failure.
134 */
135char *blkid_devno_to_devname(dev_t devno)
136{
137 struct dir_list *list = NULL, *new_list = NULL;
138 char *devname = NULL;
139 const char **dir;
140
141 /*
142 * Add the starting directories to search in reverse order of
143 * importance, since we are using a stack...
144 */
145 for (dir = blkid_devdirs; *dir; dir++)
146 add_to_dirlist(*dir, &list);
147
148 while (list) {
149 struct dir_list *current = list;
150
151 list = list->next;
152 DBG(DEBUG_DEVNO, printf("directory %s\n", current->name));
153 scan_dir(current->name, devno, &new_list, &devname);
154 free(current->name);
155 free(current);
156 if (devname)
157 break;
158 /*
159 * If we're done checking at this level, descend to
160 * the next level of subdirectories. (breadth-first)
161 */
162 if (list == NULL) {
163 list = new_list;
164 new_list = NULL;
165 }
166 }
167 free_dirlist(&list);
168 free_dirlist(&new_list);
169
170 if (!devname) {
171 DBG(DEBUG_DEVNO,
172 printf("blkid: cannot find devno 0x%04lx\n",
173 (unsigned long) devno));
174 } else {
175 DBG(DEBUG_DEVNO,
176 printf("found devno 0x%04llx as %s\n", devno, devname));
177 }
178
179
180 return devname;
181}
182
183#ifdef TEST_PROGRAM
184int main(int argc, char** argv)
185{
186 char *devname, *tmp;
187 int major, minor;
188 dev_t devno;
189 const char *errmsg = "Cannot parse %s: %s\n";
190
191 blkid_debug_mask = DEBUG_ALL;
192 if ((argc != 2) && (argc != 3)) {
193 fprintf(stderr, "Usage:\t%s device_number\n\t%s major minor\n"
194 "Resolve a device number to a device name\n",
195 argv[0], argv[0]);
196 exit(1);
197 }
198 if (argc == 2) {
199 devno = strtoul(argv[1], &tmp, 0);
200 if (*tmp) {
201 fprintf(stderr, errmsg, "device number", argv[1]);
202 exit(1);
203 }
204 } else {
205 major = strtoul(argv[1], &tmp, 0);
206 if (*tmp) {
207 fprintf(stderr, errmsg, "major number", argv[1]);
208 exit(1);
209 }
210 minor = strtoul(argv[2], &tmp, 0);
211 if (*tmp) {
212 fprintf(stderr, errmsg, "minor number", argv[2]);
213 exit(1);
214 }
215 devno = makedev(major, minor);
216 }
217 printf("Looking for device 0x%04Lx\n", devno);
218 devname = blkid_devno_to_devname(devno);
219 free(devname);
220 return 0;
221}
222#endif
diff --git a/e2fsprogs/old_e2fsprogs/blkid/list.c b/e2fsprogs/old_e2fsprogs/blkid/list.c
deleted file mode 100644
index 04d61a19b..000000000
--- a/e2fsprogs/old_e2fsprogs/blkid/list.c
+++ /dev/null
@@ -1,110 +0,0 @@
1/* vi: set sw=4 ts=4: */
2
3#include "list.h"
4
5/*
6 * Insert a new entry between two known consecutive entries.
7 *
8 * This is only for internal list manipulation where we know
9 * the prev/next entries already!
10 */
11void __list_add(struct list_head * add,
12 struct list_head * prev,
13 struct list_head * next)
14{
15 next->prev = add;
16 add->next = next;
17 add->prev = prev;
18 prev->next = add;
19}
20
21/*
22 * list_add - add a new entry
23 * @add: new entry to be added
24 * @head: list head to add it after
25 *
26 * Insert a new entry after the specified head.
27 * This is good for implementing stacks.
28 */
29void list_add(struct list_head *add, struct list_head *head)
30{
31 __list_add(add, head, head->next);
32}
33
34/*
35 * list_add_tail - add a new entry
36 * @add: new entry to be added
37 * @head: list head to add it before
38 *
39 * Insert a new entry before the specified head.
40 * This is useful for implementing queues.
41 */
42void list_add_tail(struct list_head *add, struct list_head *head)
43{
44 __list_add(add, head->prev, head);
45}
46
47/*
48 * Delete a list entry by making the prev/next entries
49 * point to each other.
50 *
51 * This is only for internal list manipulation where we know
52 * the prev/next entries already!
53 */
54void __list_del(struct list_head * prev, struct list_head * next)
55{
56 next->prev = prev;
57 prev->next = next;
58}
59
60/*
61 * list_del - deletes entry from list.
62 * @entry: the element to delete from the list.
63 *
64 * list_empty() on @entry does not return true after this, @entry is
65 * in an undefined state.
66 */
67void list_del(struct list_head *entry)
68{
69 __list_del(entry->prev, entry->next);
70}
71
72/*
73 * list_del_init - deletes entry from list and reinitialize it.
74 * @entry: the element to delete from the list.
75 */
76void list_del_init(struct list_head *entry)
77{
78 __list_del(entry->prev, entry->next);
79 INIT_LIST_HEAD(entry);
80}
81
82/*
83 * list_empty - tests whether a list is empty
84 * @head: the list to test.
85 */
86int list_empty(struct list_head *head)
87{
88 return head->next == head;
89}
90
91/*
92 * list_splice - join two lists
93 * @list: the new list to add.
94 * @head: the place to add it in the first list.
95 */
96void list_splice(struct list_head *list, struct list_head *head)
97{
98 struct list_head *first = list->next;
99
100 if (first != list) {
101 struct list_head *last = list->prev;
102 struct list_head *at = head->next;
103
104 first->prev = head;
105 head->next = first;
106
107 last->next = at;
108 at->prev = last;
109 }
110}
diff --git a/e2fsprogs/old_e2fsprogs/blkid/list.h b/e2fsprogs/old_e2fsprogs/blkid/list.h
deleted file mode 100644
index a24baaa91..000000000
--- a/e2fsprogs/old_e2fsprogs/blkid/list.h
+++ /dev/null
@@ -1,73 +0,0 @@
1/* vi: set sw=4 ts=4: */
2#if !defined(_BLKID_LIST_H) && !defined(LIST_HEAD)
3#define BLKID_LIST_H 1
4
5#ifdef __cplusplus
6extern "C" {
7#endif
8
9/*
10 * Simple doubly linked list implementation.
11 *
12 * Some of the internal functions ("__xxx") are useful when
13 * manipulating whole lists rather than single entries, as
14 * sometimes we already know the next/prev entries and we can
15 * generate better code by using them directly rather than
16 * using the generic single-entry routines.
17 */
18
19struct list_head {
20 struct list_head *next, *prev;
21};
22
23#define LIST_HEAD_INIT(name) { &(name), &(name) }
24
25#define LIST_HEAD(name) \
26 struct list_head name = LIST_HEAD_INIT(name)
27
28#define INIT_LIST_HEAD(ptr) do { \
29 (ptr)->next = (ptr); (ptr)->prev = (ptr); \
30} while (0)
31
32void __list_add(struct list_head * add, struct list_head * prev, struct list_head * next);
33void list_add(struct list_head *add, struct list_head *head);
34void list_add_tail(struct list_head *add, struct list_head *head);
35void __list_del(struct list_head * prev, struct list_head * next);
36void list_del(struct list_head *entry);
37void list_del_init(struct list_head *entry);
38int list_empty(struct list_head *head);
39void list_splice(struct list_head *list, struct list_head *head);
40
41/**
42 * list_entry - get the struct for this entry
43 * @ptr: the &struct list_head pointer.
44 * @type: the type of the struct this is embedded in.
45 * @member: the name of the list_struct within the struct.
46 */
47#define list_entry(ptr, type, member) \
48 ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
49
50/**
51 * list_for_each - iterate over elements in a list
52 * @pos: the &struct list_head to use as a loop counter.
53 * @head: the head for your list.
54 */
55#define list_for_each(pos, head) \
56 for (pos = (head)->next; pos != (head); pos = pos->next)
57
58/**
59 * list_for_each_safe - iterate over elements in a list, but don't dereference
60 * pos after the body is done (in case it is freed)
61 * @pos: the &struct list_head to use as a loop counter.
62 * @pnext: the &struct list_head to use as a pointer to the next item.
63 * @head: the head for your list (not included in iteration).
64 */
65#define list_for_each_safe(pos, pnext, head) \
66 for (pos = (head)->next, pnext = pos->next; pos != (head); \
67 pos = pnext, pnext = pos->next)
68
69#ifdef __cplusplus
70}
71#endif
72
73#endif
diff --git a/e2fsprogs/old_e2fsprogs/blkid/probe.c b/e2fsprogs/old_e2fsprogs/blkid/probe.c
deleted file mode 100644
index 651193b42..000000000
--- a/e2fsprogs/old_e2fsprogs/blkid/probe.c
+++ /dev/null
@@ -1,726 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * probe.c - identify a block device by its contents, and return a dev
4 * struct with the details
5 *
6 * Copyright (C) 1999 by Andries Brouwer
7 * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
8 * Copyright (C) 2001 by Andreas Dilger
9 *
10 * %Begin-Header%
11 * This file may be redistributed under the terms of the
12 * GNU Lesser General Public License.
13 * %End-Header%
14 */
15
16#include <stdio.h>
17#include <string.h>
18#include <stdlib.h>
19#include <unistd.h>
20#include <fcntl.h>
21#include <sys/types.h>
22#ifdef HAVE_SYS_STAT_H
23#include <sys/stat.h>
24#endif
25#ifdef HAVE_SYS_MKDEV_H
26#include <sys/mkdev.h>
27#endif
28#ifdef HAVE_ERRNO_H
29#include <errno.h>
30#endif
31#include "blkidP.h"
32#include "../uuid/uuid.h"
33#include "probe.h"
34
35/*
36 * This is a special case code to check for an MDRAID device. We do
37 * this special since it requires checking for a superblock at the end
38 * of the device.
39 */
40static int check_mdraid(int fd, unsigned char *ret_uuid)
41{
42 struct mdp_superblock_s *md;
43 blkid_loff_t offset;
44 char buf[4096];
45
46 if (fd < 0)
47 return -BLKID_ERR_PARAM;
48
49 offset = (blkid_get_dev_size(fd) & ~((blkid_loff_t)65535)) - 65536;
50
51 if (blkid_llseek(fd, offset, 0) < 0 ||
52 read(fd, buf, 4096) != 4096)
53 return -BLKID_ERR_IO;
54
55 /* Check for magic number */
56 if (memcmp("\251+N\374", buf, 4))
57 return -BLKID_ERR_PARAM;
58
59 if (!ret_uuid)
60 return 0;
61 *ret_uuid = 0;
62
63 /* The MD UUID is not contiguous in the superblock, make it so */
64 md = (struct mdp_superblock_s *)buf;
65 if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) {
66 memcpy(ret_uuid, &md->set_uuid0, 4);
67 memcpy(ret_uuid, &md->set_uuid1, 12);
68 }
69 return 0;
70}
71
72static void set_uuid(blkid_dev dev, uuid_t uuid)
73{
74 char str[37];
75
76 if (!uuid_is_null(uuid)) {
77 uuid_unparse(uuid, str);
78 blkid_set_tag(dev, "UUID", str, sizeof(str));
79 }
80}
81
82static void get_ext2_info(blkid_dev dev, unsigned char *buf)
83{
84 struct ext2_super_block *es = (struct ext2_super_block *) buf;
85 const char *label = NULL;
86
87 DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n",
88 blkid_le32(es->s_feature_compat),
89 blkid_le32(es->s_feature_incompat),
90 blkid_le32(es->s_feature_ro_compat)));
91
92 if (strlen(es->s_volume_name))
93 label = es->s_volume_name;
94 blkid_set_tag(dev, "LABEL", label, sizeof(es->s_volume_name));
95
96 set_uuid(dev, es->s_uuid);
97}
98
99static int probe_ext3(int fd __BLKID_ATTR((unused)),
100 blkid_cache cache __BLKID_ATTR((unused)),
101 blkid_dev dev,
102 const struct blkid_magic *id __BLKID_ATTR((unused)),
103 unsigned char *buf)
104{
105 struct ext2_super_block *es;
106
107 es = (struct ext2_super_block *)buf;
108
109 /* Distinguish between jbd and ext2/3 fs */
110 if (blkid_le32(es->s_feature_incompat) &
111 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
112 return -BLKID_ERR_PARAM;
113
114 /* Distinguish between ext3 and ext2 */
115 if (!(blkid_le32(es->s_feature_compat) &
116 EXT3_FEATURE_COMPAT_HAS_JOURNAL))
117 return -BLKID_ERR_PARAM;
118
119 get_ext2_info(dev, buf);
120
121 blkid_set_tag(dev, "SEC_TYPE", "ext2", sizeof("ext2"));
122
123 return 0;
124}
125
126static int probe_ext2(int fd __BLKID_ATTR((unused)),
127 blkid_cache cache __BLKID_ATTR((unused)),
128 blkid_dev dev,
129 const struct blkid_magic *id __BLKID_ATTR((unused)),
130 unsigned char *buf)
131{
132 struct ext2_super_block *es;
133
134 es = (struct ext2_super_block *)buf;
135
136 /* Distinguish between jbd and ext2/3 fs */
137 if (blkid_le32(es->s_feature_incompat) &
138 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
139 return -BLKID_ERR_PARAM;
140
141 get_ext2_info(dev, buf);
142
143 return 0;
144}
145
146static int probe_jbd(int fd __BLKID_ATTR((unused)),
147 blkid_cache cache __BLKID_ATTR((unused)),
148 blkid_dev dev,
149 const struct blkid_magic *id __BLKID_ATTR((unused)),
150 unsigned char *buf)
151{
152 struct ext2_super_block *es = (struct ext2_super_block *) buf;
153
154 if (!(blkid_le32(es->s_feature_incompat) &
155 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV))
156 return -BLKID_ERR_PARAM;
157
158 get_ext2_info(dev, buf);
159
160 return 0;
161}
162
163static int probe_vfat(int fd __BLKID_ATTR((unused)),
164 blkid_cache cache __BLKID_ATTR((unused)),
165 blkid_dev dev,
166 const struct blkid_magic *id __BLKID_ATTR((unused)),
167 unsigned char *buf)
168{
169 struct vfat_super_block *vs;
170 char serno[10];
171 const char *label = NULL;
172 int label_len = 0;
173
174 vs = (struct vfat_super_block *)buf;
175
176 if (strncmp(vs->vs_label, "NO NAME", 7)) {
177 char *end = vs->vs_label + sizeof(vs->vs_label) - 1;
178
179 while (*end == ' ' && end >= vs->vs_label)
180 --end;
181 if (end >= vs->vs_label) {
182 label = vs->vs_label;
183 label_len = end - vs->vs_label + 1;
184 }
185 }
186
187 /* We can't just print them as %04X, because they are unaligned */
188 sprintf(serno, "%02X%02X-%02X%02X", vs->vs_serno[3], vs->vs_serno[2],
189 vs->vs_serno[1], vs->vs_serno[0]);
190 blkid_set_tag(dev, "LABEL", label, label_len);
191 blkid_set_tag(dev, "UUID", serno, sizeof(serno));
192
193 return 0;
194}
195
196static int probe_msdos(int fd __BLKID_ATTR((unused)),
197 blkid_cache cache __BLKID_ATTR((unused)),
198 blkid_dev dev,
199 const struct blkid_magic *id __BLKID_ATTR((unused)),
200 unsigned char *buf)
201{
202 struct msdos_super_block *ms = (struct msdos_super_block *) buf;
203 char serno[10];
204 const char *label = NULL;
205 int label_len = 0;
206
207 if (strncmp(ms->ms_label, "NO NAME", 7)) {
208 char *end = ms->ms_label + sizeof(ms->ms_label) - 1;
209
210 while (*end == ' ' && end >= ms->ms_label)
211 --end;
212 if (end >= ms->ms_label) {
213 label = ms->ms_label;
214 label_len = end - ms->ms_label + 1;
215 }
216 }
217
218 /* We can't just print them as %04X, because they are unaligned */
219 sprintf(serno, "%02X%02X-%02X%02X", ms->ms_serno[3], ms->ms_serno[2],
220 ms->ms_serno[1], ms->ms_serno[0]);
221 blkid_set_tag(dev, "UUID", serno, 0);
222 blkid_set_tag(dev, "LABEL", label, label_len);
223 blkid_set_tag(dev, "SEC_TYPE", "msdos", sizeof("msdos"));
224
225 return 0;
226}
227
228static int probe_xfs(int fd __BLKID_ATTR((unused)),
229 blkid_cache cache __BLKID_ATTR((unused)),
230 blkid_dev dev,
231 const struct blkid_magic *id __BLKID_ATTR((unused)),
232 unsigned char *buf)
233{
234 struct xfs_super_block *xs;
235 const char *label = NULL;
236
237 xs = (struct xfs_super_block *)buf;
238
239 if (strlen(xs->xs_fname))
240 label = xs->xs_fname;
241 blkid_set_tag(dev, "LABEL", label, sizeof(xs->xs_fname));
242 set_uuid(dev, xs->xs_uuid);
243 return 0;
244}
245
246static int probe_reiserfs(int fd __BLKID_ATTR((unused)),
247 blkid_cache cache __BLKID_ATTR((unused)),
248 blkid_dev dev,
249 const struct blkid_magic *id, unsigned char *buf)
250{
251 struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf;
252 unsigned int blocksize;
253 const char *label = NULL;
254
255 blocksize = blkid_le16(rs->rs_blocksize);
256
257 /* If the superblock is inside the journal, we have the wrong one */
258 if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block))
259 return -BLKID_ERR_BIG;
260
261 /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */
262 if (!strcmp(id->bim_magic, "ReIsEr2Fs") ||
263 !strcmp(id->bim_magic, "ReIsEr3Fs")) {
264 if (strlen(rs->rs_label))
265 label = rs->rs_label;
266 set_uuid(dev, rs->rs_uuid);
267 }
268 blkid_set_tag(dev, "LABEL", label, sizeof(rs->rs_label));
269
270 return 0;
271}
272
273static int probe_jfs(int fd __BLKID_ATTR((unused)),
274 blkid_cache cache __BLKID_ATTR((unused)),
275 blkid_dev dev,
276 const struct blkid_magic *id __BLKID_ATTR((unused)),
277 unsigned char *buf)
278{
279 struct jfs_super_block *js;
280 const char *label = NULL;
281
282 js = (struct jfs_super_block *)buf;
283
284 if (strlen((char *) js->js_label))
285 label = (char *) js->js_label;
286 blkid_set_tag(dev, "LABEL", label, sizeof(js->js_label));
287 set_uuid(dev, js->js_uuid);
288 return 0;
289}
290
291static int probe_romfs(int fd __BLKID_ATTR((unused)),
292 blkid_cache cache __BLKID_ATTR((unused)),
293 blkid_dev dev,
294 const struct blkid_magic *id __BLKID_ATTR((unused)),
295 unsigned char *buf)
296{
297 struct romfs_super_block *ros;
298 const char *label = NULL;
299
300 ros = (struct romfs_super_block *)buf;
301
302 if (strlen((char *) ros->ros_volume))
303 label = (char *) ros->ros_volume;
304 blkid_set_tag(dev, "LABEL", label, 0);
305 return 0;
306}
307
308static int probe_cramfs(int fd __BLKID_ATTR((unused)),
309 blkid_cache cache __BLKID_ATTR((unused)),
310 blkid_dev dev,
311 const struct blkid_magic *id __BLKID_ATTR((unused)),
312 unsigned char *buf)
313{
314 struct cramfs_super_block *csb;
315 const char *label = NULL;
316
317 csb = (struct cramfs_super_block *)buf;
318
319 if (strlen((char *) csb->name))
320 label = (char *) csb->name;
321 blkid_set_tag(dev, "LABEL", label, 0);
322 return 0;
323}
324
325static int probe_swap0(int fd __BLKID_ATTR((unused)),
326 blkid_cache cache __BLKID_ATTR((unused)),
327 blkid_dev dev,
328 const struct blkid_magic *id __BLKID_ATTR((unused)),
329 unsigned char *buf __BLKID_ATTR((unused)))
330{
331 blkid_set_tag(dev, "UUID", 0, 0);
332 blkid_set_tag(dev, "LABEL", 0, 0);
333 return 0;
334}
335
336static int probe_swap1(int fd,
337 blkid_cache cache __BLKID_ATTR((unused)),
338 blkid_dev dev,
339 const struct blkid_magic *id __BLKID_ATTR((unused)),
340 unsigned char *buf __BLKID_ATTR((unused)))
341{
342 struct swap_id_block *sws;
343
344 probe_swap0(fd, cache, dev, id, buf);
345 /*
346 * Version 1 swap headers are always located at offset of 1024
347 * bytes, although the swap signature itself is located at the
348 * end of the page (which may vary depending on hardware
349 * pagesize).
350 */
351 if (lseek(fd, 1024, SEEK_SET) < 0) return 1;
352 sws = xmalloc(1024);
353 if (read(fd, sws, 1024) != 1024) {
354 free(sws);
355 return 1;
356 }
357
358 /* arbitrary sanity check.. is there any garbage down there? */
359 if (sws->sws_pad[32] == 0 && sws->sws_pad[33] == 0) {
360 if (sws->sws_volume[0])
361 blkid_set_tag(dev, "LABEL", (const char*)sws->sws_volume,
362 sizeof(sws->sws_volume));
363 if (sws->sws_uuid[0])
364 set_uuid(dev, sws->sws_uuid);
365 }
366 free(sws);
367
368 return 0;
369}
370
371static const char
372* const udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
373 "NSR03", "TEA01", 0 };
374
375static int probe_udf(int fd, blkid_cache cache __BLKID_ATTR((unused)),
376 blkid_dev dev __BLKID_ATTR((unused)),
377 const struct blkid_magic *id __BLKID_ATTR((unused)),
378 unsigned char *buf __BLKID_ATTR((unused)))
379{
380 int j, bs;
381 struct iso_volume_descriptor isosb;
382 const char *const *m;
383
384 /* determine the block size by scanning in 2K increments
385 (block sizes larger than 2K will be null padded) */
386 for (bs = 1; bs < 16; bs++) {
387 lseek(fd, bs*2048+32768, SEEK_SET);
388 if (read(fd, (char *)&isosb, sizeof(isosb)) != sizeof(isosb))
389 return 1;
390 if (isosb.id[0])
391 break;
392 }
393
394 /* Scan up to another 64 blocks looking for additional VSD's */
395 for (j = 1; j < 64; j++) {
396 if (j > 1) {
397 lseek(fd, j*bs*2048+32768, SEEK_SET);
398 if (read(fd, (char *)&isosb, sizeof(isosb))
399 != sizeof(isosb))
400 return 1;
401 }
402 /* If we find NSR0x then call it udf:
403 NSR01 for UDF 1.00
404 NSR02 for UDF 1.50
405 NSR03 for UDF 2.00 */
406 if (!strncmp(isosb.id, "NSR0", 4))
407 return 0;
408 for (m = udf_magic; *m; m++)
409 if (!strncmp(*m, isosb.id, 5))
410 break;
411 if (*m == 0)
412 return 1;
413 }
414 return 1;
415}
416
417static int probe_ocfs(int fd __BLKID_ATTR((unused)),
418 blkid_cache cache __BLKID_ATTR((unused)),
419 blkid_dev dev,
420 const struct blkid_magic *id __BLKID_ATTR((unused)),
421 unsigned char *buf)
422{
423 struct ocfs_volume_header ovh;
424 struct ocfs_volume_label ovl;
425 __u32 major;
426
427 memcpy(&ovh, buf, sizeof(ovh));
428 memcpy(&ovl, buf+512, sizeof(ovl));
429
430 major = ocfsmajor(ovh);
431 if (major == 1)
432 blkid_set_tag(dev, "SEC_TYPE", "ocfs1", sizeof("ocfs1"));
433 else if (major >= 9)
434 blkid_set_tag(dev, "SEC_TYPE", "ntocfs", sizeof("ntocfs"));
435
436 blkid_set_tag(dev, "LABEL", (const char*)ovl.label, ocfslabellen(ovl));
437 blkid_set_tag(dev, "MOUNT", (const char*)ovh.mount, ocfsmountlen(ovh));
438 set_uuid(dev, ovl.vol_id);
439 return 0;
440}
441
442static int probe_ocfs2(int fd __BLKID_ATTR((unused)),
443 blkid_cache cache __BLKID_ATTR((unused)),
444 blkid_dev dev,
445 const struct blkid_magic *id __BLKID_ATTR((unused)),
446 unsigned char *buf)
447{
448 struct ocfs2_super_block *osb;
449
450 osb = (struct ocfs2_super_block *)buf;
451
452 blkid_set_tag(dev, "LABEL", (const char*)osb->s_label, sizeof(osb->s_label));
453 set_uuid(dev, osb->s_uuid);
454 return 0;
455}
456
457static int probe_oracleasm(int fd __BLKID_ATTR((unused)),
458 blkid_cache cache __BLKID_ATTR((unused)),
459 blkid_dev dev,
460 const struct blkid_magic *id __BLKID_ATTR((unused)),
461 unsigned char *buf)
462{
463 struct oracle_asm_disk_label *dl;
464
465 dl = (struct oracle_asm_disk_label *)buf;
466
467 blkid_set_tag(dev, "LABEL", dl->dl_id, sizeof(dl->dl_id));
468 return 0;
469}
470
471/*
472 * BLKID_BLK_OFFS is at least as large as the highest bim_kboff defined
473 * in the type_array table below + bim_kbalign.
474 *
475 * When probing for a lot of magics, we handle everything in 1kB buffers so
476 * that we don't have to worry about reading each combination of block sizes.
477 */
478#define BLKID_BLK_OFFS 64 /* currently reiserfs */
479
480/*
481 * Various filesystem magics that we can check for. Note that kboff and
482 * sboff are in kilobytes and bytes respectively. All magics are in
483 * byte strings so we don't worry about endian issues.
484 */
485static const struct blkid_magic type_array[] = {
486/* type kboff sboff len magic probe */
487 { "oracleasm", 0, 32, 8, "ORCLDISK", probe_oracleasm },
488 { "ntfs", 0, 3, 8, "NTFS ", 0 },
489 { "jbd", 1, 0x38, 2, "\123\357", probe_jbd },
490 { "ext3", 1, 0x38, 2, "\123\357", probe_ext3 },
491 { "ext2", 1, 0x38, 2, "\123\357", probe_ext2 },
492 { "reiserfs", 8, 0x34, 8, "ReIsErFs", probe_reiserfs },
493 { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", probe_reiserfs },
494 { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", probe_reiserfs },
495 { "reiserfs", 64, 0x34, 8, "ReIsErFs", probe_reiserfs },
496 { "reiserfs", 8, 20, 8, "ReIsErFs", probe_reiserfs },
497 { "vfat", 0, 0x52, 5, "MSWIN", probe_vfat },
498 { "vfat", 0, 0x52, 8, "FAT32 ", probe_vfat },
499 { "vfat", 0, 0x36, 5, "MSDOS", probe_msdos },
500 { "vfat", 0, 0x36, 8, "FAT16 ", probe_msdos },
501 { "vfat", 0, 0x36, 8, "FAT12 ", probe_msdos },
502 { "minix", 1, 0x10, 2, "\177\023", 0 },
503 { "minix", 1, 0x10, 2, "\217\023", 0 },
504 { "minix", 1, 0x10, 2, "\150\044", 0 },
505 { "minix", 1, 0x10, 2, "\170\044", 0 },
506 { "vxfs", 1, 0, 4, "\365\374\001\245", 0 },
507 { "xfs", 0, 0, 4, "XFSB", probe_xfs },
508 { "romfs", 0, 0, 8, "-rom1fs-", probe_romfs },
509 { "bfs", 0, 0, 4, "\316\372\173\033", 0 },
510 { "cramfs", 0, 0, 4, "E=\315\050", probe_cramfs },
511 { "qnx4", 0, 4, 6, "QNX4FS", 0 },
512 { "udf", 32, 1, 5, "BEA01", probe_udf },
513 { "udf", 32, 1, 5, "BOOT2", probe_udf },
514 { "udf", 32, 1, 5, "CD001", probe_udf },
515 { "udf", 32, 1, 5, "CDW02", probe_udf },
516 { "udf", 32, 1, 5, "NSR02", probe_udf },
517 { "udf", 32, 1, 5, "NSR03", probe_udf },
518 { "udf", 32, 1, 5, "TEA01", probe_udf },
519 { "iso9660", 32, 1, 5, "CD001", 0 },
520 { "iso9660", 32, 9, 5, "CDROM", 0 },
521 { "jfs", 32, 0, 4, "JFS1", probe_jfs },
522 { "hfs", 1, 0, 2, "BD", 0 },
523 { "ufs", 8, 0x55c, 4, "T\031\001\000", 0 },
524 { "hpfs", 8, 0, 4, "I\350\225\371", 0 },
525 { "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 },
526 { "swap", 0, 0xff6, 10, "SWAP-SPACE", probe_swap0 },
527 { "swap", 0, 0xff6, 10, "SWAPSPACE2", probe_swap1 },
528 { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", probe_swap0 },
529 { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", probe_swap1 },
530 { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", probe_swap0 },
531 { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", probe_swap1 },
532 { "swap", 0, 0x7ff6, 10, "SWAP-SPACE", probe_swap0 },
533 { "swap", 0, 0x7ff6, 10, "SWAPSPACE2", probe_swap1 },
534 { "swap", 0, 0xfff6, 10, "SWAP-SPACE", probe_swap0 },
535 { "swap", 0, 0xfff6, 10, "SWAPSPACE2", probe_swap1 },
536 { "ocfs", 0, 8, 9, "OracleCFS", probe_ocfs },
537 { "ocfs2", 1, 0, 6, "OCFSV2", probe_ocfs2 },
538 { "ocfs2", 2, 0, 6, "OCFSV2", probe_ocfs2 },
539 { "ocfs2", 4, 0, 6, "OCFSV2", probe_ocfs2 },
540 { "ocfs2", 8, 0, 6, "OCFSV2", probe_ocfs2 },
541 { NULL, 0, 0, 0, NULL, NULL }
542};
543
544/*
545 * Verify that the data in dev is consistent with what is on the actual
546 * block device (using the devname field only). Normally this will be
547 * called when finding items in the cache, but for long running processes
548 * is also desirable to revalidate an item before use.
549 *
550 * If we are unable to revalidate the data, we return the old data and
551 * do not set the BLKID_BID_FL_VERIFIED flag on it.
552 */
553blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
554{
555 const struct blkid_magic *id;
556 unsigned char *bufs[BLKID_BLK_OFFS + 1], *buf;
557 const char *type;
558 struct stat st;
559 time_t diff, now;
560 int fd, idx;
561
562 if (!dev)
563 return NULL;
564
565 now = time(NULL);
566 diff = now - dev->bid_time;
567
568 if ((now < dev->bid_time) ||
569 (diff < BLKID_PROBE_MIN) ||
570 (dev->bid_flags & BLKID_BID_FL_VERIFIED &&
571 diff < BLKID_PROBE_INTERVAL))
572 return dev;
573
574 DBG(DEBUG_PROBE,
575 printf("need to revalidate %s (time since last check %lu)\n",
576 dev->bid_name, diff));
577
578 fd = open(dev->bid_name, O_RDONLY);
579 if (fd < 0
580 || fstat(fd, &st) < 0
581 ) {
582 if (fd >= 0)
583 close(fd);
584 if (errno == ENXIO || errno == ENODEV || errno == ENOENT) {
585 blkid_free_dev(dev);
586 return NULL;
587 }
588 /* We don't have read permission, just return cache data. */
589 DBG(DEBUG_PROBE,
590 printf("returning unverified data for %s\n",
591 dev->bid_name));
592 return dev;
593 }
594
595 memset(bufs, 0, sizeof(bufs));
596
597 /*
598 * Iterate over the type array. If we already know the type,
599 * then try that first. If it doesn't work, then blow away
600 * the type information, and try again.
601 *
602 */
603try_again:
604 type = 0;
605 if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) {
606 uuid_t uuid;
607
608 if (check_mdraid(fd, uuid) == 0) {
609 set_uuid(dev, uuid);
610 type = "mdraid";
611 goto found_type;
612 }
613 }
614 for (id = type_array; id->bim_type; id++) {
615 if (dev->bid_type &&
616 strcmp(id->bim_type, dev->bid_type))
617 continue;
618
619 idx = id->bim_kboff + (id->bim_sboff >> 10);
620 if (idx > BLKID_BLK_OFFS || idx < 0)
621 continue;
622 buf = bufs[idx];
623 if (!buf) {
624 if (lseek(fd, idx << 10, SEEK_SET) < 0)
625 continue;
626
627 buf = xmalloc(1024);
628
629 if (read(fd, buf, 1024) != 1024) {
630 free(buf);
631 continue;
632 }
633 bufs[idx] = buf;
634 }
635
636 if (memcmp(id->bim_magic, buf + (id->bim_sboff&0x3ff),
637 id->bim_len))
638 continue;
639
640 if ((id->bim_probe == NULL) ||
641 (id->bim_probe(fd, cache, dev, id, buf) == 0)) {
642 type = id->bim_type;
643 goto found_type;
644 }
645 }
646
647 if (!id->bim_type && dev->bid_type) {
648 /*
649 * Zap the device filesystem type and try again
650 */
651 blkid_set_tag(dev, "TYPE", 0, 0);
652 blkid_set_tag(dev, "SEC_TYPE", 0, 0);
653 blkid_set_tag(dev, "LABEL", 0, 0);
654 blkid_set_tag(dev, "UUID", 0, 0);
655 goto try_again;
656 }
657
658 if (!dev->bid_type) {
659 blkid_free_dev(dev);
660 close(fd);
661 return NULL;
662 }
663
664found_type:
665 if (dev && type) {
666 dev->bid_devno = st.st_rdev;
667 dev->bid_time = time(NULL);
668 dev->bid_flags |= BLKID_BID_FL_VERIFIED;
669 cache->bic_flags |= BLKID_BIC_FL_CHANGED;
670
671 blkid_set_tag(dev, "TYPE", type, 0);
672
673 DBG(DEBUG_PROBE, printf("%s: devno 0x%04llx, type %s\n",
674 dev->bid_name, st.st_rdev, type));
675 }
676
677 close(fd);
678
679 return dev;
680}
681
682int blkid_known_fstype(const char *fstype)
683{
684 const struct blkid_magic *id;
685
686 for (id = type_array; id->bim_type; id++) {
687 if (strcmp(fstype, id->bim_type) == 0)
688 return 1;
689 }
690 return 0;
691}
692
693#ifdef TEST_PROGRAM
694int main(int argc, char **argv)
695{
696 blkid_dev dev;
697 blkid_cache cache;
698 int ret;
699
700 blkid_debug_mask = DEBUG_ALL;
701 if (argc != 2) {
702 fprintf(stderr, "Usage: %s device\n"
703 "Probe a single device to determine type\n", argv[0]);
704 exit(1);
705 }
706 if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
707 fprintf(stderr, "%s: error creating cache (%d)\n",
708 argv[0], ret);
709 exit(1);
710 }
711 dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL);
712 if (!dev) {
713 printf("%s: %s has an unsupported type\n", argv[0], argv[1]);
714 return 1;
715 }
716 printf("%s is type %s\n", argv[1], dev->bid_type ?
717 dev->bid_type : "(null)");
718 if (dev->bid_label)
719 printf("\tlabel is '%s'\n", dev->bid_label);
720 if (dev->bid_uuid)
721 printf("\tuuid is %s\n", dev->bid_uuid);
722
723 blkid_free_dev(dev);
724 return 0;
725}
726#endif
diff --git a/e2fsprogs/old_e2fsprogs/blkid/probe.h b/e2fsprogs/old_e2fsprogs/blkid/probe.h
deleted file mode 100644
index b6d8f8e7d..000000000
--- a/e2fsprogs/old_e2fsprogs/blkid/probe.h
+++ /dev/null
@@ -1,374 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * probe.h - constants and on-disk structures for extracting device data
4 *
5 * Copyright (C) 1999 by Andries Brouwer
6 * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
7 * Copyright (C) 2001 by Andreas Dilger
8 *
9 * %Begin-Header%
10 * This file may be redistributed under the terms of the
11 * GNU Lesser General Public License.
12 * %End-Header%
13 */
14#ifndef BLKID_PROBE_H
15#define BLKID_PROBE_H 1
16
17#include <linux/types.h>
18
19struct blkid_magic;
20
21typedef int (*blkid_probe_t)(int fd, blkid_cache cache, blkid_dev dev,
22 const struct blkid_magic *id, unsigned char *buf);
23
24struct blkid_magic {
25 const char *bim_type; /* type name for this magic */
26 long bim_kboff; /* kilobyte offset of superblock */
27 unsigned bim_sboff; /* byte offset within superblock */
28 unsigned bim_len; /* length of magic */
29 const char *bim_magic; /* magic string */
30 blkid_probe_t bim_probe; /* probe function */
31};
32
33/*
34 * Structures for each of the content types we want to extract information
35 * from. We do not necessarily need the magic field here, because we have
36 * already identified the content type before we get this far. It may still
37 * be useful if there are probe functions which handle multiple content types.
38 */
39struct ext2_super_block {
40 __u32 s_inodes_count;
41 __u32 s_blocks_count;
42 __u32 s_r_blocks_count;
43 __u32 s_free_blocks_count;
44 __u32 s_free_inodes_count;
45 __u32 s_first_data_block;
46 __u32 s_log_block_size;
47 __u32 s_dummy3[7];
48 unsigned char s_magic[2];
49 __u16 s_state;
50 __u32 s_dummy5[8];
51 __u32 s_feature_compat;
52 __u32 s_feature_incompat;
53 __u32 s_feature_ro_compat;
54 unsigned char s_uuid[16];
55 char s_volume_name[16];
56};
57#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x00000004
58#define EXT3_FEATURE_INCOMPAT_RECOVER 0x00000004
59#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x00000008
60
61struct xfs_super_block {
62 unsigned char xs_magic[4];
63 __u32 xs_blocksize;
64 __u64 xs_dblocks;
65 __u64 xs_rblocks;
66 __u32 xs_dummy1[2];
67 unsigned char xs_uuid[16];
68 __u32 xs_dummy2[15];
69 char xs_fname[12];
70 __u32 xs_dummy3[2];
71 __u64 xs_icount;
72 __u64 xs_ifree;
73 __u64 xs_fdblocks;
74};
75
76struct reiserfs_super_block {
77 __u32 rs_blocks_count;
78 __u32 rs_free_blocks;
79 __u32 rs_root_block;
80 __u32 rs_journal_block;
81 __u32 rs_journal_dev;
82 __u32 rs_orig_journal_size;
83 __u32 rs_dummy2[5];
84 __u16 rs_blocksize;
85 __u16 rs_dummy3[3];
86 unsigned char rs_magic[12];
87 __u32 rs_dummy4[5];
88 unsigned char rs_uuid[16];
89 char rs_label[16];
90};
91
92struct jfs_super_block {
93 unsigned char js_magic[4];
94 __u32 js_version;
95 __u64 js_size;
96 __u32 js_bsize;
97 __u32 js_dummy1;
98 __u32 js_pbsize;
99 __u32 js_dummy2[27];
100 unsigned char js_uuid[16];
101 unsigned char js_label[16];
102 unsigned char js_loguuid[16];
103};
104
105struct romfs_super_block {
106 unsigned char ros_magic[8];
107 __u32 ros_dummy1[2];
108 unsigned char ros_volume[16];
109};
110
111struct cramfs_super_block {
112 __u8 magic[4];
113 __u32 size;
114 __u32 flags;
115 __u32 future;
116 __u8 signature[16];
117 struct cramfs_info {
118 __u32 crc;
119 __u32 edition;
120 __u32 blocks;
121 __u32 files;
122 } info;
123 __u8 name[16];
124};
125
126struct swap_id_block {
127/* unsigned char sws_boot[1024]; */
128 __u32 sws_version;
129 __u32 sws_lastpage;
130 __u32 sws_nrbad;
131 unsigned char sws_uuid[16];
132 char sws_volume[16];
133 unsigned char sws_pad[117];
134 __u32 sws_badpg;
135};
136
137/* Yucky misaligned values */
138struct vfat_super_block {
139/* 00*/ unsigned char vs_ignored[3];
140/* 03*/ unsigned char vs_sysid[8];
141/* 0b*/ unsigned char vs_sector_size[2];
142/* 0d*/ __u8 vs_cluster_size;
143/* 0e*/ __u16 vs_reserved;
144/* 10*/ __u8 vs_fats;
145/* 11*/ unsigned char vs_dir_entries[2];
146/* 13*/ unsigned char vs_sectors[2];
147/* 15*/ unsigned char vs_media;
148/* 16*/ __u16 vs_fat_length;
149/* 18*/ __u16 vs_secs_track;
150/* 1a*/ __u16 vs_heads;
151/* 1c*/ __u32 vs_hidden;
152/* 20*/ __u32 vs_total_sect;
153/* 24*/ __u32 vs_fat32_length;
154/* 28*/ __u16 vs_flags;
155/* 2a*/ __u8 vs_version[2];
156/* 2c*/ __u32 vs_root_cluster;
157/* 30*/ __u16 vs_insfo_sector;
158/* 32*/ __u16 vs_backup_boot;
159/* 34*/ __u16 vs_reserved2[6];
160/* 40*/ unsigned char vs_unknown[3];
161/* 43*/ unsigned char vs_serno[4];
162/* 47*/ char vs_label[11];
163/* 52*/ unsigned char vs_magic[8];
164/* 5a*/ unsigned char vs_dummy2[164];
165/*1fe*/ unsigned char vs_pmagic[2];
166};
167
168/* Yucky misaligned values */
169struct msdos_super_block {
170/* 00*/ unsigned char ms_ignored[3];
171/* 03*/ unsigned char ms_sysid[8];
172/* 0b*/ unsigned char ms_sector_size[2];
173/* 0d*/ __u8 ms_cluster_size;
174/* 0e*/ __u16 ms_reserved;
175/* 10*/ __u8 ms_fats;
176/* 11*/ unsigned char ms_dir_entries[2];
177/* 13*/ unsigned char ms_sectors[2];
178/* 15*/ unsigned char ms_media;
179/* 16*/ __u16 ms_fat_length;
180/* 18*/ __u16 ms_secs_track;
181/* 1a*/ __u16 ms_heads;
182/* 1c*/ __u32 ms_hidden;
183/* 20*/ __u32 ms_total_sect;
184/* 24*/ unsigned char ms_unknown[3];
185/* 27*/ unsigned char ms_serno[4];
186/* 2b*/ char ms_label[11];
187/* 36*/ unsigned char ms_magic[8];
188/* 3d*/ unsigned char ms_dummy2[192];
189/*1fe*/ unsigned char ms_pmagic[2];
190};
191
192struct minix_super_block {
193 __u16 ms_ninodes;
194 __u16 ms_nzones;
195 __u16 ms_imap_blocks;
196 __u16 ms_zmap_blocks;
197 __u16 ms_firstdatazone;
198 __u16 ms_log_zone_size;
199 __u32 ms_max_size;
200 unsigned char ms_magic[2];
201 __u16 ms_state;
202 __u32 ms_zones;
203};
204
205struct mdp_superblock_s {
206 __u32 md_magic;
207 __u32 major_version;
208 __u32 minor_version;
209 __u32 patch_version;
210 __u32 gvalid_words;
211 __u32 set_uuid0;
212 __u32 ctime;
213 __u32 level;
214 __u32 size;
215 __u32 nr_disks;
216 __u32 raid_disks;
217 __u32 md_minor;
218 __u32 not_persistent;
219 __u32 set_uuid1;
220 __u32 set_uuid2;
221 __u32 set_uuid3;
222};
223
224struct hfs_super_block {
225 char h_magic[2];
226 char h_dummy[18];
227 __u32 h_blksize;
228};
229
230struct ocfs_volume_header {
231 unsigned char minor_version[4];
232 unsigned char major_version[4];
233 unsigned char signature[128];
234 char mount[128];
235 unsigned char mount_len[2];
236};
237
238struct ocfs_volume_label {
239 unsigned char disk_lock[48];
240 char label[64];
241 unsigned char label_len[2];
242 unsigned char vol_id[16];
243 unsigned char vol_id_len[2];
244};
245
246#define ocfsmajor(o) ((__u32)o.major_version[0] \
247 + (((__u32) o.major_version[1]) << 8) \
248 + (((__u32) o.major_version[2]) << 16) \
249 + (((__u32) o.major_version[3]) << 24))
250#define ocfslabellen(o) ((__u32)o.label_len[0] + (((__u32) o.label_len[1]) << 8))
251#define ocfsmountlen(o) ((__u32)o.mount_len[0] + (((__u32) o.mount_len[1])<<8))
252
253#define OCFS_MAGIC "OracleCFS"
254
255struct ocfs2_super_block {
256 unsigned char signature[8];
257 unsigned char s_dummy1[184];
258 unsigned char s_dummy2[80];
259 char s_label[64];
260 unsigned char s_uuid[16];
261};
262
263#define OCFS2_MIN_BLOCKSIZE 512
264#define OCFS2_MAX_BLOCKSIZE 4096
265
266#define OCFS2_SUPER_BLOCK_BLKNO 2
267
268#define OCFS2_SUPER_BLOCK_SIGNATURE "OCFSV2"
269
270struct oracle_asm_disk_label {
271 char dummy[32];
272 char dl_tag[8];
273 char dl_id[24];
274};
275
276#define ORACLE_ASM_DISK_LABEL_MARKED "ORCLDISK"
277#define ORACLE_ASM_DISK_LABEL_OFFSET 32
278
279#define ISODCL(from, to) (to - from + 1)
280struct iso_volume_descriptor {
281 char type[ISODCL(1,1)]; /* 711 */
282 char id[ISODCL(2,6)];
283 char version[ISODCL(7,7)];
284 char data[ISODCL(8,2048)];
285};
286
287/*
288 * Byte swap functions
289 */
290#ifdef __GNUC__
291#define _INLINE_ static __inline__
292#else /* For Watcom C */
293#define _INLINE_ static inline
294#endif
295
296static __u16 blkid_swab16(__u16 val);
297static __u32 blkid_swab32(__u32 val);
298static __u64 blkid_swab64(__u64 val);
299
300#if ((defined __GNUC__) && \
301 (defined(__i386__) || defined(__i486__) || defined(__i586__)))
302
303#define _BLKID_HAVE_ASM_BITOPS_
304
305_INLINE_ __u32 blkid_swab32(__u32 val)
306{
307#ifdef EXT2FS_REQUIRE_486
308 __asm__("bswap %0" : "=r" (val) : "0" (val));
309#else
310 __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
311 "rorl $16,%0\n\t" /* swap words */
312 "xchgb %b0,%h0" /* swap higher bytes */
313 :"=q" (val)
314 : "0" (val));
315#endif
316 return val;
317}
318
319_INLINE_ __u16 blkid_swab16(__u16 val)
320{
321 __asm__("xchgb %b0,%h0" /* swap bytes */
322 : "=q" (val)
323 : "0" (val));
324 return val;
325}
326
327_INLINE_ __u64 blkid_swab64(__u64 val)
328{
329 return blkid_swab32(val >> 32) |
330 ( ((__u64)blkid_swab32((__u32)val)) << 32 );
331}
332#endif
333
334#if !defined(_BLKID_HAVE_ASM_BITOPS_)
335
336_INLINE_ __u16 blkid_swab16(__u16 val)
337{
338 return (val >> 8) | (val << 8);
339}
340
341_INLINE_ __u32 blkid_swab32(__u32 val)
342{
343 return (val>>24) | ((val>>8) & 0xFF00) |
344 ((val<<8) & 0xFF0000) | (val<<24);
345}
346
347_INLINE_ __u64 blkid_swab64(__u64 val)
348{
349 return blkid_swab32(val >> 32) |
350 ( ((__u64)blkid_swab32((__u32)val)) << 32 );
351}
352#endif
353
354
355
356#if __BYTE_ORDER == __BIG_ENDIAN
357#define blkid_le16(x) blkid_swab16(x)
358#define blkid_le32(x) blkid_swab32(x)
359#define blkid_le64(x) blkid_swab64(x)
360#define blkid_be16(x) (x)
361#define blkid_be32(x) (x)
362#define blkid_be64(x) (x)
363#else
364#define blkid_le16(x) (x)
365#define blkid_le32(x) (x)
366#define blkid_le64(x) (x)
367#define blkid_be16(x) blkid_swab16(x)
368#define blkid_be32(x) blkid_swab32(x)
369#define blkid_be64(x) blkid_swab64(x)
370#endif
371
372#undef _INLINE_
373
374#endif /* _BLKID_PROBE_H */
diff --git a/e2fsprogs/old_e2fsprogs/blkid/read.c b/e2fsprogs/old_e2fsprogs/blkid/read.c
deleted file mode 100644
index feeda518b..000000000
--- a/e2fsprogs/old_e2fsprogs/blkid/read.c
+++ /dev/null
@@ -1,459 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * read.c - read the blkid cache from disk, to avoid scanning all devices
4 *
5 * Copyright (C) 2001, 2003 Theodore Y. Ts'o
6 * Copyright (C) 2001 Andreas Dilger
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the
10 * GNU Lesser General Public License.
11 * %End-Header%
12 */
13
14#include <stdio.h>
15#include <ctype.h>
16#include <string.h>
17#include <time.h>
18#include <sys/types.h>
19#include <sys/stat.h>
20#include <fcntl.h>
21#include <unistd.h>
22#include <errno.h>
23
24#include "blkidP.h"
25#include "../uuid/uuid.h"
26
27#ifdef HAVE_STRTOULL
28#define __USE_ISOC9X
29#define STRTOULL strtoull /* defined in stdlib.h if you try hard enough */
30#else
31/* FIXME: need to support real strtoull here */
32#define STRTOULL strtoul
33#endif
34
35#include <stdlib.h>
36
37#ifdef TEST_PROGRAM
38#define blkid_debug_dump_dev(dev) (debug_dump_dev(dev))
39static void debug_dump_dev(blkid_dev dev);
40#endif
41
42/*
43 * File format:
44 *
45 * <device [<NAME="value"> ...]>device_name</device>
46 *
47 * The following tags are required for each entry:
48 * <ID="id"> unique (within this file) ID number of this device
49 * <TIME="time"> (ascii time_t) time this entry was last read from disk
50 * <TYPE="type"> (detected) type of filesystem/data for this partition
51 *
52 * The following tags may be present, depending on the device contents
53 * <LABEL="label"> (user supplied) label (volume name, etc)
54 * <UUID="uuid"> (generated) universally unique identifier (serial no)
55 */
56
57static char *skip_over_blank(char *cp)
58{
59 while (*cp && isspace(*cp))
60 cp++;
61 return cp;
62}
63
64static char *skip_over_word(char *cp)
65{
66 char ch;
67
68 while ((ch = *cp)) {
69 /* If we see a backslash, skip the next character */
70 if (ch == '\\') {
71 cp++;
72 if (*cp == '\0')
73 break;
74 cp++;
75 continue;
76 }
77 if (isspace(ch) || ch == '<' || ch == '>')
78 break;
79 cp++;
80 }
81 return cp;
82}
83
84static char *strip_line(char *line)
85{
86 char *p;
87
88 line = skip_over_blank(line);
89
90 p = line + strlen(line) - 1;
91
92 while (*line) {
93 if (isspace(*p))
94 *p-- = '\0';
95 else
96 break;
97 }
98
99 return line;
100}
101
102/*
103 * Start parsing a new line from the cache.
104 *
105 * line starts with "<device" return 1 -> continue parsing line
106 * line starts with "<foo", empty, or # return 0 -> skip line
107 * line starts with other, return -BLKID_ERR_CACHE -> error
108 */
109static int parse_start(char **cp)
110{
111 char *p;
112
113 p = strip_line(*cp);
114
115 /* Skip comment or blank lines. We can't just NUL the first '#' char,
116 * in case it is inside quotes, or escaped.
117 */
118 if (*p == '\0' || *p == '#')
119 return 0;
120
121 if (!strncmp(p, "<device", 7)) {
122 DBG(DEBUG_READ, printf("found device header: %8s\n", p));
123 p += 7;
124
125 *cp = p;
126 return 1;
127 }
128
129 if (*p == '<')
130 return 0;
131
132 return -BLKID_ERR_CACHE;
133}
134
135/* Consume the remaining XML on the line (cosmetic only) */
136static int parse_end(char **cp)
137{
138 *cp = skip_over_blank(*cp);
139
140 if (!strncmp(*cp, "</device>", 9)) {
141 DBG(DEBUG_READ, printf("found device trailer %9s\n", *cp));
142 *cp += 9;
143 return 0;
144 }
145
146 return -BLKID_ERR_CACHE;
147}
148
149/*
150 * Allocate a new device struct with device name filled in. Will handle
151 * finding the device on lines of the form:
152 * <device foo=bar>devname</device>
153 * <device>devname<foo>bar</foo></device>
154 */
155static int parse_dev(blkid_cache cache, blkid_dev *dev, char **cp)
156{
157 char *start, *tmp, *end, *name;
158 int ret;
159
160 if ((ret = parse_start(cp)) <= 0)
161 return ret;
162
163 start = tmp = strchr(*cp, '>');
164 if (!start) {
165 DBG(DEBUG_READ,
166 printf("blkid: short line parsing dev: %s\n", *cp));
167 return -BLKID_ERR_CACHE;
168 }
169 start = skip_over_blank(start + 1);
170 end = skip_over_word(start);
171
172 DBG(DEBUG_READ, printf("device should be %*s\n", end - start, start));
173
174 if (**cp == '>')
175 *cp = end;
176 else
177 (*cp)++;
178
179 *tmp = '\0';
180
181 if (!(tmp = strrchr(end, '<')) || parse_end(&tmp) < 0) {
182 DBG(DEBUG_READ,
183 printf("blkid: missing </device> ending: %s\n", end));
184 } else if (tmp)
185 *tmp = '\0';
186
187 if (end - start <= 1) {
188 DBG(DEBUG_READ, printf("blkid: empty device name: %s\n", *cp));
189 return -BLKID_ERR_CACHE;
190 }
191
192 name = blkid_strndup(start, end-start);
193 if (name == NULL)
194 return -BLKID_ERR_MEM;
195
196 DBG(DEBUG_READ, printf("found dev %s\n", name));
197
198 if (!(*dev = blkid_get_dev(cache, name, BLKID_DEV_CREATE)))
199 return -BLKID_ERR_MEM;
200
201 free(name);
202 return 1;
203}
204
205/*
206 * Extract a tag of the form NAME="value" from the line.
207 */
208static int parse_token(char **name, char **value, char **cp)
209{
210 char *end;
211
212 if (!name || !value || !cp)
213 return -BLKID_ERR_PARAM;
214
215 if (!(*value = strchr(*cp, '=')))
216 return 0;
217
218 **value = '\0';
219 *name = strip_line(*cp);
220 *value = skip_over_blank(*value + 1);
221
222 if (**value == '"') {
223 end = strchr(*value + 1, '"');
224 if (!end) {
225 DBG(DEBUG_READ,
226 printf("unbalanced quotes at: %s\n", *value));
227 *cp = *value;
228 return -BLKID_ERR_CACHE;
229 }
230 (*value)++;
231 *end = '\0';
232 end++;
233 } else {
234 end = skip_over_word(*value);
235 if (*end) {
236 *end = '\0';
237 end++;
238 }
239 }
240 *cp = end;
241
242 return 1;
243}
244
245/*
246 * Extract a tag of the form <NAME>value</NAME> from the line.
247 */
248/*
249static int parse_xml(char **name, char **value, char **cp)
250{
251 char *end;
252
253 if (!name || !value || !cp)
254 return -BLKID_ERR_PARAM;
255
256 *name = strip_line(*cp);
257
258 if ((*name)[0] != '<' || (*name)[1] == '/')
259 return 0;
260
261 FIXME: finish this.
262}
263*/
264
265/*
266 * Extract a tag from the line.
267 *
268 * Return 1 if a valid tag was found.
269 * Return 0 if no tag found.
270 * Return -ve error code.
271 */
272static int parse_tag(blkid_cache cache, blkid_dev dev, char **cp)
273{
274 char *name;
275 char *value;
276 int ret;
277
278 if (!cache || !dev)
279 return -BLKID_ERR_PARAM;
280
281 if ((ret = parse_token(&name, &value, cp)) <= 0 /* &&
282 (ret = parse_xml(&name, &value, cp)) <= 0 */)
283 return ret;
284
285 /* Some tags are stored directly in the device struct */
286 if (!strcmp(name, "DEVNO"))
287 dev->bid_devno = STRTOULL(value, 0, 0);
288 else if (!strcmp(name, "PRI"))
289 dev->bid_pri = strtol(value, 0, 0);
290 else if (!strcmp(name, "TIME"))
291 /* FIXME: need to parse a long long eventually */
292 dev->bid_time = strtol(value, 0, 0);
293 else
294 ret = blkid_set_tag(dev, name, value, strlen(value));
295
296 DBG(DEBUG_READ, printf(" tag: %s=\"%s\"\n", name, value));
297
298 return ret < 0 ? ret : 1;
299}
300
301/*
302 * Parse a single line of data, and return a newly allocated dev struct.
303 * Add the new device to the cache struct, if one was read.
304 *
305 * Lines are of the form <device [TAG="value" ...]>/dev/foo</device>
306 *
307 * Returns -ve value on error.
308 * Returns 0 otherwise.
309 * If a valid device was read, *dev_p is non-NULL, otherwise it is NULL
310 * (e.g. comment lines, unknown XML content, etc).
311 */
312static int blkid_parse_line(blkid_cache cache, blkid_dev *dev_p, char *cp)
313{
314 blkid_dev dev;
315 int ret;
316
317 if (!cache || !dev_p)
318 return -BLKID_ERR_PARAM;
319
320 *dev_p = NULL;
321
322 DBG(DEBUG_READ, printf("line: %s\n", cp));
323
324 if ((ret = parse_dev(cache, dev_p, &cp)) <= 0)
325 return ret;
326
327 dev = *dev_p;
328
329 while ((ret = parse_tag(cache, dev, &cp)) > 0) {
330 ;
331 }
332
333 if (dev->bid_type == NULL) {
334 DBG(DEBUG_READ,
335 printf("blkid: device %s has no TYPE\n",dev->bid_name));
336 blkid_free_dev(dev);
337 }
338
339 DBG(DEBUG_READ, blkid_debug_dump_dev(dev));
340
341 return ret;
342}
343
344/*
345 * Parse the specified filename, and return the data in the supplied or
346 * a newly allocated cache struct. If the file doesn't exist, return a
347 * new empty cache struct.
348 */
349void blkid_read_cache(blkid_cache cache)
350{
351 FILE *file;
352 char buf[4096];
353 int fd, lineno = 0;
354 struct stat st;
355
356 if (!cache)
357 return;
358
359 /*
360 * If the file doesn't exist, then we just return an empty
361 * struct so that the cache can be populated.
362 */
363 if ((fd = open(cache->bic_filename, O_RDONLY)) < 0)
364 return;
365 if (fstat(fd, &st) < 0)
366 goto errout;
367 if ((st.st_mtime == cache->bic_ftime) ||
368 (cache->bic_flags & BLKID_BIC_FL_CHANGED)) {
369 DBG(DEBUG_CACHE, printf("skipping re-read of %s\n",
370 cache->bic_filename));
371 goto errout;
372 }
373
374 DBG(DEBUG_CACHE, printf("reading cache file %s\n",
375 cache->bic_filename));
376
377 file = xfdopen_for_read(fd);
378
379 while (fgets(buf, sizeof(buf), file)) {
380 blkid_dev dev;
381 unsigned int end;
382
383 lineno++;
384 if (buf[0] == 0)
385 continue;
386 end = strlen(buf) - 1;
387 /* Continue reading next line if it ends with a backslash */
388 while (end < sizeof(buf) - 2 && buf[end] == '\\' &&
389 fgets(buf + end, sizeof(buf) - end, file)) {
390 end = strlen(buf) - 1;
391 lineno++;
392 }
393
394 if (blkid_parse_line(cache, &dev, buf) < 0) {
395 DBG(DEBUG_READ,
396 printf("blkid: bad format on line %d\n", lineno));
397 continue;
398 }
399 }
400 fclose(file);
401
402 /*
403 * Initially we do not need to write out the cache file.
404 */
405 cache->bic_flags &= ~BLKID_BIC_FL_CHANGED;
406 cache->bic_ftime = st.st_mtime;
407
408 return;
409errout:
410 close(fd);
411}
412
413#ifdef TEST_PROGRAM
414static void debug_dump_dev(blkid_dev dev)
415{
416 struct list_head *p;
417
418 if (!dev) {
419 printf(" dev: NULL\n");
420 return;
421 }
422
423 printf(" dev: name = %s\n", dev->bid_name);
424 printf(" dev: DEVNO=\"0x%0llx\"\n", dev->bid_devno);
425 printf(" dev: TIME=\"%lu\"\n", dev->bid_time);
426 printf(" dev: PRI=\"%d\"\n", dev->bid_pri);
427 printf(" dev: flags = 0x%08X\n", dev->bid_flags);
428
429 list_for_each(p, &dev->bid_tags) {
430 blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
431 if (tag)
432 printf(" tag: %s=\"%s\"\n", tag->bit_name,
433 tag->bit_val);
434 else
435 printf(" tag: NULL\n");
436 }
437 bb_putchar('\n');
438}
439
440int main(int argc, char**argv)
441{
442 blkid_cache cache = NULL;
443 int ret;
444
445 blkid_debug_mask = DEBUG_ALL;
446 if (argc > 2) {
447 fprintf(stderr, "Usage: %s [filename]\n"
448 "Test parsing of the cache (filename)\n", argv[0]);
449 exit(1);
450 }
451 if ((ret = blkid_get_cache(&cache, argv[1])) < 0)
452 fprintf(stderr, "error %d reading cache file %s\n", ret,
453 argv[1] ? argv[1] : BLKID_CACHE_FILE);
454
455 blkid_put_cache(cache);
456
457 return ret;
458}
459#endif
diff --git a/e2fsprogs/old_e2fsprogs/blkid/resolve.c b/e2fsprogs/old_e2fsprogs/blkid/resolve.c
deleted file mode 100644
index 295ca61bf..000000000
--- a/e2fsprogs/old_e2fsprogs/blkid/resolve.c
+++ /dev/null
@@ -1,139 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * resolve.c - resolve names and tags into specific devices
4 *
5 * Copyright (C) 2001, 2003 Theodore Ts'o.
6 * Copyright (C) 2001 Andreas Dilger
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the
10 * GNU Lesser General Public License.
11 * %End-Header%
12 */
13
14#include <stdio.h>
15#ifdef HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#include <stdlib.h>
19#include <fcntl.h>
20#include <string.h>
21#include <sys/types.h>
22#include <sys/stat.h>
23#include "blkidP.h"
24#include "probe.h"
25
26/*
27 * Find a tagname (e.g. LABEL or UUID) on a specific device.
28 */
29char *blkid_get_tag_value(blkid_cache cache, const char *tagname,
30 const char *devname)
31{
32 blkid_tag found;
33 blkid_dev dev;
34 blkid_cache c = cache;
35 char *ret = NULL;
36
37 DBG(DEBUG_RESOLVE, printf("looking for %s on %s\n", tagname, devname));
38
39 if (!devname)
40 return NULL;
41
42 if (!cache) {
43 if (blkid_get_cache(&c, NULL) < 0)
44 return NULL;
45 }
46
47 if ((dev = blkid_get_dev(c, devname, BLKID_DEV_NORMAL)) &&
48 (found = blkid_find_tag_dev(dev, tagname)))
49 ret = blkid_strdup(found->bit_val);
50
51 if (!cache)
52 blkid_put_cache(c);
53
54 return ret;
55}
56
57/*
58 * Locate a device name from a token (NAME=value string), or (name, value)
59 * pair. In the case of a token, value is ignored. If the "token" is not
60 * of the form "NAME=value" and there is no value given, then it is assumed
61 * to be the actual devname and a copy is returned.
62 */
63char *blkid_get_devname(blkid_cache cache, const char *token,
64 const char *value)
65{
66 blkid_dev dev;
67 blkid_cache c = cache;
68 char *t = NULL, *v = NULL;
69 char *ret = NULL;
70
71 if (!token)
72 return NULL;
73
74 if (!cache) {
75 if (blkid_get_cache(&c, NULL) < 0)
76 return NULL;
77 }
78
79 DBG(DEBUG_RESOLVE,
80 printf("looking for %s%s%s %s\n", token, value ? "=" : "",
81 value ? value : "", cache ? "in cache" : "from disk"));
82
83 if (!value) {
84 if (!strchr(token, '='))
85 return blkid_strdup(token);
86 blkid_parse_tag_string(token, &t, &v);
87 if (!t || !v)
88 goto errout;
89 token = t;
90 value = v;
91 }
92
93 dev = blkid_find_dev_with_tag(c, token, value);
94 if (!dev)
95 goto errout;
96
97 ret = blkid_strdup(blkid_dev_devname(dev));
98
99errout:
100 free(t);
101 free(v);
102 if (!cache) {
103 blkid_put_cache(c);
104 }
105 return ret;
106}
107
108#ifdef TEST_PROGRAM
109int main(int argc, char **argv)
110{
111 char *value;
112 blkid_cache cache;
113
114 blkid_debug_mask = DEBUG_ALL;
115 if (argc != 2 && argc != 3) {
116 fprintf(stderr, "Usage:\t%s tagname=value\n"
117 "\t%s tagname devname\n"
118 "Find which device holds a given token or\n"
119 "Find what the value of a tag is in a device\n",
120 argv[0], argv[0]);
121 exit(1);
122 }
123 if (blkid_get_cache(&cache, bb_dev_null) < 0) {
124 fprintf(stderr, "Can't get blkid cache\n");
125 exit(1);
126 }
127
128 if (argv[2]) {
129 value = blkid_get_tag_value(cache, argv[1], argv[2]);
130 printf("%s has tag %s=%s\n", argv[2], argv[1],
131 value ? value : "<missing>");
132 } else {
133 value = blkid_get_devname(cache, argv[1], NULL);
134 printf("%s has tag %s\n", value ? value : "<none>", argv[1]);
135 }
136 blkid_put_cache(cache);
137 return value ? 0 : 1;
138}
139#endif
diff --git a/e2fsprogs/old_e2fsprogs/blkid/save.c b/e2fsprogs/old_e2fsprogs/blkid/save.c
deleted file mode 100644
index e60cca445..000000000
--- a/e2fsprogs/old_e2fsprogs/blkid/save.c
+++ /dev/null
@@ -1,189 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * save.c - write the cache struct to disk
4 *
5 * Copyright (C) 2001 by Andreas Dilger
6 * Copyright (C) 2003 Theodore Ts'o
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the
10 * GNU Lesser General Public License.
11 * %End-Header%
12 */
13
14#include <stdio.h>
15#include <string.h>
16#include <stdlib.h>
17#include <unistd.h>
18#include <sys/types.h>
19#ifdef HAVE_SYS_STAT_H
20#include <sys/stat.h>
21#endif
22#ifdef HAVE_SYS_MKDEV_H
23#include <sys/mkdev.h>
24#endif
25#ifdef HAVE_ERRNO_H
26#include <errno.h>
27#endif
28#include "blkidP.h"
29
30static int save_dev(blkid_dev dev, FILE *file)
31{
32 struct list_head *p;
33
34 if (!dev || dev->bid_name[0] != '/')
35 return 0;
36
37 DBG(DEBUG_SAVE,
38 printf("device %s, type %s\n", dev->bid_name, dev->bid_type));
39
40 fprintf(file,
41 "<device DEVNO=\"0x%04lx\" TIME=\"%lu\"",
42 (unsigned long) dev->bid_devno, dev->bid_time);
43 if (dev->bid_pri)
44 fprintf(file, " PRI=\"%d\"", dev->bid_pri);
45 list_for_each(p, &dev->bid_tags) {
46 blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
47 fprintf(file, " %s=\"%s\"", tag->bit_name,tag->bit_val);
48 }
49 fprintf(file, ">%s</device>\n", dev->bid_name);
50
51 return 0;
52}
53
54/*
55 * Write out the cache struct to the cache file on disk.
56 */
57int blkid_flush_cache(blkid_cache cache)
58{
59 struct list_head *p;
60 char *tmp = NULL;
61 const char *opened = NULL;
62 const char *filename;
63 FILE *file = NULL;
64 int fd, ret = 0;
65 struct stat st;
66
67 if (!cache)
68 return -BLKID_ERR_PARAM;
69
70 if (list_empty(&cache->bic_devs) ||
71 !(cache->bic_flags & BLKID_BIC_FL_CHANGED)) {
72 DBG(DEBUG_SAVE, printf("skipping cache file write\n"));
73 return 0;
74 }
75
76 filename = cache->bic_filename ? cache->bic_filename: BLKID_CACHE_FILE;
77
78 /* If we can't write to the cache file, then don't even try */
79 if (((ret = stat(filename, &st)) < 0 && errno != ENOENT) ||
80 (ret == 0 && access(filename, W_OK) < 0)) {
81 DBG(DEBUG_SAVE,
82 printf("can't write to cache file %s\n", filename));
83 return 0;
84 }
85
86 /*
87 * Try and create a temporary file in the same directory so
88 * that in case of error we don't overwrite the cache file.
89 * If the cache file doesn't yet exist, it isn't a regular
90 * file (e.g. /dev/null or a socket), or we couldn't create
91 * a temporary file then we open it directly.
92 */
93 if (ret == 0 && S_ISREG(st.st_mode)) {
94 tmp = xmalloc(strlen(filename) + 8);
95 sprintf(tmp, "%s-XXXXXX", filename);
96 fd = mkstemp(tmp);
97 if (fd >= 0) {
98 file = xfdopen_for_write(fd);
99 opened = tmp;
100 }
101 fchmod(fd, 0644);
102 }
103
104 if (!file) {
105 file = fopen_for_write(filename);
106 opened = filename;
107 }
108
109 DBG(DEBUG_SAVE,
110 printf("writing cache file %s (really %s)\n",
111 filename, opened));
112
113 if (!file) {
114 ret = errno;
115 goto errout;
116 }
117
118 list_for_each(p, &cache->bic_devs) {
119 blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs);
120 if (!dev->bid_type)
121 continue;
122 if ((ret = save_dev(dev, file)) < 0)
123 break;
124 }
125
126 if (ret >= 0) {
127 cache->bic_flags &= ~BLKID_BIC_FL_CHANGED;
128 ret = 1;
129 }
130
131 fclose(file);
132 if (opened != filename) {
133 if (ret < 0) {
134 unlink(opened);
135 DBG(DEBUG_SAVE,
136 printf("unlinked temp cache %s\n", opened));
137 } else {
138 char *backup;
139
140 backup = xmalloc(strlen(filename) + 5);
141 sprintf(backup, "%s.old", filename);
142 unlink(backup);
143 link(filename, backup);
144 free(backup);
145 rename(opened, filename);
146 DBG(DEBUG_SAVE,
147 printf("moved temp cache %s\n", opened));
148 }
149 }
150
151errout:
152 free(tmp);
153 return ret;
154}
155
156#ifdef TEST_PROGRAM
157int main(int argc, char **argv)
158{
159 blkid_cache cache = NULL;
160 int ret;
161
162 blkid_debug_mask = DEBUG_ALL;
163 if (argc > 2) {
164 fprintf(stderr, "Usage: %s [filename]\n"
165 "Test loading/saving a cache (filename)\n", argv[0]);
166 exit(1);
167 }
168
169 if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
170 fprintf(stderr, "%s: error creating cache (%d)\n",
171 argv[0], ret);
172 exit(1);
173 }
174 if ((ret = blkid_probe_all(cache)) < 0) {
175 fprintf(stderr, "error (%d) probing devices\n", ret);
176 exit(1);
177 }
178 cache->bic_filename = blkid_strdup(argv[1]);
179
180 if ((ret = blkid_flush_cache(cache)) < 0) {
181 fprintf(stderr, "error (%d) saving cache\n", ret);
182 exit(1);
183 }
184
185 blkid_put_cache(cache);
186
187 return ret;
188}
189#endif
diff --git a/e2fsprogs/old_e2fsprogs/blkid/tag.c b/e2fsprogs/old_e2fsprogs/blkid/tag.c
deleted file mode 100644
index f10a701d2..000000000
--- a/e2fsprogs/old_e2fsprogs/blkid/tag.c
+++ /dev/null
@@ -1,431 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * tag.c - allocation/initialization/free routines for tag structs
4 *
5 * Copyright (C) 2001 Andreas Dilger
6 * Copyright (C) 2003 Theodore Ts'o
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the
10 * GNU Lesser General Public License.
11 * %End-Header%
12 */
13
14#include <stdlib.h>
15#include <string.h>
16#include <stdio.h>
17
18#include "blkidP.h"
19
20static blkid_tag blkid_new_tag(void)
21{
22 blkid_tag tag;
23
24 tag = xzalloc(sizeof(struct blkid_struct_tag));
25
26 INIT_LIST_HEAD(&tag->bit_tags);
27 INIT_LIST_HEAD(&tag->bit_names);
28
29 return tag;
30}
31
32#ifdef CONFIG_BLKID_DEBUG
33void blkid_debug_dump_tag(blkid_tag tag)
34{
35 if (!tag) {
36 printf(" tag: NULL\n");
37 return;
38 }
39
40 printf(" tag: %s=\"%s\"\n", tag->bit_name, tag->bit_val);
41}
42#endif
43
44void blkid_free_tag(blkid_tag tag)
45{
46 if (!tag)
47 return;
48
49 DBG(DEBUG_TAG, printf(" freeing tag %s=%s\n", tag->bit_name,
50 tag->bit_val ? tag->bit_val : "(NULL)"));
51 DBG(DEBUG_TAG, blkid_debug_dump_tag(tag));
52
53 list_del(&tag->bit_tags); /* list of tags for this device */
54 list_del(&tag->bit_names); /* list of tags with this type */
55
56 free(tag->bit_name);
57 free(tag->bit_val);
58 free(tag);
59}
60
61/*
62 * Find the desired tag on a device. If value is NULL, then the
63 * first such tag is returned, otherwise return only exact tag if found.
64 */
65blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type)
66{
67 struct list_head *p;
68
69 if (!dev || !type)
70 return NULL;
71
72 list_for_each(p, &dev->bid_tags) {
73 blkid_tag tmp = list_entry(p, struct blkid_struct_tag,
74 bit_tags);
75
76 if (!strcmp(tmp->bit_name, type))
77 return tmp;
78 }
79 return NULL;
80}
81
82/*
83 * Find the desired tag type in the cache.
84 * We return the head tag for this tag type.
85 */
86static blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type)
87{
88 blkid_tag head = NULL, tmp;
89 struct list_head *p;
90
91 if (!cache || !type)
92 return NULL;
93
94 list_for_each(p, &cache->bic_tags) {
95 tmp = list_entry(p, struct blkid_struct_tag, bit_tags);
96 if (!strcmp(tmp->bit_name, type)) {
97 DBG(DEBUG_TAG,
98 printf(" found cache tag head %s\n", type));
99 head = tmp;
100 break;
101 }
102 }
103 return head;
104}
105
106/*
107 * Set a tag on an existing device.
108 *
109 * If value is NULL, then delete the tagsfrom the device.
110 */
111int blkid_set_tag(blkid_dev dev, const char *name,
112 const char *value, const int vlength)
113{
114 blkid_tag t = 0, head = 0;
115 char *val = NULL;
116
117 if (!dev || !name)
118 return -BLKID_ERR_PARAM;
119
120 if (!(val = blkid_strndup(value, vlength)) && value)
121 return -BLKID_ERR_MEM;
122 t = blkid_find_tag_dev(dev, name);
123 if (!value) {
124 blkid_free_tag(t);
125 } else if (t) {
126 if (!strcmp(t->bit_val, val)) {
127 /* Same thing, exit */
128 free(val);
129 return 0;
130 }
131 free(t->bit_val);
132 t->bit_val = val;
133 } else {
134 /* Existing tag not present, add to device */
135 if (!(t = blkid_new_tag()))
136 goto errout;
137 t->bit_name = blkid_strdup(name);
138 t->bit_val = val;
139 t->bit_dev = dev;
140
141 list_add_tail(&t->bit_tags, &dev->bid_tags);
142
143 if (dev->bid_cache) {
144 head = blkid_find_head_cache(dev->bid_cache,
145 t->bit_name);
146 if (!head) {
147 head = blkid_new_tag();
148 if (!head)
149 goto errout;
150
151 DBG(DEBUG_TAG,
152 printf(" creating new cache tag head %s\n", name));
153 head->bit_name = blkid_strdup(name);
154 if (!head->bit_name)
155 goto errout;
156 list_add_tail(&head->bit_tags,
157 &dev->bid_cache->bic_tags);
158 }
159 list_add_tail(&t->bit_names, &head->bit_names);
160 }
161 }
162
163 /* Link common tags directly to the device struct */
164 if (!strcmp(name, "TYPE"))
165 dev->bid_type = val;
166 else if (!strcmp(name, "LABEL"))
167 dev->bid_label = val;
168 else if (!strcmp(name, "UUID"))
169 dev->bid_uuid = val;
170
171 if (dev->bid_cache)
172 dev->bid_cache->bic_flags |= BLKID_BIC_FL_CHANGED;
173 return 0;
174
175errout:
176 blkid_free_tag(t);
177 if (!t)
178 free(val);
179 blkid_free_tag(head);
180 return -BLKID_ERR_MEM;
181}
182
183
184/*
185 * Parse a "NAME=value" string. This is slightly different than
186 * parse_token, because that will end an unquoted value at a space, while
187 * this will assume that an unquoted value is the rest of the token (e.g.
188 * if we are passed an already quoted string from the command-line we don't
189 * have to both quote and escape quote so that the quotes make it to
190 * us).
191 *
192 * Returns 0 on success, and -1 on failure.
193 */
194int blkid_parse_tag_string(const char *token, char **ret_type, char **ret_val)
195{
196 char *name, *value, *cp;
197
198 DBG(DEBUG_TAG, printf("trying to parse '%s' as a tag\n", token));
199
200 if (!token || !(cp = strchr(token, '=')))
201 return -1;
202
203 name = blkid_strdup(token);
204 if (!name)
205 return -1;
206 value = name + (cp - token);
207 *value++ = '\0';
208 if (*value == '"' || *value == '\'') {
209 char c = *value++;
210 if (!(cp = strrchr(value, c)))
211 goto errout; /* missing closing quote */
212 *cp = '\0';
213 }
214 value = blkid_strdup(value);
215 if (!value)
216 goto errout;
217
218 *ret_type = name;
219 *ret_val = value;
220
221 return 0;
222
223errout:
224 free(name);
225 return -1;
226}
227
228/*
229 * Tag iteration routines for the public libblkid interface.
230 *
231 * These routines do not expose the list.h implementation, which are a
232 * contamination of the namespace, and which force us to reveal far, far
233 * too much of our internal implementation. I'm not convinced I want
234 * to keep list.h in the long term, anyway. It's fine for kernel
235 * programming, but performance is not the #1 priority for this
236 * library, and I really don't like the tradeoff of type-safety for
237 * performance for this application. [tytso:20030125.2007EST]
238 */
239
240/*
241 * This series of functions iterate over all tags in a device
242 */
243#define TAG_ITERATE_MAGIC 0x01a5284c
244
245struct blkid_struct_tag_iterate {
246 int magic;
247 blkid_dev dev;
248 struct list_head *p;
249};
250
251blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev)
252{
253 blkid_tag_iterate iter;
254
255 iter = xmalloc(sizeof(struct blkid_struct_tag_iterate));
256 iter->magic = TAG_ITERATE_MAGIC;
257 iter->dev = dev;
258 iter->p = dev->bid_tags.next;
259 return iter;
260}
261
262/*
263 * Return 0 on success, -1 on error
264 */
265extern int blkid_tag_next(blkid_tag_iterate iter,
266 const char **type, const char **value)
267{
268 blkid_tag tag;
269
270 *type = 0;
271 *value = 0;
272 if (!iter || iter->magic != TAG_ITERATE_MAGIC ||
273 iter->p == &iter->dev->bid_tags)
274 return -1;
275 tag = list_entry(iter->p, struct blkid_struct_tag, bit_tags);
276 *type = tag->bit_name;
277 *value = tag->bit_val;
278 iter->p = iter->p->next;
279 return 0;
280}
281
282void blkid_tag_iterate_end(blkid_tag_iterate iter)
283{
284 if (!iter || iter->magic != TAG_ITERATE_MAGIC)
285 return;
286 iter->magic = 0;
287 free(iter);
288}
289
290/*
291 * This function returns a device which matches a particular
292 * type/value pair. If there is more than one device that matches the
293 * search specification, it returns the one with the highest priority
294 * value. This allows us to give preference to EVMS or LVM devices.
295 *
296 * XXX there should also be an interface which uses an iterator so we
297 * can get all of the devices which match a type/value search parameter.
298 */
299extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
300 const char *type,
301 const char *value)
302{
303 blkid_tag head;
304 blkid_dev dev;
305 int pri;
306 struct list_head *p;
307
308 if (!cache || !type || !value)
309 return NULL;
310
311 blkid_read_cache(cache);
312
313 DBG(DEBUG_TAG, printf("looking for %s=%s in cache\n", type, value));
314
315try_again:
316 pri = -1;
317 dev = 0;
318 head = blkid_find_head_cache(cache, type);
319
320 if (head) {
321 list_for_each(p, &head->bit_names) {
322 blkid_tag tmp = list_entry(p, struct blkid_struct_tag,
323 bit_names);
324
325 if (!strcmp(tmp->bit_val, value) &&
326 tmp->bit_dev->bid_pri > pri) {
327 dev = tmp->bit_dev;
328 pri = dev->bid_pri;
329 }
330 }
331 }
332 if (dev && !(dev->bid_flags & BLKID_BID_FL_VERIFIED)) {
333 dev = blkid_verify(cache, dev);
334 if (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED))
335 goto try_again;
336 }
337
338 if (!dev && !(cache->bic_flags & BLKID_BIC_FL_PROBED)) {
339 if (blkid_probe_all(cache) < 0)
340 return NULL;
341 goto try_again;
342 }
343 return dev;
344}
345
346#ifdef TEST_PROGRAM
347#ifdef HAVE_GETOPT_H
348#include <getopt.h>
349#else
350extern char *optarg;
351extern int optind;
352#endif
353
354void usage(char *prog)
355{
356 fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask] device "
357 "[type value]\n",
358 prog);
359 fprintf(stderr, "\tList all tags for a device and exit\n");
360 exit(1);
361}
362
363int main(int argc, char **argv)
364{
365 blkid_tag_iterate iter;
366 blkid_cache cache = NULL;
367 blkid_dev dev;
368 int c, ret, found;
369 int flags = BLKID_DEV_FIND;
370 char *tmp;
371 char *file = NULL;
372 char *devname = NULL;
373 char *search_type = NULL;
374 char *search_value = NULL;
375 const char *type, *value;
376
377 while ((c = getopt (argc, argv, "m:f:")) != EOF)
378 switch (c) {
379 case 'f':
380 file = optarg;
381 break;
382 case 'm':
383 blkid_debug_mask = strtoul (optarg, &tmp, 0);
384 if (*tmp) {
385 fprintf(stderr, "Invalid debug mask: %s\n",
386 optarg);
387 exit(1);
388 }
389 break;
390 case '?':
391 usage(argv[0]);
392 }
393 if (argc > optind)
394 devname = argv[optind++];
395 if (argc > optind)
396 search_type = argv[optind++];
397 if (argc > optind)
398 search_value = argv[optind++];
399 if (!devname || (argc != optind))
400 usage(argv[0]);
401
402 if ((ret = blkid_get_cache(&cache, file)) != 0) {
403 fprintf(stderr, "%s: error creating cache (%d)\n",
404 argv[0], ret);
405 exit(1);
406 }
407
408 dev = blkid_get_dev(cache, devname, flags);
409 if (!dev) {
410 fprintf(stderr, "%s: cannot find device in blkid cache\n", devname);
411 exit(1);
412 }
413 if (search_type) {
414 found = blkid_dev_has_tag(dev, search_type, search_value);
415 printf("Device %s: (%s, %s) %s\n", blkid_dev_devname(dev),
416 search_type, search_value ? search_value : "NULL",
417 found ? "FOUND" : "NOT FOUND");
418 return !found;
419 }
420 printf("Device %s...\n", blkid_dev_devname(dev));
421
422 iter = blkid_tag_iterate_begin(dev);
423 while (blkid_tag_next(iter, &type, &value) == 0) {
424 printf("\tTag %s has value %s\n", type, value);
425 }
426 blkid_tag_iterate_end(iter);
427
428 blkid_put_cache(cache);
429 return 0;
430}
431#endif
diff --git a/e2fsprogs/old_e2fsprogs/chattr.c b/e2fsprogs/old_e2fsprogs/chattr.c
deleted file mode 100644
index ae39d9224..000000000
--- a/e2fsprogs/old_e2fsprogs/chattr.c
+++ /dev/null
@@ -1,220 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * chattr.c - Change file attributes on an ext2 file system
4 *
5 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
6 * Laboratoire MASI, Institut Blaise Pascal
7 * Universite Pierre et Marie Curie (Paris VI)
8 *
9 * This file can be redistributed under the terms of the GNU General
10 * Public License
11 */
12
13/*
14 * History:
15 * 93/10/30 - Creation
16 * 93/11/13 - Replace stat() calls by lstat() to avoid loops
17 * 94/02/27 - Integrated in Ted's distribution
18 * 98/12/29 - Ignore symlinks when working recursively (G M Sipe)
19 * 98/12/29 - Display version info only when -V specified (G M Sipe)
20 */
21
22#include <sys/types.h>
23#include <dirent.h>
24#include <fcntl.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <unistd.h>
28#include <string.h>
29#include <errno.h>
30#include <sys/param.h>
31#include <sys/stat.h>
32#include "ext2fs/ext2_fs.h"
33
34#ifdef __GNUC__
35# define EXT2FS_ATTR(x) __attribute__(x)
36#else
37# define EXT2FS_ATTR(x)
38#endif
39
40#include "e2fsbb.h"
41#include "e2p/e2p.h"
42
43#define OPT_ADD 1
44#define OPT_REM 2
45#define OPT_SET 4
46#define OPT_SET_VER 8
47static int flags;
48static int recursive;
49
50static unsigned long version;
51
52static unsigned long af;
53static unsigned long rf;
54static unsigned long sf;
55
56struct flags_char {
57 unsigned long flag;
58 char optchar;
59};
60
61static const struct flags_char flags_array[] = {
62 { EXT2_NOATIME_FL, 'A' },
63 { EXT2_SYNC_FL, 'S' },
64 { EXT2_DIRSYNC_FL, 'D' },
65 { EXT2_APPEND_FL, 'a' },
66 { EXT2_COMPR_FL, 'c' },
67 { EXT2_NODUMP_FL, 'd' },
68 { EXT2_IMMUTABLE_FL, 'i' },
69 { EXT3_JOURNAL_DATA_FL, 'j' },
70 { EXT2_SECRM_FL, 's' },
71 { EXT2_UNRM_FL, 'u' },
72 { EXT2_NOTAIL_FL, 't' },
73 { EXT2_TOPDIR_FL, 'T' },
74 { 0, 0 }
75};
76
77static unsigned long get_flag(char c)
78{
79 const struct flags_char *fp;
80 for (fp = flags_array; fp->flag; fp++)
81 if (fp->optchar == c)
82 return fp->flag;
83 bb_show_usage();
84 return 0;
85}
86
87static int decode_arg(char *arg)
88{
89 unsigned long *fl;
90 char opt = *arg++;
91
92 if (opt == '-') {
93 flags |= OPT_REM;
94 fl = &rf;
95 } else if (opt == '+') {
96 flags |= OPT_ADD;
97 fl = &af;
98 } else if (opt == '=') {
99 flags |= OPT_SET;
100 fl = &sf;
101 } else
102 return EOF;
103
104 for (; *arg; ++arg)
105 (*fl) |= get_flag(*arg);
106
107 return 1;
108}
109
110static int chattr_dir_proc(const char *, struct dirent *, void *);
111
112static void change_attributes(const char * name)
113{
114 unsigned long fsflags;
115 struct stat st;
116
117 if (lstat(name, &st) == -1) {
118 bb_error_msg("stat %s failed", name);
119 return;
120 }
121 if (S_ISLNK(st.st_mode) && recursive)
122 return;
123
124 /* Don't try to open device files, fifos etc. We probably
125 * ought to display an error if the file was explicitly given
126 * on the command line (whether or not recursive was
127 * requested). */
128 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode))
129 return;
130
131 if (flags & OPT_SET_VER)
132 if (fsetversion(name, version) == -1)
133 bb_error_msg("setting version on %s", name);
134
135 if (flags & OPT_SET) {
136 fsflags = sf;
137 } else {
138 if (fgetflags(name, &fsflags) == -1) {
139 bb_error_msg("reading flags on %s", name);
140 goto skip_setflags;
141 }
142 if (flags & OPT_REM)
143 fsflags &= ~rf;
144 if (flags & OPT_ADD)
145 fsflags |= af;
146 if (!S_ISDIR(st.st_mode))
147 fsflags &= ~EXT2_DIRSYNC_FL;
148 }
149 if (fsetflags(name, fsflags) == -1)
150 bb_error_msg("setting flags on %s", name);
151
152skip_setflags:
153 if (S_ISDIR(st.st_mode) && recursive)
154 iterate_on_dir(name, chattr_dir_proc, NULL);
155}
156
157static int chattr_dir_proc(const char *dir_name, struct dirent *de,
158 void *private EXT2FS_ATTR((unused)))
159{
160 /*if (strcmp(de->d_name, ".") || strcmp(de->d_name, "..")) {*/
161 if (de->d_name[0] == '.'
162 && (!de->d_name[1] || (de->d_name[1] == '.' && !de->d_name[2]))
163 ) {
164 char *path = concat_subpath_file(dir_name, de->d_name);
165 if (path) {
166 change_attributes(path);
167 free(path);
168 }
169 }
170 return 0;
171}
172
173int chattr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
174int chattr_main(int argc, char **argv)
175{
176 int i;
177 char *arg;
178
179 /* parse the args */
180 for (i = 1; i < argc; ++i) {
181 arg = argv[i];
182
183 /* take care of -R and -v <version> */
184 if (arg[0] == '-') {
185 if (arg[1] == 'R' && arg[2] == '\0') {
186 recursive = 1;
187 continue;
188 } else if (arg[1] == 'v' && arg[2] == '\0') {
189 char *tmp;
190 ++i;
191 if (i >= argc)
192 bb_show_usage();
193 version = strtol(argv[i], &tmp, 0);
194 if (*tmp)
195 bb_error_msg_and_die("bad version '%s'", arg);
196 flags |= OPT_SET_VER;
197 continue;
198 }
199 }
200
201 if (decode_arg(arg) == EOF)
202 break;
203 }
204
205 /* run sanity checks on all the arguments given us */
206 if (i >= argc)
207 bb_show_usage();
208 if ((flags & OPT_SET) && ((flags & OPT_ADD) || (flags & OPT_REM)))
209 bb_error_msg_and_die("= is incompatible with - and +");
210 if ((rf & af) != 0)
211 bb_error_msg_and_die("Can't set and unset a flag");
212 if (!flags)
213 bb_error_msg_and_die("Must use '-v', =, - or +");
214
215 /* now run chattr on all the files passed to us */
216 while (i < argc)
217 change_attributes(argv[i++]);
218
219 return EXIT_SUCCESS;
220}
diff --git a/e2fsprogs/old_e2fsprogs/e2fsbb.h b/e2fsprogs/old_e2fsprogs/e2fsbb.h
deleted file mode 100644
index d31c31955..000000000
--- a/e2fsprogs/old_e2fsprogs/e2fsbb.h
+++ /dev/null
@@ -1,43 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * File: e2fsbb.h
4 *
5 * Redefine a bunch of e2fsprogs stuff to use busybox routines
6 * instead. This makes upgrade between e2fsprogs versions easy.
7 */
8
9#ifndef E2FSBB_H
10#define E2FSBB_H 1
11
12#include "libbb.h"
13
14/* version we've last synced against */
15#define E2FSPROGS_VERSION "1.38"
16#define E2FSPROGS_DATE "30-Jun-2005"
17
18typedef long errcode_t;
19#define ERRCODE_RANGE 8
20#define error_message(code) strerror((int) (code & ((1<<ERRCODE_RANGE)-1)))
21
22/* header defines */
23#define ENABLE_HTREE 1
24#define HAVE_ERRNO_H 1
25#define HAVE_EXT2_IOCTLS 1
26#define HAVE_LINUX_FD_H 1
27#define HAVE_MNTENT_H 1
28#define HAVE_NETINET_IN_H 1
29#define HAVE_NET_IF_H 1
30#define HAVE_SYS_IOCTL_H 1
31#define HAVE_SYS_MOUNT_H 1
32#define HAVE_SYS_QUEUE_H 1
33#define HAVE_SYS_STAT_H 1
34#define HAVE_SYS_TYPES_H 1
35#define HAVE_UNISTD_H 1
36
37/* Endianness */
38#if BB_BIG_ENDIAN
39#define ENABLE_SWAPFS 1
40#define WORDS_BIGENDIAN 1
41#endif
42
43#endif
diff --git a/e2fsprogs/old_e2fsprogs/e2fsck.c b/e2fsprogs/old_e2fsprogs/e2fsck.c
deleted file mode 100644
index b816c62b0..000000000
--- a/e2fsprogs/old_e2fsprogs/e2fsck.c
+++ /dev/null
@@ -1,13516 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * e2fsck
4 *
5 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
6 * Copyright (C) 2006 Garrett Kajmowicz
7 *
8 * Dictionary Abstract Data Type
9 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
10 * Free Software License:
11 * All rights are reserved by the author, with the following exceptions:
12 * Permission is granted to freely reproduce and distribute this software,
13 * possibly in exchange for a fee, provided that this copyright notice appears
14 * intact. Permission is also granted to adapt this software to produce
15 * derivative works, as long as the modified versions carry this copyright
16 * notice and additional notices stating that the work has been modified.
17 * This source code may be translated into executable form and incorporated
18 * into proprietary software; there is no requirement for such software to
19 * contain a copyright notice related to this source.
20 *
21 * linux/fs/recovery and linux/fs/revoke
22 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
23 *
24 * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
25 *
26 * Journal recovery routines for the generic filesystem journaling code;
27 * part of the ext2fs journaling system.
28 *
29 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
30 */
31
32/*
33//usage:#define e2fsck_trivial_usage
34//usage: "[-panyrcdfvstDFSV] [-b superblock] [-B blocksize] "
35//usage: "[-I inode_buffer_blocks] [-P process_inode_size] "
36//usage: "[-l|-L bad_blocks_file] [-C fd] [-j external_journal] "
37//usage: "[-E extended-options] device"
38//usage:#define e2fsck_full_usage "\n\n"
39//usage: "Check ext2/ext3 file system\n"
40//usage: "\n -p Automatic repair (no questions)"
41//usage: "\n -n Make no changes to the filesystem"
42//usage: "\n -y Assume 'yes' to all questions"
43//usage: "\n -c Check for bad blocks and add them to the badblock list"
44//usage: "\n -f Force checking even if filesystem is marked clean"
45//usage: "\n -v Verbose"
46//usage: "\n -b superblock Use alternative superblock"
47//usage: "\n -B blocksize Force blocksize when looking for superblock"
48//usage: "\n -j journal Set location of the external journal"
49//usage: "\n -l file Add to badblocks list"
50//usage: "\n -L file Set badblocks list"
51*/
52
53#include "e2fsck.h" /*Put all of our defines here to clean things up*/
54
55#define _(x) x
56#define N_(x) x
57
58/*
59 * Procedure declarations
60 */
61
62static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
63
64/* pass1.c */
65static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
66
67/* pass2.c */
68static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
69 ext2_ino_t ino, char *buf);
70
71/* pass3.c */
72static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
73static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
74 int num, int gauranteed_size);
75static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
76static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
77 int adj);
78
79/* rehash.c */
80static void e2fsck_rehash_directories(e2fsck_t ctx);
81
82/* util.c */
83static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
84 const char *description);
85static int ask(e2fsck_t ctx, const char * string, int def);
86static void e2fsck_read_bitmaps(e2fsck_t ctx);
87static void preenhalt(e2fsck_t ctx);
88static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
89 struct ext2_inode * inode, const char * proc);
90static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
91 struct ext2_inode * inode, const char * proc);
92static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
93 const char *name, io_manager manager);
94
95/* unix.c */
96static void e2fsck_clear_progbar(e2fsck_t ctx);
97static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
98 float percent, unsigned int dpynum);
99
100
101/*
102 * problem.h --- e2fsck problem error codes
103 */
104
105typedef __u32 problem_t;
106
107struct problem_context {
108 errcode_t errcode;
109 ext2_ino_t ino, ino2, dir;
110 struct ext2_inode *inode;
111 struct ext2_dir_entry *dirent;
112 blk_t blk, blk2;
113 e2_blkcnt_t blkcount;
114 int group;
115 __u64 num;
116 const char *str;
117};
118
119
120/*
121 * Function declarations
122 */
123static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
124static int end_problem_latch(e2fsck_t ctx, int mask);
125static int set_latch_flags(int mask, int setflags, int clearflags);
126static void clear_problem_context(struct problem_context *ctx);
127
128/*
129 * Dictionary Abstract Data Type
130 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
131 *
132 * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
133 * kazlib_1_20
134 */
135
136#ifndef DICT_H
137#define DICT_H
138
139/*
140 * Blurb for inclusion into C++ translation units
141 */
142
143typedef unsigned long dictcount_t;
144#define DICTCOUNT_T_MAX ULONG_MAX
145
146/*
147 * The dictionary is implemented as a red-black tree
148 */
149
150typedef enum { dnode_red, dnode_black } dnode_color_t;
151
152typedef struct dnode_t {
153 struct dnode_t *dict_left;
154 struct dnode_t *dict_right;
155 struct dnode_t *dict_parent;
156 dnode_color_t dict_color;
157 const void *dict_key;
158 void *dict_data;
159} dnode_t;
160
161typedef int (*dict_comp_t)(const void *, const void *);
162typedef void (*dnode_free_t)(dnode_t *);
163
164typedef struct dict_t {
165 dnode_t dict_nilnode;
166 dictcount_t dict_nodecount;
167 dictcount_t dict_maxcount;
168 dict_comp_t dict_compare;
169 dnode_free_t dict_freenode;
170 int dict_dupes;
171} dict_t;
172
173typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
174
175typedef struct dict_load_t {
176 dict_t *dict_dictptr;
177 dnode_t dict_nilnode;
178} dict_load_t;
179
180#define dict_count(D) ((D)->dict_nodecount)
181#define dnode_get(N) ((N)->dict_data)
182#define dnode_getkey(N) ((N)->dict_key)
183
184#endif
185
186/*
187 * Compatibility header file for e2fsck which should be included
188 * instead of linux/jfs.h
189 *
190 * Copyright (C) 2000 Stephen C. Tweedie
191 */
192
193/*
194 * Pull in the definition of the e2fsck context structure
195 */
196
197struct buffer_head {
198 char b_data[8192];
199 e2fsck_t b_ctx;
200 io_channel b_io;
201 int b_size;
202 blk_t b_blocknr;
203 int b_dirty;
204 int b_uptodate;
205 int b_err;
206};
207
208
209#define K_DEV_FS 1
210#define K_DEV_JOURNAL 2
211
212#define lock_buffer(bh) do {} while (0)
213#define unlock_buffer(bh) do {} while (0)
214#define buffer_req(bh) 1
215#define do_readahead(journal, start) do {} while (0)
216
217static e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
218
219typedef struct {
220 int object_length;
221} kmem_cache_t;
222
223#define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
224
225/*
226 * We use the standard libext2fs portability tricks for inline
227 * functions.
228 */
229
230static kmem_cache_t * do_cache_create(int len)
231{
232 kmem_cache_t *new_cache;
233
234 new_cache = xmalloc(sizeof(*new_cache));
235 new_cache->object_length = len;
236 return new_cache;
237}
238
239static void do_cache_destroy(kmem_cache_t *cache)
240{
241 free(cache);
242}
243
244
245/*
246 * Dictionary Abstract Data Type
247 */
248
249
250/*
251 * These macros provide short convenient names for structure members,
252 * which are embellished with dict_ prefixes so that they are
253 * properly confined to the documented namespace. It's legal for a
254 * program which uses dict to define, for instance, a macro called ``parent''.
255 * Such a macro would interfere with the dnode_t struct definition.
256 * In general, highly portable and reusable C modules which expose their
257 * structures need to confine structure member names to well-defined spaces.
258 * The resulting identifiers aren't necessarily convenient to use, nor
259 * readable, in the implementation, however!
260 */
261
262#define left dict_left
263#define right dict_right
264#define parent dict_parent
265#define color dict_color
266#define key dict_key
267#define data dict_data
268
269#define nilnode dict_nilnode
270#define maxcount dict_maxcount
271#define compare dict_compare
272#define dupes dict_dupes
273
274#define dict_root(D) ((D)->nilnode.left)
275#define dict_nil(D) (&(D)->nilnode)
276
277static void dnode_free(dnode_t *node);
278
279/*
280 * Perform a ``left rotation'' adjustment on the tree. The given node P and
281 * its right child C are rearranged so that the P instead becomes the left
282 * child of C. The left subtree of C is inherited as the new right subtree
283 * for P. The ordering of the keys within the tree is thus preserved.
284 */
285
286static void rotate_left(dnode_t *upper)
287{
288 dnode_t *lower, *lowleft, *upparent;
289
290 lower = upper->right;
291 upper->right = lowleft = lower->left;
292 lowleft->parent = upper;
293
294 lower->parent = upparent = upper->parent;
295
296 /* don't need to check for root node here because root->parent is
297 the sentinel nil node, and root->parent->left points back to root */
298
299 if (upper == upparent->left) {
300 upparent->left = lower;
301 } else {
302 assert (upper == upparent->right);
303 upparent->right = lower;
304 }
305
306 lower->left = upper;
307 upper->parent = lower;
308}
309
310/*
311 * This operation is the ``mirror'' image of rotate_left. It is
312 * the same procedure, but with left and right interchanged.
313 */
314
315static void rotate_right(dnode_t *upper)
316{
317 dnode_t *lower, *lowright, *upparent;
318
319 lower = upper->left;
320 upper->left = lowright = lower->right;
321 lowright->parent = upper;
322
323 lower->parent = upparent = upper->parent;
324
325 if (upper == upparent->right) {
326 upparent->right = lower;
327 } else {
328 assert (upper == upparent->left);
329 upparent->left = lower;
330 }
331
332 lower->right = upper;
333 upper->parent = lower;
334}
335
336/*
337 * Do a postorder traversal of the tree rooted at the specified
338 * node and free everything under it. Used by dict_free().
339 */
340
341static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
342{
343 if (node == nil)
344 return;
345 free_nodes(dict, node->left, nil);
346 free_nodes(dict, node->right, nil);
347 dict->dict_freenode(node);
348}
349
350/*
351 * Verify that the tree contains the given node. This is done by
352 * traversing all of the nodes and comparing their pointers to the
353 * given pointer. Returns 1 if the node is found, otherwise
354 * returns zero. It is intended for debugging purposes.
355 */
356
357static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
358{
359 if (root != nil) {
360 return root == node
361 || verify_dict_has_node(nil, root->left, node)
362 || verify_dict_has_node(nil, root->right, node);
363 }
364 return 0;
365}
366
367
368/*
369 * Select a different set of node allocator routines.
370 */
371
372static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
373{
374 assert(dict_count(dict) == 0);
375 dict->dict_freenode = fr;
376}
377
378/*
379 * Free all the nodes in the dictionary by using the dictionary's
380 * installed free routine. The dictionary is emptied.
381 */
382
383static void dict_free_nodes(dict_t *dict)
384{
385 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
386 free_nodes(dict, root, nil);
387 dict->dict_nodecount = 0;
388 dict->nilnode.left = &dict->nilnode;
389 dict->nilnode.right = &dict->nilnode;
390}
391
392/*
393 * Initialize a user-supplied dictionary object.
394 */
395
396static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
397{
398 dict->compare = comp;
399 dict->dict_freenode = dnode_free;
400 dict->dict_nodecount = 0;
401 dict->maxcount = maxcount;
402 dict->nilnode.left = &dict->nilnode;
403 dict->nilnode.right = &dict->nilnode;
404 dict->nilnode.parent = &dict->nilnode;
405 dict->nilnode.color = dnode_black;
406 dict->dupes = 0;
407 return dict;
408}
409
410/*
411 * Locate a node in the dictionary having the given key.
412 * If the node is not found, a null a pointer is returned (rather than
413 * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
414 * located node is returned.
415 */
416
417static dnode_t *dict_lookup(dict_t *dict, const void *key)
418{
419 dnode_t *root = dict_root(dict);
420 dnode_t *nil = dict_nil(dict);
421 dnode_t *saved;
422 int result;
423
424 /* simple binary search adapted for trees that contain duplicate keys */
425
426 while (root != nil) {
427 result = dict->compare(key, root->key);
428 if (result < 0)
429 root = root->left;
430 else if (result > 0)
431 root = root->right;
432 else {
433 if (!dict->dupes) { /* no duplicates, return match */
434 return root;
435 } else { /* could be dupes, find leftmost one */
436 do {
437 saved = root;
438 root = root->left;
439 while (root != nil && dict->compare(key, root->key))
440 root = root->right;
441 } while (root != nil);
442 return saved;
443 }
444 }
445 }
446
447 return NULL;
448}
449
450/*
451 * Insert a node into the dictionary. The node should have been
452 * initialized with a data field. All other fields are ignored.
453 * The behavior is undefined if the user attempts to insert into
454 * a dictionary that is already full (for which the dict_isfull()
455 * function returns true).
456 */
457
458static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
459{
460 dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
461 dnode_t *parent = nil, *uncle, *grandpa;
462 int result = -1;
463
464 node->key = key;
465
466 /* basic binary tree insert */
467
468 while (where != nil) {
469 parent = where;
470 result = dict->compare(key, where->key);
471 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
472 assert(dict->dupes || result != 0);
473 if (result < 0)
474 where = where->left;
475 else
476 where = where->right;
477 }
478
479 assert(where == nil);
480
481 if (result < 0)
482 parent->left = node;
483 else
484 parent->right = node;
485
486 node->parent = parent;
487 node->left = nil;
488 node->right = nil;
489
490 dict->dict_nodecount++;
491
492 /* red black adjustments */
493
494 node->color = dnode_red;
495
496 while (parent->color == dnode_red) {
497 grandpa = parent->parent;
498 if (parent == grandpa->left) {
499 uncle = grandpa->right;
500 if (uncle->color == dnode_red) { /* red parent, red uncle */
501 parent->color = dnode_black;
502 uncle->color = dnode_black;
503 grandpa->color = dnode_red;
504 node = grandpa;
505 parent = grandpa->parent;
506 } else { /* red parent, black uncle */
507 if (node == parent->right) {
508 rotate_left(parent);
509 parent = node;
510 assert (grandpa == parent->parent);
511 /* rotation between parent and child preserves grandpa */
512 }
513 parent->color = dnode_black;
514 grandpa->color = dnode_red;
515 rotate_right(grandpa);
516 break;
517 }
518 } else { /* symmetric cases: parent == parent->parent->right */
519 uncle = grandpa->left;
520 if (uncle->color == dnode_red) {
521 parent->color = dnode_black;
522 uncle->color = dnode_black;
523 grandpa->color = dnode_red;
524 node = grandpa;
525 parent = grandpa->parent;
526 } else {
527 if (node == parent->left) {
528 rotate_right(parent);
529 parent = node;
530 assert (grandpa == parent->parent);
531 }
532 parent->color = dnode_black;
533 grandpa->color = dnode_red;
534 rotate_left(grandpa);
535 break;
536 }
537 }
538 }
539
540 dict_root(dict)->color = dnode_black;
541}
542
543/*
544 * Allocate a node using the dictionary's allocator routine, give it
545 * the data item.
546 */
547
548static dnode_t *dnode_init(dnode_t *dnode, void *data)
549{
550 dnode->data = data;
551 dnode->parent = NULL;
552 dnode->left = NULL;
553 dnode->right = NULL;
554 return dnode;
555}
556
557static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
558{
559 dnode_t *node = xmalloc(sizeof(dnode_t));
560
561 dnode_init(node, data);
562 dict_insert(dict, node, key);
563 return 1;
564}
565
566/*
567 * Return the node with the lowest (leftmost) key. If the dictionary is empty
568 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
569 */
570
571static dnode_t *dict_first(dict_t *dict)
572{
573 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
574
575 if (root != nil)
576 while ((left = root->left) != nil)
577 root = left;
578
579 return (root == nil) ? NULL : root;
580}
581
582/*
583 * Return the given node's successor node---the node which has the
584 * next key in the left to right ordering. If the node has
585 * no successor, a null pointer is returned rather than a pointer to
586 * the nil node.
587 */
588
589static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
590{
591 dnode_t *nil = dict_nil(dict), *parent, *left;
592
593 if (curr->right != nil) {
594 curr = curr->right;
595 while ((left = curr->left) != nil)
596 curr = left;
597 return curr;
598 }
599
600 parent = curr->parent;
601
602 while (parent != nil && curr == parent->right) {
603 curr = parent;
604 parent = curr->parent;
605 }
606
607 return (parent == nil) ? NULL : parent;
608}
609
610
611static void dnode_free(dnode_t *node)
612{
613 free(node);
614}
615
616
617#undef left
618#undef right
619#undef parent
620#undef color
621#undef key
622#undef data
623
624#undef nilnode
625#undef maxcount
626#undef compare
627#undef dupes
628
629
630/*
631 * dirinfo.c --- maintains the directory information table for e2fsck.
632 */
633
634/*
635 * This subroutine is called during pass1 to create a directory info
636 * entry. During pass1, the passed-in parent is 0; it will get filled
637 * in during pass2.
638 */
639static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
640{
641 struct dir_info *dir;
642 int i, j;
643 ext2_ino_t num_dirs;
644 errcode_t retval;
645 unsigned long old_size;
646
647 if (!ctx->dir_info) {
648 ctx->dir_info_count = 0;
649 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
650 if (retval)
651 num_dirs = 1024; /* Guess */
652 ctx->dir_info_size = num_dirs + 10;
653 ctx->dir_info = (struct dir_info *)
654 e2fsck_allocate_memory(ctx, ctx->dir_info_size
655 * sizeof (struct dir_info),
656 "directory map");
657 }
658
659 if (ctx->dir_info_count >= ctx->dir_info_size) {
660 old_size = ctx->dir_info_size * sizeof(struct dir_info);
661 ctx->dir_info_size += 10;
662 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
663 sizeof(struct dir_info),
664 &ctx->dir_info);
665 if (retval) {
666 ctx->dir_info_size -= 10;
667 return;
668 }
669 }
670
671 /*
672 * Normally, add_dir_info is called with each inode in
673 * sequential order; but once in a while (like when pass 3
674 * needs to recreate the root directory or lost+found
675 * directory) it is called out of order. In those cases, we
676 * need to move the dir_info entries down to make room, since
677 * the dir_info array needs to be sorted by inode number for
678 * get_dir_info()'s sake.
679 */
680 if (ctx->dir_info_count &&
681 ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
682 for (i = ctx->dir_info_count-1; i > 0; i--)
683 if (ctx->dir_info[i-1].ino < ino)
684 break;
685 dir = &ctx->dir_info[i];
686 if (dir->ino != ino)
687 for (j = ctx->dir_info_count++; j > i; j--)
688 ctx->dir_info[j] = ctx->dir_info[j-1];
689 } else
690 dir = &ctx->dir_info[ctx->dir_info_count++];
691
692 dir->ino = ino;
693 dir->dotdot = parent;
694 dir->parent = parent;
695}
696
697/*
698 * get_dir_info() --- given an inode number, try to find the directory
699 * information entry for it.
700 */
701static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
702{
703 int low, high, mid;
704
705 low = 0;
706 high = ctx->dir_info_count-1;
707 if (!ctx->dir_info)
708 return 0;
709 if (ino == ctx->dir_info[low].ino)
710 return &ctx->dir_info[low];
711 if (ino == ctx->dir_info[high].ino)
712 return &ctx->dir_info[high];
713
714 while (low < high) {
715 mid = (low+high)/2;
716 if (mid == low || mid == high)
717 break;
718 if (ino == ctx->dir_info[mid].ino)
719 return &ctx->dir_info[mid];
720 if (ino < ctx->dir_info[mid].ino)
721 high = mid;
722 else
723 low = mid;
724 }
725 return 0;
726}
727
728/*
729 * Free the dir_info structure when it isn't needed any more.
730 */
731static void e2fsck_free_dir_info(e2fsck_t ctx)
732{
733 ext2fs_free_mem(&ctx->dir_info);
734 ctx->dir_info_size = 0;
735 ctx->dir_info_count = 0;
736}
737
738/*
739 * Return the count of number of directories in the dir_info structure
740 */
741static int e2fsck_get_num_dirinfo(e2fsck_t ctx)
742{
743 return ctx->dir_info_count;
744}
745
746/*
747 * A simple interator function
748 */
749static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
750{
751 if (*control >= ctx->dir_info_count)
752 return 0;
753
754 return ctx->dir_info + (*control)++;
755}
756
757/*
758 * dirinfo.c --- maintains the directory information table for e2fsck.
759 *
760 */
761
762#ifdef ENABLE_HTREE
763
764/*
765 * This subroutine is called during pass1 to create a directory info
766 * entry. During pass1, the passed-in parent is 0; it will get filled
767 * in during pass2.
768 */
769static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
770{
771 struct dx_dir_info *dir;
772 int i, j;
773 errcode_t retval;
774 unsigned long old_size;
775
776 if (!ctx->dx_dir_info) {
777 ctx->dx_dir_info_count = 0;
778 ctx->dx_dir_info_size = 100; /* Guess */
779 ctx->dx_dir_info = (struct dx_dir_info *)
780 e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
781 * sizeof (struct dx_dir_info),
782 "directory map");
783 }
784
785 if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
786 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
787 ctx->dx_dir_info_size += 10;
788 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
789 sizeof(struct dx_dir_info),
790 &ctx->dx_dir_info);
791 if (retval) {
792 ctx->dx_dir_info_size -= 10;
793 return;
794 }
795 }
796
797 /*
798 * Normally, add_dx_dir_info is called with each inode in
799 * sequential order; but once in a while (like when pass 3
800 * needs to recreate the root directory or lost+found
801 * directory) it is called out of order. In those cases, we
802 * need to move the dx_dir_info entries down to make room, since
803 * the dx_dir_info array needs to be sorted by inode number for
804 * get_dx_dir_info()'s sake.
805 */
806 if (ctx->dx_dir_info_count &&
807 ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
808 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
809 if (ctx->dx_dir_info[i-1].ino < ino)
810 break;
811 dir = &ctx->dx_dir_info[i];
812 if (dir->ino != ino)
813 for (j = ctx->dx_dir_info_count++; j > i; j--)
814 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
815 } else
816 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
817
818 dir->ino = ino;
819 dir->numblocks = num_blocks;
820 dir->hashversion = 0;
821 dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
822 * sizeof (struct dx_dirblock_info),
823 "dx_block info array");
824}
825
826/*
827 * get_dx_dir_info() --- given an inode number, try to find the directory
828 * information entry for it.
829 */
830static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
831{
832 int low, high, mid;
833
834 low = 0;
835 high = ctx->dx_dir_info_count-1;
836 if (!ctx->dx_dir_info)
837 return 0;
838 if (ino == ctx->dx_dir_info[low].ino)
839 return &ctx->dx_dir_info[low];
840 if (ino == ctx->dx_dir_info[high].ino)
841 return &ctx->dx_dir_info[high];
842
843 while (low < high) {
844 mid = (low+high)/2;
845 if (mid == low || mid == high)
846 break;
847 if (ino == ctx->dx_dir_info[mid].ino)
848 return &ctx->dx_dir_info[mid];
849 if (ino < ctx->dx_dir_info[mid].ino)
850 high = mid;
851 else
852 low = mid;
853 }
854 return 0;
855}
856
857/*
858 * Free the dx_dir_info structure when it isn't needed any more.
859 */
860static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
861{
862 int i;
863 struct dx_dir_info *dir;
864
865 if (ctx->dx_dir_info) {
866 dir = ctx->dx_dir_info;
867 for (i=0; i < ctx->dx_dir_info_count; i++) {
868 ext2fs_free_mem(&dir->dx_block);
869 }
870 ext2fs_free_mem(&ctx->dx_dir_info);
871 }
872 ctx->dx_dir_info_size = 0;
873 ctx->dx_dir_info_count = 0;
874}
875
876/*
877 * A simple interator function
878 */
879static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
880{
881 if (*control >= ctx->dx_dir_info_count)
882 return 0;
883
884 return ctx->dx_dir_info + (*control)++;
885}
886
887#endif /* ENABLE_HTREE */
888/*
889 * e2fsck.c - a consistency checker for the new extended file system.
890 *
891 */
892
893/*
894 * This function allocates an e2fsck context
895 */
896static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
897{
898 e2fsck_t context;
899 errcode_t retval;
900
901 retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
902 if (retval)
903 return retval;
904
905 memset(context, 0, sizeof(struct e2fsck_struct));
906
907 context->process_inode_size = 256;
908 context->ext_attr_ver = 2;
909
910 *ret = context;
911 return 0;
912}
913
914struct ea_refcount_el {
915 blk_t ea_blk;
916 int ea_count;
917};
918
919struct ea_refcount {
920 blk_t count;
921 blk_t size;
922 blk_t cursor;
923 struct ea_refcount_el *list;
924};
925
926static void ea_refcount_free(ext2_refcount_t refcount)
927{
928 if (!refcount)
929 return;
930
931 ext2fs_free_mem(&refcount->list);
932 ext2fs_free_mem(&refcount);
933}
934
935/*
936 * This function resets an e2fsck context; it is called when e2fsck
937 * needs to be restarted.
938 */
939static errcode_t e2fsck_reset_context(e2fsck_t ctx)
940{
941 ctx->flags = 0;
942 ctx->lost_and_found = 0;
943 ctx->bad_lost_and_found = 0;
944 ext2fs_free_inode_bitmap(ctx->inode_used_map);
945 ctx->inode_used_map = 0;
946 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
947 ctx->inode_dir_map = 0;
948 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
949 ctx->inode_reg_map = 0;
950 ext2fs_free_block_bitmap(ctx->block_found_map);
951 ctx->block_found_map = 0;
952 ext2fs_free_icount(ctx->inode_link_info);
953 ctx->inode_link_info = 0;
954 if (ctx->journal_io) {
955 if (ctx->fs && ctx->fs->io != ctx->journal_io)
956 io_channel_close(ctx->journal_io);
957 ctx->journal_io = 0;
958 }
959 if (ctx->fs) {
960 ext2fs_free_dblist(ctx->fs->dblist);
961 ctx->fs->dblist = 0;
962 }
963 e2fsck_free_dir_info(ctx);
964#ifdef ENABLE_HTREE
965 e2fsck_free_dx_dir_info(ctx);
966#endif
967 ea_refcount_free(ctx->refcount);
968 ctx->refcount = 0;
969 ea_refcount_free(ctx->refcount_extra);
970 ctx->refcount_extra = 0;
971 ext2fs_free_block_bitmap(ctx->block_dup_map);
972 ctx->block_dup_map = 0;
973 ext2fs_free_block_bitmap(ctx->block_ea_map);
974 ctx->block_ea_map = 0;
975 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
976 ctx->inode_bad_map = 0;
977 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
978 ctx->inode_imagic_map = 0;
979 ext2fs_u32_list_free(ctx->dirs_to_hash);
980 ctx->dirs_to_hash = 0;
981
982 /*
983 * Clear the array of invalid meta-data flags
984 */
985 ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
986 ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
987 ext2fs_free_mem(&ctx->invalid_inode_table_flag);
988
989 /* Clear statistic counters */
990 ctx->fs_directory_count = 0;
991 ctx->fs_regular_count = 0;
992 ctx->fs_blockdev_count = 0;
993 ctx->fs_chardev_count = 0;
994 ctx->fs_links_count = 0;
995 ctx->fs_symlinks_count = 0;
996 ctx->fs_fast_symlinks_count = 0;
997 ctx->fs_fifo_count = 0;
998 ctx->fs_total_count = 0;
999 ctx->fs_sockets_count = 0;
1000 ctx->fs_ind_count = 0;
1001 ctx->fs_dind_count = 0;
1002 ctx->fs_tind_count = 0;
1003 ctx->fs_fragmented = 0;
1004 ctx->large_files = 0;
1005
1006 /* Reset the superblock to the user's requested value */
1007 ctx->superblock = ctx->use_superblock;
1008
1009 return 0;
1010}
1011
1012static void e2fsck_free_context(e2fsck_t ctx)
1013{
1014 if (!ctx)
1015 return;
1016
1017 e2fsck_reset_context(ctx);
1018 if (ctx->blkid)
1019 blkid_put_cache(ctx->blkid);
1020
1021 ext2fs_free_mem(&ctx);
1022}
1023
1024/*
1025 * ea_refcount.c
1026 */
1027
1028/*
1029 * The strategy we use for keeping track of EA refcounts is as
1030 * follows. We keep a sorted array of first EA blocks and its
1031 * reference counts. Once the refcount has dropped to zero, it is
1032 * removed from the array to save memory space. Once the EA block is
1033 * checked, its bit is set in the block_ea_map bitmap.
1034 */
1035
1036
1037static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
1038{
1039 ext2_refcount_t refcount;
1040 errcode_t retval;
1041 size_t bytes;
1042
1043 retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
1044 if (retval)
1045 return retval;
1046 memset(refcount, 0, sizeof(struct ea_refcount));
1047
1048 if (!size)
1049 size = 500;
1050 refcount->size = size;
1051 bytes = (size_t) (size * sizeof(struct ea_refcount_el));
1052#ifdef DEBUG
1053 printf("Refcount allocated %d entries, %lu bytes.\n",
1054 refcount->size, bytes);
1055#endif
1056 retval = ext2fs_get_mem(bytes, &refcount->list);
1057 if (retval)
1058 goto errout;
1059 memset(refcount->list, 0, bytes);
1060
1061 refcount->count = 0;
1062 refcount->cursor = 0;
1063
1064 *ret = refcount;
1065 return 0;
1066
1067errout:
1068 ea_refcount_free(refcount);
1069 return retval;
1070}
1071
1072/*
1073 * collapse_refcount() --- go through the refcount array, and get rid
1074 * of any count == zero entries
1075 */
1076static void refcount_collapse(ext2_refcount_t refcount)
1077{
1078 unsigned int i, j;
1079 struct ea_refcount_el *list;
1080
1081 list = refcount->list;
1082 for (i = 0, j = 0; i < refcount->count; i++) {
1083 if (list[i].ea_count) {
1084 if (i != j)
1085 list[j] = list[i];
1086 j++;
1087 }
1088 }
1089#if defined(DEBUG) || defined(TEST_PROGRAM)
1090 printf("Refcount_collapse: size was %d, now %d\n",
1091 refcount->count, j);
1092#endif
1093 refcount->count = j;
1094}
1095
1096
1097/*
1098 * insert_refcount_el() --- Insert a new entry into the sorted list at a
1099 * specified position.
1100 */
1101static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
1102 blk_t blk, int pos)
1103{
1104 struct ea_refcount_el *el;
1105 errcode_t retval;
1106 blk_t new_size = 0;
1107 int num;
1108
1109 if (refcount->count >= refcount->size) {
1110 new_size = refcount->size + 100;
1111#ifdef DEBUG
1112 printf("Reallocating refcount %d entries...\n", new_size);
1113#endif
1114 retval = ext2fs_resize_mem((size_t) refcount->size *
1115 sizeof(struct ea_refcount_el),
1116 (size_t) new_size *
1117 sizeof(struct ea_refcount_el),
1118 &refcount->list);
1119 if (retval)
1120 return 0;
1121 refcount->size = new_size;
1122 }
1123 num = (int) refcount->count - pos;
1124 if (num < 0)
1125 return 0; /* should never happen */
1126 if (num) {
1127 memmove(&refcount->list[pos+1], &refcount->list[pos],
1128 sizeof(struct ea_refcount_el) * num);
1129 }
1130 refcount->count++;
1131 el = &refcount->list[pos];
1132 el->ea_count = 0;
1133 el->ea_blk = blk;
1134 return el;
1135}
1136
1137
1138/*
1139 * get_refcount_el() --- given an block number, try to find refcount
1140 * information in the sorted list. If the create flag is set,
1141 * and we can't find an entry, create one in the sorted list.
1142 */
1143static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
1144 blk_t blk, int create)
1145{
1146 float range;
1147 int low, high, mid;
1148 blk_t lowval, highval;
1149
1150 if (!refcount || !refcount->list)
1151 return 0;
1152retry:
1153 low = 0;
1154 high = (int) refcount->count-1;
1155 if (create && ((refcount->count == 0) ||
1156 (blk > refcount->list[high].ea_blk))) {
1157 if (refcount->count >= refcount->size)
1158 refcount_collapse(refcount);
1159
1160 return insert_refcount_el(refcount, blk,
1161 (unsigned) refcount->count);
1162 }
1163 if (refcount->count == 0)
1164 return 0;
1165
1166 if (refcount->cursor >= refcount->count)
1167 refcount->cursor = 0;
1168 if (blk == refcount->list[refcount->cursor].ea_blk)
1169 return &refcount->list[refcount->cursor++];
1170#ifdef DEBUG
1171 printf("Non-cursor get_refcount_el: %u\n", blk);
1172#endif
1173 while (low <= high) {
1174 if (low == high)
1175 mid = low;
1176 else {
1177 /* Interpolate for efficiency */
1178 lowval = refcount->list[low].ea_blk;
1179 highval = refcount->list[high].ea_blk;
1180
1181 if (blk < lowval)
1182 range = 0;
1183 else if (blk > highval)
1184 range = 1;
1185 else
1186 range = ((float) (blk - lowval)) /
1187 (highval - lowval);
1188 mid = low + ((int) (range * (high-low)));
1189 }
1190
1191 if (blk == refcount->list[mid].ea_blk) {
1192 refcount->cursor = mid+1;
1193 return &refcount->list[mid];
1194 }
1195 if (blk < refcount->list[mid].ea_blk)
1196 high = mid-1;
1197 else
1198 low = mid+1;
1199 }
1200 /*
1201 * If we need to create a new entry, it should be right at
1202 * low (where high will be left at low-1).
1203 */
1204 if (create) {
1205 if (refcount->count >= refcount->size) {
1206 refcount_collapse(refcount);
1207 if (refcount->count < refcount->size)
1208 goto retry;
1209 }
1210 return insert_refcount_el(refcount, blk, low);
1211 }
1212 return 0;
1213}
1214
1215static errcode_t
1216ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
1217{
1218 struct ea_refcount_el *el;
1219
1220 el = get_refcount_el(refcount, blk, 1);
1221 if (!el)
1222 return EXT2_ET_NO_MEMORY;
1223 el->ea_count++;
1224
1225 if (ret)
1226 *ret = el->ea_count;
1227 return 0;
1228}
1229
1230static errcode_t
1231ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
1232{
1233 struct ea_refcount_el *el;
1234
1235 el = get_refcount_el(refcount, blk, 0);
1236 if (!el || el->ea_count == 0)
1237 return EXT2_ET_INVALID_ARGUMENT;
1238
1239 el->ea_count--;
1240
1241 if (ret)
1242 *ret = el->ea_count;
1243 return 0;
1244}
1245
1246static errcode_t
1247ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
1248{
1249 struct ea_refcount_el *el;
1250
1251 /*
1252 * Get the refcount element
1253 */
1254 el = get_refcount_el(refcount, blk, count ? 1 : 0);
1255 if (!el)
1256 return count ? EXT2_ET_NO_MEMORY : 0;
1257 el->ea_count = count;
1258 return 0;
1259}
1260
1261static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
1262{
1263 refcount->cursor = 0;
1264}
1265
1266
1267static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
1268{
1269 struct ea_refcount_el *list;
1270
1271 while (1) {
1272 if (refcount->cursor >= refcount->count)
1273 return 0;
1274 list = refcount->list;
1275 if (list[refcount->cursor].ea_count) {
1276 if (ret)
1277 *ret = list[refcount->cursor].ea_count;
1278 return list[refcount->cursor++].ea_blk;
1279 }
1280 refcount->cursor++;
1281 }
1282}
1283
1284
1285/*
1286 * ehandler.c --- handle bad block errors which come up during the
1287 * course of an e2fsck session.
1288 */
1289
1290
1291static const char *operation;
1292
1293static errcode_t
1294e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
1295 void *data, size_t size FSCK_ATTR((unused)),
1296 int actual FSCK_ATTR((unused)), errcode_t error)
1297{
1298 int i;
1299 char *p;
1300 ext2_filsys fs = (ext2_filsys) channel->app_data;
1301 e2fsck_t ctx;
1302
1303 ctx = (e2fsck_t) fs->priv_data;
1304
1305 /*
1306 * If more than one block was read, try reading each block
1307 * separately. We could use the actual bytes read to figure
1308 * out where to start, but we don't bother.
1309 */
1310 if (count > 1) {
1311 p = (char *) data;
1312 for (i=0; i < count; i++, p += channel->block_size, block++) {
1313 error = io_channel_read_blk(channel, block,
1314 1, p);
1315 if (error)
1316 return error;
1317 }
1318 return 0;
1319 }
1320 if (operation)
1321 printf(_("Error reading block %lu (%s) while %s. "), block,
1322 error_message(error), operation);
1323 else
1324 printf(_("Error reading block %lu (%s). "), block,
1325 error_message(error));
1326 preenhalt(ctx);
1327 if (ask(ctx, _("Ignore error"), 1)) {
1328 if (ask(ctx, _("Force rewrite"), 1))
1329 io_channel_write_blk(channel, block, 1, data);
1330 return 0;
1331 }
1332
1333 return error;
1334}
1335
1336static errcode_t
1337e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
1338 const void *data, size_t size FSCK_ATTR((unused)),
1339 int actual FSCK_ATTR((unused)), errcode_t error)
1340{
1341 int i;
1342 const char *p;
1343 ext2_filsys fs = (ext2_filsys) channel->app_data;
1344 e2fsck_t ctx;
1345
1346 ctx = (e2fsck_t) fs->priv_data;
1347
1348 /*
1349 * If more than one block was written, try writing each block
1350 * separately. We could use the actual bytes read to figure
1351 * out where to start, but we don't bother.
1352 */
1353 if (count > 1) {
1354 p = (const char *) data;
1355 for (i=0; i < count; i++, p += channel->block_size, block++) {
1356 error = io_channel_write_blk(channel, block,
1357 1, p);
1358 if (error)
1359 return error;
1360 }
1361 return 0;
1362 }
1363
1364 if (operation)
1365 printf(_("Error writing block %lu (%s) while %s. "), block,
1366 error_message(error), operation);
1367 else
1368 printf(_("Error writing block %lu (%s). "), block,
1369 error_message(error));
1370 preenhalt(ctx);
1371 if (ask(ctx, _("Ignore error"), 1))
1372 return 0;
1373
1374 return error;
1375}
1376
1377static const char *ehandler_operation(const char *op)
1378{
1379 const char *ret = operation;
1380
1381 operation = op;
1382 return ret;
1383}
1384
1385static void ehandler_init(io_channel channel)
1386{
1387 channel->read_error = e2fsck_handle_read_error;
1388 channel->write_error = e2fsck_handle_write_error;
1389}
1390
1391/*
1392 * journal.c --- code for handling the "ext3" journal
1393 *
1394 * Copyright (C) 2000 Andreas Dilger
1395 * Copyright (C) 2000 Theodore Ts'o
1396 *
1397 * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
1398 * Copyright (C) 1999 Red Hat Software
1399 *
1400 * This file may be redistributed under the terms of the
1401 * GNU General Public License version 2 or at your discretion
1402 * any later version.
1403 */
1404
1405/*
1406 * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
1407 * This creates a larger static binary, and a smaller binary using
1408 * shared libraries. It's also probably slightly less CPU-efficient,
1409 * which is why it's not on by default. But, it's a good way of
1410 * testing the functions in inode_io.c and fileio.c.
1411 */
1412#undef USE_INODE_IO
1413
1414/* Kernel compatibility functions for handling the journal. These allow us
1415 * to use the recovery.c file virtually unchanged from the kernel, so we
1416 * don't have to do much to keep kernel and user recovery in sync.
1417 */
1418static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
1419{
1420#ifdef USE_INODE_IO
1421 *phys = block;
1422 return 0;
1423#else
1424 struct inode *inode = journal->j_inode;
1425 errcode_t retval;
1426 blk_t pblk;
1427
1428 if (!inode) {
1429 *phys = block;
1430 return 0;
1431 }
1432
1433 retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
1434 &inode->i_ext2, NULL, 0, block, &pblk);
1435 *phys = pblk;
1436 return retval;
1437#endif
1438}
1439
1440static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
1441{
1442 struct buffer_head *bh;
1443
1444 bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
1445 if (!bh)
1446 return NULL;
1447
1448 bh->b_ctx = kdev->k_ctx;
1449 if (kdev->k_dev == K_DEV_FS)
1450 bh->b_io = kdev->k_ctx->fs->io;
1451 else
1452 bh->b_io = kdev->k_ctx->journal_io;
1453 bh->b_size = blocksize;
1454 bh->b_blocknr = blocknr;
1455
1456 return bh;
1457}
1458
1459static void sync_blockdev(kdev_t kdev)
1460{
1461 io_channel io;
1462
1463 if (kdev->k_dev == K_DEV_FS)
1464 io = kdev->k_ctx->fs->io;
1465 else
1466 io = kdev->k_ctx->journal_io;
1467
1468 io_channel_flush(io);
1469}
1470
1471static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
1472{
1473 int retval;
1474 struct buffer_head *bh;
1475
1476 for (; nr > 0; --nr) {
1477 bh = *bhp++;
1478 if (rw == READ && !bh->b_uptodate) {
1479 retval = io_channel_read_blk(bh->b_io,
1480 bh->b_blocknr,
1481 1, bh->b_data);
1482 if (retval) {
1483 bb_error_msg("while reading block %lu",
1484 (unsigned long) bh->b_blocknr);
1485 bh->b_err = retval;
1486 continue;
1487 }
1488 bh->b_uptodate = 1;
1489 } else if (rw == WRITE && bh->b_dirty) {
1490 retval = io_channel_write_blk(bh->b_io,
1491 bh->b_blocknr,
1492 1, bh->b_data);
1493 if (retval) {
1494 bb_error_msg("while writing block %lu",
1495 (unsigned long) bh->b_blocknr);
1496 bh->b_err = retval;
1497 continue;
1498 }
1499 bh->b_dirty = 0;
1500 bh->b_uptodate = 1;
1501 }
1502 }
1503}
1504
1505static void mark_buffer_dirty(struct buffer_head *bh)
1506{
1507 bh->b_dirty = 1;
1508}
1509
1510static inline void mark_buffer_clean(struct buffer_head * bh)
1511{
1512 bh->b_dirty = 0;
1513}
1514
1515static void brelse(struct buffer_head *bh)
1516{
1517 if (bh->b_dirty)
1518 ll_rw_block(WRITE, 1, &bh);
1519 ext2fs_free_mem(&bh);
1520}
1521
1522static int buffer_uptodate(struct buffer_head *bh)
1523{
1524 return bh->b_uptodate;
1525}
1526
1527static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
1528{
1529 bh->b_uptodate = val;
1530}
1531
1532static void wait_on_buffer(struct buffer_head *bh)
1533{
1534 if (!bh->b_uptodate)
1535 ll_rw_block(READ, 1, &bh);
1536}
1537
1538
1539static void e2fsck_clear_recover(e2fsck_t ctx, int error)
1540{
1541 ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
1542
1543 /* if we had an error doing journal recovery, we need a full fsck */
1544 if (error)
1545 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
1546 ext2fs_mark_super_dirty(ctx->fs);
1547}
1548
1549static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
1550{
1551 struct ext2_super_block *sb = ctx->fs->super;
1552 struct ext2_super_block jsuper;
1553 struct problem_context pctx;
1554 struct buffer_head *bh;
1555 struct inode *j_inode = NULL;
1556 struct kdev_s *dev_fs = NULL, *dev_journal;
1557 const char *journal_name = NULL;
1558 journal_t *journal = NULL;
1559 errcode_t retval = 0;
1560 io_manager io_ptr = 0;
1561 unsigned long start = 0;
1562 blk_t blk;
1563 int ext_journal = 0;
1564 int tried_backup_jnl = 0;
1565 int i;
1566
1567 clear_problem_context(&pctx);
1568
1569 journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
1570 if (!journal) {
1571 return EXT2_ET_NO_MEMORY;
1572 }
1573
1574 dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
1575 if (!dev_fs) {
1576 retval = EXT2_ET_NO_MEMORY;
1577 goto errout;
1578 }
1579 dev_journal = dev_fs+1;
1580
1581 dev_fs->k_ctx = dev_journal->k_ctx = ctx;
1582 dev_fs->k_dev = K_DEV_FS;
1583 dev_journal->k_dev = K_DEV_JOURNAL;
1584
1585 journal->j_dev = dev_journal;
1586 journal->j_fs_dev = dev_fs;
1587 journal->j_inode = NULL;
1588 journal->j_blocksize = ctx->fs->blocksize;
1589
1590 if (uuid_is_null(sb->s_journal_uuid)) {
1591 if (!sb->s_journal_inum)
1592 return EXT2_ET_BAD_INODE_NUM;
1593 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
1594 "journal inode");
1595 if (!j_inode) {
1596 retval = EXT2_ET_NO_MEMORY;
1597 goto errout;
1598 }
1599
1600 j_inode->i_ctx = ctx;
1601 j_inode->i_ino = sb->s_journal_inum;
1602
1603 if ((retval = ext2fs_read_inode(ctx->fs,
1604 sb->s_journal_inum,
1605 &j_inode->i_ext2))) {
1606 try_backup_journal:
1607 if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
1608 tried_backup_jnl)
1609 goto errout;
1610 memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
1611 memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
1612 EXT2_N_BLOCKS*4);
1613 j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
1614 j_inode->i_ext2.i_links_count = 1;
1615 j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
1616 tried_backup_jnl++;
1617 }
1618 if (!j_inode->i_ext2.i_links_count ||
1619 !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
1620 retval = EXT2_ET_NO_JOURNAL;
1621 goto try_backup_journal;
1622 }
1623 if (j_inode->i_ext2.i_size / journal->j_blocksize <
1624 JFS_MIN_JOURNAL_BLOCKS) {
1625 retval = EXT2_ET_JOURNAL_TOO_SMALL;
1626 goto try_backup_journal;
1627 }
1628 for (i=0; i < EXT2_N_BLOCKS; i++) {
1629 blk = j_inode->i_ext2.i_block[i];
1630 if (!blk) {
1631 if (i < EXT2_NDIR_BLOCKS) {
1632 retval = EXT2_ET_JOURNAL_TOO_SMALL;
1633 goto try_backup_journal;
1634 }
1635 continue;
1636 }
1637 if (blk < sb->s_first_data_block ||
1638 blk >= sb->s_blocks_count) {
1639 retval = EXT2_ET_BAD_BLOCK_NUM;
1640 goto try_backup_journal;
1641 }
1642 }
1643 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
1644
1645#ifdef USE_INODE_IO
1646 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
1647 &j_inode->i_ext2,
1648 &journal_name);
1649 if (retval)
1650 goto errout;
1651
1652 io_ptr = inode_io_manager;
1653#else
1654 journal->j_inode = j_inode;
1655 ctx->journal_io = ctx->fs->io;
1656 if ((retval = journal_bmap(journal, 0, &start)) != 0)
1657 goto errout;
1658#endif
1659 } else {
1660 ext_journal = 1;
1661 if (!ctx->journal_name) {
1662 char uuid[37];
1663
1664 uuid_unparse(sb->s_journal_uuid, uuid);
1665 ctx->journal_name = blkid_get_devname(ctx->blkid,
1666 "UUID", uuid);
1667 if (!ctx->journal_name)
1668 ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
1669 }
1670 journal_name = ctx->journal_name;
1671
1672 if (!journal_name) {
1673 fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
1674 return EXT2_ET_LOAD_EXT_JOURNAL;
1675 }
1676
1677 io_ptr = unix_io_manager;
1678 }
1679
1680#ifndef USE_INODE_IO
1681 if (ext_journal)
1682#endif
1683 retval = io_ptr->open(journal_name, IO_FLAG_RW,
1684 &ctx->journal_io);
1685 if (retval)
1686 goto errout;
1687
1688 io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
1689
1690 if (ext_journal) {
1691 if (ctx->fs->blocksize == 1024)
1692 start = 1;
1693 bh = getblk(dev_journal, start, ctx->fs->blocksize);
1694 if (!bh) {
1695 retval = EXT2_ET_NO_MEMORY;
1696 goto errout;
1697 }
1698 ll_rw_block(READ, 1, &bh);
1699 if ((retval = bh->b_err) != 0)
1700 goto errout;
1701 memcpy(&jsuper, start ? bh->b_data : bh->b_data + 1024,
1702 sizeof(jsuper));
1703 brelse(bh);
1704#if BB_BIG_ENDIAN
1705 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
1706 ext2fs_swap_super(&jsuper);
1707#endif
1708 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
1709 !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
1710 fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
1711 retval = EXT2_ET_LOAD_EXT_JOURNAL;
1712 goto errout;
1713 }
1714 /* Make sure the journal UUID is correct */
1715 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
1716 sizeof(jsuper.s_uuid))) {
1717 fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
1718 retval = EXT2_ET_LOAD_EXT_JOURNAL;
1719 goto errout;
1720 }
1721
1722 journal->j_maxlen = jsuper.s_blocks_count;
1723 start++;
1724 }
1725
1726 if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
1727 retval = EXT2_ET_NO_MEMORY;
1728 goto errout;
1729 }
1730
1731 journal->j_sb_buffer = bh;
1732 journal->j_superblock = (journal_superblock_t *)bh->b_data;
1733
1734#ifdef USE_INODE_IO
1735 ext2fs_free_mem(&j_inode);
1736#endif
1737
1738 *ret_journal = journal;
1739 return 0;
1740
1741errout:
1742 ext2fs_free_mem(&dev_fs);
1743 ext2fs_free_mem(&j_inode);
1744 ext2fs_free_mem(&journal);
1745 return retval;
1746}
1747
1748static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
1749 struct problem_context *pctx)
1750{
1751 struct ext2_super_block *sb = ctx->fs->super;
1752 int recover = ctx->fs->super->s_feature_incompat &
1753 EXT3_FEATURE_INCOMPAT_RECOVER;
1754 int has_journal = ctx->fs->super->s_feature_compat &
1755 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1756
1757 if (has_journal || sb->s_journal_inum) {
1758 /* The journal inode is bogus, remove and force full fsck */
1759 pctx->ino = sb->s_journal_inum;
1760 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
1761 if (has_journal && sb->s_journal_inum)
1762 printf("*** ext3 journal has been deleted - "
1763 "filesystem is now ext2 only ***\n\n");
1764 sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1765 sb->s_journal_inum = 0;
1766 ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
1767 e2fsck_clear_recover(ctx, 1);
1768 return 0;
1769 }
1770 return EXT2_ET_BAD_INODE_NUM;
1771 } else if (recover) {
1772 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
1773 e2fsck_clear_recover(ctx, 1);
1774 return 0;
1775 }
1776 return EXT2_ET_UNSUPP_FEATURE;
1777 }
1778 return 0;
1779}
1780
1781#define V1_SB_SIZE 0x0024
1782static void clear_v2_journal_fields(journal_t *journal)
1783{
1784 e2fsck_t ctx = journal->j_dev->k_ctx;
1785 struct problem_context pctx;
1786
1787 clear_problem_context(&pctx);
1788
1789 if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
1790 return;
1791
1792 memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
1793 ctx->fs->blocksize-V1_SB_SIZE);
1794 mark_buffer_dirty(journal->j_sb_buffer);
1795}
1796
1797
1798static errcode_t e2fsck_journal_load(journal_t *journal)
1799{
1800 e2fsck_t ctx = journal->j_dev->k_ctx;
1801 journal_superblock_t *jsb;
1802 struct buffer_head *jbh = journal->j_sb_buffer;
1803 struct problem_context pctx;
1804
1805 clear_problem_context(&pctx);
1806
1807 ll_rw_block(READ, 1, &jbh);
1808 if (jbh->b_err) {
1809 bb_error_msg(_("reading journal superblock"));
1810 return jbh->b_err;
1811 }
1812
1813 jsb = journal->j_superblock;
1814 /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
1815 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
1816 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1817
1818 switch (ntohl(jsb->s_header.h_blocktype)) {
1819 case JFS_SUPERBLOCK_V1:
1820 journal->j_format_version = 1;
1821 if (jsb->s_feature_compat ||
1822 jsb->s_feature_incompat ||
1823 jsb->s_feature_ro_compat ||
1824 jsb->s_nr_users)
1825 clear_v2_journal_fields(journal);
1826 break;
1827
1828 case JFS_SUPERBLOCK_V2:
1829 journal->j_format_version = 2;
1830 if (ntohl(jsb->s_nr_users) > 1 &&
1831 uuid_is_null(ctx->fs->super->s_journal_uuid))
1832 clear_v2_journal_fields(journal);
1833 if (ntohl(jsb->s_nr_users) > 1) {
1834 fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
1835 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1836 }
1837 break;
1838
1839 /*
1840 * These should never appear in a journal super block, so if
1841 * they do, the journal is badly corrupted.
1842 */
1843 case JFS_DESCRIPTOR_BLOCK:
1844 case JFS_COMMIT_BLOCK:
1845 case JFS_REVOKE_BLOCK:
1846 return EXT2_ET_CORRUPT_SUPERBLOCK;
1847
1848 /* If we don't understand the superblock major type, but there
1849 * is a magic number, then it is likely to be a new format we
1850 * just don't understand, so leave it alone. */
1851 default:
1852 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1853 }
1854
1855 if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
1856 return EXT2_ET_UNSUPP_FEATURE;
1857
1858 if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
1859 return EXT2_ET_RO_UNSUPP_FEATURE;
1860
1861 /* We have now checked whether we know enough about the journal
1862 * format to be able to proceed safely, so any other checks that
1863 * fail we should attempt to recover from. */
1864 if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
1865 bb_error_msg(_("%s: no valid journal superblock found"),
1866 ctx->device_name);
1867 return EXT2_ET_CORRUPT_SUPERBLOCK;
1868 }
1869
1870 if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
1871 journal->j_maxlen = ntohl(jsb->s_maxlen);
1872 else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
1873 bb_error_msg(_("%s: journal too short"),
1874 ctx->device_name);
1875 return EXT2_ET_CORRUPT_SUPERBLOCK;
1876 }
1877
1878 journal->j_tail_sequence = ntohl(jsb->s_sequence);
1879 journal->j_transaction_sequence = journal->j_tail_sequence;
1880 journal->j_tail = ntohl(jsb->s_start);
1881 journal->j_first = ntohl(jsb->s_first);
1882 journal->j_last = ntohl(jsb->s_maxlen);
1883
1884 return 0;
1885}
1886
1887static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
1888 journal_t *journal)
1889{
1890 char *p;
1891 union {
1892 uuid_t uuid;
1893 __u32 val[4];
1894 } u;
1895 __u32 new_seq = 0;
1896 int i;
1897
1898 /* Leave a valid existing V1 superblock signature alone.
1899 * Anything unrecognizable we overwrite with a new V2
1900 * signature. */
1901
1902 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
1903 jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
1904 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
1905 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
1906 }
1907
1908 /* Zero out everything else beyond the superblock header */
1909
1910 p = ((char *) jsb) + sizeof(journal_header_t);
1911 memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
1912
1913 jsb->s_blocksize = htonl(ctx->fs->blocksize);
1914 jsb->s_maxlen = htonl(journal->j_maxlen);
1915 jsb->s_first = htonl(1);
1916
1917 /* Initialize the journal sequence number so that there is "no"
1918 * chance we will find old "valid" transactions in the journal.
1919 * This avoids the need to zero the whole journal (slow to do,
1920 * and risky when we are just recovering the filesystem).
1921 */
1922 uuid_generate(u.uuid);
1923 for (i = 0; i < 4; i ++)
1924 new_seq ^= u.val[i];
1925 jsb->s_sequence = htonl(new_seq);
1926
1927 mark_buffer_dirty(journal->j_sb_buffer);
1928 ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
1929}
1930
1931static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
1932 journal_t *journal,
1933 struct problem_context *pctx)
1934{
1935 struct ext2_super_block *sb = ctx->fs->super;
1936 int recover = ctx->fs->super->s_feature_incompat &
1937 EXT3_FEATURE_INCOMPAT_RECOVER;
1938
1939 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
1940 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
1941 e2fsck_journal_reset_super(ctx, journal->j_superblock,
1942 journal);
1943 journal->j_transaction_sequence = 1;
1944 e2fsck_clear_recover(ctx, recover);
1945 return 0;
1946 }
1947 return EXT2_ET_CORRUPT_SUPERBLOCK;
1948 } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
1949 return EXT2_ET_CORRUPT_SUPERBLOCK;
1950
1951 return 0;
1952}
1953
1954static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
1955 int reset, int drop)
1956{
1957 journal_superblock_t *jsb;
1958
1959 if (drop)
1960 mark_buffer_clean(journal->j_sb_buffer);
1961 else if (!(ctx->options & E2F_OPT_READONLY)) {
1962 jsb = journal->j_superblock;
1963 jsb->s_sequence = htonl(journal->j_transaction_sequence);
1964 if (reset)
1965 jsb->s_start = 0; /* this marks the journal as empty */
1966 mark_buffer_dirty(journal->j_sb_buffer);
1967 }
1968 brelse(journal->j_sb_buffer);
1969
1970 if (ctx->journal_io) {
1971 if (ctx->fs && ctx->fs->io != ctx->journal_io)
1972 io_channel_close(ctx->journal_io);
1973 ctx->journal_io = 0;
1974 }
1975
1976#ifndef USE_INODE_IO
1977 ext2fs_free_mem(&journal->j_inode);
1978#endif
1979 ext2fs_free_mem(&journal->j_fs_dev);
1980 ext2fs_free_mem(&journal);
1981}
1982
1983/*
1984 * This function makes sure that the superblock fields regarding the
1985 * journal are consistent.
1986 */
1987static int e2fsck_check_ext3_journal(e2fsck_t ctx)
1988{
1989 struct ext2_super_block *sb = ctx->fs->super;
1990 journal_t *journal;
1991 int recover = ctx->fs->super->s_feature_incompat &
1992 EXT3_FEATURE_INCOMPAT_RECOVER;
1993 struct problem_context pctx;
1994 problem_t problem;
1995 int reset = 0, force_fsck = 0;
1996 int retval;
1997
1998 /* If we don't have any journal features, don't do anything more */
1999 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
2000 !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
2001 uuid_is_null(sb->s_journal_uuid))
2002 return 0;
2003
2004 clear_problem_context(&pctx);
2005 pctx.num = sb->s_journal_inum;
2006
2007 retval = e2fsck_get_journal(ctx, &journal);
2008 if (retval) {
2009 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
2010 (retval == EXT2_ET_BAD_BLOCK_NUM) ||
2011 (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
2012 (retval == EXT2_ET_NO_JOURNAL))
2013 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
2014 return retval;
2015 }
2016
2017 retval = e2fsck_journal_load(journal);
2018 if (retval) {
2019 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
2020 ((retval == EXT2_ET_UNSUPP_FEATURE) &&
2021 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
2022 &pctx))) ||
2023 ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
2024 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
2025 &pctx))) ||
2026 ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
2027 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
2028 retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
2029 &pctx);
2030 e2fsck_journal_release(ctx, journal, 0, 1);
2031 return retval;
2032 }
2033
2034 /*
2035 * We want to make the flags consistent here. We will not leave with
2036 * needs_recovery set but has_journal clear. We can't get in a loop
2037 * with -y, -n, or -p, only if a user isn't making up their mind.
2038 */
2039no_has_journal:
2040 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
2041 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
2042 pctx.str = "inode";
2043 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
2044 if (recover &&
2045 !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
2046 goto no_has_journal;
2047 /*
2048 * Need a full fsck if we are releasing a
2049 * journal stored on a reserved inode.
2050 */
2051 force_fsck = recover ||
2052 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
2053 /* Clear all of the journal fields */
2054 sb->s_journal_inum = 0;
2055 sb->s_journal_dev = 0;
2056 memset(sb->s_journal_uuid, 0,
2057 sizeof(sb->s_journal_uuid));
2058 e2fsck_clear_recover(ctx, force_fsck);
2059 } else if (!(ctx->options & E2F_OPT_READONLY)) {
2060 sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2061 ext2fs_mark_super_dirty(ctx->fs);
2062 }
2063 }
2064
2065 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
2066 !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
2067 journal->j_superblock->s_start != 0) {
2068 /* Print status information */
2069 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
2070 if (ctx->superblock)
2071 problem = PR_0_JOURNAL_RUN_DEFAULT;
2072 else
2073 problem = PR_0_JOURNAL_RUN;
2074 if (fix_problem(ctx, problem, &pctx)) {
2075 ctx->options |= E2F_OPT_FORCE;
2076 sb->s_feature_incompat |=
2077 EXT3_FEATURE_INCOMPAT_RECOVER;
2078 ext2fs_mark_super_dirty(ctx->fs);
2079 } else if (fix_problem(ctx,
2080 PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
2081 reset = 1;
2082 sb->s_state &= ~EXT2_VALID_FS;
2083 ext2fs_mark_super_dirty(ctx->fs);
2084 }
2085 /*
2086 * If the user answers no to the above question, we
2087 * ignore the fact that journal apparently has data;
2088 * accidentally replaying over valid data would be far
2089 * worse than skipping a questionable recovery.
2090 *
2091 * XXX should we abort with a fatal error here? What
2092 * will the ext3 kernel code do if a filesystem with
2093 * !NEEDS_RECOVERY but with a non-zero
2094 * journal->j_superblock->s_start is mounted?
2095 */
2096 }
2097
2098 e2fsck_journal_release(ctx, journal, reset, 0);
2099 return retval;
2100}
2101
2102static errcode_t recover_ext3_journal(e2fsck_t ctx)
2103{
2104 journal_t *journal;
2105 int retval;
2106
2107 journal_init_revoke_caches();
2108 retval = e2fsck_get_journal(ctx, &journal);
2109 if (retval)
2110 return retval;
2111
2112 retval = e2fsck_journal_load(journal);
2113 if (retval)
2114 goto errout;
2115
2116 retval = journal_init_revoke(journal, 1024);
2117 if (retval)
2118 goto errout;
2119
2120 retval = -journal_recover(journal);
2121 if (retval)
2122 goto errout;
2123
2124 if (journal->j_superblock->s_errno) {
2125 ctx->fs->super->s_state |= EXT2_ERROR_FS;
2126 ext2fs_mark_super_dirty(ctx->fs);
2127 journal->j_superblock->s_errno = 0;
2128 mark_buffer_dirty(journal->j_sb_buffer);
2129 }
2130
2131errout:
2132 journal_destroy_revoke(journal);
2133 journal_destroy_revoke_caches();
2134 e2fsck_journal_release(ctx, journal, 1, 0);
2135 return retval;
2136}
2137
2138static int e2fsck_run_ext3_journal(e2fsck_t ctx)
2139{
2140 io_manager io_ptr = ctx->fs->io->manager;
2141 int blocksize = ctx->fs->blocksize;
2142 errcode_t retval, recover_retval;
2143
2144 printf(_("%s: recovering journal\n"), ctx->device_name);
2145 if (ctx->options & E2F_OPT_READONLY) {
2146 printf(_("%s: won't do journal recovery while read-only\n"),
2147 ctx->device_name);
2148 return EXT2_ET_FILE_RO;
2149 }
2150
2151 if (ctx->fs->flags & EXT2_FLAG_DIRTY)
2152 ext2fs_flush(ctx->fs); /* Force out any modifications */
2153
2154 recover_retval = recover_ext3_journal(ctx);
2155
2156 /*
2157 * Reload the filesystem context to get up-to-date data from disk
2158 * because journal recovery will change the filesystem under us.
2159 */
2160 ext2fs_close(ctx->fs);
2161 retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
2162 ctx->superblock, blocksize, io_ptr,
2163 &ctx->fs);
2164
2165 if (retval) {
2166 bb_error_msg(_("while trying to re-open %s"),
2167 ctx->device_name);
2168 bb_error_msg_and_die(0);
2169 }
2170 ctx->fs->priv_data = ctx;
2171
2172 /* Set the superblock flags */
2173 e2fsck_clear_recover(ctx, recover_retval);
2174 return recover_retval;
2175}
2176
2177/*
2178 * This function will move the journal inode from a visible file in
2179 * the filesystem directory hierarchy to the reserved inode if necessary.
2180 */
2181static const char *const journal_names[] = {
2182 ".journal", "journal", ".journal.dat", "journal.dat", 0 };
2183
2184static void e2fsck_move_ext3_journal(e2fsck_t ctx)
2185{
2186 struct ext2_super_block *sb = ctx->fs->super;
2187 struct problem_context pctx;
2188 struct ext2_inode inode;
2189 ext2_filsys fs = ctx->fs;
2190 ext2_ino_t ino;
2191 errcode_t retval;
2192 const char *const * cpp;
2193 int group, mount_flags;
2194
2195 clear_problem_context(&pctx);
2196
2197 /*
2198 * If the filesystem is opened read-only, or there is no
2199 * journal, then do nothing.
2200 */
2201 if ((ctx->options & E2F_OPT_READONLY) ||
2202 (sb->s_journal_inum == 0) ||
2203 !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
2204 return;
2205
2206 /*
2207 * Read in the journal inode
2208 */
2209 if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
2210 return;
2211
2212 /*
2213 * If it's necessary to backup the journal inode, do so.
2214 */
2215 if ((sb->s_jnl_backup_type == 0) ||
2216 ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
2217 memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
2218 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
2219 memcpy(sb->s_jnl_blocks, inode.i_block,
2220 EXT2_N_BLOCKS*4);
2221 sb->s_jnl_blocks[16] = inode.i_size;
2222 sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
2223 ext2fs_mark_super_dirty(fs);
2224 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2225 }
2226 }
2227
2228 /*
2229 * If the journal is already the hidden inode, then do nothing
2230 */
2231 if (sb->s_journal_inum == EXT2_JOURNAL_INO)
2232 return;
2233
2234 /*
2235 * The journal inode had better have only one link and not be readable.
2236 */
2237 if (inode.i_links_count != 1)
2238 return;
2239
2240 /*
2241 * If the filesystem is mounted, or we can't tell whether
2242 * or not it's mounted, do nothing.
2243 */
2244 retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
2245 if (retval || (mount_flags & EXT2_MF_MOUNTED))
2246 return;
2247
2248 /*
2249 * If we can't find the name of the journal inode, then do
2250 * nothing.
2251 */
2252 for (cpp = journal_names; *cpp; cpp++) {
2253 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
2254 strlen(*cpp), 0, &ino);
2255 if ((retval == 0) && (ino == sb->s_journal_inum))
2256 break;
2257 }
2258 if (*cpp == 0)
2259 return;
2260
2261 /* We need the inode bitmap to be loaded */
2262 retval = ext2fs_read_bitmaps(fs);
2263 if (retval)
2264 return;
2265
2266 pctx.str = *cpp;
2267 if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
2268 return;
2269
2270 /*
2271 * OK, we've done all the checks, let's actually move the
2272 * journal inode. Errors at this point mean we need to force
2273 * an ext2 filesystem check.
2274 */
2275 if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
2276 goto err_out;
2277 if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
2278 goto err_out;
2279 sb->s_journal_inum = EXT2_JOURNAL_INO;
2280 ext2fs_mark_super_dirty(fs);
2281 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2282 inode.i_links_count = 0;
2283 inode.i_dtime = time(NULL);
2284 if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
2285 goto err_out;
2286
2287 group = ext2fs_group_of_ino(fs, ino);
2288 ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
2289 ext2fs_mark_ib_dirty(fs);
2290 fs->group_desc[group].bg_free_inodes_count++;
2291 fs->super->s_free_inodes_count++;
2292 return;
2293
2294err_out:
2295 pctx.errcode = retval;
2296 fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
2297 fs->super->s_state &= ~EXT2_VALID_FS;
2298 ext2fs_mark_super_dirty(fs);
2299}
2300
2301/*
2302 * message.c --- print e2fsck messages (with compression)
2303 *
2304 * print_e2fsck_message() prints a message to the user, using
2305 * compression techniques and expansions of abbreviations.
2306 *
2307 * The following % expansions are supported:
2308 *
2309 * %b <blk> block number
2310 * %B <blkcount> integer
2311 * %c <blk2> block number
2312 * %Di <dirent>->ino inode number
2313 * %Dn <dirent>->name string
2314 * %Dr <dirent>->rec_len
2315 * %Dl <dirent>->name_len
2316 * %Dt <dirent>->filetype
2317 * %d <dir> inode number
2318 * %g <group> integer
2319 * %i <ino> inode number
2320 * %Is <inode> -> i_size
2321 * %IS <inode> -> i_extra_isize
2322 * %Ib <inode> -> i_blocks
2323 * %Il <inode> -> i_links_count
2324 * %Im <inode> -> i_mode
2325 * %IM <inode> -> i_mtime
2326 * %IF <inode> -> i_faddr
2327 * %If <inode> -> i_file_acl
2328 * %Id <inode> -> i_dir_acl
2329 * %Iu <inode> -> i_uid
2330 * %Ig <inode> -> i_gid
2331 * %j <ino2> inode number
2332 * %m <com_err error message>
2333 * %N <num>
2334 * %p ext2fs_get_pathname of directory <ino>
2335 * %P ext2fs_get_pathname of <dirent>->ino with <ino2> as
2336 * the containing directory. (If dirent is NULL
2337 * then return the pathname of directory <ino2>)
2338 * %q ext2fs_get_pathname of directory <dir>
2339 * %Q ext2fs_get_pathname of directory <ino> with <dir> as
2340 * the containing directory.
2341 * %s <str> miscellaneous string
2342 * %S backup superblock
2343 * %X <num> hexadecimal format
2344 *
2345 * The following '@' expansions are supported:
2346 *
2347 * @a extended attribute
2348 * @A error allocating
2349 * @b block
2350 * @B bitmap
2351 * @c compress
2352 * @C conflicts with some other fs block
2353 * @D deleted
2354 * @d directory
2355 * @e entry
2356 * @E Entry '%Dn' in %p (%i)
2357 * @f filesystem
2358 * @F for @i %i (%Q) is
2359 * @g group
2360 * @h HTREE directory inode
2361 * @i inode
2362 * @I illegal
2363 * @j journal
2364 * @l lost+found
2365 * @L is a link
2366 * @m multiply-claimed
2367 * @n invalid
2368 * @o orphaned
2369 * @p problem in
2370 * @r root inode
2371 * @s should be
2372 * @S superblock
2373 * @u unattached
2374 * @v device
2375 * @z zero-length
2376 */
2377
2378
2379/*
2380 * This structure defines the abbreviations used by the text strings
2381 * below. The first character in the string is the index letter. An
2382 * abbreviation of the form '@<i>' is expanded by looking up the index
2383 * letter <i> in the table below.
2384 */
2385static const char *const abbrevs[] = {
2386 N_("aextended attribute"),
2387 N_("Aerror allocating"),
2388 N_("bblock"),
2389 N_("Bbitmap"),
2390 N_("ccompress"),
2391 N_("Cconflicts with some other fs @b"),
2392 N_("iinode"),
2393 N_("Iillegal"),
2394 N_("jjournal"),
2395 N_("Ddeleted"),
2396 N_("ddirectory"),
2397 N_("eentry"),
2398 N_("E@e '%Dn' in %p (%i)"),
2399 N_("ffilesystem"),
2400 N_("Ffor @i %i (%Q) is"),
2401 N_("ggroup"),
2402 N_("hHTREE @d @i"),
2403 N_("llost+found"),
2404 N_("Lis a link"),
2405 N_("mmultiply-claimed"),
2406 N_("ninvalid"),
2407 N_("oorphaned"),
2408 N_("pproblem in"),
2409 N_("rroot @i"),
2410 N_("sshould be"),
2411 N_("Ssuper@b"),
2412 N_("uunattached"),
2413 N_("vdevice"),
2414 N_("zzero-length"),
2415 "@@",
2416 0
2417 };
2418
2419/*
2420 * Give more user friendly names to the "special" inodes.
2421 */
2422#define num_special_inodes 11
2423static const char *const special_inode_name[] =
2424{
2425 N_("<The NULL inode>"), /* 0 */
2426 N_("<The bad blocks inode>"), /* 1 */
2427 "/", /* 2 */
2428 N_("<The ACL index inode>"), /* 3 */
2429 N_("<The ACL data inode>"), /* 4 */
2430 N_("<The boot loader inode>"), /* 5 */
2431 N_("<The undelete directory inode>"), /* 6 */
2432 N_("<The group descriptor inode>"), /* 7 */
2433 N_("<The journal inode>"), /* 8 */
2434 N_("<Reserved inode 9>"), /* 9 */
2435 N_("<Reserved inode 10>"), /* 10 */
2436};
2437
2438/*
2439 * This function does "safe" printing. It will convert non-printable
2440 * ASCII characters using '^' and M- notation.
2441 */
2442static void safe_print(const char *cp, int len)
2443{
2444 unsigned char ch;
2445
2446 if (len < 0)
2447 len = strlen(cp);
2448
2449 while (len--) {
2450 ch = *cp++;
2451 if (ch > 128) {
2452 fputs("M-", stdout);
2453 ch -= 128;
2454 }
2455 if ((ch < 32) || (ch == 0x7f)) {
2456 bb_putchar('^');
2457 ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
2458 }
2459 bb_putchar(ch);
2460 }
2461}
2462
2463
2464/*
2465 * This function prints a pathname, using the ext2fs_get_pathname
2466 * function
2467 */
2468static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
2469{
2470 errcode_t retval;
2471 char *path;
2472
2473 if (!dir && (ino < num_special_inodes)) {
2474 fputs(_(special_inode_name[ino]), stdout);
2475 return;
2476 }
2477
2478 retval = ext2fs_get_pathname(fs, dir, ino, &path);
2479 if (retval)
2480 fputs("???", stdout);
2481 else {
2482 safe_print(path, -1);
2483 ext2fs_free_mem(&path);
2484 }
2485}
2486
2487static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2488 struct problem_context *pctx, int first);
2489/*
2490 * This function handles the '@' expansion. We allow recursive
2491 * expansion; an @ expression can contain further '@' and '%'
2492 * expressions.
2493 */
2494static void expand_at_expression(e2fsck_t ctx, char ch,
2495 struct problem_context *pctx,
2496 int *first)
2497{
2498 const char *const *cpp;
2499 const char *str;
2500
2501 /* Search for the abbreviation */
2502 for (cpp = abbrevs; *cpp; cpp++) {
2503 if (ch == *cpp[0])
2504 break;
2505 }
2506 if (*cpp) {
2507 str = _(*cpp) + 1;
2508 if (*first && islower(*str)) {
2509 *first = 0;
2510 bb_putchar(toupper(*str++));
2511 }
2512 print_e2fsck_message(ctx, str, pctx, *first);
2513 } else
2514 printf("@%c", ch);
2515}
2516
2517/*
2518 * This function expands '%IX' expressions
2519 */
2520static void expand_inode_expression(char ch,
2521 struct problem_context *ctx)
2522{
2523 struct ext2_inode *inode;
2524 struct ext2_inode_large *large_inode;
2525 char * time_str;
2526 time_t t;
2527 int do_gmt = -1;
2528
2529 if (!ctx || !ctx->inode)
2530 goto no_inode;
2531
2532 inode = ctx->inode;
2533 large_inode = (struct ext2_inode_large *) inode;
2534
2535 switch (ch) {
2536 case 's':
2537 if (LINUX_S_ISDIR(inode->i_mode))
2538 printf("%u", inode->i_size);
2539 else {
2540 printf("%"PRIu64, (inode->i_size |
2541 ((uint64_t) inode->i_size_high << 32)));
2542 }
2543 break;
2544 case 'S':
2545 printf("%u", large_inode->i_extra_isize);
2546 break;
2547 case 'b':
2548 printf("%u", inode->i_blocks);
2549 break;
2550 case 'l':
2551 printf("%d", inode->i_links_count);
2552 break;
2553 case 'm':
2554 printf("0%o", inode->i_mode);
2555 break;
2556 case 'M':
2557 /* The diet libc doesn't respect the TZ environemnt variable */
2558 if (do_gmt == -1) {
2559 time_str = getenv("TZ");
2560 if (!time_str)
2561 time_str = "";
2562 do_gmt = !strcmp(time_str, "GMT");
2563 }
2564 t = inode->i_mtime;
2565 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
2566 printf("%.24s", time_str);
2567 break;
2568 case 'F':
2569 printf("%u", inode->i_faddr);
2570 break;
2571 case 'f':
2572 printf("%u", inode->i_file_acl);
2573 break;
2574 case 'd':
2575 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
2576 inode->i_dir_acl : 0));
2577 break;
2578 case 'u':
2579 printf("%d", (inode->i_uid |
2580 (inode->osd2.linux2.l_i_uid_high << 16)));
2581 break;
2582 case 'g':
2583 printf("%d", (inode->i_gid |
2584 (inode->osd2.linux2.l_i_gid_high << 16)));
2585 break;
2586 default:
2587 no_inode:
2588 printf("%%I%c", ch);
2589 break;
2590 }
2591}
2592
2593/*
2594 * This function expands '%dX' expressions
2595 */
2596static void expand_dirent_expression(char ch,
2597 struct problem_context *ctx)
2598{
2599 struct ext2_dir_entry *dirent;
2600 int len;
2601
2602 if (!ctx || !ctx->dirent)
2603 goto no_dirent;
2604
2605 dirent = ctx->dirent;
2606
2607 switch (ch) {
2608 case 'i':
2609 printf("%u", dirent->inode);
2610 break;
2611 case 'n':
2612 len = dirent->name_len & 0xFF;
2613 if (len > EXT2_NAME_LEN)
2614 len = EXT2_NAME_LEN;
2615 if (len > dirent->rec_len)
2616 len = dirent->rec_len;
2617 safe_print(dirent->name, len);
2618 break;
2619 case 'r':
2620 printf("%u", dirent->rec_len);
2621 break;
2622 case 'l':
2623 printf("%u", dirent->name_len & 0xFF);
2624 break;
2625 case 't':
2626 printf("%u", dirent->name_len >> 8);
2627 break;
2628 default:
2629 no_dirent:
2630 printf("%%D%c", ch);
2631 break;
2632 }
2633}
2634
2635static void expand_percent_expression(ext2_filsys fs, char ch,
2636 struct problem_context *ctx)
2637{
2638 if (!ctx)
2639 goto no_context;
2640
2641 switch (ch) {
2642 case '%':
2643 bb_putchar('%');
2644 break;
2645 case 'b':
2646 printf("%u", ctx->blk);
2647 break;
2648 case 'B':
2649 printf("%"PRIi64, ctx->blkcount);
2650 break;
2651 case 'c':
2652 printf("%u", ctx->blk2);
2653 break;
2654 case 'd':
2655 printf("%u", ctx->dir);
2656 break;
2657 case 'g':
2658 printf("%d", ctx->group);
2659 break;
2660 case 'i':
2661 printf("%u", ctx->ino);
2662 break;
2663 case 'j':
2664 printf("%u", ctx->ino2);
2665 break;
2666 case 'm':
2667 fputs(error_message(ctx->errcode), stdout);
2668 break;
2669 case 'N':
2670 printf("%"PRIi64, ctx->num);
2671 break;
2672 case 'p':
2673 print_pathname(fs, ctx->ino, 0);
2674 break;
2675 case 'P':
2676 print_pathname(fs, ctx->ino2,
2677 ctx->dirent ? ctx->dirent->inode : 0);
2678 break;
2679 case 'q':
2680 print_pathname(fs, ctx->dir, 0);
2681 break;
2682 case 'Q':
2683 print_pathname(fs, ctx->dir, ctx->ino);
2684 break;
2685 case 'S':
2686 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
2687 break;
2688 case 's':
2689 fputs((ctx->str ? ctx->str : "NULL"), stdout);
2690 break;
2691 case 'X':
2692 printf("0x%"PRIi64, ctx->num);
2693 break;
2694 default:
2695 no_context:
2696 printf("%%%c", ch);
2697 break;
2698 }
2699}
2700
2701
2702static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2703 struct problem_context *pctx, int first)
2704{
2705 ext2_filsys fs = ctx->fs;
2706 const char * cp;
2707 int i;
2708
2709 e2fsck_clear_progbar(ctx);
2710 for (cp = msg; *cp; cp++) {
2711 if (cp[0] == '@') {
2712 cp++;
2713 expand_at_expression(ctx, *cp, pctx, &first);
2714 } else if (cp[0] == '%' && cp[1] == 'I') {
2715 cp += 2;
2716 expand_inode_expression(*cp, pctx);
2717 } else if (cp[0] == '%' && cp[1] == 'D') {
2718 cp += 2;
2719 expand_dirent_expression(*cp, pctx);
2720 } else if ((cp[0] == '%')) {
2721 cp++;
2722 expand_percent_expression(fs, *cp, pctx);
2723 } else {
2724 for (i=0; cp[i]; i++)
2725 if ((cp[i] == '@') || cp[i] == '%')
2726 break;
2727 printf("%.*s", i, cp);
2728 cp += i-1;
2729 }
2730 first = 0;
2731 }
2732}
2733
2734
2735/*
2736 * region.c --- code which manages allocations within a region.
2737 */
2738
2739struct region_el {
2740 region_addr_t start;
2741 region_addr_t end;
2742 struct region_el *next;
2743};
2744
2745struct region_struct {
2746 region_addr_t min;
2747 region_addr_t max;
2748 struct region_el *allocated;
2749};
2750
2751static region_t region_create(region_addr_t min, region_addr_t max)
2752{
2753 region_t region;
2754
2755 region = xzalloc(sizeof(struct region_struct));
2756 region->min = min;
2757 region->max = max;
2758 return region;
2759}
2760
2761static void region_free(region_t region)
2762{
2763 struct region_el *r, *next;
2764
2765 for (r = region->allocated; r; r = next) {
2766 next = r->next;
2767 free(r);
2768 }
2769 memset(region, 0, sizeof(struct region_struct));
2770 free(region);
2771}
2772
2773static int region_allocate(region_t region, region_addr_t start, int n)
2774{
2775 struct region_el *r, *new_region, *prev, *next;
2776 region_addr_t end;
2777
2778 end = start+n;
2779 if ((start < region->min) || (end > region->max))
2780 return -1;
2781 if (n == 0)
2782 return 1;
2783
2784 /*
2785 * Search through the linked list. If we find that it
2786 * conflicts witih something that's already allocated, return
2787 * 1; if we can find an existing region which we can grow, do
2788 * so. Otherwise, stop when we find the appropriate place
2789 * insert a new region element into the linked list.
2790 */
2791 for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
2792 if (((start >= r->start) && (start < r->end)) ||
2793 ((end > r->start) && (end <= r->end)) ||
2794 ((start <= r->start) && (end >= r->end)))
2795 return 1;
2796 if (end == r->start) {
2797 r->start = start;
2798 return 0;
2799 }
2800 if (start == r->end) {
2801 if ((next = r->next)) {
2802 if (end > next->start)
2803 return 1;
2804 if (end == next->start) {
2805 r->end = next->end;
2806 r->next = next->next;
2807 free(next);
2808 return 0;
2809 }
2810 }
2811 r->end = end;
2812 return 0;
2813 }
2814 if (start < r->start)
2815 break;
2816 }
2817 /*
2818 * Insert a new region element structure into the linked list
2819 */
2820 new_region = xmalloc(sizeof(struct region_el));
2821 new_region->start = start;
2822 new_region->end = start + n;
2823 new_region->next = r;
2824 if (prev)
2825 prev->next = new_region;
2826 else
2827 region->allocated = new_region;
2828 return 0;
2829}
2830
2831/*
2832 * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
2833 *
2834 * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
2835 * and applies the following tests to each inode:
2836 *
2837 * - The mode field of the inode must be legal.
2838 * - The size and block count fields of the inode are correct.
2839 * - A data block must not be used by another inode
2840 *
2841 * Pass 1 also gathers the collects the following information:
2842 *
2843 * - A bitmap of which inodes are in use. (inode_used_map)
2844 * - A bitmap of which inodes are directories. (inode_dir_map)
2845 * - A bitmap of which inodes are regular files. (inode_reg_map)
2846 * - A bitmap of which inodes have bad fields. (inode_bad_map)
2847 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
2848 * - A bitmap of which blocks are in use. (block_found_map)
2849 * - A bitmap of which blocks are in use by two inodes (block_dup_map)
2850 * - The data blocks of the directory inodes. (dir_map)
2851 *
2852 * Pass 1 is designed to stash away enough information so that the
2853 * other passes should not need to read in the inode information
2854 * during the normal course of a filesystem check. (Althogh if an
2855 * inconsistency is detected, other passes may need to read in an
2856 * inode to fix it.)
2857 *
2858 * Note that pass 1B will be invoked if there are any duplicate blocks
2859 * found.
2860 */
2861
2862
2863static int process_block(ext2_filsys fs, blk_t *blocknr,
2864 e2_blkcnt_t blockcnt, blk_t ref_blk,
2865 int ref_offset, void *priv_data);
2866static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
2867 e2_blkcnt_t blockcnt, blk_t ref_blk,
2868 int ref_offset, void *priv_data);
2869static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
2870 char *block_buf);
2871static void mark_table_blocks(e2fsck_t ctx);
2872static void alloc_imagic_map(e2fsck_t ctx);
2873static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
2874static void handle_fs_bad_blocks(e2fsck_t ctx);
2875static void process_inodes(e2fsck_t ctx, char *block_buf);
2876static int process_inode_cmp(const void *a, const void *b);
2877static errcode_t scan_callback(ext2_filsys fs,
2878 dgrp_t group, void * priv_data);
2879static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
2880 char *block_buf, int adjust_sign);
2881/* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
2882
2883static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
2884 struct ext2_inode * inode, int bufsize,
2885 const char *proc);
2886
2887struct process_block_struct_1 {
2888 ext2_ino_t ino;
2889 unsigned is_dir:1, is_reg:1, clear:1, suppress:1,
2890 fragmented:1, compressed:1, bbcheck:1;
2891 blk_t num_blocks;
2892 blk_t max_blocks;
2893 e2_blkcnt_t last_block;
2894 int num_illegal_blocks;
2895 blk_t previous_block;
2896 struct ext2_inode *inode;
2897 struct problem_context *pctx;
2898 ext2fs_block_bitmap fs_meta_blocks;
2899 e2fsck_t ctx;
2900};
2901
2902struct process_inode_block {
2903 ext2_ino_t ino;
2904 struct ext2_inode inode;
2905};
2906
2907struct scan_callback_struct {
2908 e2fsck_t ctx;
2909 char *block_buf;
2910};
2911
2912/*
2913 * For the inodes to process list.
2914 */
2915static struct process_inode_block *inodes_to_process;
2916static int process_inode_count;
2917
2918static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
2919 EXT2_MIN_BLOCK_LOG_SIZE + 1];
2920
2921/*
2922 * Free all memory allocated by pass1 in preparation for restarting
2923 * things.
2924 */
2925static void unwind_pass1(void)
2926{
2927 ext2fs_free_mem(&inodes_to_process);
2928}
2929
2930/*
2931 * Check to make sure a device inode is real. Returns 1 if the device
2932 * checks out, 0 if not.
2933 *
2934 * Note: this routine is now also used to check FIFO's and Sockets,
2935 * since they have the same requirement; the i_block fields should be
2936 * zero.
2937 */
2938static int
2939e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
2940{
2941 int i;
2942
2943 /*
2944 * If i_blocks is non-zero, or the index flag is set, then
2945 * this is a bogus device/fifo/socket
2946 */
2947 if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
2948 (inode->i_flags & EXT2_INDEX_FL))
2949 return 0;
2950
2951 /*
2952 * We should be able to do the test below all the time, but
2953 * because the kernel doesn't forcibly clear the device
2954 * inode's additional i_block fields, there are some rare
2955 * occasions when a legitimate device inode will have non-zero
2956 * additional i_block fields. So for now, we only complain
2957 * when the immutable flag is set, which should never happen
2958 * for devices. (And that's when the problem is caused, since
2959 * you can't set or clear immutable flags for devices.) Once
2960 * the kernel has been fixed we can change this...
2961 */
2962 if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
2963 for (i=4; i < EXT2_N_BLOCKS; i++)
2964 if (inode->i_block[i])
2965 return 0;
2966 }
2967 return 1;
2968}
2969
2970/*
2971 * Check to make sure a symlink inode is real. Returns 1 if the symlink
2972 * checks out, 0 if not.
2973 */
2974static int
2975e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
2976{
2977 unsigned int len;
2978 int i;
2979 blk_t blocks;
2980
2981 if ((inode->i_size_high || inode->i_size == 0) ||
2982 (inode->i_flags & EXT2_INDEX_FL))
2983 return 0;
2984
2985 blocks = ext2fs_inode_data_blocks(fs, inode);
2986 if (blocks) {
2987 if ((inode->i_size >= fs->blocksize) ||
2988 (blocks != fs->blocksize >> 9) ||
2989 (inode->i_block[0] < fs->super->s_first_data_block) ||
2990 (inode->i_block[0] >= fs->super->s_blocks_count))
2991 return 0;
2992
2993 for (i = 1; i < EXT2_N_BLOCKS; i++)
2994 if (inode->i_block[i])
2995 return 0;
2996
2997 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
2998 return 0;
2999
3000 len = strnlen(buf, fs->blocksize);
3001 if (len == fs->blocksize)
3002 return 0;
3003 } else {
3004 if (inode->i_size >= sizeof(inode->i_block))
3005 return 0;
3006
3007 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
3008 if (len == sizeof(inode->i_block))
3009 return 0;
3010 }
3011 if (len != inode->i_size)
3012 return 0;
3013 return 1;
3014}
3015
3016/*
3017 * If the immutable (or append-only) flag is set on the inode, offer
3018 * to clear it.
3019 */
3020#define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
3021static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
3022{
3023 if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
3024 return;
3025
3026 if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
3027 return;
3028
3029 pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
3030 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3031}
3032
3033/*
3034 * If device, fifo or socket, check size is zero -- if not offer to
3035 * clear it
3036 */
3037static void check_size(e2fsck_t ctx, struct problem_context *pctx)
3038{
3039 struct ext2_inode *inode = pctx->inode;
3040
3041 if ((inode->i_size == 0) && (inode->i_size_high == 0))
3042 return;
3043
3044 if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
3045 return;
3046
3047 inode->i_size = 0;
3048 inode->i_size_high = 0;
3049 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3050}
3051
3052static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
3053{
3054 struct ext2_super_block *sb = ctx->fs->super;
3055 struct ext2_inode_large *inode;
3056 struct ext2_ext_attr_entry *entry;
3057 char *start, *end;
3058 int storage_size, remain, offs;
3059 int problem = 0;
3060
3061 inode = (struct ext2_inode_large *) pctx->inode;
3062 storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
3063 inode->i_extra_isize;
3064 start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3065 inode->i_extra_isize + sizeof(__u32);
3066 end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
3067 entry = (struct ext2_ext_attr_entry *) start;
3068
3069 /* scan all entry's headers first */
3070
3071 /* take finish entry 0UL into account */
3072 remain = storage_size - sizeof(__u32);
3073 offs = end - start;
3074
3075 while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
3076
3077 /* header eats this space */
3078 remain -= sizeof(struct ext2_ext_attr_entry);
3079
3080 /* is attribute name valid? */
3081 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
3082 pctx->num = entry->e_name_len;
3083 problem = PR_1_ATTR_NAME_LEN;
3084 goto fix;
3085 }
3086
3087 /* attribute len eats this space */
3088 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
3089
3090 /* check value size */
3091 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
3092 pctx->num = entry->e_value_size;
3093 problem = PR_1_ATTR_VALUE_SIZE;
3094 goto fix;
3095 }
3096
3097 /* check value placement */
3098 if (entry->e_value_offs +
3099 EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
3100 printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
3101 pctx->num = entry->e_value_offs;
3102 problem = PR_1_ATTR_VALUE_OFFSET;
3103 goto fix;
3104 }
3105
3106 /* e_value_block must be 0 in inode's ea */
3107 if (entry->e_value_block != 0) {
3108 pctx->num = entry->e_value_block;
3109 problem = PR_1_ATTR_VALUE_BLOCK;
3110 goto fix;
3111 }
3112
3113 /* e_hash must be 0 in inode's ea */
3114 if (entry->e_hash != 0) {
3115 pctx->num = entry->e_hash;
3116 problem = PR_1_ATTR_HASH;
3117 goto fix;
3118 }
3119
3120 remain -= entry->e_value_size;
3121 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
3122
3123 entry = EXT2_EXT_ATTR_NEXT(entry);
3124 }
3125fix:
3126 /*
3127 * it seems like a corruption. it's very unlikely we could repair
3128 * EA(s) in automatic fashion -bzzz
3129 */
3130 if (problem == 0 || !fix_problem(ctx, problem, pctx))
3131 return;
3132
3133 /* simple remove all possible EA(s) */
3134 *((__u32 *)start) = 0UL;
3135 e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
3136 EXT2_INODE_SIZE(sb), "pass1");
3137}
3138
3139static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
3140{
3141 struct ext2_super_block *sb = ctx->fs->super;
3142 struct ext2_inode_large *inode;
3143 __u32 *eamagic;
3144 int min, max;
3145
3146 inode = (struct ext2_inode_large *) pctx->inode;
3147 if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
3148 /* this isn't large inode. so, nothing to check */
3149 return;
3150 }
3151
3152 /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
3153 min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
3154 max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
3155 /*
3156 * For now we will allow i_extra_isize to be 0, but really
3157 * implementations should never allow i_extra_isize to be 0
3158 */
3159 if (inode->i_extra_isize &&
3160 (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
3161 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
3162 return;
3163 inode->i_extra_isize = min;
3164 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
3165 EXT2_INODE_SIZE(sb), "pass1");
3166 return;
3167 }
3168
3169 eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3170 inode->i_extra_isize);
3171 if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
3172 /* it seems inode has an extended attribute(s) in body */
3173 check_ea_in_inode(ctx, pctx);
3174 }
3175}
3176
3177static void e2fsck_pass1(e2fsck_t ctx)
3178{
3179 int i;
3180 __u64 max_sizes;
3181 ext2_filsys fs = ctx->fs;
3182 ext2_ino_t ino;
3183 struct ext2_inode *inode;
3184 ext2_inode_scan scan;
3185 char *block_buf;
3186 unsigned char frag, fsize;
3187 struct problem_context pctx;
3188 struct scan_callback_struct scan_struct;
3189 struct ext2_super_block *sb = ctx->fs->super;
3190 int imagic_fs;
3191 int busted_fs_time = 0;
3192 int inode_size;
3193
3194 clear_problem_context(&pctx);
3195
3196 if (!(ctx->options & E2F_OPT_PREEN))
3197 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
3198
3199 if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
3200 !(ctx->options & E2F_OPT_NO)) {
3201 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
3202 ctx->dirs_to_hash = 0;
3203 }
3204
3205 /* Pass 1 */
3206
3207#define EXT2_BPP(bits) (1ULL << ((bits) - 2))
3208
3209 for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
3210 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
3211 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
3212 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
3213 max_sizes = (max_sizes * (1UL << i)) - 1;
3214 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
3215 }
3216#undef EXT2_BPP
3217
3218 imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
3219
3220 /*
3221 * Allocate bitmaps structures
3222 */
3223 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
3224 &ctx->inode_used_map);
3225 if (pctx.errcode) {
3226 pctx.num = 1;
3227 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3228 ctx->flags |= E2F_FLAG_ABORT;
3229 return;
3230 }
3231 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3232 _("directory inode map"), &ctx->inode_dir_map);
3233 if (pctx.errcode) {
3234 pctx.num = 2;
3235 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3236 ctx->flags |= E2F_FLAG_ABORT;
3237 return;
3238 }
3239 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3240 _("regular file inode map"), &ctx->inode_reg_map);
3241 if (pctx.errcode) {
3242 pctx.num = 6;
3243 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3244 ctx->flags |= E2F_FLAG_ABORT;
3245 return;
3246 }
3247 pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
3248 &ctx->block_found_map);
3249 if (pctx.errcode) {
3250 pctx.num = 1;
3251 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3252 ctx->flags |= E2F_FLAG_ABORT;
3253 return;
3254 }
3255 pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
3256 &ctx->inode_link_info);
3257 if (pctx.errcode) {
3258 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
3259 ctx->flags |= E2F_FLAG_ABORT;
3260 return;
3261 }
3262 inode_size = EXT2_INODE_SIZE(fs->super);
3263 inode = (struct ext2_inode *)
3264 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
3265
3266 inodes_to_process = (struct process_inode_block *)
3267 e2fsck_allocate_memory(ctx,
3268 (ctx->process_inode_size *
3269 sizeof(struct process_inode_block)),
3270 "array of inodes to process");
3271 process_inode_count = 0;
3272
3273 pctx.errcode = ext2fs_init_dblist(fs, 0);
3274 if (pctx.errcode) {
3275 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
3276 ctx->flags |= E2F_FLAG_ABORT;
3277 return;
3278 }
3279
3280 /*
3281 * If the last orphan field is set, clear it, since the pass1
3282 * processing will automatically find and clear the orphans.
3283 * In the future, we may want to try using the last_orphan
3284 * linked list ourselves, but for now, we clear it so that the
3285 * ext3 mount code won't get confused.
3286 */
3287 if (!(ctx->options & E2F_OPT_READONLY)) {
3288 if (fs->super->s_last_orphan) {
3289 fs->super->s_last_orphan = 0;
3290 ext2fs_mark_super_dirty(fs);
3291 }
3292 }
3293
3294 mark_table_blocks(ctx);
3295 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
3296 "block interate buffer");
3297 e2fsck_use_inode_shortcuts(ctx, 1);
3298 ehandler_operation(_("doing inode scan"));
3299 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
3300 &scan);
3301 if (pctx.errcode) {
3302 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3303 ctx->flags |= E2F_FLAG_ABORT;
3304 return;
3305 }
3306 ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
3307 ctx->stashed_inode = inode;
3308 scan_struct.ctx = ctx;
3309 scan_struct.block_buf = block_buf;
3310 ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
3311 if (ctx->progress)
3312 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
3313 return;
3314 if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
3315 (fs->super->s_mtime < fs->super->s_inodes_count))
3316 busted_fs_time = 1;
3317
3318 while (1) {
3319 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
3320 inode, inode_size);
3321 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3322 return;
3323 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
3324 continue;
3325 }
3326 if (pctx.errcode) {
3327 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3328 ctx->flags |= E2F_FLAG_ABORT;
3329 return;
3330 }
3331 if (!ino)
3332 break;
3333 pctx.ino = ino;
3334 pctx.inode = inode;
3335 ctx->stashed_ino = ino;
3336 if (inode->i_links_count) {
3337 pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
3338 ino, inode->i_links_count);
3339 if (pctx.errcode) {
3340 pctx.num = inode->i_links_count;
3341 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
3342 ctx->flags |= E2F_FLAG_ABORT;
3343 return;
3344 }
3345 }
3346 if (ino == EXT2_BAD_INO) {
3347 struct process_block_struct_1 pb;
3348
3349 pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
3350 &pb.fs_meta_blocks);
3351 if (pctx.errcode) {
3352 pctx.num = 4;
3353 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3354 ctx->flags |= E2F_FLAG_ABORT;
3355 return;
3356 }
3357 pb.ino = EXT2_BAD_INO;
3358 pb.num_blocks = pb.last_block = 0;
3359 pb.num_illegal_blocks = 0;
3360 pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
3361 pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
3362 pb.inode = inode;
3363 pb.pctx = &pctx;
3364 pb.ctx = ctx;
3365 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
3366 block_buf, process_bad_block, &pb);
3367 ext2fs_free_block_bitmap(pb.fs_meta_blocks);
3368 if (pctx.errcode) {
3369 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
3370 ctx->flags |= E2F_FLAG_ABORT;
3371 return;
3372 }
3373 if (pb.bbcheck)
3374 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
3375 ctx->flags |= E2F_FLAG_ABORT;
3376 return;
3377 }
3378 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3379 clear_problem_context(&pctx);
3380 continue;
3381 } else if (ino == EXT2_ROOT_INO) {
3382 /*
3383 * Make sure the root inode is a directory; if
3384 * not, offer to clear it. It will be
3385 * regnerated in pass #3.
3386 */
3387 if (!LINUX_S_ISDIR(inode->i_mode)) {
3388 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
3389 inode->i_dtime = time(NULL);
3390 inode->i_links_count = 0;
3391 ext2fs_icount_store(ctx->inode_link_info,
3392 ino, 0);
3393 e2fsck_write_inode(ctx, ino, inode,
3394 "pass1");
3395 }
3396 }
3397 /*
3398 * If dtime is set, offer to clear it. mke2fs
3399 * version 0.2b created filesystems with the
3400 * dtime field set for the root and lost+found
3401 * directories. We won't worry about
3402 * /lost+found, since that can be regenerated
3403 * easily. But we will fix the root directory
3404 * as a special case.
3405 */
3406 if (inode->i_dtime && inode->i_links_count) {
3407 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
3408 inode->i_dtime = 0;
3409 e2fsck_write_inode(ctx, ino, inode,
3410 "pass1");
3411 }
3412 }
3413 } else if (ino == EXT2_JOURNAL_INO) {
3414 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3415 if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
3416 if (!LINUX_S_ISREG(inode->i_mode) &&
3417 fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
3418 &pctx)) {
3419 inode->i_mode = LINUX_S_IFREG;
3420 e2fsck_write_inode(ctx, ino, inode,
3421 "pass1");
3422 }
3423 check_blocks(ctx, &pctx, block_buf);
3424 continue;
3425 }
3426 if ((inode->i_links_count || inode->i_blocks ||
3427 inode->i_block[0]) &&
3428 fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
3429 &pctx)) {
3430 memset(inode, 0, inode_size);
3431 ext2fs_icount_store(ctx->inode_link_info,
3432 ino, 0);
3433 e2fsck_write_inode_full(ctx, ino, inode,
3434 inode_size, "pass1");
3435 }
3436 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
3437 int problem = 0;
3438
3439 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3440 if (ino == EXT2_BOOT_LOADER_INO) {
3441 if (LINUX_S_ISDIR(inode->i_mode))
3442 problem = PR_1_RESERVED_BAD_MODE;
3443 } else if (ino == EXT2_RESIZE_INO) {
3444 if (inode->i_mode &&
3445 !LINUX_S_ISREG(inode->i_mode))
3446 problem = PR_1_RESERVED_BAD_MODE;
3447 } else {
3448 if (inode->i_mode != 0)
3449 problem = PR_1_RESERVED_BAD_MODE;
3450 }
3451 if (problem) {
3452 if (fix_problem(ctx, problem, &pctx)) {
3453 inode->i_mode = 0;
3454 e2fsck_write_inode(ctx, ino, inode,
3455 "pass1");
3456 }
3457 }
3458 check_blocks(ctx, &pctx, block_buf);
3459 continue;
3460 }
3461 /*
3462 * Check for inodes who might have been part of the
3463 * orphaned list linked list. They should have gotten
3464 * dealt with by now, unless the list had somehow been
3465 * corrupted.
3466 *
3467 * FIXME: In the future, inodes which are still in use
3468 * (and which are therefore) pending truncation should
3469 * be handled specially. Right now we just clear the
3470 * dtime field, and the normal e2fsck handling of
3471 * inodes where i_size and the inode blocks are
3472 * inconsistent is to fix i_size, instead of releasing
3473 * the extra blocks. This won't catch the inodes that
3474 * was at the end of the orphan list, but it's better
3475 * than nothing. The right answer is that there
3476 * shouldn't be any bugs in the orphan list handling. :-)
3477 */
3478 if (inode->i_dtime && !busted_fs_time &&
3479 inode->i_dtime < ctx->fs->super->s_inodes_count) {
3480 if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
3481 inode->i_dtime = inode->i_links_count ?
3482 0 : time(NULL);
3483 e2fsck_write_inode(ctx, ino, inode,
3484 "pass1");
3485 }
3486 }
3487
3488 /*
3489 * This code assumes that deleted inodes have
3490 * i_links_count set to 0.
3491 */
3492 if (!inode->i_links_count) {
3493 if (!inode->i_dtime && inode->i_mode) {
3494 if (fix_problem(ctx,
3495 PR_1_ZERO_DTIME, &pctx)) {
3496 inode->i_dtime = time(NULL);
3497 e2fsck_write_inode(ctx, ino, inode,
3498 "pass1");
3499 }
3500 }
3501 continue;
3502 }
3503 /*
3504 * n.b. 0.3c ext2fs code didn't clear i_links_count for
3505 * deleted files. Oops.
3506 *
3507 * Since all new ext2 implementations get this right,
3508 * we now assume that the case of non-zero
3509 * i_links_count and non-zero dtime means that we
3510 * should keep the file, not delete it.
3511 *
3512 */
3513 if (inode->i_dtime) {
3514 if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
3515 inode->i_dtime = 0;
3516 e2fsck_write_inode(ctx, ino, inode, "pass1");
3517 }
3518 }
3519
3520 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3521 switch (fs->super->s_creator_os) {
3522 case EXT2_OS_LINUX:
3523 frag = inode->osd2.linux2.l_i_frag;
3524 fsize = inode->osd2.linux2.l_i_fsize;
3525 break;
3526 case EXT2_OS_HURD:
3527 frag = inode->osd2.hurd2.h_i_frag;
3528 fsize = inode->osd2.hurd2.h_i_fsize;
3529 break;
3530 case EXT2_OS_MASIX:
3531 frag = inode->osd2.masix2.m_i_frag;
3532 fsize = inode->osd2.masix2.m_i_fsize;
3533 break;
3534 default:
3535 frag = fsize = 0;
3536 }
3537
3538 if (inode->i_faddr || frag || fsize ||
3539 (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
3540 mark_inode_bad(ctx, ino);
3541 if (inode->i_flags & EXT2_IMAGIC_FL) {
3542 if (imagic_fs) {
3543 if (!ctx->inode_imagic_map)
3544 alloc_imagic_map(ctx);
3545 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
3546 ino);
3547 } else {
3548 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
3549 inode->i_flags &= ~EXT2_IMAGIC_FL;
3550 e2fsck_write_inode(ctx, ino,
3551 inode, "pass1");
3552 }
3553 }
3554 }
3555
3556 check_inode_extra_space(ctx, &pctx);
3557
3558 if (LINUX_S_ISDIR(inode->i_mode)) {
3559 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
3560 e2fsck_add_dir_info(ctx, ino, 0);
3561 ctx->fs_directory_count++;
3562 } else if (LINUX_S_ISREG (inode->i_mode)) {
3563 ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
3564 ctx->fs_regular_count++;
3565 } else if (LINUX_S_ISCHR (inode->i_mode) &&
3566 e2fsck_pass1_check_device_inode(fs, inode)) {
3567 check_immutable(ctx, &pctx);
3568 check_size(ctx, &pctx);
3569 ctx->fs_chardev_count++;
3570 } else if (LINUX_S_ISBLK (inode->i_mode) &&
3571 e2fsck_pass1_check_device_inode(fs, inode)) {
3572 check_immutable(ctx, &pctx);
3573 check_size(ctx, &pctx);
3574 ctx->fs_blockdev_count++;
3575 } else if (LINUX_S_ISLNK (inode->i_mode) &&
3576 e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
3577 check_immutable(ctx, &pctx);
3578 ctx->fs_symlinks_count++;
3579 if (ext2fs_inode_data_blocks(fs, inode) == 0) {
3580 ctx->fs_fast_symlinks_count++;
3581 check_blocks(ctx, &pctx, block_buf);
3582 continue;
3583 }
3584 }
3585 else if (LINUX_S_ISFIFO (inode->i_mode) &&
3586 e2fsck_pass1_check_device_inode(fs, inode)) {
3587 check_immutable(ctx, &pctx);
3588 check_size(ctx, &pctx);
3589 ctx->fs_fifo_count++;
3590 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
3591 e2fsck_pass1_check_device_inode(fs, inode)) {
3592 check_immutable(ctx, &pctx);
3593 check_size(ctx, &pctx);
3594 ctx->fs_sockets_count++;
3595 } else
3596 mark_inode_bad(ctx, ino);
3597 if (inode->i_block[EXT2_IND_BLOCK])
3598 ctx->fs_ind_count++;
3599 if (inode->i_block[EXT2_DIND_BLOCK])
3600 ctx->fs_dind_count++;
3601 if (inode->i_block[EXT2_TIND_BLOCK])
3602 ctx->fs_tind_count++;
3603 if (inode->i_block[EXT2_IND_BLOCK] ||
3604 inode->i_block[EXT2_DIND_BLOCK] ||
3605 inode->i_block[EXT2_TIND_BLOCK] ||
3606 inode->i_file_acl) {
3607 inodes_to_process[process_inode_count].ino = ino;
3608 inodes_to_process[process_inode_count].inode = *inode;
3609 process_inode_count++;
3610 } else
3611 check_blocks(ctx, &pctx, block_buf);
3612
3613 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3614 return;
3615
3616 if (process_inode_count >= ctx->process_inode_size) {
3617 process_inodes(ctx, block_buf);
3618
3619 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3620 return;
3621 }
3622 }
3623 process_inodes(ctx, block_buf);
3624 ext2fs_close_inode_scan(scan);
3625 ehandler_operation(0);
3626
3627 /*
3628 * If any extended attribute blocks' reference counts need to
3629 * be adjusted, either up (ctx->refcount_extra), or down
3630 * (ctx->refcount), then fix them.
3631 */
3632 if (ctx->refcount) {
3633 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
3634 ea_refcount_free(ctx->refcount);
3635 ctx->refcount = 0;
3636 }
3637 if (ctx->refcount_extra) {
3638 adjust_extattr_refcount(ctx, ctx->refcount_extra,
3639 block_buf, +1);
3640 ea_refcount_free(ctx->refcount_extra);
3641 ctx->refcount_extra = 0;
3642 }
3643
3644 if (ctx->invalid_bitmaps)
3645 handle_fs_bad_blocks(ctx);
3646
3647 /* We don't need the block_ea_map any more */
3648 ext2fs_free_block_bitmap(ctx->block_ea_map);
3649 ctx->block_ea_map = 0;
3650
3651 if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
3652 ext2fs_block_bitmap save_bmap;
3653
3654 save_bmap = fs->block_map;
3655 fs->block_map = ctx->block_found_map;
3656 clear_problem_context(&pctx);
3657 pctx.errcode = ext2fs_create_resize_inode(fs);
3658 if (pctx.errcode) {
3659 fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
3660 /* Should never get here */
3661 ctx->flags |= E2F_FLAG_ABORT;
3662 return;
3663 }
3664 e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
3665 "recreate inode");
3666 inode->i_mtime = time(NULL);
3667 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
3668 "recreate inode");
3669 fs->block_map = save_bmap;
3670 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
3671 }
3672
3673 if (ctx->flags & E2F_FLAG_RESTART) {
3674 /*
3675 * Only the master copy of the superblock and block
3676 * group descriptors are going to be written during a
3677 * restart, so set the superblock to be used to be the
3678 * master superblock.
3679 */
3680 ctx->use_superblock = 0;
3681 unwind_pass1();
3682 goto endit;
3683 }
3684
3685 if (ctx->block_dup_map) {
3686 if (ctx->options & E2F_OPT_PREEN) {
3687 clear_problem_context(&pctx);
3688 fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
3689 }
3690 e2fsck_pass1_dupblocks(ctx, block_buf);
3691 }
3692 ext2fs_free_mem(&inodes_to_process);
3693endit:
3694 e2fsck_use_inode_shortcuts(ctx, 0);
3695
3696 ext2fs_free_mem(&block_buf);
3697 ext2fs_free_mem(&inode);
3698}
3699
3700/*
3701 * When the inode_scan routines call this callback at the end of the
3702 * glock group, call process_inodes.
3703 */
3704static errcode_t scan_callback(ext2_filsys fs,
3705 dgrp_t group, void * priv_data)
3706{
3707 struct scan_callback_struct *scan_struct;
3708 e2fsck_t ctx;
3709
3710 scan_struct = (struct scan_callback_struct *) priv_data;
3711 ctx = scan_struct->ctx;
3712
3713 process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
3714
3715 if (ctx->progress)
3716 if ((ctx->progress)(ctx, 1, group+1,
3717 ctx->fs->group_desc_count))
3718 return EXT2_ET_CANCEL_REQUESTED;
3719
3720 return 0;
3721}
3722
3723/*
3724 * Process the inodes in the "inodes to process" list.
3725 */
3726static void process_inodes(e2fsck_t ctx, char *block_buf)
3727{
3728 int i;
3729 struct ext2_inode *old_stashed_inode;
3730 ext2_ino_t old_stashed_ino;
3731 const char *old_operation;
3732 char buf[80];
3733 struct problem_context pctx;
3734
3735 /* begin process_inodes */
3736 if (process_inode_count == 0)
3737 return;
3738 old_operation = ehandler_operation(0);
3739 old_stashed_inode = ctx->stashed_inode;
3740 old_stashed_ino = ctx->stashed_ino;
3741 qsort(inodes_to_process, process_inode_count,
3742 sizeof(struct process_inode_block), process_inode_cmp);
3743 clear_problem_context(&pctx);
3744 for (i=0; i < process_inode_count; i++) {
3745 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
3746 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
3747 sprintf(buf, _("reading indirect blocks of inode %u"),
3748 pctx.ino);
3749 ehandler_operation(buf);
3750 check_blocks(ctx, &pctx, block_buf);
3751 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3752 break;
3753 }
3754 ctx->stashed_inode = old_stashed_inode;
3755 ctx->stashed_ino = old_stashed_ino;
3756 process_inode_count = 0;
3757 /* end process inodes */
3758
3759 ehandler_operation(old_operation);
3760}
3761
3762static int process_inode_cmp(const void *a, const void *b)
3763{
3764 const struct process_inode_block *ib_a =
3765 (const struct process_inode_block *) a;
3766 const struct process_inode_block *ib_b =
3767 (const struct process_inode_block *) b;
3768 int ret;
3769
3770 ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
3771 ib_b->inode.i_block[EXT2_IND_BLOCK]);
3772 if (ret == 0)
3773 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
3774 return ret;
3775}
3776
3777/*
3778 * Mark an inode as being bad in some what
3779 */
3780static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
3781{
3782 struct problem_context pctx;
3783
3784 if (!ctx->inode_bad_map) {
3785 clear_problem_context(&pctx);
3786
3787 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3788 _("bad inode map"), &ctx->inode_bad_map);
3789 if (pctx.errcode) {
3790 pctx.num = 3;
3791 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3792 /* Should never get here */
3793 ctx->flags |= E2F_FLAG_ABORT;
3794 return;
3795 }
3796 }
3797 ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
3798}
3799
3800
3801/*
3802 * This procedure will allocate the inode imagic table
3803 */
3804static void alloc_imagic_map(e2fsck_t ctx)
3805{
3806 struct problem_context pctx;
3807
3808 clear_problem_context(&pctx);
3809 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3810 _("imagic inode map"),
3811 &ctx->inode_imagic_map);
3812 if (pctx.errcode) {
3813 pctx.num = 5;
3814 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3815 /* Should never get here */
3816 ctx->flags |= E2F_FLAG_ABORT;
3817 return;
3818 }
3819}
3820
3821/*
3822 * Marks a block as in use, setting the dup_map if it's been set
3823 * already. Called by process_block and process_bad_block.
3824 *
3825 * WARNING: Assumes checks have already been done to make sure block
3826 * is valid. This is true in both process_block and process_bad_block.
3827 */
3828static void mark_block_used(e2fsck_t ctx, blk_t block)
3829{
3830 struct problem_context pctx;
3831
3832 clear_problem_context(&pctx);
3833
3834 if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
3835 if (!ctx->block_dup_map) {
3836 pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
3837 _("multiply claimed block map"),
3838 &ctx->block_dup_map);
3839 if (pctx.errcode) {
3840 pctx.num = 3;
3841 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
3842 &pctx);
3843 /* Should never get here */
3844 ctx->flags |= E2F_FLAG_ABORT;
3845 return;
3846 }
3847 }
3848 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
3849 } else {
3850 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
3851 }
3852}
3853
3854/*
3855 * Adjust the extended attribute block's reference counts at the end
3856 * of pass 1, either by subtracting out references for EA blocks that
3857 * are still referenced in ctx->refcount, or by adding references for
3858 * EA blocks that had extra references as accounted for in
3859 * ctx->refcount_extra.
3860 */
3861static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
3862 char *block_buf, int adjust_sign)
3863{
3864 struct ext2_ext_attr_header *header;
3865 struct problem_context pctx;
3866 ext2_filsys fs = ctx->fs;
3867 blk_t blk;
3868 __u32 should_be;
3869 int count;
3870
3871 clear_problem_context(&pctx);
3872
3873 ea_refcount_intr_begin(refcount);
3874 while (1) {
3875 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
3876 break;
3877 pctx.blk = blk;
3878 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3879 if (pctx.errcode) {
3880 fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
3881 return;
3882 }
3883 header = (struct ext2_ext_attr_header *) block_buf;
3884 pctx.blkcount = header->h_refcount;
3885 should_be = header->h_refcount + adjust_sign * count;
3886 pctx.num = should_be;
3887 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
3888 header->h_refcount = should_be;
3889 pctx.errcode = ext2fs_write_ext_attr(fs, blk,
3890 block_buf);
3891 if (pctx.errcode) {
3892 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
3893 continue;
3894 }
3895 }
3896 }
3897}
3898
3899/*
3900 * Handle processing the extended attribute blocks
3901 */
3902static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
3903 char *block_buf)
3904{
3905 ext2_filsys fs = ctx->fs;
3906 ext2_ino_t ino = pctx->ino;
3907 struct ext2_inode *inode = pctx->inode;
3908 blk_t blk;
3909 char * end;
3910 struct ext2_ext_attr_header *header;
3911 struct ext2_ext_attr_entry *entry;
3912 int count;
3913 region_t region;
3914
3915 blk = inode->i_file_acl;
3916 if (blk == 0)
3917 return 0;
3918
3919 /*
3920 * If the Extended attribute flag isn't set, then a non-zero
3921 * file acl means that the inode is corrupted.
3922 *
3923 * Or if the extended attribute block is an invalid block,
3924 * then the inode is also corrupted.
3925 */
3926 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
3927 (blk < fs->super->s_first_data_block) ||
3928 (blk >= fs->super->s_blocks_count)) {
3929 mark_inode_bad(ctx, ino);
3930 return 0;
3931 }
3932
3933 /* If ea bitmap hasn't been allocated, create it */
3934 if (!ctx->block_ea_map) {
3935 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
3936 _("ext attr block map"),
3937 &ctx->block_ea_map);
3938 if (pctx->errcode) {
3939 pctx->num = 2;
3940 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
3941 ctx->flags |= E2F_FLAG_ABORT;
3942 return 0;
3943 }
3944 }
3945
3946 /* Create the EA refcount structure if necessary */
3947 if (!ctx->refcount) {
3948 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
3949 if (pctx->errcode) {
3950 pctx->num = 1;
3951 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3952 ctx->flags |= E2F_FLAG_ABORT;
3953 return 0;
3954 }
3955 }
3956
3957 /* Have we seen this EA block before? */
3958 if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
3959 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
3960 return 1;
3961 /* Ooops, this EA was referenced more than it stated */
3962 if (!ctx->refcount_extra) {
3963 pctx->errcode = ea_refcount_create(0,
3964 &ctx->refcount_extra);
3965 if (pctx->errcode) {
3966 pctx->num = 2;
3967 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3968 ctx->flags |= E2F_FLAG_ABORT;
3969 return 0;
3970 }
3971 }
3972 ea_refcount_increment(ctx->refcount_extra, blk, 0);
3973 return 1;
3974 }
3975
3976 /*
3977 * OK, we haven't seen this EA block yet. So we need to
3978 * validate it
3979 */
3980 pctx->blk = blk;
3981 pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3982 if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
3983 goto clear_extattr;
3984 header = (struct ext2_ext_attr_header *) block_buf;
3985 pctx->blk = inode->i_file_acl;
3986 if (((ctx->ext_attr_ver == 1) &&
3987 (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
3988 ((ctx->ext_attr_ver == 2) &&
3989 (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
3990 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
3991 goto clear_extattr;
3992 }
3993
3994 if (header->h_blocks != 1) {
3995 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
3996 goto clear_extattr;
3997 }
3998
3999 region = region_create(0, fs->blocksize);
4000 if (!region) {
4001 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
4002 ctx->flags |= E2F_FLAG_ABORT;
4003 return 0;
4004 }
4005 if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
4006 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4007 goto clear_extattr;
4008 }
4009
4010 entry = (struct ext2_ext_attr_entry *)(header+1);
4011 end = block_buf + fs->blocksize;
4012 while ((char *)entry < end && *(__u32 *)entry) {
4013 if (region_allocate(region, (char *)entry - (char *)header,
4014 EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
4015 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4016 goto clear_extattr;
4017 }
4018 if ((ctx->ext_attr_ver == 1 &&
4019 (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
4020 (ctx->ext_attr_ver == 2 &&
4021 entry->e_name_index == 0)) {
4022 if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
4023 goto clear_extattr;
4024 }
4025 if (entry->e_value_block != 0) {
4026 if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
4027 goto clear_extattr;
4028 }
4029 if (entry->e_value_size &&
4030 region_allocate(region, entry->e_value_offs,
4031 EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
4032 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4033 goto clear_extattr;
4034 }
4035 entry = EXT2_EXT_ATTR_NEXT(entry);
4036 }
4037 if (region_allocate(region, (char *)entry - (char *)header, 4)) {
4038 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4039 goto clear_extattr;
4040 }
4041 region_free(region);
4042
4043 count = header->h_refcount - 1;
4044 if (count)
4045 ea_refcount_store(ctx->refcount, blk, count);
4046 mark_block_used(ctx, blk);
4047 ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
4048
4049 return 1;
4050
4051clear_extattr:
4052 inode->i_file_acl = 0;
4053 e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
4054 return 0;
4055}
4056
4057/* Returns 1 if bad htree, 0 if OK */
4058static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
4059 ext2_ino_t ino FSCK_ATTR((unused)),
4060 struct ext2_inode *inode,
4061 char *block_buf)
4062{
4063 struct ext2_dx_root_info *root;
4064 ext2_filsys fs = ctx->fs;
4065 errcode_t retval;
4066 blk_t blk;
4067
4068 if ((!LINUX_S_ISDIR(inode->i_mode) &&
4069 fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
4070 (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4071 fix_problem(ctx, PR_1_HTREE_SET, pctx)))
4072 return 1;
4073
4074 blk = inode->i_block[0];
4075 if (((blk == 0) ||
4076 (blk < fs->super->s_first_data_block) ||
4077 (blk >= fs->super->s_blocks_count)) &&
4078 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4079 return 1;
4080
4081 retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
4082 if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4083 return 1;
4084
4085 /* XXX should check that beginning matches a directory */
4086 root = (struct ext2_dx_root_info *) (block_buf + 24);
4087
4088 if ((root->reserved_zero || root->info_length < 8) &&
4089 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4090 return 1;
4091
4092 pctx->num = root->hash_version;
4093 if ((root->hash_version != EXT2_HASH_LEGACY) &&
4094 (root->hash_version != EXT2_HASH_HALF_MD4) &&
4095 (root->hash_version != EXT2_HASH_TEA) &&
4096 fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
4097 return 1;
4098
4099 if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
4100 fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
4101 return 1;
4102
4103 pctx->num = root->indirect_levels;
4104 if ((root->indirect_levels > 1) &&
4105 fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
4106 return 1;
4107
4108 return 0;
4109}
4110
4111/*
4112 * This subroutine is called on each inode to account for all of the
4113 * blocks used by that inode.
4114 */
4115static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4116 char *block_buf)
4117{
4118 ext2_filsys fs = ctx->fs;
4119 struct process_block_struct_1 pb;
4120 ext2_ino_t ino = pctx->ino;
4121 struct ext2_inode *inode = pctx->inode;
4122 int bad_size = 0;
4123 int dirty_inode = 0;
4124 __u64 size;
4125
4126 pb.ino = ino;
4127 pb.num_blocks = 0;
4128 pb.last_block = -1;
4129 pb.num_illegal_blocks = 0;
4130 pb.suppress = 0; pb.clear = 0;
4131 pb.fragmented = 0;
4132 pb.compressed = 0;
4133 pb.previous_block = 0;
4134 pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
4135 pb.is_reg = LINUX_S_ISREG(inode->i_mode);
4136 pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
4137 pb.inode = inode;
4138 pb.pctx = pctx;
4139 pb.ctx = ctx;
4140 pctx->ino = ino;
4141 pctx->errcode = 0;
4142
4143 if (inode->i_flags & EXT2_COMPRBLK_FL) {
4144 if (fs->super->s_feature_incompat &
4145 EXT2_FEATURE_INCOMPAT_COMPRESSION)
4146 pb.compressed = 1;
4147 else {
4148 if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
4149 inode->i_flags &= ~EXT2_COMPRBLK_FL;
4150 dirty_inode++;
4151 }
4152 }
4153 }
4154
4155 if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
4156 pb.num_blocks++;
4157
4158 if (ext2fs_inode_has_valid_blocks(inode))
4159 pctx->errcode = ext2fs_block_iterate2(fs, ino,
4160 pb.is_dir ? BLOCK_FLAG_HOLE : 0,
4161 block_buf, process_block, &pb);
4162 end_problem_latch(ctx, PR_LATCH_BLOCK);
4163 end_problem_latch(ctx, PR_LATCH_TOOBIG);
4164 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4165 goto out;
4166 if (pctx->errcode)
4167 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
4168
4169 if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
4170 ctx->fs_fragmented++;
4171
4172 if (pb.clear) {
4173 inode->i_links_count = 0;
4174 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4175 inode->i_dtime = time(NULL);
4176 dirty_inode++;
4177 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4178 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4179 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4180 /*
4181 * The inode was probably partially accounted for
4182 * before processing was aborted, so we need to
4183 * restart the pass 1 scan.
4184 */
4185 ctx->flags |= E2F_FLAG_RESTART;
4186 goto out;
4187 }
4188
4189 if (inode->i_flags & EXT2_INDEX_FL) {
4190 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
4191 inode->i_flags &= ~EXT2_INDEX_FL;
4192 dirty_inode++;
4193 } else {
4194#ifdef ENABLE_HTREE
4195 e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
4196#endif
4197 }
4198 }
4199 if (ctx->dirs_to_hash && pb.is_dir &&
4200 !(inode->i_flags & EXT2_INDEX_FL) &&
4201 ((inode->i_size / fs->blocksize) >= 3))
4202 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
4203
4204 if (!pb.num_blocks && pb.is_dir) {
4205 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
4206 inode->i_links_count = 0;
4207 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4208 inode->i_dtime = time(NULL);
4209 dirty_inode++;
4210 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4211 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4212 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4213 ctx->fs_directory_count--;
4214 goto out;
4215 }
4216 }
4217
4218 pb.num_blocks *= (fs->blocksize / 512);
4219
4220 if (pb.is_dir) {
4221 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
4222 if (nblock > (pb.last_block + 1))
4223 bad_size = 1;
4224 else if (nblock < (pb.last_block + 1)) {
4225 if (((pb.last_block + 1) - nblock) >
4226 fs->super->s_prealloc_dir_blocks)
4227 bad_size = 2;
4228 }
4229 } else {
4230 size = EXT2_I_SIZE(inode);
4231 if ((pb.last_block >= 0) &&
4232 (size < (__u64) pb.last_block * fs->blocksize))
4233 bad_size = 3;
4234 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
4235 bad_size = 4;
4236 }
4237 /* i_size for symlinks is checked elsewhere */
4238 if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
4239 pctx->num = (pb.last_block+1) * fs->blocksize;
4240 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
4241 inode->i_size = pctx->num;
4242 if (!LINUX_S_ISDIR(inode->i_mode))
4243 inode->i_size_high = pctx->num >> 32;
4244 dirty_inode++;
4245 }
4246 pctx->num = 0;
4247 }
4248 if (LINUX_S_ISREG(inode->i_mode) &&
4249 (inode->i_size_high || inode->i_size & 0x80000000UL))
4250 ctx->large_files++;
4251 if (pb.num_blocks != inode->i_blocks) {
4252 pctx->num = pb.num_blocks;
4253 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
4254 inode->i_blocks = pb.num_blocks;
4255 dirty_inode++;
4256 }
4257 pctx->num = 0;
4258 }
4259out:
4260 if (dirty_inode)
4261 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
4262}
4263
4264
4265/*
4266 * This is a helper function for check_blocks().
4267 */
4268static int process_block(ext2_filsys fs,
4269 blk_t *block_nr,
4270 e2_blkcnt_t blockcnt,
4271 blk_t ref_block FSCK_ATTR((unused)),
4272 int ref_offset FSCK_ATTR((unused)),
4273 void *priv_data)
4274{
4275 struct process_block_struct_1 *p;
4276 struct problem_context *pctx;
4277 blk_t blk = *block_nr;
4278 int ret_code = 0;
4279 int problem = 0;
4280 e2fsck_t ctx;
4281
4282 p = (struct process_block_struct_1 *) priv_data;
4283 pctx = p->pctx;
4284 ctx = p->ctx;
4285
4286 if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
4287 /* todo: Check that the comprblk_fl is high, that the
4288 blkaddr pattern looks right (all non-holes up to
4289 first EXT2FS_COMPRESSED_BLKADDR, then all
4290 EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
4291 that the feature_incompat bit is high, and that the
4292 inode is a regular file. If we're doing a "full
4293 check" (a concept introduced to e2fsck by e2compr,
4294 meaning that we look at data blocks as well as
4295 metadata) then call some library routine that
4296 checks the compressed data. I'll have to think
4297 about this, because one particularly important
4298 problem to be able to fix is to recalculate the
4299 cluster size if necessary. I think that perhaps
4300 we'd better do most/all e2compr-specific checks
4301 separately, after the non-e2compr checks. If not
4302 doing a full check, it may be useful to test that
4303 the personality is linux; e.g. if it isn't then
4304 perhaps this really is just an illegal block. */
4305 return 0;
4306 }
4307
4308 if (blk == 0) {
4309 if (p->is_dir == 0) {
4310 /*
4311 * Should never happen, since only directories
4312 * get called with BLOCK_FLAG_HOLE
4313 */
4314#ifdef DEBUG_E2FSCK
4315 printf("process_block() called with blk == 0, "
4316 "blockcnt=%d, inode %lu???\n",
4317 blockcnt, p->ino);
4318#endif
4319 return 0;
4320 }
4321 if (blockcnt < 0)
4322 return 0;
4323 if (blockcnt * fs->blocksize < p->inode->i_size) {
4324 goto mark_dir;
4325 }
4326 return 0;
4327 }
4328
4329 /*
4330 * Simplistic fragmentation check. We merely require that the
4331 * file be contiguous. (Which can never be true for really
4332 * big files that are greater than a block group.)
4333 */
4334 if (!HOLE_BLKADDR(p->previous_block)) {
4335 if (p->previous_block+1 != blk)
4336 p->fragmented = 1;
4337 }
4338 p->previous_block = blk;
4339
4340 if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
4341 problem = PR_1_TOOBIG_DIR;
4342 if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
4343 problem = PR_1_TOOBIG_REG;
4344 if (!p->is_dir && !p->is_reg && blockcnt > 0)
4345 problem = PR_1_TOOBIG_SYMLINK;
4346
4347 if (blk < fs->super->s_first_data_block ||
4348 blk >= fs->super->s_blocks_count)
4349 problem = PR_1_ILLEGAL_BLOCK_NUM;
4350
4351 if (problem) {
4352 p->num_illegal_blocks++;
4353 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
4354 if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
4355 p->clear = 1;
4356 return BLOCK_ABORT;
4357 }
4358 if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
4359 p->suppress = 1;
4360 set_latch_flags(PR_LATCH_BLOCK,
4361 PRL_SUPPRESS, 0);
4362 }
4363 }
4364 pctx->blk = blk;
4365 pctx->blkcount = blockcnt;
4366 if (fix_problem(ctx, problem, pctx)) {
4367 blk = *block_nr = 0;
4368 ret_code = BLOCK_CHANGED;
4369 goto mark_dir;
4370 } else
4371 return 0;
4372 }
4373
4374 if (p->ino == EXT2_RESIZE_INO) {
4375 /*
4376 * The resize inode has already be sanity checked
4377 * during pass #0 (the superblock checks). All we
4378 * have to do is mark the double indirect block as
4379 * being in use; all of the other blocks are handled
4380 * by mark_table_blocks()).
4381 */
4382 if (blockcnt == BLOCK_COUNT_DIND)
4383 mark_block_used(ctx, blk);
4384 } else
4385 mark_block_used(ctx, blk);
4386 p->num_blocks++;
4387 if (blockcnt >= 0)
4388 p->last_block = blockcnt;
4389mark_dir:
4390 if (p->is_dir && (blockcnt >= 0)) {
4391 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
4392 blk, blockcnt);
4393 if (pctx->errcode) {
4394 pctx->blk = blk;
4395 pctx->num = blockcnt;
4396 fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
4397 /* Should never get here */
4398 ctx->flags |= E2F_FLAG_ABORT;
4399 return BLOCK_ABORT;
4400 }
4401 }
4402 return ret_code;
4403}
4404
4405static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)),
4406 blk_t *block_nr,
4407 e2_blkcnt_t blockcnt,
4408 blk_t ref_block FSCK_ATTR((unused)),
4409 int ref_offset FSCK_ATTR((unused)),
4410 void *priv_data EXT2FS_ATTR((unused)))
4411{
4412 /*
4413 * Note: This function processes blocks for the bad blocks
4414 * inode, which is never compressed. So we don't use HOLE_BLKADDR().
4415 */
4416
4417 printf("Unrecoverable Error: Found %"PRIi64" bad blocks starting at block number: %u\n", blockcnt, *block_nr);
4418 return BLOCK_ERROR;
4419}
4420
4421/*
4422 * This routine gets called at the end of pass 1 if bad blocks are
4423 * detected in the superblock, group descriptors, inode_bitmaps, or
4424 * block bitmaps. At this point, all of the blocks have been mapped
4425 * out, so we can try to allocate new block(s) to replace the bad
4426 * blocks.
4427 */
4428static void handle_fs_bad_blocks(e2fsck_t ctx)
4429{
4430 printf("Bad blocks detected on your filesystem\n"
4431 "You should get your data off as the device will soon die\n");
4432}
4433
4434/*
4435 * This routine marks all blocks which are used by the superblock,
4436 * group descriptors, inode bitmaps, and block bitmaps.
4437 */
4438static void mark_table_blocks(e2fsck_t ctx)
4439{
4440 ext2_filsys fs = ctx->fs;
4441 blk_t block, b;
4442 dgrp_t i;
4443 int j;
4444 struct problem_context pctx;
4445
4446 clear_problem_context(&pctx);
4447
4448 block = fs->super->s_first_data_block;
4449 for (i = 0; i < fs->group_desc_count; i++) {
4450 pctx.group = i;
4451
4452 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
4453
4454 /*
4455 * Mark the blocks used for the inode table
4456 */
4457 if (fs->group_desc[i].bg_inode_table) {
4458 for (j = 0, b = fs->group_desc[i].bg_inode_table;
4459 j < fs->inode_blocks_per_group;
4460 j++, b++) {
4461 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4462 b)) {
4463 pctx.blk = b;
4464 if (fix_problem(ctx,
4465 PR_1_ITABLE_CONFLICT, &pctx)) {
4466 ctx->invalid_inode_table_flag[i]++;
4467 ctx->invalid_bitmaps++;
4468 }
4469 } else {
4470 ext2fs_mark_block_bitmap(ctx->block_found_map, b);
4471 }
4472 }
4473 }
4474
4475 /*
4476 * Mark block used for the block bitmap
4477 */
4478 if (fs->group_desc[i].bg_block_bitmap) {
4479 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4480 fs->group_desc[i].bg_block_bitmap)) {
4481 pctx.blk = fs->group_desc[i].bg_block_bitmap;
4482 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
4483 ctx->invalid_block_bitmap_flag[i]++;
4484 ctx->invalid_bitmaps++;
4485 }
4486 } else {
4487 ext2fs_mark_block_bitmap(ctx->block_found_map,
4488 fs->group_desc[i].bg_block_bitmap);
4489 }
4490 }
4491 /*
4492 * Mark block used for the inode bitmap
4493 */
4494 if (fs->group_desc[i].bg_inode_bitmap) {
4495 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4496 fs->group_desc[i].bg_inode_bitmap)) {
4497 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
4498 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
4499 ctx->invalid_inode_bitmap_flag[i]++;
4500 ctx->invalid_bitmaps++;
4501 }
4502 } else {
4503 ext2fs_mark_block_bitmap(ctx->block_found_map,
4504 fs->group_desc[i].bg_inode_bitmap);
4505 }
4506 }
4507 block += fs->super->s_blocks_per_group;
4508 }
4509}
4510
4511/*
4512 * Thes subroutines short circuits ext2fs_get_blocks and
4513 * ext2fs_check_directory; we use them since we already have the inode
4514 * structure, so there's no point in letting the ext2fs library read
4515 * the inode again.
4516 */
4517static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
4518 blk_t *blocks)
4519{
4520 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4521 int i;
4522
4523 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4524 return EXT2_ET_CALLBACK_NOTHANDLED;
4525
4526 for (i=0; i < EXT2_N_BLOCKS; i++)
4527 blocks[i] = ctx->stashed_inode->i_block[i];
4528 return 0;
4529}
4530
4531static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
4532 struct ext2_inode *inode)
4533{
4534 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4535
4536 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4537 return EXT2_ET_CALLBACK_NOTHANDLED;
4538 *inode = *ctx->stashed_inode;
4539 return 0;
4540}
4541
4542static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
4543 struct ext2_inode *inode)
4544{
4545 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4546
4547 if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
4548 *ctx->stashed_inode = *inode;
4549 return EXT2_ET_CALLBACK_NOTHANDLED;
4550}
4551
4552static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
4553{
4554 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4555
4556 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4557 return EXT2_ET_CALLBACK_NOTHANDLED;
4558
4559 if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
4560 return EXT2_ET_NO_DIRECTORY;
4561 return 0;
4562}
4563
4564void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
4565{
4566 ext2_filsys fs = ctx->fs;
4567
4568 if (bool) {
4569 fs->get_blocks = pass1_get_blocks;
4570 fs->check_directory = pass1_check_directory;
4571 fs->read_inode = pass1_read_inode;
4572 fs->write_inode = pass1_write_inode;
4573 ctx->stashed_ino = 0;
4574 } else {
4575 fs->get_blocks = 0;
4576 fs->check_directory = 0;
4577 fs->read_inode = 0;
4578 fs->write_inode = 0;
4579 }
4580}
4581
4582/*
4583 * pass1b.c --- Pass #1b of e2fsck
4584 *
4585 * This file contains pass1B, pass1C, and pass1D of e2fsck. They are
4586 * only invoked if pass 1 discovered blocks which are in use by more
4587 * than one inode.
4588 *
4589 * Pass1B scans the data blocks of all the inodes again, generating a
4590 * complete list of duplicate blocks and which inodes have claimed
4591 * them.
4592 *
4593 * Pass1C does a tree-traversal of the filesystem, to determine the
4594 * parent directories of these inodes. This step is necessary so that
4595 * e2fsck can print out the pathnames of affected inodes.
4596 *
4597 * Pass1D is a reconciliation pass. For each inode with duplicate
4598 * blocks, the user is prompted if s/he would like to clone the file
4599 * (so that the file gets a fresh copy of the duplicated blocks) or
4600 * simply to delete the file.
4601 *
4602 */
4603
4604
4605/* Needed for architectures where sizeof(int) != sizeof(void *) */
4606#define INT_TO_VOIDPTR(val) ((void *)(intptr_t)(val))
4607#define VOIDPTR_TO_INT(ptr) ((int)(intptr_t)(ptr))
4608
4609/* Define an extension to the ext2 library's block count information */
4610#define BLOCK_COUNT_EXTATTR (-5)
4611
4612struct block_el {
4613 blk_t block;
4614 struct block_el *next;
4615};
4616
4617struct inode_el {
4618 ext2_ino_t inode;
4619 struct inode_el *next;
4620};
4621
4622struct dup_block {
4623 int num_bad;
4624 struct inode_el *inode_list;
4625};
4626
4627/*
4628 * This structure stores information about a particular inode which
4629 * is sharing blocks with other inodes. This information is collected
4630 * to display to the user, so that the user knows what files he or she
4631 * is dealing with, when trying to decide how to resolve the conflict
4632 * of multiply-claimed blocks.
4633 */
4634struct dup_inode {
4635 ext2_ino_t dir;
4636 int num_dupblocks;
4637 struct ext2_inode inode;
4638 struct block_el *block_list;
4639};
4640
4641static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
4642 e2_blkcnt_t blockcnt, blk_t ref_blk,
4643 int ref_offset, void *priv_data);
4644static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
4645 struct dup_inode *dp, char *block_buf);
4646static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
4647 struct dup_inode *dp, char* block_buf);
4648static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
4649
4650static void pass1b(e2fsck_t ctx, char *block_buf);
4651static void pass1c(e2fsck_t ctx, char *block_buf);
4652static void pass1d(e2fsck_t ctx, char *block_buf);
4653
4654static int dup_inode_count = 0;
4655
4656static dict_t blk_dict, ino_dict;
4657
4658static ext2fs_inode_bitmap inode_dup_map;
4659
4660static int dict_int_cmp(const void *a, const void *b)
4661{
4662 intptr_t ia, ib;
4663
4664 ia = (intptr_t)a;
4665 ib = (intptr_t)b;
4666
4667 return (ia-ib);
4668}
4669
4670/*
4671 * Add a duplicate block record
4672 */
4673static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
4674 struct ext2_inode *inode)
4675{
4676 dnode_t *n;
4677 struct dup_block *db;
4678 struct dup_inode *di;
4679 struct block_el *blk_el;
4680 struct inode_el *ino_el;
4681
4682 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
4683 if (n)
4684 db = (struct dup_block *) dnode_get(n);
4685 else {
4686 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
4687 sizeof(struct dup_block), "duplicate block header");
4688 db->num_bad = 0;
4689 db->inode_list = 0;
4690 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
4691 }
4692 ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
4693 sizeof(struct inode_el), "inode element");
4694 ino_el->inode = ino;
4695 ino_el->next = db->inode_list;
4696 db->inode_list = ino_el;
4697 db->num_bad++;
4698
4699 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
4700 if (n)
4701 di = (struct dup_inode *) dnode_get(n);
4702 else {
4703 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
4704 sizeof(struct dup_inode), "duplicate inode header");
4705 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0;
4706 di->num_dupblocks = 0;
4707 di->block_list = 0;
4708 di->inode = *inode;
4709 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
4710 }
4711 blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
4712 sizeof(struct block_el), "block element");
4713 blk_el->block = blk;
4714 blk_el->next = di->block_list;
4715 di->block_list = blk_el;
4716 di->num_dupblocks++;
4717}
4718
4719/*
4720 * Free a duplicate inode record
4721 */
4722static void inode_dnode_free(dnode_t *node)
4723{
4724 struct dup_inode *di;
4725 struct block_el *p, *next;
4726
4727 di = (struct dup_inode *) dnode_get(node);
4728 for (p = di->block_list; p; p = next) {
4729 next = p->next;
4730 free(p);
4731 }
4732 free(node);
4733}
4734
4735/*
4736 * Free a duplicate block record
4737 */
4738static void block_dnode_free(dnode_t *node)
4739{
4740 struct dup_block *db;
4741 struct inode_el *p, *next;
4742
4743 db = (struct dup_block *) dnode_get(node);
4744 for (p = db->inode_list; p; p = next) {
4745 next = p->next;
4746 free(p);
4747 }
4748 free(node);
4749}
4750
4751
4752/*
4753 * Main procedure for handling duplicate blocks
4754 */
4755void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
4756{
4757 ext2_filsys fs = ctx->fs;
4758 struct problem_context pctx;
4759
4760 clear_problem_context(&pctx);
4761
4762 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4763 _("multiply claimed inode map"), &inode_dup_map);
4764 if (pctx.errcode) {
4765 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
4766 ctx->flags |= E2F_FLAG_ABORT;
4767 return;
4768 }
4769
4770 dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4771 dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4772 dict_set_allocator(&ino_dict, inode_dnode_free);
4773 dict_set_allocator(&blk_dict, block_dnode_free);
4774
4775 pass1b(ctx, block_buf);
4776 pass1c(ctx, block_buf);
4777 pass1d(ctx, block_buf);
4778
4779 /*
4780 * Time to free all of the accumulated data structures that we
4781 * don't need anymore.
4782 */
4783 dict_free_nodes(&ino_dict);
4784 dict_free_nodes(&blk_dict);
4785}
4786
4787/*
4788 * Scan the inodes looking for inodes that contain duplicate blocks.
4789 */
4790struct process_block_struct_1b {
4791 e2fsck_t ctx;
4792 ext2_ino_t ino;
4793 int dup_blocks;
4794 struct ext2_inode *inode;
4795 struct problem_context *pctx;
4796};
4797
4798static void pass1b(e2fsck_t ctx, char *block_buf)
4799{
4800 ext2_filsys fs = ctx->fs;
4801 ext2_ino_t ino;
4802 struct ext2_inode inode;
4803 ext2_inode_scan scan;
4804 struct process_block_struct_1b pb;
4805 struct problem_context pctx;
4806
4807 clear_problem_context(&pctx);
4808
4809 if (!(ctx->options & E2F_OPT_PREEN))
4810 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
4811 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4812 &scan);
4813 if (pctx.errcode) {
4814 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4815 ctx->flags |= E2F_FLAG_ABORT;
4816 return;
4817 }
4818 ctx->stashed_inode = &inode;
4819 pb.ctx = ctx;
4820 pb.pctx = &pctx;
4821 pctx.str = "pass1b";
4822 while (1) {
4823 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
4824 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
4825 continue;
4826 if (pctx.errcode) {
4827 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4828 ctx->flags |= E2F_FLAG_ABORT;
4829 return;
4830 }
4831 if (!ino)
4832 break;
4833 pctx.ino = ctx->stashed_ino = ino;
4834 if ((ino != EXT2_BAD_INO) &&
4835 !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
4836 continue;
4837
4838 pb.ino = ino;
4839 pb.dup_blocks = 0;
4840 pb.inode = &inode;
4841
4842 if (ext2fs_inode_has_valid_blocks(&inode) ||
4843 (ino == EXT2_BAD_INO))
4844 pctx.errcode = ext2fs_block_iterate2(fs, ino,
4845 0, block_buf, process_pass1b_block, &pb);
4846 if (inode.i_file_acl)
4847 process_pass1b_block(fs, &inode.i_file_acl,
4848 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
4849 if (pb.dup_blocks) {
4850 end_problem_latch(ctx, PR_LATCH_DBLOCK);
4851 if (ino >= EXT2_FIRST_INODE(fs->super) ||
4852 ino == EXT2_ROOT_INO)
4853 dup_inode_count++;
4854 }
4855 if (pctx.errcode)
4856 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
4857 }
4858 ext2fs_close_inode_scan(scan);
4859 e2fsck_use_inode_shortcuts(ctx, 0);
4860}
4861
4862static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
4863 blk_t *block_nr,
4864 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
4865 blk_t ref_blk FSCK_ATTR((unused)),
4866 int ref_offset FSCK_ATTR((unused)),
4867 void *priv_data)
4868{
4869 struct process_block_struct_1b *p;
4870 e2fsck_t ctx;
4871
4872 if (HOLE_BLKADDR(*block_nr))
4873 return 0;
4874 p = (struct process_block_struct_1b *) priv_data;
4875 ctx = p->ctx;
4876
4877 if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
4878 return 0;
4879
4880 /* OK, this is a duplicate block */
4881 if (p->ino != EXT2_BAD_INO) {
4882 p->pctx->blk = *block_nr;
4883 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
4884 }
4885 p->dup_blocks++;
4886 ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
4887
4888 add_dupe(ctx, p->ino, *block_nr, p->inode);
4889
4890 return 0;
4891}
4892
4893/*
4894 * Pass 1c: Scan directories for inodes with duplicate blocks. This
4895 * is used so that we can print pathnames when prompting the user for
4896 * what to do.
4897 */
4898struct search_dir_struct {
4899 int count;
4900 ext2_ino_t first_inode;
4901 ext2_ino_t max_inode;
4902};
4903
4904static int search_dirent_proc(ext2_ino_t dir, int entry,
4905 struct ext2_dir_entry *dirent,
4906 int offset FSCK_ATTR((unused)),
4907 int blocksize FSCK_ATTR((unused)),
4908 char *buf FSCK_ATTR((unused)),
4909 void *priv_data)
4910{
4911 struct search_dir_struct *sd;
4912 struct dup_inode *p;
4913 dnode_t *n;
4914
4915 sd = (struct search_dir_struct *) priv_data;
4916
4917 if (dirent->inode > sd->max_inode)
4918 /* Should abort this inode, but not everything */
4919 return 0;
4920
4921 if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
4922 !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
4923 return 0;
4924
4925 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
4926 if (!n)
4927 return 0;
4928 p = (struct dup_inode *) dnode_get(n);
4929 p->dir = dir;
4930 sd->count--;
4931
4932 return sd->count ? 0 : DIRENT_ABORT;
4933}
4934
4935
4936static void pass1c(e2fsck_t ctx, char *block_buf)
4937{
4938 ext2_filsys fs = ctx->fs;
4939 struct search_dir_struct sd;
4940 struct problem_context pctx;
4941
4942 clear_problem_context(&pctx);
4943
4944 if (!(ctx->options & E2F_OPT_PREEN))
4945 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
4946
4947 /*
4948 * Search through all directories to translate inodes to names
4949 * (by searching for the containing directory for that inode.)
4950 */
4951 sd.count = dup_inode_count;
4952 sd.first_inode = EXT2_FIRST_INODE(fs->super);
4953 sd.max_inode = fs->super->s_inodes_count;
4954 ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
4955 search_dirent_proc, &sd);
4956}
4957
4958static void pass1d(e2fsck_t ctx, char *block_buf)
4959{
4960 ext2_filsys fs = ctx->fs;
4961 struct dup_inode *p, *t;
4962 struct dup_block *q;
4963 ext2_ino_t *shared, ino;
4964 int shared_len;
4965 int i;
4966 int file_ok;
4967 int meta_data = 0;
4968 struct problem_context pctx;
4969 dnode_t *n, *m;
4970 struct block_el *s;
4971 struct inode_el *r;
4972
4973 clear_problem_context(&pctx);
4974
4975 if (!(ctx->options & E2F_OPT_PREEN))
4976 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
4977 e2fsck_read_bitmaps(ctx);
4978
4979 pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
4980 fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
4981 shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
4982 sizeof(ext2_ino_t) * dict_count(&ino_dict),
4983 "Shared inode list");
4984 for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
4985 p = (struct dup_inode *) dnode_get(n);
4986 shared_len = 0;
4987 file_ok = 1;
4988 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
4989 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
4990 continue;
4991
4992 /*
4993 * Find all of the inodes which share blocks with this
4994 * one. First we find all of the duplicate blocks
4995 * belonging to this inode, and then search each block
4996 * get the list of inodes, and merge them together.
4997 */
4998 for (s = p->block_list; s; s = s->next) {
4999 m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
5000 if (!m)
5001 continue; /* Should never happen... */
5002 q = (struct dup_block *) dnode_get(m);
5003 if (q->num_bad > 1)
5004 file_ok = 0;
5005 if (check_if_fs_block(ctx, s->block)) {
5006 file_ok = 0;
5007 meta_data = 1;
5008 }
5009
5010 /*
5011 * Add all inodes used by this block to the
5012 * shared[] --- which is a unique list, so
5013 * if an inode is already in shared[], don't
5014 * add it again.
5015 */
5016 for (r = q->inode_list; r; r = r->next) {
5017 if (r->inode == ino)
5018 continue;
5019 for (i = 0; i < shared_len; i++)
5020 if (shared[i] == r->inode)
5021 break;
5022 if (i == shared_len) {
5023 shared[shared_len++] = r->inode;
5024 }
5025 }
5026 }
5027
5028 /*
5029 * Report the inode that we are working on
5030 */
5031 pctx.inode = &p->inode;
5032 pctx.ino = ino;
5033 pctx.dir = p->dir;
5034 pctx.blkcount = p->num_dupblocks;
5035 pctx.num = meta_data ? shared_len+1 : shared_len;
5036 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
5037 pctx.blkcount = 0;
5038 pctx.num = 0;
5039
5040 if (meta_data)
5041 fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
5042
5043 for (i = 0; i < shared_len; i++) {
5044 m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
5045 if (!m)
5046 continue; /* should never happen */
5047 t = (struct dup_inode *) dnode_get(m);
5048 /*
5049 * Report the inode that we are sharing with
5050 */
5051 pctx.inode = &t->inode;
5052 pctx.ino = shared[i];
5053 pctx.dir = t->dir;
5054 fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
5055 }
5056 if (file_ok) {
5057 fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
5058 continue;
5059 }
5060 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
5061 pctx.errcode = clone_file(ctx, ino, p, block_buf);
5062 if (pctx.errcode)
5063 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
5064 else
5065 continue;
5066 }
5067 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
5068 delete_file(ctx, ino, p, block_buf);
5069 else
5070 ext2fs_unmark_valid(fs);
5071 }
5072 ext2fs_free_mem(&shared);
5073}
5074
5075/*
5076 * Drop the refcount on the dup_block structure, and clear the entry
5077 * in the block_dup_map if appropriate.
5078 */
5079static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
5080{
5081 p->num_bad--;
5082 if (p->num_bad <= 0 ||
5083 (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
5084 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
5085}
5086
5087static int delete_file_block(ext2_filsys fs,
5088 blk_t *block_nr,
5089 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
5090 blk_t ref_block FSCK_ATTR((unused)),
5091 int ref_offset FSCK_ATTR((unused)),
5092 void *priv_data)
5093{
5094 struct process_block_struct_1b *pb;
5095 struct dup_block *p;
5096 dnode_t *n;
5097 e2fsck_t ctx;
5098
5099 pb = (struct process_block_struct_1b *) priv_data;
5100 ctx = pb->ctx;
5101
5102 if (HOLE_BLKADDR(*block_nr))
5103 return 0;
5104
5105 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5106 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5107 if (n) {
5108 p = (struct dup_block *) dnode_get(n);
5109 decrement_badcount(ctx, *block_nr, p);
5110 } else
5111 bb_error_msg(_("internal error; can't find dup_blk for %d"),
5112 *block_nr);
5113 } else {
5114 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
5115 ext2fs_block_alloc_stats(fs, *block_nr, -1);
5116 }
5117
5118 return 0;
5119}
5120
5121static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
5122 struct dup_inode *dp, char* block_buf)
5123{
5124 ext2_filsys fs = ctx->fs;
5125 struct process_block_struct_1b pb;
5126 struct ext2_inode inode;
5127 struct problem_context pctx;
5128 unsigned int count;
5129
5130 clear_problem_context(&pctx);
5131 pctx.ino = pb.ino = ino;
5132 pb.dup_blocks = dp->num_dupblocks;
5133 pb.ctx = ctx;
5134 pctx.str = "delete_file";
5135
5136 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5137 if (ext2fs_inode_has_valid_blocks(&inode))
5138 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5139 delete_file_block, &pb);
5140 if (pctx.errcode)
5141 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5142 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5143 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5144 if (ctx->inode_bad_map)
5145 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
5146 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
5147
5148 /* Inode may have changed by block_iterate, so reread it */
5149 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5150 inode.i_links_count = 0;
5151 inode.i_dtime = time(NULL);
5152 if (inode.i_file_acl &&
5153 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
5154 count = 1;
5155 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
5156 block_buf, -1, &count);
5157 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
5158 pctx.errcode = 0;
5159 count = 1;
5160 }
5161 if (pctx.errcode) {
5162 pctx.blk = inode.i_file_acl;
5163 fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
5164 }
5165 /*
5166 * If the count is zero, then arrange to have the
5167 * block deleted. If the block is in the block_dup_map,
5168 * also call delete_file_block since it will take care
5169 * of keeping the accounting straight.
5170 */
5171 if ((count == 0) ||
5172 ext2fs_test_block_bitmap(ctx->block_dup_map,
5173 inode.i_file_acl))
5174 delete_file_block(fs, &inode.i_file_acl,
5175 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
5176 }
5177 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
5178}
5179
5180struct clone_struct {
5181 errcode_t errcode;
5182 ext2_ino_t dir;
5183 char *buf;
5184 e2fsck_t ctx;
5185};
5186
5187static int clone_file_block(ext2_filsys fs,
5188 blk_t *block_nr,
5189 e2_blkcnt_t blockcnt,
5190 blk_t ref_block FSCK_ATTR((unused)),
5191 int ref_offset FSCK_ATTR((unused)),
5192 void *priv_data)
5193{
5194 struct dup_block *p;
5195 blk_t new_block;
5196 errcode_t retval;
5197 struct clone_struct *cs = (struct clone_struct *) priv_data;
5198 dnode_t *n;
5199 e2fsck_t ctx;
5200
5201 ctx = cs->ctx;
5202
5203 if (HOLE_BLKADDR(*block_nr))
5204 return 0;
5205
5206 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5207 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5208 if (n) {
5209 p = (struct dup_block *) dnode_get(n);
5210 retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
5211 &new_block);
5212 if (retval) {
5213 cs->errcode = retval;
5214 return BLOCK_ABORT;
5215 }
5216 if (cs->dir && (blockcnt >= 0)) {
5217 retval = ext2fs_set_dir_block(fs->dblist,
5218 cs->dir, new_block, blockcnt);
5219 if (retval) {
5220 cs->errcode = retval;
5221 return BLOCK_ABORT;
5222 }
5223 }
5224
5225 retval = io_channel_read_blk(fs->io, *block_nr, 1,
5226 cs->buf);
5227 if (retval) {
5228 cs->errcode = retval;
5229 return BLOCK_ABORT;
5230 }
5231 retval = io_channel_write_blk(fs->io, new_block, 1,
5232 cs->buf);
5233 if (retval) {
5234 cs->errcode = retval;
5235 return BLOCK_ABORT;
5236 }
5237 decrement_badcount(ctx, *block_nr, p);
5238 *block_nr = new_block;
5239 ext2fs_mark_block_bitmap(ctx->block_found_map,
5240 new_block);
5241 ext2fs_mark_block_bitmap(fs->block_map, new_block);
5242 return BLOCK_CHANGED;
5243 } else
5244 bb_error_msg(_("internal error; can't find dup_blk for %d"),
5245 *block_nr);
5246 }
5247 return 0;
5248}
5249
5250static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
5251 struct dup_inode *dp, char* block_buf)
5252{
5253 ext2_filsys fs = ctx->fs;
5254 errcode_t retval;
5255 struct clone_struct cs;
5256 struct problem_context pctx;
5257 blk_t blk;
5258 dnode_t *n;
5259 struct inode_el *ino_el;
5260 struct dup_block *db;
5261 struct dup_inode *di;
5262
5263 clear_problem_context(&pctx);
5264 cs.errcode = 0;
5265 cs.dir = 0;
5266 cs.ctx = ctx;
5267 retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
5268 if (retval)
5269 return retval;
5270
5271 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
5272 cs.dir = ino;
5273
5274 pctx.ino = ino;
5275 pctx.str = "clone_file";
5276 if (ext2fs_inode_has_valid_blocks(&dp->inode))
5277 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5278 clone_file_block, &cs);
5279 ext2fs_mark_bb_dirty(fs);
5280 if (pctx.errcode) {
5281 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5282 retval = pctx.errcode;
5283 goto errout;
5284 }
5285 if (cs.errcode) {
5286 bb_error_msg(_("returned from clone_file_block"));
5287 retval = cs.errcode;
5288 goto errout;
5289 }
5290 /* The inode may have changed on disk, so we have to re-read it */
5291 e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
5292 blk = dp->inode.i_file_acl;
5293 if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
5294 BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
5295 BLOCK_CHANGED)) {
5296 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
5297 /*
5298 * If we cloned the EA block, find all other inodes
5299 * which refered to that EA block, and modify
5300 * them to point to the new EA block.
5301 */
5302 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
5303 db = (struct dup_block *) dnode_get(n);
5304 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
5305 if (ino_el->inode == ino)
5306 continue;
5307 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
5308 di = (struct dup_inode *) dnode_get(n);
5309 if (di->inode.i_file_acl == blk) {
5310 di->inode.i_file_acl = dp->inode.i_file_acl;
5311 e2fsck_write_inode(ctx, ino_el->inode,
5312 &di->inode, "clone file EA");
5313 decrement_badcount(ctx, blk, db);
5314 }
5315 }
5316 }
5317 retval = 0;
5318errout:
5319 ext2fs_free_mem(&cs.buf);
5320 return retval;
5321}
5322
5323/*
5324 * This routine returns 1 if a block overlaps with one of the superblocks,
5325 * group descriptors, inode bitmaps, or block bitmaps.
5326 */
5327static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
5328{
5329 ext2_filsys fs = ctx->fs;
5330 blk_t block;
5331 dgrp_t i;
5332
5333 block = fs->super->s_first_data_block;
5334 for (i = 0; i < fs->group_desc_count; i++) {
5335
5336 /* Check superblocks/block group descriptros */
5337 if (ext2fs_bg_has_super(fs, i)) {
5338 if (test_block >= block &&
5339 (test_block <= block + fs->desc_blocks))
5340 return 1;
5341 }
5342
5343 /* Check the inode table */
5344 if ((fs->group_desc[i].bg_inode_table) &&
5345 (test_block >= fs->group_desc[i].bg_inode_table) &&
5346 (test_block < (fs->group_desc[i].bg_inode_table +
5347 fs->inode_blocks_per_group)))
5348 return 1;
5349
5350 /* Check the bitmap blocks */
5351 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
5352 (test_block == fs->group_desc[i].bg_inode_bitmap))
5353 return 1;
5354
5355 block += fs->super->s_blocks_per_group;
5356 }
5357 return 0;
5358}
5359/*
5360 * pass2.c --- check directory structure
5361 *
5362 * Pass 2 of e2fsck iterates through all active directory inodes, and
5363 * applies to following tests to each directory entry in the directory
5364 * blocks in the inodes:
5365 *
5366 * - The length of the directory entry (rec_len) should be at
5367 * least 8 bytes, and no more than the remaining space
5368 * left in the directory block.
5369 * - The length of the name in the directory entry (name_len)
5370 * should be less than (rec_len - 8).
5371 * - The inode number in the directory entry should be within
5372 * legal bounds.
5373 * - The inode number should refer to a in-use inode.
5374 * - The first entry should be '.', and its inode should be
5375 * the inode of the directory.
5376 * - The second entry should be '..'.
5377 *
5378 * To minimize disk seek time, the directory blocks are processed in
5379 * sorted order of block numbers.
5380 *
5381 * Pass 2 also collects the following information:
5382 * - The inode numbers of the subdirectories for each directory.
5383 *
5384 * Pass 2 relies on the following information from previous passes:
5385 * - The directory information collected in pass 1.
5386 * - The inode_used_map bitmap
5387 * - The inode_bad_map bitmap
5388 * - The inode_dir_map bitmap
5389 *
5390 * Pass 2 frees the following data structures
5391 * - The inode_bad_map bitmap
5392 * - The inode_reg_map bitmap
5393 */
5394
5395/*
5396 * Keeps track of how many times an inode is referenced.
5397 */
5398static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
5399static int check_dir_block(ext2_filsys fs,
5400 struct ext2_db_entry *dir_blocks_info,
5401 void *priv_data);
5402static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
5403 struct problem_context *pctx);
5404static int update_dir_block(ext2_filsys fs,
5405 blk_t *block_nr,
5406 e2_blkcnt_t blockcnt,
5407 blk_t ref_block,
5408 int ref_offset,
5409 void *priv_data);
5410static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
5411static int htree_depth(struct dx_dir_info *dx_dir,
5412 struct dx_dirblock_info *dx_db);
5413static int special_dir_block_cmp(const void *a, const void *b);
5414
5415struct check_dir_struct {
5416 char *buf;
5417 struct problem_context pctx;
5418 int count, max;
5419 e2fsck_t ctx;
5420};
5421
5422static void e2fsck_pass2(e2fsck_t ctx)
5423{
5424 struct ext2_super_block *sb = ctx->fs->super;
5425 struct problem_context pctx;
5426 ext2_filsys fs = ctx->fs;
5427 char *buf;
5428 struct dir_info *dir;
5429 struct check_dir_struct cd;
5430 struct dx_dir_info *dx_dir;
5431 struct dx_dirblock_info *dx_db, *dx_parent;
5432 int b;
5433 int i, depth;
5434 problem_t code;
5435 int bad_dir;
5436
5437 clear_problem_context(&cd.pctx);
5438
5439 /* Pass 2 */
5440
5441 if (!(ctx->options & E2F_OPT_PREEN))
5442 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
5443
5444 cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
5445 0, ctx->inode_link_info,
5446 &ctx->inode_count);
5447 if (cd.pctx.errcode) {
5448 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
5449 ctx->flags |= E2F_FLAG_ABORT;
5450 return;
5451 }
5452 buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
5453 "directory scan buffer");
5454
5455 /*
5456 * Set up the parent pointer for the root directory, if
5457 * present. (If the root directory is not present, we will
5458 * create it in pass 3.)
5459 */
5460 dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
5461 if (dir)
5462 dir->parent = EXT2_ROOT_INO;
5463
5464 cd.buf = buf;
5465 cd.ctx = ctx;
5466 cd.count = 1;
5467 cd.max = ext2fs_dblist_count(fs->dblist);
5468
5469 if (ctx->progress)
5470 (void) (ctx->progress)(ctx, 2, 0, cd.max);
5471
5472 if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
5473 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
5474
5475 cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
5476 &cd);
5477 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5478 return;
5479 if (cd.pctx.errcode) {
5480 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
5481 ctx->flags |= E2F_FLAG_ABORT;
5482 return;
5483 }
5484
5485#ifdef ENABLE_HTREE
5486 for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
5487 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5488 return;
5489 if (dx_dir->numblocks == 0)
5490 continue;
5491 clear_problem_context(&pctx);
5492 bad_dir = 0;
5493 pctx.dir = dx_dir->ino;
5494 dx_db = dx_dir->dx_block;
5495 if (dx_db->flags & DX_FLAG_REFERENCED)
5496 dx_db->flags |= DX_FLAG_DUP_REF;
5497 else
5498 dx_db->flags |= DX_FLAG_REFERENCED;
5499 /*
5500 * Find all of the first and last leaf blocks, and
5501 * update their parent's min and max hash values
5502 */
5503 for (b=0, dx_db = dx_dir->dx_block;
5504 b < dx_dir->numblocks;
5505 b++, dx_db++) {
5506 if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
5507 !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
5508 continue;
5509 dx_parent = &dx_dir->dx_block[dx_db->parent];
5510 /*
5511 * XXX Make sure dx_parent->min_hash > dx_db->min_hash
5512 */
5513 if (dx_db->flags & DX_FLAG_FIRST)
5514 dx_parent->min_hash = dx_db->min_hash;
5515 /*
5516 * XXX Make sure dx_parent->max_hash < dx_db->max_hash
5517 */
5518 if (dx_db->flags & DX_FLAG_LAST)
5519 dx_parent->max_hash = dx_db->max_hash;
5520 }
5521
5522 for (b=0, dx_db = dx_dir->dx_block;
5523 b < dx_dir->numblocks;
5524 b++, dx_db++) {
5525 pctx.blkcount = b;
5526 pctx.group = dx_db->parent;
5527 code = 0;
5528 if (!(dx_db->flags & DX_FLAG_FIRST) &&
5529 (dx_db->min_hash < dx_db->node_min_hash)) {
5530 pctx.blk = dx_db->min_hash;
5531 pctx.blk2 = dx_db->node_min_hash;
5532 code = PR_2_HTREE_MIN_HASH;
5533 fix_problem(ctx, code, &pctx);
5534 bad_dir++;
5535 }
5536 if (dx_db->type == DX_DIRBLOCK_LEAF) {
5537 depth = htree_depth(dx_dir, dx_db);
5538 if (depth != dx_dir->depth) {
5539 code = PR_2_HTREE_BAD_DEPTH;
5540 fix_problem(ctx, code, &pctx);
5541 bad_dir++;
5542 }
5543 }
5544 /*
5545 * This test doesn't apply for the root block
5546 * at block #0
5547 */
5548 if (b &&
5549 (dx_db->max_hash > dx_db->node_max_hash)) {
5550 pctx.blk = dx_db->max_hash;
5551 pctx.blk2 = dx_db->node_max_hash;
5552 code = PR_2_HTREE_MAX_HASH;
5553 fix_problem(ctx, code, &pctx);
5554 bad_dir++;
5555 }
5556 if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
5557 code = PR_2_HTREE_NOTREF;
5558 fix_problem(ctx, code, &pctx);
5559 bad_dir++;
5560 } else if (dx_db->flags & DX_FLAG_DUP_REF) {
5561 code = PR_2_HTREE_DUPREF;
5562 fix_problem(ctx, code, &pctx);
5563 bad_dir++;
5564 }
5565 if (code == 0)
5566 continue;
5567 }
5568 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
5569 clear_htree(ctx, dx_dir->ino);
5570 dx_dir->numblocks = 0;
5571 }
5572 }
5573#endif
5574 ext2fs_free_mem(&buf);
5575 ext2fs_free_dblist(fs->dblist);
5576
5577 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
5578 ctx->inode_bad_map = 0;
5579 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
5580 ctx->inode_reg_map = 0;
5581
5582 clear_problem_context(&pctx);
5583 if (ctx->large_files) {
5584 if (!(sb->s_feature_ro_compat &
5585 EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
5586 fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
5587 sb->s_feature_ro_compat |=
5588 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5589 ext2fs_mark_super_dirty(fs);
5590 }
5591 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
5592 fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
5593 ext2fs_update_dynamic_rev(fs);
5594 ext2fs_mark_super_dirty(fs);
5595 }
5596 } else if (!ctx->large_files &&
5597 (sb->s_feature_ro_compat &
5598 EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
5599 if (fs->flags & EXT2_FLAG_RW) {
5600 sb->s_feature_ro_compat &=
5601 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5602 ext2fs_mark_super_dirty(fs);
5603 }
5604 }
5605}
5606
5607#define MAX_DEPTH 32000
5608static int htree_depth(struct dx_dir_info *dx_dir,
5609 struct dx_dirblock_info *dx_db)
5610{
5611 int depth = 0;
5612
5613 while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
5614 dx_db = &dx_dir->dx_block[dx_db->parent];
5615 depth++;
5616 }
5617 return depth;
5618}
5619
5620static int dict_de_cmp(const void *a, const void *b)
5621{
5622 const struct ext2_dir_entry *de_a, *de_b;
5623 int a_len, b_len;
5624
5625 de_a = (const struct ext2_dir_entry *) a;
5626 a_len = de_a->name_len & 0xFF;
5627 de_b = (const struct ext2_dir_entry *) b;
5628 b_len = de_b->name_len & 0xFF;
5629
5630 if (a_len != b_len)
5631 return (a_len - b_len);
5632
5633 return strncmp(de_a->name, de_b->name, a_len);
5634}
5635
5636/*
5637 * This is special sort function that makes sure that directory blocks
5638 * with a dirblock of zero are sorted to the beginning of the list.
5639 * This guarantees that the root node of the htree directories are
5640 * processed first, so we know what hash version to use.
5641 */
5642static int special_dir_block_cmp(const void *a, const void *b)
5643{
5644 const struct ext2_db_entry *db_a =
5645 (const struct ext2_db_entry *) a;
5646 const struct ext2_db_entry *db_b =
5647 (const struct ext2_db_entry *) b;
5648
5649 if (db_a->blockcnt && !db_b->blockcnt)
5650 return 1;
5651
5652 if (!db_a->blockcnt && db_b->blockcnt)
5653 return -1;
5654
5655 if (db_a->blk != db_b->blk)
5656 return (int) (db_a->blk - db_b->blk);
5657
5658 if (db_a->ino != db_b->ino)
5659 return (int) (db_a->ino - db_b->ino);
5660
5661 return (int) (db_a->blockcnt - db_b->blockcnt);
5662}
5663
5664
5665/*
5666 * Make sure the first entry in the directory is '.', and that the
5667 * directory entry is sane.
5668 */
5669static int check_dot(e2fsck_t ctx,
5670 struct ext2_dir_entry *dirent,
5671 ext2_ino_t ino, struct problem_context *pctx)
5672{
5673 struct ext2_dir_entry *nextdir;
5674 int status = 0;
5675 int created = 0;
5676 int new_len;
5677 int problem = 0;
5678
5679 if (!dirent->inode)
5680 problem = PR_2_MISSING_DOT;
5681 else if (((dirent->name_len & 0xFF) != 1) ||
5682 (dirent->name[0] != '.'))
5683 problem = PR_2_1ST_NOT_DOT;
5684 else if (dirent->name[1] != '\0')
5685 problem = PR_2_DOT_NULL_TERM;
5686
5687 if (problem) {
5688 if (fix_problem(ctx, problem, pctx)) {
5689 if (dirent->rec_len < 12)
5690 dirent->rec_len = 12;
5691 dirent->inode = ino;
5692 dirent->name_len = 1;
5693 dirent->name[0] = '.';
5694 dirent->name[1] = '\0';
5695 status = 1;
5696 created = 1;
5697 }
5698 }
5699 if (dirent->inode != ino) {
5700 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
5701 dirent->inode = ino;
5702 status = 1;
5703 }
5704 }
5705 if (dirent->rec_len > 12) {
5706 new_len = dirent->rec_len - 12;
5707 if (new_len > 12) {
5708 if (created ||
5709 fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
5710 nextdir = (struct ext2_dir_entry *)
5711 ((char *) dirent + 12);
5712 dirent->rec_len = 12;
5713 nextdir->rec_len = new_len;
5714 nextdir->inode = 0;
5715 nextdir->name_len = 0;
5716 status = 1;
5717 }
5718 }
5719 }
5720 return status;
5721}
5722
5723/*
5724 * Make sure the second entry in the directory is '..', and that the
5725 * directory entry is sane. We do not check the inode number of '..'
5726 * here; this gets done in pass 3.
5727 */
5728static int check_dotdot(e2fsck_t ctx,
5729 struct ext2_dir_entry *dirent,
5730 struct dir_info *dir, struct problem_context *pctx)
5731{
5732 int problem = 0;
5733
5734 if (!dirent->inode)
5735 problem = PR_2_MISSING_DOT_DOT;
5736 else if (((dirent->name_len & 0xFF) != 2) ||
5737 (dirent->name[0] != '.') ||
5738 (dirent->name[1] != '.'))
5739 problem = PR_2_2ND_NOT_DOT_DOT;
5740 else if (dirent->name[2] != '\0')
5741 problem = PR_2_DOT_DOT_NULL_TERM;
5742
5743 if (problem) {
5744 if (fix_problem(ctx, problem, pctx)) {
5745 if (dirent->rec_len < 12)
5746 dirent->rec_len = 12;
5747 /*
5748 * Note: we don't have the parent inode just
5749 * yet, so we will fill it in with the root
5750 * inode. This will get fixed in pass 3.
5751 */
5752 dirent->inode = EXT2_ROOT_INO;
5753 dirent->name_len = 2;
5754 dirent->name[0] = '.';
5755 dirent->name[1] = '.';
5756 dirent->name[2] = '\0';
5757 return 1;
5758 }
5759 return 0;
5760 }
5761 dir->dotdot = dirent->inode;
5762 return 0;
5763}
5764
5765/*
5766 * Check to make sure a directory entry doesn't contain any illegal
5767 * characters.
5768 */
5769static int check_name(e2fsck_t ctx,
5770 struct ext2_dir_entry *dirent,
5771 struct problem_context *pctx)
5772{
5773 int i;
5774 int fixup = -1;
5775 int ret = 0;
5776
5777 for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
5778 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
5779 if (fixup < 0) {
5780 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
5781 }
5782 if (fixup) {
5783 dirent->name[i] = '.';
5784 ret = 1;
5785 }
5786 }
5787 }
5788 return ret;
5789}
5790
5791/*
5792 * Check the directory filetype (if present)
5793 */
5794
5795/*
5796 * Given a mode, return the ext2 file type
5797 */
5798static int ext2_file_type(unsigned int mode)
5799{
5800 if (LINUX_S_ISREG(mode))
5801 return EXT2_FT_REG_FILE;
5802
5803 if (LINUX_S_ISDIR(mode))
5804 return EXT2_FT_DIR;
5805
5806 if (LINUX_S_ISCHR(mode))
5807 return EXT2_FT_CHRDEV;
5808
5809 if (LINUX_S_ISBLK(mode))
5810 return EXT2_FT_BLKDEV;
5811
5812 if (LINUX_S_ISLNK(mode))
5813 return EXT2_FT_SYMLINK;
5814
5815 if (LINUX_S_ISFIFO(mode))
5816 return EXT2_FT_FIFO;
5817
5818 if (LINUX_S_ISSOCK(mode))
5819 return EXT2_FT_SOCK;
5820
5821 return 0;
5822}
5823
5824static int check_filetype(e2fsck_t ctx,
5825 struct ext2_dir_entry *dirent,
5826 struct problem_context *pctx)
5827{
5828 int filetype = dirent->name_len >> 8;
5829 int should_be = EXT2_FT_UNKNOWN;
5830 struct ext2_inode inode;
5831
5832 if (!(ctx->fs->super->s_feature_incompat &
5833 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
5834 if (filetype == 0 ||
5835 !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
5836 return 0;
5837 dirent->name_len = dirent->name_len & 0xFF;
5838 return 1;
5839 }
5840
5841 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
5842 should_be = EXT2_FT_DIR;
5843 } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
5844 dirent->inode)) {
5845 should_be = EXT2_FT_REG_FILE;
5846 } else if (ctx->inode_bad_map &&
5847 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
5848 dirent->inode))
5849 should_be = 0;
5850 else {
5851 e2fsck_read_inode(ctx, dirent->inode, &inode,
5852 "check_filetype");
5853 should_be = ext2_file_type(inode.i_mode);
5854 }
5855 if (filetype == should_be)
5856 return 0;
5857 pctx->num = should_be;
5858
5859 if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
5860 pctx) == 0)
5861 return 0;
5862
5863 dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
5864 return 1;
5865}
5866
5867#ifdef ENABLE_HTREE
5868static void parse_int_node(ext2_filsys fs,
5869 struct ext2_db_entry *db,
5870 struct check_dir_struct *cd,
5871 struct dx_dir_info *dx_dir,
5872 char *block_buf)
5873{
5874 struct ext2_dx_root_info *root;
5875 struct ext2_dx_entry *ent;
5876 struct ext2_dx_countlimit *limit;
5877 struct dx_dirblock_info *dx_db;
5878 int i, expect_limit, count;
5879 blk_t blk;
5880 ext2_dirhash_t min_hash = 0xffffffff;
5881 ext2_dirhash_t max_hash = 0;
5882 ext2_dirhash_t hash = 0, prev_hash;
5883
5884 if (db->blockcnt == 0) {
5885 root = (struct ext2_dx_root_info *) (block_buf + 24);
5886 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
5887 } else {
5888 ent = (struct ext2_dx_entry *) (block_buf+8);
5889 }
5890 limit = (struct ext2_dx_countlimit *) ent;
5891
5892 count = ext2fs_le16_to_cpu(limit->count);
5893 expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
5894 sizeof(struct ext2_dx_entry);
5895 if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
5896 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
5897 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
5898 goto clear_and_exit;
5899 }
5900 if (count > expect_limit) {
5901 cd->pctx.num = count;
5902 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
5903 goto clear_and_exit;
5904 count = expect_limit;
5905 }
5906
5907 for (i=0; i < count; i++) {
5908 prev_hash = hash;
5909 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
5910 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
5911 /* Check to make sure the block is valid */
5912 if (blk > (blk_t) dx_dir->numblocks) {
5913 cd->pctx.blk = blk;
5914 if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
5915 &cd->pctx))
5916 goto clear_and_exit;
5917 }
5918 if (hash < prev_hash &&
5919 fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
5920 goto clear_and_exit;
5921 dx_db = &dx_dir->dx_block[blk];
5922 if (dx_db->flags & DX_FLAG_REFERENCED) {
5923 dx_db->flags |= DX_FLAG_DUP_REF;
5924 } else {
5925 dx_db->flags |= DX_FLAG_REFERENCED;
5926 dx_db->parent = db->blockcnt;
5927 }
5928 if (hash < min_hash)
5929 min_hash = hash;
5930 if (hash > max_hash)
5931 max_hash = hash;
5932 dx_db->node_min_hash = hash;
5933 if ((i+1) < count)
5934 dx_db->node_max_hash =
5935 ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
5936 else {
5937 dx_db->node_max_hash = 0xfffffffe;
5938 dx_db->flags |= DX_FLAG_LAST;
5939 }
5940 if (i == 0)
5941 dx_db->flags |= DX_FLAG_FIRST;
5942 }
5943 dx_db = &dx_dir->dx_block[db->blockcnt];
5944 dx_db->min_hash = min_hash;
5945 dx_db->max_hash = max_hash;
5946 return;
5947
5948clear_and_exit:
5949 clear_htree(cd->ctx, cd->pctx.ino);
5950 dx_dir->numblocks = 0;
5951}
5952#endif /* ENABLE_HTREE */
5953
5954/*
5955 * Given a busted directory, try to salvage it somehow.
5956 *
5957 */
5958static void salvage_directory(ext2_filsys fs,
5959 struct ext2_dir_entry *dirent,
5960 struct ext2_dir_entry *prev,
5961 unsigned int *offset)
5962{
5963 char *cp = (char *) dirent;
5964 int left = fs->blocksize - *offset - dirent->rec_len;
5965 int name_len = dirent->name_len & 0xFF;
5966
5967 /*
5968 * Special case of directory entry of size 8: copy what's left
5969 * of the directory block up to cover up the invalid hole.
5970 */
5971 if ((left >= 12) && (dirent->rec_len == 8)) {
5972 memmove(cp, cp+8, left);
5973 memset(cp + left, 0, 8);
5974 return;
5975 }
5976 /*
5977 * If the directory entry overruns the end of the directory
5978 * block, and the name is small enough to fit, then adjust the
5979 * record length.
5980 */
5981 if ((left < 0) &&
5982 (name_len + 8 <= dirent->rec_len + left) &&
5983 dirent->inode <= fs->super->s_inodes_count &&
5984 strnlen(dirent->name, name_len) == name_len) {
5985 dirent->rec_len += left;
5986 return;
5987 }
5988 /*
5989 * If the directory entry is a multiple of four, so it is
5990 * valid, let the previous directory entry absorb the invalid
5991 * one.
5992 */
5993 if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
5994 prev->rec_len += dirent->rec_len;
5995 *offset += dirent->rec_len;
5996 return;
5997 }
5998 /*
5999 * Default salvage method --- kill all of the directory
6000 * entries for the rest of the block. We will either try to
6001 * absorb it into the previous directory entry, or create a
6002 * new empty directory entry the rest of the directory block.
6003 */
6004 if (prev) {
6005 prev->rec_len += fs->blocksize - *offset;
6006 *offset = fs->blocksize;
6007 } else {
6008 dirent->rec_len = fs->blocksize - *offset;
6009 dirent->name_len = 0;
6010 dirent->inode = 0;
6011 }
6012}
6013
6014static int check_dir_block(ext2_filsys fs,
6015 struct ext2_db_entry *db,
6016 void *priv_data)
6017{
6018 struct dir_info *subdir, *dir;
6019 struct dx_dir_info *dx_dir;
6020#ifdef ENABLE_HTREE
6021 struct dx_dirblock_info *dx_db = NULL;
6022#endif /* ENABLE_HTREE */
6023 struct ext2_dir_entry *dirent, *prev;
6024 ext2_dirhash_t hash;
6025 unsigned int offset = 0;
6026 int dir_modified = 0;
6027 int dot_state;
6028 blk_t block_nr = db->blk;
6029 ext2_ino_t ino = db->ino;
6030 __u16 links;
6031 struct check_dir_struct *cd;
6032 char *buf;
6033 e2fsck_t ctx;
6034 int problem;
6035 struct ext2_dx_root_info *root;
6036 struct ext2_dx_countlimit *limit;
6037 static dict_t de_dict;
6038 struct problem_context pctx;
6039 int dups_found = 0;
6040
6041 cd = (struct check_dir_struct *) priv_data;
6042 buf = cd->buf;
6043 ctx = cd->ctx;
6044
6045 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6046 return DIRENT_ABORT;
6047
6048 if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
6049 return DIRENT_ABORT;
6050
6051 /*
6052 * Make sure the inode is still in use (could have been
6053 * deleted in the duplicate/bad blocks pass.
6054 */
6055 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
6056 return 0;
6057
6058 cd->pctx.ino = ino;
6059 cd->pctx.blk = block_nr;
6060 cd->pctx.blkcount = db->blockcnt;
6061 cd->pctx.ino2 = 0;
6062 cd->pctx.dirent = 0;
6063 cd->pctx.num = 0;
6064
6065 if (db->blk == 0) {
6066 if (allocate_dir_block(ctx, db, &cd->pctx))
6067 return 0;
6068 block_nr = db->blk;
6069 }
6070
6071 if (db->blockcnt)
6072 dot_state = 2;
6073 else
6074 dot_state = 0;
6075
6076 if (ctx->dirs_to_hash &&
6077 ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
6078 dups_found++;
6079
6080 cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
6081 if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
6082 cd->pctx.errcode = 0; /* We'll handle this ourselves */
6083 if (cd->pctx.errcode) {
6084 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
6085 ctx->flags |= E2F_FLAG_ABORT;
6086 return DIRENT_ABORT;
6087 }
6088 memset(buf, 0, fs->blocksize);
6089 }
6090#ifdef ENABLE_HTREE
6091 dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
6092 if (dx_dir && dx_dir->numblocks) {
6093 if (db->blockcnt >= dx_dir->numblocks) {
6094 printf("XXX should never happen!!!\n");
6095 abort();
6096 }
6097 dx_db = &dx_dir->dx_block[db->blockcnt];
6098 dx_db->type = DX_DIRBLOCK_LEAF;
6099 dx_db->phys = block_nr;
6100 dx_db->min_hash = ~0;
6101 dx_db->max_hash = 0;
6102
6103 dirent = (struct ext2_dir_entry *) buf;
6104 limit = (struct ext2_dx_countlimit *) (buf+8);
6105 if (db->blockcnt == 0) {
6106 root = (struct ext2_dx_root_info *) (buf + 24);
6107 dx_db->type = DX_DIRBLOCK_ROOT;
6108 dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
6109 if ((root->reserved_zero ||
6110 root->info_length < 8 ||
6111 root->indirect_levels > 1) &&
6112 fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
6113 clear_htree(ctx, ino);
6114 dx_dir->numblocks = 0;
6115 dx_db = 0;
6116 }
6117 dx_dir->hashversion = root->hash_version;
6118 dx_dir->depth = root->indirect_levels + 1;
6119 } else if ((dirent->inode == 0) &&
6120 (dirent->rec_len == fs->blocksize) &&
6121 (dirent->name_len == 0) &&
6122 (ext2fs_le16_to_cpu(limit->limit) ==
6123 ((fs->blocksize-8) /
6124 sizeof(struct ext2_dx_entry))))
6125 dx_db->type = DX_DIRBLOCK_NODE;
6126 }
6127#endif /* ENABLE_HTREE */
6128
6129 dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
6130 prev = 0;
6131 do {
6132 problem = 0;
6133 dirent = (struct ext2_dir_entry *) (buf + offset);
6134 cd->pctx.dirent = dirent;
6135 cd->pctx.num = offset;
6136 if (((offset + dirent->rec_len) > fs->blocksize) ||
6137 (dirent->rec_len < 12) ||
6138 ((dirent->rec_len % 4) != 0) ||
6139 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
6140 if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
6141 salvage_directory(fs, dirent, prev, &offset);
6142 dir_modified++;
6143 continue;
6144 } else
6145 goto abort_free_dict;
6146 }
6147 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
6148 if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
6149 dirent->name_len = EXT2_NAME_LEN;
6150 dir_modified++;
6151 }
6152 }
6153
6154 if (dot_state == 0) {
6155 if (check_dot(ctx, dirent, ino, &cd->pctx))
6156 dir_modified++;
6157 } else if (dot_state == 1) {
6158 dir = e2fsck_get_dir_info(ctx, ino);
6159 if (!dir) {
6160 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6161 goto abort_free_dict;
6162 }
6163 if (check_dotdot(ctx, dirent, dir, &cd->pctx))
6164 dir_modified++;
6165 } else if (dirent->inode == ino) {
6166 problem = PR_2_LINK_DOT;
6167 if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
6168 dirent->inode = 0;
6169 dir_modified++;
6170 goto next;
6171 }
6172 }
6173 if (!dirent->inode)
6174 goto next;
6175
6176 /*
6177 * Make sure the inode listed is a legal one.
6178 */
6179 if (((dirent->inode != EXT2_ROOT_INO) &&
6180 (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
6181 (dirent->inode > fs->super->s_inodes_count)) {
6182 problem = PR_2_BAD_INO;
6183 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
6184 dirent->inode))) {
6185 /*
6186 * If the inode is unused, offer to clear it.
6187 */
6188 problem = PR_2_UNUSED_INODE;
6189 } else if ((dot_state > 1) &&
6190 ((dirent->name_len & 0xFF) == 1) &&
6191 (dirent->name[0] == '.')) {
6192 /*
6193 * If there's a '.' entry in anything other
6194 * than the first directory entry, it's a
6195 * duplicate entry that should be removed.
6196 */
6197 problem = PR_2_DUP_DOT;
6198 } else if ((dot_state > 1) &&
6199 ((dirent->name_len & 0xFF) == 2) &&
6200 (dirent->name[0] == '.') &&
6201 (dirent->name[1] == '.')) {
6202 /*
6203 * If there's a '..' entry in anything other
6204 * than the second directory entry, it's a
6205 * duplicate entry that should be removed.
6206 */
6207 problem = PR_2_DUP_DOT_DOT;
6208 } else if ((dot_state > 1) &&
6209 (dirent->inode == EXT2_ROOT_INO)) {
6210 /*
6211 * Don't allow links to the root directory.
6212 * We check this specially to make sure we
6213 * catch this error case even if the root
6214 * directory hasn't been created yet.
6215 */
6216 problem = PR_2_LINK_ROOT;
6217 } else if ((dot_state > 1) &&
6218 (dirent->name_len & 0xFF) == 0) {
6219 /*
6220 * Don't allow zero-length directory names.
6221 */
6222 problem = PR_2_NULL_NAME;
6223 }
6224
6225 if (problem) {
6226 if (fix_problem(ctx, problem, &cd->pctx)) {
6227 dirent->inode = 0;
6228 dir_modified++;
6229 goto next;
6230 } else {
6231 ext2fs_unmark_valid(fs);
6232 if (problem == PR_2_BAD_INO)
6233 goto next;
6234 }
6235 }
6236
6237 /*
6238 * If the inode was marked as having bad fields in
6239 * pass1, process it and offer to fix/clear it.
6240 * (We wait until now so that we can display the
6241 * pathname to the user.)
6242 */
6243 if (ctx->inode_bad_map &&
6244 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
6245 dirent->inode)) {
6246 if (e2fsck_process_bad_inode(ctx, ino,
6247 dirent->inode,
6248 buf + fs->blocksize)) {
6249 dirent->inode = 0;
6250 dir_modified++;
6251 goto next;
6252 }
6253 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6254 return DIRENT_ABORT;
6255 }
6256
6257 if (check_name(ctx, dirent, &cd->pctx))
6258 dir_modified++;
6259
6260 if (check_filetype(ctx, dirent, &cd->pctx))
6261 dir_modified++;
6262
6263#ifdef ENABLE_HTREE
6264 if (dx_db) {
6265 ext2fs_dirhash(dx_dir->hashversion, dirent->name,
6266 (dirent->name_len & 0xFF),
6267 fs->super->s_hash_seed, &hash, 0);
6268 if (hash < dx_db->min_hash)
6269 dx_db->min_hash = hash;
6270 if (hash > dx_db->max_hash)
6271 dx_db->max_hash = hash;
6272 }
6273#endif
6274
6275 /*
6276 * If this is a directory, then mark its parent in its
6277 * dir_info structure. If the parent field is already
6278 * filled in, then this directory has more than one
6279 * hard link. We assume the first link is correct,
6280 * and ask the user if he/she wants to clear this one.
6281 */
6282 if ((dot_state > 1) &&
6283 (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6284 dirent->inode))) {
6285 subdir = e2fsck_get_dir_info(ctx, dirent->inode);
6286 if (!subdir) {
6287 cd->pctx.ino = dirent->inode;
6288 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6289 goto abort_free_dict;
6290 }
6291 if (subdir->parent) {
6292 cd->pctx.ino2 = subdir->parent;
6293 if (fix_problem(ctx, PR_2_LINK_DIR,
6294 &cd->pctx)) {
6295 dirent->inode = 0;
6296 dir_modified++;
6297 goto next;
6298 }
6299 cd->pctx.ino2 = 0;
6300 } else
6301 subdir->parent = ino;
6302 }
6303
6304 if (dups_found) {
6305 ;
6306 } else if (dict_lookup(&de_dict, dirent)) {
6307 clear_problem_context(&pctx);
6308 pctx.ino = ino;
6309 pctx.dirent = dirent;
6310 fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
6311 if (!ctx->dirs_to_hash)
6312 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
6313 if (ctx->dirs_to_hash)
6314 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6315 dups_found++;
6316 } else
6317 dict_alloc_insert(&de_dict, dirent, dirent);
6318
6319 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
6320 &links);
6321 if (links > 1)
6322 ctx->fs_links_count++;
6323 ctx->fs_total_count++;
6324 next:
6325 prev = dirent;
6326 offset += dirent->rec_len;
6327 dot_state++;
6328 } while (offset < fs->blocksize);
6329#ifdef ENABLE_HTREE
6330 if (dx_db) {
6331 cd->pctx.dir = cd->pctx.ino;
6332 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
6333 (dx_db->type == DX_DIRBLOCK_NODE))
6334 parse_int_node(fs, db, cd, dx_dir, buf);
6335 }
6336#endif /* ENABLE_HTREE */
6337 if (offset != fs->blocksize) {
6338 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
6339 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
6340 dirent->rec_len = cd->pctx.num;
6341 dir_modified++;
6342 }
6343 }
6344 if (dir_modified) {
6345 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
6346 if (cd->pctx.errcode) {
6347 if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
6348 &cd->pctx))
6349 goto abort_free_dict;
6350 }
6351 ext2fs_mark_changed(fs);
6352 }
6353 dict_free_nodes(&de_dict);
6354 return 0;
6355abort_free_dict:
6356 dict_free_nodes(&de_dict);
6357 ctx->flags |= E2F_FLAG_ABORT;
6358 return DIRENT_ABORT;
6359}
6360
6361/*
6362 * This function is called to deallocate a block, and is an interator
6363 * functioned called by deallocate inode via ext2fs_iterate_block().
6364 */
6365static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
6366 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6367 blk_t ref_block FSCK_ATTR((unused)),
6368 int ref_offset FSCK_ATTR((unused)),
6369 void *priv_data)
6370{
6371 e2fsck_t ctx = (e2fsck_t) priv_data;
6372
6373 if (HOLE_BLKADDR(*block_nr))
6374 return 0;
6375 if ((*block_nr < fs->super->s_first_data_block) ||
6376 (*block_nr >= fs->super->s_blocks_count))
6377 return 0;
6378 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6379 ext2fs_block_alloc_stats(fs, *block_nr, -1);
6380 return 0;
6381}
6382
6383/*
6384 * This function deallocates an inode
6385 */
6386static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
6387{
6388 ext2_filsys fs = ctx->fs;
6389 struct ext2_inode inode;
6390 struct problem_context pctx;
6391 __u32 count;
6392
6393 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
6394 e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
6395 inode.i_links_count = 0;
6396 inode.i_dtime = time(NULL);
6397 e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
6398 clear_problem_context(&pctx);
6399 pctx.ino = ino;
6400
6401 /*
6402 * Fix up the bitmaps...
6403 */
6404 e2fsck_read_bitmaps(ctx);
6405 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6406 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6407 if (ctx->inode_bad_map)
6408 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6409 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6410
6411 if (inode.i_file_acl &&
6412 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6413 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6414 block_buf, -1, &count);
6415 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6416 pctx.errcode = 0;
6417 count = 1;
6418 }
6419 if (pctx.errcode) {
6420 pctx.blk = inode.i_file_acl;
6421 fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
6422 ctx->flags |= E2F_FLAG_ABORT;
6423 return;
6424 }
6425 if (count == 0) {
6426 ext2fs_unmark_block_bitmap(ctx->block_found_map,
6427 inode.i_file_acl);
6428 ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
6429 }
6430 inode.i_file_acl = 0;
6431 }
6432
6433 if (!ext2fs_inode_has_valid_blocks(&inode))
6434 return;
6435
6436 if (LINUX_S_ISREG(inode.i_mode) &&
6437 (inode.i_size_high || inode.i_size & 0x80000000UL))
6438 ctx->large_files--;
6439
6440 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6441 deallocate_inode_block, ctx);
6442 if (pctx.errcode) {
6443 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
6444 ctx->flags |= E2F_FLAG_ABORT;
6445 return;
6446 }
6447}
6448
6449/*
6450 * This function clears the htree flag on an inode
6451 */
6452static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
6453{
6454 struct ext2_inode inode;
6455
6456 e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
6457 inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
6458 e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
6459 if (ctx->dirs_to_hash)
6460 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6461}
6462
6463
6464static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
6465 ext2_ino_t ino, char *buf)
6466{
6467 ext2_filsys fs = ctx->fs;
6468 struct ext2_inode inode;
6469 int inode_modified = 0;
6470 int not_fixed = 0;
6471 unsigned char *frag, *fsize;
6472 struct problem_context pctx;
6473 int problem = 0;
6474
6475 e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
6476
6477 clear_problem_context(&pctx);
6478 pctx.ino = ino;
6479 pctx.dir = dir;
6480 pctx.inode = &inode;
6481
6482 if (inode.i_file_acl &&
6483 !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
6484 fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
6485 inode.i_file_acl = 0;
6486#if BB_BIG_ENDIAN
6487 /*
6488 * This is a special kludge to deal with long symlinks
6489 * on big endian systems. i_blocks had already been
6490 * decremented earlier in pass 1, but since i_file_acl
6491 * hadn't yet been cleared, ext2fs_read_inode()
6492 * assumed that the file was short symlink and would
6493 * not have byte swapped i_block[0]. Hence, we have
6494 * to byte-swap it here.
6495 */
6496 if (LINUX_S_ISLNK(inode.i_mode) &&
6497 (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
6498 (inode.i_blocks == fs->blocksize >> 9))
6499 inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
6500#endif
6501 inode_modified++;
6502 } else
6503 not_fixed++;
6504
6505 if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
6506 !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
6507 !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
6508 !(LINUX_S_ISSOCK(inode.i_mode)))
6509 problem = PR_2_BAD_MODE;
6510 else if (LINUX_S_ISCHR(inode.i_mode)
6511 && !e2fsck_pass1_check_device_inode(fs, &inode))
6512 problem = PR_2_BAD_CHAR_DEV;
6513 else if (LINUX_S_ISBLK(inode.i_mode)
6514 && !e2fsck_pass1_check_device_inode(fs, &inode))
6515 problem = PR_2_BAD_BLOCK_DEV;
6516 else if (LINUX_S_ISFIFO(inode.i_mode)
6517 && !e2fsck_pass1_check_device_inode(fs, &inode))
6518 problem = PR_2_BAD_FIFO;
6519 else if (LINUX_S_ISSOCK(inode.i_mode)
6520 && !e2fsck_pass1_check_device_inode(fs, &inode))
6521 problem = PR_2_BAD_SOCKET;
6522 else if (LINUX_S_ISLNK(inode.i_mode)
6523 && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
6524 problem = PR_2_INVALID_SYMLINK;
6525 }
6526
6527 if (problem) {
6528 if (fix_problem(ctx, problem, &pctx)) {
6529 deallocate_inode(ctx, ino, 0);
6530 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6531 return 0;
6532 return 1;
6533 } else
6534 not_fixed++;
6535 problem = 0;
6536 }
6537
6538 if (inode.i_faddr) {
6539 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
6540 inode.i_faddr = 0;
6541 inode_modified++;
6542 } else
6543 not_fixed++;
6544 }
6545
6546 switch (fs->super->s_creator_os) {
6547 case EXT2_OS_LINUX:
6548 frag = &inode.osd2.linux2.l_i_frag;
6549 fsize = &inode.osd2.linux2.l_i_fsize;
6550 break;
6551 case EXT2_OS_HURD:
6552 frag = &inode.osd2.hurd2.h_i_frag;
6553 fsize = &inode.osd2.hurd2.h_i_fsize;
6554 break;
6555 case EXT2_OS_MASIX:
6556 frag = &inode.osd2.masix2.m_i_frag;
6557 fsize = &inode.osd2.masix2.m_i_fsize;
6558 break;
6559 default:
6560 frag = fsize = 0;
6561 }
6562 if (frag && *frag) {
6563 pctx.num = *frag;
6564 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
6565 *frag = 0;
6566 inode_modified++;
6567 } else
6568 not_fixed++;
6569 pctx.num = 0;
6570 }
6571 if (fsize && *fsize) {
6572 pctx.num = *fsize;
6573 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
6574 *fsize = 0;
6575 inode_modified++;
6576 } else
6577 not_fixed++;
6578 pctx.num = 0;
6579 }
6580
6581 if (inode.i_file_acl &&
6582 ((inode.i_file_acl < fs->super->s_first_data_block) ||
6583 (inode.i_file_acl >= fs->super->s_blocks_count))) {
6584 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
6585 inode.i_file_acl = 0;
6586 inode_modified++;
6587 } else
6588 not_fixed++;
6589 }
6590 if (inode.i_dir_acl &&
6591 LINUX_S_ISDIR(inode.i_mode)) {
6592 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
6593 inode.i_dir_acl = 0;
6594 inode_modified++;
6595 } else
6596 not_fixed++;
6597 }
6598
6599 if (inode_modified)
6600 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
6601 if (!not_fixed)
6602 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6603 return 0;
6604}
6605
6606
6607/*
6608 * allocate_dir_block --- this function allocates a new directory
6609 * block for a particular inode; this is done if a directory has
6610 * a "hole" in it, or if a directory has a illegal block number
6611 * that was zeroed out and now needs to be replaced.
6612 */
6613static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
6614 struct problem_context *pctx)
6615{
6616 ext2_filsys fs = ctx->fs;
6617 blk_t blk;
6618 char *block;
6619 struct ext2_inode inode;
6620
6621 if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
6622 return 1;
6623
6624 /*
6625 * Read the inode and block bitmaps in; we'll be messing with
6626 * them.
6627 */
6628 e2fsck_read_bitmaps(ctx);
6629
6630 /*
6631 * First, find a free block
6632 */
6633 pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6634 if (pctx->errcode) {
6635 pctx->str = "ext2fs_new_block";
6636 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6637 return 1;
6638 }
6639 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6640 ext2fs_mark_block_bitmap(fs->block_map, blk);
6641 ext2fs_mark_bb_dirty(fs);
6642
6643 /*
6644 * Now let's create the actual data block for the inode
6645 */
6646 if (db->blockcnt)
6647 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
6648 else
6649 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
6650 EXT2_ROOT_INO, &block);
6651
6652 if (pctx->errcode) {
6653 pctx->str = "ext2fs_new_dir_block";
6654 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6655 return 1;
6656 }
6657
6658 pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
6659 ext2fs_free_mem(&block);
6660 if (pctx->errcode) {
6661 pctx->str = "ext2fs_write_dir_block";
6662 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6663 return 1;
6664 }
6665
6666 /*
6667 * Update the inode block count
6668 */
6669 e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
6670 inode.i_blocks += fs->blocksize / 512;
6671 if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
6672 inode.i_size = (db->blockcnt+1) * fs->blocksize;
6673 e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
6674
6675 /*
6676 * Finally, update the block pointers for the inode
6677 */
6678 db->blk = blk;
6679 pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
6680 0, update_dir_block, db);
6681 if (pctx->errcode) {
6682 pctx->str = "ext2fs_block_iterate";
6683 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6684 return 1;
6685 }
6686
6687 return 0;
6688}
6689
6690/*
6691 * This is a helper function for allocate_dir_block().
6692 */
6693static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
6694 blk_t *block_nr,
6695 e2_blkcnt_t blockcnt,
6696 blk_t ref_block FSCK_ATTR((unused)),
6697 int ref_offset FSCK_ATTR((unused)),
6698 void *priv_data)
6699{
6700 struct ext2_db_entry *db;
6701
6702 db = (struct ext2_db_entry *) priv_data;
6703 if (db->blockcnt == (int) blockcnt) {
6704 *block_nr = db->blk;
6705 return BLOCK_CHANGED;
6706 }
6707 return 0;
6708}
6709
6710/*
6711 * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
6712 *
6713 * Pass #3 assures that all directories are connected to the
6714 * filesystem tree, using the following algorithm:
6715 *
6716 * First, the root directory is checked to make sure it exists; if
6717 * not, e2fsck will offer to create a new one. It is then marked as
6718 * "done".
6719 *
6720 * Then, pass3 interates over all directory inodes; for each directory
6721 * it attempts to trace up the filesystem tree, using dirinfo.parent
6722 * until it reaches a directory which has been marked "done". If it
6723 * cannot do so, then the directory must be disconnected, and e2fsck
6724 * will offer to reconnect it to /lost+found. While it is chasing
6725 * parent pointers up the filesystem tree, if pass3 sees a directory
6726 * twice, then it has detected a filesystem loop, and it will again
6727 * offer to reconnect the directory to /lost+found in to break the
6728 * filesystem loop.
6729 *
6730 * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
6731 * reconnect inodes to /lost+found; this subroutine is also used by
6732 * pass 4. e2fsck_reconnect_file() calls get_lost_and_found(), which
6733 * is responsible for creating /lost+found if it does not exist.
6734 *
6735 * Pass 3 frees the following data structures:
6736 * - The dirinfo directory information cache.
6737 */
6738
6739static void check_root(e2fsck_t ctx);
6740static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6741 struct problem_context *pctx);
6742static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
6743
6744static ext2fs_inode_bitmap inode_loop_detect;
6745static ext2fs_inode_bitmap inode_done_map;
6746
6747static void e2fsck_pass3(e2fsck_t ctx)
6748{
6749 ext2_filsys fs = ctx->fs;
6750 int i;
6751 struct problem_context pctx;
6752 struct dir_info *dir;
6753 unsigned long maxdirs, count;
6754
6755 clear_problem_context(&pctx);
6756
6757 /* Pass 3 */
6758
6759 if (!(ctx->options & E2F_OPT_PREEN))
6760 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
6761
6762 /*
6763 * Allocate some bitmaps to do loop detection.
6764 */
6765 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
6766 &inode_done_map);
6767 if (pctx.errcode) {
6768 pctx.num = 2;
6769 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
6770 ctx->flags |= E2F_FLAG_ABORT;
6771 goto abort_exit;
6772 }
6773 check_root(ctx);
6774 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6775 goto abort_exit;
6776
6777 ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
6778
6779 maxdirs = e2fsck_get_num_dirinfo(ctx);
6780 count = 1;
6781
6782 if (ctx->progress)
6783 if ((ctx->progress)(ctx, 3, 0, maxdirs))
6784 goto abort_exit;
6785
6786 for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
6787 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6788 goto abort_exit;
6789 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
6790 goto abort_exit;
6791 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
6792 if (check_directory(ctx, dir, &pctx))
6793 goto abort_exit;
6794 }
6795
6796 /*
6797 * Force the creation of /lost+found if not present
6798 */
6799 if ((ctx->flags & E2F_OPT_READONLY) == 0)
6800 e2fsck_get_lost_and_found(ctx, 1);
6801
6802 /*
6803 * If there are any directories that need to be indexed or
6804 * optimized, do it here.
6805 */
6806 e2fsck_rehash_directories(ctx);
6807
6808abort_exit:
6809 e2fsck_free_dir_info(ctx);
6810 ext2fs_free_inode_bitmap(inode_loop_detect);
6811 inode_loop_detect = 0;
6812 ext2fs_free_inode_bitmap(inode_done_map);
6813 inode_done_map = 0;
6814}
6815
6816/*
6817 * This makes sure the root inode is present; if not, we ask if the
6818 * user wants us to create it. Not creating it is a fatal error.
6819 */
6820static void check_root(e2fsck_t ctx)
6821{
6822 ext2_filsys fs = ctx->fs;
6823 blk_t blk;
6824 struct ext2_inode inode;
6825 char * block;
6826 struct problem_context pctx;
6827
6828 clear_problem_context(&pctx);
6829
6830 if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
6831 /*
6832 * If the root inode is not a directory, die here. The
6833 * user must have answered 'no' in pass1 when we
6834 * offered to clear it.
6835 */
6836 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6837 EXT2_ROOT_INO))) {
6838 fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
6839 ctx->flags |= E2F_FLAG_ABORT;
6840 }
6841 return;
6842 }
6843
6844 if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
6845 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
6846 ctx->flags |= E2F_FLAG_ABORT;
6847 return;
6848 }
6849
6850 e2fsck_read_bitmaps(ctx);
6851
6852 /*
6853 * First, find a free block
6854 */
6855 pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6856 if (pctx.errcode) {
6857 pctx.str = "ext2fs_new_block";
6858 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6859 ctx->flags |= E2F_FLAG_ABORT;
6860 return;
6861 }
6862 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6863 ext2fs_mark_block_bitmap(fs->block_map, blk);
6864 ext2fs_mark_bb_dirty(fs);
6865
6866 /*
6867 * Now let's create the actual data block for the inode
6868 */
6869 pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
6870 &block);
6871 if (pctx.errcode) {
6872 pctx.str = "ext2fs_new_dir_block";
6873 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6874 ctx->flags |= E2F_FLAG_ABORT;
6875 return;
6876 }
6877
6878 pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
6879 if (pctx.errcode) {
6880 pctx.str = "ext2fs_write_dir_block";
6881 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6882 ctx->flags |= E2F_FLAG_ABORT;
6883 return;
6884 }
6885 ext2fs_free_mem(&block);
6886
6887 /*
6888 * Set up the inode structure
6889 */
6890 memset(&inode, 0, sizeof(inode));
6891 inode.i_mode = 040755;
6892 inode.i_size = fs->blocksize;
6893 inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
6894 inode.i_links_count = 2;
6895 inode.i_blocks = fs->blocksize / 512;
6896 inode.i_block[0] = blk;
6897
6898 /*
6899 * Write out the inode.
6900 */
6901 pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
6902 if (pctx.errcode) {
6903 pctx.str = "ext2fs_write_inode";
6904 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6905 ctx->flags |= E2F_FLAG_ABORT;
6906 return;
6907 }
6908
6909 /*
6910 * Miscellaneous bookkeeping...
6911 */
6912 e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
6913 ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
6914 ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
6915
6916 ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
6917 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
6918 ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
6919 ext2fs_mark_ib_dirty(fs);
6920}
6921
6922/*
6923 * This subroutine is responsible for making sure that a particular
6924 * directory is connected to the root; if it isn't we trace it up as
6925 * far as we can go, and then offer to connect the resulting parent to
6926 * the lost+found. We have to do loop detection; if we ever discover
6927 * a loop, we treat that as a disconnected directory and offer to
6928 * reparent it to lost+found.
6929 *
6930 * However, loop detection is expensive, because for very large
6931 * filesystems, the inode_loop_detect bitmap is huge, and clearing it
6932 * is non-trivial. Loops in filesystems are also a rare error case,
6933 * and we shouldn't optimize for error cases. So we try two passes of
6934 * the algorithm. The first time, we ignore loop detection and merely
6935 * increment a counter; if the counter exceeds some extreme threshold,
6936 * then we try again with the loop detection bitmap enabled.
6937 */
6938static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6939 struct problem_context *pctx)
6940{
6941 ext2_filsys fs = ctx->fs;
6942 struct dir_info *p = dir;
6943 int loop_pass = 0, parent_count = 0;
6944
6945 if (!p)
6946 return 0;
6947
6948 while (1) {
6949 /*
6950 * Mark this inode as being "done"; by the time we
6951 * return from this function, the inode we either be
6952 * verified as being connected to the directory tree,
6953 * or we will have offered to reconnect this to
6954 * lost+found.
6955 *
6956 * If it was marked done already, then we've reached a
6957 * parent we've already checked.
6958 */
6959 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
6960 break;
6961
6962 /*
6963 * If this directory doesn't have a parent, or we've
6964 * seen the parent once already, then offer to
6965 * reparent it to lost+found
6966 */
6967 if (!p->parent ||
6968 (loop_pass &&
6969 (ext2fs_test_inode_bitmap(inode_loop_detect,
6970 p->parent)))) {
6971 pctx->ino = p->ino;
6972 if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
6973 if (e2fsck_reconnect_file(ctx, pctx->ino))
6974 ext2fs_unmark_valid(fs);
6975 else {
6976 p = e2fsck_get_dir_info(ctx, pctx->ino);
6977 p->parent = ctx->lost_and_found;
6978 fix_dotdot(ctx, p, ctx->lost_and_found);
6979 }
6980 }
6981 break;
6982 }
6983 p = e2fsck_get_dir_info(ctx, p->parent);
6984 if (!p) {
6985 fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
6986 return 0;
6987 }
6988 if (loop_pass) {
6989 ext2fs_mark_inode_bitmap(inode_loop_detect,
6990 p->ino);
6991 } else if (parent_count++ > 2048) {
6992 /*
6993 * If we've run into a path depth that's
6994 * greater than 2048, try again with the inode
6995 * loop bitmap turned on and start from the
6996 * top.
6997 */
6998 loop_pass = 1;
6999 if (inode_loop_detect)
7000 ext2fs_clear_inode_bitmap(inode_loop_detect);
7001 else {
7002 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
7003 if (pctx->errcode) {
7004 pctx->num = 1;
7005 fix_problem(ctx,
7006 PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
7007 ctx->flags |= E2F_FLAG_ABORT;
7008 return -1;
7009 }
7010 }
7011 p = dir;
7012 }
7013 }
7014
7015 /*
7016 * Make sure that .. and the parent directory are the same;
7017 * offer to fix it if not.
7018 */
7019 if (dir->parent != dir->dotdot) {
7020 pctx->ino = dir->ino;
7021 pctx->ino2 = dir->dotdot;
7022 pctx->dir = dir->parent;
7023 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
7024 fix_dotdot(ctx, dir, dir->parent);
7025 }
7026 return 0;
7027}
7028
7029/*
7030 * This routine gets the lost_and_found inode, making it a directory
7031 * if necessary
7032 */
7033ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
7034{
7035 ext2_filsys fs = ctx->fs;
7036 ext2_ino_t ino;
7037 blk_t blk;
7038 errcode_t retval;
7039 struct ext2_inode inode;
7040 char * block;
7041 static const char name[] = "lost+found";
7042 struct problem_context pctx;
7043 struct dir_info *dirinfo;
7044
7045 if (ctx->lost_and_found)
7046 return ctx->lost_and_found;
7047
7048 clear_problem_context(&pctx);
7049
7050 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
7051 sizeof(name)-1, 0, &ino);
7052 if (retval && !fix)
7053 return 0;
7054 if (!retval) {
7055 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
7056 ctx->lost_and_found = ino;
7057 return ino;
7058 }
7059
7060 /* Lost+found isn't a directory! */
7061 if (!fix)
7062 return 0;
7063 pctx.ino = ino;
7064 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
7065 return 0;
7066
7067 /* OK, unlink the old /lost+found file. */
7068 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
7069 if (pctx.errcode) {
7070 pctx.str = "ext2fs_unlink";
7071 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7072 return 0;
7073 }
7074 dirinfo = e2fsck_get_dir_info(ctx, ino);
7075 if (dirinfo)
7076 dirinfo->parent = 0;
7077 e2fsck_adjust_inode_count(ctx, ino, -1);
7078 } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
7079 pctx.errcode = retval;
7080 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
7081 }
7082 if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
7083 return 0;
7084
7085 /*
7086 * Read the inode and block bitmaps in; we'll be messing with
7087 * them.
7088 */
7089 e2fsck_read_bitmaps(ctx);
7090
7091 /*
7092 * First, find a free block
7093 */
7094 retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
7095 if (retval) {
7096 pctx.errcode = retval;
7097 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
7098 return 0;
7099 }
7100 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
7101 ext2fs_block_alloc_stats(fs, blk, +1);
7102
7103 /*
7104 * Next find a free inode.
7105 */
7106 retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
7107 ctx->inode_used_map, &ino);
7108 if (retval) {
7109 pctx.errcode = retval;
7110 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
7111 return 0;
7112 }
7113 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
7114 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
7115 ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
7116
7117 /*
7118 * Now let's create the actual data block for the inode
7119 */
7120 retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
7121 if (retval) {
7122 pctx.errcode = retval;
7123 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
7124 return 0;
7125 }
7126
7127 retval = ext2fs_write_dir_block(fs, blk, block);
7128 ext2fs_free_mem(&block);
7129 if (retval) {
7130 pctx.errcode = retval;
7131 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
7132 return 0;
7133 }
7134
7135 /*
7136 * Set up the inode structure
7137 */
7138 memset(&inode, 0, sizeof(inode));
7139 inode.i_mode = 040700;
7140 inode.i_size = fs->blocksize;
7141 inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
7142 inode.i_links_count = 2;
7143 inode.i_blocks = fs->blocksize / 512;
7144 inode.i_block[0] = blk;
7145
7146 /*
7147 * Next, write out the inode.
7148 */
7149 pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
7150 if (pctx.errcode) {
7151 pctx.str = "ext2fs_write_inode";
7152 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7153 return 0;
7154 }
7155 /*
7156 * Finally, create the directory link
7157 */
7158 pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
7159 if (pctx.errcode) {
7160 pctx.str = "ext2fs_link";
7161 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7162 return 0;
7163 }
7164
7165 /*
7166 * Miscellaneous bookkeeping that needs to be kept straight.
7167 */
7168 e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
7169 e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
7170 ext2fs_icount_store(ctx->inode_count, ino, 2);
7171 ext2fs_icount_store(ctx->inode_link_info, ino, 2);
7172 ctx->lost_and_found = ino;
7173 return ino;
7174}
7175
7176/*
7177 * This routine will connect a file to lost+found
7178 */
7179int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
7180{
7181 ext2_filsys fs = ctx->fs;
7182 errcode_t retval;
7183 char name[80];
7184 struct problem_context pctx;
7185 struct ext2_inode inode;
7186 int file_type = 0;
7187
7188 clear_problem_context(&pctx);
7189 pctx.ino = ino;
7190
7191 if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
7192 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
7193 ctx->bad_lost_and_found++;
7194 }
7195 if (ctx->bad_lost_and_found) {
7196 fix_problem(ctx, PR_3_NO_LPF, &pctx);
7197 return 1;
7198 }
7199
7200 sprintf(name, "#%u", ino);
7201 if (ext2fs_read_inode(fs, ino, &inode) == 0)
7202 file_type = ext2_file_type(inode.i_mode);
7203 retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
7204 if (retval == EXT2_ET_DIR_NO_SPACE) {
7205 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
7206 return 1;
7207 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
7208 1, 0);
7209 if (retval) {
7210 pctx.errcode = retval;
7211 fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
7212 return 1;
7213 }
7214 retval = ext2fs_link(fs, ctx->lost_and_found, name,
7215 ino, file_type);
7216 }
7217 if (retval) {
7218 pctx.errcode = retval;
7219 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
7220 return 1;
7221 }
7222 e2fsck_adjust_inode_count(ctx, ino, 1);
7223
7224 return 0;
7225}
7226
7227/*
7228 * Utility routine to adjust the inode counts on an inode.
7229 */
7230errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
7231{
7232 ext2_filsys fs = ctx->fs;
7233 errcode_t retval;
7234 struct ext2_inode inode;
7235
7236 if (!ino)
7237 return 0;
7238
7239 retval = ext2fs_read_inode(fs, ino, &inode);
7240 if (retval)
7241 return retval;
7242
7243 if (adj == 1) {
7244 ext2fs_icount_increment(ctx->inode_count, ino, 0);
7245 if (inode.i_links_count == (__u16) ~0)
7246 return 0;
7247 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
7248 inode.i_links_count++;
7249 } else if (adj == -1) {
7250 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
7251 if (inode.i_links_count == 0)
7252 return 0;
7253 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
7254 inode.i_links_count--;
7255 }
7256
7257 retval = ext2fs_write_inode(fs, ino, &inode);
7258 if (retval)
7259 return retval;
7260
7261 return 0;
7262}
7263
7264/*
7265 * Fix parent --- this routine fixes up the parent of a directory.
7266 */
7267struct fix_dotdot_struct {
7268 ext2_filsys fs;
7269 ext2_ino_t parent;
7270 int done;
7271 e2fsck_t ctx;
7272};
7273
7274static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
7275 int offset FSCK_ATTR((unused)),
7276 int blocksize FSCK_ATTR((unused)),
7277 char *buf FSCK_ATTR((unused)),
7278 void *priv_data)
7279{
7280 struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
7281 errcode_t retval;
7282 struct problem_context pctx;
7283
7284 if ((dirent->name_len & 0xFF) != 2)
7285 return 0;
7286 if (strncmp(dirent->name, "..", 2))
7287 return 0;
7288
7289 clear_problem_context(&pctx);
7290
7291 retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
7292 if (retval) {
7293 pctx.errcode = retval;
7294 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7295 }
7296 retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
7297 if (retval) {
7298 pctx.errcode = retval;
7299 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7300 }
7301 dirent->inode = fp->parent;
7302
7303 fp->done++;
7304 return DIRENT_ABORT | DIRENT_CHANGED;
7305}
7306
7307static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
7308{
7309 ext2_filsys fs = ctx->fs;
7310 errcode_t retval;
7311 struct fix_dotdot_struct fp;
7312 struct problem_context pctx;
7313
7314 fp.fs = fs;
7315 fp.parent = parent;
7316 fp.done = 0;
7317 fp.ctx = ctx;
7318
7319 retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
7320 0, fix_dotdot_proc, &fp);
7321 if (retval || !fp.done) {
7322 clear_problem_context(&pctx);
7323 pctx.ino = dir->ino;
7324 pctx.errcode = retval;
7325 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
7326 PR_3_FIX_PARENT_NOFIND, &pctx);
7327 ext2fs_unmark_valid(fs);
7328 }
7329 dir->dotdot = parent;
7330}
7331
7332/*
7333 * These routines are responsible for expanding a /lost+found if it is
7334 * too small.
7335 */
7336
7337struct expand_dir_struct {
7338 int num;
7339 int guaranteed_size;
7340 int newblocks;
7341 int last_block;
7342 errcode_t err;
7343 e2fsck_t ctx;
7344};
7345
7346static int expand_dir_proc(ext2_filsys fs,
7347 blk_t *blocknr,
7348 e2_blkcnt_t blockcnt,
7349 blk_t ref_block FSCK_ATTR((unused)),
7350 int ref_offset FSCK_ATTR((unused)),
7351 void *priv_data)
7352{
7353 struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
7354 blk_t new_blk;
7355 static blk_t last_blk = 0;
7356 char *block;
7357 errcode_t retval;
7358 e2fsck_t ctx;
7359
7360 ctx = es->ctx;
7361
7362 if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
7363 return BLOCK_ABORT;
7364
7365 if (blockcnt > 0)
7366 es->last_block = blockcnt;
7367 if (*blocknr) {
7368 last_blk = *blocknr;
7369 return 0;
7370 }
7371 retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
7372 &new_blk);
7373 if (retval) {
7374 es->err = retval;
7375 return BLOCK_ABORT;
7376 }
7377 if (blockcnt > 0) {
7378 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
7379 if (retval) {
7380 es->err = retval;
7381 return BLOCK_ABORT;
7382 }
7383 es->num--;
7384 retval = ext2fs_write_dir_block(fs, new_blk, block);
7385 } else {
7386 retval = ext2fs_get_mem(fs->blocksize, &block);
7387 if (retval) {
7388 es->err = retval;
7389 return BLOCK_ABORT;
7390 }
7391 memset(block, 0, fs->blocksize);
7392 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
7393 }
7394 if (retval) {
7395 es->err = retval;
7396 return BLOCK_ABORT;
7397 }
7398 ext2fs_free_mem(&block);
7399 *blocknr = new_blk;
7400 ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
7401 ext2fs_block_alloc_stats(fs, new_blk, +1);
7402 es->newblocks++;
7403
7404 if (es->num == 0)
7405 return (BLOCK_CHANGED | BLOCK_ABORT);
7406 else
7407 return BLOCK_CHANGED;
7408}
7409
7410errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
7411 int num, int guaranteed_size)
7412{
7413 ext2_filsys fs = ctx->fs;
7414 errcode_t retval;
7415 struct expand_dir_struct es;
7416 struct ext2_inode inode;
7417
7418 if (!(fs->flags & EXT2_FLAG_RW))
7419 return EXT2_ET_RO_FILSYS;
7420
7421 /*
7422 * Read the inode and block bitmaps in; we'll be messing with
7423 * them.
7424 */
7425 e2fsck_read_bitmaps(ctx);
7426
7427 retval = ext2fs_check_directory(fs, dir);
7428 if (retval)
7429 return retval;
7430
7431 es.num = num;
7432 es.guaranteed_size = guaranteed_size;
7433 es.last_block = 0;
7434 es.err = 0;
7435 es.newblocks = 0;
7436 es.ctx = ctx;
7437
7438 retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
7439 0, expand_dir_proc, &es);
7440
7441 if (es.err)
7442 return es.err;
7443
7444 /*
7445 * Update the size and block count fields in the inode.
7446 */
7447 retval = ext2fs_read_inode(fs, dir, &inode);
7448 if (retval)
7449 return retval;
7450
7451 inode.i_size = (es.last_block + 1) * fs->blocksize;
7452 inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
7453
7454 e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
7455
7456 return 0;
7457}
7458
7459/*
7460 * pass4.c -- pass #4 of e2fsck: Check reference counts
7461 *
7462 * Pass 4 frees the following data structures:
7463 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
7464 */
7465
7466/*
7467 * This routine is called when an inode is not connected to the
7468 * directory tree.
7469 *
7470 * This subroutine returns 1 then the caller shouldn't bother with the
7471 * rest of the pass 4 tests.
7472 */
7473static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
7474{
7475 ext2_filsys fs = ctx->fs;
7476 struct ext2_inode inode;
7477 struct problem_context pctx;
7478
7479 e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
7480 clear_problem_context(&pctx);
7481 pctx.ino = i;
7482 pctx.inode = &inode;
7483
7484 /*
7485 * Offer to delete any zero-length files that does not have
7486 * blocks. If there is an EA block, it might have useful
7487 * information, so we won't prompt to delete it, but let it be
7488 * reconnected to lost+found.
7489 */
7490 if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
7491 LINUX_S_ISDIR(inode.i_mode))) {
7492 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
7493 ext2fs_icount_store(ctx->inode_link_info, i, 0);
7494 inode.i_links_count = 0;
7495 inode.i_dtime = time(NULL);
7496 e2fsck_write_inode(ctx, i, &inode,
7497 "disconnect_inode");
7498 /*
7499 * Fix up the bitmaps...
7500 */
7501 e2fsck_read_bitmaps(ctx);
7502 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
7503 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
7504 ext2fs_inode_alloc_stats2(fs, i, -1,
7505 LINUX_S_ISDIR(inode.i_mode));
7506 return 0;
7507 }
7508 }
7509
7510 /*
7511 * Prompt to reconnect.
7512 */
7513 if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
7514 if (e2fsck_reconnect_file(ctx, i))
7515 ext2fs_unmark_valid(fs);
7516 } else {
7517 /*
7518 * If we don't attach the inode, then skip the
7519 * i_links_test since there's no point in trying to
7520 * force i_links_count to zero.
7521 */
7522 ext2fs_unmark_valid(fs);
7523 return 1;
7524 }
7525 return 0;
7526}
7527
7528
7529static void e2fsck_pass4(e2fsck_t ctx)
7530{
7531 ext2_filsys fs = ctx->fs;
7532 ext2_ino_t i;
7533 struct ext2_inode inode;
7534 struct problem_context pctx;
7535 __u16 link_count, link_counted;
7536 char *buf = NULL;
7537 int group, maxgroup;
7538
7539 /* Pass 4 */
7540
7541 clear_problem_context(&pctx);
7542
7543 if (!(ctx->options & E2F_OPT_PREEN))
7544 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
7545
7546 group = 0;
7547 maxgroup = fs->group_desc_count;
7548 if (ctx->progress)
7549 if ((ctx->progress)(ctx, 4, 0, maxgroup))
7550 return;
7551
7552 for (i=1; i <= fs->super->s_inodes_count; i++) {
7553 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7554 return;
7555 if ((i % fs->super->s_inodes_per_group) == 0) {
7556 group++;
7557 if (ctx->progress)
7558 if ((ctx->progress)(ctx, 4, group, maxgroup))
7559 return;
7560 }
7561 if (i == EXT2_BAD_INO ||
7562 (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
7563 continue;
7564 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
7565 (ctx->inode_imagic_map &&
7566 ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)))
7567 continue;
7568 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
7569 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
7570 if (link_counted == 0) {
7571 if (!buf)
7572 buf = e2fsck_allocate_memory(ctx,
7573 fs->blocksize, "bad_inode buffer");
7574 if (e2fsck_process_bad_inode(ctx, 0, i, buf))
7575 continue;
7576 if (disconnect_inode(ctx, i))
7577 continue;
7578 ext2fs_icount_fetch(ctx->inode_link_info, i,
7579 &link_count);
7580 ext2fs_icount_fetch(ctx->inode_count, i,
7581 &link_counted);
7582 }
7583 if (link_counted != link_count) {
7584 e2fsck_read_inode(ctx, i, &inode, "pass4");
7585 pctx.ino = i;
7586 pctx.inode = &inode;
7587 if (link_count != inode.i_links_count) {
7588 pctx.num = link_count;
7589 fix_problem(ctx,
7590 PR_4_INCONSISTENT_COUNT, &pctx);
7591 }
7592 pctx.num = link_counted;
7593 if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
7594 inode.i_links_count = link_counted;
7595 e2fsck_write_inode(ctx, i, &inode, "pass4");
7596 }
7597 }
7598 }
7599 ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
7600 ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
7601 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
7602 ctx->inode_imagic_map = 0;
7603 ext2fs_free_mem(&buf);
7604}
7605
7606/*
7607 * pass5.c --- check block and inode bitmaps against on-disk bitmaps
7608 */
7609
7610#define NO_BLK ((blk_t) -1)
7611
7612static void print_bitmap_problem(e2fsck_t ctx, int problem,
7613 struct problem_context *pctx)
7614{
7615 switch (problem) {
7616 case PR_5_BLOCK_UNUSED:
7617 if (pctx->blk == pctx->blk2)
7618 pctx->blk2 = 0;
7619 else
7620 problem = PR_5_BLOCK_RANGE_UNUSED;
7621 break;
7622 case PR_5_BLOCK_USED:
7623 if (pctx->blk == pctx->blk2)
7624 pctx->blk2 = 0;
7625 else
7626 problem = PR_5_BLOCK_RANGE_USED;
7627 break;
7628 case PR_5_INODE_UNUSED:
7629 if (pctx->ino == pctx->ino2)
7630 pctx->ino2 = 0;
7631 else
7632 problem = PR_5_INODE_RANGE_UNUSED;
7633 break;
7634 case PR_5_INODE_USED:
7635 if (pctx->ino == pctx->ino2)
7636 pctx->ino2 = 0;
7637 else
7638 problem = PR_5_INODE_RANGE_USED;
7639 break;
7640 }
7641 fix_problem(ctx, problem, pctx);
7642 pctx->blk = pctx->blk2 = NO_BLK;
7643 pctx->ino = pctx->ino2 = 0;
7644}
7645
7646static void check_block_bitmaps(e2fsck_t ctx)
7647{
7648 ext2_filsys fs = ctx->fs;
7649 blk_t i;
7650 int *free_array;
7651 int group = 0;
7652 unsigned int blocks = 0;
7653 unsigned int free_blocks = 0;
7654 int group_free = 0;
7655 int actual, bitmap;
7656 struct problem_context pctx;
7657 int problem, save_problem, fixit, had_problem;
7658 errcode_t retval;
7659
7660 clear_problem_context(&pctx);
7661 free_array = (int *) e2fsck_allocate_memory(ctx,
7662 fs->group_desc_count * sizeof(int), "free block count array");
7663
7664 if ((fs->super->s_first_data_block <
7665 ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
7666 (fs->super->s_blocks_count-1 >
7667 ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
7668 pctx.num = 1;
7669 pctx.blk = fs->super->s_first_data_block;
7670 pctx.blk2 = fs->super->s_blocks_count -1;
7671 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
7672 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
7673 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7674
7675 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7676 return;
7677 }
7678
7679 if ((fs->super->s_first_data_block <
7680 ext2fs_get_block_bitmap_start(fs->block_map)) ||
7681 (fs->super->s_blocks_count-1 >
7682 ext2fs_get_block_bitmap_end(fs->block_map))) {
7683 pctx.num = 2;
7684 pctx.blk = fs->super->s_first_data_block;
7685 pctx.blk2 = fs->super->s_blocks_count -1;
7686 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
7687 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
7688 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7689
7690 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7691 return;
7692 }
7693
7694redo_counts:
7695 had_problem = 0;
7696 save_problem = 0;
7697 pctx.blk = pctx.blk2 = NO_BLK;
7698 for (i = fs->super->s_first_data_block;
7699 i < fs->super->s_blocks_count;
7700 i++) {
7701 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
7702 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
7703
7704 if (actual == bitmap)
7705 goto do_counts;
7706
7707 if (!actual && bitmap) {
7708 /*
7709 * Block not used, but marked in use in the bitmap.
7710 */
7711 problem = PR_5_BLOCK_UNUSED;
7712 } else {
7713 /*
7714 * Block used, but not marked in use in the bitmap.
7715 */
7716 problem = PR_5_BLOCK_USED;
7717 }
7718 if (pctx.blk == NO_BLK) {
7719 pctx.blk = pctx.blk2 = i;
7720 save_problem = problem;
7721 } else {
7722 if ((problem == save_problem) &&
7723 (pctx.blk2 == i-1))
7724 pctx.blk2++;
7725 else {
7726 print_bitmap_problem(ctx, save_problem, &pctx);
7727 pctx.blk = pctx.blk2 = i;
7728 save_problem = problem;
7729 }
7730 }
7731 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7732 had_problem++;
7733
7734 do_counts:
7735 if (!bitmap) {
7736 group_free++;
7737 free_blocks++;
7738 }
7739 blocks ++;
7740 if ((blocks == fs->super->s_blocks_per_group) ||
7741 (i == fs->super->s_blocks_count-1)) {
7742 free_array[group] = group_free;
7743 group ++;
7744 blocks = 0;
7745 group_free = 0;
7746 if (ctx->progress)
7747 if ((ctx->progress)(ctx, 5, group,
7748 fs->group_desc_count*2))
7749 return;
7750 }
7751 }
7752 if (pctx.blk != NO_BLK)
7753 print_bitmap_problem(ctx, save_problem, &pctx);
7754 if (had_problem)
7755 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
7756 else
7757 fixit = -1;
7758 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7759
7760 if (fixit == 1) {
7761 ext2fs_free_block_bitmap(fs->block_map);
7762 retval = ext2fs_copy_bitmap(ctx->block_found_map,
7763 &fs->block_map);
7764 if (retval) {
7765 clear_problem_context(&pctx);
7766 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
7767 ctx->flags |= E2F_FLAG_ABORT;
7768 return;
7769 }
7770 ext2fs_set_bitmap_padding(fs->block_map);
7771 ext2fs_mark_bb_dirty(fs);
7772
7773 /* Redo the counts */
7774 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
7775 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7776 goto redo_counts;
7777 } else if (fixit == 0)
7778 ext2fs_unmark_valid(fs);
7779
7780 for (i = 0; i < fs->group_desc_count; i++) {
7781 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
7782 pctx.group = i;
7783 pctx.blk = fs->group_desc[i].bg_free_blocks_count;
7784 pctx.blk2 = free_array[i];
7785
7786 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
7787 &pctx)) {
7788 fs->group_desc[i].bg_free_blocks_count =
7789 free_array[i];
7790 ext2fs_mark_super_dirty(fs);
7791 } else
7792 ext2fs_unmark_valid(fs);
7793 }
7794 }
7795 if (free_blocks != fs->super->s_free_blocks_count) {
7796 pctx.group = 0;
7797 pctx.blk = fs->super->s_free_blocks_count;
7798 pctx.blk2 = free_blocks;
7799
7800 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
7801 fs->super->s_free_blocks_count = free_blocks;
7802 ext2fs_mark_super_dirty(fs);
7803 } else
7804 ext2fs_unmark_valid(fs);
7805 }
7806 ext2fs_free_mem(&free_array);
7807}
7808
7809static void check_inode_bitmaps(e2fsck_t ctx)
7810{
7811 ext2_filsys fs = ctx->fs;
7812 ext2_ino_t i;
7813 unsigned int free_inodes = 0;
7814 int group_free = 0;
7815 int dirs_count = 0;
7816 int group = 0;
7817 unsigned int inodes = 0;
7818 int *free_array;
7819 int *dir_array;
7820 int actual, bitmap;
7821 errcode_t retval;
7822 struct problem_context pctx;
7823 int problem, save_problem, fixit, had_problem;
7824
7825 clear_problem_context(&pctx);
7826 free_array = (int *) e2fsck_allocate_memory(ctx,
7827 fs->group_desc_count * sizeof(int), "free inode count array");
7828
7829 dir_array = (int *) e2fsck_allocate_memory(ctx,
7830 fs->group_desc_count * sizeof(int), "directory count array");
7831
7832 if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
7833 (fs->super->s_inodes_count >
7834 ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
7835 pctx.num = 3;
7836 pctx.blk = 1;
7837 pctx.blk2 = fs->super->s_inodes_count;
7838 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
7839 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
7840 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7841
7842 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7843 return;
7844 }
7845 if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
7846 (fs->super->s_inodes_count >
7847 ext2fs_get_inode_bitmap_end(fs->inode_map))) {
7848 pctx.num = 4;
7849 pctx.blk = 1;
7850 pctx.blk2 = fs->super->s_inodes_count;
7851 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
7852 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
7853 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7854
7855 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7856 return;
7857 }
7858
7859redo_counts:
7860 had_problem = 0;
7861 save_problem = 0;
7862 pctx.ino = pctx.ino2 = 0;
7863 for (i = 1; i <= fs->super->s_inodes_count; i++) {
7864 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
7865 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
7866
7867 if (actual == bitmap)
7868 goto do_counts;
7869
7870 if (!actual && bitmap) {
7871 /*
7872 * Inode wasn't used, but marked in bitmap
7873 */
7874 problem = PR_5_INODE_UNUSED;
7875 } else /* if (actual && !bitmap) */ {
7876 /*
7877 * Inode used, but not in bitmap
7878 */
7879 problem = PR_5_INODE_USED;
7880 }
7881 if (pctx.ino == 0) {
7882 pctx.ino = pctx.ino2 = i;
7883 save_problem = problem;
7884 } else {
7885 if ((problem == save_problem) &&
7886 (pctx.ino2 == i-1))
7887 pctx.ino2++;
7888 else {
7889 print_bitmap_problem(ctx, save_problem, &pctx);
7890 pctx.ino = pctx.ino2 = i;
7891 save_problem = problem;
7892 }
7893 }
7894 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7895 had_problem++;
7896
7897do_counts:
7898 if (!bitmap) {
7899 group_free++;
7900 free_inodes++;
7901 } else {
7902 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
7903 dirs_count++;
7904 }
7905 inodes++;
7906 if ((inodes == fs->super->s_inodes_per_group) ||
7907 (i == fs->super->s_inodes_count)) {
7908 free_array[group] = group_free;
7909 dir_array[group] = dirs_count;
7910 group ++;
7911 inodes = 0;
7912 group_free = 0;
7913 dirs_count = 0;
7914 if (ctx->progress)
7915 if ((ctx->progress)(ctx, 5,
7916 group + fs->group_desc_count,
7917 fs->group_desc_count*2))
7918 return;
7919 }
7920 }
7921 if (pctx.ino)
7922 print_bitmap_problem(ctx, save_problem, &pctx);
7923
7924 if (had_problem)
7925 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
7926 else
7927 fixit = -1;
7928 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7929
7930 if (fixit == 1) {
7931 ext2fs_free_inode_bitmap(fs->inode_map);
7932 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
7933 &fs->inode_map);
7934 if (retval) {
7935 clear_problem_context(&pctx);
7936 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
7937 ctx->flags |= E2F_FLAG_ABORT;
7938 return;
7939 }
7940 ext2fs_set_bitmap_padding(fs->inode_map);
7941 ext2fs_mark_ib_dirty(fs);
7942
7943 /* redo counts */
7944 inodes = 0; free_inodes = 0; group_free = 0;
7945 dirs_count = 0; group = 0;
7946 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7947 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
7948 goto redo_counts;
7949 } else if (fixit == 0)
7950 ext2fs_unmark_valid(fs);
7951
7952 for (i = 0; i < fs->group_desc_count; i++) {
7953 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
7954 pctx.group = i;
7955 pctx.ino = fs->group_desc[i].bg_free_inodes_count;
7956 pctx.ino2 = free_array[i];
7957 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
7958 &pctx)) {
7959 fs->group_desc[i].bg_free_inodes_count =
7960 free_array[i];
7961 ext2fs_mark_super_dirty(fs);
7962 } else
7963 ext2fs_unmark_valid(fs);
7964 }
7965 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
7966 pctx.group = i;
7967 pctx.ino = fs->group_desc[i].bg_used_dirs_count;
7968 pctx.ino2 = dir_array[i];
7969
7970 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
7971 &pctx)) {
7972 fs->group_desc[i].bg_used_dirs_count =
7973 dir_array[i];
7974 ext2fs_mark_super_dirty(fs);
7975 } else
7976 ext2fs_unmark_valid(fs);
7977 }
7978 }
7979 if (free_inodes != fs->super->s_free_inodes_count) {
7980 pctx.group = -1;
7981 pctx.ino = fs->super->s_free_inodes_count;
7982 pctx.ino2 = free_inodes;
7983
7984 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
7985 fs->super->s_free_inodes_count = free_inodes;
7986 ext2fs_mark_super_dirty(fs);
7987 } else
7988 ext2fs_unmark_valid(fs);
7989 }
7990 ext2fs_free_mem(&free_array);
7991 ext2fs_free_mem(&dir_array);
7992}
7993
7994static void check_inode_end(e2fsck_t ctx)
7995{
7996 ext2_filsys fs = ctx->fs;
7997 ext2_ino_t end, save_inodes_count, i;
7998 struct problem_context pctx;
7999
8000 clear_problem_context(&pctx);
8001
8002 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
8003 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
8004 &save_inodes_count);
8005 if (pctx.errcode) {
8006 pctx.num = 1;
8007 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8008 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8009 return;
8010 }
8011 if (save_inodes_count == end)
8012 return;
8013
8014 for (i = save_inodes_count + 1; i <= end; i++) {
8015 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
8016 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
8017 for (i = save_inodes_count + 1; i <= end; i++)
8018 ext2fs_mark_inode_bitmap(fs->inode_map,
8019 i);
8020 ext2fs_mark_ib_dirty(fs);
8021 } else
8022 ext2fs_unmark_valid(fs);
8023 break;
8024 }
8025 }
8026
8027 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
8028 save_inodes_count, 0);
8029 if (pctx.errcode) {
8030 pctx.num = 2;
8031 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8032 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8033 return;
8034 }
8035}
8036
8037static void check_block_end(e2fsck_t ctx)
8038{
8039 ext2_filsys fs = ctx->fs;
8040 blk_t end, save_blocks_count, i;
8041 struct problem_context pctx;
8042
8043 clear_problem_context(&pctx);
8044
8045 end = fs->block_map->start +
8046 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
8047 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
8048 &save_blocks_count);
8049 if (pctx.errcode) {
8050 pctx.num = 3;
8051 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8052 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8053 return;
8054 }
8055 if (save_blocks_count == end)
8056 return;
8057
8058 for (i = save_blocks_count + 1; i <= end; i++) {
8059 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
8060 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
8061 for (i = save_blocks_count + 1; i <= end; i++)
8062 ext2fs_mark_block_bitmap(fs->block_map,
8063 i);
8064 ext2fs_mark_bb_dirty(fs);
8065 } else
8066 ext2fs_unmark_valid(fs);
8067 break;
8068 }
8069 }
8070
8071 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
8072 save_blocks_count, 0);
8073 if (pctx.errcode) {
8074 pctx.num = 4;
8075 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8076 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8077 return;
8078 }
8079}
8080
8081static void e2fsck_pass5(e2fsck_t ctx)
8082{
8083 struct problem_context pctx;
8084
8085 /* Pass 5 */
8086
8087 clear_problem_context(&pctx);
8088
8089 if (!(ctx->options & E2F_OPT_PREEN))
8090 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
8091
8092 if (ctx->progress)
8093 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
8094 return;
8095
8096 e2fsck_read_bitmaps(ctx);
8097
8098 check_block_bitmaps(ctx);
8099 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8100 return;
8101 check_inode_bitmaps(ctx);
8102 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8103 return;
8104 check_inode_end(ctx);
8105 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8106 return;
8107 check_block_end(ctx);
8108 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8109 return;
8110
8111 ext2fs_free_inode_bitmap(ctx->inode_used_map);
8112 ctx->inode_used_map = 0;
8113 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
8114 ctx->inode_dir_map = 0;
8115 ext2fs_free_block_bitmap(ctx->block_found_map);
8116 ctx->block_found_map = 0;
8117}
8118
8119/*
8120 * problem.c --- report filesystem problems to the user
8121 */
8122
8123#define PR_PREEN_OK 0x000001 /* Don't need to do preenhalt */
8124#define PR_NO_OK 0x000002 /* If user answers no, don't make fs invalid */
8125#define PR_NO_DEFAULT 0x000004 /* Default to no */
8126#define PR_MSG_ONLY 0x000008 /* Print message only */
8127
8128/* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
8129
8130#define PR_FATAL 0x001000 /* Fatal error */
8131#define PR_AFTER_CODE 0x002000 /* After asking the first question, */
8132 /* ask another */
8133#define PR_PREEN_NOMSG 0x004000 /* Don't print a message if we're preening */
8134#define PR_NOCOLLATE 0x008000 /* Don't collate answers for this latch */
8135#define PR_NO_NOMSG 0x010000 /* Don't print a message if e2fsck -n */
8136#define PR_PREEN_NO 0x020000 /* Use No as an answer if preening */
8137#define PR_PREEN_NOHDR 0x040000 /* Don't print the preen header */
8138
8139
8140#define PROMPT_NONE 0
8141#define PROMPT_FIX 1
8142#define PROMPT_CLEAR 2
8143#define PROMPT_RELOCATE 3
8144#define PROMPT_ALLOCATE 4
8145#define PROMPT_EXPAND 5
8146#define PROMPT_CONNECT 6
8147#define PROMPT_CREATE 7
8148#define PROMPT_SALVAGE 8
8149#define PROMPT_TRUNCATE 9
8150#define PROMPT_CLEAR_INODE 10
8151#define PROMPT_ABORT 11
8152#define PROMPT_SPLIT 12
8153#define PROMPT_CONTINUE 13
8154#define PROMPT_CLONE 14
8155#define PROMPT_DELETE 15
8156#define PROMPT_SUPPRESS 16
8157#define PROMPT_UNLINK 17
8158#define PROMPT_CLEAR_HTREE 18
8159#define PROMPT_RECREATE 19
8160#define PROMPT_NULL 20
8161
8162struct e2fsck_problem {
8163 problem_t e2p_code;
8164 const char * e2p_description;
8165 char prompt;
8166 int flags;
8167 problem_t second_code;
8168};
8169
8170struct latch_descr {
8171 int latch_code;
8172 problem_t question;
8173 problem_t end_message;
8174 int flags;
8175};
8176
8177/*
8178 * These are the prompts which are used to ask the user if they want
8179 * to fix a problem.
8180 */
8181static const char *const prompt[] = {
8182 N_("(no prompt)"), /* 0 */
8183 N_("Fix"), /* 1 */
8184 N_("Clear"), /* 2 */
8185 N_("Relocate"), /* 3 */
8186 N_("Allocate"), /* 4 */
8187 N_("Expand"), /* 5 */
8188 N_("Connect to /lost+found"), /* 6 */
8189 N_("Create"), /* 7 */
8190 N_("Salvage"), /* 8 */
8191 N_("Truncate"), /* 9 */
8192 N_("Clear inode"), /* 10 */
8193 N_("Abort"), /* 11 */
8194 N_("Split"), /* 12 */
8195 N_("Continue"), /* 13 */
8196 N_("Clone multiply-claimed blocks"), /* 14 */
8197 N_("Delete file"), /* 15 */
8198 N_("Suppress messages"),/* 16 */
8199 N_("Unlink"), /* 17 */
8200 N_("Clear HTree index"),/* 18 */
8201 N_("Recreate"), /* 19 */
8202 "", /* 20 */
8203};
8204
8205/*
8206 * These messages are printed when we are preen mode and we will be
8207 * automatically fixing the problem.
8208 */
8209static const char *const preen_msg[] = {
8210 N_("(NONE)"), /* 0 */
8211 N_("FIXED"), /* 1 */
8212 N_("CLEARED"), /* 2 */
8213 N_("RELOCATED"), /* 3 */
8214 N_("ALLOCATED"), /* 4 */
8215 N_("EXPANDED"), /* 5 */
8216 N_("RECONNECTED"), /* 6 */
8217 N_("CREATED"), /* 7 */
8218 N_("SALVAGED"), /* 8 */
8219 N_("TRUNCATED"), /* 9 */
8220 N_("INODE CLEARED"), /* 10 */
8221 N_("ABORTED"), /* 11 */
8222 N_("SPLIT"), /* 12 */
8223 N_("CONTINUING"), /* 13 */
8224 N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
8225 N_("FILE DELETED"), /* 15 */
8226 N_("SUPPRESSED"), /* 16 */
8227 N_("UNLINKED"), /* 17 */
8228 N_("HTREE INDEX CLEARED"),/* 18 */
8229 N_("WILL RECREATE"), /* 19 */
8230 "", /* 20 */
8231};
8232
8233static const struct e2fsck_problem problem_table[] = {
8234
8235 /* Pre-Pass 1 errors */
8236
8237 /* Block bitmap not in group */
8238 { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g. (@b %b)\n"),
8239 PROMPT_RELOCATE, PR_LATCH_RELOC },
8240
8241 /* Inode bitmap not in group */
8242 { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g. (@b %b)\n"),
8243 PROMPT_RELOCATE, PR_LATCH_RELOC },
8244
8245 /* Inode table not in group */
8246 { PR_0_ITABLE_NOT_GROUP,
8247 N_("@i table for @g %g is not in @g. (@b %b)\n"
8248 "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
8249 PROMPT_RELOCATE, PR_LATCH_RELOC },
8250
8251 /* Superblock corrupt */
8252 { PR_0_SB_CORRUPT,
8253 N_("\nThe @S could not be read or does not describe a correct ext2\n"
8254 "@f. If the @v is valid and it really contains an ext2\n"
8255 "@f (and not swap or ufs or something else), then the @S\n"
8256 "is corrupt, and you might try running e2fsck with an alternate @S:\n"
8257 " e2fsck -b %S <@v>\n\n"),
8258 PROMPT_NONE, PR_FATAL },
8259
8260 /* Filesystem size is wrong */
8261 { PR_0_FS_SIZE_WRONG,
8262 N_("The @f size (according to the @S) is %b @bs\n"
8263 "The physical size of the @v is %c @bs\n"
8264 "Either the @S or the partition table is likely to be corrupt!\n"),
8265 PROMPT_ABORT, 0 },
8266
8267 /* Fragments not supported */
8268 { PR_0_NO_FRAGMENTS,
8269 N_("@S @b_size = %b, fragsize = %c.\n"
8270 "This version of e2fsck does not support fragment sizes different\n"
8271 "from the @b size.\n"),
8272 PROMPT_NONE, PR_FATAL },
8273
8274 /* Bad blocks_per_group */
8275 { PR_0_BLOCKS_PER_GROUP,
8276 N_("@S @bs_per_group = %b, should have been %c\n"),
8277 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8278
8279 /* Bad first_data_block */
8280 { PR_0_FIRST_DATA_BLOCK,
8281 N_("@S first_data_@b = %b, should have been %c\n"),
8282 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8283
8284 /* Adding UUID to filesystem */
8285 { PR_0_ADD_UUID,
8286 N_("@f did not have a UUID; generating one.\n\n"),
8287 PROMPT_NONE, 0 },
8288
8289 /* Relocate hint */
8290 { PR_0_RELOCATE_HINT,
8291 N_("Note: if several inode or block bitmap blocks or part\n"
8292 "of the inode table require relocation, you may wish to try\n"
8293 "running e2fsck with the '-b %S' option first. The problem\n"
8294 "may lie only with the primary block group descriptors, and\n"
8295 "the backup block group descriptors may be OK.\n\n"),
8296 PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
8297
8298 /* Miscellaneous superblock corruption */
8299 { PR_0_MISC_CORRUPT_SUPER,
8300 N_("Corruption found in @S. (%s = %N).\n"),
8301 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8302
8303 /* Error determing physical device size of filesystem */
8304 { PR_0_GETSIZE_ERROR,
8305 N_("Error determining size of the physical @v: %m\n"),
8306 PROMPT_NONE, PR_FATAL },
8307
8308 /* Inode count in superblock is incorrect */
8309 { PR_0_INODE_COUNT_WRONG,
8310 N_("@i count in @S is %i, @s %j.\n"),
8311 PROMPT_FIX, 0 },
8312
8313 { PR_0_HURD_CLEAR_FILETYPE,
8314 N_("The Hurd does not support the filetype feature.\n"),
8315 PROMPT_CLEAR, 0 },
8316
8317 /* Journal inode is invalid */
8318 { PR_0_JOURNAL_BAD_INODE,
8319 N_("@S has an @n ext3 @j (@i %i).\n"),
8320 PROMPT_CLEAR, PR_PREEN_OK },
8321
8322 /* The external journal has (unsupported) multiple filesystems */
8323 { PR_0_JOURNAL_UNSUPP_MULTIFS,
8324 N_("External @j has multiple @f users (unsupported).\n"),
8325 PROMPT_NONE, PR_FATAL },
8326
8327 /* Can't find external journal */
8328 { PR_0_CANT_FIND_JOURNAL,
8329 N_("Can't find external @j\n"),
8330 PROMPT_NONE, PR_FATAL },
8331
8332 /* External journal has bad superblock */
8333 { PR_0_EXT_JOURNAL_BAD_SUPER,
8334 N_("External @j has bad @S\n"),
8335 PROMPT_NONE, PR_FATAL },
8336
8337 /* Superblock has a bad journal UUID */
8338 { PR_0_JOURNAL_BAD_UUID,
8339 N_("External @j does not support this @f\n"),
8340 PROMPT_NONE, PR_FATAL },
8341
8342 /* Journal has an unknown superblock type */
8343 { PR_0_JOURNAL_UNSUPP_SUPER,
8344 N_("Ext3 @j @S is unknown type %N (unsupported).\n"
8345 "It is likely that your copy of e2fsck is old and/or doesn't "
8346 "support this @j format.\n"
8347 "It is also possible the @j @S is corrupt.\n"),
8348 PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
8349
8350 /* Journal superblock is corrupt */
8351 { PR_0_JOURNAL_BAD_SUPER,
8352 N_("Ext3 @j @S is corrupt.\n"),
8353 PROMPT_FIX, PR_PREEN_OK },
8354
8355 /* Superblock flag should be cleared */
8356 { PR_0_JOURNAL_HAS_JOURNAL,
8357 N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
8358 PROMPT_CLEAR, PR_PREEN_OK },
8359
8360 /* Superblock flag is incorrect */
8361 { PR_0_JOURNAL_RECOVER_SET,
8362 N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
8363 PROMPT_CLEAR, PR_PREEN_OK },
8364
8365 /* Journal has data, but recovery flag is clear */
8366 { PR_0_JOURNAL_RECOVERY_CLEAR,
8367 N_("ext3 recovery flag is clear, but @j has data.\n"),
8368 PROMPT_NONE, 0 },
8369
8370 /* Ask if we should clear the journal */
8371 { PR_0_JOURNAL_RESET_JOURNAL,
8372 N_("Clear @j"),
8373 PROMPT_NULL, PR_PREEN_NOMSG },
8374
8375 /* Ask if we should run the journal anyway */
8376 { PR_0_JOURNAL_RUN,
8377 N_("Run @j anyway"),
8378 PROMPT_NULL, 0 },
8379
8380 /* Run the journal by default */
8381 { PR_0_JOURNAL_RUN_DEFAULT,
8382 N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
8383 PROMPT_NONE, 0 },
8384
8385 /* Clearing orphan inode */
8386 { PR_0_ORPHAN_CLEAR_INODE,
8387 N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
8388 PROMPT_NONE, 0 },
8389
8390 /* Illegal block found in orphaned inode */
8391 { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
8392 N_("@I @b #%B (%b) found in @o @i %i.\n"),
8393 PROMPT_NONE, 0 },
8394
8395 /* Already cleared block found in orphaned inode */
8396 { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
8397 N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
8398 PROMPT_NONE, 0 },
8399
8400 /* Illegal orphan inode in superblock */
8401 { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
8402 N_("@I @o @i %i in @S.\n"),
8403 PROMPT_NONE, 0 },
8404
8405 /* Illegal inode in orphaned inode list */
8406 { PR_0_ORPHAN_ILLEGAL_INODE,
8407 N_("@I @i %i in @o @i list.\n"),
8408 PROMPT_NONE, 0 },
8409
8410 /* Filesystem revision is 0, but feature flags are set */
8411 { PR_0_FS_REV_LEVEL,
8412 N_("@f has feature flag(s) set, but is a revision 0 @f. "),
8413 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8414
8415 /* Journal superblock has an unknown read-only feature flag set */
8416 { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
8417 N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
8418 PROMPT_ABORT, 0 },
8419
8420 /* Journal superblock has an unknown incompatible feature flag set */
8421 { PR_0_JOURNAL_UNSUPP_INCOMPAT,
8422 N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
8423 PROMPT_ABORT, 0 },
8424
8425 /* Journal has unsupported version number */
8426 { PR_0_JOURNAL_UNSUPP_VERSION,
8427 N_("@j version not supported by this e2fsck.\n"),
8428 PROMPT_ABORT, 0 },
8429
8430 /* Moving journal to hidden file */
8431 { PR_0_MOVE_JOURNAL,
8432 N_("Moving @j from /%s to hidden @i.\n\n"),
8433 PROMPT_NONE, 0 },
8434
8435 /* Error moving journal to hidden file */
8436 { PR_0_ERR_MOVE_JOURNAL,
8437 N_("Error moving @j: %m\n\n"),
8438 PROMPT_NONE, 0 },
8439
8440 /* Clearing V2 journal superblock */
8441 { PR_0_CLEAR_V2_JOURNAL,
8442 N_("Found @n V2 @j @S fields (from V1 @j).\n"
8443 "Clearing fields beyond the V1 @j @S...\n\n"),
8444 PROMPT_NONE, 0 },
8445
8446 /* Backup journal inode blocks */
8447 { PR_0_BACKUP_JNL,
8448 N_("Backing up @j @i @b information.\n\n"),
8449 PROMPT_NONE, 0 },
8450
8451 /* Reserved blocks w/o resize_inode */
8452 { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
8453 N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
8454 "is %N; @s zero. "),
8455 PROMPT_FIX, 0 },
8456
8457 /* Resize_inode not enabled, but resize inode is non-zero */
8458 { PR_0_CLEAR_RESIZE_INODE,
8459 N_("Resize_@i not enabled, but the resize @i is non-zero. "),
8460 PROMPT_CLEAR, 0 },
8461
8462 /* Resize inode invalid */
8463 { PR_0_RESIZE_INODE_INVALID,
8464 N_("Resize @i not valid. "),
8465 PROMPT_RECREATE, 0 },
8466
8467 /* Pass 1 errors */
8468
8469 /* Pass 1: Checking inodes, blocks, and sizes */
8470 { PR_1_PASS_HEADER,
8471 N_("Pass 1: Checking @is, @bs, and sizes\n"),
8472 PROMPT_NONE, 0 },
8473
8474 /* Root directory is not an inode */
8475 { PR_1_ROOT_NO_DIR, N_("@r is not a @d. "),
8476 PROMPT_CLEAR, 0 },
8477
8478 /* Root directory has dtime set */
8479 { PR_1_ROOT_DTIME,
8480 N_("@r has dtime set (probably due to old mke2fs). "),
8481 PROMPT_FIX, PR_PREEN_OK },
8482
8483 /* Reserved inode has bad mode */
8484 { PR_1_RESERVED_BAD_MODE,
8485 N_("Reserved @i %i (%Q) has @n mode. "),
8486 PROMPT_CLEAR, PR_PREEN_OK },
8487
8488 /* Deleted inode has zero dtime */
8489 { PR_1_ZERO_DTIME,
8490 N_("@D @i %i has zero dtime. "),
8491 PROMPT_FIX, PR_PREEN_OK },
8492
8493 /* Inode in use, but dtime set */
8494 { PR_1_SET_DTIME,
8495 N_("@i %i is in use, but has dtime set. "),
8496 PROMPT_FIX, PR_PREEN_OK },
8497
8498 /* Zero-length directory */
8499 { PR_1_ZERO_LENGTH_DIR,
8500 N_("@i %i is a @z @d. "),
8501 PROMPT_CLEAR, PR_PREEN_OK },
8502
8503 /* Block bitmap conflicts with some other fs block */
8504 { PR_1_BB_CONFLICT,
8505 N_("@g %g's @b @B at %b @C.\n"),
8506 PROMPT_RELOCATE, 0 },
8507
8508 /* Inode bitmap conflicts with some other fs block */
8509 { PR_1_IB_CONFLICT,
8510 N_("@g %g's @i @B at %b @C.\n"),
8511 PROMPT_RELOCATE, 0 },
8512
8513 /* Inode table conflicts with some other fs block */
8514 { PR_1_ITABLE_CONFLICT,
8515 N_("@g %g's @i table at %b @C.\n"),
8516 PROMPT_RELOCATE, 0 },
8517
8518 /* Block bitmap is on a bad block */
8519 { PR_1_BB_BAD_BLOCK,
8520 N_("@g %g's @b @B (%b) is bad. "),
8521 PROMPT_RELOCATE, 0 },
8522
8523 /* Inode bitmap is on a bad block */
8524 { PR_1_IB_BAD_BLOCK,
8525 N_("@g %g's @i @B (%b) is bad. "),
8526 PROMPT_RELOCATE, 0 },
8527
8528 /* Inode has incorrect i_size */
8529 { PR_1_BAD_I_SIZE,
8530 N_("@i %i, i_size is %Is, @s %N. "),
8531 PROMPT_FIX, PR_PREEN_OK },
8532
8533 /* Inode has incorrect i_blocks */
8534 { PR_1_BAD_I_BLOCKS,
8535 N_("@i %i, i_@bs is %Ib, @s %N. "),
8536 PROMPT_FIX, PR_PREEN_OK },
8537
8538 /* Illegal blocknumber in inode */
8539 { PR_1_ILLEGAL_BLOCK_NUM,
8540 N_("@I @b #%B (%b) in @i %i. "),
8541 PROMPT_CLEAR, PR_LATCH_BLOCK },
8542
8543 /* Block number overlaps fs metadata */
8544 { PR_1_BLOCK_OVERLAPS_METADATA,
8545 N_("@b #%B (%b) overlaps @f metadata in @i %i. "),
8546 PROMPT_CLEAR, PR_LATCH_BLOCK },
8547
8548 /* Inode has illegal blocks (latch question) */
8549 { PR_1_INODE_BLOCK_LATCH,
8550 N_("@i %i has illegal @b(s). "),
8551 PROMPT_CLEAR, 0 },
8552
8553 /* Too many bad blocks in inode */
8554 { PR_1_TOO_MANY_BAD_BLOCKS,
8555 N_("Too many illegal @bs in @i %i.\n"),
8556 PROMPT_CLEAR_INODE, PR_NO_OK },
8557
8558 /* Illegal block number in bad block inode */
8559 { PR_1_BB_ILLEGAL_BLOCK_NUM,
8560 N_("@I @b #%B (%b) in bad @b @i. "),
8561 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8562
8563 /* Bad block inode has illegal blocks (latch question) */
8564 { PR_1_INODE_BBLOCK_LATCH,
8565 N_("Bad @b @i has illegal @b(s). "),
8566 PROMPT_CLEAR, 0 },
8567
8568 /* Duplicate or bad blocks in use! */
8569 { PR_1_DUP_BLOCKS_PREENSTOP,
8570 N_("Duplicate or bad @b in use!\n"),
8571 PROMPT_NONE, 0 },
8572
8573 /* Bad block used as bad block indirect block */
8574 { PR_1_BBINODE_BAD_METABLOCK,
8575 N_("Bad @b %b used as bad @b @i indirect @b. "),
8576 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8577
8578 /* Inconsistency can't be fixed prompt */
8579 { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
8580 N_("\nThe bad @b @i has probably been corrupted. You probably\n"
8581 "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
8582 "in the @f.\n"),
8583 PROMPT_CONTINUE, PR_PREEN_NOMSG },
8584
8585 /* Bad primary block */
8586 { PR_1_BAD_PRIMARY_BLOCK,
8587 N_("\nIf the @b is really bad, the @f cannot be fixed.\n"),
8588 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
8589
8590 /* Bad primary block prompt */
8591 { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
8592 N_("You can remove this @b from the bad @b list and hope\n"
8593 "that the @b is really OK. But there are no guarantees.\n\n"),
8594 PROMPT_CLEAR, PR_PREEN_NOMSG },
8595
8596 /* Bad primary superblock */
8597 { PR_1_BAD_PRIMARY_SUPERBLOCK,
8598 N_("The primary @S (%b) is on the bad @b list.\n"),
8599 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8600
8601 /* Bad primary block group descriptors */
8602 { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
8603 N_("Block %b in the primary @g descriptors "
8604 "is on the bad @b list\n"),
8605 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8606
8607 /* Bad superblock in group */
8608 { PR_1_BAD_SUPERBLOCK,
8609 N_("Warning: Group %g's @S (%b) is bad.\n"),
8610 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8611
8612 /* Bad block group descriptors in group */
8613 { PR_1_BAD_GROUP_DESCRIPTORS,
8614 N_("Warning: Group %g's copy of the @g descriptors has a bad "
8615 "@b (%b).\n"),
8616 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8617
8618 /* Block claimed for no reason */
8619 { PR_1_PROGERR_CLAIMED_BLOCK,
8620 N_("Programming error? @b #%b claimed for no reason in "
8621 "process_bad_@b.\n"),
8622 PROMPT_NONE, PR_PREEN_OK },
8623
8624 /* Error allocating blocks for relocating metadata */
8625 { PR_1_RELOC_BLOCK_ALLOCATE,
8626 N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
8627 PROMPT_NONE, PR_PREEN_OK },
8628
8629 /* Error allocating block buffer during relocation process */
8630 { PR_1_RELOC_MEMORY_ALLOCATE,
8631 N_("@A @b buffer for relocating %s\n"),
8632 PROMPT_NONE, PR_PREEN_OK },
8633
8634 /* Relocating metadata group information from X to Y */
8635 { PR_1_RELOC_FROM_TO,
8636 N_("Relocating @g %g's %s from %b to %c...\n"),
8637 PROMPT_NONE, PR_PREEN_OK },
8638
8639 /* Relocating metatdata group information to X */
8640 { PR_1_RELOC_TO,
8641 N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
8642 PROMPT_NONE, PR_PREEN_OK },
8643
8644 /* Block read error during relocation process */
8645 { PR_1_RELOC_READ_ERR,
8646 N_("Warning: could not read @b %b of %s: %m\n"),
8647 PROMPT_NONE, PR_PREEN_OK },
8648
8649 /* Block write error during relocation process */
8650 { PR_1_RELOC_WRITE_ERR,
8651 N_("Warning: could not write @b %b for %s: %m\n"),
8652 PROMPT_NONE, PR_PREEN_OK },
8653
8654 /* Error allocating inode bitmap */
8655 { PR_1_ALLOCATE_IBITMAP_ERROR,
8656 N_("@A @i @B (%N): %m\n"),
8657 PROMPT_NONE, PR_FATAL },
8658
8659 /* Error allocating block bitmap */
8660 { PR_1_ALLOCATE_BBITMAP_ERROR,
8661 N_("@A @b @B (%N): %m\n"),
8662 PROMPT_NONE, PR_FATAL },
8663
8664 /* Error allocating icount structure */
8665 { PR_1_ALLOCATE_ICOUNT,
8666 N_("@A icount link information: %m\n"),
8667 PROMPT_NONE, PR_FATAL },
8668
8669 /* Error allocating dbcount */
8670 { PR_1_ALLOCATE_DBCOUNT,
8671 N_("@A @d @b array: %m\n"),
8672 PROMPT_NONE, PR_FATAL },
8673
8674 /* Error while scanning inodes */
8675 { PR_1_ISCAN_ERROR,
8676 N_("Error while scanning @is (%i): %m\n"),
8677 PROMPT_NONE, PR_FATAL },
8678
8679 /* Error while iterating over blocks */
8680 { PR_1_BLOCK_ITERATE,
8681 N_("Error while iterating over @bs in @i %i: %m\n"),
8682 PROMPT_NONE, PR_FATAL },
8683
8684 /* Error while storing inode count information */
8685 { PR_1_ICOUNT_STORE,
8686 N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
8687 PROMPT_NONE, PR_FATAL },
8688
8689 /* Error while storing directory block information */
8690 { PR_1_ADD_DBLOCK,
8691 N_("Error storing @d @b information "
8692 "(@i=%i, @b=%b, num=%N): %m\n"),
8693 PROMPT_NONE, PR_FATAL },
8694
8695 /* Error while reading inode (for clearing) */
8696 { PR_1_READ_INODE,
8697 N_("Error reading @i %i: %m\n"),
8698 PROMPT_NONE, PR_FATAL },
8699
8700 /* Suppress messages prompt */
8701 { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
8702
8703 /* Imagic flag set on an inode when filesystem doesn't support it */
8704 { PR_1_SET_IMAGIC,
8705 N_("@i %i has imagic flag set. "),
8706 PROMPT_CLEAR, 0 },
8707
8708 /* Immutable flag set on a device or socket inode */
8709 { PR_1_SET_IMMUTABLE,
8710 N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
8711 "or append-only flag set. "),
8712 PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
8713
8714 /* Compression flag set on an inode when filesystem doesn't support it */
8715 { PR_1_COMPR_SET,
8716 N_("@i %i has @cion flag set on @f without @cion support. "),
8717 PROMPT_CLEAR, 0 },
8718
8719 /* Non-zero size for device, fifo or socket inode */
8720 { PR_1_SET_NONZSIZE,
8721 N_("Special (@v/socket/fifo) @i %i has non-zero size. "),
8722 PROMPT_FIX, PR_PREEN_OK },
8723
8724 /* Filesystem revision is 0, but feature flags are set */
8725 { PR_1_FS_REV_LEVEL,
8726 N_("@f has feature flag(s) set, but is a revision 0 @f. "),
8727 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8728
8729 /* Journal inode is not in use, but contains data */
8730 { PR_1_JOURNAL_INODE_NOT_CLEAR,
8731 N_("@j @i is not in use, but contains data. "),
8732 PROMPT_CLEAR, PR_PREEN_OK },
8733
8734 /* Journal has bad mode */
8735 { PR_1_JOURNAL_BAD_MODE,
8736 N_("@j is not regular file. "),
8737 PROMPT_FIX, PR_PREEN_OK },
8738
8739 /* Deal with inodes that were part of orphan linked list */
8740 { PR_1_LOW_DTIME,
8741 N_("@i %i was part of the @o @i list. "),
8742 PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
8743
8744 /* Deal with inodes that were part of corrupted orphan linked
8745 list (latch question) */
8746 { PR_1_ORPHAN_LIST_REFUGEES,
8747 N_("@is that were part of a corrupted orphan linked list found. "),
8748 PROMPT_FIX, 0 },
8749
8750 /* Error allocating refcount structure */
8751 { PR_1_ALLOCATE_REFCOUNT,
8752 N_("@A refcount structure (%N): %m\n"),
8753 PROMPT_NONE, PR_FATAL },
8754
8755 /* Error reading extended attribute block */
8756 { PR_1_READ_EA_BLOCK,
8757 N_("Error reading @a @b %b for @i %i. "),
8758 PROMPT_CLEAR, 0 },
8759
8760 /* Invalid extended attribute block */
8761 { PR_1_BAD_EA_BLOCK,
8762 N_("@i %i has a bad @a @b %b. "),
8763 PROMPT_CLEAR, 0 },
8764
8765 /* Error reading Extended Attribute block while fixing refcount */
8766 { PR_1_EXTATTR_READ_ABORT,
8767 N_("Error reading @a @b %b (%m). "),
8768 PROMPT_ABORT, 0 },
8769
8770 /* Extended attribute reference count incorrect */
8771 { PR_1_EXTATTR_REFCOUNT,
8772 N_("@a @b %b has reference count %B, @s %N. "),
8773 PROMPT_FIX, 0 },
8774
8775 /* Error writing Extended Attribute block while fixing refcount */
8776 { PR_1_EXTATTR_WRITE,
8777 N_("Error writing @a @b %b (%m). "),
8778 PROMPT_ABORT, 0 },
8779
8780 /* Multiple EA blocks not supported */
8781 { PR_1_EA_MULTI_BLOCK,
8782 N_("@a @b %b has h_@bs > 1. "),
8783 PROMPT_CLEAR, 0},
8784
8785 /* Error allocating EA region allocation structure */
8786 { PR_1_EA_ALLOC_REGION,
8787 N_("@A @a @b %b. "),
8788 PROMPT_ABORT, 0},
8789
8790 /* Error EA allocation collision */
8791 { PR_1_EA_ALLOC_COLLISION,
8792 N_("@a @b %b is corrupt (allocation collision). "),
8793 PROMPT_CLEAR, 0},
8794
8795 /* Bad extended attribute name */
8796 { PR_1_EA_BAD_NAME,
8797 N_("@a @b %b is corrupt (@n name). "),
8798 PROMPT_CLEAR, 0},
8799
8800 /* Bad extended attribute value */
8801 { PR_1_EA_BAD_VALUE,
8802 N_("@a @b %b is corrupt (@n value). "),
8803 PROMPT_CLEAR, 0},
8804
8805 /* Inode too big (latch question) */
8806 { PR_1_INODE_TOOBIG,
8807 N_("@i %i is too big. "), PROMPT_TRUNCATE, 0 },
8808
8809 /* Directory too big */
8810 { PR_1_TOOBIG_DIR,
8811 N_("@b #%B (%b) causes @d to be too big. "),
8812 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8813
8814 /* Regular file too big */
8815 { PR_1_TOOBIG_REG,
8816 N_("@b #%B (%b) causes file to be too big. "),
8817 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8818
8819 /* Symlink too big */
8820 { PR_1_TOOBIG_SYMLINK,
8821 N_("@b #%B (%b) causes symlink to be too big. "),
8822 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8823
8824 /* INDEX_FL flag set on a non-HTREE filesystem */
8825 { PR_1_HTREE_SET,
8826 N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
8827 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8828
8829 /* INDEX_FL flag set on a non-directory */
8830 { PR_1_HTREE_NODIR,
8831 N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
8832 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8833
8834 /* Invalid root node in HTREE directory */
8835 { PR_1_HTREE_BADROOT,
8836 N_("@h %i has an @n root node.\n"),
8837 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8838
8839 /* Unsupported hash version in HTREE directory */
8840 { PR_1_HTREE_HASHV,
8841 N_("@h %i has an unsupported hash version (%N)\n"),
8842 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8843
8844 /* Incompatible flag in HTREE root node */
8845 { PR_1_HTREE_INCOMPAT,
8846 N_("@h %i uses an incompatible htree root node flag.\n"),
8847 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8848
8849 /* HTREE too deep */
8850 { PR_1_HTREE_DEPTH,
8851 N_("@h %i has a tree depth (%N) which is too big\n"),
8852 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8853
8854 /* Bad block has indirect block that conflicts with filesystem block */
8855 { PR_1_BB_FS_BLOCK,
8856 N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
8857 "@f metadata. "),
8858 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8859
8860 /* Resize inode failed */
8861 { PR_1_RESIZE_INODE_CREATE,
8862 N_("Resize @i (re)creation failed: %m."),
8863 PROMPT_ABORT, 0 },
8864
8865 /* invalid inode->i_extra_isize */
8866 { PR_1_EXTRA_ISIZE,
8867 N_("@i %i has a extra size (%IS) which is @n\n"),
8868 PROMPT_FIX, PR_PREEN_OK },
8869
8870 /* invalid ea entry->e_name_len */
8871 { PR_1_ATTR_NAME_LEN,
8872 N_("@a in @i %i has a namelen (%N) which is @n\n"),
8873 PROMPT_CLEAR, PR_PREEN_OK },
8874
8875 /* invalid ea entry->e_value_size */
8876 { PR_1_ATTR_VALUE_SIZE,
8877 N_("@a in @i %i has a value size (%N) which is @n\n"),
8878 PROMPT_CLEAR, PR_PREEN_OK },
8879
8880 /* invalid ea entry->e_value_offs */
8881 { PR_1_ATTR_VALUE_OFFSET,
8882 N_("@a in @i %i has a value offset (%N) which is @n\n"),
8883 PROMPT_CLEAR, PR_PREEN_OK },
8884
8885 /* invalid ea entry->e_value_block */
8886 { PR_1_ATTR_VALUE_BLOCK,
8887 N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
8888 PROMPT_CLEAR, PR_PREEN_OK },
8889
8890 /* invalid ea entry->e_hash */
8891 { PR_1_ATTR_HASH,
8892 N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
8893 PROMPT_CLEAR, PR_PREEN_OK },
8894
8895 /* Pass 1b errors */
8896
8897 /* Pass 1B: Rescan for duplicate/bad blocks */
8898 { PR_1B_PASS_HEADER,
8899 N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
8900 "Pass 1B: Rescanning for @m @bs\n"),
8901 PROMPT_NONE, 0 },
8902
8903 /* Duplicate/bad block(s) header */
8904 { PR_1B_DUP_BLOCK_HEADER,
8905 N_("@m @b(s) in @i %i:"),
8906 PROMPT_NONE, 0 },
8907
8908 /* Duplicate/bad block(s) in inode */
8909 { PR_1B_DUP_BLOCK,
8910 " %b",
8911 PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
8912
8913 /* Duplicate/bad block(s) end */
8914 { PR_1B_DUP_BLOCK_END,
8915 "\n",
8916 PROMPT_NONE, PR_PREEN_NOHDR },
8917
8918 /* Error while scanning inodes */
8919 { PR_1B_ISCAN_ERROR,
8920 N_("Error while scanning inodes (%i): %m\n"),
8921 PROMPT_NONE, PR_FATAL },
8922
8923 /* Error allocating inode bitmap */
8924 { PR_1B_ALLOCATE_IBITMAP_ERROR,
8925 N_("@A @i @B (@i_dup_map): %m\n"),
8926 PROMPT_NONE, PR_FATAL },
8927
8928 /* Error while iterating over blocks */
8929 { PR_1B_BLOCK_ITERATE,
8930 N_("Error while iterating over @bs in @i %i (%s): %m\n"),
8931 PROMPT_NONE, 0 },
8932
8933 /* Error adjusting EA refcount */
8934 { PR_1B_ADJ_EA_REFCOUNT,
8935 N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
8936 PROMPT_NONE, 0 },
8937
8938
8939 /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
8940 { PR_1C_PASS_HEADER,
8941 N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
8942 PROMPT_NONE, 0 },
8943
8944
8945 /* Pass 1D: Reconciling multiply-claimed blocks */
8946 { PR_1D_PASS_HEADER,
8947 N_("Pass 1D: Reconciling @m @bs\n"),
8948 PROMPT_NONE, 0 },
8949
8950 /* File has duplicate blocks */
8951 { PR_1D_DUP_FILE,
8952 N_("File %Q (@i #%i, mod time %IM)\n"
8953 " has %B @m @b(s), shared with %N file(s):\n"),
8954 PROMPT_NONE, 0 },
8955
8956 /* List of files sharing duplicate blocks */
8957 { PR_1D_DUP_FILE_LIST,
8958 N_("\t%Q (@i #%i, mod time %IM)\n"),
8959 PROMPT_NONE, 0 },
8960
8961 /* File sharing blocks with filesystem metadata */
8962 { PR_1D_SHARE_METADATA,
8963 N_("\t<@f metadata>\n"),
8964 PROMPT_NONE, 0 },
8965
8966 /* Report of how many duplicate/bad inodes */
8967 { PR_1D_NUM_DUP_INODES,
8968 N_("(There are %N @is containing @m @bs.)\n\n"),
8969 PROMPT_NONE, 0 },
8970
8971 /* Duplicated blocks already reassigned or cloned. */
8972 { PR_1D_DUP_BLOCKS_DEALT,
8973 N_("@m @bs already reassigned or cloned.\n\n"),
8974 PROMPT_NONE, 0 },
8975
8976 /* Clone duplicate/bad blocks? */
8977 { PR_1D_CLONE_QUESTION,
8978 "", PROMPT_CLONE, PR_NO_OK },
8979
8980 /* Delete file? */
8981 { PR_1D_DELETE_QUESTION,
8982 "", PROMPT_DELETE, 0 },
8983
8984 /* Couldn't clone file (error) */
8985 { PR_1D_CLONE_ERROR,
8986 N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
8987
8988 /* Pass 2 errors */
8989
8990 /* Pass 2: Checking directory structure */
8991 { PR_2_PASS_HEADER,
8992 N_("Pass 2: Checking @d structure\n"),
8993 PROMPT_NONE, 0 },
8994
8995 /* Bad inode number for '.' */
8996 { PR_2_BAD_INODE_DOT,
8997 N_("@n @i number for '.' in @d @i %i.\n"),
8998 PROMPT_FIX, 0 },
8999
9000 /* Directory entry has bad inode number */
9001 { PR_2_BAD_INO,
9002 N_("@E has @n @i #: %Di.\n"),
9003 PROMPT_CLEAR, 0 },
9004
9005 /* Directory entry has deleted or unused inode */
9006 { PR_2_UNUSED_INODE,
9007 N_("@E has @D/unused @i %Di. "),
9008 PROMPT_CLEAR, PR_PREEN_OK },
9009
9010 /* Directry entry is link to '.' */
9011 { PR_2_LINK_DOT,
9012 N_("@E @L to '.' "),
9013 PROMPT_CLEAR, 0 },
9014
9015 /* Directory entry points to inode now located in a bad block */
9016 { PR_2_BB_INODE,
9017 N_("@E points to @i (%Di) located in a bad @b.\n"),
9018 PROMPT_CLEAR, 0 },
9019
9020 /* Directory entry contains a link to a directory */
9021 { PR_2_LINK_DIR,
9022 N_("@E @L to @d %P (%Di).\n"),
9023 PROMPT_CLEAR, 0 },
9024
9025 /* Directory entry contains a link to the root directry */
9026 { PR_2_LINK_ROOT,
9027 N_("@E @L to the @r.\n"),
9028 PROMPT_CLEAR, 0 },
9029
9030 /* Directory entry has illegal characters in its name */
9031 { PR_2_BAD_NAME,
9032 N_("@E has illegal characters in its name.\n"),
9033 PROMPT_FIX, 0 },
9034
9035 /* Missing '.' in directory inode */
9036 { PR_2_MISSING_DOT,
9037 N_("Missing '.' in @d @i %i.\n"),
9038 PROMPT_FIX, 0 },
9039
9040 /* Missing '..' in directory inode */
9041 { PR_2_MISSING_DOT_DOT,
9042 N_("Missing '..' in @d @i %i.\n"),
9043 PROMPT_FIX, 0 },
9044
9045 /* First entry in directory inode doesn't contain '.' */
9046 { PR_2_1ST_NOT_DOT,
9047 N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
9048 PROMPT_FIX, 0 },
9049
9050 /* Second entry in directory inode doesn't contain '..' */
9051 { PR_2_2ND_NOT_DOT_DOT,
9052 N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
9053 PROMPT_FIX, 0 },
9054
9055 /* i_faddr should be zero */
9056 { PR_2_FADDR_ZERO,
9057 N_("i_faddr @F %IF, @s zero.\n"),
9058 PROMPT_CLEAR, 0 },
9059
9060 /* i_file_acl should be zero */
9061 { PR_2_FILE_ACL_ZERO,
9062 N_("i_file_acl @F %If, @s zero.\n"),
9063 PROMPT_CLEAR, 0 },
9064
9065 /* i_dir_acl should be zero */
9066 { PR_2_DIR_ACL_ZERO,
9067 N_("i_dir_acl @F %Id, @s zero.\n"),
9068 PROMPT_CLEAR, 0 },
9069
9070 /* i_frag should be zero */
9071 { PR_2_FRAG_ZERO,
9072 N_("i_frag @F %N, @s zero.\n"),
9073 PROMPT_CLEAR, 0 },
9074
9075 /* i_fsize should be zero */
9076 { PR_2_FSIZE_ZERO,
9077 N_("i_fsize @F %N, @s zero.\n"),
9078 PROMPT_CLEAR, 0 },
9079
9080 /* inode has bad mode */
9081 { PR_2_BAD_MODE,
9082 N_("@i %i (%Q) has @n mode (%Im).\n"),
9083 PROMPT_CLEAR, 0 },
9084
9085 /* directory corrupted */
9086 { PR_2_DIR_CORRUPTED,
9087 N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
9088 PROMPT_SALVAGE, 0 },
9089
9090 /* filename too long */
9091 { PR_2_FILENAME_LONG,
9092 N_("@d @i %i, @b %B, offset %N: filename too long\n"),
9093 PROMPT_TRUNCATE, 0 },
9094
9095 /* Directory inode has a missing block (hole) */
9096 { PR_2_DIRECTORY_HOLE,
9097 N_("@d @i %i has an unallocated @b #%B. "),
9098 PROMPT_ALLOCATE, 0 },
9099
9100 /* '.' is not NULL terminated */
9101 { PR_2_DOT_NULL_TERM,
9102 N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
9103 PROMPT_FIX, 0 },
9104
9105 /* '..' is not NULL terminated */
9106 { PR_2_DOT_DOT_NULL_TERM,
9107 N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
9108 PROMPT_FIX, 0 },
9109
9110 /* Illegal character device inode */
9111 { PR_2_BAD_CHAR_DEV,
9112 N_("@i %i (%Q) is an @I character @v.\n"),
9113 PROMPT_CLEAR, 0 },
9114
9115 /* Illegal block device inode */
9116 { PR_2_BAD_BLOCK_DEV,
9117 N_("@i %i (%Q) is an @I @b @v.\n"),
9118 PROMPT_CLEAR, 0 },
9119
9120 /* Duplicate '.' entry */
9121 { PR_2_DUP_DOT,
9122 N_("@E is duplicate '.' @e.\n"),
9123 PROMPT_FIX, 0 },
9124
9125 /* Duplicate '..' entry */
9126 { PR_2_DUP_DOT_DOT,
9127 N_("@E is duplicate '..' @e.\n"),
9128 PROMPT_FIX, 0 },
9129
9130 /* Internal error: couldn't find dir_info */
9131 { PR_2_NO_DIRINFO,
9132 N_("Internal error: cannot find dir_info for %i.\n"),
9133 PROMPT_NONE, PR_FATAL },
9134
9135 /* Final rec_len is wrong */
9136 { PR_2_FINAL_RECLEN,
9137 N_("@E has rec_len of %Dr, @s %N.\n"),
9138 PROMPT_FIX, 0 },
9139
9140 /* Error allocating icount structure */
9141 { PR_2_ALLOCATE_ICOUNT,
9142 N_("@A icount structure: %m\n"),
9143 PROMPT_NONE, PR_FATAL },
9144
9145 /* Error iterating over directory blocks */
9146 { PR_2_DBLIST_ITERATE,
9147 N_("Error iterating over @d @bs: %m\n"),
9148 PROMPT_NONE, PR_FATAL },
9149
9150 /* Error reading directory block */
9151 { PR_2_READ_DIRBLOCK,
9152 N_("Error reading @d @b %b (@i %i): %m\n"),
9153 PROMPT_CONTINUE, 0 },
9154
9155 /* Error writing directory block */
9156 { PR_2_WRITE_DIRBLOCK,
9157 N_("Error writing @d @b %b (@i %i): %m\n"),
9158 PROMPT_CONTINUE, 0 },
9159
9160 /* Error allocating new directory block */
9161 { PR_2_ALLOC_DIRBOCK,
9162 N_("@A new @d @b for @i %i (%s): %m\n"),
9163 PROMPT_NONE, 0 },
9164
9165 /* Error deallocating inode */
9166 { PR_2_DEALLOC_INODE,
9167 N_("Error deallocating @i %i: %m\n"),
9168 PROMPT_NONE, PR_FATAL },
9169
9170 /* Directory entry for '.' is big. Split? */
9171 { PR_2_SPLIT_DOT,
9172 N_("@d @e for '.' is big. "),
9173 PROMPT_SPLIT, PR_NO_OK },
9174
9175 /* Illegal FIFO inode */
9176 { PR_2_BAD_FIFO,
9177 N_("@i %i (%Q) is an @I FIFO.\n"),
9178 PROMPT_CLEAR, 0 },
9179
9180 /* Illegal socket inode */
9181 { PR_2_BAD_SOCKET,
9182 N_("@i %i (%Q) is an @I socket.\n"),
9183 PROMPT_CLEAR, 0 },
9184
9185 /* Directory filetype not set */
9186 { PR_2_SET_FILETYPE,
9187 N_("Setting filetype for @E to %N.\n"),
9188 PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
9189
9190 /* Directory filetype incorrect */
9191 { PR_2_BAD_FILETYPE,
9192 N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
9193 PROMPT_FIX, 0 },
9194
9195 /* Directory filetype set on filesystem */
9196 { PR_2_CLEAR_FILETYPE,
9197 N_("@E has filetype set.\n"),
9198 PROMPT_CLEAR, PR_PREEN_OK },
9199
9200 /* Directory filename is null */
9201 { PR_2_NULL_NAME,
9202 N_("@E has a @z name.\n"),
9203 PROMPT_CLEAR, 0 },
9204
9205 /* Invalid symlink */
9206 { PR_2_INVALID_SYMLINK,
9207 N_("Symlink %Q (@i #%i) is @n.\n"),
9208 PROMPT_CLEAR, 0 },
9209
9210 /* i_file_acl (extended attribute block) is bad */
9211 { PR_2_FILE_ACL_BAD,
9212 N_("@a @b @F @n (%If).\n"),
9213 PROMPT_CLEAR, 0 },
9214
9215 /* Filesystem contains large files, but has no such flag in sb */
9216 { PR_2_FEATURE_LARGE_FILES,
9217 N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
9218 PROMPT_FIX, 0 },
9219
9220 /* Node in HTREE directory not referenced */
9221 { PR_2_HTREE_NOTREF,
9222 N_("@p @h %d: node (%B) not referenced\n"),
9223 PROMPT_NONE, 0 },
9224
9225 /* Node in HTREE directory referenced twice */
9226 { PR_2_HTREE_DUPREF,
9227 N_("@p @h %d: node (%B) referenced twice\n"),
9228 PROMPT_NONE, 0 },
9229
9230 /* Node in HTREE directory has bad min hash */
9231 { PR_2_HTREE_MIN_HASH,
9232 N_("@p @h %d: node (%B) has bad min hash\n"),
9233 PROMPT_NONE, 0 },
9234
9235 /* Node in HTREE directory has bad max hash */
9236 { PR_2_HTREE_MAX_HASH,
9237 N_("@p @h %d: node (%B) has bad max hash\n"),
9238 PROMPT_NONE, 0 },
9239
9240 /* Clear invalid HTREE directory */
9241 { PR_2_HTREE_CLEAR,
9242 N_("@n @h %d (%q). "), PROMPT_CLEAR, 0 },
9243
9244 /* Bad block in htree interior node */
9245 { PR_2_HTREE_BADBLK,
9246 N_("@p @h %d (%q): bad @b number %b.\n"),
9247 PROMPT_CLEAR_HTREE, 0 },
9248
9249 /* Error adjusting EA refcount */
9250 { PR_2_ADJ_EA_REFCOUNT,
9251 N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
9252 PROMPT_NONE, PR_FATAL },
9253
9254 /* Invalid HTREE root node */
9255 { PR_2_HTREE_BAD_ROOT,
9256 N_("@p @h %d: root node is @n\n"),
9257 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9258
9259 /* Invalid HTREE limit */
9260 { PR_2_HTREE_BAD_LIMIT,
9261 N_("@p @h %d: node (%B) has @n limit (%N)\n"),
9262 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9263
9264 /* Invalid HTREE count */
9265 { PR_2_HTREE_BAD_COUNT,
9266 N_("@p @h %d: node (%B) has @n count (%N)\n"),
9267 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9268
9269 /* HTREE interior node has out-of-order hashes in table */
9270 { PR_2_HTREE_HASH_ORDER,
9271 N_("@p @h %d: node (%B) has an unordered hash table\n"),
9272 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9273
9274 /* Node in HTREE directory has invalid depth */
9275 { PR_2_HTREE_BAD_DEPTH,
9276 N_("@p @h %d: node (%B) has @n depth\n"),
9277 PROMPT_NONE, 0 },
9278
9279 /* Duplicate directory entry found */
9280 { PR_2_DUPLICATE_DIRENT,
9281 N_("Duplicate @E found. "),
9282 PROMPT_CLEAR, 0 },
9283
9284 /* Non-unique filename found */
9285 { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
9286 N_("@E has a non-unique filename.\nRename to %s"),
9287 PROMPT_NULL, 0 },
9288
9289 /* Duplicate directory entry found */
9290 { PR_2_REPORT_DUP_DIRENT,
9291 N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
9292 PROMPT_NONE, 0 },
9293
9294 /* Pass 3 errors */
9295
9296 /* Pass 3: Checking directory connectivity */
9297 { PR_3_PASS_HEADER,
9298 N_("Pass 3: Checking @d connectivity\n"),
9299 PROMPT_NONE, 0 },
9300
9301 /* Root inode not allocated */
9302 { PR_3_NO_ROOT_INODE,
9303 N_("@r not allocated. "),
9304 PROMPT_ALLOCATE, 0 },
9305
9306 /* No room in lost+found */
9307 { PR_3_EXPAND_LF_DIR,
9308 N_("No room in @l @d. "),
9309 PROMPT_EXPAND, 0 },
9310
9311 /* Unconnected directory inode */
9312 { PR_3_UNCONNECTED_DIR,
9313 N_("Unconnected @d @i %i (%p)\n"),
9314 PROMPT_CONNECT, 0 },
9315
9316 /* /lost+found not found */
9317 { PR_3_NO_LF_DIR,
9318 N_("/@l not found. "),
9319 PROMPT_CREATE, PR_PREEN_OK },
9320
9321 /* .. entry is incorrect */
9322 { PR_3_BAD_DOT_DOT,
9323 N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
9324 PROMPT_FIX, 0 },
9325
9326 /* Bad or non-existent /lost+found. Cannot reconnect */
9327 { PR_3_NO_LPF,
9328 N_("Bad or non-existent /@l. Cannot reconnect.\n"),
9329 PROMPT_NONE, 0 },
9330
9331 /* Could not expand /lost+found */
9332 { PR_3_CANT_EXPAND_LPF,
9333 N_("Could not expand /@l: %m\n"),
9334 PROMPT_NONE, 0 },
9335
9336 /* Could not reconnect inode */
9337 { PR_3_CANT_RECONNECT,
9338 N_("Could not reconnect %i: %m\n"),
9339 PROMPT_NONE, 0 },
9340
9341 /* Error while trying to find /lost+found */
9342 { PR_3_ERR_FIND_LPF,
9343 N_("Error while trying to find /@l: %m\n"),
9344 PROMPT_NONE, 0 },
9345
9346 /* Error in ext2fs_new_block while creating /lost+found */
9347 { PR_3_ERR_LPF_NEW_BLOCK,
9348 N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
9349 PROMPT_NONE, 0 },
9350
9351 /* Error in ext2fs_new_inode while creating /lost+found */
9352 { PR_3_ERR_LPF_NEW_INODE,
9353 N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
9354 PROMPT_NONE, 0 },
9355
9356 /* Error in ext2fs_new_dir_block while creating /lost+found */
9357 { PR_3_ERR_LPF_NEW_DIR_BLOCK,
9358 N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
9359 PROMPT_NONE, 0 },
9360
9361 /* Error while writing directory block for /lost+found */
9362 { PR_3_ERR_LPF_WRITE_BLOCK,
9363 N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
9364 PROMPT_NONE, 0 },
9365
9366 /* Error while adjusting inode count */
9367 { PR_3_ADJUST_INODE,
9368 N_("Error while adjusting @i count on @i %i\n"),
9369 PROMPT_NONE, 0 },
9370
9371 /* Couldn't fix parent directory -- error */
9372 { PR_3_FIX_PARENT_ERR,
9373 N_("Couldn't fix parent of @i %i: %m\n\n"),
9374 PROMPT_NONE, 0 },
9375
9376 /* Couldn't fix parent directory -- couldn't find it */
9377 { PR_3_FIX_PARENT_NOFIND,
9378 N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
9379 PROMPT_NONE, 0 },
9380
9381 /* Error allocating inode bitmap */
9382 { PR_3_ALLOCATE_IBITMAP_ERROR,
9383 N_("@A @i @B (%N): %m\n"),
9384 PROMPT_NONE, PR_FATAL },
9385
9386 /* Error creating root directory */
9387 { PR_3_CREATE_ROOT_ERROR,
9388 N_("Error creating root @d (%s): %m\n"),
9389 PROMPT_NONE, PR_FATAL },
9390
9391 /* Error creating lost and found directory */
9392 { PR_3_CREATE_LPF_ERROR,
9393 N_("Error creating /@l @d (%s): %m\n"),
9394 PROMPT_NONE, PR_FATAL },
9395
9396 /* Root inode is not directory; aborting */
9397 { PR_3_ROOT_NOT_DIR_ABORT,
9398 N_("@r is not a @d; aborting.\n"),
9399 PROMPT_NONE, PR_FATAL },
9400
9401 /* Cannot proceed without a root inode. */
9402 { PR_3_NO_ROOT_INODE_ABORT,
9403 N_("can't proceed without a @r.\n"),
9404 PROMPT_NONE, PR_FATAL },
9405
9406 /* Internal error: couldn't find dir_info */
9407 { PR_3_NO_DIRINFO,
9408 N_("Internal error: cannot find dir_info for %i.\n"),
9409 PROMPT_NONE, PR_FATAL },
9410
9411 /* Lost+found not a directory */
9412 { PR_3_LPF_NOTDIR,
9413 N_("/@l is not a @d (ino=%i)\n"),
9414 PROMPT_UNLINK, 0 },
9415
9416 /* Pass 3A Directory Optimization */
9417
9418 /* Pass 3A: Optimizing directories */
9419 { PR_3A_PASS_HEADER,
9420 N_("Pass 3A: Optimizing directories\n"),
9421 PROMPT_NONE, PR_PREEN_NOMSG },
9422
9423 /* Error iterating over directories */
9424 { PR_3A_OPTIMIZE_ITER,
9425 N_("Failed to create dirs_to_hash iterator: %m"),
9426 PROMPT_NONE, 0 },
9427
9428 /* Error rehash directory */
9429 { PR_3A_OPTIMIZE_DIR_ERR,
9430 N_("Failed to optimize directory %q (%d): %m"),
9431 PROMPT_NONE, 0 },
9432
9433 /* Rehashing dir header */
9434 { PR_3A_OPTIMIZE_DIR_HEADER,
9435 N_("Optimizing directories: "),
9436 PROMPT_NONE, PR_MSG_ONLY },
9437
9438 /* Rehashing directory %d */
9439 { PR_3A_OPTIMIZE_DIR,
9440 " %d",
9441 PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
9442
9443 /* Rehashing dir end */
9444 { PR_3A_OPTIMIZE_DIR_END,
9445 "\n",
9446 PROMPT_NONE, PR_PREEN_NOHDR },
9447
9448 /* Pass 4 errors */
9449
9450 /* Pass 4: Checking reference counts */
9451 { PR_4_PASS_HEADER,
9452 N_("Pass 4: Checking reference counts\n"),
9453 PROMPT_NONE, 0 },
9454
9455 /* Unattached zero-length inode */
9456 { PR_4_ZERO_LEN_INODE,
9457 N_("@u @z @i %i. "),
9458 PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
9459
9460 /* Unattached inode */
9461 { PR_4_UNATTACHED_INODE,
9462 N_("@u @i %i\n"),
9463 PROMPT_CONNECT, 0 },
9464
9465 /* Inode ref count wrong */
9466 { PR_4_BAD_REF_COUNT,
9467 N_("@i %i ref count is %Il, @s %N. "),
9468 PROMPT_FIX, PR_PREEN_OK },
9469
9470 { PR_4_INCONSISTENT_COUNT,
9471 N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
9472 "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
9473 "@i_link_info[%i] is %N, @i.i_links_count is %Il. "
9474 "They @s the same!\n"),
9475 PROMPT_NONE, 0 },
9476
9477 /* Pass 5 errors */
9478
9479 /* Pass 5: Checking group summary information */
9480 { PR_5_PASS_HEADER,
9481 N_("Pass 5: Checking @g summary information\n"),
9482 PROMPT_NONE, 0 },
9483
9484 /* Padding at end of inode bitmap is not set. */
9485 { PR_5_INODE_BMAP_PADDING,
9486 N_("Padding at end of @i @B is not set. "),
9487 PROMPT_FIX, PR_PREEN_OK },
9488
9489 /* Padding at end of block bitmap is not set. */
9490 { PR_5_BLOCK_BMAP_PADDING,
9491 N_("Padding at end of @b @B is not set. "),
9492 PROMPT_FIX, PR_PREEN_OK },
9493
9494 /* Block bitmap differences header */
9495 { PR_5_BLOCK_BITMAP_HEADER,
9496 N_("@b @B differences: "),
9497 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
9498
9499 /* Block not used, but marked in bitmap */
9500 { PR_5_BLOCK_UNUSED,
9501 " -%b",
9502 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9503
9504 /* Block used, but not marked used in bitmap */
9505 { PR_5_BLOCK_USED,
9506 " +%b",
9507 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9508
9509 /* Block bitmap differences end */
9510 { PR_5_BLOCK_BITMAP_END,
9511 "\n",
9512 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9513
9514 /* Inode bitmap differences header */
9515 { PR_5_INODE_BITMAP_HEADER,
9516 N_("@i @B differences: "),
9517 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
9518
9519 /* Inode not used, but marked in bitmap */
9520 { PR_5_INODE_UNUSED,
9521 " -%i",
9522 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9523
9524 /* Inode used, but not marked used in bitmap */
9525 { PR_5_INODE_USED,
9526 " +%i",
9527 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9528
9529 /* Inode bitmap differences end */
9530 { PR_5_INODE_BITMAP_END,
9531 "\n",
9532 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9533
9534 /* Free inodes count for group wrong */
9535 { PR_5_FREE_INODE_COUNT_GROUP,
9536 N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
9537 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9538
9539 /* Directories count for group wrong */
9540 { PR_5_FREE_DIR_COUNT_GROUP,
9541 N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
9542 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9543
9544 /* Free inodes count wrong */
9545 { PR_5_FREE_INODE_COUNT,
9546 N_("Free @is count wrong (%i, counted=%j).\n"),
9547 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9548
9549 /* Free blocks count for group wrong */
9550 { PR_5_FREE_BLOCK_COUNT_GROUP,
9551 N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
9552 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9553
9554 /* Free blocks count wrong */
9555 { PR_5_FREE_BLOCK_COUNT,
9556 N_("Free @bs count wrong (%b, counted=%c).\n"),
9557 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9558
9559 /* Programming error: bitmap endpoints don't match */
9560 { PR_5_BMAP_ENDPOINTS,
9561 N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
9562 "match calculated @B endpoints (%i, %j)\n"),
9563 PROMPT_NONE, PR_FATAL },
9564
9565 /* Internal error: fudging end of bitmap */
9566 { PR_5_FUDGE_BITMAP_ERROR,
9567 N_("Internal error: fudging end of bitmap (%N)\n"),
9568 PROMPT_NONE, PR_FATAL },
9569
9570 /* Error copying in replacement inode bitmap */
9571 { PR_5_COPY_IBITMAP_ERROR,
9572 N_("Error copying in replacement @i @B: %m\n"),
9573 PROMPT_NONE, PR_FATAL },
9574
9575 /* Error copying in replacement block bitmap */
9576 { PR_5_COPY_BBITMAP_ERROR,
9577 N_("Error copying in replacement @b @B: %m\n"),
9578 PROMPT_NONE, PR_FATAL },
9579
9580 /* Block range not used, but marked in bitmap */
9581 { PR_5_BLOCK_RANGE_UNUSED,
9582 " -(%b--%c)",
9583 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9584
9585 /* Block range used, but not marked used in bitmap */
9586 { PR_5_BLOCK_RANGE_USED,
9587 " +(%b--%c)",
9588 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9589
9590 /* Inode range not used, but marked in bitmap */
9591 { PR_5_INODE_RANGE_UNUSED,
9592 " -(%i--%j)",
9593 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9594
9595 /* Inode range used, but not marked used in bitmap */
9596 { PR_5_INODE_RANGE_USED,
9597 " +(%i--%j)",
9598 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9599
9600 { 0 }
9601};
9602
9603/*
9604 * This is the latch flags register. It allows several problems to be
9605 * "latched" together. This means that the user has to answer but one
9606 * question for the set of problems, and all of the associated
9607 * problems will be either fixed or not fixed.
9608 */
9609static struct latch_descr pr_latch_info[] = {
9610 { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
9611 { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
9612 { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
9613 { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
9614 { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
9615 { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
9616 { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
9617 { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
9618 { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
9619 { -1, 0, 0 },
9620};
9621
9622static const struct e2fsck_problem *find_problem(problem_t code)
9623{
9624 int i;
9625
9626 for (i=0; problem_table[i].e2p_code; i++) {
9627 if (problem_table[i].e2p_code == code)
9628 return &problem_table[i];
9629 }
9630 return 0;
9631}
9632
9633static struct latch_descr *find_latch(int code)
9634{
9635 int i;
9636
9637 for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
9638 if (pr_latch_info[i].latch_code == code)
9639 return &pr_latch_info[i];
9640 }
9641 return 0;
9642}
9643
9644int end_problem_latch(e2fsck_t ctx, int mask)
9645{
9646 struct latch_descr *ldesc;
9647 struct problem_context pctx;
9648 int answer = -1;
9649
9650 ldesc = find_latch(mask);
9651 if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
9652 clear_problem_context(&pctx);
9653 answer = fix_problem(ctx, ldesc->end_message, &pctx);
9654 }
9655 ldesc->flags &= ~(PRL_VARIABLE);
9656 return answer;
9657}
9658
9659int set_latch_flags(int mask, int setflags, int clearflags)
9660{
9661 struct latch_descr *ldesc;
9662
9663 ldesc = find_latch(mask);
9664 if (!ldesc)
9665 return -1;
9666 ldesc->flags |= setflags;
9667 ldesc->flags &= ~clearflags;
9668 return 0;
9669}
9670
9671void clear_problem_context(struct problem_context *ctx)
9672{
9673 memset(ctx, 0, sizeof(struct problem_context));
9674 ctx->blkcount = -1;
9675 ctx->group = -1;
9676}
9677
9678int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
9679{
9680 ext2_filsys fs = ctx->fs;
9681 const struct e2fsck_problem *ptr;
9682 struct latch_descr *ldesc = NULL;
9683 const char *message;
9684 int def_yn, answer, ans;
9685 int print_answer = 0;
9686 int suppress = 0;
9687
9688 ptr = find_problem(code);
9689 if (!ptr) {
9690 printf(_("Unhandled error code (0x%x)!\n"), code);
9691 return 0;
9692 }
9693 def_yn = 1;
9694 if ((ptr->flags & PR_NO_DEFAULT) ||
9695 ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
9696 (ctx->options & E2F_OPT_NO))
9697 def_yn= 0;
9698
9699 /*
9700 * Do special latch processing. This is where we ask the
9701 * latch question, if it exists
9702 */
9703 if (ptr->flags & PR_LATCH_MASK) {
9704 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
9705 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
9706 ans = fix_problem(ctx, ldesc->question, pctx);
9707 if (ans == 1)
9708 ldesc->flags |= PRL_YES;
9709 if (ans == 0)
9710 ldesc->flags |= PRL_NO;
9711 ldesc->flags |= PRL_LATCHED;
9712 }
9713 if (ldesc->flags & PRL_SUPPRESS)
9714 suppress++;
9715 }
9716 if ((ptr->flags & PR_PREEN_NOMSG) &&
9717 (ctx->options & E2F_OPT_PREEN))
9718 suppress++;
9719 if ((ptr->flags & PR_NO_NOMSG) &&
9720 (ctx->options & E2F_OPT_NO))
9721 suppress++;
9722 if (!suppress) {
9723 message = ptr->e2p_description;
9724 if ((ctx->options & E2F_OPT_PREEN) &&
9725 !(ptr->flags & PR_PREEN_NOHDR)) {
9726 printf("%s: ", ctx->device_name ?
9727 ctx->device_name : ctx->filesystem_name);
9728 }
9729 if (*message)
9730 print_e2fsck_message(ctx, _(message), pctx, 1);
9731 }
9732 if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
9733 preenhalt(ctx);
9734
9735 if (ptr->flags & PR_FATAL)
9736 bb_error_msg_and_die(0);
9737
9738 if (ptr->prompt == PROMPT_NONE) {
9739 if (ptr->flags & PR_NOCOLLATE)
9740 answer = -1;
9741 else
9742 answer = def_yn;
9743 } else {
9744 if (ctx->options & E2F_OPT_PREEN) {
9745 answer = def_yn;
9746 if (!(ptr->flags & PR_PREEN_NOMSG))
9747 print_answer = 1;
9748 } else if ((ptr->flags & PR_LATCH_MASK) &&
9749 (ldesc->flags & (PRL_YES | PRL_NO))) {
9750 if (!suppress)
9751 print_answer = 1;
9752 if (ldesc->flags & PRL_YES)
9753 answer = 1;
9754 else
9755 answer = 0;
9756 } else
9757 answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
9758 if (!answer && !(ptr->flags & PR_NO_OK))
9759 ext2fs_unmark_valid(fs);
9760
9761 if (print_answer)
9762 printf("%s.\n", answer ?
9763 _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
9764 }
9765
9766 if ((ptr->prompt == PROMPT_ABORT) && answer)
9767 bb_error_msg_and_die(0);
9768
9769 if (ptr->flags & PR_AFTER_CODE)
9770 answer = fix_problem(ctx, ptr->second_code, pctx);
9771
9772 return answer;
9773}
9774
9775/*
9776 * linux/fs/recovery.c
9777 *
9778 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
9779 */
9780
9781/*
9782 * Maintain information about the progress of the recovery job, so that
9783 * the different passes can carry information between them.
9784 */
9785struct recovery_info
9786{
9787 tid_t start_transaction;
9788 tid_t end_transaction;
9789
9790 int nr_replays;
9791 int nr_revokes;
9792 int nr_revoke_hits;
9793};
9794
9795enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
9796static int do_one_pass(journal_t *journal,
9797 struct recovery_info *info, enum passtype pass);
9798static int scan_revoke_records(journal_t *, struct buffer_head *,
9799 tid_t, struct recovery_info *);
9800
9801/*
9802 * Read a block from the journal
9803 */
9804
9805static int jread(struct buffer_head **bhp, journal_t *journal,
9806 unsigned int offset)
9807{
9808 int err;
9809 unsigned long blocknr;
9810 struct buffer_head *bh;
9811
9812 *bhp = NULL;
9813
9814 err = journal_bmap(journal, offset, &blocknr);
9815
9816 if (err) {
9817 printf("JBD: bad block at offset %u\n", offset);
9818 return err;
9819 }
9820
9821 bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
9822 if (!bh)
9823 return -ENOMEM;
9824
9825 if (!buffer_uptodate(bh)) {
9826 /* If this is a brand new buffer, start readahead.
9827 Otherwise, we assume we are already reading it. */
9828 if (!buffer_req(bh))
9829 do_readahead(journal, offset);
9830 wait_on_buffer(bh);
9831 }
9832
9833 if (!buffer_uptodate(bh)) {
9834 printf("JBD: Failed to read block at offset %u\n", offset);
9835 brelse(bh);
9836 return -EIO;
9837 }
9838
9839 *bhp = bh;
9840 return 0;
9841}
9842
9843
9844/*
9845 * Count the number of in-use tags in a journal descriptor block.
9846 */
9847
9848static int count_tags(struct buffer_head *bh, int size)
9849{
9850 char * tagp;
9851 journal_block_tag_t * tag;
9852 int nr = 0;
9853
9854 tagp = &bh->b_data[sizeof(journal_header_t)];
9855
9856 while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
9857 tag = (journal_block_tag_t *) tagp;
9858
9859 nr++;
9860 tagp += sizeof(journal_block_tag_t);
9861 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
9862 tagp += 16;
9863
9864 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
9865 break;
9866 }
9867
9868 return nr;
9869}
9870
9871
9872/* Make sure we wrap around the log correctly! */
9873#define wrap(journal, var) \
9874do { \
9875 if (var >= (journal)->j_last) \
9876 var -= ((journal)->j_last - (journal)->j_first); \
9877} while (0)
9878
9879/**
9880 * int journal_recover(journal_t *journal) - recovers a on-disk journal
9881 * @journal: the journal to recover
9882 *
9883 * The primary function for recovering the log contents when mounting a
9884 * journaled device.
9885 *
9886 * Recovery is done in three passes. In the first pass, we look for the
9887 * end of the log. In the second, we assemble the list of revoke
9888 * blocks. In the third and final pass, we replay any un-revoked blocks
9889 * in the log.
9890 */
9891int journal_recover(journal_t *journal)
9892{
9893 int err;
9894 journal_superblock_t * sb;
9895
9896 struct recovery_info info;
9897
9898 memset(&info, 0, sizeof(info));
9899 sb = journal->j_superblock;
9900
9901 /*
9902 * The journal superblock's s_start field (the current log head)
9903 * is always zero if, and only if, the journal was cleanly
9904 * unmounted.
9905 */
9906
9907 if (!sb->s_start) {
9908 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
9909 return 0;
9910 }
9911
9912 err = do_one_pass(journal, &info, PASS_SCAN);
9913 if (!err)
9914 err = do_one_pass(journal, &info, PASS_REVOKE);
9915 if (!err)
9916 err = do_one_pass(journal, &info, PASS_REPLAY);
9917
9918 /* Restart the log at the next transaction ID, thus invalidating
9919 * any existing commit records in the log. */
9920 journal->j_transaction_sequence = ++info.end_transaction;
9921
9922 journal_clear_revoke(journal);
9923 sync_blockdev(journal->j_fs_dev);
9924 return err;
9925}
9926
9927static int do_one_pass(journal_t *journal,
9928 struct recovery_info *info, enum passtype pass)
9929{
9930 unsigned int first_commit_ID, next_commit_ID;
9931 unsigned long next_log_block;
9932 int err, success = 0;
9933 journal_superblock_t * sb;
9934 journal_header_t * tmp;
9935 struct buffer_head * bh;
9936 unsigned int sequence;
9937 int blocktype;
9938
9939 /* Precompute the maximum metadata descriptors in a descriptor block */
9940 int MAX_BLOCKS_PER_DESC;
9941 MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
9942 / sizeof(journal_block_tag_t));
9943
9944 /*
9945 * First thing is to establish what we expect to find in the log
9946 * (in terms of transaction IDs), and where (in terms of log
9947 * block offsets): query the superblock.
9948 */
9949
9950 sb = journal->j_superblock;
9951 next_commit_ID = ntohl(sb->s_sequence);
9952 next_log_block = ntohl(sb->s_start);
9953
9954 first_commit_ID = next_commit_ID;
9955 if (pass == PASS_SCAN)
9956 info->start_transaction = first_commit_ID;
9957
9958 /*
9959 * Now we walk through the log, transaction by transaction,
9960 * making sure that each transaction has a commit block in the
9961 * expected place. Each complete transaction gets replayed back
9962 * into the main filesystem.
9963 */
9964
9965 while (1) {
9966 int flags;
9967 char * tagp;
9968 journal_block_tag_t * tag;
9969 struct buffer_head * obh;
9970 struct buffer_head * nbh;
9971
9972 /* If we already know where to stop the log traversal,
9973 * check right now that we haven't gone past the end of
9974 * the log. */
9975
9976 if (pass != PASS_SCAN)
9977 if (tid_geq(next_commit_ID, info->end_transaction))
9978 break;
9979
9980 /* Skip over each chunk of the transaction looking
9981 * either the next descriptor block or the final commit
9982 * record. */
9983
9984 err = jread(&bh, journal, next_log_block);
9985 if (err)
9986 goto failed;
9987
9988 next_log_block++;
9989 wrap(journal, next_log_block);
9990
9991 /* What kind of buffer is it?
9992 *
9993 * If it is a descriptor block, check that it has the
9994 * expected sequence number. Otherwise, we're all done
9995 * here. */
9996
9997 tmp = (journal_header_t *)bh->b_data;
9998
9999 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
10000 brelse(bh);
10001 break;
10002 }
10003
10004 blocktype = ntohl(tmp->h_blocktype);
10005 sequence = ntohl(tmp->h_sequence);
10006
10007 if (sequence != next_commit_ID) {
10008 brelse(bh);
10009 break;
10010 }
10011
10012 /* OK, we have a valid descriptor block which matches
10013 * all of the sequence number checks. What are we going
10014 * to do with it? That depends on the pass... */
10015
10016 switch (blocktype) {
10017 case JFS_DESCRIPTOR_BLOCK:
10018 /* If it is a valid descriptor block, replay it
10019 * in pass REPLAY; otherwise, just skip over the
10020 * blocks it describes. */
10021 if (pass != PASS_REPLAY) {
10022 next_log_block +=
10023 count_tags(bh, journal->j_blocksize);
10024 wrap(journal, next_log_block);
10025 brelse(bh);
10026 continue;
10027 }
10028
10029 /* A descriptor block: we can now write all of
10030 * the data blocks. Yay, useful work is finally
10031 * getting done here! */
10032
10033 tagp = &bh->b_data[sizeof(journal_header_t)];
10034 while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
10035 <= journal->j_blocksize) {
10036 unsigned long io_block;
10037
10038 tag = (journal_block_tag_t *) tagp;
10039 flags = ntohl(tag->t_flags);
10040
10041 io_block = next_log_block++;
10042 wrap(journal, next_log_block);
10043 err = jread(&obh, journal, io_block);
10044 if (err) {
10045 /* Recover what we can, but
10046 * report failure at the end. */
10047 success = err;
10048 printf("JBD: IO error %d recovering "
10049 "block %ld in log\n",
10050 err, io_block);
10051 } else {
10052 unsigned long blocknr;
10053
10054 blocknr = ntohl(tag->t_blocknr);
10055
10056 /* If the block has been
10057 * revoked, then we're all done
10058 * here. */
10059 if (journal_test_revoke
10060 (journal, blocknr,
10061 next_commit_ID)) {
10062 brelse(obh);
10063 ++info->nr_revoke_hits;
10064 goto skip_write;
10065 }
10066
10067 /* Find a buffer for the new
10068 * data being restored */
10069 nbh = getblk(journal->j_fs_dev,
10070 blocknr,
10071 journal->j_blocksize);
10072 if (nbh == NULL) {
10073 printf("JBD: Out of memory "
10074 "during recovery.\n");
10075 err = -ENOMEM;
10076 brelse(bh);
10077 brelse(obh);
10078 goto failed;
10079 }
10080
10081 lock_buffer(nbh);
10082 memcpy(nbh->b_data, obh->b_data,
10083 journal->j_blocksize);
10084 if (flags & JFS_FLAG_ESCAPE) {
10085 *((unsigned int *)bh->b_data) =
10086 htonl(JFS_MAGIC_NUMBER);
10087 }
10088
10089 mark_buffer_uptodate(nbh, 1);
10090 mark_buffer_dirty(nbh);
10091 ++info->nr_replays;
10092 /* ll_rw_block(WRITE, 1, &nbh); */
10093 unlock_buffer(nbh);
10094 brelse(obh);
10095 brelse(nbh);
10096 }
10097
10098 skip_write:
10099 tagp += sizeof(journal_block_tag_t);
10100 if (!(flags & JFS_FLAG_SAME_UUID))
10101 tagp += 16;
10102
10103 if (flags & JFS_FLAG_LAST_TAG)
10104 break;
10105 }
10106
10107 brelse(bh);
10108 continue;
10109
10110 case JFS_COMMIT_BLOCK:
10111 /* Found an expected commit block: not much to
10112 * do other than move on to the next sequence
10113 * number. */
10114 brelse(bh);
10115 next_commit_ID++;
10116 continue;
10117
10118 case JFS_REVOKE_BLOCK:
10119 /* If we aren't in the REVOKE pass, then we can
10120 * just skip over this block. */
10121 if (pass != PASS_REVOKE) {
10122 brelse(bh);
10123 continue;
10124 }
10125
10126 err = scan_revoke_records(journal, bh,
10127 next_commit_ID, info);
10128 brelse(bh);
10129 if (err)
10130 goto failed;
10131 continue;
10132
10133 default:
10134 goto done;
10135 }
10136 }
10137
10138 done:
10139 /*
10140 * We broke out of the log scan loop: either we came to the
10141 * known end of the log or we found an unexpected block in the
10142 * log. If the latter happened, then we know that the "current"
10143 * transaction marks the end of the valid log.
10144 */
10145
10146 if (pass == PASS_SCAN)
10147 info->end_transaction = next_commit_ID;
10148 else {
10149 /* It's really bad news if different passes end up at
10150 * different places (but possible due to IO errors). */
10151 if (info->end_transaction != next_commit_ID) {
10152 printf("JBD: recovery pass %d ended at "
10153 "transaction %u, expected %u\n",
10154 pass, next_commit_ID, info->end_transaction);
10155 if (!success)
10156 success = -EIO;
10157 }
10158 }
10159
10160 return success;
10161
10162 failed:
10163 return err;
10164}
10165
10166
10167/* Scan a revoke record, marking all blocks mentioned as revoked. */
10168
10169static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
10170 tid_t sequence, struct recovery_info *info)
10171{
10172 journal_revoke_header_t *header;
10173 int offset, max;
10174
10175 header = (journal_revoke_header_t *) bh->b_data;
10176 offset = sizeof(journal_revoke_header_t);
10177 max = ntohl(header->r_count);
10178
10179 while (offset < max) {
10180 unsigned long blocknr;
10181 int err;
10182
10183 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
10184 offset += 4;
10185 err = journal_set_revoke(journal, blocknr, sequence);
10186 if (err)
10187 return err;
10188 ++info->nr_revokes;
10189 }
10190 return 0;
10191}
10192
10193
10194/*
10195 * rehash.c --- rebuild hash tree directories
10196 *
10197 * This algorithm is designed for simplicity of implementation and to
10198 * pack the directory as much as possible. It however requires twice
10199 * as much memory as the size of the directory. The maximum size
10200 * directory supported using a 4k blocksize is roughly a gigabyte, and
10201 * so there may very well be problems with machines that don't have
10202 * virtual memory, and obscenely large directories.
10203 *
10204 * An alternate algorithm which is much more disk intensive could be
10205 * written, and probably will need to be written in the future. The
10206 * design goals of such an algorithm are: (a) use (roughly) constant
10207 * amounts of memory, no matter how large the directory, (b) the
10208 * directory must be safe at all times, even if e2fsck is interrupted
10209 * in the middle, (c) we must use minimal amounts of extra disk
10210 * blocks. This pretty much requires an incremental approach, where
10211 * we are reading from one part of the directory, and inserting into
10212 * the front half. So the algorithm will have to keep track of a
10213 * moving block boundary between the new tree and the old tree, and
10214 * files will need to be moved from the old directory and inserted
10215 * into the new tree. If the new directory requires space which isn't
10216 * yet available, blocks from the beginning part of the old directory
10217 * may need to be moved to the end of the directory to make room for
10218 * the new tree:
10219 *
10220 * --------------------------------------------------------
10221 * | new tree | | old tree |
10222 * --------------------------------------------------------
10223 * ^ ptr ^ptr
10224 * tail new head old
10225 *
10226 * This is going to be a pain in the tuckus to implement, and will
10227 * require a lot more disk accesses. So I'm going to skip it for now;
10228 * it's only really going to be an issue for really, really big
10229 * filesystems (when we reach the level of tens of millions of files
10230 * in a single directory). It will probably be easier to simply
10231 * require that e2fsck use VM first.
10232 */
10233
10234struct fill_dir_struct {
10235 char *buf;
10236 struct ext2_inode *inode;
10237 int err;
10238 e2fsck_t ctx;
10239 struct hash_entry *harray;
10240 int max_array, num_array;
10241 int dir_size;
10242 int compress;
10243 ino_t parent;
10244};
10245
10246struct hash_entry {
10247 ext2_dirhash_t hash;
10248 ext2_dirhash_t minor_hash;
10249 struct ext2_dir_entry *dir;
10250};
10251
10252struct out_dir {
10253 int num;
10254 int max;
10255 char *buf;
10256 ext2_dirhash_t *hashes;
10257};
10258
10259static int fill_dir_block(ext2_filsys fs,
10260 blk_t *block_nr,
10261 e2_blkcnt_t blockcnt,
10262 blk_t ref_block FSCK_ATTR((unused)),
10263 int ref_offset FSCK_ATTR((unused)),
10264 void *priv_data)
10265{
10266 struct fill_dir_struct *fd = (struct fill_dir_struct *) priv_data;
10267 struct hash_entry *new_array, *ent;
10268 struct ext2_dir_entry *dirent;
10269 char *dir;
10270 unsigned int offset, dir_offset;
10271
10272 if (blockcnt < 0)
10273 return 0;
10274
10275 offset = blockcnt * fs->blocksize;
10276 if (offset + fs->blocksize > fd->inode->i_size) {
10277 fd->err = EXT2_ET_DIR_CORRUPTED;
10278 return BLOCK_ABORT;
10279 }
10280 dir = (fd->buf+offset);
10281 if (HOLE_BLKADDR(*block_nr)) {
10282 memset(dir, 0, fs->blocksize);
10283 dirent = (struct ext2_dir_entry *) dir;
10284 dirent->rec_len = fs->blocksize;
10285 } else {
10286 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
10287 if (fd->err)
10288 return BLOCK_ABORT;
10289 }
10290 /* While the directory block is "hot", index it. */
10291 dir_offset = 0;
10292 while (dir_offset < fs->blocksize) {
10293 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
10294 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
10295 (dirent->rec_len < 8) ||
10296 ((dirent->rec_len % 4) != 0) ||
10297 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
10298 fd->err = EXT2_ET_DIR_CORRUPTED;
10299 return BLOCK_ABORT;
10300 }
10301 dir_offset += dirent->rec_len;
10302 if (dirent->inode == 0)
10303 continue;
10304 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
10305 (dirent->name[0] == '.'))
10306 continue;
10307 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
10308 (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
10309 fd->parent = dirent->inode;
10310 continue;
10311 }
10312 if (fd->num_array >= fd->max_array) {
10313 new_array = xrealloc(fd->harray,
10314 sizeof(struct hash_entry) * (fd->max_array+500));
10315 fd->harray = new_array;
10316 fd->max_array += 500;
10317 }
10318 ent = fd->harray + fd->num_array++;
10319 ent->dir = dirent;
10320 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
10321 if (fd->compress)
10322 ent->hash = ent->minor_hash = 0;
10323 else {
10324 fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
10325 dirent->name,
10326 dirent->name_len & 0xFF,
10327 fs->super->s_hash_seed,
10328 &ent->hash, &ent->minor_hash);
10329 if (fd->err)
10330 return BLOCK_ABORT;
10331 }
10332 }
10333
10334 return 0;
10335}
10336
10337/* Used for sorting the hash entry */
10338static int name_cmp(const void *a, const void *b)
10339{
10340 const struct hash_entry *he_a = (const struct hash_entry *) a;
10341 const struct hash_entry *he_b = (const struct hash_entry *) b;
10342 int ret;
10343 int min_len;
10344
10345 min_len = he_a->dir->name_len;
10346 if (min_len > he_b->dir->name_len)
10347 min_len = he_b->dir->name_len;
10348
10349 ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
10350 if (ret == 0) {
10351 if (he_a->dir->name_len > he_b->dir->name_len)
10352 ret = 1;
10353 else if (he_a->dir->name_len < he_b->dir->name_len)
10354 ret = -1;
10355 else
10356 ret = he_b->dir->inode - he_a->dir->inode;
10357 }
10358 return ret;
10359}
10360
10361/* Used for sorting the hash entry */
10362static int hash_cmp(const void *a, const void *b)
10363{
10364 const struct hash_entry *he_a = (const struct hash_entry *) a;
10365 const struct hash_entry *he_b = (const struct hash_entry *) b;
10366 int ret;
10367
10368 if (he_a->hash > he_b->hash)
10369 ret = 1;
10370 else if (he_a->hash < he_b->hash)
10371 ret = -1;
10372 else {
10373 if (he_a->minor_hash > he_b->minor_hash)
10374 ret = 1;
10375 else if (he_a->minor_hash < he_b->minor_hash)
10376 ret = -1;
10377 else
10378 ret = name_cmp(a, b);
10379 }
10380 return ret;
10381}
10382
10383static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
10384 int blocks)
10385{
10386 void *new_mem;
10387
10388 if (outdir->max) {
10389 new_mem = xrealloc(outdir->buf, blocks * fs->blocksize);
10390 outdir->buf = new_mem;
10391 new_mem = xrealloc(outdir->hashes,
10392 blocks * sizeof(ext2_dirhash_t));
10393 outdir->hashes = new_mem;
10394 } else {
10395 outdir->buf = xmalloc(blocks * fs->blocksize);
10396 outdir->hashes = xmalloc(blocks * sizeof(ext2_dirhash_t));
10397 outdir->num = 0;
10398 }
10399 outdir->max = blocks;
10400 return 0;
10401}
10402
10403static void free_out_dir(struct out_dir *outdir)
10404{
10405 free(outdir->buf);
10406 free(outdir->hashes);
10407 outdir->max = 0;
10408 outdir->num =0;
10409}
10410
10411static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
10412 char ** ret)
10413{
10414 errcode_t retval;
10415
10416 if (outdir->num >= outdir->max) {
10417 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
10418 if (retval)
10419 return retval;
10420 }
10421 *ret = outdir->buf + (outdir->num++ * fs->blocksize);
10422 memset(*ret, 0, fs->blocksize);
10423 return 0;
10424}
10425
10426/*
10427 * This function is used to make a unique filename. We do this by
10428 * appending ~0, and then incrementing the number. However, we cannot
10429 * expand the length of the filename beyond the padding available in
10430 * the directory entry.
10431 */
10432static void mutate_name(char *str, __u16 *len)
10433{
10434 int i;
10435 __u16 l = *len & 0xFF, h = *len & 0xff00;
10436
10437 /*
10438 * First check to see if it looks the name has been mutated
10439 * already
10440 */
10441 for (i = l-1; i > 0; i--) {
10442 if (!isdigit(str[i]))
10443 break;
10444 }
10445 if ((i == l-1) || (str[i] != '~')) {
10446 if (((l-1) & 3) < 2)
10447 l += 2;
10448 else
10449 l = (l+3) & ~3;
10450 str[l-2] = '~';
10451 str[l-1] = '0';
10452 *len = l | h;
10453 return;
10454 }
10455 for (i = l-1; i >= 0; i--) {
10456 if (isdigit(str[i])) {
10457 if (str[i] == '9')
10458 str[i] = '0';
10459 else {
10460 str[i]++;
10461 return;
10462 }
10463 continue;
10464 }
10465 if (i == 1) {
10466 if (str[0] == 'z')
10467 str[0] = 'A';
10468 else if (str[0] == 'Z') {
10469 str[0] = '~';
10470 str[1] = '0';
10471 } else
10472 str[0]++;
10473 } else if (i > 0) {
10474 str[i] = '1';
10475 str[i-1] = '~';
10476 } else {
10477 if (str[0] == '~')
10478 str[0] = 'a';
10479 else
10480 str[0]++;
10481 }
10482 break;
10483 }
10484}
10485
10486static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
10487 ext2_ino_t ino,
10488 struct fill_dir_struct *fd)
10489{
10490 struct problem_context pctx;
10491 struct hash_entry *ent, *prev;
10492 int i, j;
10493 int fixed = 0;
10494 char new_name[256];
10495 __u16 new_len;
10496
10497 clear_problem_context(&pctx);
10498 pctx.ino = ino;
10499
10500 for (i=1; i < fd->num_array; i++) {
10501 ent = fd->harray + i;
10502 prev = ent - 1;
10503 if (!ent->dir->inode ||
10504 ((ent->dir->name_len & 0xFF) !=
10505 (prev->dir->name_len & 0xFF)) ||
10506 (strncmp(ent->dir->name, prev->dir->name,
10507 ent->dir->name_len & 0xFF)))
10508 continue;
10509 pctx.dirent = ent->dir;
10510 if ((ent->dir->inode == prev->dir->inode) &&
10511 fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
10512 e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
10513 ent->dir->inode = 0;
10514 fixed++;
10515 continue;
10516 }
10517 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
10518 new_len = ent->dir->name_len;
10519 mutate_name(new_name, &new_len);
10520 for (j=0; j < fd->num_array; j++) {
10521 if ((i==j) ||
10522 ((ent->dir->name_len & 0xFF) !=
10523 (fd->harray[j].dir->name_len & 0xFF)) ||
10524 (strncmp(new_name, fd->harray[j].dir->name,
10525 new_len & 0xFF)))
10526 continue;
10527 mutate_name(new_name, &new_len);
10528
10529 j = -1;
10530 }
10531 new_name[new_len & 0xFF] = 0;
10532 pctx.str = new_name;
10533 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
10534 memcpy(ent->dir->name, new_name, new_len & 0xFF);
10535 ent->dir->name_len = new_len;
10536 ext2fs_dirhash(fs->super->s_def_hash_version,
10537 ent->dir->name,
10538 ent->dir->name_len & 0xFF,
10539 fs->super->s_hash_seed,
10540 &ent->hash, &ent->minor_hash);
10541 fixed++;
10542 }
10543 }
10544 return fixed;
10545}
10546
10547
10548static errcode_t copy_dir_entries(ext2_filsys fs,
10549 struct fill_dir_struct *fd,
10550 struct out_dir *outdir)
10551{
10552 errcode_t retval;
10553 char *block_start;
10554 struct hash_entry *ent;
10555 struct ext2_dir_entry *dirent;
10556 int i, rec_len, left;
10557 ext2_dirhash_t prev_hash;
10558 int offset;
10559
10560 outdir->max = 0;
10561 retval = alloc_size_dir(fs, outdir,
10562 (fd->dir_size / fs->blocksize) + 2);
10563 if (retval)
10564 return retval;
10565 outdir->num = fd->compress ? 0 : 1;
10566 offset = 0;
10567 outdir->hashes[0] = 0;
10568 prev_hash = 1;
10569 if ((retval = get_next_block(fs, outdir, &block_start)))
10570 return retval;
10571 dirent = (struct ext2_dir_entry *) block_start;
10572 left = fs->blocksize;
10573 for (i=0; i < fd->num_array; i++) {
10574 ent = fd->harray + i;
10575 if (ent->dir->inode == 0)
10576 continue;
10577 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
10578 if (rec_len > left) {
10579 if (left)
10580 dirent->rec_len += left;
10581 if ((retval = get_next_block(fs, outdir,
10582 &block_start)))
10583 return retval;
10584 offset = 0;
10585 }
10586 left = fs->blocksize - offset;
10587 dirent = (struct ext2_dir_entry *) (block_start + offset);
10588 if (offset == 0) {
10589 if (ent->hash == prev_hash)
10590 outdir->hashes[outdir->num-1] = ent->hash | 1;
10591 else
10592 outdir->hashes[outdir->num-1] = ent->hash;
10593 }
10594 dirent->inode = ent->dir->inode;
10595 dirent->name_len = ent->dir->name_len;
10596 dirent->rec_len = rec_len;
10597 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
10598 offset += rec_len;
10599 left -= rec_len;
10600 if (left < 12) {
10601 dirent->rec_len += left;
10602 offset += left;
10603 left = 0;
10604 }
10605 prev_hash = ent->hash;
10606 }
10607 if (left)
10608 dirent->rec_len += left;
10609
10610 return 0;
10611}
10612
10613
10614static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
10615 ext2_ino_t ino, ext2_ino_t parent)
10616{
10617 struct ext2_dir_entry *dir;
10618 struct ext2_dx_root_info *root;
10619 struct ext2_dx_countlimit *limits;
10620 int filetype = 0;
10621
10622 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
10623 filetype = EXT2_FT_DIR << 8;
10624
10625 memset(buf, 0, fs->blocksize);
10626 dir = (struct ext2_dir_entry *) buf;
10627 dir->inode = ino;
10628 dir->name[0] = '.';
10629 dir->name_len = 1 | filetype;
10630 dir->rec_len = 12;
10631 dir = (struct ext2_dir_entry *) (buf + 12);
10632 dir->inode = parent;
10633 dir->name[0] = '.';
10634 dir->name[1] = '.';
10635 dir->name_len = 2 | filetype;
10636 dir->rec_len = fs->blocksize - 12;
10637
10638 root = (struct ext2_dx_root_info *) (buf+24);
10639 root->reserved_zero = 0;
10640 root->hash_version = fs->super->s_def_hash_version;
10641 root->info_length = 8;
10642 root->indirect_levels = 0;
10643 root->unused_flags = 0;
10644
10645 limits = (struct ext2_dx_countlimit *) (buf+32);
10646 limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
10647 limits->count = 0;
10648
10649 return root;
10650}
10651
10652
10653static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
10654{
10655 struct ext2_dir_entry *dir;
10656 struct ext2_dx_countlimit *limits;
10657
10658 memset(buf, 0, fs->blocksize);
10659 dir = (struct ext2_dir_entry *) buf;
10660 dir->inode = 0;
10661 dir->rec_len = fs->blocksize;
10662
10663 limits = (struct ext2_dx_countlimit *) (buf+8);
10664 limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
10665 limits->count = 0;
10666
10667 return (struct ext2_dx_entry *) limits;
10668}
10669
10670/*
10671 * This function takes the leaf nodes which have been written in
10672 * outdir, and populates the root node and any necessary interior nodes.
10673 */
10674static errcode_t calculate_tree(ext2_filsys fs,
10675 struct out_dir *outdir,
10676 ext2_ino_t ino,
10677 ext2_ino_t parent)
10678{
10679 struct ext2_dx_root_info *root_info;
10680 struct ext2_dx_entry *root, *dx_ent = NULL;
10681 struct ext2_dx_countlimit *root_limit, *limit;
10682 errcode_t retval;
10683 char * block_start;
10684 int i, c1, c2, nblks;
10685 int limit_offset, root_offset;
10686
10687 root_info = set_root_node(fs, outdir->buf, ino, parent);
10688 root_offset = limit_offset = ((char *) root_info - outdir->buf) +
10689 root_info->info_length;
10690 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10691 c1 = root_limit->limit;
10692 nblks = outdir->num;
10693
10694 /* Write out the pointer blocks */
10695 if (nblks-1 <= c1) {
10696 /* Just write out the root block, and we're done */
10697 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
10698 for (i=1; i < nblks; i++) {
10699 root->block = ext2fs_cpu_to_le32(i);
10700 if (i != 1)
10701 root->hash =
10702 ext2fs_cpu_to_le32(outdir->hashes[i]);
10703 root++;
10704 c1--;
10705 }
10706 } else {
10707 c2 = 0;
10708 limit = 0;
10709 root_info->indirect_levels = 1;
10710 for (i=1; i < nblks; i++) {
10711 if (c1 == 0)
10712 return ENOSPC;
10713 if (c2 == 0) {
10714 if (limit)
10715 limit->limit = limit->count =
10716 ext2fs_cpu_to_le16(limit->limit);
10717 root = (struct ext2_dx_entry *)
10718 (outdir->buf + root_offset);
10719 root->block = ext2fs_cpu_to_le32(outdir->num);
10720 if (i != 1)
10721 root->hash =
10722 ext2fs_cpu_to_le32(outdir->hashes[i]);
10723 if ((retval = get_next_block(fs, outdir,
10724 &block_start)))
10725 return retval;
10726 dx_ent = set_int_node(fs, block_start);
10727 limit = (struct ext2_dx_countlimit *) dx_ent;
10728 c2 = limit->limit;
10729 root_offset += sizeof(struct ext2_dx_entry);
10730 c1--;
10731 }
10732 dx_ent->block = ext2fs_cpu_to_le32(i);
10733 if (c2 != limit->limit)
10734 dx_ent->hash =
10735 ext2fs_cpu_to_le32(outdir->hashes[i]);
10736 dx_ent++;
10737 c2--;
10738 }
10739 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
10740 limit->limit = ext2fs_cpu_to_le16(limit->limit);
10741 }
10742 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10743 root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
10744 root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
10745
10746 return 0;
10747}
10748
10749struct write_dir_struct {
10750 struct out_dir *outdir;
10751 errcode_t err;
10752 e2fsck_t ctx;
10753 int cleared;
10754};
10755
10756/*
10757 * Helper function which writes out a directory block.
10758 */
10759static int write_dir_block(ext2_filsys fs,
10760 blk_t *block_nr,
10761 e2_blkcnt_t blockcnt,
10762 blk_t ref_block FSCK_ATTR((unused)),
10763 int ref_offset FSCK_ATTR((unused)),
10764 void *priv_data)
10765{
10766 struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
10767 blk_t blk;
10768 char *dir;
10769
10770 if (*block_nr == 0)
10771 return 0;
10772 if (blockcnt >= wd->outdir->num) {
10773 e2fsck_read_bitmaps(wd->ctx);
10774 blk = *block_nr;
10775 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
10776 ext2fs_block_alloc_stats(fs, blk, -1);
10777 *block_nr = 0;
10778 wd->cleared++;
10779 return BLOCK_CHANGED;
10780 }
10781 if (blockcnt < 0)
10782 return 0;
10783
10784 dir = wd->outdir->buf + (blockcnt * fs->blocksize);
10785 wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
10786 if (wd->err)
10787 return BLOCK_ABORT;
10788 return 0;
10789}
10790
10791static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
10792 struct out_dir *outdir,
10793 ext2_ino_t ino, int compress)
10794{
10795 struct write_dir_struct wd;
10796 errcode_t retval;
10797 struct ext2_inode inode;
10798
10799 retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
10800 if (retval)
10801 return retval;
10802
10803 wd.outdir = outdir;
10804 wd.err = 0;
10805 wd.ctx = ctx;
10806 wd.cleared = 0;
10807
10808 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10809 write_dir_block, &wd);
10810 if (retval)
10811 return retval;
10812 if (wd.err)
10813 return wd.err;
10814
10815 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10816 if (compress)
10817 inode.i_flags &= ~EXT2_INDEX_FL;
10818 else
10819 inode.i_flags |= EXT2_INDEX_FL;
10820 inode.i_size = outdir->num * fs->blocksize;
10821 inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
10822 e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
10823
10824 return 0;
10825}
10826
10827static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
10828{
10829 ext2_filsys fs = ctx->fs;
10830 errcode_t retval;
10831 struct ext2_inode inode;
10832 char *dir_buf = NULL;
10833 struct fill_dir_struct fd;
10834 struct out_dir outdir;
10835
10836 outdir.max = outdir.num = 0;
10837 outdir.buf = 0;
10838 outdir.hashes = 0;
10839 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10840
10841 retval = ENOMEM;
10842 fd.harray = 0;
10843 dir_buf = xmalloc(inode.i_size);
10844
10845 fd.max_array = inode.i_size / 32;
10846 fd.num_array = 0;
10847 fd.harray = xmalloc(fd.max_array * sizeof(struct hash_entry));
10848
10849 fd.ctx = ctx;
10850 fd.buf = dir_buf;
10851 fd.inode = &inode;
10852 fd.err = 0;
10853 fd.dir_size = 0;
10854 fd.compress = 0;
10855 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
10856 (inode.i_size / fs->blocksize) < 2)
10857 fd.compress = 1;
10858 fd.parent = 0;
10859
10860 /* Read in the entire directory into memory */
10861 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10862 fill_dir_block, &fd);
10863 if (fd.err) {
10864 retval = fd.err;
10865 goto errout;
10866 }
10867
10868 /* Sort the list */
10869resort:
10870 if (fd.compress)
10871 qsort(fd.harray+2, fd.num_array-2,
10872 sizeof(struct hash_entry), name_cmp);
10873 else
10874 qsort(fd.harray, fd.num_array,
10875 sizeof(struct hash_entry), hash_cmp);
10876
10877 /*
10878 * Look for duplicates
10879 */
10880 if (duplicate_search_and_fix(ctx, fs, ino, &fd))
10881 goto resort;
10882
10883 if (ctx->options & E2F_OPT_NO) {
10884 retval = 0;
10885 goto errout;
10886 }
10887
10888 /*
10889 * Copy the directory entries. In a htree directory these
10890 * will become the leaf nodes.
10891 */
10892 retval = copy_dir_entries(fs, &fd, &outdir);
10893 if (retval)
10894 goto errout;
10895
10896 free(dir_buf); dir_buf = 0;
10897
10898 if (!fd.compress) {
10899 /* Calculate the interior nodes */
10900 retval = calculate_tree(fs, &outdir, ino, fd.parent);
10901 if (retval)
10902 goto errout;
10903 }
10904
10905 retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
10906
10907errout:
10908 free(dir_buf);
10909 free(fd.harray);
10910
10911 free_out_dir(&outdir);
10912 return retval;
10913}
10914
10915void e2fsck_rehash_directories(e2fsck_t ctx)
10916{
10917 struct problem_context pctx;
10918 struct dir_info *dir;
10919 ext2_u32_iterate iter;
10920 ext2_ino_t ino;
10921 errcode_t retval;
10922 int i, cur, max, all_dirs, dir_index, first = 1;
10923
10924 all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
10925
10926 if (!ctx->dirs_to_hash && !all_dirs)
10927 return;
10928
10929 e2fsck_get_lost_and_found(ctx, 0);
10930
10931 clear_problem_context(&pctx);
10932
10933 dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
10934 cur = 0;
10935 if (all_dirs) {
10936 i = 0;
10937 max = e2fsck_get_num_dirinfo(ctx);
10938 } else {
10939 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
10940 &iter);
10941 if (retval) {
10942 pctx.errcode = retval;
10943 fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
10944 return;
10945 }
10946 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
10947 }
10948 while (1) {
10949 if (all_dirs) {
10950 if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
10951 break;
10952 ino = dir->ino;
10953 } else {
10954 if (!ext2fs_u32_list_iterate(iter, &ino))
10955 break;
10956 }
10957 if (ino == ctx->lost_and_found)
10958 continue;
10959 pctx.dir = ino;
10960 if (first) {
10961 fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
10962 first = 0;
10963 }
10964 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
10965 if (pctx.errcode) {
10966 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10967 fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
10968 }
10969 if (ctx->progress && !ctx->progress_fd)
10970 e2fsck_simple_progress(ctx, "Rebuilding directory",
10971 100.0 * (float) (++cur) / (float) max, ino);
10972 }
10973 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10974 if (!all_dirs)
10975 ext2fs_u32_list_iterate_end(iter);
10976
10977 ext2fs_u32_list_free(ctx->dirs_to_hash);
10978 ctx->dirs_to_hash = 0;
10979}
10980
10981/*
10982 * linux/fs/revoke.c
10983 *
10984 * Journal revoke routines for the generic filesystem journaling code;
10985 * part of the ext2fs journaling system.
10986 *
10987 * Revoke is the mechanism used to prevent old log records for deleted
10988 * metadata from being replayed on top of newer data using the same
10989 * blocks. The revoke mechanism is used in two separate places:
10990 *
10991 * + Commit: during commit we write the entire list of the current
10992 * transaction's revoked blocks to the journal
10993 *
10994 * + Recovery: during recovery we record the transaction ID of all
10995 * revoked blocks. If there are multiple revoke records in the log
10996 * for a single block, only the last one counts, and if there is a log
10997 * entry for a block beyond the last revoke, then that log entry still
10998 * gets replayed.
10999 *
11000 * We can get interactions between revokes and new log data within a
11001 * single transaction:
11002 *
11003 * Block is revoked and then journaled:
11004 * The desired end result is the journaling of the new block, so we
11005 * cancel the revoke before the transaction commits.
11006 *
11007 * Block is journaled and then revoked:
11008 * The revoke must take precedence over the write of the block, so we
11009 * need either to cancel the journal entry or to write the revoke
11010 * later in the log than the log block. In this case, we choose the
11011 * latter: journaling a block cancels any revoke record for that block
11012 * in the current transaction, so any revoke for that block in the
11013 * transaction must have happened after the block was journaled and so
11014 * the revoke must take precedence.
11015 *
11016 * Block is revoked and then written as data:
11017 * The data write is allowed to succeed, but the revoke is _not_
11018 * cancelled. We still need to prevent old log records from
11019 * overwriting the new data. We don't even need to clear the revoke
11020 * bit here.
11021 *
11022 * Revoke information on buffers is a tri-state value:
11023 *
11024 * RevokeValid clear: no cached revoke status, need to look it up
11025 * RevokeValid set, Revoked clear:
11026 * buffer has not been revoked, and cancel_revoke
11027 * need do nothing.
11028 * RevokeValid set, Revoked set:
11029 * buffer has been revoked.
11030 */
11031
11032static kmem_cache_t *revoke_record_cache;
11033static kmem_cache_t *revoke_table_cache;
11034
11035/* Each revoke record represents one single revoked block. During
11036 journal replay, this involves recording the transaction ID of the
11037 last transaction to revoke this block. */
11038
11039struct jbd_revoke_record_s
11040{
11041 struct list_head hash;
11042 tid_t sequence; /* Used for recovery only */
11043 unsigned long blocknr;
11044};
11045
11046
11047/* The revoke table is just a simple hash table of revoke records. */
11048struct jbd_revoke_table_s
11049{
11050 /* It is conceivable that we might want a larger hash table
11051 * for recovery. Must be a power of two. */
11052 int hash_size;
11053 int hash_shift;
11054 struct list_head *hash_table;
11055};
11056
11057
11058/* Utility functions to maintain the revoke table */
11059
11060/* Borrowed from buffer.c: this is a tried and tested block hash function */
11061static int hash(journal_t *journal, unsigned long block)
11062{
11063 struct jbd_revoke_table_s *table = journal->j_revoke;
11064 int hash_shift = table->hash_shift;
11065
11066 return ((block << (hash_shift - 6)) ^
11067 (block >> 13) ^
11068 (block << (hash_shift - 12))) & (table->hash_size - 1);
11069}
11070
11071static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
11072 tid_t seq)
11073{
11074 struct list_head *hash_list;
11075 struct jbd_revoke_record_s *record;
11076
11077 record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
11078 if (!record)
11079 goto oom;
11080
11081 record->sequence = seq;
11082 record->blocknr = blocknr;
11083 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11084 list_add(&record->hash, hash_list);
11085 return 0;
11086
11087oom:
11088 return -ENOMEM;
11089}
11090
11091/* Find a revoke record in the journal's hash table. */
11092
11093static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
11094 unsigned long blocknr)
11095{
11096 struct list_head *hash_list;
11097 struct jbd_revoke_record_s *record;
11098
11099 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11100
11101 record = (struct jbd_revoke_record_s *) hash_list->next;
11102 while (&(record->hash) != hash_list) {
11103 if (record->blocknr == blocknr)
11104 return record;
11105 record = (struct jbd_revoke_record_s *) record->hash.next;
11106 }
11107 return NULL;
11108}
11109
11110int journal_init_revoke_caches(void)
11111{
11112 revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
11113 if (revoke_record_cache == 0)
11114 return -ENOMEM;
11115
11116 revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
11117 if (revoke_table_cache == 0) {
11118 do_cache_destroy(revoke_record_cache);
11119 revoke_record_cache = NULL;
11120 return -ENOMEM;
11121 }
11122 return 0;
11123}
11124
11125void journal_destroy_revoke_caches(void)
11126{
11127 do_cache_destroy(revoke_record_cache);
11128 revoke_record_cache = 0;
11129 do_cache_destroy(revoke_table_cache);
11130 revoke_table_cache = 0;
11131}
11132
11133/* Initialise the revoke table for a given journal to a given size. */
11134
11135int journal_init_revoke(journal_t *journal, int hash_size)
11136{
11137 int shift, tmp;
11138
11139 journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
11140 if (!journal->j_revoke)
11141 return -ENOMEM;
11142
11143 /* Check that the hash_size is a power of two */
11144 journal->j_revoke->hash_size = hash_size;
11145
11146 shift = 0;
11147 tmp = hash_size;
11148 while ((tmp >>= 1UL) != 0UL)
11149 shift++;
11150 journal->j_revoke->hash_shift = shift;
11151
11152 journal->j_revoke->hash_table = xmalloc(hash_size * sizeof(struct list_head));
11153
11154 for (tmp = 0; tmp < hash_size; tmp++)
11155 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
11156
11157 return 0;
11158}
11159
11160/* Destoy a journal's revoke table. The table must already be empty! */
11161
11162void journal_destroy_revoke(journal_t *journal)
11163{
11164 struct jbd_revoke_table_s *table;
11165 struct list_head *hash_list;
11166 int i;
11167
11168 table = journal->j_revoke;
11169 if (!table)
11170 return;
11171
11172 for (i=0; i<table->hash_size; i++) {
11173 hash_list = &table->hash_table[i];
11174 }
11175
11176 free(table->hash_table);
11177 free(table);
11178 journal->j_revoke = NULL;
11179}
11180
11181/*
11182 * Revoke support for recovery.
11183 *
11184 * Recovery needs to be able to:
11185 *
11186 * record all revoke records, including the tid of the latest instance
11187 * of each revoke in the journal
11188 *
11189 * check whether a given block in a given transaction should be replayed
11190 * (ie. has not been revoked by a revoke record in that or a subsequent
11191 * transaction)
11192 *
11193 * empty the revoke table after recovery.
11194 */
11195
11196/*
11197 * First, setting revoke records. We create a new revoke record for
11198 * every block ever revoked in the log as we scan it for recovery, and
11199 * we update the existing records if we find multiple revokes for a
11200 * single block.
11201 */
11202
11203int journal_set_revoke(journal_t *journal, unsigned long blocknr,
11204 tid_t sequence)
11205{
11206 struct jbd_revoke_record_s *record;
11207
11208 record = find_revoke_record(journal, blocknr);
11209 if (record) {
11210 /* If we have multiple occurences, only record the
11211 * latest sequence number in the hashed record */
11212 if (tid_gt(sequence, record->sequence))
11213 record->sequence = sequence;
11214 return 0;
11215 }
11216 return insert_revoke_hash(journal, blocknr, sequence);
11217}
11218
11219/*
11220 * Test revoke records. For a given block referenced in the log, has
11221 * that block been revoked? A revoke record with a given transaction
11222 * sequence number revokes all blocks in that transaction and earlier
11223 * ones, but later transactions still need replayed.
11224 */
11225
11226int journal_test_revoke(journal_t *journal, unsigned long blocknr,
11227 tid_t sequence)
11228{
11229 struct jbd_revoke_record_s *record;
11230
11231 record = find_revoke_record(journal, blocknr);
11232 if (!record)
11233 return 0;
11234 if (tid_gt(sequence, record->sequence))
11235 return 0;
11236 return 1;
11237}
11238
11239/*
11240 * Finally, once recovery is over, we need to clear the revoke table so
11241 * that it can be reused by the running filesystem.
11242 */
11243
11244void journal_clear_revoke(journal_t *journal)
11245{
11246 int i;
11247 struct list_head *hash_list;
11248 struct jbd_revoke_record_s *record;
11249 struct jbd_revoke_table_s *revoke_var;
11250
11251 revoke_var = journal->j_revoke;
11252
11253 for (i = 0; i < revoke_var->hash_size; i++) {
11254 hash_list = &revoke_var->hash_table[i];
11255 while (!list_empty(hash_list)) {
11256 record = (struct jbd_revoke_record_s*) hash_list->next;
11257 list_del(&record->hash);
11258 free(record);
11259 }
11260 }
11261}
11262
11263/*
11264 * e2fsck.c - superblock checks
11265 */
11266
11267#define MIN_CHECK 1
11268#define MAX_CHECK 2
11269
11270static void check_super_value(e2fsck_t ctx, const char *descr,
11271 unsigned long value, int flags,
11272 unsigned long min_val, unsigned long max_val)
11273{
11274 struct problem_context pctx;
11275
11276 if (((flags & MIN_CHECK) && (value < min_val)) ||
11277 ((flags & MAX_CHECK) && (value > max_val))) {
11278 clear_problem_context(&pctx);
11279 pctx.num = value;
11280 pctx.str = descr;
11281 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11282 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11283 }
11284}
11285
11286/*
11287 * This routine may get stubbed out in special compilations of the
11288 * e2fsck code..
11289 */
11290#ifndef EXT2_SPECIAL_DEVICE_SIZE
11291static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
11292{
11293 return (ext2fs_get_device_size(ctx->filesystem_name,
11294 EXT2_BLOCK_SIZE(ctx->fs->super),
11295 &ctx->num_blocks));
11296}
11297#endif
11298
11299/*
11300 * helper function to release an inode
11301 */
11302struct process_block_struct {
11303 e2fsck_t ctx;
11304 char *buf;
11305 struct problem_context *pctx;
11306 int truncating;
11307 int truncate_offset;
11308 e2_blkcnt_t truncate_block;
11309 int truncated_blocks;
11310 int abort;
11311 errcode_t errcode;
11312};
11313
11314static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
11315 e2_blkcnt_t blockcnt,
11316 blk_t ref_blk FSCK_ATTR((unused)),
11317 int ref_offset FSCK_ATTR((unused)),
11318 void *priv_data)
11319{
11320 struct process_block_struct *pb;
11321 e2fsck_t ctx;
11322 struct problem_context *pctx;
11323 blk_t blk = *block_nr;
11324 int retval = 0;
11325
11326 pb = (struct process_block_struct *) priv_data;
11327 ctx = pb->ctx;
11328 pctx = pb->pctx;
11329
11330 pctx->blk = blk;
11331 pctx->blkcount = blockcnt;
11332
11333 if (HOLE_BLKADDR(blk))
11334 return 0;
11335
11336 if ((blk < fs->super->s_first_data_block) ||
11337 (blk >= fs->super->s_blocks_count)) {
11338 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
11339 return_abort:
11340 pb->abort = 1;
11341 return BLOCK_ABORT;
11342 }
11343
11344 if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
11345 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
11346 goto return_abort;
11347 }
11348
11349 /*
11350 * If we are deleting an orphan, then we leave the fields alone.
11351 * If we are truncating an orphan, then update the inode fields
11352 * and clean up any partial block data.
11353 */
11354 if (pb->truncating) {
11355 /*
11356 * We only remove indirect blocks if they are
11357 * completely empty.
11358 */
11359 if (blockcnt < 0) {
11360 int i, limit;
11361 blk_t *bp;
11362
11363 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11364 pb->buf);
11365 if (pb->errcode)
11366 goto return_abort;
11367
11368 limit = fs->blocksize >> 2;
11369 for (i = 0, bp = (blk_t *) pb->buf;
11370 i < limit; i++, bp++)
11371 if (*bp)
11372 return 0;
11373 }
11374 /*
11375 * We don't remove direct blocks until we've reached
11376 * the truncation block.
11377 */
11378 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
11379 return 0;
11380 /*
11381 * If part of the last block needs truncating, we do
11382 * it here.
11383 */
11384 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
11385 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11386 pb->buf);
11387 if (pb->errcode)
11388 goto return_abort;
11389 memset(pb->buf + pb->truncate_offset, 0,
11390 fs->blocksize - pb->truncate_offset);
11391 pb->errcode = io_channel_write_blk(fs->io, blk, 1,
11392 pb->buf);
11393 if (pb->errcode)
11394 goto return_abort;
11395 }
11396 pb->truncated_blocks++;
11397 *block_nr = 0;
11398 retval |= BLOCK_CHANGED;
11399 }
11400
11401 ext2fs_block_alloc_stats(fs, blk, -1);
11402 return retval;
11403}
11404
11405/*
11406 * This function releases an inode. Returns 1 if an inconsistency was
11407 * found. If the inode has a link count, then it is being truncated and
11408 * not deleted.
11409 */
11410static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
11411 struct ext2_inode *inode, char *block_buf,
11412 struct problem_context *pctx)
11413{
11414 struct process_block_struct pb;
11415 ext2_filsys fs = ctx->fs;
11416 errcode_t retval;
11417 __u32 count;
11418
11419 if (!ext2fs_inode_has_valid_blocks(inode))
11420 return 0;
11421
11422 pb.buf = block_buf + 3 * ctx->fs->blocksize;
11423 pb.ctx = ctx;
11424 pb.abort = 0;
11425 pb.errcode = 0;
11426 pb.pctx = pctx;
11427 if (inode->i_links_count) {
11428 pb.truncating = 1;
11429 pb.truncate_block = (e2_blkcnt_t)
11430 ((((long long)inode->i_size_high << 32) +
11431 inode->i_size + fs->blocksize - 1) /
11432 fs->blocksize);
11433 pb.truncate_offset = inode->i_size % fs->blocksize;
11434 } else {
11435 pb.truncating = 0;
11436 pb.truncate_block = 0;
11437 pb.truncate_offset = 0;
11438 }
11439 pb.truncated_blocks = 0;
11440 retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
11441 block_buf, release_inode_block, &pb);
11442 if (retval) {
11443 bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"),
11444 ino);
11445 return 1;
11446 }
11447 if (pb.abort)
11448 return 1;
11449
11450 /* Refresh the inode since ext2fs_block_iterate may have changed it */
11451 e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
11452
11453 if (pb.truncated_blocks)
11454 inode->i_blocks -= pb.truncated_blocks *
11455 (fs->blocksize / 512);
11456
11457 if (inode->i_file_acl) {
11458 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
11459 block_buf, -1, &count);
11460 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
11461 retval = 0;
11462 count = 1;
11463 }
11464 if (retval) {
11465 bb_error_msg(_("while calling ext2fs_adjust_ea_refcount for inode %d"),
11466 ino);
11467 return 1;
11468 }
11469 if (count == 0)
11470 ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
11471 inode->i_file_acl = 0;
11472 }
11473 return 0;
11474}
11475
11476/*
11477 * This function releases all of the orphan inodes. It returns 1 if
11478 * it hit some error, and 0 on success.
11479 */
11480static int release_orphan_inodes(e2fsck_t ctx)
11481{
11482 ext2_filsys fs = ctx->fs;
11483 ext2_ino_t ino, next_ino;
11484 struct ext2_inode inode;
11485 struct problem_context pctx;
11486 char *block_buf;
11487
11488 if ((ino = fs->super->s_last_orphan) == 0)
11489 return 0;
11490
11491 /*
11492 * Win or lose, we won't be using the head of the orphan inode
11493 * list again.
11494 */
11495 fs->super->s_last_orphan = 0;
11496 ext2fs_mark_super_dirty(fs);
11497
11498 /*
11499 * If the filesystem contains errors, don't run the orphan
11500 * list, since the orphan list can't be trusted; and we're
11501 * going to be running a full e2fsck run anyway...
11502 */
11503 if (fs->super->s_state & EXT2_ERROR_FS)
11504 return 0;
11505
11506 if ((ino < EXT2_FIRST_INODE(fs->super)) ||
11507 (ino > fs->super->s_inodes_count)) {
11508 clear_problem_context(&pctx);
11509 pctx.ino = ino;
11510 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
11511 return 1;
11512 }
11513
11514 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
11515 "block iterate buffer");
11516 e2fsck_read_bitmaps(ctx);
11517
11518 while (ino) {
11519 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
11520 clear_problem_context(&pctx);
11521 pctx.ino = ino;
11522 pctx.inode = &inode;
11523 pctx.str = inode.i_links_count ? _("Truncating") :
11524 _("Clearing");
11525
11526 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
11527
11528 next_ino = inode.i_dtime;
11529 if (next_ino &&
11530 ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
11531 (next_ino > fs->super->s_inodes_count))) {
11532 pctx.ino = next_ino;
11533 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
11534 goto return_abort;
11535 }
11536
11537 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
11538 goto return_abort;
11539
11540 if (!inode.i_links_count) {
11541 ext2fs_inode_alloc_stats2(fs, ino, -1,
11542 LINUX_S_ISDIR(inode.i_mode));
11543 inode.i_dtime = time(NULL);
11544 } else {
11545 inode.i_dtime = 0;
11546 }
11547 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
11548 ino = next_ino;
11549 }
11550 ext2fs_free_mem(&block_buf);
11551 return 0;
11552 return_abort:
11553 ext2fs_free_mem(&block_buf);
11554 return 1;
11555}
11556
11557/*
11558 * Check the resize inode to make sure it is sane. We check both for
11559 * the case where on-line resizing is not enabled (in which case the
11560 * resize inode should be cleared) as well as the case where on-line
11561 * resizing is enabled.
11562 */
11563static void check_resize_inode(e2fsck_t ctx)
11564{
11565 ext2_filsys fs = ctx->fs;
11566 struct ext2_inode inode;
11567 struct problem_context pctx;
11568 int i, j, gdt_off, ind_off;
11569 blk_t blk, pblk, expect;
11570 __u32 *dind_buf = NULL, *ind_buf;
11571 errcode_t retval;
11572
11573 clear_problem_context(&pctx);
11574
11575 /*
11576 * If the resize inode feature isn't set, then
11577 * s_reserved_gdt_blocks must be zero.
11578 */
11579 if (!(fs->super->s_feature_compat &
11580 EXT2_FEATURE_COMPAT_RESIZE_INO)) {
11581 if (fs->super->s_reserved_gdt_blocks) {
11582 pctx.num = fs->super->s_reserved_gdt_blocks;
11583 if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
11584 &pctx)) {
11585 fs->super->s_reserved_gdt_blocks = 0;
11586 ext2fs_mark_super_dirty(fs);
11587 }
11588 }
11589 }
11590
11591 /* Read the resize inode */
11592 pctx.ino = EXT2_RESIZE_INO;
11593 retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
11594 if (retval) {
11595 if (fs->super->s_feature_compat &
11596 EXT2_FEATURE_COMPAT_RESIZE_INO)
11597 ctx->flags |= E2F_FLAG_RESIZE_INODE;
11598 return;
11599 }
11600
11601 /*
11602 * If the resize inode feature isn't set, check to make sure
11603 * the resize inode is cleared; then we're done.
11604 */
11605 if (!(fs->super->s_feature_compat &
11606 EXT2_FEATURE_COMPAT_RESIZE_INO)) {
11607 for (i=0; i < EXT2_N_BLOCKS; i++) {
11608 if (inode.i_block[i])
11609 break;
11610 }
11611 if ((i < EXT2_N_BLOCKS) &&
11612 fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
11613 memset(&inode, 0, sizeof(inode));
11614 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11615 "clear_resize");
11616 }
11617 return;
11618 }
11619
11620 /*
11621 * The resize inode feature is enabled; check to make sure the
11622 * only block in use is the double indirect block
11623 */
11624 blk = inode.i_block[EXT2_DIND_BLOCK];
11625 for (i=0; i < EXT2_N_BLOCKS; i++) {
11626 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
11627 break;
11628 }
11629 if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
11630 !(inode.i_mode & LINUX_S_IFREG) ||
11631 (blk < fs->super->s_first_data_block ||
11632 blk >= fs->super->s_blocks_count)) {
11633 resize_inode_invalid:
11634 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
11635 memset(&inode, 0, sizeof(inode));
11636 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11637 "clear_resize");
11638 ctx->flags |= E2F_FLAG_RESIZE_INODE;
11639 }
11640 if (!(ctx->options & E2F_OPT_READONLY)) {
11641 fs->super->s_state &= ~EXT2_VALID_FS;
11642 ext2fs_mark_super_dirty(fs);
11643 }
11644 goto cleanup;
11645 }
11646 dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
11647 "resize dind buffer");
11648 ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
11649
11650 retval = ext2fs_read_ind_block(fs, blk, dind_buf);
11651 if (retval)
11652 goto resize_inode_invalid;
11653
11654 gdt_off = fs->desc_blocks;
11655 pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
11656 for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
11657 i++, gdt_off++, pblk++) {
11658 gdt_off %= fs->blocksize/4;
11659 if (dind_buf[gdt_off] != pblk)
11660 goto resize_inode_invalid;
11661 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
11662 if (retval)
11663 goto resize_inode_invalid;
11664 ind_off = 0;
11665 for (j = 1; j < fs->group_desc_count; j++) {
11666 if (!ext2fs_bg_has_super(fs, j))
11667 continue;
11668 expect = pblk + (j * fs->super->s_blocks_per_group);
11669 if (ind_buf[ind_off] != expect)
11670 goto resize_inode_invalid;
11671 ind_off++;
11672 }
11673 }
11674
11675 cleanup:
11676 ext2fs_free_mem(&dind_buf);
11677}
11678
11679static void check_super_block(e2fsck_t ctx)
11680{
11681 ext2_filsys fs = ctx->fs;
11682 blk_t first_block, last_block;
11683 struct ext2_super_block *sb = fs->super;
11684 struct ext2_group_desc *gd;
11685 blk_t blocks_per_group = fs->super->s_blocks_per_group;
11686 blk_t bpg_max;
11687 int inodes_per_block;
11688 int ipg_max;
11689 int inode_size;
11690 dgrp_t i;
11691 blk_t should_be;
11692 struct problem_context pctx;
11693 __u32 free_blocks = 0, free_inodes = 0;
11694
11695 inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
11696 ipg_max = inodes_per_block * (blocks_per_group - 4);
11697 if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
11698 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
11699 bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
11700 if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
11701 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
11702
11703 ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11704 sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
11705 ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11706 sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
11707 ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
11708 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
11709
11710 clear_problem_context(&pctx);
11711
11712 /*
11713 * Verify the super block constants...
11714 */
11715 check_super_value(ctx, "inodes_count", sb->s_inodes_count,
11716 MIN_CHECK, 1, 0);
11717 check_super_value(ctx, "blocks_count", sb->s_blocks_count,
11718 MIN_CHECK, 1, 0);
11719 check_super_value(ctx, "first_data_block", sb->s_first_data_block,
11720 MAX_CHECK, 0, sb->s_blocks_count);
11721 check_super_value(ctx, "log_block_size", sb->s_log_block_size,
11722 MIN_CHECK | MAX_CHECK, 0,
11723 EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
11724 check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
11725 MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
11726 check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
11727 MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
11728 bpg_max);
11729 check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
11730 MIN_CHECK | MAX_CHECK, 8, bpg_max);
11731 check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
11732 MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
11733 check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
11734 MAX_CHECK, 0, sb->s_blocks_count / 2);
11735 check_super_value(ctx, "reserved_gdt_blocks",
11736 sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
11737 fs->blocksize/4);
11738 inode_size = EXT2_INODE_SIZE(sb);
11739 check_super_value(ctx, "inode_size",
11740 inode_size, MIN_CHECK | MAX_CHECK,
11741 EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
11742 if (inode_size & (inode_size - 1)) {
11743 pctx.num = inode_size;
11744 pctx.str = "inode_size";
11745 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11746 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11747 return;
11748 }
11749
11750 if (!ctx->num_blocks) {
11751 pctx.errcode = e2fsck_get_device_size(ctx);
11752 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
11753 fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
11754 ctx->flags |= E2F_FLAG_ABORT;
11755 return;
11756 }
11757 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
11758 (ctx->num_blocks < sb->s_blocks_count)) {
11759 pctx.blk = sb->s_blocks_count;
11760 pctx.blk2 = ctx->num_blocks;
11761 if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
11762 ctx->flags |= E2F_FLAG_ABORT;
11763 return;
11764 }
11765 }
11766 }
11767
11768 if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
11769 pctx.blk = EXT2_BLOCK_SIZE(sb);
11770 pctx.blk2 = EXT2_FRAG_SIZE(sb);
11771 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
11772 ctx->flags |= E2F_FLAG_ABORT;
11773 return;
11774 }
11775
11776 should_be = sb->s_frags_per_group >>
11777 (sb->s_log_block_size - sb->s_log_frag_size);
11778 if (sb->s_blocks_per_group != should_be) {
11779 pctx.blk = sb->s_blocks_per_group;
11780 pctx.blk2 = should_be;
11781 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
11782 ctx->flags |= E2F_FLAG_ABORT;
11783 return;
11784 }
11785
11786 should_be = (sb->s_log_block_size == 0) ? 1 : 0;
11787 if (sb->s_first_data_block != should_be) {
11788 pctx.blk = sb->s_first_data_block;
11789 pctx.blk2 = should_be;
11790 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
11791 ctx->flags |= E2F_FLAG_ABORT;
11792 return;
11793 }
11794
11795 should_be = sb->s_inodes_per_group * fs->group_desc_count;
11796 if (sb->s_inodes_count != should_be) {
11797 pctx.ino = sb->s_inodes_count;
11798 pctx.ino2 = should_be;
11799 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
11800 sb->s_inodes_count = should_be;
11801 ext2fs_mark_super_dirty(fs);
11802 }
11803 }
11804
11805 /*
11806 * Verify the group descriptors....
11807 */
11808 first_block = sb->s_first_data_block;
11809 last_block = first_block + blocks_per_group;
11810
11811 for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
11812 pctx.group = i;
11813
11814 if (i == fs->group_desc_count - 1)
11815 last_block = sb->s_blocks_count;
11816 if ((gd->bg_block_bitmap < first_block) ||
11817 (gd->bg_block_bitmap >= last_block)) {
11818 pctx.blk = gd->bg_block_bitmap;
11819 if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
11820 gd->bg_block_bitmap = 0;
11821 }
11822 if (gd->bg_block_bitmap == 0) {
11823 ctx->invalid_block_bitmap_flag[i]++;
11824 ctx->invalid_bitmaps++;
11825 }
11826 if ((gd->bg_inode_bitmap < first_block) ||
11827 (gd->bg_inode_bitmap >= last_block)) {
11828 pctx.blk = gd->bg_inode_bitmap;
11829 if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
11830 gd->bg_inode_bitmap = 0;
11831 }
11832 if (gd->bg_inode_bitmap == 0) {
11833 ctx->invalid_inode_bitmap_flag[i]++;
11834 ctx->invalid_bitmaps++;
11835 }
11836 if ((gd->bg_inode_table < first_block) ||
11837 ((gd->bg_inode_table +
11838 fs->inode_blocks_per_group - 1) >= last_block)) {
11839 pctx.blk = gd->bg_inode_table;
11840 if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
11841 gd->bg_inode_table = 0;
11842 }
11843 if (gd->bg_inode_table == 0) {
11844 ctx->invalid_inode_table_flag[i]++;
11845 ctx->invalid_bitmaps++;
11846 }
11847 free_blocks += gd->bg_free_blocks_count;
11848 free_inodes += gd->bg_free_inodes_count;
11849 first_block += sb->s_blocks_per_group;
11850 last_block += sb->s_blocks_per_group;
11851
11852 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
11853 (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
11854 (gd->bg_used_dirs_count > sb->s_inodes_per_group))
11855 ext2fs_unmark_valid(fs);
11856 }
11857
11858 /*
11859 * Update the global counts from the block group counts. This
11860 * is needed for an experimental patch which eliminates
11861 * locking the entire filesystem when allocating blocks or
11862 * inodes; if the filesystem is not unmounted cleanly, the
11863 * global counts may not be accurate.
11864 */
11865 if ((free_blocks != sb->s_free_blocks_count) ||
11866 (free_inodes != sb->s_free_inodes_count)) {
11867 if (ctx->options & E2F_OPT_READONLY)
11868 ext2fs_unmark_valid(fs);
11869 else {
11870 sb->s_free_blocks_count = free_blocks;
11871 sb->s_free_inodes_count = free_inodes;
11872 ext2fs_mark_super_dirty(fs);
11873 }
11874 }
11875
11876 if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
11877 (sb->s_free_inodes_count > sb->s_inodes_count))
11878 ext2fs_unmark_valid(fs);
11879
11880
11881 /*
11882 * If we have invalid bitmaps, set the error state of the
11883 * filesystem.
11884 */
11885 if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
11886 sb->s_state &= ~EXT2_VALID_FS;
11887 ext2fs_mark_super_dirty(fs);
11888 }
11889
11890 clear_problem_context(&pctx);
11891
11892 /*
11893 * If the UUID field isn't assigned, assign it.
11894 */
11895 if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
11896 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
11897 uuid_generate(sb->s_uuid);
11898 ext2fs_mark_super_dirty(fs);
11899 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
11900 }
11901 }
11902
11903 /* FIXME - HURD support?
11904 * For the Hurd, check to see if the filetype option is set,
11905 * since it doesn't support it.
11906 */
11907 if (!(ctx->options & E2F_OPT_READONLY) &&
11908 fs->super->s_creator_os == EXT2_OS_HURD &&
11909 (fs->super->s_feature_incompat &
11910 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
11911 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
11912 fs->super->s_feature_incompat &=
11913 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
11914 ext2fs_mark_super_dirty(fs);
11915 }
11916 }
11917
11918 /*
11919 * If we have any of the compatibility flags set, we need to have a
11920 * revision 1 filesystem. Most kernels will not check the flags on
11921 * a rev 0 filesystem and we may have corruption issues because of
11922 * the incompatible changes to the filesystem.
11923 */
11924 if (!(ctx->options & E2F_OPT_READONLY) &&
11925 fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
11926 (fs->super->s_feature_compat ||
11927 fs->super->s_feature_ro_compat ||
11928 fs->super->s_feature_incompat) &&
11929 fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
11930 ext2fs_update_dynamic_rev(fs);
11931 ext2fs_mark_super_dirty(fs);
11932 }
11933
11934 check_resize_inode(ctx);
11935
11936 /*
11937 * Clean up any orphan inodes, if present.
11938 */
11939 if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
11940 fs->super->s_state &= ~EXT2_VALID_FS;
11941 ext2fs_mark_super_dirty(fs);
11942 }
11943
11944 /*
11945 * Move the ext3 journal file, if necessary.
11946 */
11947 e2fsck_move_ext3_journal(ctx);
11948}
11949
11950/*
11951 * swapfs.c --- byte-swap an ext2 filesystem
11952 */
11953
11954#ifdef ENABLE_SWAPFS
11955
11956struct swap_block_struct {
11957 ext2_ino_t ino;
11958 int isdir;
11959 errcode_t errcode;
11960 char *dir_buf;
11961 struct ext2_inode *inode;
11962};
11963
11964/*
11965 * This is a helper function for block_iterate. We mark all of the
11966 * indirect and direct blocks as changed, so that block_iterate will
11967 * write them out.
11968 */
11969static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
11970 void *priv_data)
11971{
11972 errcode_t retval;
11973
11974 struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
11975
11976 if (sb->isdir && (blockcnt >= 0) && *block_nr) {
11977 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
11978 if (retval) {
11979 sb->errcode = retval;
11980 return BLOCK_ABORT;
11981 }
11982 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
11983 if (retval) {
11984 sb->errcode = retval;
11985 return BLOCK_ABORT;
11986 }
11987 }
11988 if (blockcnt >= 0) {
11989 if (blockcnt < EXT2_NDIR_BLOCKS)
11990 return 0;
11991 return BLOCK_CHANGED;
11992 }
11993 if (blockcnt == BLOCK_COUNT_IND) {
11994 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
11995 return 0;
11996 return BLOCK_CHANGED;
11997 }
11998 if (blockcnt == BLOCK_COUNT_DIND) {
11999 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
12000 return 0;
12001 return BLOCK_CHANGED;
12002 }
12003 if (blockcnt == BLOCK_COUNT_TIND) {
12004 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
12005 return 0;
12006 return BLOCK_CHANGED;
12007 }
12008 return BLOCK_CHANGED;
12009}
12010
12011/*
12012 * This function is responsible for byte-swapping all of the indirect,
12013 * block pointers. It is also responsible for byte-swapping directories.
12014 */
12015static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
12016 struct ext2_inode *inode)
12017{
12018 errcode_t retval;
12019 struct swap_block_struct sb;
12020
12021 sb.ino = ino;
12022 sb.inode = inode;
12023 sb.dir_buf = block_buf + ctx->fs->blocksize*3;
12024 sb.errcode = 0;
12025 sb.isdir = 0;
12026 if (LINUX_S_ISDIR(inode->i_mode))
12027 sb.isdir = 1;
12028
12029 retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
12030 swap_block, &sb);
12031 if (retval) {
12032 bb_error_msg(_("while calling ext2fs_block_iterate"));
12033 ctx->flags |= E2F_FLAG_ABORT;
12034 return;
12035 }
12036 if (sb.errcode) {
12037 bb_error_msg(_("while calling iterator function"));
12038 ctx->flags |= E2F_FLAG_ABORT;
12039 return;
12040 }
12041}
12042
12043static void swap_inodes(e2fsck_t ctx)
12044{
12045 ext2_filsys fs = ctx->fs;
12046 dgrp_t group;
12047 unsigned int i;
12048 ext2_ino_t ino = 1;
12049 char *buf, *block_buf;
12050 errcode_t retval;
12051 struct ext2_inode * inode;
12052
12053 e2fsck_use_inode_shortcuts(ctx, 1);
12054
12055 retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
12056 &buf);
12057 if (retval) {
12058 bb_error_msg(_("while allocating inode buffer"));
12059 ctx->flags |= E2F_FLAG_ABORT;
12060 return;
12061 }
12062 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
12063 "block interate buffer");
12064 for (group = 0; group < fs->group_desc_count; group++) {
12065 retval = io_channel_read_blk(fs->io,
12066 fs->group_desc[group].bg_inode_table,
12067 fs->inode_blocks_per_group, buf);
12068 if (retval) {
12069 bb_error_msg(_("while reading inode table (group %d)"),
12070 group);
12071 ctx->flags |= E2F_FLAG_ABORT;
12072 return;
12073 }
12074 inode = (struct ext2_inode *) buf;
12075 for (i=0; i < fs->super->s_inodes_per_group;
12076 i++, ino++, inode++) {
12077 ctx->stashed_ino = ino;
12078 ctx->stashed_inode = inode;
12079
12080 if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
12081 ext2fs_swap_inode(fs, inode, inode, 0);
12082
12083 /*
12084 * Skip deleted files.
12085 */
12086 if (inode->i_links_count == 0)
12087 continue;
12088
12089 if (LINUX_S_ISDIR(inode->i_mode) ||
12090 ((inode->i_block[EXT2_IND_BLOCK] ||
12091 inode->i_block[EXT2_DIND_BLOCK] ||
12092 inode->i_block[EXT2_TIND_BLOCK]) &&
12093 ext2fs_inode_has_valid_blocks(inode)))
12094 swap_inode_blocks(ctx, ino, block_buf, inode);
12095
12096 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12097 return;
12098
12099 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12100 ext2fs_swap_inode(fs, inode, inode, 1);
12101 }
12102 retval = io_channel_write_blk(fs->io,
12103 fs->group_desc[group].bg_inode_table,
12104 fs->inode_blocks_per_group, buf);
12105 if (retval) {
12106 bb_error_msg(_("while writing inode table (group %d)"),
12107 group);
12108 ctx->flags |= E2F_FLAG_ABORT;
12109 return;
12110 }
12111 }
12112 ext2fs_free_mem(&buf);
12113 ext2fs_free_mem(&block_buf);
12114 e2fsck_use_inode_shortcuts(ctx, 0);
12115 ext2fs_flush_icache(fs);
12116}
12117
12118#if defined(__powerpc__) && BB_BIG_ENDIAN
12119/*
12120 * On the PowerPC, the big-endian variant of the ext2 filesystem
12121 * has its bitmaps stored as 32-bit words with bit 0 as the LSB
12122 * of each word. Thus a bitmap with only bit 0 set would be, as
12123 * a string of bytes, 00 00 00 01 00 ...
12124 * To cope with this, we byte-reverse each word of a bitmap if
12125 * we have a big-endian filesystem, that is, if we are *not*
12126 * byte-swapping other word-sized numbers.
12127 */
12128#define EXT2_BIG_ENDIAN_BITMAPS
12129#endif
12130
12131#ifdef EXT2_BIG_ENDIAN_BITMAPS
12132static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
12133{
12134 __u32 *p = (__u32 *) bmap->bitmap;
12135 int n, nbytes = (bmap->end - bmap->start + 7) / 8;
12136
12137 for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
12138 *p = ext2fs_swab32(*p);
12139}
12140#endif
12141
12142
12143#ifdef ENABLE_SWAPFS
12144static void swap_filesys(e2fsck_t ctx)
12145{
12146 ext2_filsys fs = ctx->fs;
12147 if (!(ctx->options & E2F_OPT_PREEN))
12148 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
12149
12150 /* Byte swap */
12151
12152 if (fs->super->s_mnt_count) {
12153 fprintf(stderr, _("%s: the filesystem must be freshly "
12154 "checked using fsck\n"
12155 "and not mounted before trying to "
12156 "byte-swap it.\n"), ctx->device_name);
12157 ctx->flags |= E2F_FLAG_ABORT;
12158 return;
12159 }
12160 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
12161 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
12162 EXT2_FLAG_SWAP_BYTES_WRITE);
12163 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
12164 } else {
12165 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
12166 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
12167 }
12168 swap_inodes(ctx);
12169 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12170 return;
12171 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12172 fs->flags |= EXT2_FLAG_SWAP_BYTES;
12173 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
12174 EXT2_FLAG_SWAP_BYTES_WRITE);
12175
12176#ifdef EXT2_BIG_ENDIAN_BITMAPS
12177 e2fsck_read_bitmaps(ctx);
12178 ext2fs_swap_bitmap(fs->inode_map);
12179 ext2fs_swap_bitmap(fs->block_map);
12180 fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
12181#endif
12182 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
12183 ext2fs_flush(fs);
12184 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
12185}
12186#endif /* ENABLE_SWAPFS */
12187
12188#endif
12189
12190/*
12191 * util.c --- miscellaneous utilities
12192 */
12193
12194
12195void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
12196 const char *description)
12197{
12198 return xzalloc(size);
12199}
12200
12201static char *string_copy(const char *str, int len)
12202{
12203 char *ret;
12204
12205 if (!str)
12206 return NULL;
12207 if (!len)
12208 len = strlen(str);
12209 ret = xmalloc(len+1);
12210 strncpy(ret, str, len);
12211 ret[len] = 0;
12212 return ret;
12213}
12214
12215#ifndef HAVE_CONIO_H
12216static int read_a_char(void)
12217{
12218 char c;
12219 int r;
12220 int fail = 0;
12221
12222 while (1) {
12223 if (e2fsck_global_ctx &&
12224 (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
12225 return 3;
12226 }
12227 r = read(0, &c, 1);
12228 if (r == 1)
12229 return c;
12230 if (fail++ > 100)
12231 break;
12232 }
12233 return EOF;
12234}
12235#endif
12236
12237static int ask_yn(const char * string, int def)
12238{
12239 int c;
12240 const char *defstr;
12241 static const char short_yes[] = "yY";
12242 static const char short_no[] = "nN";
12243
12244#ifdef HAVE_TERMIOS_H
12245 struct termios termios, tmp;
12246
12247 tcgetattr (0, &termios);
12248 tmp = termios;
12249 tmp.c_lflag &= ~(ICANON | ECHO);
12250 tmp.c_cc[VMIN] = 1;
12251 tmp.c_cc[VTIME] = 0;
12252 tcsetattr_stdin_TCSANOW(&tmp);
12253#endif
12254
12255 if (def == 1)
12256 defstr = "<y>";
12257 else if (def == 0)
12258 defstr = "<n>";
12259 else
12260 defstr = " (y/n)";
12261 printf("%s%s? ", string, defstr);
12262 while (1) {
12263 fflush (stdout);
12264 if ((c = read_a_char()) == EOF)
12265 break;
12266 if (c == 3) {
12267#ifdef HAVE_TERMIOS_H
12268 tcsetattr_stdin_TCSANOW(&termios);
12269#endif
12270 if (e2fsck_global_ctx &&
12271 e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
12272 puts("\n");
12273 longjmp(e2fsck_global_ctx->abort_loc, 1);
12274 }
12275 puts(_("cancelled!\n"));
12276 return 0;
12277 }
12278 if (strchr(short_yes, (char) c)) {
12279 def = 1;
12280 break;
12281 }
12282 else if (strchr(short_no, (char) c)) {
12283 def = 0;
12284 break;
12285 }
12286 else if ((c == ' ' || c == '\n') && (def != -1))
12287 break;
12288 }
12289 if (def)
12290 puts("yes\n");
12291 else
12292 puts ("no\n");
12293#ifdef HAVE_TERMIOS_H
12294 tcsetattr_stdin_TCSANOW(&termios);
12295#endif
12296 return def;
12297}
12298
12299int ask (e2fsck_t ctx, const char * string, int def)
12300{
12301 if (ctx->options & E2F_OPT_NO) {
12302 printf(_("%s? no\n\n"), string);
12303 return 0;
12304 }
12305 if (ctx->options & E2F_OPT_YES) {
12306 printf(_("%s? yes\n\n"), string);
12307 return 1;
12308 }
12309 if (ctx->options & E2F_OPT_PREEN) {
12310 printf("%s? %s\n\n", string, def ? _("yes") : _("no"));
12311 return def;
12312 }
12313 return ask_yn(string, def);
12314}
12315
12316void e2fsck_read_bitmaps(e2fsck_t ctx)
12317{
12318 ext2_filsys fs = ctx->fs;
12319 errcode_t retval;
12320
12321 if (ctx->invalid_bitmaps) {
12322 bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
12323 ctx->device_name);
12324 bb_error_msg_and_die(0);
12325 }
12326
12327 ehandler_operation(_("reading inode and block bitmaps"));
12328 retval = ext2fs_read_bitmaps(fs);
12329 ehandler_operation(0);
12330 if (retval) {
12331 bb_error_msg(_("while retrying to read bitmaps for %s"),
12332 ctx->device_name);
12333 bb_error_msg_and_die(0);
12334 }
12335}
12336
12337static void e2fsck_write_bitmaps(e2fsck_t ctx)
12338{
12339 ext2_filsys fs = ctx->fs;
12340 errcode_t retval;
12341
12342 if (ext2fs_test_bb_dirty(fs)) {
12343 ehandler_operation(_("writing block bitmaps"));
12344 retval = ext2fs_write_block_bitmap(fs);
12345 ehandler_operation(0);
12346 if (retval) {
12347 bb_error_msg(_("while retrying to write block bitmaps for %s"),
12348 ctx->device_name);
12349 bb_error_msg_and_die(0);
12350 }
12351 }
12352
12353 if (ext2fs_test_ib_dirty(fs)) {
12354 ehandler_operation(_("writing inode bitmaps"));
12355 retval = ext2fs_write_inode_bitmap(fs);
12356 ehandler_operation(0);
12357 if (retval) {
12358 bb_error_msg(_("while retrying to write inode bitmaps for %s"),
12359 ctx->device_name);
12360 bb_error_msg_and_die(0);
12361 }
12362 }
12363}
12364
12365void preenhalt(e2fsck_t ctx)
12366{
12367 ext2_filsys fs = ctx->fs;
12368
12369 if (!(ctx->options & E2F_OPT_PREEN))
12370 return;
12371 fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
12372 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
12373 ctx->device_name);
12374 if (fs != NULL) {
12375 fs->super->s_state |= EXT2_ERROR_FS;
12376 ext2fs_mark_super_dirty(fs);
12377 ext2fs_close(fs);
12378 }
12379 exit(EXIT_UNCORRECTED);
12380}
12381
12382void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
12383 struct ext2_inode * inode, const char *proc)
12384{
12385 int retval;
12386
12387 retval = ext2fs_read_inode(ctx->fs, ino, inode);
12388 if (retval) {
12389 bb_error_msg(_("while reading inode %ld in %s"), ino, proc);
12390 bb_error_msg_and_die(0);
12391 }
12392}
12393
12394extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
12395 struct ext2_inode * inode, int bufsize,
12396 const char *proc)
12397{
12398 int retval;
12399
12400 retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
12401 if (retval) {
12402 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12403 bb_error_msg_and_die(0);
12404 }
12405}
12406
12407extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
12408 struct ext2_inode * inode, const char *proc)
12409{
12410 int retval;
12411
12412 retval = ext2fs_write_inode(ctx->fs, ino, inode);
12413 if (retval) {
12414 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12415 bb_error_msg_and_die(0);
12416 }
12417}
12418
12419blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
12420 io_manager manager)
12421{
12422 struct ext2_super_block *sb;
12423 io_channel io = NULL;
12424 void *buf = NULL;
12425 int blocksize;
12426 blk_t superblock, ret_sb = 8193;
12427
12428 if (fs && fs->super) {
12429 ret_sb = (fs->super->s_blocks_per_group +
12430 fs->super->s_first_data_block);
12431 if (ctx) {
12432 ctx->superblock = ret_sb;
12433 ctx->blocksize = fs->blocksize;
12434 }
12435 return ret_sb;
12436 }
12437
12438 if (ctx) {
12439 if (ctx->blocksize) {
12440 ret_sb = ctx->blocksize * 8;
12441 if (ctx->blocksize == 1024)
12442 ret_sb++;
12443 ctx->superblock = ret_sb;
12444 return ret_sb;
12445 }
12446 ctx->superblock = ret_sb;
12447 ctx->blocksize = 1024;
12448 }
12449
12450 if (!name || !manager)
12451 goto cleanup;
12452
12453 if (manager->open(name, 0, &io) != 0)
12454 goto cleanup;
12455
12456 if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
12457 goto cleanup;
12458 sb = (struct ext2_super_block *) buf;
12459
12460 for (blocksize = EXT2_MIN_BLOCK_SIZE;
12461 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
12462 superblock = blocksize*8;
12463 if (blocksize == 1024)
12464 superblock++;
12465 io_channel_set_blksize(io, blocksize);
12466 if (io_channel_read_blk(io, superblock,
12467 -SUPERBLOCK_SIZE, buf))
12468 continue;
12469#if BB_BIG_ENDIAN
12470 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
12471 ext2fs_swap_super(sb);
12472#endif
12473 if (sb->s_magic == EXT2_SUPER_MAGIC) {
12474 ret_sb = superblock;
12475 if (ctx) {
12476 ctx->superblock = superblock;
12477 ctx->blocksize = blocksize;
12478 }
12479 break;
12480 }
12481 }
12482
12483cleanup:
12484 if (io)
12485 io_channel_close(io);
12486 ext2fs_free_mem(&buf);
12487 return ret_sb;
12488}
12489
12490
12491/*
12492 * This function runs through the e2fsck passes and calls them all,
12493 * returning restart, abort, or cancel as necessary...
12494 */
12495typedef void (*pass_t)(e2fsck_t ctx);
12496
12497static const pass_t e2fsck_passes[] = {
12498 e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
12499 e2fsck_pass5, 0 };
12500
12501#define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
12502
12503static int e2fsck_run(e2fsck_t ctx)
12504{
12505 int i;
12506 pass_t e2fsck_pass;
12507
12508 if (setjmp(ctx->abort_loc)) {
12509 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12510 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12511 }
12512 ctx->flags |= E2F_FLAG_SETJMP_OK;
12513
12514 for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
12515 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12516 break;
12517 e2fsck_pass(ctx);
12518 if (ctx->progress)
12519 (void) (ctx->progress)(ctx, 0, 0, 0);
12520 }
12521 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12522
12523 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12524 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12525 return 0;
12526}
12527
12528
12529/*
12530 * unix.c - The unix-specific code for e2fsck
12531 */
12532
12533
12534/* Command line options */
12535static int swapfs;
12536#ifdef ENABLE_SWAPFS
12537static int normalize_swapfs;
12538#endif
12539static int cflag; /* check disk */
12540static int show_version_only;
12541static int verbose;
12542
12543#define P_E2(singular, plural, n) n, ((n) == 1 ? singular : plural)
12544
12545static void show_stats(e2fsck_t ctx)
12546{
12547 ext2_filsys fs = ctx->fs;
12548 int inodes, inodes_used, blocks, blocks_used;
12549 int dir_links;
12550 int num_files, num_links;
12551 int frag_percent;
12552
12553 dir_links = 2 * ctx->fs_directory_count - 1;
12554 num_files = ctx->fs_total_count - dir_links;
12555 num_links = ctx->fs_links_count - dir_links;
12556 inodes = fs->super->s_inodes_count;
12557 inodes_used = (fs->super->s_inodes_count -
12558 fs->super->s_free_inodes_count);
12559 blocks = fs->super->s_blocks_count;
12560 blocks_used = (fs->super->s_blocks_count -
12561 fs->super->s_free_blocks_count);
12562
12563 frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
12564 frag_percent = (frag_percent + 5) / 10;
12565
12566 if (!verbose) {
12567 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
12568 ctx->device_name, inodes_used, inodes,
12569 frag_percent / 10, frag_percent % 10,
12570 blocks_used, blocks);
12571 return;
12572 }
12573 printf("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
12574 100 * inodes_used / inodes);
12575 printf("%8d non-contiguous inode%s (%0d.%d%%)\n",
12576 P_E2("", "s", ctx->fs_fragmented),
12577 frag_percent / 10, frag_percent % 10);
12578 printf(_(" # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
12579 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
12580 printf("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
12581 (int) ((long long) 100 * blocks_used / blocks));
12582 printf("%8d large file%s\n", P_E2("", "s", ctx->large_files));
12583 printf("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
12584 printf("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
12585 printf("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
12586 printf("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
12587 printf("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
12588 printf("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
12589 printf("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
12590 printf(" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
12591 printf("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
12592 printf("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
12593}
12594
12595static void check_mount(e2fsck_t ctx)
12596{
12597 errcode_t retval;
12598 int cont;
12599
12600 retval = ext2fs_check_if_mounted(ctx->filesystem_name,
12601 &ctx->mount_flags);
12602 if (retval) {
12603 bb_error_msg(_("while determining whether %s is mounted"),
12604 ctx->filesystem_name);
12605 return;
12606 }
12607
12608 /*
12609 * If the filesystem isn't mounted, or it's the root filesystem
12610 * and it's mounted read-only, then everything's fine.
12611 */
12612 if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
12613 ((ctx->mount_flags & EXT2_MF_ISROOT) &&
12614 (ctx->mount_flags & EXT2_MF_READONLY)))
12615 return;
12616
12617 if (ctx->options & E2F_OPT_READONLY) {
12618 printf(_("Warning! %s is mounted.\n"), ctx->filesystem_name);
12619 return;
12620 }
12621
12622 printf(_("%s is mounted. "), ctx->filesystem_name);
12623 if (!ctx->interactive)
12624 bb_error_msg_and_die(_("can't continue, aborting"));
12625 printf(_("\n\n\007\007\007\007WARNING!!! "
12626 "Running e2fsck on a mounted filesystem may cause\n"
12627 "SEVERE filesystem damage.\007\007\007\n\n"));
12628 cont = ask_yn(_("Do you really want to continue"), -1);
12629 if (!cont) {
12630 printf(_("check aborted.\n"));
12631 exit(0);
12632 }
12633}
12634
12635static int is_on_batt(void)
12636{
12637 FILE *f;
12638 DIR *d;
12639 char tmp[80], tmp2[80], fname[80];
12640 unsigned int acflag;
12641 struct dirent* de;
12642
12643 f = fopen_for_read("/proc/apm");
12644 if (f) {
12645 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
12646 acflag = 1;
12647 fclose(f);
12648 return (acflag != 1);
12649 }
12650 d = opendir("/proc/acpi/ac_adapter");
12651 if (d) {
12652 while ((de=readdir(d)) != NULL) {
12653 if (!strncmp(".", de->d_name, 1))
12654 continue;
12655 snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
12656 de->d_name);
12657 f = fopen_for_read(fname);
12658 if (!f)
12659 continue;
12660 if (fscanf(f, "%s %s", tmp2, tmp) != 2)
12661 tmp[0] = 0;
12662 fclose(f);
12663 if (strncmp(tmp, "off-line", 8) == 0) {
12664 closedir(d);
12665 return 1;
12666 }
12667 }
12668 closedir(d);
12669 }
12670 return 0;
12671}
12672
12673/*
12674 * This routine checks to see if a filesystem can be skipped; if so,
12675 * it will exit with EXIT_OK. Under some conditions it will print a
12676 * message explaining why a check is being forced.
12677 */
12678static void check_if_skip(e2fsck_t ctx)
12679{
12680 ext2_filsys fs = ctx->fs;
12681 const char *reason = NULL;
12682 unsigned int reason_arg = 0;
12683 long next_check;
12684 int batt = is_on_batt();
12685 time_t now = time(NULL);
12686
12687 if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
12688 return;
12689
12690 if ((fs->super->s_state & EXT2_ERROR_FS) ||
12691 !ext2fs_test_valid(fs))
12692 reason = _(" contains a file system with errors");
12693 else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
12694 reason = _(" was not cleanly unmounted");
12695 else if ((fs->super->s_max_mnt_count > 0) &&
12696 (fs->super->s_mnt_count >=
12697 (unsigned) fs->super->s_max_mnt_count)) {
12698 reason = _(" has been mounted %u times without being checked");
12699 reason_arg = fs->super->s_mnt_count;
12700 if (batt && (fs->super->s_mnt_count <
12701 (unsigned) fs->super->s_max_mnt_count*2))
12702 reason = 0;
12703 } else if (fs->super->s_checkinterval &&
12704 ((now - fs->super->s_lastcheck) >=
12705 fs->super->s_checkinterval)) {
12706 reason = _(" has gone %u days without being checked");
12707 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
12708 if (batt && ((now - fs->super->s_lastcheck) <
12709 fs->super->s_checkinterval*2))
12710 reason = 0;
12711 }
12712 if (reason) {
12713 fputs(ctx->device_name, stdout);
12714 printf(reason, reason_arg);
12715 fputs(_(", check forced.\n"), stdout);
12716 return;
12717 }
12718 printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
12719 fs->super->s_inodes_count - fs->super->s_free_inodes_count,
12720 fs->super->s_inodes_count,
12721 fs->super->s_blocks_count - fs->super->s_free_blocks_count,
12722 fs->super->s_blocks_count);
12723 next_check = 100000;
12724 if (fs->super->s_max_mnt_count > 0) {
12725 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
12726 if (next_check <= 0)
12727 next_check = 1;
12728 }
12729 if (fs->super->s_checkinterval &&
12730 ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
12731 next_check = 1;
12732 if (next_check <= 5) {
12733 if (next_check == 1)
12734 fputs(_(" (check after next mount)"), stdout);
12735 else
12736 printf(_(" (check in %ld mounts)"), next_check);
12737 }
12738 bb_putchar('\n');
12739 ext2fs_close(fs);
12740 ctx->fs = NULL;
12741 e2fsck_free_context(ctx);
12742 exit(EXIT_OK);
12743}
12744
12745/*
12746 * For completion notice
12747 */
12748struct percent_tbl {
12749 int max_pass;
12750 int table[32];
12751};
12752static const struct percent_tbl e2fsck_tbl = {
12753 5, { 0, 70, 90, 92, 95, 100 }
12754};
12755
12756static char bar[128], spaces[128];
12757
12758static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
12759 int max)
12760{
12761 float percent;
12762
12763 if (pass <= 0)
12764 return 0.0;
12765 if (pass > tbl->max_pass || max == 0)
12766 return 100.0;
12767 percent = ((float) curr) / ((float) max);
12768 return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
12769 + tbl->table[pass-1]);
12770}
12771
12772void e2fsck_clear_progbar(e2fsck_t ctx)
12773{
12774 if (!(ctx->flags & E2F_FLAG_PROG_BAR))
12775 return;
12776
12777 printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
12778 ctx->stop_meta);
12779 fflush(stdout);
12780 ctx->flags &= ~E2F_FLAG_PROG_BAR;
12781}
12782
12783int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
12784 unsigned int dpynum)
12785{
12786 static const char spinner[] = "\\|/-";
12787 int i;
12788 unsigned int tick;
12789 struct timeval tv;
12790 int dpywidth;
12791 int fixed_percent;
12792
12793 if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
12794 return 0;
12795
12796 /*
12797 * Calculate the new progress position. If the
12798 * percentage hasn't changed, then we skip out right
12799 * away.
12800 */
12801 fixed_percent = (int) ((10 * percent) + 0.5);
12802 if (ctx->progress_last_percent == fixed_percent)
12803 return 0;
12804 ctx->progress_last_percent = fixed_percent;
12805
12806 /*
12807 * If we've already updated the spinner once within
12808 * the last 1/8th of a second, no point doing it
12809 * again.
12810 */
12811 gettimeofday(&tv, NULL);
12812 tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
12813 if ((tick == ctx->progress_last_time) &&
12814 (fixed_percent != 0) && (fixed_percent != 1000))
12815 return 0;
12816 ctx->progress_last_time = tick;
12817
12818 /*
12819 * Advance the spinner, and note that the progress bar
12820 * will be on the screen
12821 */
12822 ctx->progress_pos = (ctx->progress_pos+1) & 3;
12823 ctx->flags |= E2F_FLAG_PROG_BAR;
12824
12825 dpywidth = 66 - strlen(label);
12826 dpywidth = 8 * (dpywidth / 8);
12827 if (dpynum)
12828 dpywidth -= 8;
12829
12830 i = ((percent * dpywidth) + 50) / 100;
12831 printf("%s%s: |%s%s", ctx->start_meta, label,
12832 bar + (sizeof(bar) - (i+1)),
12833 spaces + (sizeof(spaces) - (dpywidth - i + 1)));
12834 if (fixed_percent == 1000)
12835 bb_putchar('|');
12836 else
12837 bb_putchar(spinner[ctx->progress_pos & 3]);
12838 printf(" %4.1f%% ", percent);
12839 if (dpynum)
12840 printf("%u\r", dpynum);
12841 else
12842 fputs(" \r", stdout);
12843 fputs(ctx->stop_meta, stdout);
12844
12845 if (fixed_percent == 1000)
12846 e2fsck_clear_progbar(ctx);
12847 fflush(stdout);
12848
12849 return 0;
12850}
12851
12852static int e2fsck_update_progress(e2fsck_t ctx, int pass,
12853 unsigned long cur, unsigned long max)
12854{
12855 char buf[80];
12856 float percent;
12857
12858 if (pass == 0)
12859 return 0;
12860
12861 if (ctx->progress_fd) {
12862 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
12863 xwrite_str(ctx->progress_fd, buf);
12864 } else {
12865 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
12866 e2fsck_simple_progress(ctx, ctx->device_name,
12867 percent, 0);
12868 }
12869 return 0;
12870}
12871
12872static void reserve_stdio_fds(void)
12873{
12874 int fd;
12875
12876 while (1) {
12877 fd = open(bb_dev_null, O_RDWR);
12878 if (fd > 2)
12879 break;
12880 if (fd < 0) {
12881 fprintf(stderr, _("ERROR: Cannot open "
12882 "/dev/null (%s)\n"),
12883 strerror(errno));
12884 break;
12885 }
12886 }
12887 close(fd);
12888}
12889
12890static void signal_progress_on(int sig FSCK_ATTR((unused)))
12891{
12892 e2fsck_t ctx = e2fsck_global_ctx;
12893
12894 if (!ctx)
12895 return;
12896
12897 ctx->progress = e2fsck_update_progress;
12898 ctx->progress_fd = 0;
12899}
12900
12901static void signal_progress_off(int sig FSCK_ATTR((unused)))
12902{
12903 e2fsck_t ctx = e2fsck_global_ctx;
12904
12905 if (!ctx)
12906 return;
12907
12908 e2fsck_clear_progbar(ctx);
12909 ctx->progress = 0;
12910}
12911
12912static void signal_cancel(int sig FSCK_ATTR((unused)))
12913{
12914 e2fsck_t ctx = e2fsck_global_ctx;
12915
12916 if (!ctx)
12917 exit(FSCK_CANCELED);
12918
12919 ctx->flags |= E2F_FLAG_CANCEL;
12920}
12921
12922static void parse_extended_opts(e2fsck_t ctx, const char *opts)
12923{
12924 char *buf, *token, *next, *p, *arg;
12925 int ea_ver;
12926 int extended_usage = 0;
12927
12928 buf = string_copy(opts, 0);
12929 for (token = buf; token && *token; token = next) {
12930 p = strchr(token, ',');
12931 next = 0;
12932 if (p) {
12933 *p = 0;
12934 next = p+1;
12935 }
12936 arg = strchr(token, '=');
12937 if (arg) {
12938 *arg = 0;
12939 arg++;
12940 }
12941 if (strcmp(token, "ea_ver") == 0) {
12942 if (!arg) {
12943 extended_usage++;
12944 continue;
12945 }
12946 ea_ver = strtoul(arg, &p, 0);
12947 if (*p ||
12948 ((ea_ver != 1) && (ea_ver != 2))) {
12949 fprintf(stderr,
12950 _("Invalid EA version.\n"));
12951 extended_usage++;
12952 continue;
12953 }
12954 ctx->ext_attr_ver = ea_ver;
12955 } else {
12956 fprintf(stderr, _("Unknown extended option: %s\n"),
12957 token);
12958 extended_usage++;
12959 }
12960 }
12961 if (extended_usage) {
12962 bb_error_msg_and_die(
12963 "Extended options are separated by commas, "
12964 "and may take an argument which\n"
12965 "is set off by an equals ('=') sign. "
12966 "Valid extended options are:\n"
12967 "\tea_ver=<ea_version (1 or 2)>\n\n");
12968 }
12969}
12970
12971
12972static errcode_t PRS(int argc, char **argv, e2fsck_t *ret_ctx)
12973{
12974 int flush = 0;
12975 int c, fd;
12976 e2fsck_t ctx;
12977 errcode_t retval;
12978 struct sigaction sa;
12979 char *extended_opts = NULL;
12980
12981 retval = e2fsck_allocate_context(&ctx);
12982 if (retval)
12983 return retval;
12984
12985 *ret_ctx = ctx;
12986
12987 setvbuf(stdout, NULL, _IONBF, BUFSIZ);
12988 setvbuf(stderr, NULL, _IONBF, BUFSIZ);
12989 if (isatty(0) && isatty(1)) {
12990 ctx->interactive = 1;
12991 } else {
12992 ctx->start_meta[0] = '\001';
12993 ctx->stop_meta[0] = '\002';
12994 }
12995 memset(bar, '=', sizeof(bar)-1);
12996 memset(spaces, ' ', sizeof(spaces)-1);
12997 blkid_get_cache(&ctx->blkid, NULL);
12998
12999 if (argc && *argv)
13000 ctx->program_name = *argv;
13001 else
13002 ctx->program_name = "e2fsck";
13003 while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
13004 switch (c) {
13005 case 'C':
13006 ctx->progress = e2fsck_update_progress;
13007 ctx->progress_fd = atoi(optarg);
13008 if (!ctx->progress_fd)
13009 break;
13010 /* Validate the file descriptor to avoid disasters */
13011 fd = dup(ctx->progress_fd);
13012 if (fd < 0) {
13013 fprintf(stderr,
13014 _("Error validating file descriptor %d: %s\n"),
13015 ctx->progress_fd,
13016 error_message(errno));
13017 bb_error_msg_and_die(_("Invalid completion information file descriptor"));
13018 } else
13019 close(fd);
13020 break;
13021 case 'D':
13022 ctx->options |= E2F_OPT_COMPRESS_DIRS;
13023 break;
13024 case 'E':
13025 extended_opts = optarg;
13026 break;
13027 case 'p':
13028 case 'a':
13029 if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
13030 conflict_opt:
13031 bb_error_msg_and_die(_("only one the options -p/-a, -n or -y may be specified"));
13032 }
13033 ctx->options |= E2F_OPT_PREEN;
13034 break;
13035 case 'n':
13036 if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
13037 goto conflict_opt;
13038 ctx->options |= E2F_OPT_NO;
13039 break;
13040 case 'y':
13041 if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
13042 goto conflict_opt;
13043 ctx->options |= E2F_OPT_YES;
13044 break;
13045 case 't':
13046 /* FIXME - This needs to go away in a future path - will change binary */
13047 fprintf(stderr, _("The -t option is not "
13048 "supported on this version of e2fsck.\n"));
13049 break;
13050 case 'c':
13051 if (cflag++)
13052 ctx->options |= E2F_OPT_WRITECHECK;
13053 ctx->options |= E2F_OPT_CHECKBLOCKS;
13054 break;
13055 case 'r':
13056 /* What we do by default, anyway! */
13057 break;
13058 case 'b':
13059 ctx->use_superblock = atoi(optarg);
13060 ctx->flags |= E2F_FLAG_SB_SPECIFIED;
13061 break;
13062 case 'B':
13063 ctx->blocksize = atoi(optarg);
13064 break;
13065 case 'I':
13066 ctx->inode_buffer_blocks = atoi(optarg);
13067 break;
13068 case 'j':
13069 ctx->journal_name = string_copy(optarg, 0);
13070 break;
13071 case 'P':
13072 ctx->process_inode_size = atoi(optarg);
13073 break;
13074 case 'd':
13075 ctx->options |= E2F_OPT_DEBUG;
13076 break;
13077 case 'f':
13078 ctx->options |= E2F_OPT_FORCE;
13079 break;
13080 case 'F':
13081 flush = 1;
13082 break;
13083 case 'v':
13084 verbose = 1;
13085 break;
13086 case 'V':
13087 show_version_only = 1;
13088 break;
13089 case 'N':
13090 ctx->device_name = optarg;
13091 break;
13092#ifdef ENABLE_SWAPFS
13093 case 's':
13094 normalize_swapfs = 1;
13095 case 'S':
13096 swapfs = 1;
13097 break;
13098#else
13099 case 's':
13100 case 'S':
13101 fprintf(stderr, _("Byte-swapping filesystems "
13102 "not compiled in this version "
13103 "of e2fsck\n"));
13104 exit(1);
13105#endif
13106 default:
13107 bb_show_usage();
13108 }
13109 if (show_version_only)
13110 return 0;
13111 if (optind != argc - 1)
13112 bb_show_usage();
13113 if ((ctx->options & E2F_OPT_NO) &&
13114 !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
13115 ctx->options |= E2F_OPT_READONLY;
13116 ctx->io_options = strchr(argv[optind], '?');
13117 if (ctx->io_options)
13118 *ctx->io_options++ = 0;
13119 ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
13120 if (!ctx->filesystem_name) {
13121 bb_error_msg(_("Unable to resolve '%s'"), argv[optind]);
13122 bb_error_msg_and_die(0);
13123 }
13124 if (extended_opts)
13125 parse_extended_opts(ctx, extended_opts);
13126
13127 if (flush) {
13128 fd = open(ctx->filesystem_name, O_RDONLY, 0);
13129 if (fd < 0) {
13130 bb_error_msg(_("while opening %s for flushing"),
13131 ctx->filesystem_name);
13132 bb_error_msg_and_die(0);
13133 }
13134 if ((retval = ext2fs_sync_device(fd, 1))) {
13135 bb_error_msg(_("while trying to flush %s"),
13136 ctx->filesystem_name);
13137 bb_error_msg_and_die(0);
13138 }
13139 close(fd);
13140 }
13141#ifdef ENABLE_SWAPFS
13142 if (swapfs && cflag) {
13143 fprintf(stderr, _("Incompatible options not "
13144 "allowed when byte-swapping.\n"));
13145 exit(EXIT_USAGE);
13146 }
13147#endif
13148 /*
13149 * Set up signal action
13150 */
13151 memset(&sa, 0, sizeof(struct sigaction));
13152 sa.sa_handler = signal_cancel;
13153 sigaction(SIGINT, &sa, 0);
13154 sigaction(SIGTERM, &sa, 0);
13155#ifdef SA_RESTART
13156 sa.sa_flags = SA_RESTART;
13157#endif
13158 e2fsck_global_ctx = ctx;
13159 sa.sa_handler = signal_progress_on;
13160 sigaction(SIGUSR1, &sa, 0);
13161 sa.sa_handler = signal_progress_off;
13162 sigaction(SIGUSR2, &sa, 0);
13163
13164 /* Update our PATH to include /sbin if we need to run badblocks */
13165 if (cflag)
13166 e2fs_set_sbin_path();
13167 return 0;
13168}
13169
13170static const char my_ver_string[] = E2FSPROGS_VERSION;
13171static const char my_ver_date[] = E2FSPROGS_DATE;
13172
13173int e2fsck_main (int argc, char **argv);
13174int e2fsck_main (int argc, char **argv)
13175{
13176 errcode_t retval;
13177 int exit_value = EXIT_OK;
13178 ext2_filsys fs = 0;
13179 io_manager io_ptr;
13180 struct ext2_super_block *sb;
13181 const char *lib_ver_date;
13182 int my_ver, lib_ver;
13183 e2fsck_t ctx;
13184 struct problem_context pctx;
13185 int flags, run_result;
13186
13187 clear_problem_context(&pctx);
13188
13189 my_ver = ext2fs_parse_version_string(my_ver_string);
13190 lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
13191 if (my_ver > lib_ver) {
13192 fprintf( stderr, _("Error: ext2fs library version "
13193 "out of date!\n"));
13194 show_version_only++;
13195 }
13196
13197 retval = PRS(argc, argv, &ctx);
13198 if (retval) {
13199 bb_error_msg(_("while trying to initialize program"));
13200 exit(EXIT_ERROR);
13201 }
13202 reserve_stdio_fds();
13203
13204 if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
13205 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
13206 my_ver_date);
13207
13208 if (show_version_only) {
13209 fprintf(stderr, _("\tUsing %s, %s\n"),
13210 error_message(EXT2_ET_BASE), lib_ver_date);
13211 exit(EXIT_OK);
13212 }
13213
13214 check_mount(ctx);
13215
13216 if (!(ctx->options & E2F_OPT_PREEN) &&
13217 !(ctx->options & E2F_OPT_NO) &&
13218 !(ctx->options & E2F_OPT_YES)) {
13219 if (!ctx->interactive)
13220 bb_error_msg_and_die(_("need terminal for interactive repairs"));
13221 }
13222 ctx->superblock = ctx->use_superblock;
13223restart:
13224#ifdef CONFIG_TESTIO_DEBUG
13225 io_ptr = test_io_manager;
13226 test_io_backing_manager = unix_io_manager;
13227#else
13228 io_ptr = unix_io_manager;
13229#endif
13230 flags = 0;
13231 if ((ctx->options & E2F_OPT_READONLY) == 0)
13232 flags |= EXT2_FLAG_RW;
13233
13234 if (ctx->superblock && ctx->blocksize) {
13235 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13236 flags, ctx->superblock, ctx->blocksize,
13237 io_ptr, &fs);
13238 } else if (ctx->superblock) {
13239 int blocksize;
13240 for (blocksize = EXT2_MIN_BLOCK_SIZE;
13241 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
13242 retval = ext2fs_open2(ctx->filesystem_name,
13243 ctx->io_options, flags,
13244 ctx->superblock, blocksize,
13245 io_ptr, &fs);
13246 if (!retval)
13247 break;
13248 }
13249 } else
13250 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13251 flags, 0, 0, io_ptr, &fs);
13252 if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
13253 !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
13254 ((retval == EXT2_ET_BAD_MAGIC) ||
13255 ((retval == 0) && ext2fs_check_desc(fs)))) {
13256 if (!fs || (fs->group_desc_count > 1)) {
13257 printf(_("%s trying backup blocks...\n"),
13258 retval ? _("Couldn't find ext2 superblock,") :
13259 _("Group descriptors look bad..."));
13260 get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
13261 if (fs)
13262 ext2fs_close(fs);
13263 goto restart;
13264 }
13265 }
13266 if (retval) {
13267 bb_error_msg(_("while trying to open %s"),
13268 ctx->filesystem_name);
13269 if (retval == EXT2_ET_REV_TOO_HIGH) {
13270 printf(_("The filesystem revision is apparently "
13271 "too high for this version of e2fsck.\n"
13272 "(Or the filesystem superblock "
13273 "is corrupt)\n\n"));
13274 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13275 } else if (retval == EXT2_ET_SHORT_READ)
13276 printf(_("Could this be a zero-length partition?\n"));
13277 else if ((retval == EPERM) || (retval == EACCES))
13278 printf(_("You must have %s access to the "
13279 "filesystem or be root\n"),
13280 (ctx->options & E2F_OPT_READONLY) ?
13281 "r/o" : "r/w");
13282 else if (retval == ENXIO)
13283 printf(_("Possibly non-existent or swap device?\n"));
13284#ifdef EROFS
13285 else if (retval == EROFS)
13286 printf(_("Disk write-protected; use the -n option "
13287 "to do a read-only\n"
13288 "check of the device.\n"));
13289#endif
13290 else
13291 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13292 bb_error_msg_and_die(0);
13293 }
13294 ctx->fs = fs;
13295 fs->priv_data = ctx;
13296 sb = fs->super;
13297 if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
13298 bb_error_msg(_("while trying to open %s"),
13299 ctx->filesystem_name);
13300 get_newer:
13301 bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
13302 }
13303
13304 /*
13305 * Set the device name, which is used whenever we print error
13306 * or informational messages to the user.
13307 */
13308 if (ctx->device_name == 0 &&
13309 (sb->s_volume_name[0] != 0)) {
13310 ctx->device_name = string_copy(sb->s_volume_name,
13311 sizeof(sb->s_volume_name));
13312 }
13313 if (ctx->device_name == 0)
13314 ctx->device_name = ctx->filesystem_name;
13315
13316 /*
13317 * Make sure the ext3 superblock fields are consistent.
13318 */
13319 retval = e2fsck_check_ext3_journal(ctx);
13320 if (retval) {
13321 bb_error_msg(_("while checking ext3 journal for %s"),
13322 ctx->device_name);
13323 bb_error_msg_and_die(0);
13324 }
13325
13326 /*
13327 * Check to see if we need to do ext3-style recovery. If so,
13328 * do it, and then restart the fsck.
13329 */
13330 if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
13331 if (ctx->options & E2F_OPT_READONLY) {
13332 printf(_("Warning: skipping journal recovery "
13333 "because doing a read-only filesystem "
13334 "check.\n"));
13335 io_channel_flush(ctx->fs->io);
13336 } else {
13337 if (ctx->flags & E2F_FLAG_RESTARTED) {
13338 /*
13339 * Whoops, we attempted to run the
13340 * journal twice. This should never
13341 * happen, unless the hardware or
13342 * device driver is being bogus.
13343 */
13344 bb_error_msg(_("can't set superblock flags on %s"), ctx->device_name);
13345 bb_error_msg_and_die(0);
13346 }
13347 retval = e2fsck_run_ext3_journal(ctx);
13348 if (retval) {
13349 bb_error_msg(_("while recovering ext3 journal of %s"),
13350 ctx->device_name);
13351 bb_error_msg_and_die(0);
13352 }
13353 ext2fs_close(ctx->fs);
13354 ctx->fs = 0;
13355 ctx->flags |= E2F_FLAG_RESTARTED;
13356 goto restart;
13357 }
13358 }
13359
13360 /*
13361 * Check for compatibility with the feature sets. We need to
13362 * be more stringent than ext2fs_open().
13363 */
13364 if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
13365 (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
13366 bb_error_msg("(%s)", ctx->device_name);
13367 goto get_newer;
13368 }
13369 if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
13370 bb_error_msg("(%s)", ctx->device_name);
13371 goto get_newer;
13372 }
13373#ifdef ENABLE_COMPRESSION
13374 /* FIXME - do we support this at all? */
13375 if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
13376 bb_error_msg(_("warning: compression support is experimental"));
13377#endif
13378#ifndef ENABLE_HTREE
13379 if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
13380 bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
13381 "but filesystem %s has HTREE directories."),
13382 ctx->device_name);
13383 goto get_newer;
13384 }
13385#endif
13386
13387 /*
13388 * If the user specified a specific superblock, presumably the
13389 * master superblock has been trashed. So we mark the
13390 * superblock as dirty, so it can be written out.
13391 */
13392 if (ctx->superblock &&
13393 !(ctx->options & E2F_OPT_READONLY))
13394 ext2fs_mark_super_dirty(fs);
13395
13396 /*
13397 * We only update the master superblock because (a) paranoia;
13398 * we don't want to corrupt the backup superblocks, and (b) we
13399 * don't need to update the mount count and last checked
13400 * fields in the backup superblock (the kernel doesn't
13401 * update the backup superblocks anyway).
13402 */
13403 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
13404
13405 ehandler_init(fs->io);
13406
13407 if (ctx->superblock)
13408 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
13409 ext2fs_mark_valid(fs);
13410 check_super_block(ctx);
13411 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13412 bb_error_msg_and_die(0);
13413 check_if_skip(ctx);
13414 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13415 bb_error_msg_and_die(0);
13416#ifdef ENABLE_SWAPFS
13417
13418#ifdef WORDS_BIGENDIAN
13419#define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
13420#else
13421#define NATIVE_FLAG 0
13422#endif
13423
13424
13425 if (normalize_swapfs) {
13426 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
13427 fprintf(stderr, _("%s: Filesystem byte order "
13428 "already normalized.\n"), ctx->device_name);
13429 bb_error_msg_and_die(0);
13430 }
13431 }
13432 if (swapfs) {
13433 swap_filesys(ctx);
13434 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13435 bb_error_msg_and_die(0);
13436 }
13437#endif
13438
13439 /*
13440 * Mark the system as valid, 'til proven otherwise
13441 */
13442 ext2fs_mark_valid(fs);
13443
13444 retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
13445 if (retval) {
13446 bb_error_msg(_("while reading bad blocks inode"));
13447 preenhalt(ctx);
13448 printf(_("This doesn't bode well,"
13449 " but we'll try to go on...\n"));
13450 }
13451
13452 run_result = e2fsck_run(ctx);
13453 e2fsck_clear_progbar(ctx);
13454 if (run_result == E2F_FLAG_RESTART) {
13455 printf(_("Restarting e2fsck from the beginning...\n"));
13456 retval = e2fsck_reset_context(ctx);
13457 if (retval) {
13458 bb_error_msg(_("while resetting context"));
13459 bb_error_msg_and_die(0);
13460 }
13461 ext2fs_close(fs);
13462 goto restart;
13463 }
13464 if (run_result & E2F_FLAG_CANCEL) {
13465 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
13466 ctx->device_name : ctx->filesystem_name);
13467 exit_value |= FSCK_CANCELED;
13468 }
13469 if (run_result & E2F_FLAG_ABORT)
13470 bb_error_msg_and_die(_("aborted"));
13471
13472 /* Cleanup */
13473 if (ext2fs_test_changed(fs)) {
13474 exit_value |= EXIT_NONDESTRUCT;
13475 if (!(ctx->options & E2F_OPT_PREEN))
13476 printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
13477 ctx->device_name);
13478 if (ctx->mount_flags & EXT2_MF_ISROOT) {
13479 printf(_("%s: ***** REBOOT LINUX *****\n"),
13480 ctx->device_name);
13481 exit_value |= EXIT_DESTRUCT;
13482 }
13483 }
13484 if (!ext2fs_test_valid(fs)) {
13485 printf(_("\n%s: ********** WARNING: Filesystem still has "
13486 "errors **********\n\n"), ctx->device_name);
13487 exit_value |= EXIT_UNCORRECTED;
13488 exit_value &= ~EXIT_NONDESTRUCT;
13489 }
13490 if (exit_value & FSCK_CANCELED)
13491 exit_value &= ~EXIT_NONDESTRUCT;
13492 else {
13493 show_stats(ctx);
13494 if (!(ctx->options & E2F_OPT_READONLY)) {
13495 if (ext2fs_test_valid(fs)) {
13496 if (!(sb->s_state & EXT2_VALID_FS))
13497 exit_value |= EXIT_NONDESTRUCT;
13498 sb->s_state = EXT2_VALID_FS;
13499 } else
13500 sb->s_state &= ~EXT2_VALID_FS;
13501 sb->s_mnt_count = 0;
13502 sb->s_lastcheck = time(NULL);
13503 ext2fs_mark_super_dirty(fs);
13504 }
13505 }
13506
13507 e2fsck_write_bitmaps(ctx);
13508
13509 ext2fs_close(fs);
13510 ctx->fs = NULL;
13511 free(ctx->filesystem_name);
13512 free(ctx->journal_name);
13513 e2fsck_free_context(ctx);
13514
13515 return exit_value;
13516}
diff --git a/e2fsprogs/old_e2fsprogs/e2fsck.h b/e2fsprogs/old_e2fsprogs/e2fsck.h
deleted file mode 100644
index c159fabab..000000000
--- a/e2fsprogs/old_e2fsprogs/e2fsck.h
+++ /dev/null
@@ -1,638 +0,0 @@
1/* vi: set sw=4 ts=4: */
2#include <sys/types.h>
3#include <stdio.h>
4#include <string.h>
5#include <unistd.h>
6#include <stdlib.h>
7#include <time.h>
8#include <fcntl.h>
9#include <ctype.h>
10#include <setjmp.h>
11#include <errno.h>
12#include <getopt.h>
13#include <limits.h>
14#include <stddef.h>
15#include <assert.h>
16#include <signal.h>
17#include <sys/stat.h>
18#include <sys/resource.h>
19#include <sys/param.h>
20#include <sys/mount.h>
21#include <sys/ioctl.h>
22#include <termios.h>
23#include <mntent.h>
24#include <dirent.h>
25#include "ext2fs/kernel-list.h"
26#include <sys/types.h>
27#include <linux/types.h>
28
29/*
30 * Now pull in the real linux/jfs.h definitions.
31 */
32#include "ext2fs/kernel-jbd.h"
33
34
35
36#include "fsck.h"
37
38#include "ext2fs/ext2_fs.h"
39#include "blkid/blkid.h"
40#include "ext2fs/ext2_ext_attr.h"
41#include "uuid/uuid.h"
42#include "libbb.h"
43
44#ifdef HAVE_CONIO_H
45#undef HAVE_TERMIOS_H
46#include <conio.h>
47#define read_a_char() getch()
48#else
49#ifdef HAVE_TERMIOS_H
50#include <termios.h>
51#endif
52#endif
53
54
55/*
56 * The last ext2fs revision level that this version of e2fsck is able to
57 * support
58 */
59#define E2FSCK_CURRENT_REV 1
60
61/* Used by the region allocation code */
62typedef __u32 region_addr_t;
63typedef struct region_struct *region_t;
64
65struct dx_dirblock_info {
66 int type;
67 blk_t phys;
68 int flags;
69 blk_t parent;
70 ext2_dirhash_t min_hash;
71 ext2_dirhash_t max_hash;
72 ext2_dirhash_t node_min_hash;
73 ext2_dirhash_t node_max_hash;
74};
75
76/*
77These defines are used in the type field of dx_dirblock_info
78*/
79
80#define DX_DIRBLOCK_ROOT 1
81#define DX_DIRBLOCK_LEAF 2
82#define DX_DIRBLOCK_NODE 3
83
84
85/*
86The following defines are used in the 'flags' field of a dx_dirblock_info
87*/
88#define DX_FLAG_REFERENCED 1
89#define DX_FLAG_DUP_REF 2
90#define DX_FLAG_FIRST 4
91#define DX_FLAG_LAST 8
92
93/*
94 * E2fsck options
95 */
96#define E2F_OPT_READONLY 0x0001
97#define E2F_OPT_PREEN 0x0002
98#define E2F_OPT_YES 0x0004
99#define E2F_OPT_NO 0x0008
100#define E2F_OPT_TIME 0x0010
101#define E2F_OPT_CHECKBLOCKS 0x0040
102#define E2F_OPT_DEBUG 0x0080
103#define E2F_OPT_FORCE 0x0100
104#define E2F_OPT_WRITECHECK 0x0200
105#define E2F_OPT_COMPRESS_DIRS 0x0400
106
107/*
108 * E2fsck flags
109 */
110#define E2F_FLAG_ABORT 0x0001 /* Abort signaled */
111#define E2F_FLAG_CANCEL 0x0002 /* Cancel signaled */
112#define E2F_FLAG_SIGNAL_MASK 0x0003
113#define E2F_FLAG_RESTART 0x0004 /* Restart signaled */
114
115#define E2F_FLAG_SETJMP_OK 0x0010 /* Setjmp valid for abort */
116
117#define E2F_FLAG_PROG_BAR 0x0020 /* Progress bar on screen */
118#define E2F_FLAG_PROG_SUPPRESS 0x0040 /* Progress suspended */
119#define E2F_FLAG_JOURNAL_INODE 0x0080 /* Create a new ext3 journal inode */
120#define E2F_FLAG_SB_SPECIFIED 0x0100 /* The superblock was explicitly
121 * specified by the user */
122#define E2F_FLAG_RESTARTED 0x0200 /* E2fsck has been restarted */
123#define E2F_FLAG_RESIZE_INODE 0x0400 /* Request to recreate resize inode */
124
125
126/*Don't know where these come from*/
127#define READ 0
128#define WRITE 1
129#define cpu_to_be32(n) htonl(n)
130#define be32_to_cpu(n) ntohl(n)
131
132/*
133 * We define a set of "latch groups"; these are problems which are
134 * handled as a set. The user answers once for a particular latch
135 * group.
136 */
137#define PR_LATCH_MASK 0x0ff0 /* Latch mask */
138#define PR_LATCH_BLOCK 0x0010 /* Latch for illegal blocks (pass 1) */
139#define PR_LATCH_BBLOCK 0x0020 /* Latch for bad block inode blocks (pass 1) */
140#define PR_LATCH_IBITMAP 0x0030 /* Latch for pass 5 inode bitmap proc. */
141#define PR_LATCH_BBITMAP 0x0040 /* Latch for pass 5 inode bitmap proc. */
142#define PR_LATCH_RELOC 0x0050 /* Latch for superblock relocate hint */
143#define PR_LATCH_DBLOCK 0x0060 /* Latch for pass 1b dup block headers */
144#define PR_LATCH_LOW_DTIME 0x0070 /* Latch for pass1 orphaned list refugees */
145#define PR_LATCH_TOOBIG 0x0080 /* Latch for file to big errors */
146#define PR_LATCH_OPTIMIZE_DIR 0x0090 /* Latch for optimize directories */
147
148#define PR_LATCH(x) ((((x) & PR_LATCH_MASK) >> 4) - 1)
149
150/*
151 * Latch group descriptor flags
152 */
153#define PRL_YES 0x0001 /* Answer yes */
154#define PRL_NO 0x0002 /* Answer no */
155#define PRL_LATCHED 0x0004 /* The latch group is latched */
156#define PRL_SUPPRESS 0x0008 /* Suppress all latch group questions */
157
158#define PRL_VARIABLE 0x000f /* All the flags that need to be reset */
159
160/*
161 * Pre-Pass 1 errors
162 */
163
164#define PR_0_BB_NOT_GROUP 0x000001 /* Block bitmap not in group */
165#define PR_0_IB_NOT_GROUP 0x000002 /* Inode bitmap not in group */
166#define PR_0_ITABLE_NOT_GROUP 0x000003 /* Inode table not in group */
167#define PR_0_SB_CORRUPT 0x000004 /* Superblock corrupt */
168#define PR_0_FS_SIZE_WRONG 0x000005 /* Filesystem size is wrong */
169#define PR_0_NO_FRAGMENTS 0x000006 /* Fragments not supported */
170#define PR_0_BLOCKS_PER_GROUP 0x000007 /* Bad blocks_per_group */
171#define PR_0_FIRST_DATA_BLOCK 0x000008 /* Bad first_data_block */
172#define PR_0_ADD_UUID 0x000009 /* Adding UUID to filesystem */
173#define PR_0_RELOCATE_HINT 0x00000A /* Relocate hint */
174#define PR_0_MISC_CORRUPT_SUPER 0x00000B /* Miscellaneous superblock corruption */
175#define PR_0_GETSIZE_ERROR 0x00000C /* Error determing physical device size of filesystem */
176#define PR_0_INODE_COUNT_WRONG 0x00000D /* Inode count in the superblock incorrect */
177#define PR_0_HURD_CLEAR_FILETYPE 0x00000E /* The Hurd does not support the filetype feature */
178#define PR_0_JOURNAL_BAD_INODE 0x00000F /* The Hurd does not support the filetype feature */
179#define PR_0_JOURNAL_UNSUPP_MULTIFS 0x000010 /* The external journal has multiple filesystems (which we can't handle yet) */
180#define PR_0_CANT_FIND_JOURNAL 0x000011 /* Can't find external journal */
181#define PR_0_EXT_JOURNAL_BAD_SUPER 0x000012/* External journal has bad superblock */
182#define PR_0_JOURNAL_BAD_UUID 0x000013 /* Superblock has a bad journal UUID */
183#define PR_0_JOURNAL_UNSUPP_SUPER 0x000014 /* Journal has an unknown superblock type */
184#define PR_0_JOURNAL_BAD_SUPER 0x000015 /* Journal superblock is corrupt */
185#define PR_0_JOURNAL_HAS_JOURNAL 0x000016 /* Journal superblock is corrupt */
186#define PR_0_JOURNAL_RECOVER_SET 0x000017 /* Superblock has recovery flag set but no journal */
187#define PR_0_JOURNAL_RECOVERY_CLEAR 0x000018 /* Journal has data, but recovery flag is clear */
188#define PR_0_JOURNAL_RESET_JOURNAL 0x000019 /* Ask if we should clear the journal */
189#define PR_0_FS_REV_LEVEL 0x00001A /* Filesystem revision is 0, but feature flags are set */
190#define PR_0_ORPHAN_CLEAR_INODE 0x000020 /* Clearing orphan inode */
191#define PR_0_ORPHAN_ILLEGAL_BLOCK_NUM 0x000021 /* Illegal block found in orphaned inode */
192#define PR_0_ORPHAN_ALREADY_CLEARED_BLOCK 0x000022 /* Already cleared block found in orphaned inode */
193#define PR_0_ORPHAN_ILLEGAL_HEAD_INODE 0x000023 /* Illegal orphan inode in superblock */
194#define PR_0_ORPHAN_ILLEGAL_INODE 0x000024 /* Illegal inode in orphaned inode list */
195#define PR_0_JOURNAL_UNSUPP_ROCOMPAT 0x000025 /* Journal has unsupported read-only feature - abort */
196#define PR_0_JOURNAL_UNSUPP_INCOMPAT 0x000026 /* Journal has unsupported incompatible feature - abort */
197#define PR_0_JOURNAL_UNSUPP_VERSION 0x000027 /* Journal has unsupported version number */
198#define PR_0_MOVE_JOURNAL 0x000028 /* Moving journal to hidden file */
199#define PR_0_ERR_MOVE_JOURNAL 0x000029 /* Error moving journal */
200#define PR_0_CLEAR_V2_JOURNAL 0x00002A /* Clearing V2 journal superblock */
201#define PR_0_JOURNAL_RUN 0x00002B /* Run journal anyway */
202#define PR_0_JOURNAL_RUN_DEFAULT 0x00002C /* Run journal anyway by default */
203#define PR_0_BACKUP_JNL 0x00002D /* Backup journal inode blocks */
204#define PR_0_NONZERO_RESERVED_GDT_BLOCKS 0x00002E /* Reserved blocks w/o resize_inode */
205#define PR_0_CLEAR_RESIZE_INODE 0x00002F /* Resize_inode not enabled, but resize inode is non-zero */
206#define PR_0_RESIZE_INODE_INVALID 0x000030 /* Resize inode invalid */
207
208/*
209 * Pass 1 errors
210 */
211
212#define PR_1_PASS_HEADER 0x010000 /* Pass 1: Checking inodes, blocks, and sizes */
213#define PR_1_ROOT_NO_DIR 0x010001 /* Root directory is not an inode */
214#define PR_1_ROOT_DTIME 0x010002 /* Root directory has dtime set */
215#define PR_1_RESERVED_BAD_MODE 0x010003 /* Reserved inode has bad mode */
216#define PR_1_ZERO_DTIME 0x010004 /* Deleted inode has zero dtime */
217#define PR_1_SET_DTIME 0x010005 /* Inode in use, but dtime set */
218#define PR_1_ZERO_LENGTH_DIR 0x010006 /* Zero-length directory */
219#define PR_1_BB_CONFLICT 0x010007 /* Block bitmap conflicts with some other fs block */
220#define PR_1_IB_CONFLICT 0x010008 /* Inode bitmap conflicts with some other fs block */
221#define PR_1_ITABLE_CONFLICT 0x010009 /* Inode table conflicts with some other fs block */
222#define PR_1_BB_BAD_BLOCK 0x01000A /* Block bitmap is on a bad block */
223#define PR_1_IB_BAD_BLOCK 0x01000B /* Inode bitmap is on a bad block */
224#define PR_1_BAD_I_SIZE 0x01000C /* Inode has incorrect i_size */
225#define PR_1_BAD_I_BLOCKS 0x01000D /* Inode has incorrect i_blocks */
226#define PR_1_ILLEGAL_BLOCK_NUM 0x01000E /* Illegal block number in inode */
227#define PR_1_BLOCK_OVERLAPS_METADATA 0x01000F /* Block number overlaps fs metadata */
228#define PR_1_INODE_BLOCK_LATCH 0x010010 /* Inode has illegal blocks (latch question) */
229#define PR_1_TOO_MANY_BAD_BLOCKS 0x010011 /* Too many bad blocks in inode */
230#define PR_1_BB_ILLEGAL_BLOCK_NUM 0x010012 /* Illegal block number in bad block inode */
231#define PR_1_INODE_BBLOCK_LATCH 0x010013 /* Bad block inode has illegal blocks (latch question) */
232#define PR_1_DUP_BLOCKS_PREENSTOP 0x010014 /* Duplicate or bad blocks in use! */
233#define PR_1_BBINODE_BAD_METABLOCK 0x010015 /* Bad block used as bad block indirect block */
234#define PR_1_BBINODE_BAD_METABLOCK_PROMPT 0x010016 /* Inconsistency can't be fixed prompt */
235#define PR_1_BAD_PRIMARY_BLOCK 0x010017 /* Bad primary block */
236#define PR_1_BAD_PRIMARY_BLOCK_PROMPT 0x010018 /* Bad primary block prompt */
237#define PR_1_BAD_PRIMARY_SUPERBLOCK 0x010019 /* Bad primary superblock */
238#define PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR 0x01001A /* Bad primary block group descriptors */
239#define PR_1_BAD_SUPERBLOCK 0x01001B /* Bad superblock in group */
240#define PR_1_BAD_GROUP_DESCRIPTORS 0x01001C /* Bad block group descriptors in group */
241#define PR_1_PROGERR_CLAIMED_BLOCK 0x01001D /* Block claimed for no reason */
242#define PR_1_RELOC_BLOCK_ALLOCATE 0x01001E /* Error allocating blocks for relocating metadata */
243#define PR_1_RELOC_MEMORY_ALLOCATE 0x01001F /* Error allocating block buffer during relocation process */
244#define PR_1_RELOC_FROM_TO 0x010020 /* Relocating metadata group information from X to Y */
245#define PR_1_RELOC_TO 0x010021 /* Relocating metatdata group information to X */
246#define PR_1_RELOC_READ_ERR 0x010022 /* Block read error during relocation process */
247#define PR_1_RELOC_WRITE_ERR 0x010023 /* Block write error during relocation process */
248#define PR_1_ALLOCATE_IBITMAP_ERROR 0x010024 /* Error allocating inode bitmap */
249#define PR_1_ALLOCATE_BBITMAP_ERROR 0x010025 /* Error allocating block bitmap */
250#define PR_1_ALLOCATE_ICOUNT 0x010026 /* Error allocating icount structure */
251#define PR_1_ALLOCATE_DBCOUNT 0x010027 /* Error allocating dbcount */
252#define PR_1_ISCAN_ERROR 0x010028 /* Error while scanning inodes */
253#define PR_1_BLOCK_ITERATE 0x010029 /* Error while iterating over blocks */
254#define PR_1_ICOUNT_STORE 0x01002A /* Error while storing inode count information */
255#define PR_1_ADD_DBLOCK 0x01002B /* Error while storing directory block information */
256#define PR_1_READ_INODE 0x01002C /* Error while reading inode (for clearing) */
257#define PR_1_SUPPRESS_MESSAGES 0x01002D /* Suppress messages prompt */
258#define PR_1_SET_IMAGIC 0x01002F /* Imagic flag set on an inode when filesystem doesn't support it */
259#define PR_1_SET_IMMUTABLE 0x010030 /* Immutable flag set on a device or socket inode */
260#define PR_1_COMPR_SET 0x010031 /* Compression flag set on a non-compressed filesystem */
261#define PR_1_SET_NONZSIZE 0x010032 /* Non-zero size on device, fifo or socket inode */
262#define PR_1_FS_REV_LEVEL 0x010033 /* Filesystem revision is 0, but feature flags are set */
263#define PR_1_JOURNAL_INODE_NOT_CLEAR 0x010034 /* Journal inode not in use, needs clearing */
264#define PR_1_JOURNAL_BAD_MODE 0x010035 /* Journal inode has wrong mode */
265#define PR_1_LOW_DTIME 0x010036 /* Inode that was part of orphan linked list */
266#define PR_1_ORPHAN_LIST_REFUGEES 0x010037 /* Latch question which asks how to deal with low dtime inodes */
267#define PR_1_ALLOCATE_REFCOUNT 0x010038 /* Error allocating refcount structure */
268#define PR_1_READ_EA_BLOCK 0x010039 /* Error reading Extended Attribute block */
269#define PR_1_BAD_EA_BLOCK 0x01003A /* Invalid Extended Attribute block */
270#define PR_1_EXTATTR_READ_ABORT 0x01003B /* Error reading Extended Attribute block while fixing refcount -- abort */
271#define PR_1_EXTATTR_REFCOUNT 0x01003C /* Extended attribute reference count incorrect */
272#define PR_1_EXTATTR_WRITE 0x01003D /* Error writing Extended Attribute block while fixing refcount */
273#define PR_1_EA_MULTI_BLOCK 0x01003E /* Multiple EA blocks not supported */
274#define PR_1_EA_ALLOC_REGION 0x01003F /* Error allocating EA region allocation structure */
275#define PR_1_EA_ALLOC_COLLISION 0x010040 /* Error EA allocation collision */
276#define PR_1_EA_BAD_NAME 0x010041 /* Bad extended attribute name */
277#define PR_1_EA_BAD_VALUE 0x010042 /* Bad extended attribute value */
278#define PR_1_INODE_TOOBIG 0x010043 /* Inode too big (latch question) */
279#define PR_1_TOOBIG_DIR 0x010044 /* Directory too big */
280#define PR_1_TOOBIG_REG 0x010045 /* Regular file too big */
281#define PR_1_TOOBIG_SYMLINK 0x010046 /* Symlink too big */
282#define PR_1_HTREE_SET 0x010047 /* INDEX_FL flag set on a non-HTREE filesystem */
283#define PR_1_HTREE_NODIR 0x010048 /* INDEX_FL flag set on a non-directory */
284#define PR_1_HTREE_BADROOT 0x010049 /* Invalid root node in HTREE directory */
285#define PR_1_HTREE_HASHV 0x01004A /* Unsupported hash version in HTREE directory */
286#define PR_1_HTREE_INCOMPAT 0x01004B /* Incompatible flag in HTREE root node */
287#define PR_1_HTREE_DEPTH 0x01004C /* HTREE too deep */
288#define PR_1_BB_FS_BLOCK 0x01004D /* Bad block has indirect block that conflicts with filesystem block */
289#define PR_1_RESIZE_INODE_CREATE 0x01004E /* Resize inode failed */
290#define PR_1_EXTRA_ISIZE 0x01004F /* inode->i_size is too long */
291#define PR_1_ATTR_NAME_LEN 0x010050 /* attribute name is too long */
292#define PR_1_ATTR_VALUE_OFFSET 0x010051 /* wrong EA value offset */
293#define PR_1_ATTR_VALUE_BLOCK 0x010052 /* wrong EA blocknumber */
294#define PR_1_ATTR_VALUE_SIZE 0x010053 /* wrong EA value size */
295#define PR_1_ATTR_HASH 0x010054 /* wrong EA hash value */
296
297/*
298 * Pass 1b errors
299 */
300
301#define PR_1B_PASS_HEADER 0x011000 /* Pass 1B: Rescan for duplicate/bad blocks */
302#define PR_1B_DUP_BLOCK_HEADER 0x011001 /* Duplicate/bad block(s) header */
303#define PR_1B_DUP_BLOCK 0x011002 /* Duplicate/bad block(s) in inode */
304#define PR_1B_DUP_BLOCK_END 0x011003 /* Duplicate/bad block(s) end */
305#define PR_1B_ISCAN_ERROR 0x011004 /* Error while scanning inodes */
306#define PR_1B_ALLOCATE_IBITMAP_ERROR 0x011005 /* Error allocating inode bitmap */
307#define PR_1B_BLOCK_ITERATE 0x0110006 /* Error while iterating over blocks */
308#define PR_1B_ADJ_EA_REFCOUNT 0x0110007 /* Error adjusting EA refcount */
309#define PR_1C_PASS_HEADER 0x012000 /* Pass 1C: Scan directories for inodes with dup blocks. */
310#define PR_1D_PASS_HEADER 0x013000 /* Pass 1D: Reconciling duplicate blocks */
311#define PR_1D_DUP_FILE 0x013001 /* File has duplicate blocks */
312#define PR_1D_DUP_FILE_LIST 0x013002 /* List of files sharing duplicate blocks */
313#define PR_1D_SHARE_METADATA 0x013003 /* File sharing blocks with filesystem metadata */
314#define PR_1D_NUM_DUP_INODES 0x013004 /* Report of how many duplicate/bad inodes */
315#define PR_1D_DUP_BLOCKS_DEALT 0x013005 /* Duplicated blocks already reassigned or cloned. */
316#define PR_1D_CLONE_QUESTION 0x013006 /* Clone duplicate/bad blocks? */
317#define PR_1D_DELETE_QUESTION 0x013007 /* Delete file? */
318#define PR_1D_CLONE_ERROR 0x013008 /* Couldn't clone file (error) */
319
320/*
321 * Pass 2 errors
322 */
323
324#define PR_2_PASS_HEADER 0x020000 /* Pass 2: Checking directory structure */
325#define PR_2_BAD_INODE_DOT 0x020001 /* Bad inode number for '.' */
326#define PR_2_BAD_INO 0x020002 /* Directory entry has bad inode number */
327#define PR_2_UNUSED_INODE 0x020003 /* Directory entry has deleted or unused inode */
328#define PR_2_LINK_DOT 0x020004 /* Directry entry is link to '.' */
329#define PR_2_BB_INODE 0x020005 /* Directory entry points to inode now located in a bad block */
330#define PR_2_LINK_DIR 0x020006 /* Directory entry contains a link to a directory */
331#define PR_2_LINK_ROOT 0x020007 /* Directory entry contains a link to the root directry */
332#define PR_2_BAD_NAME 0x020008 /* Directory entry has illegal characters in its name */
333#define PR_2_MISSING_DOT 0x020009 /* Missing '.' in directory inode */
334#define PR_2_MISSING_DOT_DOT 0x02000A /* Missing '..' in directory inode */
335#define PR_2_1ST_NOT_DOT 0x02000B /* First entry in directory inode doesn't contain '.' */
336#define PR_2_2ND_NOT_DOT_DOT 0x02000C /* Second entry in directory inode doesn't contain '..' */
337#define PR_2_FADDR_ZERO 0x02000D /* i_faddr should be zero */
338#define PR_2_FILE_ACL_ZERO 0x02000E /* i_file_acl should be zero */
339#define PR_2_DIR_ACL_ZERO 0x02000F /* i_dir_acl should be zero */
340#define PR_2_FRAG_ZERO 0x020010 /* i_frag should be zero */
341#define PR_2_FSIZE_ZERO 0x020011 /* i_fsize should be zero */
342#define PR_2_BAD_MODE 0x020012 /* inode has bad mode */
343#define PR_2_DIR_CORRUPTED 0x020013 /* directory corrupted */
344#define PR_2_FILENAME_LONG 0x020014 /* filename too long */
345#define PR_2_DIRECTORY_HOLE 0x020015 /* Directory inode has a missing block (hole) */
346#define PR_2_DOT_NULL_TERM 0x020016 /* '.' is not NULL terminated */
347#define PR_2_DOT_DOT_NULL_TERM 0x020017 /* '..' is not NULL terminated */
348#define PR_2_BAD_CHAR_DEV 0x020018 /* Illegal character device in inode */
349#define PR_2_BAD_BLOCK_DEV 0x020019 /* Illegal block device in inode */
350#define PR_2_DUP_DOT 0x02001A /* Duplicate '.' entry */
351#define PR_2_DUP_DOT_DOT 0x02001B /* Duplicate '..' entry */
352#define PR_2_NO_DIRINFO 0x02001C /* Internal error: couldn't find dir_info */
353#define PR_2_FINAL_RECLEN 0x02001D /* Final rec_len is wrong */
354#define PR_2_ALLOCATE_ICOUNT 0x02001E /* Error allocating icount structure */
355#define PR_2_DBLIST_ITERATE 0x02001F /* Error iterating over directory blocks */
356#define PR_2_READ_DIRBLOCK 0x020020 /* Error reading directory block */
357#define PR_2_WRITE_DIRBLOCK 0x020021 /* Error writing directory block */
358#define PR_2_ALLOC_DIRBOCK 0x020022 /* Error allocating new directory block */
359#define PR_2_DEALLOC_INODE 0x020023 /* Error deallocating inode */
360#define PR_2_SPLIT_DOT 0x020024 /* Directory entry for '.' is big. Split? */
361#define PR_2_BAD_FIFO 0x020025 /* Illegal FIFO */
362#define PR_2_BAD_SOCKET 0x020026 /* Illegal socket */
363#define PR_2_SET_FILETYPE 0x020027 /* Directory filetype not set */
364#define PR_2_BAD_FILETYPE 0x020028 /* Directory filetype incorrect */
365#define PR_2_CLEAR_FILETYPE 0x020029 /* Directory filetype set when it shouldn't be */
366#define PR_2_NULL_NAME 0x020030 /* Directory filename can't be zero-length */
367#define PR_2_INVALID_SYMLINK 0x020031 /* Invalid symlink */
368#define PR_2_FILE_ACL_BAD 0x020032 /* i_file_acl (extended attribute) is bad */
369#define PR_2_FEATURE_LARGE_FILES 0x020033 /* Filesystem contains large files, but has no such flag in sb */
370#define PR_2_HTREE_NOTREF 0x020034 /* Node in HTREE directory not referenced */
371#define PR_2_HTREE_DUPREF 0x020035 /* Node in HTREE directory referenced twice */
372#define PR_2_HTREE_MIN_HASH 0x020036 /* Node in HTREE directory has bad min hash */
373#define PR_2_HTREE_MAX_HASH 0x020037 /* Node in HTREE directory has bad max hash */
374#define PR_2_HTREE_CLEAR 0x020038 /* Clear invalid HTREE directory */
375#define PR_2_HTREE_BADBLK 0x02003A /* Bad block in htree interior node */
376#define PR_2_ADJ_EA_REFCOUNT 0x02003B /* Error adjusting EA refcount */
377#define PR_2_HTREE_BAD_ROOT 0x02003C /* Invalid HTREE root node */
378#define PR_2_HTREE_BAD_LIMIT 0x02003D /* Invalid HTREE limit */
379#define PR_2_HTREE_BAD_COUNT 0x02003E /* Invalid HTREE count */
380#define PR_2_HTREE_HASH_ORDER 0x02003F /* HTREE interior node has out-of-order hashes in table */
381#define PR_2_HTREE_BAD_DEPTH 0x020040 /* Node in HTREE directory has bad depth */
382#define PR_2_DUPLICATE_DIRENT 0x020041 /* Duplicate directory entry found */
383#define PR_2_NON_UNIQUE_FILE 0x020042 /* Non-unique filename found */
384#define PR_2_REPORT_DUP_DIRENT 0x020043 /* Duplicate directory entry found */
385
386/*
387 * Pass 3 errors
388 */
389
390#define PR_3_PASS_HEADER 0x030000 /* Pass 3: Checking directory connectivity */
391#define PR_3_NO_ROOT_INODE 0x030001 /* Root inode not allocated */
392#define PR_3_EXPAND_LF_DIR 0x030002 /* No room in lost+found */
393#define PR_3_UNCONNECTED_DIR 0x030003 /* Unconnected directory inode */
394#define PR_3_NO_LF_DIR 0x030004 /* /lost+found not found */
395#define PR_3_BAD_DOT_DOT 0x030005 /* .. entry is incorrect */
396#define PR_3_NO_LPF 0x030006 /* Bad or non-existent /lost+found. Cannot reconnect */
397#define PR_3_CANT_EXPAND_LPF 0x030007 /* Could not expand /lost+found */
398#define PR_3_CANT_RECONNECT 0x030008 /* Could not reconnect inode */
399#define PR_3_ERR_FIND_LPF 0x030009 /* Error while trying to find /lost+found */
400#define PR_3_ERR_LPF_NEW_BLOCK 0x03000A /* Error in ext2fs_new_block while creating /lost+found */
401#define PR_3_ERR_LPF_NEW_INODE 0x03000B /* Error in ext2fs_new_inode while creating /lost+found */
402#define PR_3_ERR_LPF_NEW_DIR_BLOCK 0x03000C /* Error in ext2fs_new_dir_block while creating /lost+found */
403#define PR_3_ERR_LPF_WRITE_BLOCK 0x03000D /* Error while writing directory block for /lost+found */
404#define PR_3_ADJUST_INODE 0x03000E /* Error while adjusting inode count */
405#define PR_3_FIX_PARENT_ERR 0x03000F /* Couldn't fix parent directory -- error */
406#define PR_3_FIX_PARENT_NOFIND 0x030010 /* Couldn't fix parent directory -- couldn't find it */
407#define PR_3_ALLOCATE_IBITMAP_ERROR 0x030011 /* Error allocating inode bitmap */
408#define PR_3_CREATE_ROOT_ERROR 0x030012 /* Error creating root directory */
409#define PR_3_CREATE_LPF_ERROR 0x030013 /* Error creating lost and found directory */
410#define PR_3_ROOT_NOT_DIR_ABORT 0x030014 /* Root inode is not directory; aborting */
411#define PR_3_NO_ROOT_INODE_ABORT 0x030015 /* Cannot proceed without a root inode. */
412#define PR_3_NO_DIRINFO 0x030016 /* Internal error: couldn't find dir_info */
413#define PR_3_LPF_NOTDIR 0x030017 /* Lost+found is not a directory */
414
415/*
416 * Pass 3a --- rehashing diretories
417 */
418#define PR_3A_PASS_HEADER 0x031000 /* Pass 3a: Reindexing directories */
419#define PR_3A_OPTIMIZE_ITER 0x031001 /* Error iterating over directories */
420#define PR_3A_OPTIMIZE_DIR_ERR 0x031002 /* Error rehash directory */
421#define PR_3A_OPTIMIZE_DIR_HEADER 0x031003 /* Rehashing dir header */
422#define PR_3A_OPTIMIZE_DIR 0x031004 /* Rehashing directory %d */
423#define PR_3A_OPTIMIZE_DIR_END 0x031005 /* Rehashing dir end */
424
425/*
426 * Pass 4 errors
427 */
428
429#define PR_4_PASS_HEADER 0x040000 /* Pass 4: Checking reference counts */
430#define PR_4_ZERO_LEN_INODE 0x040001 /* Unattached zero-length inode */
431#define PR_4_UNATTACHED_INODE 0x040002 /* Unattached inode */
432#define PR_4_BAD_REF_COUNT 0x040003 /* Inode ref count wrong */
433#define PR_4_INCONSISTENT_COUNT 0x040004 /* Inconsistent inode count information cached */
434
435/*
436 * Pass 5 errors
437 */
438
439#define PR_5_PASS_HEADER 0x050000 /* Pass 5: Checking group summary information */
440#define PR_5_INODE_BMAP_PADDING 0x050001 /* Padding at end of inode bitmap is not set. */
441#define PR_5_BLOCK_BMAP_PADDING 0x050002 /* Padding at end of block bitmap is not set. */
442#define PR_5_BLOCK_BITMAP_HEADER 0x050003 /* Block bitmap differences header */
443#define PR_5_BLOCK_UNUSED 0x050004 /* Block not used, but marked in bitmap */
444#define PR_5_BLOCK_USED 0x050005 /* Block used, but not marked used in bitmap */
445#define PR_5_BLOCK_BITMAP_END 0x050006 /* Block bitmap differences end */
446#define PR_5_INODE_BITMAP_HEADER 0x050007 /* Inode bitmap differences header */
447#define PR_5_INODE_UNUSED 0x050008 /* Inode not used, but marked in bitmap */
448#define PR_5_INODE_USED 0x050009 /* Inode used, but not marked used in bitmap */
449#define PR_5_INODE_BITMAP_END 0x05000A /* Inode bitmap differences end */
450#define PR_5_FREE_INODE_COUNT_GROUP 0x05000B /* Free inodes count for group wrong */
451#define PR_5_FREE_DIR_COUNT_GROUP 0x05000C /* Directories count for group wrong */
452#define PR_5_FREE_INODE_COUNT 0x05000D /* Free inodes count wrong */
453#define PR_5_FREE_BLOCK_COUNT_GROUP 0x05000E /* Free blocks count for group wrong */
454#define PR_5_FREE_BLOCK_COUNT 0x05000F /* Free blocks count wrong */
455#define PR_5_BMAP_ENDPOINTS 0x050010 /* Programming error: bitmap endpoints don't match */
456#define PR_5_FUDGE_BITMAP_ERROR 0x050011 /* Internal error: fudging end of bitmap */
457#define PR_5_COPY_IBITMAP_ERROR 0x050012 /* Error copying in replacement inode bitmap */
458#define PR_5_COPY_BBITMAP_ERROR 0x050013 /* Error copying in replacement block bitmap */
459#define PR_5_BLOCK_RANGE_UNUSED 0x050014 /* Block range not used, but marked in bitmap */
460#define PR_5_BLOCK_RANGE_USED 0x050015 /* Block range used, but not marked used in bitmap */
461#define PR_5_INODE_RANGE_UNUSED 0x050016 /* Inode range not used, but marked in bitmap */
462#define PR_5_INODE_RANGE_USED 0x050017 /* Inode rangeused, but not marked used in bitmap */
463
464
465/*
466 * The directory information structure; stores directory information
467 * collected in earlier passes, to avoid disk i/o in fetching the
468 * directory information.
469 */
470struct dir_info {
471 ext2_ino_t ino; /* Inode number */
472 ext2_ino_t dotdot; /* Parent according to '..' */
473 ext2_ino_t parent; /* Parent according to treewalk */
474};
475
476
477
478/*
479 * The indexed directory information structure; stores information for
480 * directories which contain a hash tree index.
481 */
482struct dx_dir_info {
483 ext2_ino_t ino; /* Inode number */
484 int numblocks; /* number of blocks */
485 int hashversion;
486 short depth; /* depth of tree */
487 struct dx_dirblock_info *dx_block; /* Array of size numblocks */
488};
489
490/*
491 * Define the extended attribute refcount structure
492 */
493typedef struct ea_refcount *ext2_refcount_t;
494
495struct e2fsck_struct {
496 ext2_filsys fs;
497 const char *program_name;
498 char *filesystem_name;
499 char *device_name;
500 char *io_options;
501 int flags; /* E2fsck internal flags */
502 int options;
503 blk_t use_superblock; /* sb requested by user */
504 blk_t superblock; /* sb used to open fs */
505 int blocksize; /* blocksize */
506 blk_t num_blocks; /* Total number of blocks */
507 int mount_flags;
508 blkid_cache blkid; /* blkid cache */
509
510 jmp_buf abort_loc;
511
512 unsigned long abort_code;
513
514 int (*progress)(e2fsck_t ctx, int pass, unsigned long cur,
515 unsigned long max);
516
517 ext2fs_inode_bitmap inode_used_map; /* Inodes which are in use */
518 ext2fs_inode_bitmap inode_bad_map; /* Inodes which are bad somehow */
519 ext2fs_inode_bitmap inode_dir_map; /* Inodes which are directories */
520 ext2fs_inode_bitmap inode_imagic_map; /* AFS inodes */
521 ext2fs_inode_bitmap inode_reg_map; /* Inodes which are regular files*/
522
523 ext2fs_block_bitmap block_found_map; /* Blocks which are in use */
524 ext2fs_block_bitmap block_dup_map; /* Blks referenced more than once */
525 ext2fs_block_bitmap block_ea_map; /* Blocks which are used by EA's */
526
527 /*
528 * Inode count arrays
529 */
530 ext2_icount_t inode_count;
531 ext2_icount_t inode_link_info;
532
533 ext2_refcount_t refcount;
534 ext2_refcount_t refcount_extra;
535
536 /*
537 * Array of flags indicating whether an inode bitmap, block
538 * bitmap, or inode table is invalid
539 */
540 int *invalid_inode_bitmap_flag;
541 int *invalid_block_bitmap_flag;
542 int *invalid_inode_table_flag;
543 int invalid_bitmaps; /* There are invalid bitmaps/itable */
544
545 /*
546 * Block buffer
547 */
548 char *block_buf;
549
550 /*
551 * For pass1_check_directory and pass1_get_blocks
552 */
553 ext2_ino_t stashed_ino;
554 struct ext2_inode *stashed_inode;
555
556 /*
557 * Location of the lost and found directory
558 */
559 ext2_ino_t lost_and_found;
560 int bad_lost_and_found;
561
562 /*
563 * Directory information
564 */
565 int dir_info_count;
566 int dir_info_size;
567 struct dir_info *dir_info;
568
569 /*
570 * Indexed directory information
571 */
572 int dx_dir_info_count;
573 int dx_dir_info_size;
574 struct dx_dir_info *dx_dir_info;
575
576 /*
577 * Directories to hash
578 */
579 ext2_u32_list dirs_to_hash;
580
581 /*
582 * Tuning parameters
583 */
584 int process_inode_size;
585 int inode_buffer_blocks;
586
587 /*
588 * ext3 journal support
589 */
590 io_channel journal_io;
591 char *journal_name;
592
593 /*
594 * How we display the progress update (for unix)
595 */
596 int progress_fd;
597 int progress_pos;
598 int progress_last_percent;
599 unsigned int progress_last_time;
600 int interactive; /* Are we connected directly to a tty? */
601 char start_meta[2], stop_meta[2];
602
603 /* File counts */
604 int fs_directory_count;
605 int fs_regular_count;
606 int fs_blockdev_count;
607 int fs_chardev_count;
608 int fs_links_count;
609 int fs_symlinks_count;
610 int fs_fast_symlinks_count;
611 int fs_fifo_count;
612 int fs_total_count;
613 int fs_sockets_count;
614 int fs_ind_count;
615 int fs_dind_count;
616 int fs_tind_count;
617 int fs_fragmented;
618 int large_files;
619 int fs_ext_attr_inodes;
620 int fs_ext_attr_blocks;
621
622 int ext_attr_ver;
623
624 /*
625 * For the use of callers of the e2fsck functions; not used by
626 * e2fsck functions themselves.
627 */
628 void *priv_data;
629};
630
631
632#define tid_gt(x, y) ((x - y) > 0)
633
634static inline int tid_geq(tid_t x, tid_t y)
635{
636 int difference = (x - y);
637 return (difference >= 0);
638}
diff --git a/e2fsprogs/old_e2fsprogs/e2p/Kbuild.src b/e2fsprogs/old_e2fsprogs/e2p/Kbuild.src
deleted file mode 100644
index 482630cc2..000000000
--- a/e2fsprogs/old_e2fsprogs/e2p/Kbuild.src
+++ /dev/null
@@ -1,18 +0,0 @@
1# Makefile for busybox
2#
3# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
4#
5# Licensed under GPLv2, see file LICENSE in this source tree.
6
7NEEDED-$(CONFIG_CHATTR) = y
8NEEDED-$(CONFIG_LSATTR) = y
9NEEDED-$(CONFIG_MKE2FS) = y
10NEEDED-$(CONFIG_TUNE2FS) = y
11
12lib-y:=
13
14INSERT
15
16lib-$(NEEDED-y) += fgetsetflags.o fgetsetversion.o pf.o iod.o mntopts.o \
17 feature.o ls.o uuid.o pe.o ostype.o ps.o hashstr.o \
18 parse_num.o
diff --git a/e2fsprogs/old_e2fsprogs/e2p/e2p.h b/e2fsprogs/old_e2fsprogs/e2p/e2p.h
deleted file mode 100644
index bad2d6ac9..000000000
--- a/e2fsprogs/old_e2fsprogs/e2p/e2p.h
+++ /dev/null
@@ -1,64 +0,0 @@
1/* vi: set sw=4 ts=4: */
2#include "libbb.h"
3#include <sys/types.h> /* Needed by dirent.h on netbsd */
4#include <stdio.h>
5#include <dirent.h>
6
7#include "../ext2fs/ext2_fs.h"
8
9#define E2P_FEATURE_COMPAT 0
10#define E2P_FEATURE_INCOMPAT 1
11#define E2P_FEATURE_RO_INCOMPAT 2
12#ifndef EXT3_FEATURE_INCOMPAT_EXTENTS
13#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040
14#endif
15
16/* `options' for print_e2flags() */
17
18#define PFOPT_LONG 1 /* Must be 1 for compatibility with `int long_format'. */
19
20/*int fgetversion (const char * name, unsigned long * version);*/
21/*int fsetversion (const char * name, unsigned long version);*/
22int fgetsetversion(const char * name, unsigned long * get_version, unsigned long set_version);
23#define fgetversion(name, version) fgetsetversion(name, version, 0)
24#define fsetversion(name, version) fgetsetversion(name, NULL, version)
25
26/*int fgetflags (const char * name, unsigned long * flags);*/
27/*int fsetflags (const char * name, unsigned long flags);*/
28int fgetsetflags(const char * name, unsigned long * get_flags, unsigned long set_flags);
29#define fgetflags(name, flags) fgetsetflags(name, flags, 0)
30#define fsetflags(name, flags) fgetsetflags(name, NULL, flags)
31
32int getflags (int fd, unsigned long * flags);
33int getversion (int fd, unsigned long * version);
34int iterate_on_dir (const char * dir_name,
35 int (*func) (const char *, struct dirent *, void *),
36 void * private);
37/*void list_super(struct ext2_super_block * s);*/
38void list_super2(struct ext2_super_block * s, FILE *f);
39#define list_super(s) list_super2(s, stdout)
40void print_fs_errors (FILE *f, unsigned short errors);
41void print_flags (FILE *f, unsigned long flags, unsigned options);
42void print_fs_state (FILE *f, unsigned short state);
43int setflags (int fd, unsigned long flags);
44int setversion (int fd, unsigned long version);
45
46const char *e2p_feature2string(int compat, unsigned int mask);
47int e2p_string2feature(char *string, int *compat, unsigned int *mask);
48int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array);
49
50int e2p_is_null_uuid(void *uu);
51void e2p_uuid_to_str(void *uu, char *out);
52const char *e2p_uuid2str(void *uu);
53
54const char *e2p_hash2string(int num);
55int e2p_string2hash(char *string);
56
57const char *e2p_mntopt2string(unsigned int mask);
58int e2p_string2mntopt(char *string, unsigned int *mask);
59int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok);
60
61unsigned long parse_num_blocks(const char *arg, int log_block_size);
62
63char *e2p_os2string(int os_type);
64int e2p_string2os(char *str);
diff --git a/e2fsprogs/old_e2fsprogs/e2p/feature.c b/e2fsprogs/old_e2fsprogs/e2p/feature.c
deleted file mode 100644
index 2102ed8e7..000000000
--- a/e2fsprogs/old_e2fsprogs/e2p/feature.c
+++ /dev/null
@@ -1,187 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * feature.c --- convert between features and strings
4 *
5 * Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu>
6 *
7 * This file can be redistributed under the terms of the GNU Library General
8 * Public License
9 *
10 */
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <ctype.h>
16#include <errno.h>
17
18#include "e2p.h"
19
20struct feature {
21 int compat;
22 unsigned int mask;
23 const char *string;
24};
25
26static const struct feature feature_list[] = {
27 { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_PREALLOC,
28 "dir_prealloc" },
29 { E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL,
30 "has_journal" },
31 { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_IMAGIC_INODES,
32 "imagic_inodes" },
33 { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_EXT_ATTR,
34 "ext_attr" },
35 { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX,
36 "dir_index" },
37 { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_RESIZE_INO,
38 "resize_inode" },
39 { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER,
40 "sparse_super" },
41 { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_LARGE_FILE,
42 "large_file" },
43 { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_COMPRESSION,
44 "compression" },
45 { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_FILETYPE,
46 "filetype" },
47 { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_RECOVER,
48 "needs_recovery" },
49 { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV,
50 "journal_dev" },
51 { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS,
52 "extents" },
53 { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_META_BG,
54 "meta_bg" },
55 { 0, 0, 0 },
56};
57
58const char *e2p_feature2string(int compat, unsigned int mask)
59{
60 const struct feature *f;
61 static char buf[20];
62 char fchar;
63 int fnum;
64
65 for (f = feature_list; f->string; f++) {
66 if ((compat == f->compat) &&
67 (mask == f->mask))
68 return f->string;
69 }
70 switch (compat) {
71 case E2P_FEATURE_COMPAT:
72 fchar = 'C';
73 break;
74 case E2P_FEATURE_INCOMPAT:
75 fchar = 'I';
76 break;
77 case E2P_FEATURE_RO_INCOMPAT:
78 fchar = 'R';
79 break;
80 default:
81 fchar = '?';
82 break;
83 }
84 for (fnum = 0; mask >>= 1; fnum++);
85 sprintf(buf, "FEATURE_%c%d", fchar, fnum);
86 return buf;
87}
88
89int e2p_string2feature(char *string, int *compat_type, unsigned int *mask)
90{
91 const struct feature *f;
92 char *eptr;
93 int num;
94
95 for (f = feature_list; f->string; f++) {
96 if (!strcasecmp(string, f->string)) {
97 *compat_type = f->compat;
98 *mask = f->mask;
99 return 0;
100 }
101 }
102 if (strncasecmp(string, "FEATURE_", 8))
103 return 1;
104
105 switch (string[8]) {
106 case 'c':
107 case 'C':
108 *compat_type = E2P_FEATURE_COMPAT;
109 break;
110 case 'i':
111 case 'I':
112 *compat_type = E2P_FEATURE_INCOMPAT;
113 break;
114 case 'r':
115 case 'R':
116 *compat_type = E2P_FEATURE_RO_INCOMPAT;
117 break;
118 default:
119 return 1;
120 }
121 if (string[9] == 0)
122 return 1;
123 num = strtol(string+9, &eptr, 10);
124 if (num > 32 || num < 0)
125 return 1;
126 if (*eptr)
127 return 1;
128 *mask = 1 << num;
129 return 0;
130}
131
132static inline char *skip_over_blanks(char *cp)
133{
134 while (*cp && isspace(*cp))
135 cp++;
136 return cp;
137}
138
139static inline char *skip_over_word(char *cp)
140{
141 while (*cp && !isspace(*cp) && *cp != ',')
142 cp++;
143 return cp;
144}
145
146/*
147 * Edit a feature set array as requested by the user. The ok_array,
148 * if set, allows the application to limit what features the user is
149 * allowed to set or clear using this function.
150 */
151int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array)
152{
153 char *cp, *buf, *next;
154 int neg;
155 unsigned int mask;
156 int compat_type;
157
158 buf = xstrdup(str);
159 cp = buf;
160 while (cp && *cp) {
161 neg = 0;
162 cp = skip_over_blanks(cp);
163 next = skip_over_word(cp);
164 if (*next == 0)
165 next = 0;
166 else
167 *next = 0;
168 switch (*cp) {
169 case '-':
170 case '^':
171 neg++;
172 case '+':
173 cp++;
174 break;
175 }
176 if (e2p_string2feature(cp, &compat_type, &mask))
177 return 1;
178 if (ok_array && !(ok_array[compat_type] & mask))
179 return 1;
180 if (neg)
181 compat_array[compat_type] &= ~mask;
182 else
183 compat_array[compat_type] |= mask;
184 cp = next ? next+1 : 0;
185 }
186 return 0;
187}
diff --git a/e2fsprogs/old_e2fsprogs/e2p/fgetsetflags.c b/e2fsprogs/old_e2fsprogs/e2p/fgetsetflags.c
deleted file mode 100644
index 008b79850..000000000
--- a/e2fsprogs/old_e2fsprogs/e2p/fgetsetflags.c
+++ /dev/null
@@ -1,70 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * fgetflags.c - Get a file flags on an ext2 file system
4 * fsetflags.c - Set a file flags on an ext2 file system
5 *
6 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
7 * Laboratoire MASI, Institut Blaise Pascal
8 * Universite Pierre et Marie Curie (Paris VI)
9 *
10 * This file can be redistributed under the terms of the GNU Library General
11 * Public License
12 */
13
14/*
15 * History:
16 * 93/10/30 - Creation
17 */
18
19#ifdef HAVE_ERRNO_H
20#include <errno.h>
21#endif
22#ifdef HAVE_UNISTD_H
23#include <unistd.h>
24#endif
25#include <sys/types.h>
26#include <sys/stat.h>
27#ifdef HAVE_EXT2_IOCTLS
28#include <fcntl.h>
29#include <sys/ioctl.h>
30#endif
31
32#include "e2p.h"
33
34#ifdef O_LARGEFILE
35#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
36#else
37#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
38#endif
39
40int fgetsetflags (const char * name, unsigned long * get_flags, unsigned long set_flags)
41{
42#ifdef HAVE_EXT2_IOCTLS
43 struct stat buf;
44 int fd, r, f, save_errno = 0;
45
46 if (!stat(name, &buf) &&
47 !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) {
48 goto notsupp;
49 }
50 fd = open (name, OPEN_FLAGS);
51 if (fd == -1)
52 return -1;
53 if (!get_flags) {
54 f = (int) set_flags;
55 r = ioctl (fd, EXT2_IOC_SETFLAGS, &f);
56 } else {
57 r = ioctl (fd, EXT2_IOC_GETFLAGS, &f);
58 *get_flags = f;
59 }
60 if (r == -1)
61 save_errno = errno;
62 close (fd);
63 if (save_errno)
64 errno = save_errno;
65 return r;
66notsupp:
67#endif /* HAVE_EXT2_IOCTLS */
68 errno = EOPNOTSUPP;
69 return -1;
70}
diff --git a/e2fsprogs/old_e2fsprogs/e2p/fgetsetversion.c b/e2fsprogs/old_e2fsprogs/e2p/fgetsetversion.c
deleted file mode 100644
index 8d79054d6..000000000
--- a/e2fsprogs/old_e2fsprogs/e2p/fgetsetversion.c
+++ /dev/null
@@ -1,70 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * fgetversion.c - Get a file version on an ext2 file system
4 * fsetversion.c - Set a file version on an ext2 file system
5 *
6 *
7 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
8 * Laboratoire MASI, Institut Blaise Pascal
9 * Universite Pierre et Marie Curie (Paris VI)
10 *
11 * This file can be redistributed under the terms of the GNU Library General
12 * Public License
13 */
14
15/*
16 * History:
17 * 93/10/30 - Creation
18 */
19
20#ifdef HAVE_ERRNO_H
21#include <errno.h>
22#endif
23#ifdef HAVE_UNISTD_H
24#include <unistd.h>
25#endif
26#include <fcntl.h>
27#include <sys/ioctl.h>
28
29#include "e2p.h"
30
31#ifdef O_LARGEFILE
32#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
33#else
34#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
35#endif
36
37/*
38 To do fsetversion: unsigned long *ptr_version must be set to NULL.
39 and unsigned long version must be set to a value
40 To do fgetversion: unsigned long *ptr_version must NOT be set to NULL
41 and unsigned long version is ignored.
42 TITO.
43*/
44
45int fgetsetversion (const char * name, unsigned long * get_version, unsigned long set_version)
46{
47#ifdef HAVE_EXT2_IOCTLS
48 int fd, r, ver, save_errno = 0;
49
50 fd = open (name, OPEN_FLAGS);
51 if (fd == -1)
52 return -1;
53 if (!get_version) {
54 ver = (int) set_version;
55 r = ioctl (fd, EXT2_IOC_SETVERSION, &ver);
56 } else {
57 r = ioctl (fd, EXT2_IOC_GETVERSION, &ver);
58 *get_version = ver;
59 }
60 if (r == -1)
61 save_errno = errno;
62 close (fd);
63 if (save_errno)
64 errno = save_errno;
65 return r;
66#else /* ! HAVE_EXT2_IOCTLS */
67 errno = EOPNOTSUPP;
68 return -1;
69#endif /* ! HAVE_EXT2_IOCTLS */
70}
diff --git a/e2fsprogs/old_e2fsprogs/e2p/hashstr.c b/e2fsprogs/old_e2fsprogs/e2p/hashstr.c
deleted file mode 100644
index 697ffadc3..000000000
--- a/e2fsprogs/old_e2fsprogs/e2p/hashstr.c
+++ /dev/null
@@ -1,70 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * feature.c --- convert between features and strings
4 *
5 * Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu>
6 *
7 * This file can be redistributed under the terms of the GNU Library General
8 * Public License
9 *
10 */
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <ctype.h>
16#include <errno.h>
17
18#include "e2p.h"
19
20struct hash {
21 int num;
22 const char *string;
23};
24
25static const struct hash hash_list[] = {
26 { EXT2_HASH_LEGACY, "legacy" },
27 { EXT2_HASH_HALF_MD4, "half_md4" },
28 { EXT2_HASH_TEA, "tea" },
29 { 0, 0 },
30};
31
32const char *e2p_hash2string(int num)
33{
34 const struct hash *p;
35 static char buf[20];
36
37 for (p = hash_list; p->string; p++) {
38 if (num == p->num)
39 return p->string;
40 }
41 sprintf(buf, "HASHALG_%d", num);
42 return buf;
43}
44
45/*
46 * Returns the hash algorithm, or -1 on error
47 */
48int e2p_string2hash(char *string)
49{
50 const struct hash *p;
51 char *eptr;
52 int num;
53
54 for (p = hash_list; p->string; p++) {
55 if (!strcasecmp(string, p->string)) {
56 return p->num;
57 }
58 }
59 if (strncasecmp(string, "HASHALG_", 8))
60 return -1;
61
62 if (string[8] == 0)
63 return -1;
64 num = strtol(string+8, &eptr, 10);
65 if (num > 255 || num < 0)
66 return -1;
67 if (*eptr)
68 return -1;
69 return num;
70}
diff --git a/e2fsprogs/old_e2fsprogs/e2p/iod.c b/e2fsprogs/old_e2fsprogs/e2p/iod.c
deleted file mode 100644
index 23ab8d5b5..000000000
--- a/e2fsprogs/old_e2fsprogs/e2p/iod.c
+++ /dev/null
@@ -1,52 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * iod.c - Iterate a function on each entry of a directory
4 *
5 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
6 * Laboratoire MASI, Institut Blaise Pascal
7 * Universite Pierre et Marie Curie (Paris VI)
8 *
9 * This file can be redistributed under the terms of the GNU Library General
10 * Public License
11 */
12
13/*
14 * History:
15 * 93/10/30 - Creation
16 */
17
18#include "e2p.h"
19#include <unistd.h>
20#include <stdlib.h>
21#include <string.h>
22
23int iterate_on_dir (const char * dir_name,
24 int (*func) (const char *, struct dirent *, void *),
25 void * private)
26{
27 DIR * dir;
28 struct dirent *de, *dep;
29 int max_len, len;
30
31 max_len = PATH_MAX + sizeof(struct dirent);
32 de = xmalloc(max_len+1);
33 memset(de, 0, max_len+1);
34
35 dir = opendir (dir_name);
36 if (dir == NULL) {
37 free(de);
38 return -1;
39 }
40 while ((dep = readdir (dir))) {
41 len = sizeof(struct dirent);
42 if (len < dep->d_reclen)
43 len = dep->d_reclen;
44 if (len > max_len)
45 len = max_len;
46 memcpy(de, dep, len);
47 (*func) (dir_name, de, private);
48 }
49 free(de);
50 closedir(dir);
51 return 0;
52}
diff --git a/e2fsprogs/old_e2fsprogs/e2p/ls.c b/e2fsprogs/old_e2fsprogs/e2p/ls.c
deleted file mode 100644
index 9d29db6af..000000000
--- a/e2fsprogs/old_e2fsprogs/e2p/ls.c
+++ /dev/null
@@ -1,273 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * ls.c - List the contents of an ext2fs superblock
4 *
5 * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr>
6 * Laboratoire MASI, Institut Blaise Pascal
7 * Universite Pierre et Marie Curie (Paris VI)
8 *
9 * Copyright (C) 1995, 1996, 1997 Theodore Ts'o <tytso@mit.edu>
10 *
11 * This file can be redistributed under the terms of the GNU Library General
12 * Public License
13 */
14
15#include <stdio.h>
16#include <stdlib.h>
17#include <sys/types.h>
18#include <string.h>
19#include <grp.h>
20#include <pwd.h>
21#include <time.h>
22
23#include "e2p.h"
24
25static void print_user(unsigned short uid, FILE *f)
26{
27 struct passwd *pw = getpwuid(uid);
28 fprintf(f, "%u (user %s)\n", uid,
29 (pw == NULL ? "unknown" : pw->pw_name));
30}
31
32static void print_group(unsigned short gid, FILE *f)
33{
34 struct group *gr = getgrgid(gid);
35 fprintf(f, "%u (group %s)\n", gid,
36 (gr == NULL ? "unknown" : gr->gr_name));
37}
38
39#define MONTH_INT (86400 * 30)
40#define WEEK_INT (86400 * 7)
41#define DAY_INT (86400)
42#define HOUR_INT (60 * 60)
43#define MINUTE_INT (60)
44
45static const char *interval_string(unsigned int secs)
46{
47 static char buf[256], tmp[80];
48 int hr, min, num;
49
50 buf[0] = 0;
51
52 if (secs == 0)
53 return "<none>";
54
55 if (secs >= MONTH_INT) {
56 num = secs / MONTH_INT;
57 secs -= num*MONTH_INT;
58 sprintf(buf, "%d month%s", num, (num>1) ? "s" : "");
59 }
60 if (secs >= WEEK_INT) {
61 num = secs / WEEK_INT;
62 secs -= num*WEEK_INT;
63 sprintf(tmp, "%s%d week%s", buf[0] ? ", " : "",
64 num, (num>1) ? "s" : "");
65 strcat(buf, tmp);
66 }
67 if (secs >= DAY_INT) {
68 num = secs / DAY_INT;
69 secs -= num*DAY_INT;
70 sprintf(tmp, "%s%d day%s", buf[0] ? ", " : "",
71 num, (num>1) ? "s" : "");
72 strcat(buf, tmp);
73 }
74 if (secs > 0) {
75 hr = secs / HOUR_INT;
76 secs -= hr*HOUR_INT;
77 min = secs / MINUTE_INT;
78 secs -= min*MINUTE_INT;
79 sprintf(tmp, "%s%d:%02d:%02d", buf[0] ? ", " : "",
80 hr, min, secs);
81 strcat(buf, tmp);
82 }
83 return buf;
84}
85
86static void print_features(struct ext2_super_block * s, FILE *f)
87{
88#ifdef EXT2_DYNAMIC_REV
89 int i, j, printed=0;
90 __u32 *mask = &s->s_feature_compat, m;
91
92 fprintf(f, "Filesystem features: ");
93 for (i=0; i <3; i++,mask++) {
94 for (j=0,m=1; j < 32; j++, m<<=1) {
95 if (*mask & m) {
96 fprintf(f, " %s", e2p_feature2string(i, m));
97 printed++;
98 }
99 }
100 }
101 if (printed == 0)
102 fprintf(f, " (none)");
103 fprintf(f, "\n");
104#endif
105}
106
107static void print_mntopts(struct ext2_super_block * s, FILE *f)
108{
109#ifdef EXT2_DYNAMIC_REV
110 int i, printed=0;
111 __u32 mask = s->s_default_mount_opts, m;
112
113 fprintf(f, "Default mount options: ");
114 if (mask & EXT3_DEFM_JMODE) {
115 fprintf(f, " %s", e2p_mntopt2string(mask & EXT3_DEFM_JMODE));
116 printed++;
117 }
118 for (i=0,m=1; i < 32; i++, m<<=1) {
119 if (m & EXT3_DEFM_JMODE)
120 continue;
121 if (mask & m) {
122 fprintf(f, " %s", e2p_mntopt2string(m));
123 printed++;
124 }
125 }
126 if (printed == 0)
127 fprintf(f, " (none)");
128 fprintf(f, "\n");
129#endif
130}
131
132
133#ifndef EXT2_INODE_SIZE
134#define EXT2_INODE_SIZE(s) sizeof(struct ext2_inode)
135#endif
136
137#ifndef EXT2_GOOD_OLD_REV
138#define EXT2_GOOD_OLD_REV 0
139#endif
140
141void list_super2(struct ext2_super_block * sb, FILE *f)
142{
143 int inode_blocks_per_group;
144 char buf[80], *str;
145 time_t tm;
146
147 inode_blocks_per_group = (((sb->s_inodes_per_group *
148 EXT2_INODE_SIZE(sb)) +
149 EXT2_BLOCK_SIZE(sb) - 1) /
150 EXT2_BLOCK_SIZE(sb));
151 if (sb->s_volume_name[0]) {
152 memset(buf, 0, sizeof(buf));
153 strncpy(buf, sb->s_volume_name, sizeof(sb->s_volume_name));
154 } else
155 strcpy(buf, "<none>");
156 fprintf(f, "Filesystem volume name: %s\n", buf);
157 if (sb->s_last_mounted[0]) {
158 memset(buf, 0, sizeof(buf));
159 strncpy(buf, sb->s_last_mounted, sizeof(sb->s_last_mounted));
160 } else
161 strcpy(buf, "<not available>");
162 fprintf(f,
163 "Last mounted on: %s\n"
164 "Filesystem UUID: %s\n"
165 "Filesystem magic number: 0x%04X\n"
166 "Filesystem revision #: %d",
167 buf, e2p_uuid2str(sb->s_uuid), sb->s_magic, sb->s_rev_level);
168 if (sb->s_rev_level == EXT2_GOOD_OLD_REV) {
169 fprintf(f, " (original)\n");
170#ifdef EXT2_DYNAMIC_REV
171 } else if (sb->s_rev_level == EXT2_DYNAMIC_REV) {
172 fprintf(f, " (dynamic)\n");
173#endif
174 } else
175 fprintf(f, " (unknown)\n");
176 print_features(sb, f);
177 print_mntopts(sb, f);
178 fprintf(f, "Filesystem state: ");
179 print_fs_state (f, sb->s_state);
180 fprintf(f, "\nErrors behavior: ");
181 print_fs_errors(f, sb->s_errors);
182 str = e2p_os2string(sb->s_creator_os);
183 fprintf(f,
184 "\n"
185 "Filesystem OS type: %s\n"
186 "Inode count: %u\n"
187 "Block count: %u\n"
188 "Reserved block count: %u\n"
189 "Free blocks: %u\n"
190 "Free inodes: %u\n"
191 "First block: %u\n"
192 "Block size: %u\n"
193 "Fragment size: %u\n",
194 str, sb->s_inodes_count, sb->s_blocks_count, sb->s_r_blocks_count,
195 sb->s_free_blocks_count, sb->s_free_inodes_count,
196 sb->s_first_data_block, EXT2_BLOCK_SIZE(sb), EXT2_FRAG_SIZE(sb));
197 free(str);
198 if (sb->s_reserved_gdt_blocks)
199 fprintf(f, "Reserved GDT blocks: %u\n",
200 sb->s_reserved_gdt_blocks);
201 fprintf(f,
202 "Blocks per group: %u\n"
203 "Fragments per group: %u\n"
204 "Inodes per group: %u\n"
205 "Inode blocks per group: %u\n",
206 sb->s_blocks_per_group, sb->s_frags_per_group,
207 sb->s_inodes_per_group, inode_blocks_per_group);
208 if (sb->s_first_meta_bg)
209 fprintf(f, "First meta block group: %u\n",
210 sb->s_first_meta_bg);
211 if (sb->s_mkfs_time) {
212 tm = sb->s_mkfs_time;
213 fprintf(f, "Filesystem created: %s", ctime(&tm));
214 }
215 tm = sb->s_mtime;
216 fprintf(f, "Last mount time: %s",
217 sb->s_mtime ? ctime(&tm) : "n/a\n");
218 tm = sb->s_wtime;
219 fprintf(f,
220 "Last write time: %s"
221 "Mount count: %u\n"
222 "Maximum mount count: %d\n",
223 ctime(&tm), sb->s_mnt_count, sb->s_max_mnt_count);
224 tm = sb->s_lastcheck;
225 fprintf(f,
226 "Last checked: %s"
227 "Check interval: %u (%s)\n",
228 ctime(&tm),
229 sb->s_checkinterval, interval_string(sb->s_checkinterval));
230 if (sb->s_checkinterval)
231 {
232 time_t next;
233
234 next = sb->s_lastcheck + sb->s_checkinterval;
235 fprintf(f, "Next check after: %s", ctime(&next));
236 }
237 fprintf(f, "Reserved blocks uid: ");
238 print_user(sb->s_def_resuid, f);
239 fprintf(f, "Reserved blocks gid: ");
240 print_group(sb->s_def_resgid, f);
241 if (sb->s_rev_level >= EXT2_DYNAMIC_REV) {
242 fprintf(f,
243 "First inode: %d\n"
244 "Inode size: %d\n",
245 sb->s_first_ino, sb->s_inode_size);
246 }
247 if (!e2p_is_null_uuid(sb->s_journal_uuid))
248 fprintf(f, "Journal UUID: %s\n",
249 e2p_uuid2str(sb->s_journal_uuid));
250 if (sb->s_journal_inum)
251 fprintf(f, "Journal inode: %u\n",
252 sb->s_journal_inum);
253 if (sb->s_journal_dev)
254 fprintf(f, "Journal device: 0x%04x\n",
255 sb->s_journal_dev);
256 if (sb->s_last_orphan)
257 fprintf(f, "First orphan inode: %u\n",
258 sb->s_last_orphan);
259 if ((sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
260 sb->s_def_hash_version)
261 fprintf(f, "Default directory hash: %s\n",
262 e2p_hash2string(sb->s_def_hash_version));
263 if (!e2p_is_null_uuid(sb->s_hash_seed))
264 fprintf(f, "Directory Hash Seed: %s\n",
265 e2p_uuid2str(sb->s_hash_seed));
266 if (sb->s_jnl_backup_type) {
267 fprintf(f, "Journal backup: ");
268 if (sb->s_jnl_backup_type == 1)
269 fprintf(f, "inode blocks\n");
270 else
271 fprintf(f, "type %u\n", sb->s_jnl_backup_type);
272 }
273}
diff --git a/e2fsprogs/old_e2fsprogs/e2p/mntopts.c b/e2fsprogs/old_e2fsprogs/e2p/mntopts.c
deleted file mode 100644
index 17c26c480..000000000
--- a/e2fsprogs/old_e2fsprogs/e2p/mntopts.c
+++ /dev/null
@@ -1,134 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * mountopts.c --- convert between default mount options and strings
4 *
5 * Copyright (C) 2002 Theodore Ts'o <tytso@mit.edu>
6 *
7 * This file can be redistributed under the terms of the GNU Library General
8 * Public License
9 *
10 */
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <ctype.h>
16#include <errno.h>
17
18#include "e2p.h"
19
20struct mntopt {
21 unsigned int mask;
22 const char *string;
23};
24
25static const struct mntopt mntopt_list[] = {
26 { EXT2_DEFM_DEBUG, "debug" },
27 { EXT2_DEFM_BSDGROUPS, "bsdgroups" },
28 { EXT2_DEFM_XATTR_USER, "user_xattr" },
29 { EXT2_DEFM_ACL, "acl" },
30 { EXT2_DEFM_UID16, "uid16" },
31 { EXT3_DEFM_JMODE_DATA, "journal_data" },
32 { EXT3_DEFM_JMODE_ORDERED, "journal_data_ordered" },
33 { EXT3_DEFM_JMODE_WBACK, "journal_data_writeback" },
34 { 0, 0 },
35};
36
37const char *e2p_mntopt2string(unsigned int mask)
38{
39 const struct mntopt *f;
40 static char buf[20];
41 int fnum;
42
43 for (f = mntopt_list; f->string; f++) {
44 if (mask == f->mask)
45 return f->string;
46 }
47 for (fnum = 0; mask >>= 1; fnum++);
48 sprintf(buf, "MNTOPT_%d", fnum);
49 return buf;
50}
51
52int e2p_string2mntopt(char *string, unsigned int *mask)
53{
54 const struct mntopt *f;
55 char *eptr;
56 int num;
57
58 for (f = mntopt_list; f->string; f++) {
59 if (!strcasecmp(string, f->string)) {
60 *mask = f->mask;
61 return 0;
62 }
63 }
64 if (strncasecmp(string, "MNTOPT_", 8))
65 return 1;
66
67 if (string[8] == 0)
68 return 1;
69 num = strtol(string+8, &eptr, 10);
70 if (num > 32 || num < 0)
71 return 1;
72 if (*eptr)
73 return 1;
74 *mask = 1 << num;
75 return 0;
76}
77
78static char *skip_over_blanks(char *cp)
79{
80 while (*cp && isspace(*cp))
81 cp++;
82 return cp;
83}
84
85static char *skip_over_word(char *cp)
86{
87 while (*cp && !isspace(*cp) && *cp != ',')
88 cp++;
89 return cp;
90}
91
92/*
93 * Edit a mntopt set array as requested by the user. The ok
94 * parameter, if non-zero, allows the application to limit what
95 * mntopts the user is allowed to set or clear using this function.
96 */
97int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok)
98{
99 char *cp, *buf, *next;
100 int neg;
101 unsigned int mask;
102
103 buf = xstrdup(str);
104 cp = buf;
105 while (cp && *cp) {
106 neg = 0;
107 cp = skip_over_blanks(cp);
108 next = skip_over_word(cp);
109 if (*next == 0)
110 next = 0;
111 else
112 *next = 0;
113 switch (*cp) {
114 case '-':
115 case '^':
116 neg++;
117 case '+':
118 cp++;
119 break;
120 }
121 if (e2p_string2mntopt(cp, &mask))
122 return 1;
123 if (ok && !(ok & mask))
124 return 1;
125 if (mask & EXT3_DEFM_JMODE)
126 *mntopts &= ~EXT3_DEFM_JMODE;
127 if (neg)
128 *mntopts &= ~mask;
129 else
130 *mntopts |= mask;
131 cp = next ? next+1 : 0;
132 }
133 return 0;
134}
diff --git a/e2fsprogs/old_e2fsprogs/e2p/ostype.c b/e2fsprogs/old_e2fsprogs/e2p/ostype.c
deleted file mode 100644
index 6a2f178f3..000000000
--- a/e2fsprogs/old_e2fsprogs/e2p/ostype.c
+++ /dev/null
@@ -1,72 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * getostype.c - Get the Filesystem OS type
4 *
5 * Copyright (C) 2004,2005 Theodore Ts'o <tytso@mit.edu>
6 *
7 * This file can be redistributed under the terms of the GNU Library General
8 * Public License
9 */
10
11#include "e2p.h"
12#include <string.h>
13#include <stdlib.h>
14
15static const char *const os_tab[] =
16 { "Linux",
17 "Hurd",
18 "Masix",
19 "FreeBSD",
20 "Lites",
21 0 };
22
23/*
24 * Convert an os_type to a string
25 */
26char *e2p_os2string(int os_type)
27{
28 const char *os;
29 char *ret;
30
31 if (os_type <= EXT2_OS_LITES)
32 os = os_tab[os_type];
33 else
34 os = "(unknown os)";
35
36 ret = xstrdup(os);
37 return ret;
38}
39
40/*
41 * Convert an os_type to a string
42 */
43int e2p_string2os(char *str)
44{
45 const char *const *cpp;
46 int i = 0;
47
48 for (cpp = os_tab; *cpp; cpp++, i++) {
49 if (!strcasecmp(str, *cpp))
50 return i;
51 }
52 return -1;
53}
54
55#ifdef TEST_PROGRAM
56int main(int argc, char **argv)
57{
58 char *s;
59 int i, os;
60
61 for (i=0; i <= EXT2_OS_LITES; i++) {
62 s = e2p_os2string(i);
63 os = e2p_string2os(s);
64 printf("%d: %s (%d)\n", i, s, os);
65 if (i != os) {
66 fprintf(stderr, "Failure!\n");
67 exit(1);
68 }
69 }
70 exit(0);
71}
72#endif
diff --git a/e2fsprogs/old_e2fsprogs/e2p/parse_num.c b/e2fsprogs/old_e2fsprogs/e2p/parse_num.c
deleted file mode 100644
index 6db076f9c..000000000
--- a/e2fsprogs/old_e2fsprogs/e2p/parse_num.c
+++ /dev/null
@@ -1,65 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * parse_num.c - Parse the number of blocks
4 *
5 * Copyright (C) 2004,2005 Theodore Ts'o <tytso@mit.edu>
6 *
7 * This file can be redistributed under the terms of the GNU Library General
8 * Public License
9 */
10
11#include "e2p.h"
12
13#include <stdlib.h>
14
15unsigned long parse_num_blocks(const char *arg, int log_block_size)
16{
17 char *p;
18 unsigned long long num;
19
20 num = strtoull(arg, &p, 0);
21
22 if (p[0] && p[1])
23 return 0;
24
25 switch (*p) { /* Using fall-through logic */
26 case 'T': case 't':
27 num <<= 10;
28 case 'G': case 'g':
29 num <<= 10;
30 case 'M': case 'm':
31 num <<= 10;
32 case 'K': case 'k':
33 num >>= log_block_size;
34 break;
35 case 's':
36 num >>= 1;
37 break;
38 case '\0':
39 break;
40 default:
41 return 0;
42 }
43 return num;
44}
45
46#ifdef DEBUG
47#include <unistd.h>
48#include <stdio.h>
49
50main(int argc, char **argv)
51{
52 unsigned long num;
53 int log_block_size = 0;
54
55 if (argc != 2) {
56 fprintf(stderr, "Usage: %s arg\n", argv[0]);
57 exit(1);
58 }
59
60 num = parse_num_blocks(argv[1], log_block_size);
61
62 printf("Parsed number: %lu\n", num);
63 exit(0);
64}
65#endif
diff --git a/e2fsprogs/old_e2fsprogs/e2p/pe.c b/e2fsprogs/old_e2fsprogs/e2p/pe.c
deleted file mode 100644
index 835274b54..000000000
--- a/e2fsprogs/old_e2fsprogs/e2p/pe.c
+++ /dev/null
@@ -1,32 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * pe.c - Print a second extended filesystem errors behavior
4 *
5 * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr>
6 * Laboratoire MASI, Institut Blaise Pascal
7 * Universite Pierre et Marie Curie (Paris VI)
8 *
9 * This file can be redistributed under the terms of the GNU Library General
10 * Public License
11 */
12
13/*
14 * History:
15 * 94/01/09 - Creation
16 */
17
18#include <stdio.h>
19
20#include "e2p.h"
21
22void print_fs_errors(FILE *f, unsigned short errors)
23{
24 char *disp = NULL;
25 switch (errors) {
26 case EXT2_ERRORS_CONTINUE: disp = "Continue"; break;
27 case EXT2_ERRORS_RO: disp = "Remount read-only"; break;
28 case EXT2_ERRORS_PANIC: disp = "Panic"; break;
29 default: disp = "Unknown (continue)";
30 }
31 fprintf(f, disp);
32}
diff --git a/e2fsprogs/old_e2fsprogs/e2p/pf.c b/e2fsprogs/old_e2fsprogs/e2p/pf.c
deleted file mode 100644
index 02cbec7e0..000000000
--- a/e2fsprogs/old_e2fsprogs/e2p/pf.c
+++ /dev/null
@@ -1,74 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * pf.c - Print file attributes on an ext2 file system
4 *
5 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
6 * Laboratoire MASI, Institut Blaise Pascal
7 * Universite Pierre et Marie Curie (Paris VI)
8 *
9 * This file can be redistributed under the terms of the GNU Library General
10 * Public License
11 */
12
13/*
14 * History:
15 * 93/10/30 - Creation
16 */
17
18#include <stdio.h>
19
20#include "e2p.h"
21
22struct flags_name {
23 unsigned long flag;
24 const char *short_name;
25 const char *long_name;
26};
27
28static const struct flags_name flags_array[] = {
29 { EXT2_SECRM_FL, "s", "Secure_Deletion" },
30 { EXT2_UNRM_FL, "u" , "Undelete" },
31 { EXT2_SYNC_FL, "S", "Synchronous_Updates" },
32 { EXT2_DIRSYNC_FL, "D", "Synchronous_Directory_Updates" },
33 { EXT2_IMMUTABLE_FL, "i", "Immutable" },
34 { EXT2_APPEND_FL, "a", "Append_Only" },
35 { EXT2_NODUMP_FL, "d", "No_Dump" },
36 { EXT2_NOATIME_FL, "A", "No_Atime" },
37 { EXT2_COMPR_FL, "c", "Compression_Requested" },
38#ifdef ENABLE_COMPRESSION
39 { EXT2_COMPRBLK_FL, "B", "Compressed_File" },
40 { EXT2_DIRTY_FL, "Z", "Compressed_Dirty_File" },
41 { EXT2_NOCOMPR_FL, "X", "Compression_Raw_Access" },
42 { EXT2_ECOMPR_FL, "E", "Compression_Error" },
43#endif
44 { EXT3_JOURNAL_DATA_FL, "j", "Journaled_Data" },
45 { EXT2_INDEX_FL, "I", "Indexed_direcctory" },
46 { EXT2_NOTAIL_FL, "t", "No_Tailmerging" },
47 { EXT2_TOPDIR_FL, "T", "Top_of_Directory_Hierarchies" },
48 { 0, NULL, NULL }
49};
50
51void print_flags (FILE *f, unsigned long flags, unsigned options)
52{
53 int long_opt = (options & PFOPT_LONG);
54 const struct flags_name *fp;
55 int first = 1;
56
57 for (fp = flags_array; fp->flag != 0; fp++) {
58 if (flags & fp->flag) {
59 if (long_opt) {
60 if (first)
61 first = 0;
62 else
63 fputs(", ", f);
64 fputs(fp->long_name, f);
65 } else
66 fputs(fp->short_name, f);
67 } else {
68 if (!long_opt)
69 fputs("-", f);
70 }
71 }
72 if (long_opt && first)
73 fputs("---", f);
74}
diff --git a/e2fsprogs/old_e2fsprogs/e2p/ps.c b/e2fsprogs/old_e2fsprogs/e2p/ps.c
deleted file mode 100644
index a6b4099db..000000000
--- a/e2fsprogs/old_e2fsprogs/e2p/ps.c
+++ /dev/null
@@ -1,27 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * ps.c - Print filesystem state
4 *
5 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
6 * Laboratoire MASI, Institut Blaise Pascal
7 * Universite Pierre et Marie Curie (Paris VI)
8 *
9 * This file can be redistributed under the terms of the GNU Library General
10 * Public License
11 */
12
13/*
14 * History:
15 * 93/12/22 - Creation
16 */
17
18#include <stdio.h>
19
20#include "e2p.h"
21
22void print_fs_state(FILE *f, unsigned short state)
23{
24 fprintf(f, (state & EXT2_VALID_FS ? " clean" : " not clean"));
25 if (state & EXT2_ERROR_FS)
26 fprintf(f, " with errors");
27}
diff --git a/e2fsprogs/old_e2fsprogs/e2p/uuid.c b/e2fsprogs/old_e2fsprogs/e2p/uuid.c
deleted file mode 100644
index 474d64a5a..000000000
--- a/e2fsprogs/old_e2fsprogs/e2p/uuid.c
+++ /dev/null
@@ -1,78 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * uuid.c -- utility routines for manipulating UUID's.
4 */
5
6#include <stdio.h>
7#include <string.h>
8#include "../ext2fs/ext2_types.h"
9
10#include "e2p.h"
11
12struct uuid {
13 __u32 time_low;
14 __u16 time_mid;
15 __u16 time_hi_and_version;
16 __u16 clock_seq;
17 __u8 node[6];
18};
19
20/* Returns 1 if the uuid is the NULL uuid */
21int e2p_is_null_uuid(void *uu)
22{
23 __u8 *cp;
24 int i;
25
26 for (i=0, cp = uu; i < 16; i++)
27 if (*cp)
28 return 0;
29 return 1;
30}
31
32static void e2p_unpack_uuid(void *in, struct uuid *uu)
33{
34 __u8 *ptr = in;
35 __u32 tmp;
36
37 tmp = *ptr++;
38 tmp = (tmp << 8) | *ptr++;
39 tmp = (tmp << 8) | *ptr++;
40 tmp = (tmp << 8) | *ptr++;
41 uu->time_low = tmp;
42
43 tmp = *ptr++;
44 tmp = (tmp << 8) | *ptr++;
45 uu->time_mid = tmp;
46
47 tmp = *ptr++;
48 tmp = (tmp << 8) | *ptr++;
49 uu->time_hi_and_version = tmp;
50
51 tmp = *ptr++;
52 tmp = (tmp << 8) | *ptr++;
53 uu->clock_seq = tmp;
54
55 memcpy(uu->node, ptr, 6);
56}
57
58void e2p_uuid_to_str(void *uu, char *out)
59{
60 struct uuid uuid;
61
62 e2p_unpack_uuid(uu, &uuid);
63 sprintf(out,
64 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
65 uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
66 uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
67 uuid.node[0], uuid.node[1], uuid.node[2],
68 uuid.node[3], uuid.node[4], uuid.node[5]);
69}
70
71const char *e2p_uuid2str(void *uu)
72{
73 static char buf[80];
74 if (e2p_is_null_uuid(uu))
75 return "<none>";
76 e2p_uuid_to_str(uu, buf);
77 return buf;
78}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/Kbuild.src b/e2fsprogs/old_e2fsprogs/ext2fs/Kbuild.src
deleted file mode 100644
index 12adc6e46..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/Kbuild.src
+++ /dev/null
@@ -1,26 +0,0 @@
1# Makefile for busybox
2#
3# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
4#
5# Licensed under GPLv2, see file LICENSE in this source tree.
6
7NEEDED-$(CONFIG_E2FSCK) = y
8NEEDED-$(CONFIG_FSCK) = y
9NEEDED-$(CONFIG_MKE2FS) = y
10NEEDED-$(CONFIG_TUNE2FS) = y
11
12lib-y:=
13
14INSERT
15
16lib-$(NEEDED-y) += gen_bitmap.o bitops.o ismounted.o mkjournal.o unix_io.o \
17 rw_bitmaps.o initialize.o bitmaps.o block.o \
18 ind_block.o inode.o freefs.o alloc_stats.o closefs.o \
19 openfs.o io_manager.o finddev.o read_bb.o alloc.o badblocks.o \
20 getsize.o getsectsize.o alloc_tables.o read_bb_file.o mkdir.o \
21 bb_inode.o newdir.o alloc_sb.o lookup.o dirblock.o expanddir.o \
22 dir_iterate.o link.o res_gdt.o icount.o get_pathname.o dblist.o \
23 dirhash.o version.o flushb.o unlink.o check_desc.o valid_blk.o \
24 ext_attr.o bmap.o dblist_dir.o ext2fs_inline.o swapfs.o
25
26CFLAGS += -include $(srctree)/e2fsprogs/e2fsbb.h
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/alloc.c b/e2fsprogs/old_e2fsprogs/ext2fs/alloc.c
deleted file mode 100644
index cbb63e15a..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/alloc.c
+++ /dev/null
@@ -1,173 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * alloc.c --- allocate new inodes, blocks for ext2fs
4 *
5 * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 *
12 */
13
14#include <stdio.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#include <time.h>
19#include <string.h>
20#if HAVE_SYS_STAT_H
21#include <sys/stat.h>
22#endif
23#if HAVE_SYS_TYPES_H
24#include <sys/types.h>
25#endif
26
27#include "ext2_fs.h"
28#include "ext2fs.h"
29
30/*
31 * Right now, just search forward from the parent directory's block
32 * group to find the next free inode.
33 *
34 * Should have a special policy for directories.
35 */
36errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir,
37 int mode EXT2FS_ATTR((unused)),
38 ext2fs_inode_bitmap map, ext2_ino_t *ret)
39{
40 ext2_ino_t dir_group = 0;
41 ext2_ino_t i;
42 ext2_ino_t start_inode;
43
44 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
45
46 if (!map)
47 map = fs->inode_map;
48 if (!map)
49 return EXT2_ET_NO_INODE_BITMAP;
50
51 if (dir > 0)
52 dir_group = (dir - 1) / EXT2_INODES_PER_GROUP(fs->super);
53
54 start_inode = (dir_group * EXT2_INODES_PER_GROUP(fs->super)) + 1;
55 if (start_inode < EXT2_FIRST_INODE(fs->super))
56 start_inode = EXT2_FIRST_INODE(fs->super);
57 i = start_inode;
58
59 do {
60 if (!ext2fs_fast_test_inode_bitmap(map, i))
61 break;
62 i++;
63 if (i > fs->super->s_inodes_count)
64 i = EXT2_FIRST_INODE(fs->super);
65 } while (i != start_inode);
66
67 if (ext2fs_test_inode_bitmap(map, i))
68 return EXT2_ET_INODE_ALLOC_FAIL;
69 *ret = i;
70 return 0;
71}
72
73/*
74 * Stupid algorithm --- we now just search forward starting from the
75 * goal. Should put in a smarter one someday....
76 */
77errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
78 ext2fs_block_bitmap map, blk_t *ret)
79{
80 blk_t i;
81
82 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
83
84 if (!map)
85 map = fs->block_map;
86 if (!map)
87 return EXT2_ET_NO_BLOCK_BITMAP;
88 if (!goal || (goal >= fs->super->s_blocks_count))
89 goal = fs->super->s_first_data_block;
90 i = goal;
91 do {
92 if (!ext2fs_fast_test_block_bitmap(map, i)) {
93 *ret = i;
94 return 0;
95 }
96 i++;
97 if (i >= fs->super->s_blocks_count)
98 i = fs->super->s_first_data_block;
99 } while (i != goal);
100 return EXT2_ET_BLOCK_ALLOC_FAIL;
101}
102
103/*
104 * This function zeros out the allocated block, and updates all of the
105 * appropriate filesystem records.
106 */
107errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
108 char *block_buf, blk_t *ret)
109{
110 errcode_t retval;
111 blk_t block;
112 char *buf = NULL;
113
114 if (!block_buf) {
115 retval = ext2fs_get_mem(fs->blocksize, &buf);
116 if (retval)
117 return retval;
118 block_buf = buf;
119 }
120 memset(block_buf, 0, fs->blocksize);
121
122 if (!fs->block_map) {
123 retval = ext2fs_read_block_bitmap(fs);
124 if (retval)
125 goto fail;
126 }
127
128 retval = ext2fs_new_block(fs, goal, 0, &block);
129 if (retval)
130 goto fail;
131
132 retval = io_channel_write_blk(fs->io, block, 1, block_buf);
133 if (retval)
134 goto fail;
135
136 ext2fs_block_alloc_stats(fs, block, +1);
137 *ret = block;
138 return 0;
139
140fail:
141 if (buf)
142 ext2fs_free_mem(&buf);
143 return retval;
144}
145
146errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish,
147 int num, ext2fs_block_bitmap map, blk_t *ret)
148{
149 blk_t b = start;
150
151 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
152
153 if (!map)
154 map = fs->block_map;
155 if (!map)
156 return EXT2_ET_NO_BLOCK_BITMAP;
157 if (!b)
158 b = fs->super->s_first_data_block;
159 if (!finish)
160 finish = start;
161 if (!num)
162 num = 1;
163 do {
164 if (b+num-1 > fs->super->s_blocks_count)
165 b = fs->super->s_first_data_block;
166 if (ext2fs_fast_test_block_bitmap_range(map, b, num)) {
167 *ret = b;
168 return 0;
169 }
170 b++;
171 } while (b != finish);
172 return EXT2_ET_BLOCK_ALLOC_FAIL;
173}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/alloc_sb.c b/e2fsprogs/old_e2fsprogs/ext2fs/alloc_sb.c
deleted file mode 100644
index a7437c96f..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/alloc_sb.c
+++ /dev/null
@@ -1,58 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * alloc_sb.c --- Allocate the superblock and block group descriptors for a
4 * newly initialized filesystem. Used by mke2fs when initializing a filesystem
5 *
6 * Copyright (C) 1994, 1995, 1996, 2003 Theodore Ts'o.
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the GNU Public
10 * License.
11 * %End-Header%
12 */
13
14#include <stdio.h>
15#include <string.h>
16#if HAVE_UNISTD_H
17#include <unistd.h>
18#endif
19#include <fcntl.h>
20#include <time.h>
21#if HAVE_SYS_STAT_H
22#include <sys/stat.h>
23#endif
24#if HAVE_SYS_TYPES_H
25#include <sys/types.h>
26#endif
27
28#include "ext2_fs.h"
29#include "ext2fs.h"
30
31int ext2fs_reserve_super_and_bgd(ext2_filsys fs,
32 dgrp_t group,
33 ext2fs_block_bitmap bmap)
34{
35 blk_t super_blk, old_desc_blk, new_desc_blk;
36 int j, old_desc_blocks, num_blocks;
37
38 num_blocks = ext2fs_super_and_bgd_loc(fs, group, &super_blk,
39 &old_desc_blk, &new_desc_blk, 0);
40
41 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
42 old_desc_blocks = fs->super->s_first_meta_bg;
43 else
44 old_desc_blocks =
45 fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
46
47 if (super_blk || (group == 0))
48 ext2fs_mark_block_bitmap(bmap, super_blk);
49
50 if (old_desc_blk) {
51 for (j=0; j < old_desc_blocks; j++)
52 ext2fs_mark_block_bitmap(bmap, old_desc_blk + j);
53 }
54 if (new_desc_blk)
55 ext2fs_mark_block_bitmap(bmap, new_desc_blk);
56
57 return num_blocks;
58}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/alloc_stats.c b/e2fsprogs/old_e2fsprogs/ext2fs/alloc_stats.c
deleted file mode 100644
index f3ab06a23..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/alloc_stats.c
+++ /dev/null
@@ -1,53 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * alloc_stats.c --- Update allocation statistics for ext2fs
4 *
5 * Copyright (C) 2001 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 *
12 */
13
14#include <stdio.h>
15
16#include "ext2_fs.h"
17#include "ext2fs.h"
18
19void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino,
20 int inuse, int isdir)
21{
22 int group = ext2fs_group_of_ino(fs, ino);
23
24 if (inuse > 0)
25 ext2fs_mark_inode_bitmap(fs->inode_map, ino);
26 else
27 ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
28 fs->group_desc[group].bg_free_inodes_count -= inuse;
29 if (isdir)
30 fs->group_desc[group].bg_used_dirs_count += inuse;
31 fs->super->s_free_inodes_count -= inuse;
32 ext2fs_mark_super_dirty(fs);
33 ext2fs_mark_ib_dirty(fs);
34}
35
36void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse)
37{
38 ext2fs_inode_alloc_stats2(fs, ino, inuse, 0);
39}
40
41void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse)
42{
43 int group = ext2fs_group_of_blk(fs, blk);
44
45 if (inuse > 0)
46 ext2fs_mark_block_bitmap(fs->block_map, blk);
47 else
48 ext2fs_unmark_block_bitmap(fs->block_map, blk);
49 fs->group_desc[group].bg_free_blocks_count -= inuse;
50 fs->super->s_free_blocks_count -= inuse;
51 ext2fs_mark_super_dirty(fs);
52 ext2fs_mark_bb_dirty(fs);
53}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/alloc_tables.c b/e2fsprogs/old_e2fsprogs/ext2fs/alloc_tables.c
deleted file mode 100644
index 7c60e2bf5..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/alloc_tables.c
+++ /dev/null
@@ -1,114 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * alloc_tables.c --- Allocate tables for a newly initialized
4 * filesystem. Used by mke2fs when initializing a filesystem
5 *
6 * Copyright (C) 1996 Theodore Ts'o.
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the GNU Public
10 * License.
11 * %End-Header%
12 */
13
14#include <stdio.h>
15#include <string.h>
16#if HAVE_UNISTD_H
17#include <unistd.h>
18#endif
19#include <fcntl.h>
20#include <time.h>
21#if HAVE_SYS_STAT_H
22#include <sys/stat.h>
23#endif
24#if HAVE_SYS_TYPES_H
25#include <sys/types.h>
26#endif
27
28#include "ext2_fs.h"
29#include "ext2fs.h"
30
31errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
32 ext2fs_block_bitmap bmap)
33{
34 errcode_t retval;
35 blk_t group_blk, start_blk, last_blk, new_blk, blk;
36 int j;
37
38 group_blk = fs->super->s_first_data_block +
39 (group * fs->super->s_blocks_per_group);
40
41 last_blk = group_blk + fs->super->s_blocks_per_group;
42 if (last_blk >= fs->super->s_blocks_count)
43 last_blk = fs->super->s_blocks_count - 1;
44
45 if (!bmap)
46 bmap = fs->block_map;
47
48 /*
49 * Allocate the block and inode bitmaps, if necessary
50 */
51 if (fs->stride) {
52 start_blk = group_blk + fs->inode_blocks_per_group;
53 start_blk += ((fs->stride * group) %
54 (last_blk - start_blk));
55 if (start_blk > last_blk)
56 start_blk = group_blk;
57 } else
58 start_blk = group_blk;
59
60 if (!fs->group_desc[group].bg_block_bitmap) {
61 retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
62 1, bmap, &new_blk);
63 if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
64 retval = ext2fs_get_free_blocks(fs, group_blk,
65 last_blk, 1, bmap, &new_blk);
66 if (retval)
67 return retval;
68 ext2fs_mark_block_bitmap(bmap, new_blk);
69 fs->group_desc[group].bg_block_bitmap = new_blk;
70 }
71
72 if (!fs->group_desc[group].bg_inode_bitmap) {
73 retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
74 1, bmap, &new_blk);
75 if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
76 retval = ext2fs_get_free_blocks(fs, group_blk,
77 last_blk, 1, bmap, &new_blk);
78 if (retval)
79 return retval;
80 ext2fs_mark_block_bitmap(bmap, new_blk);
81 fs->group_desc[group].bg_inode_bitmap = new_blk;
82 }
83
84 /*
85 * Allocate the inode table
86 */
87 if (!fs->group_desc[group].bg_inode_table) {
88 retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
89 fs->inode_blocks_per_group,
90 bmap, &new_blk);
91 if (retval)
92 return retval;
93 for (j=0, blk = new_blk;
94 j < fs->inode_blocks_per_group;
95 j++, blk++)
96 ext2fs_mark_block_bitmap(bmap, blk);
97 fs->group_desc[group].bg_inode_table = new_blk;
98 }
99
100 return 0;
101}
102
103errcode_t ext2fs_allocate_tables(ext2_filsys fs)
104{
105 errcode_t retval;
106 dgrp_t i;
107
108 for (i = 0; i < fs->group_desc_count; i++) {
109 retval = ext2fs_allocate_group_table(fs, i, fs->block_map);
110 if (retval)
111 return retval;
112 }
113 return 0;
114}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/badblocks.c b/e2fsprogs/old_e2fsprogs/ext2fs/badblocks.c
deleted file mode 100644
index 6e5cc10b8..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/badblocks.c
+++ /dev/null
@@ -1,328 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * badblocks.c --- routines to manipulate the bad block structure
4 *
5 * Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#include <fcntl.h>
19#include <time.h>
20#if HAVE_SYS_STAT_H
21#include <sys/stat.h>
22#endif
23#if HAVE_SYS_TYPES_H
24#include <sys/types.h>
25#endif
26
27#include "ext2_fs.h"
28#include "ext2fsP.h"
29
30/*
31 * Helper function for making a badblocks list
32 */
33static errcode_t make_u32_list(int size, int num, __u32 *list,
34 ext2_u32_list *ret)
35{
36 ext2_u32_list bb;
37 errcode_t retval;
38
39 retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_list), &bb);
40 if (retval)
41 return retval;
42 memset(bb, 0, sizeof(struct ext2_struct_u32_list));
43 bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST;
44 bb->size = size ? size : 10;
45 bb->num = num;
46 retval = ext2fs_get_mem(bb->size * sizeof(blk_t), &bb->list);
47 if (!bb->list) {
48 ext2fs_free_mem(&bb);
49 return retval;
50 }
51 if (list)
52 memcpy(bb->list, list, bb->size * sizeof(blk_t));
53 else
54 memset(bb->list, 0, bb->size * sizeof(blk_t));
55 *ret = bb;
56 return 0;
57}
58
59
60/*
61 * This procedure creates an empty u32 list.
62 */
63errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size)
64{
65 return make_u32_list(size, 0, 0, ret);
66}
67
68/*
69 * This procedure creates an empty badblocks list.
70 */
71errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size)
72{
73 return make_u32_list(size, 0, 0, (ext2_badblocks_list *) ret);
74}
75
76
77/*
78 * This procedure copies a badblocks list
79 */
80errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest)
81{
82 errcode_t retval;
83
84 retval = make_u32_list(src->size, src->num, src->list, dest);
85 if (retval)
86 return retval;
87 (*dest)->badblocks_flags = src->badblocks_flags;
88 return 0;
89}
90
91errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
92 ext2_badblocks_list *dest)
93{
94 return ext2fs_u32_copy((ext2_u32_list) src,
95 (ext2_u32_list *) dest);
96}
97
98/*
99 * This procedure frees a badblocks list.
100 *
101 * (note: moved to closefs.c)
102 */
103
104
105/*
106 * This procedure adds a block to a badblocks list.
107 */
108errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk)
109{
110 errcode_t retval;
111 int i, j;
112 unsigned long old_size;
113
114 EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
115
116 if (bb->num >= bb->size) {
117 old_size = bb->size * sizeof(__u32);
118 bb->size += 100;
119 retval = ext2fs_resize_mem(old_size, bb->size * sizeof(__u32),
120 &bb->list);
121 if (retval) {
122 bb->size -= 100;
123 return retval;
124 }
125 }
126
127 /*
128 * Add special case code for appending to the end of the list
129 */
130 i = bb->num-1;
131 if ((bb->num != 0) && (bb->list[i] == blk))
132 return 0;
133 if ((bb->num == 0) || (bb->list[i] < blk)) {
134 bb->list[bb->num++] = blk;
135 return 0;
136 }
137
138 j = bb->num;
139 for (i=0; i < bb->num; i++) {
140 if (bb->list[i] == blk)
141 return 0;
142 if (bb->list[i] > blk) {
143 j = i;
144 break;
145 }
146 }
147 for (i=bb->num; i > j; i--)
148 bb->list[i] = bb->list[i-1];
149 bb->list[j] = blk;
150 bb->num++;
151 return 0;
152}
153
154errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk)
155{
156 return ext2fs_u32_list_add((ext2_u32_list) bb, (__u32) blk);
157}
158
159/*
160 * This procedure finds a particular block is on a badblocks
161 * list.
162 */
163int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk)
164{
165 int low, high, mid;
166
167 if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
168 return -1;
169
170 if (bb->num == 0)
171 return -1;
172
173 low = 0;
174 high = bb->num-1;
175 if (blk == bb->list[low])
176 return low;
177 if (blk == bb->list[high])
178 return high;
179
180 while (low < high) {
181 mid = (low+high)/2;
182 if (mid == low || mid == high)
183 break;
184 if (blk == bb->list[mid])
185 return mid;
186 if (blk < bb->list[mid])
187 high = mid;
188 else
189 low = mid;
190 }
191 return -1;
192}
193
194/*
195 * This procedure tests to see if a particular block is on a badblocks
196 * list.
197 */
198int ext2fs_u32_list_test(ext2_u32_list bb, __u32 blk)
199{
200 if (ext2fs_u32_list_find(bb, blk) < 0)
201 return 0;
202 else
203 return 1;
204}
205
206int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk)
207{
208 return ext2fs_u32_list_test((ext2_u32_list) bb, (__u32) blk);
209}
210
211
212/*
213 * Remove a block from the badblock list
214 */
215int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk)
216{
217 int remloc, i;
218
219 if (bb->num == 0)
220 return -1;
221
222 remloc = ext2fs_u32_list_find(bb, blk);
223 if (remloc < 0)
224 return -1;
225
226 for (i = remloc; i < bb->num - 1; i++)
227 bb->list[i] = bb->list[i+1];
228 bb->num--;
229 return 0;
230}
231
232void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk)
233{
234 ext2fs_u32_list_del(bb, blk);
235}
236
237errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb,
238 ext2_u32_iterate *ret)
239{
240 ext2_u32_iterate iter;
241 errcode_t retval;
242
243 EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
244
245 retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_iterate), &iter);
246 if (retval)
247 return retval;
248
249 iter->magic = EXT2_ET_MAGIC_BADBLOCKS_ITERATE;
250 iter->bb = bb;
251 iter->ptr = 0;
252 *ret = iter;
253 return 0;
254}
255
256errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
257 ext2_badblocks_iterate *ret)
258{
259 return ext2fs_u32_list_iterate_begin((ext2_u32_list) bb,
260 (ext2_u32_iterate *) ret);
261}
262
263
264int ext2fs_u32_list_iterate(ext2_u32_iterate iter, __u32 *blk)
265{
266 ext2_u32_list bb;
267
268 if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)
269 return 0;
270
271 bb = iter->bb;
272
273 if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
274 return 0;
275
276 if (iter->ptr < bb->num) {
277 *blk = bb->list[iter->ptr++];
278 return 1;
279 }
280 *blk = 0;
281 return 0;
282}
283
284int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk)
285{
286 return ext2fs_u32_list_iterate((ext2_u32_iterate) iter,
287 (__u32 *) blk);
288}
289
290
291void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter)
292{
293 if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE))
294 return;
295
296 iter->bb = 0;
297 ext2fs_free_mem(&iter);
298}
299
300void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter)
301{
302 ext2fs_u32_list_iterate_end((ext2_u32_iterate) iter);
303}
304
305
306int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2)
307{
308 EXT2_CHECK_MAGIC(bb1, EXT2_ET_MAGIC_BADBLOCKS_LIST);
309 EXT2_CHECK_MAGIC(bb2, EXT2_ET_MAGIC_BADBLOCKS_LIST);
310
311 if (bb1->num != bb2->num)
312 return 0;
313
314 if (memcmp(bb1->list, bb2->list, bb1->num * sizeof(blk_t)) != 0)
315 return 0;
316 return 1;
317}
318
319int ext2fs_badblocks_equal(ext2_badblocks_list bb1, ext2_badblocks_list bb2)
320{
321 return ext2fs_u32_list_equal((ext2_u32_list) bb1,
322 (ext2_u32_list) bb2);
323}
324
325int ext2fs_u32_list_count(ext2_u32_list bb)
326{
327 return bb->num;
328}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/bb_compat.c b/e2fsprogs/old_e2fsprogs/ext2fs/bb_compat.c
deleted file mode 100644
index 419ac7785..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/bb_compat.c
+++ /dev/null
@@ -1,64 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * bb_compat.c --- compatibility badblocks routines
4 *
5 * Copyright (C) 1997 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#include <fcntl.h>
19#include <time.h>
20#if HAVE_SYS_STAT_H
21#include <sys/stat.h>
22#endif
23#if HAVE_SYS_TYPES_H
24#include <sys/types.h>
25#endif
26
27#include "ext2_fs.h"
28#include "ext2fsP.h"
29
30errcode_t badblocks_list_create(badblocks_list *ret, int size)
31{
32 return ext2fs_badblocks_list_create(ret, size);
33}
34
35void badblocks_list_free(badblocks_list bb)
36{
37 ext2fs_badblocks_list_free(bb);
38}
39
40errcode_t badblocks_list_add(badblocks_list bb, blk_t blk)
41{
42 return ext2fs_badblocks_list_add(bb, blk);
43}
44
45int badblocks_list_test(badblocks_list bb, blk_t blk)
46{
47 return ext2fs_badblocks_list_test(bb, blk);
48}
49
50errcode_t badblocks_list_iterate_begin(badblocks_list bb,
51 badblocks_iterate *ret)
52{
53 return ext2fs_badblocks_list_iterate_begin(bb, ret);
54}
55
56int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk)
57{
58 return ext2fs_badblocks_list_iterate(iter, blk);
59}
60
61void badblocks_list_iterate_end(badblocks_iterate iter)
62{
63 ext2fs_badblocks_list_iterate_end(iter);
64}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/bb_inode.c b/e2fsprogs/old_e2fsprogs/ext2fs/bb_inode.c
deleted file mode 100644
index a96789618..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/bb_inode.c
+++ /dev/null
@@ -1,262 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * bb_inode.c --- routines to update the bad block inode.
4 *
5 * WARNING: This routine modifies a lot of state in the filesystem; if
6 * this routine returns an error, the bad block inode may be in an
7 * inconsistent state.
8 *
9 * Copyright (C) 1994, 1995 Theodore Ts'o.
10 *
11 * %Begin-Header%
12 * This file may be redistributed under the terms of the GNU Public
13 * License.
14 * %End-Header%
15 */
16
17#include <stdio.h>
18#include <string.h>
19#if HAVE_UNISTD_H
20#include <unistd.h>
21#endif
22#include <fcntl.h>
23#include <time.h>
24#if HAVE_SYS_STAT_H
25#include <sys/stat.h>
26#endif
27#if HAVE_SYS_TYPES_H
28#include <sys/types.h>
29#endif
30
31#include "ext2_fs.h"
32#include "ext2fs.h"
33
34struct set_badblock_record {
35 ext2_badblocks_iterate bb_iter;
36 int bad_block_count;
37 blk_t *ind_blocks;
38 int max_ind_blocks;
39 int ind_blocks_size;
40 int ind_blocks_ptr;
41 char *block_buf;
42 errcode_t err;
43};
44
45static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
46 e2_blkcnt_t blockcnt,
47 blk_t ref_block, int ref_offset,
48 void *priv_data);
49static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
50 e2_blkcnt_t blockcnt,
51 blk_t ref_block, int ref_offset,
52 void *priv_data);
53
54/*
55 * Given a bad blocks bitmap, update the bad blocks inode to reflect
56 * the map.
57 */
58errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list)
59{
60 errcode_t retval;
61 struct set_badblock_record rec;
62 struct ext2_inode inode;
63
64 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
65
66 if (!fs->block_map)
67 return EXT2_ET_NO_BLOCK_BITMAP;
68
69 rec.bad_block_count = 0;
70 rec.ind_blocks_size = rec.ind_blocks_ptr = 0;
71 rec.max_ind_blocks = 10;
72 retval = ext2fs_get_mem(rec.max_ind_blocks * sizeof(blk_t),
73 &rec.ind_blocks);
74 if (retval)
75 return retval;
76 memset(rec.ind_blocks, 0, rec.max_ind_blocks * sizeof(blk_t));
77 retval = ext2fs_get_mem(fs->blocksize, &rec.block_buf);
78 if (retval)
79 goto cleanup;
80 memset(rec.block_buf, 0, fs->blocksize);
81 rec.err = 0;
82
83 /*
84 * First clear the old bad blocks (while saving the indirect blocks)
85 */
86 retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
87 BLOCK_FLAG_DEPTH_TRAVERSE, 0,
88 clear_bad_block_proc, &rec);
89 if (retval)
90 goto cleanup;
91 if (rec.err) {
92 retval = rec.err;
93 goto cleanup;
94 }
95
96 /*
97 * Now set the bad blocks!
98 *
99 * First, mark the bad blocks as used. This prevents a bad
100 * block from being used as an indirecto block for the bad
101 * block inode (!).
102 */
103 if (bb_list) {
104 retval = ext2fs_badblocks_list_iterate_begin(bb_list,
105 &rec.bb_iter);
106 if (retval)
107 goto cleanup;
108 retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
109 BLOCK_FLAG_APPEND, 0,
110 set_bad_block_proc, &rec);
111 ext2fs_badblocks_list_iterate_end(rec.bb_iter);
112 if (retval)
113 goto cleanup;
114 if (rec.err) {
115 retval = rec.err;
116 goto cleanup;
117 }
118 }
119
120 /*
121 * Update the bad block inode's mod time and block count
122 * field.
123 */
124 retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode);
125 if (retval)
126 goto cleanup;
127
128 inode.i_atime = inode.i_mtime = time(NULL);
129 if (!inode.i_ctime)
130 inode.i_ctime = time(NULL);
131 inode.i_blocks = rec.bad_block_count * (fs->blocksize / 512);
132 inode.i_size = rec.bad_block_count * fs->blocksize;
133
134 retval = ext2fs_write_inode(fs, EXT2_BAD_INO, &inode);
135 if (retval)
136 goto cleanup;
137
138cleanup:
139 ext2fs_free_mem(&rec.ind_blocks);
140 ext2fs_free_mem(&rec.block_buf);
141 return retval;
142}
143
144/*
145 * Helper function for update_bb_inode()
146 *
147 * Clear the bad blocks in the bad block inode, while saving the
148 * indirect blocks.
149 */
150#ifdef __TURBOC__
151# pragma argsused
152#endif
153static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
154 e2_blkcnt_t blockcnt,
155 blk_t ref_block EXT2FS_ATTR((unused)),
156 int ref_offset EXT2FS_ATTR((unused)),
157 void *priv_data)
158{
159 struct set_badblock_record *rec = (struct set_badblock_record *)
160 priv_data;
161 errcode_t retval;
162 unsigned long old_size;
163
164 if (!*block_nr)
165 return 0;
166
167 /*
168 * If the block number is outrageous, clear it and ignore it.
169 */
170 if (*block_nr >= fs->super->s_blocks_count ||
171 *block_nr < fs->super->s_first_data_block) {
172 *block_nr = 0;
173 return BLOCK_CHANGED;
174 }
175
176 if (blockcnt < 0) {
177 if (rec->ind_blocks_size >= rec->max_ind_blocks) {
178 old_size = rec->max_ind_blocks * sizeof(blk_t);
179 rec->max_ind_blocks += 10;
180 retval = ext2fs_resize_mem(old_size,
181 rec->max_ind_blocks * sizeof(blk_t),
182 &rec->ind_blocks);
183 if (retval) {
184 rec->max_ind_blocks -= 10;
185 rec->err = retval;
186 return BLOCK_ABORT;
187 }
188 }
189 rec->ind_blocks[rec->ind_blocks_size++] = *block_nr;
190 }
191
192 /*
193 * Mark the block as unused, and update accounting information
194 */
195 ext2fs_block_alloc_stats(fs, *block_nr, -1);
196
197 *block_nr = 0;
198 return BLOCK_CHANGED;
199}
200
201
202/*
203 * Helper function for update_bb_inode()
204 *
205 * Set the block list in the bad block inode, using the supplied bitmap.
206 */
207#ifdef __TURBOC__
208 #pragma argsused
209#endif
210static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
211 e2_blkcnt_t blockcnt,
212 blk_t ref_block EXT2FS_ATTR((unused)),
213 int ref_offset EXT2FS_ATTR((unused)),
214 void *priv_data)
215{
216 struct set_badblock_record *rec = (struct set_badblock_record *)
217 priv_data;
218 errcode_t retval;
219 blk_t blk;
220
221 if (blockcnt >= 0) {
222 /*
223 * Get the next bad block.
224 */
225 if (!ext2fs_badblocks_list_iterate(rec->bb_iter, &blk))
226 return BLOCK_ABORT;
227 rec->bad_block_count++;
228 } else {
229 /*
230 * An indirect block; fetch a block from the
231 * previously used indirect block list. The block
232 * most be not marked as used; if so, get another one.
233 * If we run out of reserved indirect blocks, allocate
234 * a new one.
235 */
236 retry:
237 if (rec->ind_blocks_ptr < rec->ind_blocks_size) {
238 blk = rec->ind_blocks[rec->ind_blocks_ptr++];
239 if (ext2fs_test_block_bitmap(fs->block_map, blk))
240 goto retry;
241 } else {
242 retval = ext2fs_new_block(fs, 0, 0, &blk);
243 if (retval) {
244 rec->err = retval;
245 return BLOCK_ABORT;
246 }
247 }
248 retval = io_channel_write_blk(fs->io, blk, 1, rec->block_buf);
249 if (retval) {
250 rec->err = retval;
251 return BLOCK_ABORT;
252 }
253 }
254
255 /*
256 * Update block counts
257 */
258 ext2fs_block_alloc_stats(fs, blk, +1);
259
260 *block_nr = blk;
261 return BLOCK_CHANGED;
262}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/bitmaps.c b/e2fsprogs/old_e2fsprogs/ext2fs/bitmaps.c
deleted file mode 100644
index 637ed27af..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/bitmaps.c
+++ /dev/null
@@ -1,211 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * bitmaps.c --- routines to read, write, and manipulate the inode and
4 * block bitmaps.
5 *
6 * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the GNU Public
10 * License.
11 * %End-Header%
12 */
13
14#include <stdio.h>
15#include <string.h>
16#if HAVE_UNISTD_H
17#include <unistd.h>
18#endif
19#include <fcntl.h>
20#include <time.h>
21#if HAVE_SYS_STAT_H
22#include <sys/stat.h>
23#endif
24#if HAVE_SYS_TYPES_H
25#include <sys/types.h>
26#endif
27
28#include "ext2_fs.h"
29#include "ext2fs.h"
30
31static errcode_t make_bitmap(__u32 start, __u32 end, __u32 real_end,
32 const char *descr, char *init_map,
33 ext2fs_generic_bitmap *ret)
34{
35 ext2fs_generic_bitmap bitmap;
36 errcode_t retval;
37 size_t size;
38
39 retval = ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap),
40 &bitmap);
41 if (retval)
42 return retval;
43
44 bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
45 bitmap->fs = NULL;
46 bitmap->start = start;
47 bitmap->end = end;
48 bitmap->real_end = real_end;
49 bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK;
50 if (descr) {
51 retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description);
52 if (retval) {
53 ext2fs_free_mem(&bitmap);
54 return retval;
55 }
56 strcpy(bitmap->description, descr);
57 } else
58 bitmap->description = 0;
59
60 size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1);
61 retval = ext2fs_get_mem(size, &bitmap->bitmap);
62 if (retval) {
63 ext2fs_free_mem(&bitmap->description);
64 ext2fs_free_mem(&bitmap);
65 return retval;
66 }
67
68 if (init_map)
69 memcpy(bitmap->bitmap, init_map, size);
70 else
71 memset(bitmap->bitmap, 0, size);
72 *ret = bitmap;
73 return 0;
74}
75
76errcode_t ext2fs_allocate_generic_bitmap(__u32 start,
77 __u32 end,
78 __u32 real_end,
79 const char *descr,
80 ext2fs_generic_bitmap *ret)
81{
82 return make_bitmap(start, end, real_end, descr, 0, ret);
83}
84
85errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
86 ext2fs_generic_bitmap *dest)
87{
88 errcode_t retval;
89 ext2fs_generic_bitmap new_map;
90
91 retval = make_bitmap(src->start, src->end, src->real_end,
92 src->description, src->bitmap, &new_map);
93 if (retval)
94 return retval;
95 new_map->magic = src->magic;
96 new_map->fs = src->fs;
97 new_map->base_error_code = src->base_error_code;
98 *dest = new_map;
99 return 0;
100}
101
102void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map)
103{
104 __u32 i, j;
105
106 for (i=map->end+1, j = i - map->start; i <= map->real_end; i++, j++)
107 ext2fs_set_bit(j, map->bitmap);
108}
109
110errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs,
111 const char *descr,
112 ext2fs_inode_bitmap *ret)
113{
114 ext2fs_inode_bitmap bitmap;
115 errcode_t retval;
116 __u32 start, end, real_end;
117
118 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
119
120 fs->write_bitmaps = ext2fs_write_bitmaps;
121
122 start = 1;
123 end = fs->super->s_inodes_count;
124 real_end = (EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count);
125
126 retval = ext2fs_allocate_generic_bitmap(start, end, real_end,
127 descr, &bitmap);
128 if (retval)
129 return retval;
130
131 bitmap->magic = EXT2_ET_MAGIC_INODE_BITMAP;
132 bitmap->fs = fs;
133 bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK;
134
135 *ret = bitmap;
136 return 0;
137}
138
139errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
140 const char *descr,
141 ext2fs_block_bitmap *ret)
142{
143 ext2fs_block_bitmap bitmap;
144 errcode_t retval;
145 __u32 start, end, real_end;
146
147 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
148
149 fs->write_bitmaps = ext2fs_write_bitmaps;
150
151 start = fs->super->s_first_data_block;
152 end = fs->super->s_blocks_count-1;
153 real_end = (EXT2_BLOCKS_PER_GROUP(fs->super)
154 * fs->group_desc_count)-1 + start;
155
156 retval = ext2fs_allocate_generic_bitmap(start, end, real_end,
157 descr, &bitmap);
158 if (retval)
159 return retval;
160
161 bitmap->magic = EXT2_ET_MAGIC_BLOCK_BITMAP;
162 bitmap->fs = fs;
163 bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK;
164
165 *ret = bitmap;
166 return 0;
167}
168
169errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap,
170 ext2_ino_t end, ext2_ino_t *oend)
171{
172 EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_INODE_BITMAP);
173
174 if (end > bitmap->real_end)
175 return EXT2_ET_FUDGE_INODE_BITMAP_END;
176 if (oend)
177 *oend = bitmap->end;
178 bitmap->end = end;
179 return 0;
180}
181
182errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap,
183 blk_t end, blk_t *oend)
184{
185 EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_BLOCK_BITMAP);
186
187 if (end > bitmap->real_end)
188 return EXT2_ET_FUDGE_BLOCK_BITMAP_END;
189 if (oend)
190 *oend = bitmap->end;
191 bitmap->end = end;
192 return 0;
193}
194
195void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap)
196{
197 if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_INODE_BITMAP))
198 return;
199
200 memset(bitmap->bitmap, 0,
201 (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
202}
203
204void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap)
205{
206 if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_BLOCK_BITMAP))
207 return;
208
209 memset(bitmap->bitmap, 0,
210 (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
211}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/bitops.c b/e2fsprogs/old_e2fsprogs/ext2fs/bitops.c
deleted file mode 100644
index 3d08394d8..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/bitops.c
+++ /dev/null
@@ -1,90 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * bitops.c --- Bitmap frobbing code. See bitops.h for the inlined
4 * routines.
5 *
6 * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the GNU Public
10 * License.
11 * %End-Header%
12 */
13
14#include <stdio.h>
15#if HAVE_SYS_TYPES_H
16#include <sys/types.h>
17#endif
18
19#include "ext2_fs.h"
20#include "ext2fs.h"
21
22#ifndef _EXT2_HAVE_ASM_BITOPS_
23
24/*
25 * For the benefit of those who are trying to port Linux to another
26 * architecture, here are some C-language equivalents. You should
27 * recode these in the native assmebly language, if at all possible.
28 *
29 * C language equivalents written by Theodore Ts'o, 9/26/92.
30 * Modified by Pete A. Zaitcev 7/14/95 to be portable to big endian
31 * systems, as well as non-32 bit systems.
32 */
33
34int ext2fs_set_bit(unsigned int nr,void * addr)
35{
36 int mask, retval;
37 unsigned char *ADDR = (unsigned char *) addr;
38
39 ADDR += nr >> 3;
40 mask = 1 << (nr & 0x07);
41 retval = mask & *ADDR;
42 *ADDR |= mask;
43 return retval;
44}
45
46int ext2fs_clear_bit(unsigned int nr, void * addr)
47{
48 int mask, retval;
49 unsigned char *ADDR = (unsigned char *) addr;
50
51 ADDR += nr >> 3;
52 mask = 1 << (nr & 0x07);
53 retval = mask & *ADDR;
54 *ADDR &= ~mask;
55 return retval;
56}
57
58int ext2fs_test_bit(unsigned int nr, const void * addr)
59{
60 int mask;
61 const unsigned char *ADDR = (const unsigned char *) addr;
62
63 ADDR += nr >> 3;
64 mask = 1 << (nr & 0x07);
65 return (mask & *ADDR);
66}
67
68#endif /* !_EXT2_HAVE_ASM_BITOPS_ */
69
70void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
71 const char *description)
72{
73#ifndef OMIT_COM_ERR
74 if (description)
75 bb_error_msg("#%lu for %s", arg, description);
76 else
77 bb_error_msg("#%lu", arg);
78#endif
79}
80
81void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
82 int code, unsigned long arg)
83{
84#ifndef OMIT_COM_ERR
85 if (bitmap->description)
86 bb_error_msg("#%lu for %s", arg, bitmap->description);
87 else
88 bb_error_msg("#%lu", arg);
89#endif
90}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/bitops.h b/e2fsprogs/old_e2fsprogs/ext2fs/bitops.h
deleted file mode 100644
index 7271a497b..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/bitops.h
+++ /dev/null
@@ -1,105 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * bitops.h --- Bitmap frobbing code. The byte swapping routines are
4 * also included here.
5 *
6 * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the GNU Public
10 * License.
11 * %End-Header%
12 *
13 * i386 bitops operations taken from <asm/bitops.h>, Copyright 1992,
14 * Linus Torvalds.
15 */
16#include <string.h>
17
18extern int ext2fs_set_bit(unsigned int nr,void * addr);
19extern int ext2fs_clear_bit(unsigned int nr, void * addr);
20extern int ext2fs_test_bit(unsigned int nr, const void * addr);
21extern __u16 ext2fs_swab16(__u16 val);
22extern __u32 ext2fs_swab32(__u32 val);
23
24#ifdef WORDS_BIGENDIAN
25#define ext2fs_cpu_to_le32(x) ext2fs_swab32((x))
26#define ext2fs_le32_to_cpu(x) ext2fs_swab32((x))
27#define ext2fs_cpu_to_le16(x) ext2fs_swab16((x))
28#define ext2fs_le16_to_cpu(x) ext2fs_swab16((x))
29#define ext2fs_cpu_to_be32(x) ((__u32)(x))
30#define ext2fs_be32_to_cpu(x) ((__u32)(x))
31#define ext2fs_cpu_to_be16(x) ((__u16)(x))
32#define ext2fs_be16_to_cpu(x) ((__u16)(x))
33#else
34#define ext2fs_cpu_to_le32(x) ((__u32)(x))
35#define ext2fs_le32_to_cpu(x) ((__u32)(x))
36#define ext2fs_cpu_to_le16(x) ((__u16)(x))
37#define ext2fs_le16_to_cpu(x) ((__u16)(x))
38#define ext2fs_cpu_to_be32(x) ext2fs_swab32((x))
39#define ext2fs_be32_to_cpu(x) ext2fs_swab32((x))
40#define ext2fs_cpu_to_be16(x) ext2fs_swab16((x))
41#define ext2fs_be16_to_cpu(x) ext2fs_swab16((x))
42#endif
43
44/*
45 * EXT2FS bitmap manipulation routines.
46 */
47
48/* Support for sending warning messages from the inline subroutines */
49extern const char *ext2fs_block_string;
50extern const char *ext2fs_inode_string;
51extern const char *ext2fs_mark_string;
52extern const char *ext2fs_unmark_string;
53extern const char *ext2fs_test_string;
54extern void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
55 const char *description);
56extern void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
57 int code, unsigned long arg);
58
59extern int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
60extern int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
61 blk_t block);
62extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
63
64extern int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
65extern int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
66 ext2_ino_t inode);
67extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
68
69extern void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
70 blk_t block);
71extern void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
72 blk_t block);
73extern int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
74 blk_t block);
75
76extern void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
77 ext2_ino_t inode);
78extern void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
79 ext2_ino_t inode);
80extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
81 ext2_ino_t inode);
82extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap);
83extern ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap);
84extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap);
85extern ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap);
86
87extern void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
88 blk_t block, int num);
89extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
90 blk_t block, int num);
91extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
92 blk_t block, int num);
93extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
94 blk_t block, int num);
95extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
96 blk_t block, int num);
97extern int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
98 blk_t block, int num);
99extern void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map);
100
101/* These two routines moved to gen_bitmap.c */
102extern int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
103 __u32 bitno);
104extern int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
105 blk_t bitno);
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/block.c b/e2fsprogs/old_e2fsprogs/ext2fs/block.c
deleted file mode 100644
index dbd04f846..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/block.c
+++ /dev/null
@@ -1,437 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * block.c --- iterate over all blocks in an inode
4 *
5 * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18
19#include "ext2_fs.h"
20#include "ext2fs.h"
21
22struct block_context {
23 ext2_filsys fs;
24 int (*func)(ext2_filsys fs,
25 blk_t *blocknr,
26 e2_blkcnt_t bcount,
27 blk_t ref_blk,
28 int ref_offset,
29 void *priv_data);
30 e2_blkcnt_t bcount;
31 int bsize;
32 int flags;
33 errcode_t errcode;
34 char *ind_buf;
35 char *dind_buf;
36 char *tind_buf;
37 void *priv_data;
38};
39
40static int block_iterate_ind(blk_t *ind_block, blk_t ref_block,
41 int ref_offset, struct block_context *ctx)
42{
43 int ret = 0, changed = 0;
44 int i, flags, limit, offset;
45 blk_t *block_nr;
46
47 limit = ctx->fs->blocksize >> 2;
48 if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
49 !(ctx->flags & BLOCK_FLAG_DATA_ONLY))
50 ret = (*ctx->func)(ctx->fs, ind_block,
51 BLOCK_COUNT_IND, ref_block,
52 ref_offset, ctx->priv_data);
53 if (!*ind_block || (ret & BLOCK_ABORT)) {
54 ctx->bcount += limit;
55 return ret;
56 }
57 if (*ind_block >= ctx->fs->super->s_blocks_count ||
58 *ind_block < ctx->fs->super->s_first_data_block) {
59 ctx->errcode = EXT2_ET_BAD_IND_BLOCK;
60 ret |= BLOCK_ERROR;
61 return ret;
62 }
63 ctx->errcode = ext2fs_read_ind_block(ctx->fs, *ind_block,
64 ctx->ind_buf);
65 if (ctx->errcode) {
66 ret |= BLOCK_ERROR;
67 return ret;
68 }
69
70 block_nr = (blk_t *) ctx->ind_buf;
71 offset = 0;
72 if (ctx->flags & BLOCK_FLAG_APPEND) {
73 for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
74 flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
75 *ind_block, offset,
76 ctx->priv_data);
77 changed |= flags;
78 if (flags & BLOCK_ABORT) {
79 ret |= BLOCK_ABORT;
80 break;
81 }
82 offset += sizeof(blk_t);
83 }
84 } else {
85 for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
86 if (*block_nr == 0)
87 continue;
88 flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
89 *ind_block, offset,
90 ctx->priv_data);
91 changed |= flags;
92 if (flags & BLOCK_ABORT) {
93 ret |= BLOCK_ABORT;
94 break;
95 }
96 offset += sizeof(blk_t);
97 }
98 }
99 if (changed & BLOCK_CHANGED) {
100 ctx->errcode = ext2fs_write_ind_block(ctx->fs, *ind_block,
101 ctx->ind_buf);
102 if (ctx->errcode)
103 ret |= BLOCK_ERROR | BLOCK_ABORT;
104 }
105 if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
106 !(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
107 !(ret & BLOCK_ABORT))
108 ret |= (*ctx->func)(ctx->fs, ind_block,
109 BLOCK_COUNT_IND, ref_block,
110 ref_offset, ctx->priv_data);
111 return ret;
112}
113
114static int block_iterate_dind(blk_t *dind_block, blk_t ref_block,
115 int ref_offset, struct block_context *ctx)
116{
117 int ret = 0, changed = 0;
118 int i, flags, limit, offset;
119 blk_t *block_nr;
120
121 limit = ctx->fs->blocksize >> 2;
122 if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE |
123 BLOCK_FLAG_DATA_ONLY)))
124 ret = (*ctx->func)(ctx->fs, dind_block,
125 BLOCK_COUNT_DIND, ref_block,
126 ref_offset, ctx->priv_data);
127 if (!*dind_block || (ret & BLOCK_ABORT)) {
128 ctx->bcount += limit*limit;
129 return ret;
130 }
131 if (*dind_block >= ctx->fs->super->s_blocks_count ||
132 *dind_block < ctx->fs->super->s_first_data_block) {
133 ctx->errcode = EXT2_ET_BAD_DIND_BLOCK;
134 ret |= BLOCK_ERROR;
135 return ret;
136 }
137 ctx->errcode = ext2fs_read_ind_block(ctx->fs, *dind_block,
138 ctx->dind_buf);
139 if (ctx->errcode) {
140 ret |= BLOCK_ERROR;
141 return ret;
142 }
143
144 block_nr = (blk_t *) ctx->dind_buf;
145 offset = 0;
146 if (ctx->flags & BLOCK_FLAG_APPEND) {
147 for (i = 0; i < limit; i++, block_nr++) {
148 flags = block_iterate_ind(block_nr,
149 *dind_block, offset,
150 ctx);
151 changed |= flags;
152 if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
153 ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
154 break;
155 }
156 offset += sizeof(blk_t);
157 }
158 } else {
159 for (i = 0; i < limit; i++, block_nr++) {
160 if (*block_nr == 0) {
161 ctx->bcount += limit;
162 continue;
163 }
164 flags = block_iterate_ind(block_nr,
165 *dind_block, offset,
166 ctx);
167 changed |= flags;
168 if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
169 ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
170 break;
171 }
172 offset += sizeof(blk_t);
173 }
174 }
175 if (changed & BLOCK_CHANGED) {
176 ctx->errcode = ext2fs_write_ind_block(ctx->fs, *dind_block,
177 ctx->dind_buf);
178 if (ctx->errcode)
179 ret |= BLOCK_ERROR | BLOCK_ABORT;
180 }
181 if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
182 !(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
183 !(ret & BLOCK_ABORT))
184 ret |= (*ctx->func)(ctx->fs, dind_block,
185 BLOCK_COUNT_DIND, ref_block,
186 ref_offset, ctx->priv_data);
187 return ret;
188}
189
190static int block_iterate_tind(blk_t *tind_block, blk_t ref_block,
191 int ref_offset, struct block_context *ctx)
192{
193 int ret = 0, changed = 0;
194 int i, flags, limit, offset;
195 blk_t *block_nr;
196
197 limit = ctx->fs->blocksize >> 2;
198 if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE |
199 BLOCK_FLAG_DATA_ONLY)))
200 ret = (*ctx->func)(ctx->fs, tind_block,
201 BLOCK_COUNT_TIND, ref_block,
202 ref_offset, ctx->priv_data);
203 if (!*tind_block || (ret & BLOCK_ABORT)) {
204 ctx->bcount += limit*limit*limit;
205 return ret;
206 }
207 if (*tind_block >= ctx->fs->super->s_blocks_count ||
208 *tind_block < ctx->fs->super->s_first_data_block) {
209 ctx->errcode = EXT2_ET_BAD_TIND_BLOCK;
210 ret |= BLOCK_ERROR;
211 return ret;
212 }
213 ctx->errcode = ext2fs_read_ind_block(ctx->fs, *tind_block,
214 ctx->tind_buf);
215 if (ctx->errcode) {
216 ret |= BLOCK_ERROR;
217 return ret;
218 }
219
220 block_nr = (blk_t *) ctx->tind_buf;
221 offset = 0;
222 if (ctx->flags & BLOCK_FLAG_APPEND) {
223 for (i = 0; i < limit; i++, block_nr++) {
224 flags = block_iterate_dind(block_nr,
225 *tind_block,
226 offset, ctx);
227 changed |= flags;
228 if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
229 ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
230 break;
231 }
232 offset += sizeof(blk_t);
233 }
234 } else {
235 for (i = 0; i < limit; i++, block_nr++) {
236 if (*block_nr == 0) {
237 ctx->bcount += limit*limit;
238 continue;
239 }
240 flags = block_iterate_dind(block_nr,
241 *tind_block,
242 offset, ctx);
243 changed |= flags;
244 if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
245 ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
246 break;
247 }
248 offset += sizeof(blk_t);
249 }
250 }
251 if (changed & BLOCK_CHANGED) {
252 ctx->errcode = ext2fs_write_ind_block(ctx->fs, *tind_block,
253 ctx->tind_buf);
254 if (ctx->errcode)
255 ret |= BLOCK_ERROR | BLOCK_ABORT;
256 }
257 if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
258 !(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
259 !(ret & BLOCK_ABORT))
260 ret |= (*ctx->func)(ctx->fs, tind_block,
261 BLOCK_COUNT_TIND, ref_block,
262 ref_offset, ctx->priv_data);
263
264 return ret;
265}
266
267errcode_t ext2fs_block_iterate2(ext2_filsys fs,
268 ext2_ino_t ino,
269 int flags,
270 char *block_buf,
271 int (*func)(ext2_filsys fs,
272 blk_t *blocknr,
273 e2_blkcnt_t blockcnt,
274 blk_t ref_blk,
275 int ref_offset,
276 void *priv_data),
277 void *priv_data)
278{
279 int i;
280 int got_inode = 0;
281 int ret = 0;
282 blk_t blocks[EXT2_N_BLOCKS]; /* directory data blocks */
283 struct ext2_inode inode;
284 errcode_t retval;
285 struct block_context ctx;
286 int limit;
287
288 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
289
290 /*
291 * Check to see if we need to limit large files
292 */
293 if (flags & BLOCK_FLAG_NO_LARGE) {
294 ctx.errcode = ext2fs_read_inode(fs, ino, &inode);
295 if (ctx.errcode)
296 return ctx.errcode;
297 got_inode = 1;
298 if (!LINUX_S_ISDIR(inode.i_mode) &&
299 (inode.i_size_high != 0))
300 return EXT2_ET_FILE_TOO_BIG;
301 }
302
303 retval = ext2fs_get_blocks(fs, ino, blocks);
304 if (retval)
305 return retval;
306
307 limit = fs->blocksize >> 2;
308
309 ctx.fs = fs;
310 ctx.func = func;
311 ctx.priv_data = priv_data;
312 ctx.flags = flags;
313 ctx.bcount = 0;
314 if (block_buf) {
315 ctx.ind_buf = block_buf;
316 } else {
317 retval = ext2fs_get_mem(fs->blocksize * 3, &ctx.ind_buf);
318 if (retval)
319 return retval;
320 }
321 ctx.dind_buf = ctx.ind_buf + fs->blocksize;
322 ctx.tind_buf = ctx.dind_buf + fs->blocksize;
323
324 /*
325 * Iterate over the HURD translator block (if present)
326 */
327 if ((fs->super->s_creator_os == EXT2_OS_HURD) &&
328 !(flags & BLOCK_FLAG_DATA_ONLY)) {
329 ctx.errcode = ext2fs_read_inode(fs, ino, &inode);
330 if (ctx.errcode)
331 goto abort_exit;
332 got_inode = 1;
333 if (inode.osd1.hurd1.h_i_translator) {
334 ret |= (*ctx.func)(fs,
335 &inode.osd1.hurd1.h_i_translator,
336 BLOCK_COUNT_TRANSLATOR,
337 0, 0, priv_data);
338 if (ret & BLOCK_ABORT)
339 goto abort_exit;
340 }
341 }
342
343 /*
344 * Iterate over normal data blocks
345 */
346 for (i = 0; i < EXT2_NDIR_BLOCKS; i++, ctx.bcount++) {
347 if (blocks[i] || (flags & BLOCK_FLAG_APPEND)) {
348 ret |= (*ctx.func)(fs, &blocks[i],
349 ctx.bcount, 0, i, priv_data);
350 if (ret & BLOCK_ABORT)
351 goto abort_exit;
352 }
353 }
354 if (*(blocks + EXT2_IND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
355 ret |= block_iterate_ind(blocks + EXT2_IND_BLOCK,
356 0, EXT2_IND_BLOCK, &ctx);
357 if (ret & BLOCK_ABORT)
358 goto abort_exit;
359 } else
360 ctx.bcount += limit;
361 if (*(blocks + EXT2_DIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
362 ret |= block_iterate_dind(blocks + EXT2_DIND_BLOCK,
363 0, EXT2_DIND_BLOCK, &ctx);
364 if (ret & BLOCK_ABORT)
365 goto abort_exit;
366 } else
367 ctx.bcount += limit * limit;
368 if (*(blocks + EXT2_TIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
369 ret |= block_iterate_tind(blocks + EXT2_TIND_BLOCK,
370 0, EXT2_TIND_BLOCK, &ctx);
371 if (ret & BLOCK_ABORT)
372 goto abort_exit;
373 }
374
375abort_exit:
376 if (ret & BLOCK_CHANGED) {
377 if (!got_inode) {
378 retval = ext2fs_read_inode(fs, ino, &inode);
379 if (retval)
380 return retval;
381 }
382 for (i=0; i < EXT2_N_BLOCKS; i++)
383 inode.i_block[i] = blocks[i];
384 retval = ext2fs_write_inode(fs, ino, &inode);
385 if (retval)
386 return retval;
387 }
388
389 if (!block_buf)
390 ext2fs_free_mem(&ctx.ind_buf);
391
392 return (ret & BLOCK_ERROR) ? ctx.errcode : 0;
393}
394
395/*
396 * Emulate the old ext2fs_block_iterate function!
397 */
398
399struct xlate {
400 int (*func)(ext2_filsys fs,
401 blk_t *blocknr,
402 int bcount,
403 void *priv_data);
404 void *real_private;
405};
406
407#ifdef __TURBOC__
408# pragma argsused
409#endif
410static int xlate_func(ext2_filsys fs, blk_t *blocknr, e2_blkcnt_t blockcnt,
411 blk_t ref_block EXT2FS_ATTR((unused)),
412 int ref_offset EXT2FS_ATTR((unused)),
413 void *priv_data)
414{
415 struct xlate *xl = (struct xlate *) priv_data;
416
417 return (*xl->func)(fs, blocknr, (int) blockcnt, xl->real_private);
418}
419
420errcode_t ext2fs_block_iterate(ext2_filsys fs,
421 ext2_ino_t ino,
422 int flags,
423 char *block_buf,
424 int (*func)(ext2_filsys fs,
425 blk_t *blocknr,
426 int blockcnt,
427 void *priv_data),
428 void *priv_data)
429{
430 struct xlate xl;
431
432 xl.real_private = priv_data;
433 xl.func = func;
434
435 return ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_NO_LARGE | flags,
436 block_buf, xlate_func, &xl);
437}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/bmap.c b/e2fsprogs/old_e2fsprogs/ext2fs/bmap.c
deleted file mode 100644
index 796b0e4f5..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/bmap.c
+++ /dev/null
@@ -1,261 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * bmap.c --- logical to physical block mapping
4 *
5 * Copyright (C) 1997 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18
19#include "ext2_fs.h"
20#include "ext2fs.h"
21
22extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino,
23 struct ext2_inode *inode,
24 char *block_buf, int bmap_flags,
25 blk_t block, blk_t *phys_blk);
26
27#define inode_bmap(inode, nr) ((inode)->i_block[(nr)])
28
29static errcode_t block_ind_bmap(ext2_filsys fs, int flags,
30 blk_t ind, char *block_buf,
31 int *blocks_alloc,
32 blk_t nr, blk_t *ret_blk)
33{
34 errcode_t retval;
35 blk_t b;
36
37 if (!ind) {
38 if (flags & BMAP_SET)
39 return EXT2_ET_SET_BMAP_NO_IND;
40 *ret_blk = 0;
41 return 0;
42 }
43 retval = io_channel_read_blk(fs->io, ind, 1, block_buf);
44 if (retval)
45 return retval;
46
47 if (flags & BMAP_SET) {
48 b = *ret_blk;
49#if BB_BIG_ENDIAN
50 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
51 (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
52 b = ext2fs_swab32(b);
53#endif
54 ((blk_t *) block_buf)[nr] = b;
55 return io_channel_write_blk(fs->io, ind, 1, block_buf);
56 }
57
58 b = ((blk_t *) block_buf)[nr];
59
60#if BB_BIG_ENDIAN
61 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
62 (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
63 b = ext2fs_swab32(b);
64#endif
65
66 if (!b && (flags & BMAP_ALLOC)) {
67 b = nr ? ((blk_t *) block_buf)[nr-1] : 0;
68 retval = ext2fs_alloc_block(fs, b,
69 block_buf + fs->blocksize, &b);
70 if (retval)
71 return retval;
72
73#if BB_BIG_ENDIAN
74 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
75 (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
76 ((blk_t *) block_buf)[nr] = ext2fs_swab32(b);
77 else
78#endif
79 ((blk_t *) block_buf)[nr] = b;
80
81 retval = io_channel_write_blk(fs->io, ind, 1, block_buf);
82 if (retval)
83 return retval;
84
85 (*blocks_alloc)++;
86 }
87
88 *ret_blk = b;
89 return 0;
90}
91
92static errcode_t block_dind_bmap(ext2_filsys fs, int flags,
93 blk_t dind, char *block_buf,
94 int *blocks_alloc,
95 blk_t nr, blk_t *ret_blk)
96{
97 blk_t b;
98 errcode_t retval;
99 blk_t addr_per_block;
100
101 addr_per_block = (blk_t) fs->blocksize >> 2;
102
103 retval = block_ind_bmap(fs, flags & ~BMAP_SET, dind, block_buf,
104 blocks_alloc, nr / addr_per_block, &b);
105 if (retval)
106 return retval;
107 retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc,
108 nr % addr_per_block, ret_blk);
109 return retval;
110}
111
112static errcode_t block_tind_bmap(ext2_filsys fs, int flags,
113 blk_t tind, char *block_buf,
114 int *blocks_alloc,
115 blk_t nr, blk_t *ret_blk)
116{
117 blk_t b;
118 errcode_t retval;
119 blk_t addr_per_block;
120
121 addr_per_block = (blk_t) fs->blocksize >> 2;
122
123 retval = block_dind_bmap(fs, flags & ~BMAP_SET, tind, block_buf,
124 blocks_alloc, nr / addr_per_block, &b);
125 if (retval)
126 return retval;
127 retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc,
128 nr % addr_per_block, ret_blk);
129 return retval;
130}
131
132errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode,
133 char *block_buf, int bmap_flags, blk_t block,
134 blk_t *phys_blk)
135{
136 struct ext2_inode inode_buf;
137 blk_t addr_per_block;
138 blk_t b;
139 char *buf = NULL;
140 errcode_t retval = 0;
141 int blocks_alloc = 0, inode_dirty = 0;
142
143 if (!(bmap_flags & BMAP_SET))
144 *phys_blk = 0;
145
146 /* Read inode structure if necessary */
147 if (!inode) {
148 retval = ext2fs_read_inode(fs, ino, &inode_buf);
149 if (retval)
150 return retval;
151 inode = &inode_buf;
152 }
153 addr_per_block = (blk_t) fs->blocksize >> 2;
154
155 if (!block_buf) {
156 retval = ext2fs_get_mem(fs->blocksize * 2, &buf);
157 if (retval)
158 return retval;
159 block_buf = buf;
160 }
161
162 if (block < EXT2_NDIR_BLOCKS) {
163 if (bmap_flags & BMAP_SET) {
164 b = *phys_blk;
165#if BB_BIG_ENDIAN
166 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
167 (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
168 b = ext2fs_swab32(b);
169#endif
170 inode_bmap(inode, block) = b;
171 inode_dirty++;
172 goto done;
173 }
174
175 *phys_blk = inode_bmap(inode, block);
176 b = block ? inode_bmap(inode, block-1) : 0;
177
178 if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) {
179 retval = ext2fs_alloc_block(fs, b, block_buf, &b);
180 if (retval)
181 goto done;
182 inode_bmap(inode, block) = b;
183 blocks_alloc++;
184 *phys_blk = b;
185 }
186 goto done;
187 }
188
189 /* Indirect block */
190 block -= EXT2_NDIR_BLOCKS;
191 if (block < addr_per_block) {
192 b = inode_bmap(inode, EXT2_IND_BLOCK);
193 if (!b) {
194 if (!(bmap_flags & BMAP_ALLOC)) {
195 if (bmap_flags & BMAP_SET)
196 retval = EXT2_ET_SET_BMAP_NO_IND;
197 goto done;
198 }
199
200 b = inode_bmap(inode, EXT2_IND_BLOCK-1);
201 retval = ext2fs_alloc_block(fs, b, block_buf, &b);
202 if (retval)
203 goto done;
204 inode_bmap(inode, EXT2_IND_BLOCK) = b;
205 blocks_alloc++;
206 }
207 retval = block_ind_bmap(fs, bmap_flags, b, block_buf,
208 &blocks_alloc, block, phys_blk);
209 goto done;
210 }
211
212 /* Doubly indirect block */
213 block -= addr_per_block;
214 if (block < addr_per_block * addr_per_block) {
215 b = inode_bmap(inode, EXT2_DIND_BLOCK);
216 if (!b) {
217 if (!(bmap_flags & BMAP_ALLOC)) {
218 if (bmap_flags & BMAP_SET)
219 retval = EXT2_ET_SET_BMAP_NO_IND;
220 goto done;
221 }
222
223 b = inode_bmap(inode, EXT2_IND_BLOCK);
224 retval = ext2fs_alloc_block(fs, b, block_buf, &b);
225 if (retval)
226 goto done;
227 inode_bmap(inode, EXT2_DIND_BLOCK) = b;
228 blocks_alloc++;
229 }
230 retval = block_dind_bmap(fs, bmap_flags, b, block_buf,
231 &blocks_alloc, block, phys_blk);
232 goto done;
233 }
234
235 /* Triply indirect block */
236 block -= addr_per_block * addr_per_block;
237 b = inode_bmap(inode, EXT2_TIND_BLOCK);
238 if (!b) {
239 if (!(bmap_flags & BMAP_ALLOC)) {
240 if (bmap_flags & BMAP_SET)
241 retval = EXT2_ET_SET_BMAP_NO_IND;
242 goto done;
243 }
244
245 b = inode_bmap(inode, EXT2_DIND_BLOCK);
246 retval = ext2fs_alloc_block(fs, b, block_buf, &b);
247 if (retval)
248 goto done;
249 inode_bmap(inode, EXT2_TIND_BLOCK) = b;
250 blocks_alloc++;
251 }
252 retval = block_tind_bmap(fs, bmap_flags, b, block_buf,
253 &blocks_alloc, block, phys_blk);
254done:
255 ext2fs_free_mem(&buf);
256 if ((retval == 0) && (blocks_alloc || inode_dirty)) {
257 inode->i_blocks += (blocks_alloc * fs->blocksize) / 512;
258 retval = ext2fs_write_inode(fs, ino, inode);
259 }
260 return retval;
261}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/bmove.c b/e2fsprogs/old_e2fsprogs/ext2fs/bmove.c
deleted file mode 100644
index ec9244d0b..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/bmove.c
+++ /dev/null
@@ -1,155 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * bmove.c --- Move blocks around to make way for a particular
4 * filesystem structure.
5 *
6 * Copyright (C) 1997 Theodore Ts'o. This file may be redistributed
7 * under the terms of the GNU Public License.
8 */
9
10#include <stdio.h>
11#include <string.h>
12#if HAVE_UNISTD_H
13#include <unistd.h>
14#endif
15#if HAVE_SYS_TYPES_H
16#include <sys/types.h>
17#endif
18
19#include "ext2_fs.h"
20#include "ext2fsP.h"
21
22struct process_block_struct {
23 ext2_ino_t ino;
24 struct ext2_inode * inode;
25 ext2fs_block_bitmap reserve;
26 ext2fs_block_bitmap alloc_map;
27 errcode_t error;
28 char *buf;
29 int add_dir;
30 int flags;
31};
32
33static int process_block(ext2_filsys fs, blk_t *block_nr,
34 e2_blkcnt_t blockcnt, blk_t ref_block,
35 int ref_offset, void *priv_data)
36{
37 struct process_block_struct *pb;
38 errcode_t retval;
39 int ret;
40 blk_t block, orig;
41
42 pb = (struct process_block_struct *) priv_data;
43 block = orig = *block_nr;
44 ret = 0;
45
46 /*
47 * Let's see if this is one which we need to relocate
48 */
49 if (ext2fs_test_block_bitmap(pb->reserve, block)) {
50 do {
51 if (++block >= fs->super->s_blocks_count)
52 block = fs->super->s_first_data_block;
53 if (block == orig) {
54 pb->error = EXT2_ET_BLOCK_ALLOC_FAIL;
55 return BLOCK_ABORT;
56 }
57 } while (ext2fs_test_block_bitmap(pb->reserve, block) ||
58 ext2fs_test_block_bitmap(pb->alloc_map, block));
59
60 retval = io_channel_read_blk(fs->io, orig, 1, pb->buf);
61 if (retval) {
62 pb->error = retval;
63 return BLOCK_ABORT;
64 }
65 retval = io_channel_write_blk(fs->io, block, 1, pb->buf);
66 if (retval) {
67 pb->error = retval;
68 return BLOCK_ABORT;
69 }
70 *block_nr = block;
71 ext2fs_mark_block_bitmap(pb->alloc_map, block);
72 ret = BLOCK_CHANGED;
73 if (pb->flags & EXT2_BMOVE_DEBUG)
74 printf("ino=%ld, blockcnt=%lld, %d->%d\n", pb->ino,
75 blockcnt, orig, block);
76 }
77 if (pb->add_dir) {
78 retval = ext2fs_add_dir_block(fs->dblist, pb->ino,
79 block, (int) blockcnt);
80 if (retval) {
81 pb->error = retval;
82 ret |= BLOCK_ABORT;
83 }
84 }
85 return ret;
86}
87
88errcode_t ext2fs_move_blocks(ext2_filsys fs,
89 ext2fs_block_bitmap reserve,
90 ext2fs_block_bitmap alloc_map,
91 int flags)
92{
93 ext2_ino_t ino;
94 struct ext2_inode inode;
95 errcode_t retval;
96 struct process_block_struct pb;
97 ext2_inode_scan scan;
98 char *block_buf;
99
100 retval = ext2fs_open_inode_scan(fs, 0, &scan);
101 if (retval)
102 return retval;
103
104 pb.reserve = reserve;
105 pb.error = 0;
106 pb.alloc_map = alloc_map ? alloc_map : fs->block_map;
107 pb.flags = flags;
108
109 retval = ext2fs_get_mem(fs->blocksize * 4, &block_buf);
110 if (retval)
111 return retval;
112 pb.buf = block_buf + fs->blocksize * 3;
113
114 /*
115 * If GET_DBLIST is set in the flags field, then we should
116 * gather directory block information while we're doing the
117 * block move.
118 */
119 if (flags & EXT2_BMOVE_GET_DBLIST) {
120 ext2fs_free_dblist(fs->dblist);
121 fs->dblist = NULL;
122 retval = ext2fs_init_dblist(fs, 0);
123 if (retval)
124 return retval;
125 }
126
127 retval = ext2fs_get_next_inode(scan, &ino, &inode);
128 if (retval)
129 return retval;
130
131 while (ino) {
132 if ((inode.i_links_count == 0) ||
133 !ext2fs_inode_has_valid_blocks(&inode))
134 goto next;
135
136 pb.ino = ino;
137 pb.inode = &inode;
138
139 pb.add_dir = (LINUX_S_ISDIR(inode.i_mode) &&
140 flags & EXT2_BMOVE_GET_DBLIST);
141
142 retval = ext2fs_block_iterate2(fs, ino, 0, block_buf,
143 process_block, &pb);
144 if (retval)
145 return retval;
146 if (pb.error)
147 return pb.error;
148
149 next:
150 retval = ext2fs_get_next_inode(scan, &ino, &inode);
151 if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
152 goto next;
153 }
154 return 0;
155}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/brel.h b/e2fsprogs/old_e2fsprogs/ext2fs/brel.h
deleted file mode 100644
index 87bf72be4..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/brel.h
+++ /dev/null
@@ -1,86 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * brel.h
4 *
5 * Copyright (C) 1996, 1997 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13struct ext2_block_relocate_entry {
14 blk_t new;
15 __s16 offset;
16 __u16 flags;
17 union {
18 blk_t block_ref;
19 ext2_ino_t inode_ref;
20 } owner;
21};
22
23#define RELOCATE_TYPE_REF 0x0007
24#define RELOCATE_BLOCK_REF 0x0001
25#define RELOCATE_INODE_REF 0x0002
26
27typedef struct ext2_block_relocation_table *ext2_brel;
28
29struct ext2_block_relocation_table {
30 __u32 magic;
31 char *name;
32 blk_t current;
33 void *priv_data;
34
35 /*
36 * Add a block relocation entry.
37 */
38 errcode_t (*put)(ext2_brel brel, blk_t old,
39 struct ext2_block_relocate_entry *ent);
40
41 /*
42 * Get a block relocation entry.
43 */
44 errcode_t (*get)(ext2_brel brel, blk_t old,
45 struct ext2_block_relocate_entry *ent);
46
47 /*
48 * Initialize for iterating over the block relocation entries.
49 */
50 errcode_t (*start_iter)(ext2_brel brel);
51
52 /*
53 * The iterator function for the inode relocation entries.
54 * Returns an inode number of 0 when out of entries.
55 */
56 errcode_t (*next)(ext2_brel brel, blk_t *old,
57 struct ext2_block_relocate_entry *ent);
58
59 /*
60 * Move the inode relocation table from one block number to
61 * another.
62 */
63 errcode_t (*move)(ext2_brel brel, blk_t old, blk_t new);
64
65 /*
66 * Remove a block relocation entry.
67 */
68 errcode_t (*delete)(ext2_brel brel, blk_t old);
69
70
71 /*
72 * Free the block relocation table.
73 */
74 errcode_t (*free)(ext2_brel brel);
75};
76
77errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block,
78 ext2_brel *brel);
79
80#define ext2fs_brel_put(brel, old, ent) ((brel)->put((brel), old, ent))
81#define ext2fs_brel_get(brel, old, ent) ((brel)->get((brel), old, ent))
82#define ext2fs_brel_start_iter(brel) ((brel)->start_iter((brel)))
83#define ext2fs_brel_next(brel, old, ent) ((brel)->next((brel), old, ent))
84#define ext2fs_brel_move(brel, old, new) ((brel)->move((brel), old, new))
85#define ext2fs_brel_delete(brel, old) ((brel)->delete((brel), old))
86#define ext2fs_brel_free(brel) ((brel)->free((brel)))
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/brel_ma.c b/e2fsprogs/old_e2fsprogs/ext2fs/brel_ma.c
deleted file mode 100644
index 652a3509c..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/brel_ma.c
+++ /dev/null
@@ -1,196 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * brel_ma.c
4 *
5 * Copyright (C) 1996, 1997 Theodore Ts'o.
6 *
7 * TODO: rewrite to not use a direct array!!! (Fortunately this
8 * module isn't really used yet.)
9 *
10 * %Begin-Header%
11 * This file may be redistributed under the terms of the GNU Public
12 * License.
13 * %End-Header%
14 */
15
16#include <fcntl.h>
17#include <stdio.h>
18#include <string.h>
19#if HAVE_UNISTD_H
20#include <unistd.h>
21#endif
22#if HAVE_ERRNO_H
23#include <errno.h>
24#endif
25
26#include "ext2_fs.h"
27#include "ext2fs.h"
28#include "brel.h"
29
30static errcode_t bma_put(ext2_brel brel, blk_t old,
31 struct ext2_block_relocate_entry *ent);
32static errcode_t bma_get(ext2_brel brel, blk_t old,
33 struct ext2_block_relocate_entry *ent);
34static errcode_t bma_start_iter(ext2_brel brel);
35static errcode_t bma_next(ext2_brel brel, blk_t *old,
36 struct ext2_block_relocate_entry *ent);
37static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new);
38static errcode_t bma_delete(ext2_brel brel, blk_t old);
39static errcode_t bma_free(ext2_brel brel);
40
41struct brel_ma {
42 __u32 magic;
43 blk_t max_block;
44 struct ext2_block_relocate_entry *entries;
45};
46
47errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block,
48 ext2_brel *new_brel)
49{
50 ext2_brel brel = 0;
51 errcode_t retval;
52 struct brel_ma *ma = 0;
53 size_t size;
54
55 *new_brel = 0;
56
57 /*
58 * Allocate memory structures
59 */
60 retval = ext2fs_get_mem(sizeof(struct ext2_block_relocation_table),
61 &brel);
62 if (retval)
63 goto errout;
64 memset(brel, 0, sizeof(struct ext2_block_relocation_table));
65
66 retval = ext2fs_get_mem(strlen(name)+1, &brel->name);
67 if (retval)
68 goto errout;
69 strcpy(brel->name, name);
70
71 retval = ext2fs_get_mem(sizeof(struct brel_ma), &ma);
72 if (retval)
73 goto errout;
74 memset(ma, 0, sizeof(struct brel_ma));
75 brel->priv_data = ma;
76
77 size = (size_t) (sizeof(struct ext2_block_relocate_entry) *
78 (max_block+1));
79 retval = ext2fs_get_mem(size, &ma->entries);
80 if (retval)
81 goto errout;
82 memset(ma->entries, 0, size);
83 ma->max_block = max_block;
84
85 /*
86 * Fill in the brel data structure
87 */
88 brel->put = bma_put;
89 brel->get = bma_get;
90 brel->start_iter = bma_start_iter;
91 brel->next = bma_next;
92 brel->move = bma_move;
93 brel->delete = bma_delete;
94 brel->free = bma_free;
95
96 *new_brel = brel;
97 return 0;
98
99errout:
100 bma_free(brel);
101 return retval;
102}
103
104static errcode_t bma_put(ext2_brel brel, blk_t old,
105 struct ext2_block_relocate_entry *ent)
106{
107 struct brel_ma *ma;
108
109 ma = brel->priv_data;
110 if (old > ma->max_block)
111 return EXT2_ET_INVALID_ARGUMENT;
112 ma->entries[(unsigned)old] = *ent;
113 return 0;
114}
115
116static errcode_t bma_get(ext2_brel brel, blk_t old,
117 struct ext2_block_relocate_entry *ent)
118{
119 struct brel_ma *ma;
120
121 ma = brel->priv_data;
122 if (old > ma->max_block)
123 return EXT2_ET_INVALID_ARGUMENT;
124 if (ma->entries[(unsigned)old].new == 0)
125 return ENOENT;
126 *ent = ma->entries[old];
127 return 0;
128}
129
130static errcode_t bma_start_iter(ext2_brel brel)
131{
132 brel->current = 0;
133 return 0;
134}
135
136static errcode_t bma_next(ext2_brel brel, blk_t *old,
137 struct ext2_block_relocate_entry *ent)
138{
139 struct brel_ma *ma;
140
141 ma = brel->priv_data;
142 while (++brel->current < ma->max_block) {
143 if (ma->entries[(unsigned)brel->current].new == 0)
144 continue;
145 *old = brel->current;
146 *ent = ma->entries[(unsigned)brel->current];
147 return 0;
148 }
149 *old = 0;
150 return 0;
151}
152
153static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new)
154{
155 struct brel_ma *ma;
156
157 ma = brel->priv_data;
158 if ((old > ma->max_block) || (new > ma->max_block))
159 return EXT2_ET_INVALID_ARGUMENT;
160 if (ma->entries[(unsigned)old].new == 0)
161 return ENOENT;
162 ma->entries[(unsigned)new] = ma->entries[old];
163 ma->entries[(unsigned)old].new = 0;
164 return 0;
165}
166
167static errcode_t bma_delete(ext2_brel brel, blk_t old)
168{
169 struct brel_ma *ma;
170
171 ma = brel->priv_data;
172 if (old > ma->max_block)
173 return EXT2_ET_INVALID_ARGUMENT;
174 if (ma->entries[(unsigned)old].new == 0)
175 return ENOENT;
176 ma->entries[(unsigned)old].new = 0;
177 return 0;
178}
179
180static errcode_t bma_free(ext2_brel brel)
181{
182 struct brel_ma *ma;
183
184 if (!brel)
185 return 0;
186
187 ma = brel->priv_data;
188
189 if (ma) {
190 ext2fs_free_mem(&ma->entries);
191 ext2fs_free_mem(&ma);
192 }
193 ext2fs_free_mem(&brel->name);
194 ext2fs_free_mem(&brel);
195 return 0;
196}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/check_desc.c b/e2fsprogs/old_e2fsprogs/ext2fs/check_desc.c
deleted file mode 100644
index dd4b0e9cf..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/check_desc.c
+++ /dev/null
@@ -1,69 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * check_desc.c --- Check the group descriptors of an ext2 filesystem
4 *
5 * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#include <fcntl.h>
19#include <time.h>
20#if HAVE_SYS_STAT_H
21#include <sys/stat.h>
22#endif
23#if HAVE_SYS_TYPES_H
24#include <sys/types.h>
25#endif
26
27#include "ext2_fs.h"
28#include "ext2fs.h"
29
30/*
31 * This routine sanity checks the group descriptors
32 */
33errcode_t ext2fs_check_desc(ext2_filsys fs)
34{
35 dgrp_t i;
36 blk_t block = fs->super->s_first_data_block;
37 blk_t next;
38
39 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
40
41 for (i = 0; i < fs->group_desc_count; i++) {
42 next = block + fs->super->s_blocks_per_group;
43 /*
44 * Check to make sure block bitmap for group is
45 * located within the group.
46 */
47 if (fs->group_desc[i].bg_block_bitmap < block ||
48 fs->group_desc[i].bg_block_bitmap >= next)
49 return EXT2_ET_GDESC_BAD_BLOCK_MAP;
50 /*
51 * Check to make sure inode bitmap for group is
52 * located within the group
53 */
54 if (fs->group_desc[i].bg_inode_bitmap < block ||
55 fs->group_desc[i].bg_inode_bitmap >= next)
56 return EXT2_ET_GDESC_BAD_INODE_MAP;
57 /*
58 * Check to make sure inode table for group is located
59 * within the group
60 */
61 if (fs->group_desc[i].bg_inode_table < block ||
62 ((fs->group_desc[i].bg_inode_table +
63 fs->inode_blocks_per_group) >= next))
64 return EXT2_ET_GDESC_BAD_INODE_TABLE;
65
66 block = next;
67 }
68 return 0;
69}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/closefs.c b/e2fsprogs/old_e2fsprogs/ext2fs/closefs.c
deleted file mode 100644
index bfa15e22a..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/closefs.c
+++ /dev/null
@@ -1,380 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * closefs.c --- close an ext2 filesystem
4 *
5 * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#if HAVE_UNISTD_H
15#include <unistd.h>
16#endif
17#include <time.h>
18#include <string.h>
19
20#include "ext2_fs.h"
21#include "ext2fsP.h"
22
23static int test_root(int a, int b)
24{
25 if (a == 0)
26 return 1;
27 while (1) {
28 if (a == 1)
29 return 1;
30 if (a % b)
31 return 0;
32 a = a / b;
33 }
34}
35
36int ext2fs_bg_has_super(ext2_filsys fs, int group_block)
37{
38 if (!(fs->super->s_feature_ro_compat &
39 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
40 return 1;
41
42 if (test_root(group_block, 3) || (test_root(group_block, 5)) ||
43 test_root(group_block, 7))
44 return 1;
45
46 return 0;
47}
48
49int ext2fs_super_and_bgd_loc(ext2_filsys fs,
50 dgrp_t group,
51 blk_t *ret_super_blk,
52 blk_t *ret_old_desc_blk,
53 blk_t *ret_new_desc_blk,
54 int *ret_meta_bg)
55{
56 blk_t group_block, super_blk = 0, old_desc_blk = 0, new_desc_blk = 0;
57 unsigned int meta_bg, meta_bg_size;
58 int numblocks, has_super;
59 int old_desc_blocks;
60
61 group_block = fs->super->s_first_data_block +
62 (group * fs->super->s_blocks_per_group);
63
64 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
65 old_desc_blocks = fs->super->s_first_meta_bg;
66 else
67 old_desc_blocks =
68 fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
69
70 if (group == fs->group_desc_count-1) {
71 numblocks = (fs->super->s_blocks_count -
72 fs->super->s_first_data_block) %
73 fs->super->s_blocks_per_group;
74 if (!numblocks)
75 numblocks = fs->super->s_blocks_per_group;
76 } else
77 numblocks = fs->super->s_blocks_per_group;
78
79 has_super = ext2fs_bg_has_super(fs, group);
80
81 if (has_super) {
82 super_blk = group_block;
83 numblocks--;
84 }
85 meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc));
86 meta_bg = group / meta_bg_size;
87
88 if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
89 (meta_bg < fs->super->s_first_meta_bg)) {
90 if (has_super) {
91 old_desc_blk = group_block + 1;
92 numblocks -= old_desc_blocks;
93 }
94 } else {
95 if (((group % meta_bg_size) == 0) ||
96 ((group % meta_bg_size) == 1) ||
97 ((group % meta_bg_size) == (meta_bg_size-1))) {
98 if (has_super)
99 has_super = 1;
100 new_desc_blk = group_block + has_super;
101 numblocks--;
102 }
103 }
104
105 numblocks -= 2 + fs->inode_blocks_per_group;
106
107 if (ret_super_blk)
108 *ret_super_blk = super_blk;
109 if (ret_old_desc_blk)
110 *ret_old_desc_blk = old_desc_blk;
111 if (ret_new_desc_blk)
112 *ret_new_desc_blk = new_desc_blk;
113 if (ret_meta_bg)
114 *ret_meta_bg = meta_bg;
115 return numblocks;
116}
117
118
119/*
120 * This function forces out the primary superblock. We need to only
121 * write out those fields which we have changed, since if the
122 * filesystem is mounted, it may have changed some of the other
123 * fields.
124 *
125 * It takes as input a superblock which has already been byte swapped
126 * (if necessary).
127 *
128 */
129static errcode_t write_primary_superblock(ext2_filsys fs,
130 struct ext2_super_block *super)
131{
132 __u16 *old_super, *new_super;
133 int check_idx, write_idx, size;
134 errcode_t retval;
135
136 if (!fs->io->manager->write_byte || !fs->orig_super) {
137 io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET);
138 retval = io_channel_write_blk(fs->io, 1, -SUPERBLOCK_SIZE,
139 super);
140 io_channel_set_blksize(fs->io, fs->blocksize);
141 return retval;
142 }
143
144 old_super = (__u16 *) fs->orig_super;
145 new_super = (__u16 *) super;
146
147 for (check_idx = 0; check_idx < SUPERBLOCK_SIZE/2; check_idx++) {
148 if (old_super[check_idx] == new_super[check_idx])
149 continue;
150 write_idx = check_idx;
151 for (check_idx++; check_idx < SUPERBLOCK_SIZE/2; check_idx++)
152 if (old_super[check_idx] == new_super[check_idx])
153 break;
154 size = 2 * (check_idx - write_idx);
155 retval = io_channel_write_byte(fs->io,
156 SUPERBLOCK_OFFSET + (2 * write_idx), size,
157 new_super + write_idx);
158 if (retval)
159 return retval;
160 }
161 memcpy(fs->orig_super, super, SUPERBLOCK_SIZE);
162 return 0;
163}
164
165
166/*
167 * Updates the revision to EXT2_DYNAMIC_REV
168 */
169void ext2fs_update_dynamic_rev(ext2_filsys fs)
170{
171 struct ext2_super_block *sb = fs->super;
172
173 if (sb->s_rev_level > EXT2_GOOD_OLD_REV)
174 return;
175
176 sb->s_rev_level = EXT2_DYNAMIC_REV;
177 sb->s_first_ino = EXT2_GOOD_OLD_FIRST_INO;
178 sb->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
179 /* s_uuid is handled by e2fsck already */
180 /* other fields should be left alone */
181}
182
183static errcode_t write_backup_super(ext2_filsys fs, dgrp_t group,
184 blk_t group_block,
185 struct ext2_super_block *super_shadow)
186{
187 dgrp_t sgrp = group;
188
189 if (sgrp > ((1 << 16) - 1))
190 sgrp = (1 << 16) - 1;
191#if BB_BIG_ENDIAN
192 if (fs->flags & EXT2_FLAG_SWAP_BYTES)
193 super_shadow->s_block_group_nr = ext2fs_swab16(sgrp);
194 else
195#endif
196 fs->super->s_block_group_nr = sgrp;
197
198 return io_channel_write_blk(fs->io, group_block, -SUPERBLOCK_SIZE,
199 super_shadow);
200}
201
202
203errcode_t ext2fs_flush(ext2_filsys fs)
204{
205 dgrp_t i;
206 blk_t group_block;
207 errcode_t retval;
208 unsigned long fs_state;
209 struct ext2_super_block *super_shadow = NULL;
210 struct ext2_group_desc *group_shadow = NULL;
211 char *group_ptr;
212 int old_desc_blocks;
213#if BB_BIG_ENDIAN
214 dgrp_t j;
215 struct ext2_group_desc *s, *t;
216#endif
217
218 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
219
220 fs_state = fs->super->s_state;
221
222 fs->super->s_wtime = time(NULL);
223 fs->super->s_block_group_nr = 0;
224#if BB_BIG_ENDIAN
225 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
226 retval = EXT2_ET_NO_MEMORY;
227 retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow);
228 if (retval)
229 goto errout;
230 retval = ext2fs_get_mem((size_t)(fs->blocksize *
231 fs->desc_blocks),
232 &group_shadow);
233 if (retval)
234 goto errout;
235 memset(group_shadow, 0, (size_t) fs->blocksize *
236 fs->desc_blocks);
237
238 /* swap the group descriptors */
239 for (j=0, s=fs->group_desc, t=group_shadow;
240 j < fs->group_desc_count; j++, t++, s++) {
241 *t = *s;
242 ext2fs_swap_group_desc(t);
243 }
244 } else {
245 super_shadow = fs->super;
246 group_shadow = fs->group_desc;
247 }
248#else
249 super_shadow = fs->super;
250 group_shadow = fs->group_desc;
251#endif
252
253 /*
254 * If this is an external journal device, don't write out the
255 * block group descriptors or any of the backup superblocks
256 */
257 if (fs->super->s_feature_incompat &
258 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
259 goto write_primary_superblock_only;
260
261 /*
262 * Set the state of the FS to be non-valid. (The state has
263 * already been backed up earlier, and will be restored after
264 * we write out the backup superblocks.)
265 */
266 fs->super->s_state &= ~EXT2_VALID_FS;
267#if BB_BIG_ENDIAN
268 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
269 *super_shadow = *fs->super;
270 ext2fs_swap_super(super_shadow);
271 }
272#endif
273
274 /*
275 * Write out the master group descriptors, and the backup
276 * superblocks and group descriptors.
277 */
278 group_block = fs->super->s_first_data_block;
279 group_ptr = (char *) group_shadow;
280 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
281 old_desc_blocks = fs->super->s_first_meta_bg;
282 else
283 old_desc_blocks = fs->desc_blocks;
284
285 for (i = 0; i < fs->group_desc_count; i++) {
286 blk_t super_blk, old_desc_blk, new_desc_blk;
287 int meta_bg;
288
289 ext2fs_super_and_bgd_loc(fs, i, &super_blk, &old_desc_blk,
290 &new_desc_blk, &meta_bg);
291
292 if (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) &&i && super_blk) {
293 retval = write_backup_super(fs, i, super_blk,
294 super_shadow);
295 if (retval)
296 goto errout;
297 }
298 if (fs->flags & EXT2_FLAG_SUPER_ONLY)
299 continue;
300 if ((old_desc_blk) &&
301 (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) || (i == 0))) {
302 retval = io_channel_write_blk(fs->io,
303 old_desc_blk, old_desc_blocks, group_ptr);
304 if (retval)
305 goto errout;
306 }
307 if (new_desc_blk) {
308 retval = io_channel_write_blk(fs->io, new_desc_blk,
309 1, group_ptr + (meta_bg*fs->blocksize));
310 if (retval)
311 goto errout;
312 }
313 }
314 fs->super->s_block_group_nr = 0;
315 fs->super->s_state = fs_state;
316#if BB_BIG_ENDIAN
317 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
318 *super_shadow = *fs->super;
319 ext2fs_swap_super(super_shadow);
320 }
321#endif
322
323 /*
324 * If the write_bitmaps() function is present, call it to
325 * flush the bitmaps. This is done this way so that a simple
326 * program that doesn't mess with the bitmaps doesn't need to
327 * drag in the bitmaps.c code.
328 */
329 if (fs->write_bitmaps) {
330 retval = fs->write_bitmaps(fs);
331 if (retval)
332 goto errout;
333 }
334
335write_primary_superblock_only:
336 /*
337 * Write out master superblock. This has to be done
338 * separately, since it is located at a fixed location
339 * (SUPERBLOCK_OFFSET). We flush all other pending changes
340 * out to disk first, just to avoid a race condition with an
341 * insy-tinsy window....
342 */
343 retval = io_channel_flush(fs->io);
344 retval = write_primary_superblock(fs, super_shadow);
345 if (retval)
346 goto errout;
347
348 fs->flags &= ~EXT2_FLAG_DIRTY;
349
350 retval = io_channel_flush(fs->io);
351errout:
352 fs->super->s_state = fs_state;
353 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
354 if (super_shadow)
355 ext2fs_free_mem(&super_shadow);
356 if (group_shadow)
357 ext2fs_free_mem(&group_shadow);
358 }
359 return retval;
360}
361
362errcode_t ext2fs_close(ext2_filsys fs)
363{
364 errcode_t retval;
365
366 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
367
368 if (fs->flags & EXT2_FLAG_DIRTY) {
369 retval = ext2fs_flush(fs);
370 if (retval)
371 return retval;
372 }
373 if (fs->write_bitmaps) {
374 retval = fs->write_bitmaps(fs);
375 if (retval)
376 return retval;
377 }
378 ext2fs_free(fs);
379 return 0;
380}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/cmp_bitmaps.c b/e2fsprogs/old_e2fsprogs/ext2fs/cmp_bitmaps.c
deleted file mode 100644
index 7f78ff804..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/cmp_bitmaps.c
+++ /dev/null
@@ -1,72 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * cmp_bitmaps.c --- routines to compare inode and block bitmaps.
4 *
5 * Copyright (C) 1995 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#include <fcntl.h>
19#include <time.h>
20#if HAVE_SYS_STAT_H
21#include <sys/stat.h>
22#endif
23#if HAVE_SYS_TYPES_H
24#include <sys/types.h>
25#endif
26
27#include "ext2_fs.h"
28#include "ext2fs.h"
29
30errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
31 ext2fs_block_bitmap bm2)
32{
33 blk_t i;
34
35 EXT2_CHECK_MAGIC(bm1, EXT2_ET_MAGIC_BLOCK_BITMAP);
36 EXT2_CHECK_MAGIC(bm2, EXT2_ET_MAGIC_BLOCK_BITMAP);
37
38 if ((bm1->start != bm2->start) ||
39 (bm1->end != bm2->end) ||
40 (memcmp(bm1->bitmap, bm2->bitmap,
41 (size_t) (bm1->end - bm1->start)/8)))
42 return EXT2_ET_NEQ_BLOCK_BITMAP;
43
44 for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
45 if (ext2fs_fast_test_block_bitmap(bm1, i) !=
46 ext2fs_fast_test_block_bitmap(bm2, i))
47 return EXT2_ET_NEQ_BLOCK_BITMAP;
48
49 return 0;
50}
51
52errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
53 ext2fs_inode_bitmap bm2)
54{
55 ext2_ino_t i;
56
57 EXT2_CHECK_MAGIC(bm1, EXT2_ET_MAGIC_INODE_BITMAP);
58 EXT2_CHECK_MAGIC(bm2, EXT2_ET_MAGIC_INODE_BITMAP);
59
60 if ((bm1->start != bm2->start) ||
61 (bm1->end != bm2->end) ||
62 (memcmp(bm1->bitmap, bm2->bitmap,
63 (size_t) (bm1->end - bm1->start)/8)))
64 return EXT2_ET_NEQ_INODE_BITMAP;
65
66 for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
67 if (ext2fs_fast_test_inode_bitmap(bm1, i) !=
68 ext2fs_fast_test_inode_bitmap(bm2, i))
69 return EXT2_ET_NEQ_INODE_BITMAP;
70
71 return 0;
72}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/dblist.c b/e2fsprogs/old_e2fsprogs/ext2fs/dblist.c
deleted file mode 100644
index 06ff6d807..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/dblist.c
+++ /dev/null
@@ -1,260 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * dblist.c -- directory block list functions
4 *
5 * Copyright 1997 by Theodore Ts'o
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 *
12 */
13
14#include <stdio.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#include <string.h>
19#include <time.h>
20
21#include "ext2_fs.h"
22#include "ext2fsP.h"
23
24static int dir_block_cmp(const void *a, const void *b);
25
26/*
27 * Returns the number of directories in the filesystem as reported by
28 * the group descriptors. Of course, the group descriptors could be
29 * wrong!
30 */
31errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs)
32{
33 dgrp_t i;
34 ext2_ino_t num_dirs, max_dirs;
35
36 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
37
38 num_dirs = 0;
39 max_dirs = fs->super->s_inodes_per_group;
40 for (i = 0; i < fs->group_desc_count; i++) {
41 if (fs->group_desc[i].bg_used_dirs_count > max_dirs)
42 num_dirs += max_dirs / 8;
43 else
44 num_dirs += fs->group_desc[i].bg_used_dirs_count;
45 }
46 if (num_dirs > fs->super->s_inodes_count)
47 num_dirs = fs->super->s_inodes_count;
48
49 *ret_num_dirs = num_dirs;
50
51 return 0;
52}
53
54/*
55 * helper function for making a new directory block list (for
56 * initialize and copy).
57 */
58static errcode_t make_dblist(ext2_filsys fs, ext2_ino_t size, ext2_ino_t count,
59 struct ext2_db_entry *list,
60 ext2_dblist *ret_dblist)
61{
62 ext2_dblist dblist;
63 errcode_t retval;
64 size_t len;
65
66 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
67
68 if ((ret_dblist == 0) && fs->dblist &&
69 (fs->dblist->magic == EXT2_ET_MAGIC_DBLIST))
70 return 0;
71
72 retval = ext2fs_get_mem(sizeof(struct ext2_struct_dblist), &dblist);
73 if (retval)
74 return retval;
75 memset(dblist, 0, sizeof(struct ext2_struct_dblist));
76
77 dblist->magic = EXT2_ET_MAGIC_DBLIST;
78 dblist->fs = fs;
79 if (size)
80 dblist->size = size;
81 else {
82 retval = ext2fs_get_num_dirs(fs, &dblist->size);
83 if (retval)
84 goto cleanup;
85 dblist->size = (dblist->size * 2) + 12;
86 }
87 len = (size_t) sizeof(struct ext2_db_entry) * dblist->size;
88 dblist->count = count;
89 retval = ext2fs_get_mem(len, &dblist->list);
90 if (retval)
91 goto cleanup;
92
93 if (list)
94 memcpy(dblist->list, list, len);
95 else
96 memset(dblist->list, 0, len);
97 if (ret_dblist)
98 *ret_dblist = dblist;
99 else
100 fs->dblist = dblist;
101 return 0;
102cleanup:
103 ext2fs_free_mem(&dblist);
104 return retval;
105}
106
107/*
108 * Initialize a directory block list
109 */
110errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist)
111{
112 ext2_dblist dblist;
113 errcode_t retval;
114
115 retval = make_dblist(fs, 0, 0, 0, &dblist);
116 if (retval)
117 return retval;
118
119 dblist->sorted = 1;
120 if (ret_dblist)
121 *ret_dblist = dblist;
122 else
123 fs->dblist = dblist;
124
125 return 0;
126}
127
128/*
129 * Copy a directory block list
130 */
131errcode_t ext2fs_copy_dblist(ext2_dblist src, ext2_dblist *dest)
132{
133 ext2_dblist dblist;
134 errcode_t retval;
135
136 retval = make_dblist(src->fs, src->size, src->count, src->list,
137 &dblist);
138 if (retval)
139 return retval;
140 dblist->sorted = src->sorted;
141 *dest = dblist;
142 return 0;
143}
144
145/*
146 * Close a directory block list
147 *
148 * (moved to closefs.c)
149 */
150
151
152/*
153 * Add a directory block to the directory block list
154 */
155errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk,
156 int blockcnt)
157{
158 struct ext2_db_entry *new_entry;
159 errcode_t retval;
160 unsigned long old_size;
161
162 EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
163
164 if (dblist->count >= dblist->size) {
165 old_size = dblist->size * sizeof(struct ext2_db_entry);
166 dblist->size += 100;
167 retval = ext2fs_resize_mem(old_size, (size_t) dblist->size *
168 sizeof(struct ext2_db_entry),
169 &dblist->list);
170 if (retval) {
171 dblist->size -= 100;
172 return retval;
173 }
174 }
175 new_entry = dblist->list + ( (int) dblist->count++);
176 new_entry->blk = blk;
177 new_entry->ino = ino;
178 new_entry->blockcnt = blockcnt;
179
180 dblist->sorted = 0;
181
182 return 0;
183}
184
185/*
186 * Change the directory block to the directory block list
187 */
188errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk,
189 int blockcnt)
190{
191 dgrp_t i;
192
193 EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
194
195 for (i=0; i < dblist->count; i++) {
196 if ((dblist->list[i].ino != ino) ||
197 (dblist->list[i].blockcnt != blockcnt))
198 continue;
199 dblist->list[i].blk = blk;
200 dblist->sorted = 0;
201 return 0;
202 }
203 return EXT2_ET_DB_NOT_FOUND;
204}
205
206void ext2fs_dblist_sort(ext2_dblist dblist,
207 int (*sortfunc)(const void *,
208 const void *))
209{
210 if (!sortfunc)
211 sortfunc = dir_block_cmp;
212 qsort(dblist->list, (size_t) dblist->count,
213 sizeof(struct ext2_db_entry), sortfunc);
214 dblist->sorted = 1;
215}
216
217/*
218 * This function iterates over the directory block list
219 */
220errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
221 int (*func)(ext2_filsys fs,
222 struct ext2_db_entry *db_info,
223 void *priv_data),
224 void *priv_data)
225{
226 ext2_ino_t i;
227 int ret;
228
229 EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
230
231 if (!dblist->sorted)
232 ext2fs_dblist_sort(dblist, 0);
233 for (i=0; i < dblist->count; i++) {
234 ret = (*func)(dblist->fs, &dblist->list[(int)i], priv_data);
235 if (ret & DBLIST_ABORT)
236 return 0;
237 }
238 return 0;
239}
240
241static int dir_block_cmp(const void *a, const void *b)
242{
243 const struct ext2_db_entry *db_a =
244 (const struct ext2_db_entry *) a;
245 const struct ext2_db_entry *db_b =
246 (const struct ext2_db_entry *) b;
247
248 if (db_a->blk != db_b->blk)
249 return (int) (db_a->blk - db_b->blk);
250
251 if (db_a->ino != db_b->ino)
252 return (int) (db_a->ino - db_b->ino);
253
254 return (int) (db_a->blockcnt - db_b->blockcnt);
255}
256
257int ext2fs_dblist_count(ext2_dblist dblist)
258{
259 return (int) dblist->count;
260}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/dblist_dir.c b/e2fsprogs/old_e2fsprogs/ext2fs/dblist_dir.c
deleted file mode 100644
index b23920466..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/dblist_dir.c
+++ /dev/null
@@ -1,76 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * dblist_dir.c --- iterate by directory entry
4 *
5 * Copyright 1997 by Theodore Ts'o
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 *
12 */
13
14#include <stdio.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#include <string.h>
19#include <time.h>
20
21#include "ext2_fs.h"
22#include "ext2fsP.h"
23
24static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info,
25 void *priv_data);
26
27errcode_t ext2fs_dblist_dir_iterate(ext2_dblist dblist,
28 int flags,
29 char *block_buf,
30 int (*func)(ext2_ino_t dir,
31 int entry,
32 struct ext2_dir_entry *dirent,
33 int offset,
34 int blocksize,
35 char *buf,
36 void *priv_data),
37 void *priv_data)
38{
39 errcode_t retval;
40 struct dir_context ctx;
41
42 EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
43
44 ctx.dir = 0;
45 ctx.flags = flags;
46 if (block_buf)
47 ctx.buf = block_buf;
48 else {
49 retval = ext2fs_get_mem(dblist->fs->blocksize, &ctx.buf);
50 if (retval)
51 return retval;
52 }
53 ctx.func = func;
54 ctx.priv_data = priv_data;
55 ctx.errcode = 0;
56
57 retval = ext2fs_dblist_iterate(dblist, db_dir_proc, &ctx);
58
59 if (!block_buf)
60 ext2fs_free_mem(&ctx.buf);
61 if (retval)
62 return retval;
63 return ctx.errcode;
64}
65
66static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info,
67 void *priv_data)
68{
69 struct dir_context *ctx;
70
71 ctx = (struct dir_context *) priv_data;
72 ctx->dir = db_info->ino;
73
74 return ext2fs_process_dir_block(fs, &db_info->blk,
75 db_info->blockcnt, 0, 0, priv_data);
76}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/dir_iterate.c b/e2fsprogs/old_e2fsprogs/ext2fs/dir_iterate.c
deleted file mode 100644
index eb5dae0a6..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/dir_iterate.c
+++ /dev/null
@@ -1,219 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * dir_iterate.c --- ext2fs directory iteration operations
4 *
5 * Copyright (C) 1993, 1994, 1994, 1995, 1996, 1997 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#if HAVE_ERRNO_H
19#include <errno.h>
20#endif
21
22#include "ext2_fs.h"
23#include "ext2fsP.h"
24
25/*
26 * This function checks to see whether or not a potential deleted
27 * directory entry looks valid. What we do is check the deleted entry
28 * and each successive entry to make sure that they all look valid and
29 * that the last deleted entry ends at the beginning of the next
30 * undeleted entry. Returns 1 if the deleted entry looks valid, zero
31 * if not valid.
32 */
33static int ext2fs_validate_entry(char *buf, int offset, int final_offset)
34{
35 struct ext2_dir_entry *dirent;
36
37 while (offset < final_offset) {
38 dirent = (struct ext2_dir_entry *)(buf + offset);
39 offset += dirent->rec_len;
40 if ((dirent->rec_len < 8) ||
41 ((dirent->rec_len % 4) != 0) ||
42 (((dirent->name_len & 0xFF)+8) > dirent->rec_len))
43 return 0;
44 }
45 return (offset == final_offset);
46}
47
48errcode_t ext2fs_dir_iterate2(ext2_filsys fs,
49 ext2_ino_t dir,
50 int flags,
51 char *block_buf,
52 int (*func)(ext2_ino_t dir,
53 int entry,
54 struct ext2_dir_entry *dirent,
55 int offset,
56 int blocksize,
57 char *buf,
58 void *priv_data),
59 void *priv_data)
60{
61 struct dir_context ctx;
62 errcode_t retval;
63
64 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
65
66 retval = ext2fs_check_directory(fs, dir);
67 if (retval)
68 return retval;
69
70 ctx.dir = dir;
71 ctx.flags = flags;
72 if (block_buf)
73 ctx.buf = block_buf;
74 else {
75 retval = ext2fs_get_mem(fs->blocksize, &ctx.buf);
76 if (retval)
77 return retval;
78 }
79 ctx.func = func;
80 ctx.priv_data = priv_data;
81 ctx.errcode = 0;
82 retval = ext2fs_block_iterate2(fs, dir, 0, 0,
83 ext2fs_process_dir_block, &ctx);
84 if (!block_buf)
85 ext2fs_free_mem(&ctx.buf);
86 if (retval)
87 return retval;
88 return ctx.errcode;
89}
90
91struct xlate {
92 int (*func)(struct ext2_dir_entry *dirent,
93 int offset,
94 int blocksize,
95 char *buf,
96 void *priv_data);
97 void *real_private;
98};
99
100static int xlate_func(ext2_ino_t dir EXT2FS_ATTR((unused)),
101 int entry EXT2FS_ATTR((unused)),
102 struct ext2_dir_entry *dirent, int offset,
103 int blocksize, char *buf, void *priv_data)
104{
105 struct xlate *xl = (struct xlate *) priv_data;
106
107 return (*xl->func)(dirent, offset, blocksize, buf, xl->real_private);
108}
109
110extern errcode_t ext2fs_dir_iterate(ext2_filsys fs,
111 ext2_ino_t dir,
112 int flags,
113 char *block_buf,
114 int (*func)(struct ext2_dir_entry *dirent,
115 int offset,
116 int blocksize,
117 char *buf,
118 void *priv_data),
119 void *priv_data)
120{
121 struct xlate xl;
122
123 xl.real_private = priv_data;
124 xl.func = func;
125
126 return ext2fs_dir_iterate2(fs, dir, flags, block_buf,
127 xlate_func, &xl);
128}
129
130
131/*
132 * Helper function which is private to this module. Used by
133 * ext2fs_dir_iterate() and ext2fs_dblist_dir_iterate()
134 */
135int ext2fs_process_dir_block(ext2_filsys fs,
136 blk_t *blocknr,
137 e2_blkcnt_t blockcnt,
138 blk_t ref_block EXT2FS_ATTR((unused)),
139 int ref_offset EXT2FS_ATTR((unused)),
140 void *priv_data)
141{
142 struct dir_context *ctx = (struct dir_context *) priv_data;
143 unsigned int offset = 0;
144 unsigned int next_real_entry = 0;
145 int ret = 0;
146 int changed = 0;
147 int do_abort = 0;
148 int entry, size;
149 struct ext2_dir_entry *dirent;
150
151 if (blockcnt < 0)
152 return 0;
153
154 entry = blockcnt ? DIRENT_OTHER_FILE : DIRENT_DOT_FILE;
155
156 ctx->errcode = ext2fs_read_dir_block(fs, *blocknr, ctx->buf);
157 if (ctx->errcode)
158 return BLOCK_ABORT;
159
160 while (offset < fs->blocksize) {
161 dirent = (struct ext2_dir_entry *) (ctx->buf + offset);
162 if (((offset + dirent->rec_len) > fs->blocksize) ||
163 (dirent->rec_len < 8) ||
164 ((dirent->rec_len % 4) != 0) ||
165 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
166 ctx->errcode = EXT2_ET_DIR_CORRUPTED;
167 return BLOCK_ABORT;
168 }
169 if (!dirent->inode &&
170 !(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY))
171 goto next;
172
173 ret = (ctx->func)(ctx->dir,
174 (next_real_entry > offset) ?
175 DIRENT_DELETED_FILE : entry,
176 dirent, offset,
177 fs->blocksize, ctx->buf,
178 ctx->priv_data);
179 if (entry < DIRENT_OTHER_FILE)
180 entry++;
181
182 if (ret & DIRENT_CHANGED)
183 changed++;
184 if (ret & DIRENT_ABORT) {
185 do_abort++;
186 break;
187 }
188next:
189 if (next_real_entry == offset)
190 next_real_entry += dirent->rec_len;
191
192 if (ctx->flags & DIRENT_FLAG_INCLUDE_REMOVED) {
193 size = ((dirent->name_len & 0xFF) + 11) & ~3;
194
195 if (dirent->rec_len != size) {
196 unsigned int final_offset;
197
198 final_offset = offset + dirent->rec_len;
199 offset += size;
200 while (offset < final_offset &&
201 !ext2fs_validate_entry(ctx->buf,
202 offset,
203 final_offset))
204 offset += 4;
205 continue;
206 }
207 }
208 offset += dirent->rec_len;
209 }
210
211 if (changed) {
212 ctx->errcode = ext2fs_write_dir_block(fs, *blocknr, ctx->buf);
213 if (ctx->errcode)
214 return BLOCK_ABORT;
215 }
216 if (do_abort)
217 return BLOCK_ABORT;
218 return 0;
219}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/dirblock.c b/e2fsprogs/old_e2fsprogs/ext2fs/dirblock.c
deleted file mode 100644
index f9c5a104b..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/dirblock.c
+++ /dev/null
@@ -1,132 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * dirblock.c --- directory block routines.
4 *
5 * Copyright (C) 1995, 1996 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#if HAVE_UNISTD_H
15#include <unistd.h>
16#endif
17#include <string.h>
18#include <time.h>
19
20#include "ext2_fs.h"
21#include "ext2fs.h"
22
23errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
24 void *buf, int flags EXT2FS_ATTR((unused)))
25{
26 errcode_t retval;
27 char *p, *end;
28 struct ext2_dir_entry *dirent;
29 unsigned int name_len, rec_len;
30#if BB_BIG_ENDIAN
31 unsigned int do_swap;
32#endif
33
34 retval = io_channel_read_blk(fs->io, block, 1, buf);
35 if (retval)
36 return retval;
37#if BB_BIG_ENDIAN
38 do_swap = (fs->flags & (EXT2_FLAG_SWAP_BYTES|
39 EXT2_FLAG_SWAP_BYTES_READ)) != 0;
40#endif
41 p = (char *) buf;
42 end = (char *) buf + fs->blocksize;
43 while (p < end-8) {
44 dirent = (struct ext2_dir_entry *) p;
45#if BB_BIG_ENDIAN
46 if (do_swap) {
47 dirent->inode = ext2fs_swab32(dirent->inode);
48 dirent->rec_len = ext2fs_swab16(dirent->rec_len);
49 dirent->name_len = ext2fs_swab16(dirent->name_len);
50 }
51#endif
52 name_len = dirent->name_len;
53#ifdef WORDS_BIGENDIAN
54 if (flags & EXT2_DIRBLOCK_V2_STRUCT)
55 dirent->name_len = ext2fs_swab16(dirent->name_len);
56#endif
57 rec_len = dirent->rec_len;
58 if ((rec_len < 8) || (rec_len % 4)) {
59 rec_len = 8;
60 retval = EXT2_ET_DIR_CORRUPTED;
61 }
62 if (((name_len & 0xFF) + 8) > dirent->rec_len)
63 retval = EXT2_ET_DIR_CORRUPTED;
64 p += rec_len;
65 }
66 return retval;
67}
68
69errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
70 void *buf)
71{
72 return ext2fs_read_dir_block2(fs, block, buf, 0);
73}
74
75
76errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
77 void *inbuf, int flags EXT2FS_ATTR((unused)))
78{
79#if BB_BIG_ENDIAN
80 int do_swap = 0;
81 errcode_t retval;
82 char *p, *end;
83 char *buf = NULL;
84 struct ext2_dir_entry *dirent;
85
86 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
87 (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
88 do_swap = 1;
89
90#ifndef WORDS_BIGENDIAN
91 if (!do_swap)
92 return io_channel_write_blk(fs->io, block, 1, (char *) inbuf);
93#endif
94
95 retval = ext2fs_get_mem(fs->blocksize, &buf);
96 if (retval)
97 return retval;
98 memcpy(buf, inbuf, fs->blocksize);
99 p = buf;
100 end = buf + fs->blocksize;
101 while (p < end) {
102 dirent = (struct ext2_dir_entry *) p;
103 if ((dirent->rec_len < 8) ||
104 (dirent->rec_len % 4)) {
105 ext2fs_free_mem(&buf);
106 return EXT2_ET_DIR_CORRUPTED;
107 }
108 p += dirent->rec_len;
109 if (do_swap) {
110 dirent->inode = ext2fs_swab32(dirent->inode);
111 dirent->rec_len = ext2fs_swab16(dirent->rec_len);
112 dirent->name_len = ext2fs_swab16(dirent->name_len);
113 }
114#ifdef WORDS_BIGENDIAN
115 if (flags & EXT2_DIRBLOCK_V2_STRUCT)
116 dirent->name_len = ext2fs_swab16(dirent->name_len);
117#endif
118 }
119 retval = io_channel_write_blk(fs->io, block, 1, buf);
120 ext2fs_free_mem(&buf);
121 return retval;
122#else
123 return io_channel_write_blk(fs->io, block, 1, (char *) inbuf);
124#endif
125}
126
127
128errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
129 void *inbuf)
130{
131 return ext2fs_write_dir_block2(fs, block, inbuf, 0);
132}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/dirhash.c b/e2fsprogs/old_e2fsprogs/ext2fs/dirhash.c
deleted file mode 100644
index 09e34be3b..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/dirhash.c
+++ /dev/null
@@ -1,234 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * dirhash.c -- Calculate the hash of a directory entry
4 *
5 * Copyright (c) 2001 Daniel Phillips
6 *
7 * Copyright (c) 2002 Theodore Ts'o.
8 *
9 * %Begin-Header%
10 * This file may be redistributed under the terms of the GNU Public
11 * License.
12 * %End-Header%
13 */
14
15#include <stdio.h>
16#include <string.h>
17
18#include "ext2_fs.h"
19#include "ext2fs.h"
20
21/*
22 * Keyed 32-bit hash function using TEA in a Davis-Meyer function
23 * H0 = Key
24 * Hi = E Mi(Hi-1) + Hi-1
25 *
26 * (see Applied Cryptography, 2nd edition, p448).
27 *
28 * Jeremy Fitzhardinge <jeremy@zip.com.au> 1998
29 *
30 * This code is made available under the terms of the GPL
31 */
32#define DELTA 0x9E3779B9
33
34static void TEA_transform(__u32 buf[4], __u32 const in[])
35{
36 __u32 sum = 0;
37 __u32 b0 = buf[0], b1 = buf[1];
38 __u32 a = in[0], b = in[1], c = in[2], d = in[3];
39 int n = 16;
40
41 do {
42 sum += DELTA;
43 b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
44 b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
45 } while (--n);
46
47 buf[0] += b0;
48 buf[1] += b1;
49}
50
51/* F, G and H are basic MD4 functions: selection, majority, parity */
52#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
53#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
54#define H(x, y, z) ((x) ^ (y) ^ (z))
55
56/*
57 * The generic round function. The application is so specific that
58 * we don't bother protecting all the arguments with parens, as is generally
59 * good macro practice, in favor of extra legibility.
60 * Rotation is separate from addition to prevent recomputation
61 */
62#define ROUND(f, a, b, c, d, x, s) \
63 (a += f(b, c, d) + x, a = (a << s) | (a >> (32-s)))
64#define K1 0
65#define K2 013240474631UL
66#define K3 015666365641UL
67
68/*
69 * Basic cut-down MD4 transform. Returns only 32 bits of result.
70 */
71static void halfMD4Transform (__u32 buf[4], __u32 const in[])
72{
73 __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
74
75 /* Round 1 */
76 ROUND(F, a, b, c, d, in[0] + K1, 3);
77 ROUND(F, d, a, b, c, in[1] + K1, 7);
78 ROUND(F, c, d, a, b, in[2] + K1, 11);
79 ROUND(F, b, c, d, a, in[3] + K1, 19);
80 ROUND(F, a, b, c, d, in[4] + K1, 3);
81 ROUND(F, d, a, b, c, in[5] + K1, 7);
82 ROUND(F, c, d, a, b, in[6] + K1, 11);
83 ROUND(F, b, c, d, a, in[7] + K1, 19);
84
85 /* Round 2 */
86 ROUND(G, a, b, c, d, in[1] + K2, 3);
87 ROUND(G, d, a, b, c, in[3] + K2, 5);
88 ROUND(G, c, d, a, b, in[5] + K2, 9);
89 ROUND(G, b, c, d, a, in[7] + K2, 13);
90 ROUND(G, a, b, c, d, in[0] + K2, 3);
91 ROUND(G, d, a, b, c, in[2] + K2, 5);
92 ROUND(G, c, d, a, b, in[4] + K2, 9);
93 ROUND(G, b, c, d, a, in[6] + K2, 13);
94
95 /* Round 3 */
96 ROUND(H, a, b, c, d, in[3] + K3, 3);
97 ROUND(H, d, a, b, c, in[7] + K3, 9);
98 ROUND(H, c, d, a, b, in[2] + K3, 11);
99 ROUND(H, b, c, d, a, in[6] + K3, 15);
100 ROUND(H, a, b, c, d, in[1] + K3, 3);
101 ROUND(H, d, a, b, c, in[5] + K3, 9);
102 ROUND(H, c, d, a, b, in[0] + K3, 11);
103 ROUND(H, b, c, d, a, in[4] + K3, 15);
104
105 buf[0] += a;
106 buf[1] += b;
107 buf[2] += c;
108 buf[3] += d;
109}
110
111#undef ROUND
112#undef F
113#undef G
114#undef H
115#undef K1
116#undef K2
117#undef K3
118
119/* The old legacy hash */
120static ext2_dirhash_t dx_hack_hash (const char *name, int len)
121{
122 __u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
123 while (len--) {
124 __u32 hash = hash1 + (hash0 ^ (*name++ * 7152373));
125
126 if (hash & 0x80000000) hash -= 0x7fffffff;
127 hash1 = hash0;
128 hash0 = hash;
129 }
130 return (hash0 << 1);
131}
132
133static void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
134{
135 __u32 pad, val;
136 int i;
137
138 pad = (__u32)len | ((__u32)len << 8);
139 pad |= pad << 16;
140
141 val = pad;
142 if (len > num*4)
143 len = num * 4;
144 for (i=0; i < len; i++) {
145 if ((i % 4) == 0)
146 val = pad;
147 val = msg[i] + (val << 8);
148 if ((i % 4) == 3) {
149 *buf++ = val;
150 val = pad;
151 num--;
152 }
153 }
154 if (--num >= 0)
155 *buf++ = val;
156 while (--num >= 0)
157 *buf++ = pad;
158}
159
160/*
161 * Returns the hash of a filename. If len is 0 and name is NULL, then
162 * this function can be used to test whether or not a hash version is
163 * supported.
164 *
165 * The seed is an 4 longword (32 bits) "secret" which can be used to
166 * uniquify a hash. If the seed is all zero's, then some default seed
167 * may be used.
168 *
169 * A particular hash version specifies whether or not the seed is
170 * represented, and whether or not the returned hash is 32 bits or 64
171 * bits. 32 bit hashes will return 0 for the minor hash.
172 */
173errcode_t ext2fs_dirhash(int version, const char *name, int len,
174 const __u32 *seed,
175 ext2_dirhash_t *ret_hash,
176 ext2_dirhash_t *ret_minor_hash)
177{
178 __u32 hash;
179 __u32 minor_hash = 0;
180 const char *p;
181 int i;
182 __u32 in[8], buf[4];
183
184 /* Initialize the default seed for the hash checksum functions */
185 buf[0] = 0x67452301;
186 buf[1] = 0xefcdab89;
187 buf[2] = 0x98badcfe;
188 buf[3] = 0x10325476;
189
190 /* Check to see if the seed is all zero's */
191 if (seed) {
192 for (i=0; i < 4; i++) {
193 if (seed[i])
194 break;
195 }
196 if (i < 4)
197 memcpy(buf, seed, sizeof(buf));
198 }
199
200 switch (version) {
201 case EXT2_HASH_LEGACY:
202 hash = dx_hack_hash(name, len);
203 break;
204 case EXT2_HASH_HALF_MD4:
205 p = name;
206 while (len > 0) {
207 str2hashbuf(p, len, in, 8);
208 halfMD4Transform(buf, in);
209 len -= 32;
210 p += 32;
211 }
212 minor_hash = buf[2];
213 hash = buf[1];
214 break;
215 case EXT2_HASH_TEA:
216 p = name;
217 while (len > 0) {
218 str2hashbuf(p, len, in, 4);
219 TEA_transform(buf, in);
220 len -= 16;
221 p += 16;
222 }
223 hash = buf[0];
224 minor_hash = buf[1];
225 break;
226 default:
227 *ret_hash = 0;
228 return EXT2_ET_DIRHASH_UNSUPP;
229 }
230 *ret_hash = hash & ~1;
231 if (ret_minor_hash)
232 *ret_minor_hash = minor_hash;
233 return 0;
234}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/dupfs.c b/e2fsprogs/old_e2fsprogs/ext2fs/dupfs.c
deleted file mode 100644
index d1879377a..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/dupfs.c
+++ /dev/null
@@ -1,95 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * dupfs.c --- duplicate a ext2 filesystem handle
4 *
5 * Copyright (C) 1997, 1998, 2001, 2003, 2005 by Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#if HAVE_UNISTD_H
15#include <unistd.h>
16#endif
17#include <time.h>
18#include <string.h>
19
20#include "ext2_fs.h"
21#include "ext2fsP.h"
22
23errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest)
24{
25 ext2_filsys fs;
26 errcode_t retval;
27
28 EXT2_CHECK_MAGIC(src, EXT2_ET_MAGIC_EXT2FS_FILSYS);
29
30 retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
31 if (retval)
32 return retval;
33
34 *fs = *src;
35 fs->device_name = 0;
36 fs->super = 0;
37 fs->orig_super = 0;
38 fs->group_desc = 0;
39 fs->inode_map = 0;
40 fs->block_map = 0;
41 fs->badblocks = 0;
42 fs->dblist = 0;
43
44 io_channel_bumpcount(fs->io);
45 if (fs->icache)
46 fs->icache->refcount++;
47
48 retval = ext2fs_get_mem(strlen(src->device_name)+1, &fs->device_name);
49 if (retval)
50 goto errout;
51 strcpy(fs->device_name, src->device_name);
52
53 retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->super);
54 if (retval)
55 goto errout;
56 memcpy(fs->super, src->super, SUPERBLOCK_SIZE);
57
58 retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super);
59 if (retval)
60 goto errout;
61 memcpy(fs->orig_super, src->orig_super, SUPERBLOCK_SIZE);
62
63 retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize,
64 &fs->group_desc);
65 if (retval)
66 goto errout;
67 memcpy(fs->group_desc, src->group_desc,
68 (size_t) fs->desc_blocks * fs->blocksize);
69
70 if (src->inode_map) {
71 retval = ext2fs_copy_bitmap(src->inode_map, &fs->inode_map);
72 if (retval)
73 goto errout;
74 }
75 if (src->block_map) {
76 retval = ext2fs_copy_bitmap(src->block_map, &fs->block_map);
77 if (retval)
78 goto errout;
79 }
80 if (src->badblocks) {
81 retval = ext2fs_badblocks_copy(src->badblocks, &fs->badblocks);
82 if (retval)
83 goto errout;
84 }
85 if (src->dblist) {
86 retval = ext2fs_copy_dblist(src->dblist, &fs->dblist);
87 if (retval)
88 goto errout;
89 }
90 *dest = fs;
91 return 0;
92errout:
93 ext2fs_free(fs);
94 return retval;
95}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/e2image.h b/e2fsprogs/old_e2fsprogs/ext2fs/e2image.h
deleted file mode 100644
index a598d0111..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/e2image.h
+++ /dev/null
@@ -1,39 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * e2image.h --- header file describing the ext2 image format
4 *
5 * Copyright (C) 2000 Theodore Ts'o.
6 *
7 * Note: this uses the POSIX IO interfaces, unlike most of the other
8 * functions in this library. So sue me.
9 *
10 * %Begin-Header%
11 * This file may be redistributed under the terms of the GNU Public
12 * License.
13 * %End-Header%
14 */
15
16
17struct ext2_image_hdr {
18 __u32 magic_number; /* This must be EXT2_ET_MAGIC_E2IMAGE */
19 char magic_descriptor[16]; /* "Ext2 Image 1.0", w/ null padding */
20 char fs_hostname[64];/* Hostname of machine of image */
21 char fs_netaddr[32]; /* Network address */
22 __u32 fs_netaddr_type;/* 0 = IPV4, 1 = IPV6, etc. */
23 __u32 fs_device; /* Device number of image */
24 char fs_device_name[64]; /* Device name */
25 char fs_uuid[16]; /* UUID of filesystem */
26 __u32 fs_blocksize; /* Block size of the filesystem */
27 __u32 fs_reserved[8];
28
29 __u32 image_device; /* Device number of image file */
30 __u32 image_inode; /* Inode number of image file */
31 __u32 image_time; /* Time of image creation */
32 __u32 image_reserved[8];
33
34 __u32 offset_super; /* Byte offset of the sb and descriptors */
35 __u32 offset_inode; /* Byte offset of the inode table */
36 __u32 offset_inodemap; /* Byte offset of the inode bitmaps */
37 __u32 offset_blockmap; /* Byte offset of the inode bitmaps */
38 __u32 offset_reserved[8];
39};
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/expanddir.c b/e2fsprogs/old_e2fsprogs/ext2fs/expanddir.c
deleted file mode 100644
index 8a29ae584..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/expanddir.c
+++ /dev/null
@@ -1,127 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * expand.c --- expand an ext2fs directory
4 *
5 * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18
19#include "ext2_fs.h"
20#include "ext2fs.h"
21
22struct expand_dir_struct {
23 int done;
24 int newblocks;
25 errcode_t err;
26};
27
28static int expand_dir_proc(ext2_filsys fs,
29 blk_t *blocknr,
30 e2_blkcnt_t blockcnt,
31 blk_t ref_block EXT2FS_ATTR((unused)),
32 int ref_offset EXT2FS_ATTR((unused)),
33 void *priv_data)
34{
35 struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
36 blk_t new_blk;
37 static blk_t last_blk = 0;
38 char *block;
39 errcode_t retval;
40
41 if (*blocknr) {
42 last_blk = *blocknr;
43 return 0;
44 }
45 retval = ext2fs_new_block(fs, last_blk, 0, &new_blk);
46 if (retval) {
47 es->err = retval;
48 return BLOCK_ABORT;
49 }
50 if (blockcnt > 0) {
51 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
52 if (retval) {
53 es->err = retval;
54 return BLOCK_ABORT;
55 }
56 es->done = 1;
57 retval = ext2fs_write_dir_block(fs, new_blk, block);
58 } else {
59 retval = ext2fs_get_mem(fs->blocksize, &block);
60 if (retval) {
61 es->err = retval;
62 return BLOCK_ABORT;
63 }
64 memset(block, 0, fs->blocksize);
65 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
66 }
67 if (retval) {
68 es->err = retval;
69 return BLOCK_ABORT;
70 }
71 ext2fs_free_mem(&block);
72 *blocknr = new_blk;
73 ext2fs_block_alloc_stats(fs, new_blk, +1);
74 es->newblocks++;
75
76 if (es->done)
77 return (BLOCK_CHANGED | BLOCK_ABORT);
78 else
79 return BLOCK_CHANGED;
80}
81
82errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir)
83{
84 errcode_t retval;
85 struct expand_dir_struct es;
86 struct ext2_inode inode;
87
88 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
89
90 if (!(fs->flags & EXT2_FLAG_RW))
91 return EXT2_ET_RO_FILSYS;
92
93 if (!fs->block_map)
94 return EXT2_ET_NO_BLOCK_BITMAP;
95
96 retval = ext2fs_check_directory(fs, dir);
97 if (retval)
98 return retval;
99
100 es.done = 0;
101 es.err = 0;
102 es.newblocks = 0;
103
104 retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
105 0, expand_dir_proc, &es);
106
107 if (es.err)
108 return es.err;
109 if (!es.done)
110 return EXT2_ET_EXPAND_DIR_ERR;
111
112 /*
113 * Update the size and block count fields in the inode.
114 */
115 retval = ext2fs_read_inode(fs, dir, &inode);
116 if (retval)
117 return retval;
118
119 inode.i_size += fs->blocksize;
120 inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
121
122 retval = ext2fs_write_inode(fs, dir, &inode);
123 if (retval)
124 return retval;
125
126 return 0;
127}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/ext2_err.h b/e2fsprogs/old_e2fsprogs/ext2fs/ext2_err.h
deleted file mode 100644
index ead352810..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/ext2_err.h
+++ /dev/null
@@ -1,116 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * ext2_err.h:
4 * This file is automatically generated; please do not edit it.
5 */
6
7#define EXT2_ET_BASE (2133571328L)
8#define EXT2_ET_MAGIC_EXT2FS_FILSYS (2133571329L)
9#define EXT2_ET_MAGIC_BADBLOCKS_LIST (2133571330L)
10#define EXT2_ET_MAGIC_BADBLOCKS_ITERATE (2133571331L)
11#define EXT2_ET_MAGIC_INODE_SCAN (2133571332L)
12#define EXT2_ET_MAGIC_IO_CHANNEL (2133571333L)
13#define EXT2_ET_MAGIC_UNIX_IO_CHANNEL (2133571334L)
14#define EXT2_ET_MAGIC_IO_MANAGER (2133571335L)
15#define EXT2_ET_MAGIC_BLOCK_BITMAP (2133571336L)
16#define EXT2_ET_MAGIC_INODE_BITMAP (2133571337L)
17#define EXT2_ET_MAGIC_GENERIC_BITMAP (2133571338L)
18#define EXT2_ET_MAGIC_TEST_IO_CHANNEL (2133571339L)
19#define EXT2_ET_MAGIC_DBLIST (2133571340L)
20#define EXT2_ET_MAGIC_ICOUNT (2133571341L)
21#define EXT2_ET_MAGIC_PQ_IO_CHANNEL (2133571342L)
22#define EXT2_ET_MAGIC_EXT2_FILE (2133571343L)
23#define EXT2_ET_MAGIC_E2IMAGE (2133571344L)
24#define EXT2_ET_MAGIC_INODE_IO_CHANNEL (2133571345L)
25#define EXT2_ET_MAGIC_RESERVED_9 (2133571346L)
26#define EXT2_ET_BAD_MAGIC (2133571347L)
27#define EXT2_ET_REV_TOO_HIGH (2133571348L)
28#define EXT2_ET_RO_FILSYS (2133571349L)
29#define EXT2_ET_GDESC_READ (2133571350L)
30#define EXT2_ET_GDESC_WRITE (2133571351L)
31#define EXT2_ET_GDESC_BAD_BLOCK_MAP (2133571352L)
32#define EXT2_ET_GDESC_BAD_INODE_MAP (2133571353L)
33#define EXT2_ET_GDESC_BAD_INODE_TABLE (2133571354L)
34#define EXT2_ET_INODE_BITMAP_WRITE (2133571355L)
35#define EXT2_ET_INODE_BITMAP_READ (2133571356L)
36#define EXT2_ET_BLOCK_BITMAP_WRITE (2133571357L)
37#define EXT2_ET_BLOCK_BITMAP_READ (2133571358L)
38#define EXT2_ET_INODE_TABLE_WRITE (2133571359L)
39#define EXT2_ET_INODE_TABLE_READ (2133571360L)
40#define EXT2_ET_NEXT_INODE_READ (2133571361L)
41#define EXT2_ET_UNEXPECTED_BLOCK_SIZE (2133571362L)
42#define EXT2_ET_DIR_CORRUPTED (2133571363L)
43#define EXT2_ET_SHORT_READ (2133571364L)
44#define EXT2_ET_SHORT_WRITE (2133571365L)
45#define EXT2_ET_DIR_NO_SPACE (2133571366L)
46#define EXT2_ET_NO_INODE_BITMAP (2133571367L)
47#define EXT2_ET_NO_BLOCK_BITMAP (2133571368L)
48#define EXT2_ET_BAD_INODE_NUM (2133571369L)
49#define EXT2_ET_BAD_BLOCK_NUM (2133571370L)
50#define EXT2_ET_EXPAND_DIR_ERR (2133571371L)
51#define EXT2_ET_TOOSMALL (2133571372L)
52#define EXT2_ET_BAD_BLOCK_MARK (2133571373L)
53#define EXT2_ET_BAD_BLOCK_UNMARK (2133571374L)
54#define EXT2_ET_BAD_BLOCK_TEST (2133571375L)
55#define EXT2_ET_BAD_INODE_MARK (2133571376L)
56#define EXT2_ET_BAD_INODE_UNMARK (2133571377L)
57#define EXT2_ET_BAD_INODE_TEST (2133571378L)
58#define EXT2_ET_FUDGE_BLOCK_BITMAP_END (2133571379L)
59#define EXT2_ET_FUDGE_INODE_BITMAP_END (2133571380L)
60#define EXT2_ET_BAD_IND_BLOCK (2133571381L)
61#define EXT2_ET_BAD_DIND_BLOCK (2133571382L)
62#define EXT2_ET_BAD_TIND_BLOCK (2133571383L)
63#define EXT2_ET_NEQ_BLOCK_BITMAP (2133571384L)
64#define EXT2_ET_NEQ_INODE_BITMAP (2133571385L)
65#define EXT2_ET_BAD_DEVICE_NAME (2133571386L)
66#define EXT2_ET_MISSING_INODE_TABLE (2133571387L)
67#define EXT2_ET_CORRUPT_SUPERBLOCK (2133571388L)
68#define EXT2_ET_BAD_GENERIC_MARK (2133571389L)
69#define EXT2_ET_BAD_GENERIC_UNMARK (2133571390L)
70#define EXT2_ET_BAD_GENERIC_TEST (2133571391L)
71#define EXT2_ET_SYMLINK_LOOP (2133571392L)
72#define EXT2_ET_CALLBACK_NOTHANDLED (2133571393L)
73#define EXT2_ET_BAD_BLOCK_IN_INODE_TABLE (2133571394L)
74#define EXT2_ET_UNSUPP_FEATURE (2133571395L)
75#define EXT2_ET_RO_UNSUPP_FEATURE (2133571396L)
76#define EXT2_ET_LLSEEK_FAILED (2133571397L)
77#define EXT2_ET_NO_MEMORY (2133571398L)
78#define EXT2_ET_INVALID_ARGUMENT (2133571399L)
79#define EXT2_ET_BLOCK_ALLOC_FAIL (2133571400L)
80#define EXT2_ET_INODE_ALLOC_FAIL (2133571401L)
81#define EXT2_ET_NO_DIRECTORY (2133571402L)
82#define EXT2_ET_TOO_MANY_REFS (2133571403L)
83#define EXT2_ET_FILE_NOT_FOUND (2133571404L)
84#define EXT2_ET_FILE_RO (2133571405L)
85#define EXT2_ET_DB_NOT_FOUND (2133571406L)
86#define EXT2_ET_DIR_EXISTS (2133571407L)
87#define EXT2_ET_UNIMPLEMENTED (2133571408L)
88#define EXT2_ET_CANCEL_REQUESTED (2133571409L)
89#define EXT2_ET_FILE_TOO_BIG (2133571410L)
90#define EXT2_ET_JOURNAL_NOT_BLOCK (2133571411L)
91#define EXT2_ET_NO_JOURNAL_SB (2133571412L)
92#define EXT2_ET_JOURNAL_TOO_SMALL (2133571413L)
93#define EXT2_ET_JOURNAL_UNSUPP_VERSION (2133571414L)
94#define EXT2_ET_LOAD_EXT_JOURNAL (2133571415L)
95#define EXT2_ET_NO_JOURNAL (2133571416L)
96#define EXT2_ET_DIRHASH_UNSUPP (2133571417L)
97#define EXT2_ET_BAD_EA_BLOCK_NUM (2133571418L)
98#define EXT2_ET_TOO_MANY_INODES (2133571419L)
99#define EXT2_ET_NOT_IMAGE_FILE (2133571420L)
100#define EXT2_ET_RES_GDT_BLOCKS (2133571421L)
101#define EXT2_ET_RESIZE_INODE_CORRUPT (2133571422L)
102#define EXT2_ET_SET_BMAP_NO_IND (2133571423L)
103
104#if 0
105extern const struct error_table et_ext2_error_table;
106extern void initialize_ext2_error_table(void);
107
108/* For compatibility with Heimdal */
109extern void initialize_ext2_error_table_r(struct et_list **list);
110
111#define ERROR_TABLE_BASE_ext2 (2133571328L)
112
113/* for compatibility with older versions... */
114#define init_ext2_err_tbl initialize_ext2_error_table
115#define ext2_err_base ERROR_TABLE_BASE_ext2
116#endif
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/ext2_ext_attr.h b/e2fsprogs/old_e2fsprogs/ext2fs/ext2_ext_attr.h
deleted file mode 100644
index ca309c0d0..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/ext2_ext_attr.h
+++ /dev/null
@@ -1,52 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 File: linux/ext2_ext_attr.h
4
5 On-disk format of extended attributes for the ext2 filesystem.
6
7 (C) 2000 Andreas Gruenbacher, <a.gruenbacher@computer.org>
8*/
9
10/* Magic value in attribute blocks */
11#define EXT2_EXT_ATTR_MAGIC_v1 0xEA010000
12#define EXT2_EXT_ATTR_MAGIC 0xEA020000
13
14/* Maximum number of references to one attribute block */
15#define EXT2_EXT_ATTR_REFCOUNT_MAX 1024
16
17struct ext2_ext_attr_header {
18 __u32 h_magic; /* magic number for identification */
19 __u32 h_refcount; /* reference count */
20 __u32 h_blocks; /* number of disk blocks used */
21 __u32 h_hash; /* hash value of all attributes */
22 __u32 h_reserved[4]; /* zero right now */
23};
24
25struct ext2_ext_attr_entry {
26 __u8 e_name_len; /* length of name */
27 __u8 e_name_index; /* attribute name index */
28 __u16 e_value_offs; /* offset in disk block of value */
29 __u32 e_value_block; /* disk block attribute is stored on (n/i) */
30 __u32 e_value_size; /* size of attribute value */
31 __u32 e_hash; /* hash value of name and value */
32};
33
34#define EXT2_EXT_ATTR_PAD_BITS 2
35#define EXT2_EXT_ATTR_PAD (1<<EXT2_EXT_ATTR_PAD_BITS)
36#define EXT2_EXT_ATTR_ROUND (EXT2_EXT_ATTR_PAD-1)
37#define EXT2_EXT_ATTR_LEN(name_len) \
38 (((name_len) + EXT2_EXT_ATTR_ROUND + \
39 sizeof(struct ext2_ext_attr_entry)) & ~EXT2_EXT_ATTR_ROUND)
40#define EXT2_EXT_ATTR_NEXT(entry) \
41 ( (struct ext2_ext_attr_entry *)( \
42 (char *)(entry) + EXT2_EXT_ATTR_LEN((entry)->e_name_len)) )
43#define EXT2_EXT_ATTR_SIZE(size) \
44 (((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND)
45#define EXT2_EXT_IS_LAST_ENTRY(entry) (*((__u32 *)(entry)) == 0UL)
46#define EXT2_EXT_ATTR_NAME(entry) \
47 (((char *) (entry)) + sizeof(struct ext2_ext_attr_entry))
48#define EXT2_XATTR_LEN(name_len) \
49 (((name_len) + EXT2_EXT_ATTR_ROUND + \
50 sizeof(struct ext2_xattr_entry)) & ~EXT2_EXT_ATTR_ROUND)
51#define EXT2_XATTR_SIZE(size) \
52 (((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND)
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/ext2_fs.h b/e2fsprogs/old_e2fsprogs/ext2fs/ext2_fs.h
deleted file mode 100644
index 80ea2cbdd..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/ext2_fs.h
+++ /dev/null
@@ -1,569 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * linux/include/linux/ext2_fs.h
4 *
5 * Copyright (C) 1992, 1993, 1994, 1995
6 * Remy Card (card@masi.ibp.fr)
7 * Laboratoire MASI - Institut Blaise Pascal
8 * Universite Pierre et Marie Curie (Paris VI)
9 *
10 * from
11 *
12 * linux/include/linux/minix_fs.h
13 *
14 * Copyright (C) 1991, 1992 Linus Torvalds
15 */
16#ifndef LINUX_EXT2_FS_H
17#define LINUX_EXT2_FS_H 1
18
19#include "ext2_types.h" /* Changed from linux/types.h */
20
21/*
22 * Special inode numbers
23 */
24#define EXT2_BAD_INO 1 /* Bad blocks inode */
25#define EXT2_ROOT_INO 2 /* Root inode */
26#define EXT2_ACL_IDX_INO 3 /* ACL inode */
27#define EXT2_ACL_DATA_INO 4 /* ACL inode */
28#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
29#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
30#define EXT2_RESIZE_INO 7 /* Reserved group descriptors inode */
31#define EXT2_JOURNAL_INO 8 /* Journal inode */
32
33/* First non-reserved inode for old ext2 filesystems */
34#define EXT2_GOOD_OLD_FIRST_INO 11
35
36/*
37 * The second extended file system magic number
38 */
39#define EXT2_SUPER_MAGIC 0xEF53
40
41/* Assume that user mode programs are passing in an ext2fs superblock, not
42 * a kernel struct super_block. This will allow us to call the feature-test
43 * macros from user land. */
44#define EXT2_SB(sb) (sb)
45
46/*
47 * Maximal count of links to a file
48 */
49#define EXT2_LINK_MAX 32000
50
51/*
52 * Macro-instructions used to manage several block sizes
53 */
54#define EXT2_MIN_BLOCK_LOG_SIZE 10 /* 1024 */
55#define EXT2_MAX_BLOCK_LOG_SIZE 16 /* 65536 */
56#define EXT2_MIN_BLOCK_SIZE (1 << EXT2_MIN_BLOCK_LOG_SIZE)
57#define EXT2_MAX_BLOCK_SIZE (1 << EXT2_MAX_BLOCK_LOG_SIZE)
58#define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
59#define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
60#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
61 EXT2_GOOD_OLD_INODE_SIZE : (s)->s_inode_size)
62#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
63 EXT2_GOOD_OLD_FIRST_INO : (s)->s_first_ino)
64#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof(__u32))
65
66/*
67 * Macro-instructions used to manage fragments
68 */
69#define EXT2_MIN_FRAG_SIZE EXT2_MIN_BLOCK_SIZE
70#define EXT2_MAX_FRAG_SIZE EXT2_MAX_BLOCK_SIZE
71#define EXT2_MIN_FRAG_LOG_SIZE EXT2_MIN_BLOCK_LOG_SIZE
72# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size)
73# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
74
75/*
76 * ACL structures
77 */
78struct ext2_acl_header /* Header of Access Control Lists */
79{
80 __u32 aclh_size;
81 __u32 aclh_file_count;
82 __u32 aclh_acle_count;
83 __u32 aclh_first_acle;
84};
85
86struct ext2_acl_entry /* Access Control List Entry */
87{
88 __u32 acle_size;
89 __u16 acle_perms; /* Access permissions */
90 __u16 acle_type; /* Type of entry */
91 __u16 acle_tag; /* User or group identity */
92 __u16 acle_pad1;
93 __u32 acle_next; /* Pointer on next entry for the */
94 /* same inode or on next free entry */
95};
96
97/*
98 * Structure of a blocks group descriptor
99 */
100struct ext2_group_desc
101{
102 __u32 bg_block_bitmap; /* Blocks bitmap block */
103 __u32 bg_inode_bitmap; /* Inodes bitmap block */
104 __u32 bg_inode_table; /* Inodes table block */
105 __u16 bg_free_blocks_count; /* Free blocks count */
106 __u16 bg_free_inodes_count; /* Free inodes count */
107 __u16 bg_used_dirs_count; /* Directories count */
108 __u16 bg_pad;
109 __u32 bg_reserved[3];
110};
111
112/*
113 * Data structures used by the directory indexing feature
114 *
115 * Note: all of the multibyte integer fields are little endian.
116 */
117
118/*
119 * Note: dx_root_info is laid out so that if it should somehow get
120 * overlaid by a dirent the two low bits of the hash version will be
121 * zero. Therefore, the hash version mod 4 should never be 0.
122 * Sincerely, the paranoia department.
123 */
124struct ext2_dx_root_info {
125 __u32 reserved_zero;
126 __u8 hash_version; /* 0 now, 1 at release */
127 __u8 info_length; /* 8 */
128 __u8 indirect_levels;
129 __u8 unused_flags;
130};
131
132#define EXT2_HASH_LEGACY 0
133#define EXT2_HASH_HALF_MD4 1
134#define EXT2_HASH_TEA 2
135
136#define EXT2_HASH_FLAG_INCOMPAT 0x1
137
138struct ext2_dx_entry {
139 __u32 hash;
140 __u32 block;
141};
142
143struct ext2_dx_countlimit {
144 __u16 limit;
145 __u16 count;
146};
147
148
149/*
150 * Macro-instructions used to manage group descriptors
151 */
152#define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->s_blocks_per_group)
153#define EXT2_INODES_PER_GROUP(s) (EXT2_SB(s)->s_inodes_per_group)
154#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s))
155/* limits imposed by 16-bit value gd_free_{blocks,inode}_count */
156#define EXT2_MAX_BLOCKS_PER_GROUP(s) ((1 << 16) - 8)
157#define EXT2_MAX_INODES_PER_GROUP(s) ((1 << 16) - EXT2_INODES_PER_BLOCK(s))
158#define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
159
160/*
161 * Constants relative to the data blocks
162 */
163#define EXT2_NDIR_BLOCKS 12
164#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
165#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
166#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
167#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
168
169/*
170 * Inode flags
171 */
172#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */
173#define EXT2_UNRM_FL 0x00000002 /* Undelete */
174#define EXT2_COMPR_FL 0x00000004 /* Compress file */
175#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */
176#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */
177#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */
178#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */
179#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */
180/* Reserved for compression usage... */
181#define EXT2_DIRTY_FL 0x00000100
182#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
183#define EXT2_NOCOMPR_FL 0x00000400 /* Access raw compressed data */
184#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */
185/* End compression flags --- maybe not all used */
186#define EXT2_BTREE_FL 0x00001000 /* btree format dir */
187#define EXT2_INDEX_FL 0x00001000 /* hash-indexed directory */
188#define EXT2_IMAGIC_FL 0x00002000
189#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */
190#define EXT2_NOTAIL_FL 0x00008000 /* file tail should not be merged */
191#define EXT2_DIRSYNC_FL 0x00010000 /* Synchronous directory modifications */
192#define EXT2_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
193#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */
194#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
195
196#define EXT2_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */
197#define EXT2_FL_USER_MODIFIABLE 0x000080FF /* User modifiable flags */
198
199/*
200 * ioctl commands
201 */
202#define EXT2_IOC_GETFLAGS _IOR('f', 1, long)
203#define EXT2_IOC_SETFLAGS _IOW('f', 2, long)
204#define EXT2_IOC_GETVERSION _IOR('v', 1, long)
205#define EXT2_IOC_SETVERSION _IOW('v', 2, long)
206
207/*
208 * Structure of an inode on the disk
209 */
210struct ext2_inode {
211 __u16 i_mode; /* File mode */
212 __u16 i_uid; /* Low 16 bits of Owner Uid */
213 __u32 i_size; /* Size in bytes */
214 __u32 i_atime; /* Access time */
215 __u32 i_ctime; /* Creation time */
216 __u32 i_mtime; /* Modification time */
217 __u32 i_dtime; /* Deletion Time */
218 __u16 i_gid; /* Low 16 bits of Group Id */
219 __u16 i_links_count; /* Links count */
220 __u32 i_blocks; /* Blocks count */
221 __u32 i_flags; /* File flags */
222 union {
223 struct {
224 __u32 l_i_reserved1;
225 } linux1;
226 struct {
227 __u32 h_i_translator;
228 } hurd1;
229 struct {
230 __u32 m_i_reserved1;
231 } masix1;
232 } osd1; /* OS dependent 1 */
233 __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
234 __u32 i_generation; /* File version (for NFS) */
235 __u32 i_file_acl; /* File ACL */
236 __u32 i_dir_acl; /* Directory ACL */
237 __u32 i_faddr; /* Fragment address */
238 union {
239 struct {
240 __u8 l_i_frag; /* Fragment number */
241 __u8 l_i_fsize; /* Fragment size */
242 __u16 i_pad1;
243 __u16 l_i_uid_high; /* these 2 fields */
244 __u16 l_i_gid_high; /* were reserved2[0] */
245 __u32 l_i_reserved2;
246 } linux2;
247 struct {
248 __u8 h_i_frag; /* Fragment number */
249 __u8 h_i_fsize; /* Fragment size */
250 __u16 h_i_mode_high;
251 __u16 h_i_uid_high;
252 __u16 h_i_gid_high;
253 __u32 h_i_author;
254 } hurd2;
255 struct {
256 __u8 m_i_frag; /* Fragment number */
257 __u8 m_i_fsize; /* Fragment size */
258 __u16 m_pad1;
259 __u32 m_i_reserved2[2];
260 } masix2;
261 } osd2; /* OS dependent 2 */
262};
263
264/*
265 * Permanent part of an large inode on the disk
266 */
267struct ext2_inode_large {
268 __u16 i_mode; /* File mode */
269 __u16 i_uid; /* Low 16 bits of Owner Uid */
270 __u32 i_size; /* Size in bytes */
271 __u32 i_atime; /* Access time */
272 __u32 i_ctime; /* Creation time */
273 __u32 i_mtime; /* Modification time */
274 __u32 i_dtime; /* Deletion Time */
275 __u16 i_gid; /* Low 16 bits of Group Id */
276 __u16 i_links_count; /* Links count */
277 __u32 i_blocks; /* Blocks count */
278 __u32 i_flags; /* File flags */
279 union {
280 struct {
281 __u32 l_i_reserved1;
282 } linux1;
283 struct {
284 __u32 h_i_translator;
285 } hurd1;
286 struct {
287 __u32 m_i_reserved1;
288 } masix1;
289 } osd1; /* OS dependent 1 */
290 __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
291 __u32 i_generation; /* File version (for NFS) */
292 __u32 i_file_acl; /* File ACL */
293 __u32 i_dir_acl; /* Directory ACL */
294 __u32 i_faddr; /* Fragment address */
295 union {
296 struct {
297 __u8 l_i_frag; /* Fragment number */
298 __u8 l_i_fsize; /* Fragment size */
299 __u16 i_pad1;
300 __u16 l_i_uid_high; /* these 2 fields */
301 __u16 l_i_gid_high; /* were reserved2[0] */
302 __u32 l_i_reserved2;
303 } linux2;
304 struct {
305 __u8 h_i_frag; /* Fragment number */
306 __u8 h_i_fsize; /* Fragment size */
307 __u16 h_i_mode_high;
308 __u16 h_i_uid_high;
309 __u16 h_i_gid_high;
310 __u32 h_i_author;
311 } hurd2;
312 struct {
313 __u8 m_i_frag; /* Fragment number */
314 __u8 m_i_fsize; /* Fragment size */
315 __u16 m_pad1;
316 __u32 m_i_reserved2[2];
317 } masix2;
318 } osd2; /* OS dependent 2 */
319 __u16 i_extra_isize;
320 __u16 i_pad1;
321};
322
323#define i_size_high i_dir_acl
324
325/*
326 * File system states
327 */
328#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */
329#define EXT2_ERROR_FS 0x0002 /* Errors detected */
330
331/*
332 * Mount flags
333 */
334#define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */
335#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */
336#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */
337#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */
338#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */
339#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
340#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
341#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
342
343#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
344#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
345#define test_opt(sb, opt) (EXT2_SB(sb)->s_mount_opt & \
346 EXT2_MOUNT_##opt)
347/*
348 * Maximal mount counts between two filesystem checks
349 */
350#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */
351#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */
352
353/*
354 * Behaviour when detecting errors
355 */
356#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */
357#define EXT2_ERRORS_RO 2 /* Remount fs read-only */
358#define EXT2_ERRORS_PANIC 3 /* Panic */
359#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE
360
361/*
362 * Structure of the super block
363 */
364struct ext2_super_block {
365 __u32 s_inodes_count; /* Inodes count */
366 __u32 s_blocks_count; /* Blocks count */
367 __u32 s_r_blocks_count; /* Reserved blocks count */
368 __u32 s_free_blocks_count; /* Free blocks count */
369 __u32 s_free_inodes_count; /* Free inodes count */
370 __u32 s_first_data_block; /* First Data Block */
371 __u32 s_log_block_size; /* Block size */
372 __s32 s_log_frag_size; /* Fragment size */
373 __u32 s_blocks_per_group; /* # Blocks per group */
374 __u32 s_frags_per_group; /* # Fragments per group */
375 __u32 s_inodes_per_group; /* # Inodes per group */
376 __u32 s_mtime; /* Mount time */
377 __u32 s_wtime; /* Write time */
378 __u16 s_mnt_count; /* Mount count */
379 __s16 s_max_mnt_count; /* Maximal mount count */
380 __u16 s_magic; /* Magic signature */
381 __u16 s_state; /* File system state */
382 __u16 s_errors; /* Behaviour when detecting errors */
383 __u16 s_minor_rev_level; /* minor revision level */
384 __u32 s_lastcheck; /* time of last check */
385 __u32 s_checkinterval; /* max. time between checks */
386 __u32 s_creator_os; /* OS */
387 __u32 s_rev_level; /* Revision level */
388 __u16 s_def_resuid; /* Default uid for reserved blocks */
389 __u16 s_def_resgid; /* Default gid for reserved blocks */
390 /*
391 * These fields are for EXT2_DYNAMIC_REV superblocks only.
392 *
393 * Note: the difference between the compatible feature set and
394 * the incompatible feature set is that if there is a bit set
395 * in the incompatible feature set that the kernel doesn't
396 * know about, it should refuse to mount the filesystem.
397 *
398 * e2fsck's requirements are more strict; if it doesn't know
399 * about a feature in either the compatible or incompatible
400 * feature set, it must abort and not try to meddle with
401 * things it doesn't understand...
402 */
403 __u32 s_first_ino; /* First non-reserved inode */
404 __u16 s_inode_size; /* size of inode structure */
405 __u16 s_block_group_nr; /* block group # of this superblock */
406 __u32 s_feature_compat; /* compatible feature set */
407 __u32 s_feature_incompat; /* incompatible feature set */
408 __u32 s_feature_ro_compat; /* readonly-compatible feature set */
409 __u8 s_uuid[16]; /* 128-bit uuid for volume */
410 char s_volume_name[16]; /* volume name */
411 char s_last_mounted[64]; /* directory where last mounted */
412 __u32 s_algorithm_usage_bitmap; /* For compression */
413 /*
414 * Performance hints. Directory preallocation should only
415 * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
416 */
417 __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
418 __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
419 __u16 s_reserved_gdt_blocks; /* Per group table for online growth */
420 /*
421 * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
422 */
423 __u8 s_journal_uuid[16]; /* uuid of journal superblock */
424 __u32 s_journal_inum; /* inode number of journal file */
425 __u32 s_journal_dev; /* device number of journal file */
426 __u32 s_last_orphan; /* start of list of inodes to delete */
427 __u32 s_hash_seed[4]; /* HTREE hash seed */
428 __u8 s_def_hash_version; /* Default hash version to use */
429 __u8 s_jnl_backup_type; /* Default type of journal backup */
430 __u16 s_reserved_word_pad;
431 __u32 s_default_mount_opts;
432 __u32 s_first_meta_bg; /* First metablock group */
433 __u32 s_mkfs_time; /* When the filesystem was created */
434 __u32 s_jnl_blocks[17]; /* Backup of the journal inode */
435 __u32 s_reserved[172]; /* Padding to the end of the block */
436};
437
438/*
439 * Codes for operating systems
440 */
441#define EXT2_OS_LINUX 0
442#define EXT2_OS_HURD 1
443#define EXT2_OS_MASIX 2
444#define EXT2_OS_FREEBSD 3
445#define EXT2_OS_LITES 4
446
447/*
448 * Revision levels
449 */
450#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
451#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
452
453#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV
454#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV
455
456#define EXT2_GOOD_OLD_INODE_SIZE 128
457
458/*
459 * Journal inode backup types
460 */
461#define EXT3_JNL_BACKUP_BLOCKS 1
462
463/*
464 * Feature set definitions
465 */
466
467#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \
468 ( EXT2_SB(sb)->s_feature_compat & (mask) )
469#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \
470 ( EXT2_SB(sb)->s_feature_ro_compat & (mask) )
471#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \
472 ( EXT2_SB(sb)->s_feature_incompat & (mask) )
473
474#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001
475#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002
476#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
477#define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008
478#define EXT2_FEATURE_COMPAT_RESIZE_INO 0x0010
479#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020
480
481#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
482#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
483/* #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 not used */
484
485#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
486#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
487#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
488#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
489#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010
490#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040
491
492
493#define EXT2_FEATURE_COMPAT_SUPP 0
494#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE)
495#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
496 EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
497 EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
498
499/*
500 * Default values for user and/or group using reserved blocks
501 */
502#define EXT2_DEF_RESUID 0
503#define EXT2_DEF_RESGID 0
504
505/*
506 * Default mount options
507 */
508#define EXT2_DEFM_DEBUG 0x0001
509#define EXT2_DEFM_BSDGROUPS 0x0002
510#define EXT2_DEFM_XATTR_USER 0x0004
511#define EXT2_DEFM_ACL 0x0008
512#define EXT2_DEFM_UID16 0x0010
513#define EXT3_DEFM_JMODE 0x0060
514#define EXT3_DEFM_JMODE_DATA 0x0020
515#define EXT3_DEFM_JMODE_ORDERED 0x0040
516#define EXT3_DEFM_JMODE_WBACK 0x0060
517
518/*
519 * Structure of a directory entry
520 */
521#define EXT2_NAME_LEN 255
522
523struct ext2_dir_entry {
524 __u32 inode; /* Inode number */
525 __u16 rec_len; /* Directory entry length */
526 __u16 name_len; /* Name length */
527 char name[EXT2_NAME_LEN]; /* File name */
528};
529
530/*
531 * The new version of the directory entry. Since EXT2 structures are
532 * stored in intel byte order, and the name_len field could never be
533 * bigger than 255 chars, it's safe to reclaim the extra byte for the
534 * file_type field.
535 */
536struct ext2_dir_entry_2 {
537 __u32 inode; /* Inode number */
538 __u16 rec_len; /* Directory entry length */
539 __u8 name_len; /* Name length */
540 __u8 file_type;
541 char name[EXT2_NAME_LEN]; /* File name */
542};
543
544/*
545 * Ext2 directory file types. Only the low 3 bits are used. The
546 * other bits are reserved for now.
547 */
548#define EXT2_FT_UNKNOWN 0
549#define EXT2_FT_REG_FILE 1
550#define EXT2_FT_DIR 2
551#define EXT2_FT_CHRDEV 3
552#define EXT2_FT_BLKDEV 4
553#define EXT2_FT_FIFO 5
554#define EXT2_FT_SOCK 6
555#define EXT2_FT_SYMLINK 7
556
557#define EXT2_FT_MAX 8
558
559/*
560 * EXT2_DIR_PAD defines the directory entries boundaries
561 *
562 * NOTE: It must be a multiple of 4
563 */
564#define EXT2_DIR_PAD 4
565#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
566#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
567 ~EXT2_DIR_ROUND)
568
569#endif
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/ext2_io.h b/e2fsprogs/old_e2fsprogs/ext2fs/ext2_io.h
deleted file mode 100644
index 1900a7639..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/ext2_io.h
+++ /dev/null
@@ -1,112 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * io.h --- the I/O manager abstraction
4 *
5 * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12#ifndef EXT2FS_EXT2_IO_H
13#define EXT2FS_EXT2_IO_H 1
14
15/*
16 * ext2_loff_t is defined here since unix_io.c needs it.
17 */
18#if defined(__GNUC__) || defined(HAS_LONG_LONG)
19typedef long long ext2_loff_t;
20#else
21typedef long ext2_loff_t;
22#endif
23
24/* llseek.c */
25/* ext2_loff_t ext2fs_llseek (int, ext2_loff_t, int); */
26#ifdef CONFIG_LFS
27# define ext2fs_llseek lseek64
28#else
29# define ext2fs_llseek lseek
30#endif
31
32typedef struct struct_io_manager *io_manager;
33typedef struct struct_io_channel *io_channel;
34
35#define CHANNEL_FLAGS_WRITETHROUGH 0x01
36
37struct struct_io_channel {
38 errcode_t magic;
39 io_manager manager;
40 char *name;
41 int block_size;
42 errcode_t (*read_error)(io_channel channel,
43 unsigned long block,
44 int count,
45 void *data,
46 size_t size,
47 int actual_bytes_read,
48 errcode_t error);
49 errcode_t (*write_error)(io_channel channel,
50 unsigned long block,
51 int count,
52 const void *data,
53 size_t size,
54 int actual_bytes_written,
55 errcode_t error);
56 int refcount;
57 int flags;
58 int reserved[14];
59 void *private_data;
60 void *app_data;
61};
62
63struct struct_io_manager {
64 errcode_t magic;
65 const char *name;
66 errcode_t (*open)(const char *name, int flags, io_channel *channel);
67 errcode_t (*close)(io_channel channel);
68 errcode_t (*set_blksize)(io_channel channel, int blksize);
69 errcode_t (*read_blk)(io_channel channel, unsigned long block,
70 int count, void *data);
71 errcode_t (*write_blk)(io_channel channel, unsigned long block,
72 int count, const void *data);
73 errcode_t (*flush)(io_channel channel);
74 errcode_t (*write_byte)(io_channel channel, unsigned long offset,
75 int count, const void *data);
76 errcode_t (*set_option)(io_channel channel, const char *option,
77 const char *arg);
78 int reserved[14];
79};
80
81#define IO_FLAG_RW 1
82
83/*
84 * Convenience functions....
85 */
86#define io_channel_close(c) ((c)->manager->close((c)))
87#define io_channel_set_blksize(c,s) ((c)->manager->set_blksize((c),s))
88#define io_channel_read_blk(c,b,n,d) ((c)->manager->read_blk((c),b,n,d))
89#define io_channel_write_blk(c,b,n,d) ((c)->manager->write_blk((c),b,n,d))
90#define io_channel_flush(c) ((c)->manager->flush((c)))
91#define io_channel_bumpcount(c) ((c)->refcount++)
92
93/* io_manager.c */
94extern errcode_t io_channel_set_options(io_channel channel,
95 const char *options);
96extern errcode_t io_channel_write_byte(io_channel channel,
97 unsigned long offset,
98 int count, const void *data);
99
100/* unix_io.c */
101extern io_manager unix_io_manager;
102
103/* test_io.c */
104extern io_manager test_io_manager, test_io_backing_manager;
105extern void (*test_io_cb_read_blk)
106 (unsigned long block, int count, errcode_t err);
107extern void (*test_io_cb_write_blk)
108 (unsigned long block, int count, errcode_t err);
109extern void (*test_io_cb_set_blksize)
110 (int blksize, errcode_t err);
111
112#endif
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/ext2_types.h b/e2fsprogs/old_e2fsprogs/ext2fs/ext2_types.h
deleted file mode 100644
index 2c1196b8b..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/ext2_types.h
+++ /dev/null
@@ -1,2 +0,0 @@
1/* vi: set sw=4 ts=4: */
2#include <linux/types.h>
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs.h b/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs.h
deleted file mode 100644
index 39fb11620..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs.h
+++ /dev/null
@@ -1,922 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * ext2fs.h --- ext2fs
4 *
5 * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12#ifndef EXT2FS_EXT2FS_H
13#define EXT2FS_EXT2FS_H 1
14
15
16#define EXT2FS_ATTR(x)
17
18#ifdef __cplusplus
19extern "C" {
20#endif
21
22/*
23 * Where the master copy of the superblock is located, and how big
24 * superblocks are supposed to be. We define SUPERBLOCK_SIZE because
25 * the size of the superblock structure is not necessarily trustworthy
26 * (some versions have the padding set up so that the superblock is
27 * 1032 bytes long).
28 */
29#define SUPERBLOCK_OFFSET 1024
30#define SUPERBLOCK_SIZE 1024
31
32/*
33 * The last ext2fs revision level that this version of the library is
34 * able to support.
35 */
36#define EXT2_LIB_CURRENT_REV EXT2_DYNAMIC_REV
37
38#ifdef HAVE_SYS_TYPES_H
39#include <sys/types.h>
40#endif
41
42#include <stdio.h>
43#include <stdlib.h>
44
45#include "ext2_types.h"
46#include "ext2_fs.h"
47
48typedef __u32 ext2_ino_t;
49typedef __u32 blk_t;
50typedef __u32 dgrp_t;
51typedef __u32 ext2_off_t;
52typedef __s64 e2_blkcnt_t;
53typedef __u32 ext2_dirhash_t;
54
55#include "ext2_io.h"
56#include "ext2_err.h"
57
58typedef struct struct_ext2_filsys *ext2_filsys;
59
60struct ext2fs_struct_generic_bitmap {
61 errcode_t magic;
62 ext2_filsys fs;
63 __u32 start, end;
64 __u32 real_end;
65 char * description;
66 char * bitmap;
67 errcode_t base_error_code;
68 __u32 reserved[7];
69};
70
71#define EXT2FS_MARK_ERROR 0
72#define EXT2FS_UNMARK_ERROR 1
73#define EXT2FS_TEST_ERROR 2
74
75typedef struct ext2fs_struct_generic_bitmap *ext2fs_generic_bitmap;
76typedef struct ext2fs_struct_generic_bitmap *ext2fs_inode_bitmap;
77typedef struct ext2fs_struct_generic_bitmap *ext2fs_block_bitmap;
78
79#define EXT2_FIRST_INODE(s) EXT2_FIRST_INO(s)
80
81/*
82 * badblocks list definitions
83 */
84
85typedef struct ext2_struct_u32_list *ext2_badblocks_list;
86typedef struct ext2_struct_u32_iterate *ext2_badblocks_iterate;
87
88typedef struct ext2_struct_u32_list *ext2_u32_list;
89typedef struct ext2_struct_u32_iterate *ext2_u32_iterate;
90
91/* old */
92typedef struct ext2_struct_u32_list *badblocks_list;
93typedef struct ext2_struct_u32_iterate *badblocks_iterate;
94
95#define BADBLOCKS_FLAG_DIRTY 1
96
97/*
98 * ext2_dblist structure and abstractions (see dblist.c)
99 */
100struct ext2_db_entry {
101 ext2_ino_t ino;
102 blk_t blk;
103 int blockcnt;
104};
105
106typedef struct ext2_struct_dblist *ext2_dblist;
107
108#define DBLIST_ABORT 1
109
110/*
111 * ext2_fileio definitions
112 */
113
114#define EXT2_FILE_WRITE 0x0001
115#define EXT2_FILE_CREATE 0x0002
116
117#define EXT2_FILE_MASK 0x00FF
118
119#define EXT2_FILE_BUF_DIRTY 0x4000
120#define EXT2_FILE_BUF_VALID 0x2000
121
122typedef struct ext2_file *ext2_file_t;
123
124#define EXT2_SEEK_SET 0
125#define EXT2_SEEK_CUR 1
126#define EXT2_SEEK_END 2
127
128/*
129 * Flags for the ext2_filsys structure and for ext2fs_open()
130 */
131#define EXT2_FLAG_RW 0x01
132#define EXT2_FLAG_CHANGED 0x02
133#define EXT2_FLAG_DIRTY 0x04
134#define EXT2_FLAG_VALID 0x08
135#define EXT2_FLAG_IB_DIRTY 0x10
136#define EXT2_FLAG_BB_DIRTY 0x20
137#define EXT2_FLAG_SWAP_BYTES 0x40
138#define EXT2_FLAG_SWAP_BYTES_READ 0x80
139#define EXT2_FLAG_SWAP_BYTES_WRITE 0x100
140#define EXT2_FLAG_MASTER_SB_ONLY 0x200
141#define EXT2_FLAG_FORCE 0x400
142#define EXT2_FLAG_SUPER_ONLY 0x800
143#define EXT2_FLAG_JOURNAL_DEV_OK 0x1000
144#define EXT2_FLAG_IMAGE_FILE 0x2000
145
146/*
147 * Special flag in the ext2 inode i_flag field that means that this is
148 * a new inode. (So that ext2_write_inode() can clear extra fields.)
149 */
150#define EXT2_NEW_INODE_FL 0x80000000
151
152/*
153 * Flags for mkjournal
154 *
155 * EXT2_MKJOURNAL_V1_SUPER Make a (deprecated) V1 journal superblock
156 */
157#define EXT2_MKJOURNAL_V1_SUPER 0x0000001
158
159struct struct_ext2_filsys {
160 errcode_t magic;
161 io_channel io;
162 int flags;
163 char * device_name;
164 struct ext2_super_block * super;
165 unsigned int blocksize;
166 int fragsize;
167 dgrp_t group_desc_count;
168 unsigned long desc_blocks;
169 struct ext2_group_desc * group_desc;
170 int inode_blocks_per_group;
171 ext2fs_inode_bitmap inode_map;
172 ext2fs_block_bitmap block_map;
173 errcode_t (*get_blocks)(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks);
174 errcode_t (*check_directory)(ext2_filsys fs, ext2_ino_t ino);
175 errcode_t (*write_bitmaps)(ext2_filsys fs);
176 errcode_t (*read_inode)(ext2_filsys fs, ext2_ino_t ino,
177 struct ext2_inode *inode);
178 errcode_t (*write_inode)(ext2_filsys fs, ext2_ino_t ino,
179 struct ext2_inode *inode);
180 ext2_badblocks_list badblocks;
181 ext2_dblist dblist;
182 __u32 stride; /* for mke2fs */
183 struct ext2_super_block * orig_super;
184 struct ext2_image_hdr * image_header;
185 __u32 umask;
186 /*
187 * Reserved for future expansion
188 */
189 __u32 reserved[8];
190
191 /*
192 * Reserved for the use of the calling application.
193 */
194 void * priv_data;
195
196 /*
197 * Inode cache
198 */
199 struct ext2_inode_cache *icache;
200 io_channel image_io;
201};
202
203#include "bitops.h"
204
205/*
206 * Return flags for the block iterator functions
207 */
208#define BLOCK_CHANGED 1
209#define BLOCK_ABORT 2
210#define BLOCK_ERROR 4
211
212/*
213 * Block interate flags
214 *
215 * BLOCK_FLAG_APPEND, or BLOCK_FLAG_HOLE, indicates that the interator
216 * function should be called on blocks where the block number is zero.
217 * This is used by ext2fs_expand_dir() to be able to add a new block
218 * to an inode. It can also be used for programs that want to be able
219 * to deal with files that contain "holes".
220 *
221 * BLOCK_FLAG_TRAVERSE indicates that the iterator function for the
222 * indirect, doubly indirect, etc. blocks should be called after all
223 * of the blocks containined in the indirect blocks are processed.
224 * This is useful if you are going to be deallocating blocks from an
225 * inode.
226 *
227 * BLOCK_FLAG_DATA_ONLY indicates that the iterator function should be
228 * called for data blocks only.
229 *
230 * BLOCK_FLAG_NO_LARGE is for internal use only. It informs
231 * ext2fs_block_iterate2 that large files won't be accepted.
232 */
233#define BLOCK_FLAG_APPEND 1
234#define BLOCK_FLAG_HOLE 1
235#define BLOCK_FLAG_DEPTH_TRAVERSE 2
236#define BLOCK_FLAG_DATA_ONLY 4
237
238#define BLOCK_FLAG_NO_LARGE 0x1000
239
240/*
241 * Magic "block count" return values for the block iterator function.
242 */
243#define BLOCK_COUNT_IND (-1)
244#define BLOCK_COUNT_DIND (-2)
245#define BLOCK_COUNT_TIND (-3)
246#define BLOCK_COUNT_TRANSLATOR (-4)
247
248#if 0
249/*
250 * Flags for ext2fs_move_blocks
251 */
252#define EXT2_BMOVE_GET_DBLIST 0x0001
253#define EXT2_BMOVE_DEBUG 0x0002
254#endif
255
256/*
257 * Flags for directory block reading and writing functions
258 */
259#define EXT2_DIRBLOCK_V2_STRUCT 0x0001
260
261/*
262 * Return flags for the directory iterator functions
263 */
264#define DIRENT_CHANGED 1
265#define DIRENT_ABORT 2
266#define DIRENT_ERROR 3
267
268/*
269 * Directory iterator flags
270 */
271
272#define DIRENT_FLAG_INCLUDE_EMPTY 1
273#define DIRENT_FLAG_INCLUDE_REMOVED 2
274
275#define DIRENT_DOT_FILE 1
276#define DIRENT_DOT_DOT_FILE 2
277#define DIRENT_OTHER_FILE 3
278#define DIRENT_DELETED_FILE 4
279
280/*
281 * Inode scan definitions
282 */
283typedef struct ext2_struct_inode_scan *ext2_inode_scan;
284
285/*
286 * ext2fs_scan flags
287 */
288#define EXT2_SF_CHK_BADBLOCKS 0x0001
289#define EXT2_SF_BAD_INODE_BLK 0x0002
290#define EXT2_SF_BAD_EXTRA_BYTES 0x0004
291#define EXT2_SF_SKIP_MISSING_ITABLE 0x0008
292
293/*
294 * ext2fs_check_if_mounted flags
295 */
296#define EXT2_MF_MOUNTED 1
297#define EXT2_MF_ISROOT 2
298#define EXT2_MF_READONLY 4
299#define EXT2_MF_SWAP 8
300#define EXT2_MF_BUSY 16
301
302/*
303 * Ext2/linux mode flags. We define them here so that we don't need
304 * to depend on the OS's sys/stat.h, since we may be compiling on a
305 * non-Linux system.
306 */
307#define LINUX_S_IFMT 00170000
308#define LINUX_S_IFSOCK 0140000
309#define LINUX_S_IFLNK 0120000
310#define LINUX_S_IFREG 0100000
311#define LINUX_S_IFBLK 0060000
312#define LINUX_S_IFDIR 0040000
313#define LINUX_S_IFCHR 0020000
314#define LINUX_S_IFIFO 0010000
315#define LINUX_S_ISUID 0004000
316#define LINUX_S_ISGID 0002000
317#define LINUX_S_ISVTX 0001000
318
319#define LINUX_S_IRWXU 00700
320#define LINUX_S_IRUSR 00400
321#define LINUX_S_IWUSR 00200
322#define LINUX_S_IXUSR 00100
323
324#define LINUX_S_IRWXG 00070
325#define LINUX_S_IRGRP 00040
326#define LINUX_S_IWGRP 00020
327#define LINUX_S_IXGRP 00010
328
329#define LINUX_S_IRWXO 00007
330#define LINUX_S_IROTH 00004
331#define LINUX_S_IWOTH 00002
332#define LINUX_S_IXOTH 00001
333
334#define LINUX_S_ISLNK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFLNK)
335#define LINUX_S_ISREG(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFREG)
336#define LINUX_S_ISDIR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFDIR)
337#define LINUX_S_ISCHR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFCHR)
338#define LINUX_S_ISBLK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFBLK)
339#define LINUX_S_ISFIFO(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFIFO)
340#define LINUX_S_ISSOCK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFSOCK)
341
342/*
343 * ext2 size of an inode
344 */
345#define EXT2_I_SIZE(i) ((i)->i_size | ((__u64) (i)->i_size_high << 32))
346
347/*
348 * ext2_icount_t abstraction
349 */
350#define EXT2_ICOUNT_OPT_INCREMENT 0x01
351
352typedef struct ext2_icount *ext2_icount_t;
353
354/*
355 * Flags for ext2fs_bmap
356 */
357#define BMAP_ALLOC 0x0001
358#define BMAP_SET 0x0002
359
360/*
361 * Flags for imager.c functions
362 */
363#define IMAGER_FLAG_INODEMAP 1
364#define IMAGER_FLAG_SPARSEWRITE 2
365
366/*
367 * For checking structure magic numbers...
368 */
369
370#define EXT2_CHECK_MAGIC(struct, code) \
371 if ((struct)->magic != (code)) return (code)
372
373
374/*
375 * For ext2 compression support
376 */
377#define EXT2FS_COMPRESSED_BLKADDR ((blk_t) 0xffffffff)
378#define HOLE_BLKADDR(_b) ((_b) == 0 || (_b) == EXT2FS_COMPRESSED_BLKADDR)
379
380/*
381 * Features supported by this version of the library
382 */
383#define EXT2_LIB_FEATURE_COMPAT_SUPP (EXT2_FEATURE_COMPAT_DIR_PREALLOC|\
384 EXT2_FEATURE_COMPAT_IMAGIC_INODES|\
385 EXT3_FEATURE_COMPAT_HAS_JOURNAL|\
386 EXT2_FEATURE_COMPAT_RESIZE_INO|\
387 EXT2_FEATURE_COMPAT_DIR_INDEX|\
388 EXT2_FEATURE_COMPAT_EXT_ATTR)
389
390/* This #ifdef is temporary until compression is fully supported */
391#ifdef ENABLE_COMPRESSION
392#ifndef I_KNOW_THAT_COMPRESSION_IS_EXPERIMENTAL
393/* If the below warning bugs you, then have
394 `CPPFLAGS=-DI_KNOW_THAT_COMPRESSION_IS_EXPERIMENTAL' in your
395 environment at configure time. */
396 #warning "Compression support is experimental"
397#endif
398#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\
399 EXT2_FEATURE_INCOMPAT_COMPRESSION|\
400 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
401 EXT2_FEATURE_INCOMPAT_META_BG|\
402 EXT3_FEATURE_INCOMPAT_RECOVER)
403#else
404#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\
405 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
406 EXT2_FEATURE_INCOMPAT_META_BG|\
407 EXT3_FEATURE_INCOMPAT_RECOVER)
408#endif
409#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
410 EXT2_FEATURE_RO_COMPAT_LARGE_FILE)
411/*
412 * function prototypes
413 */
414
415/* alloc.c */
416extern errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir, int mode,
417 ext2fs_inode_bitmap map, ext2_ino_t *ret);
418extern errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
419 ext2fs_block_bitmap map, blk_t *ret);
420extern errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start,
421 blk_t finish, int num,
422 ext2fs_block_bitmap map,
423 blk_t *ret);
424extern errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
425 char *block_buf, blk_t *ret);
426
427/* alloc_sb.c */
428extern int ext2fs_reserve_super_and_bgd(ext2_filsys fs,
429 dgrp_t group,
430 ext2fs_block_bitmap bmap);
431
432/* alloc_stats.c */
433void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse);
434void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino,
435 int inuse, int isdir);
436void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse);
437
438/* alloc_tables.c */
439extern errcode_t ext2fs_allocate_tables(ext2_filsys fs);
440extern errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
441 ext2fs_block_bitmap bmap);
442
443/* badblocks.c */
444extern errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size);
445extern errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk);
446extern int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk);
447extern int ext2fs_u32_list_test(ext2_u32_list bb, blk_t blk);
448extern errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb,
449 ext2_u32_iterate *ret);
450extern int ext2fs_u32_list_iterate(ext2_u32_iterate iter, blk_t *blk);
451extern void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter);
452extern errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest);
453extern int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2);
454
455extern errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret,
456 int size);
457extern errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb,
458 blk_t blk);
459extern int ext2fs_badblocks_list_test(ext2_badblocks_list bb,
460 blk_t blk);
461extern int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk);
462extern void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk);
463extern errcode_t
464 ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
465 ext2_badblocks_iterate *ret);
466extern int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter,
467 blk_t *blk);
468extern void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter);
469extern errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
470 ext2_badblocks_list *dest);
471extern int ext2fs_badblocks_equal(ext2_badblocks_list bb1,
472 ext2_badblocks_list bb2);
473extern int ext2fs_u32_list_count(ext2_u32_list bb);
474
475/* bb_compat */
476extern errcode_t badblocks_list_create(badblocks_list *ret, int size);
477extern errcode_t badblocks_list_add(badblocks_list bb, blk_t blk);
478extern int badblocks_list_test(badblocks_list bb, blk_t blk);
479extern errcode_t badblocks_list_iterate_begin(badblocks_list bb,
480 badblocks_iterate *ret);
481extern int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk);
482extern void badblocks_list_iterate_end(badblocks_iterate iter);
483extern void badblocks_list_free(badblocks_list bb);
484
485/* bb_inode.c */
486extern errcode_t ext2fs_update_bb_inode(ext2_filsys fs,
487 ext2_badblocks_list bb_list);
488
489/* bitmaps.c */
490extern errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs);
491extern errcode_t ext2fs_write_block_bitmap (ext2_filsys fs);
492extern errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs);
493extern errcode_t ext2fs_read_block_bitmap(ext2_filsys fs);
494extern errcode_t ext2fs_allocate_generic_bitmap(__u32 start,
495 __u32 end,
496 __u32 real_end,
497 const char *descr,
498 ext2fs_generic_bitmap *ret);
499extern errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
500 const char *descr,
501 ext2fs_block_bitmap *ret);
502extern errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs,
503 const char *descr,
504 ext2fs_inode_bitmap *ret);
505extern errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap,
506 ext2_ino_t end, ext2_ino_t *oend);
507extern errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap,
508 blk_t end, blk_t *oend);
509extern void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap);
510extern void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap);
511extern errcode_t ext2fs_read_bitmaps(ext2_filsys fs);
512extern errcode_t ext2fs_write_bitmaps(ext2_filsys fs);
513
514/* block.c */
515extern errcode_t ext2fs_block_iterate(ext2_filsys fs,
516 ext2_ino_t ino,
517 int flags,
518 char *block_buf,
519 int (*func)(ext2_filsys fs,
520 blk_t *blocknr,
521 int blockcnt,
522 void *priv_data),
523 void *priv_data);
524errcode_t ext2fs_block_iterate2(ext2_filsys fs,
525 ext2_ino_t ino,
526 int flags,
527 char *block_buf,
528 int (*func)(ext2_filsys fs,
529 blk_t *blocknr,
530 e2_blkcnt_t blockcnt,
531 blk_t ref_blk,
532 int ref_offset,
533 void *priv_data),
534 void *priv_data);
535
536/* bmap.c */
537extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino,
538 struct ext2_inode *inode,
539 char *block_buf, int bmap_flags,
540 blk_t block, blk_t *phys_blk);
541
542
543#if 0
544/* bmove.c */
545extern errcode_t ext2fs_move_blocks(ext2_filsys fs,
546 ext2fs_block_bitmap reserve,
547 ext2fs_block_bitmap alloc_map,
548 int flags);
549#endif
550
551/* check_desc.c */
552extern errcode_t ext2fs_check_desc(ext2_filsys fs);
553
554/* closefs.c */
555extern errcode_t ext2fs_close(ext2_filsys fs);
556extern errcode_t ext2fs_flush(ext2_filsys fs);
557extern int ext2fs_bg_has_super(ext2_filsys fs, int group_block);
558extern int ext2fs_super_and_bgd_loc(ext2_filsys fs,
559 dgrp_t group,
560 blk_t *ret_super_blk,
561 blk_t *ret_old_desc_blk,
562 blk_t *ret_new_desc_blk,
563 int *ret_meta_bg);
564extern void ext2fs_update_dynamic_rev(ext2_filsys fs);
565
566/* cmp_bitmaps.c */
567extern errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
568 ext2fs_block_bitmap bm2);
569extern errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
570 ext2fs_inode_bitmap bm2);
571
572/* dblist.c */
573
574extern errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs);
575extern errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist);
576extern errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino,
577 blk_t blk, int blockcnt);
578extern void ext2fs_dblist_sort(ext2_dblist dblist,
579 int (*sortfunc)(const void *,
580 const void *));
581extern errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
582 int (*func)(ext2_filsys fs, struct ext2_db_entry *db_info,
583 void *priv_data),
584 void *priv_data);
585extern errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino,
586 blk_t blk, int blockcnt);
587extern errcode_t ext2fs_copy_dblist(ext2_dblist src,
588 ext2_dblist *dest);
589extern int ext2fs_dblist_count(ext2_dblist dblist);
590
591/* dblist_dir.c */
592extern errcode_t
593 ext2fs_dblist_dir_iterate(ext2_dblist dblist,
594 int flags,
595 char *block_buf,
596 int (*func)(ext2_ino_t dir,
597 int entry,
598 struct ext2_dir_entry *dirent,
599 int offset,
600 int blocksize,
601 char *buf,
602 void *priv_data),
603 void *priv_data);
604
605/* dirblock.c */
606extern errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
607 void *buf);
608extern errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
609 void *buf, int flags);
610extern errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
611 void *buf);
612extern errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
613 void *buf, int flags);
614
615/* dirhash.c */
616extern errcode_t ext2fs_dirhash(int version, const char *name, int len,
617 const __u32 *seed,
618 ext2_dirhash_t *ret_hash,
619 ext2_dirhash_t *ret_minor_hash);
620
621
622/* dir_iterate.c */
623extern errcode_t ext2fs_dir_iterate(ext2_filsys fs,
624 ext2_ino_t dir,
625 int flags,
626 char *block_buf,
627 int (*func)(struct ext2_dir_entry *dirent,
628 int offset,
629 int blocksize,
630 char *buf,
631 void *priv_data),
632 void *priv_data);
633extern errcode_t ext2fs_dir_iterate2(ext2_filsys fs,
634 ext2_ino_t dir,
635 int flags,
636 char *block_buf,
637 int (*func)(ext2_ino_t dir,
638 int entry,
639 struct ext2_dir_entry *dirent,
640 int offset,
641 int blocksize,
642 char *buf,
643 void *priv_data),
644 void *priv_data);
645
646/* dupfs.c */
647extern errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest);
648
649/* expanddir.c */
650extern errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir);
651
652/* ext_attr.c */
653extern errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf);
654extern errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block,
655 void *buf);
656extern errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk,
657 char *block_buf,
658 int adjust, __u32 *newcount);
659
660/* fileio.c */
661extern errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
662 struct ext2_inode *inode,
663 int flags, ext2_file_t *ret);
664extern errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino,
665 int flags, ext2_file_t *ret);
666extern ext2_filsys ext2fs_file_get_fs(ext2_file_t file);
667extern errcode_t ext2fs_file_close(ext2_file_t file);
668extern errcode_t ext2fs_file_flush(ext2_file_t file);
669extern errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
670 unsigned int wanted, unsigned int *got);
671extern errcode_t ext2fs_file_write(ext2_file_t file, const void *buf,
672 unsigned int nbytes, unsigned int *written);
673extern errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset,
674 int whence, __u64 *ret_pos);
675extern errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
676 int whence, ext2_off_t *ret_pos);
677errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size);
678extern ext2_off_t ext2fs_file_get_size(ext2_file_t file);
679extern errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size);
680
681/* finddev.c */
682extern char *ext2fs_find_block_device(dev_t device);
683
684/* flushb.c */
685extern errcode_t ext2fs_sync_device(int fd, int flushb);
686
687/* freefs.c */
688extern void ext2fs_free(ext2_filsys fs);
689extern void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap);
690extern void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap);
691extern void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap);
692extern void ext2fs_free_dblist(ext2_dblist dblist);
693extern void ext2fs_badblocks_list_free(ext2_badblocks_list bb);
694extern void ext2fs_u32_list_free(ext2_u32_list bb);
695
696/* getsize.c */
697extern errcode_t ext2fs_get_device_size(const char *file, int blocksize,
698 blk_t *retblocks);
699
700/* getsectsize.c */
701errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize);
702
703/* imager.c */
704extern errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags);
705extern errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd, int flags);
706extern errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, int flags);
707extern errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd, int flags);
708extern errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags);
709extern errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags);
710
711/* ind_block.c */
712errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf);
713errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf);
714
715/* initialize.c */
716extern errcode_t ext2fs_initialize(const char *name, int flags,
717 struct ext2_super_block *param,
718 io_manager manager, ext2_filsys *ret_fs);
719
720/* icount.c */
721extern void ext2fs_free_icount(ext2_icount_t icount);
722extern errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags,
723 unsigned int size,
724 ext2_icount_t hint, ext2_icount_t *ret);
725extern errcode_t ext2fs_create_icount(ext2_filsys fs, int flags,
726 unsigned int size,
727 ext2_icount_t *ret);
728extern errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino,
729 __u16 *ret);
730extern errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino,
731 __u16 *ret);
732extern errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
733 __u16 *ret);
734extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
735 __u16 count);
736extern ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount);
737errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *);
738
739/* inode.c */
740extern errcode_t ext2fs_flush_icache(ext2_filsys fs);
741extern errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan,
742 ext2_ino_t *ino,
743 struct ext2_inode *inode,
744 int bufsize);
745extern errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
746 ext2_inode_scan *ret_scan);
747extern void ext2fs_close_inode_scan(ext2_inode_scan scan);
748extern errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino,
749 struct ext2_inode *inode);
750extern errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,
751 int group);
752extern void ext2fs_set_inode_callback
753 (ext2_inode_scan scan,
754 errcode_t (*done_group)(ext2_filsys fs,
755 dgrp_t group,
756 void * priv_data),
757 void *done_group_data);
758extern int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags,
759 int clear_flags);
760extern errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
761 struct ext2_inode * inode,
762 int bufsize);
763extern errcode_t ext2fs_read_inode (ext2_filsys fs, ext2_ino_t ino,
764 struct ext2_inode * inode);
765extern errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino,
766 struct ext2_inode * inode,
767 int bufsize);
768extern errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino,
769 struct ext2_inode * inode);
770extern errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino,
771 struct ext2_inode * inode);
772extern errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks);
773extern errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino);
774
775/* inode_io.c */
776extern io_manager inode_io_manager;
777extern errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino,
778 char **name);
779extern errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino,
780 struct ext2_inode *inode,
781 char **name);
782
783/* ismounted.c */
784extern errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags);
785extern errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags,
786 char *mtpt, int mtlen);
787
788/* namei.c */
789extern errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name,
790 int namelen, char *buf, ext2_ino_t *inode);
791extern errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
792 const char *name, ext2_ino_t *inode);
793errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
794 const char *name, ext2_ino_t *inode);
795extern errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
796 ext2_ino_t inode, ext2_ino_t *res_inode);
797
798/* native.c */
799int ext2fs_native_flag(void);
800
801/* newdir.c */
802extern errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino,
803 ext2_ino_t parent_ino, char **block);
804
805/* mkdir.c */
806extern errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
807 const char *name);
808
809/* mkjournal.c */
810extern errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
811 __u32 size, int flags,
812 char **ret_jsb);
813extern errcode_t ext2fs_add_journal_device(ext2_filsys fs,
814 ext2_filsys journal_dev);
815extern errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size,
816 int flags);
817
818/* openfs.c */
819extern errcode_t ext2fs_open(const char *name, int flags, int superblock,
820 unsigned int block_size, io_manager manager,
821 ext2_filsys *ret_fs);
822extern errcode_t ext2fs_open2(const char *name, const char *io_options,
823 int flags, int superblock,
824 unsigned int block_size, io_manager manager,
825 ext2_filsys *ret_fs);
826extern blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block,
827 dgrp_t i);
828errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io);
829errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io);
830errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io);
831
832/* get_pathname.c */
833extern errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino,
834 char **name);
835
836/* link.c */
837errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name,
838 ext2_ino_t ino, int flags);
839errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir, const char *name,
840 ext2_ino_t ino, int flags);
841
842/* read_bb.c */
843extern errcode_t ext2fs_read_bb_inode(ext2_filsys fs,
844 ext2_badblocks_list *bb_list);
845
846/* read_bb_file.c */
847extern errcode_t ext2fs_read_bb_FILE2(ext2_filsys fs, FILE *f,
848 ext2_badblocks_list *bb_list,
849 void *priv_data,
850 void (*invalid)(ext2_filsys fs,
851 blk_t blk,
852 char *badstr,
853 void *priv_data));
854extern errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f,
855 ext2_badblocks_list *bb_list,
856 void (*invalid)(ext2_filsys fs,
857 blk_t blk));
858
859/* res_gdt.c */
860extern errcode_t ext2fs_create_resize_inode(ext2_filsys fs);
861
862/* rs_bitmap.c */
863extern errcode_t ext2fs_resize_generic_bitmap(__u32 new_end,
864 __u32 new_real_end,
865 ext2fs_generic_bitmap bmap);
866extern errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
867 ext2fs_inode_bitmap bmap);
868extern errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
869 ext2fs_block_bitmap bmap);
870extern errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
871 ext2fs_generic_bitmap *dest);
872
873/* swapfs.c */
874extern void ext2fs_swap_ext_attr(char *to, char *from, int bufsize,
875 int has_header);
876extern void ext2fs_swap_super(struct ext2_super_block * super);
877extern void ext2fs_swap_group_desc(struct ext2_group_desc *gdp);
878extern void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t,
879 struct ext2_inode_large *f, int hostorder,
880 int bufsize);
881extern void ext2fs_swap_inode(ext2_filsys fs,struct ext2_inode *t,
882 struct ext2_inode *f, int hostorder);
883
884/* valid_blk.c */
885extern int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode);
886
887/* version.c */
888extern int ext2fs_parse_version_string(const char *ver_string);
889extern int ext2fs_get_library_version(const char **ver_string,
890 const char **date_string);
891
892/* write_bb_file.c */
893extern errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list,
894 unsigned int flags,
895 FILE *f);
896
897
898/* inline functions */
899extern errcode_t ext2fs_get_mem(unsigned long size, void *ptr);
900extern errcode_t ext2fs_free_mem(void *ptr);
901extern errcode_t ext2fs_resize_mem(unsigned long old_size,
902 unsigned long size, void *ptr);
903extern void ext2fs_mark_super_dirty(ext2_filsys fs);
904extern void ext2fs_mark_changed(ext2_filsys fs);
905extern int ext2fs_test_changed(ext2_filsys fs);
906extern void ext2fs_mark_valid(ext2_filsys fs);
907extern void ext2fs_unmark_valid(ext2_filsys fs);
908extern int ext2fs_test_valid(ext2_filsys fs);
909extern void ext2fs_mark_ib_dirty(ext2_filsys fs);
910extern void ext2fs_mark_bb_dirty(ext2_filsys fs);
911extern int ext2fs_test_ib_dirty(ext2_filsys fs);
912extern int ext2fs_test_bb_dirty(ext2_filsys fs);
913extern int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk);
914extern int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino);
915extern blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
916 struct ext2_inode *inode);
917
918#ifdef __cplusplus
919}
920#endif
921
922#endif
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/ext2fsP.h b/e2fsprogs/old_e2fsprogs/ext2fs/ext2fsP.h
deleted file mode 100644
index 7a02e9a8e..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/ext2fsP.h
+++ /dev/null
@@ -1,87 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * ext2fsP.h --- private header file for ext2 library
4 *
5 * Copyright (C) 1997 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include "ext2fs.h"
14
15/*
16 * Badblocks list
17 */
18struct ext2_struct_u32_list {
19 int magic;
20 int num;
21 int size;
22 __u32 *list;
23 int badblocks_flags;
24};
25
26struct ext2_struct_u32_iterate {
27 int magic;
28 ext2_u32_list bb;
29 int ptr;
30};
31
32
33/*
34 * Directory block iterator definition
35 */
36struct ext2_struct_dblist {
37 int magic;
38 ext2_filsys fs;
39 ext2_ino_t size;
40 ext2_ino_t count;
41 int sorted;
42 struct ext2_db_entry * list;
43};
44
45/*
46 * For directory iterators
47 */
48struct dir_context {
49 ext2_ino_t dir;
50 int flags;
51 char *buf;
52 int (*func)(ext2_ino_t dir,
53 int entry,
54 struct ext2_dir_entry *dirent,
55 int offset,
56 int blocksize,
57 char *buf,
58 void *priv_data);
59 void *priv_data;
60 errcode_t errcode;
61};
62
63/*
64 * Inode cache structure
65 */
66struct ext2_inode_cache {
67 void * buffer;
68 blk_t buffer_blk;
69 int cache_last;
70 int cache_size;
71 int refcount;
72 struct ext2_inode_cache_ent *cache;
73};
74
75struct ext2_inode_cache_ent {
76 ext2_ino_t ino;
77 struct ext2_inode inode;
78};
79
80/* Function prototypes */
81
82extern int ext2fs_process_dir_block(ext2_filsys fs,
83 blk_t *blocknr,
84 e2_blkcnt_t blockcnt,
85 blk_t ref_block,
86 int ref_offset,
87 void *priv_data);
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs_inline.c b/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs_inline.c
deleted file mode 100644
index 7d37d232d..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs_inline.c
+++ /dev/null
@@ -1,365 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * ext2fs.h --- ext2fs
4 *
5 * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include "ext2fs.h"
14#include "bitops.h"
15#include <string.h>
16
17/*
18 * Allocate memory
19 */
20errcode_t ext2fs_get_mem(unsigned long size, void *ptr)
21{
22 void **pp = (void **)ptr;
23
24 *pp = malloc(size);
25 if (!*pp)
26 return EXT2_ET_NO_MEMORY;
27 return 0;
28}
29
30/*
31 * Free memory
32 */
33errcode_t ext2fs_free_mem(void *ptr)
34{
35 void **pp = (void **)ptr;
36
37 free(*pp);
38 *pp = 0;
39 return 0;
40}
41
42/*
43 * Resize memory
44 */
45errcode_t ext2fs_resize_mem(unsigned long EXT2FS_ATTR((unused)) old_size,
46 unsigned long size, void *ptr)
47{
48 void *p;
49
50 /* Use "memcpy" for pointer assignments here to avoid problems
51 * with C99 strict type aliasing rules. */
52 memcpy(&p, ptr, sizeof (p));
53 p = xrealloc(p, size);
54 memcpy(ptr, &p, sizeof (p));
55 return 0;
56}
57
58/*
59 * Mark a filesystem superblock as dirty
60 */
61void ext2fs_mark_super_dirty(ext2_filsys fs)
62{
63 fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_CHANGED;
64}
65
66/*
67 * Mark a filesystem as changed
68 */
69void ext2fs_mark_changed(ext2_filsys fs)
70{
71 fs->flags |= EXT2_FLAG_CHANGED;
72}
73
74/*
75 * Check to see if a filesystem has changed
76 */
77int ext2fs_test_changed(ext2_filsys fs)
78{
79 return (fs->flags & EXT2_FLAG_CHANGED);
80}
81
82/*
83 * Mark a filesystem as valid
84 */
85void ext2fs_mark_valid(ext2_filsys fs)
86{
87 fs->flags |= EXT2_FLAG_VALID;
88}
89
90/*
91 * Mark a filesystem as NOT valid
92 */
93void ext2fs_unmark_valid(ext2_filsys fs)
94{
95 fs->flags &= ~EXT2_FLAG_VALID;
96}
97
98/*
99 * Check to see if a filesystem is valid
100 */
101int ext2fs_test_valid(ext2_filsys fs)
102{
103 return (fs->flags & EXT2_FLAG_VALID);
104}
105
106/*
107 * Mark the inode bitmap as dirty
108 */
109void ext2fs_mark_ib_dirty(ext2_filsys fs)
110{
111 fs->flags |= EXT2_FLAG_IB_DIRTY | EXT2_FLAG_CHANGED;
112}
113
114/*
115 * Mark the block bitmap as dirty
116 */
117void ext2fs_mark_bb_dirty(ext2_filsys fs)
118{
119 fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_CHANGED;
120}
121
122/*
123 * Check to see if a filesystem's inode bitmap is dirty
124 */
125int ext2fs_test_ib_dirty(ext2_filsys fs)
126{
127 return (fs->flags & EXT2_FLAG_IB_DIRTY);
128}
129
130/*
131 * Check to see if a filesystem's block bitmap is dirty
132 */
133int ext2fs_test_bb_dirty(ext2_filsys fs)
134{
135 return (fs->flags & EXT2_FLAG_BB_DIRTY);
136}
137
138/*
139 * Return the group # of a block
140 */
141int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk)
142{
143 return (blk - fs->super->s_first_data_block) /
144 fs->super->s_blocks_per_group;
145}
146
147/*
148 * Return the group # of an inode number
149 */
150int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino)
151{
152 return (ino - 1) / fs->super->s_inodes_per_group;
153}
154
155blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
156 struct ext2_inode *inode)
157{
158 return inode->i_blocks -
159 (inode->i_file_acl ? fs->blocksize >> 9 : 0);
160}
161
162
163
164
165
166
167
168
169
170__u16 ext2fs_swab16(__u16 val)
171{
172 return (val >> 8) | (val << 8);
173}
174
175__u32 ext2fs_swab32(__u32 val)
176{
177 return ((val>>24) | ((val>>8)&0xFF00) |
178 ((val<<8)&0xFF0000) | (val<<24));
179}
180
181int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
182 blk_t bitno);
183
184int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
185 blk_t bitno)
186{
187 if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
188 ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, bitno);
189 return 0;
190 }
191 return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap);
192}
193
194int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap,
195 blk_t block)
196{
197 return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap)
198 bitmap,
199 block);
200}
201
202int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
203 blk_t block)
204{
205 return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
206 block);
207}
208
209int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap,
210 blk_t block)
211{
212 return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
213 block);
214}
215
216int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
217 ext2_ino_t inode)
218{
219 return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
220 inode);
221}
222
223int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
224 ext2_ino_t inode)
225{
226 return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
227 inode);
228}
229
230int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
231 ext2_ino_t inode)
232{
233 return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
234 inode);
235}
236
237void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
238 blk_t block)
239{
240 ext2fs_set_bit(block - bitmap->start, bitmap->bitmap);
241}
242
243void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
244 blk_t block)
245{
246 ext2fs_clear_bit(block - bitmap->start, bitmap->bitmap);
247}
248
249int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
250 blk_t block)
251{
252 return ext2fs_test_bit(block - bitmap->start, bitmap->bitmap);
253}
254
255void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
256 ext2_ino_t inode)
257{
258 ext2fs_set_bit(inode - bitmap->start, bitmap->bitmap);
259}
260
261void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
262 ext2_ino_t inode)
263{
264 ext2fs_clear_bit(inode - bitmap->start, bitmap->bitmap);
265}
266
267int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
268 ext2_ino_t inode)
269{
270 return ext2fs_test_bit(inode - bitmap->start, bitmap->bitmap);
271}
272
273blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap)
274{
275 return bitmap->start;
276}
277
278ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
279{
280 return bitmap->start;
281}
282
283blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap)
284{
285 return bitmap->end;
286}
287
288ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
289{
290 return bitmap->end;
291}
292
293int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
294 blk_t block, int num)
295{
296 int i;
297
298 if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
299 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
300 block, bitmap->description);
301 return 0;
302 }
303 for (i=0; i < num; i++) {
304 if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
305 return 0;
306 }
307 return 1;
308}
309
310int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
311 blk_t block, int num)
312{
313 int i;
314
315 for (i=0; i < num; i++) {
316 if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
317 return 0;
318 }
319 return 1;
320}
321
322void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
323 blk_t block, int num)
324{
325 int i;
326
327 if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
328 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
329 bitmap->description);
330 return;
331 }
332 for (i=0; i < num; i++)
333 ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
334}
335
336void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
337 blk_t block, int num)
338{
339 int i;
340
341 for (i=0; i < num; i++)
342 ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
343}
344
345void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
346 blk_t block, int num)
347{
348 int i;
349
350 if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
351 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
352 bitmap->description);
353 return;
354 }
355 for (i=0; i < num; i++)
356 ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);
357}
358
359void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
360 blk_t block, int num)
361{
362 int i;
363 for (i=0; i < num; i++)
364 ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);
365}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/ext_attr.c b/e2fsprogs/old_e2fsprogs/ext2fs/ext_attr.c
deleted file mode 100644
index a2ba12d45..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/ext_attr.c
+++ /dev/null
@@ -1,101 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * ext_attr.c --- extended attribute blocks
4 *
5 * Copyright (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
6 *
7 * Copyright (C) 2002 Theodore Ts'o.
8 *
9 * %Begin-Header%
10 * This file may be redistributed under the terms of the GNU Public
11 * License.
12 * %End-Header%
13 */
14
15#include <stdio.h>
16#include <unistd.h>
17#include <string.h>
18#include <time.h>
19
20#include "ext2_fs.h"
21#include "ext2_ext_attr.h"
22#include "ext2fs.h"
23
24errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf)
25{
26 errcode_t retval;
27
28 retval = io_channel_read_blk(fs->io, block, 1, buf);
29 if (retval)
30 return retval;
31#if BB_BIG_ENDIAN
32 if ((fs->flags & (EXT2_FLAG_SWAP_BYTES|
33 EXT2_FLAG_SWAP_BYTES_READ)) != 0)
34 ext2fs_swap_ext_attr(buf, buf, fs->blocksize, 1);
35#endif
36 return 0;
37}
38
39errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *inbuf)
40{
41 errcode_t retval;
42 char *write_buf;
43 char *buf = NULL;
44
45 if (BB_BIG_ENDIAN && ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
46 (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))) {
47 retval = ext2fs_get_mem(fs->blocksize, &buf);
48 if (retval)
49 return retval;
50 write_buf = buf;
51 ext2fs_swap_ext_attr(buf, inbuf, fs->blocksize, 1);
52 } else
53 write_buf = (char *) inbuf;
54 retval = io_channel_write_blk(fs->io, block, 1, write_buf);
55 if (buf)
56 ext2fs_free_mem(&buf);
57 if (!retval)
58 ext2fs_mark_changed(fs);
59 return retval;
60}
61
62/*
63 * This function adjusts the reference count of the EA block.
64 */
65errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk,
66 char *block_buf, int adjust,
67 __u32 *newcount)
68{
69 errcode_t retval;
70 struct ext2_ext_attr_header *header;
71 char *buf = NULL;
72
73 if ((blk >= fs->super->s_blocks_count) ||
74 (blk < fs->super->s_first_data_block))
75 return EXT2_ET_BAD_EA_BLOCK_NUM;
76
77 if (!block_buf) {
78 retval = ext2fs_get_mem(fs->blocksize, &buf);
79 if (retval)
80 return retval;
81 block_buf = buf;
82 }
83
84 retval = ext2fs_read_ext_attr(fs, blk, block_buf);
85 if (retval)
86 goto errout;
87
88 header = (struct ext2_ext_attr_header *) block_buf;
89 header->h_refcount += adjust;
90 if (newcount)
91 *newcount = header->h_refcount;
92
93 retval = ext2fs_write_ext_attr(fs, blk, block_buf);
94 if (retval)
95 goto errout;
96
97errout:
98 if (buf)
99 ext2fs_free_mem(&buf);
100 return retval;
101}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/fileio.c b/e2fsprogs/old_e2fsprogs/ext2fs/fileio.c
deleted file mode 100644
index 5a5ad3ef8..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/fileio.c
+++ /dev/null
@@ -1,377 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * fileio.c --- Simple file I/O routines
4 *
5 * Copyright (C) 1997 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18
19#include "ext2_fs.h"
20#include "ext2fs.h"
21
22struct ext2_file {
23 errcode_t magic;
24 ext2_filsys fs;
25 ext2_ino_t ino;
26 struct ext2_inode inode;
27 int flags;
28 __u64 pos;
29 blk_t blockno;
30 blk_t physblock;
31 char *buf;
32};
33
34#define BMAP_BUFFER (file->buf + fs->blocksize)
35
36errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
37 struct ext2_inode *inode,
38 int flags, ext2_file_t *ret)
39{
40 ext2_file_t file;
41 errcode_t retval;
42
43 /*
44 * Don't let caller create or open a file for writing if the
45 * filesystem is read-only.
46 */
47 if ((flags & (EXT2_FILE_WRITE | EXT2_FILE_CREATE)) &&
48 !(fs->flags & EXT2_FLAG_RW))
49 return EXT2_ET_RO_FILSYS;
50
51 retval = ext2fs_get_mem(sizeof(struct ext2_file), &file);
52 if (retval)
53 return retval;
54
55 memset(file, 0, sizeof(struct ext2_file));
56 file->magic = EXT2_ET_MAGIC_EXT2_FILE;
57 file->fs = fs;
58 file->ino = ino;
59 file->flags = flags & EXT2_FILE_MASK;
60
61 if (inode) {
62 memcpy(&file->inode, inode, sizeof(struct ext2_inode));
63 } else {
64 retval = ext2fs_read_inode(fs, ino, &file->inode);
65 if (retval)
66 goto fail;
67 }
68
69 retval = ext2fs_get_mem(fs->blocksize * 3, &file->buf);
70 if (retval)
71 goto fail;
72
73 *ret = file;
74 return 0;
75
76fail:
77 ext2fs_free_mem(&file->buf);
78 ext2fs_free_mem(&file);
79 return retval;
80}
81
82errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino,
83 int flags, ext2_file_t *ret)
84{
85 return ext2fs_file_open2(fs, ino, NULL, flags, ret);
86}
87
88/*
89 * This function returns the filesystem handle of a file from the structure
90 */
91ext2_filsys ext2fs_file_get_fs(ext2_file_t file)
92{
93 if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
94 return 0;
95 return file->fs;
96}
97
98/*
99 * This function flushes the dirty block buffer out to disk if
100 * necessary.
101 */
102errcode_t ext2fs_file_flush(ext2_file_t file)
103{
104 errcode_t retval;
105 ext2_filsys fs;
106
107 EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
108 fs = file->fs;
109
110 if (!(file->flags & EXT2_FILE_BUF_VALID) ||
111 !(file->flags & EXT2_FILE_BUF_DIRTY))
112 return 0;
113
114 /*
115 * OK, the physical block hasn't been allocated yet.
116 * Allocate it.
117 */
118 if (!file->physblock) {
119 retval = ext2fs_bmap(fs, file->ino, &file->inode,
120 BMAP_BUFFER, file->ino ? BMAP_ALLOC : 0,
121 file->blockno, &file->physblock);
122 if (retval)
123 return retval;
124 }
125
126 retval = io_channel_write_blk(fs->io, file->physblock,
127 1, file->buf);
128 if (retval)
129 return retval;
130
131 file->flags &= ~EXT2_FILE_BUF_DIRTY;
132
133 return retval;
134}
135
136/*
137 * This function synchronizes the file's block buffer and the current
138 * file position, possibly invalidating block buffer if necessary
139 */
140static errcode_t sync_buffer_position(ext2_file_t file)
141{
142 blk_t b;
143 errcode_t retval;
144
145 b = file->pos / file->fs->blocksize;
146 if (b != file->blockno) {
147 retval = ext2fs_file_flush(file);
148 if (retval)
149 return retval;
150 file->flags &= ~EXT2_FILE_BUF_VALID;
151 }
152 file->blockno = b;
153 return 0;
154}
155
156/*
157 * This function loads the file's block buffer with valid data from
158 * the disk as necessary.
159 *
160 * If dontfill is true, then skip initializing the buffer since we're
161 * going to be replacing its entire contents anyway. If set, then the
162 * function basically only sets file->physblock and EXT2_FILE_BUF_VALID
163 */
164#define DONTFILL 1
165static errcode_t load_buffer(ext2_file_t file, int dontfill)
166{
167 ext2_filsys fs = file->fs;
168 errcode_t retval;
169
170 if (!(file->flags & EXT2_FILE_BUF_VALID)) {
171 retval = ext2fs_bmap(fs, file->ino, &file->inode,
172 BMAP_BUFFER, 0, file->blockno,
173 &file->physblock);
174 if (retval)
175 return retval;
176 if (!dontfill) {
177 if (file->physblock) {
178 retval = io_channel_read_blk(fs->io,
179 file->physblock,
180 1, file->buf);
181 if (retval)
182 return retval;
183 } else
184 memset(file->buf, 0, fs->blocksize);
185 }
186 file->flags |= EXT2_FILE_BUF_VALID;
187 }
188 return 0;
189}
190
191
192errcode_t ext2fs_file_close(ext2_file_t file)
193{
194 errcode_t retval;
195
196 EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
197
198 retval = ext2fs_file_flush(file);
199
200 ext2fs_free_mem(&file->buf);
201 ext2fs_free_mem(&file);
202
203 return retval;
204}
205
206
207errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
208 unsigned int wanted, unsigned int *got)
209{
210 ext2_filsys fs;
211 errcode_t retval = 0;
212 unsigned int start, c, count = 0;
213 __u64 left;
214 char *ptr = (char *) buf;
215
216 EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
217 fs = file->fs;
218
219 while ((file->pos < EXT2_I_SIZE(&file->inode)) && (wanted > 0)) {
220 retval = sync_buffer_position(file);
221 if (retval)
222 goto fail;
223 retval = load_buffer(file, 0);
224 if (retval)
225 goto fail;
226
227 start = file->pos % fs->blocksize;
228 c = fs->blocksize - start;
229 if (c > wanted)
230 c = wanted;
231 left = EXT2_I_SIZE(&file->inode) - file->pos;
232 if (c > left)
233 c = left;
234
235 memcpy(ptr, file->buf+start, c);
236 file->pos += c;
237 ptr += c;
238 count += c;
239 wanted -= c;
240 }
241
242fail:
243 if (got)
244 *got = count;
245 return retval;
246}
247
248
249errcode_t ext2fs_file_write(ext2_file_t file, const void *buf,
250 unsigned int nbytes, unsigned int *written)
251{
252 ext2_filsys fs;
253 errcode_t retval = 0;
254 unsigned int start, c, count = 0;
255 const char *ptr = (const char *) buf;
256
257 EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
258 fs = file->fs;
259
260 if (!(file->flags & EXT2_FILE_WRITE))
261 return EXT2_ET_FILE_RO;
262
263 while (nbytes > 0) {
264 retval = sync_buffer_position(file);
265 if (retval)
266 goto fail;
267
268 start = file->pos % fs->blocksize;
269 c = fs->blocksize - start;
270 if (c > nbytes)
271 c = nbytes;
272
273 /*
274 * We only need to do a read-modify-update cycle if
275 * we're doing a partial write.
276 */
277 retval = load_buffer(file, (c == fs->blocksize));
278 if (retval)
279 goto fail;
280
281 file->flags |= EXT2_FILE_BUF_DIRTY;
282 memcpy(file->buf+start, ptr, c);
283 file->pos += c;
284 ptr += c;
285 count += c;
286 nbytes -= c;
287 }
288
289fail:
290 if (written)
291 *written = count;
292 return retval;
293}
294
295errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset,
296 int whence, __u64 *ret_pos)
297{
298 EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
299
300 if (whence == EXT2_SEEK_SET)
301 file->pos = offset;
302 else if (whence == EXT2_SEEK_CUR)
303 file->pos += offset;
304 else if (whence == EXT2_SEEK_END)
305 file->pos = EXT2_I_SIZE(&file->inode) + offset;
306 else
307 return EXT2_ET_INVALID_ARGUMENT;
308
309 if (ret_pos)
310 *ret_pos = file->pos;
311
312 return 0;
313}
314
315errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
316 int whence, ext2_off_t *ret_pos)
317{
318 __u64 loffset, ret_loffset;
319 errcode_t retval;
320
321 loffset = offset;
322 retval = ext2fs_file_llseek(file, loffset, whence, &ret_loffset);
323 if (ret_pos)
324 *ret_pos = (ext2_off_t) ret_loffset;
325 return retval;
326}
327
328
329/*
330 * This function returns the size of the file, according to the inode
331 */
332errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size)
333{
334 if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
335 return EXT2_ET_MAGIC_EXT2_FILE;
336 *ret_size = EXT2_I_SIZE(&file->inode);
337 return 0;
338}
339
340/*
341 * This function returns the size of the file, according to the inode
342 */
343ext2_off_t ext2fs_file_get_size(ext2_file_t file)
344{
345 __u64 size;
346
347 if (ext2fs_file_get_lsize(file, &size))
348 return 0;
349 if ((size >> 32) != 0)
350 return 0;
351 return size;
352}
353
354/*
355 * This function sets the size of the file, truncating it if necessary
356 *
357 * XXX still need to call truncate
358 */
359errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size)
360{
361 errcode_t retval;
362 EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
363
364 file->inode.i_size = size;
365 file->inode.i_size_high = 0;
366 if (file->ino) {
367 retval = ext2fs_write_inode(file->fs, file->ino, &file->inode);
368 if (retval)
369 return retval;
370 }
371
372 /*
373 * XXX truncate inode if necessary
374 */
375
376 return 0;
377}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/finddev.c b/e2fsprogs/old_e2fsprogs/ext2fs/finddev.c
deleted file mode 100644
index e9e83fd7a..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/finddev.c
+++ /dev/null
@@ -1,199 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * finddev.c -- this routine attempts to find a particular device in
4 * /dev
5 *
6 * Copyright (C) 2000 Theodore Ts'o.
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the GNU Public
10 * License.
11 * %End-Header%
12 */
13
14#include <stdio.h>
15#include <string.h>
16#ifdef HAVE_UNISTD_H
17#include <unistd.h>
18#endif
19#include <stdlib.h>
20#include <string.h>
21#ifdef HAVE_SYS_TYPES_H
22#include <sys/types.h>
23#endif
24#ifdef HAVE_SYS_STAT_H
25#include <sys/stat.h>
26#endif
27#include <dirent.h>
28#ifdef HAVE_ERRNO_H
29#include <errno.h>
30#endif
31#ifdef HAVE_SYS_MKDEV_H
32#include <sys/mkdev.h>
33#endif
34
35#include "ext2_fs.h"
36#include "ext2fs.h"
37
38struct dir_list {
39 char *name;
40 struct dir_list *next;
41};
42
43/*
44 * This function adds an entry to the directory list
45 */
46static void add_to_dirlist(const char *name, struct dir_list **list)
47{
48 struct dir_list *dp;
49
50 dp = xmalloc(sizeof(struct dir_list));
51 dp->name = xmalloc(strlen(name)+1);
52 strcpy(dp->name, name);
53 dp->next = *list;
54 *list = dp;
55}
56
57/*
58 * This function frees a directory list
59 */
60static void free_dirlist(struct dir_list **list)
61{
62 struct dir_list *dp, *next;
63
64 for (dp = *list; dp; dp = next) {
65 next = dp->next;
66 free(dp->name);
67 free(dp);
68 }
69 *list = 0;
70}
71
72static int scan_dir(char *dir_name, dev_t device, struct dir_list **list,
73 char **ret_path)
74{
75 DIR *dir;
76 struct dirent *dp;
77 char path[1024], *cp;
78 int dirlen;
79 struct stat st;
80
81 dirlen = strlen(dir_name);
82 if ((dir = opendir(dir_name)) == NULL)
83 return errno;
84 dp = readdir(dir);
85 while (dp) {
86 if (dirlen + strlen(dp->d_name) + 2 >= sizeof(path))
87 goto skip_to_next;
88 if (dp->d_name[0] == '.' &&
89 ((dp->d_name[1] == 0) ||
90 ((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
91 goto skip_to_next;
92 sprintf(path, "%s/%s", dir_name, dp->d_name);
93 if (stat(path, &st) < 0)
94 goto skip_to_next;
95 if (S_ISDIR(st.st_mode))
96 add_to_dirlist(path, list);
97 if (S_ISBLK(st.st_mode) && st.st_rdev == device) {
98 cp = xmalloc(strlen(path)+1);
99 strcpy(cp, path);
100 *ret_path = cp;
101 goto success;
102 }
103 skip_to_next:
104 dp = readdir(dir);
105 }
106success:
107 closedir(dir);
108 return 0;
109}
110
111/*
112 * This function finds the pathname to a block device with a given
113 * device number. It returns a pointer to allocated memory to the
114 * pathname on success, and NULL on failure.
115 */
116char *ext2fs_find_block_device(dev_t device)
117{
118 struct dir_list *list = NULL, *new_list = NULL;
119 struct dir_list *current;
120 char *ret_path = NULL;
121
122 /*
123 * Add the starting directories to search...
124 */
125 add_to_dirlist("/devices", &list);
126 add_to_dirlist("/devfs", &list);
127 add_to_dirlist("/dev", &list);
128
129 while (list) {
130 current = list;
131 list = list->next;
132#ifdef DEBUG
133 printf("Scanning directory %s\n", current->name);
134#endif
135 scan_dir(current->name, device, &new_list, &ret_path);
136 free(current->name);
137 free(current);
138 if (ret_path)
139 break;
140 /*
141 * If we're done checking at this level, descend to
142 * the next level of subdirectories. (breadth-first)
143 */
144 if (list == 0) {
145 list = new_list;
146 new_list = 0;
147 }
148 }
149 free_dirlist(&list);
150 free_dirlist(&new_list);
151 return ret_path;
152}
153
154
155#ifdef DEBUG
156int main(int argc, char** argv)
157{
158 char *devname, *tmp;
159 int major, minor;
160 dev_t device;
161 const char *errmsg = "Cannot parse %s: %s\n";
162
163 if ((argc != 2) && (argc != 3)) {
164 fprintf(stderr, "Usage: %s device_number\n", argv[0]);
165 fprintf(stderr, "\t: %s major minor\n", argv[0]);
166 exit(1);
167 }
168 if (argc == 2) {
169 device = strtoul(argv[1], &tmp, 0);
170 if (*tmp) {
171 fprintf(stderr, errmsg, "device number", argv[1]);
172 exit(1);
173 }
174 } else {
175 major = strtoul(argv[1], &tmp, 0);
176 if (*tmp) {
177 fprintf(stderr, errmsg, "major number", argv[1]);
178 exit(1);
179 }
180 minor = strtoul(argv[2], &tmp, 0);
181 if (*tmp) {
182 fprintf(stderr, errmsg, "minor number", argv[2]);
183 exit(1);
184 }
185 device = makedev(major, minor);
186 printf("Looking for device 0x%04x (%d:%d)\n", device,
187 major, minor);
188 }
189 devname = ext2fs_find_block_device(device);
190 if (devname) {
191 printf("Found device! %s\n", devname);
192 free(devname);
193 } else {
194 printf("Cannot find device.\n");
195 }
196 return 0;
197}
198
199#endif
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/flushb.c b/e2fsprogs/old_e2fsprogs/ext2fs/flushb.c
deleted file mode 100644
index 45ed76512..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/flushb.c
+++ /dev/null
@@ -1,83 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * flushb.c --- Hides system-dependent information for both syncing a
4 * device to disk and to flush any buffers from disk cache.
5 *
6 * Copyright (C) 2000 Theodore Ts'o.
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the GNU Public
10 * License.
11 * %End-Header%
12 */
13
14#include <stdio.h>
15#if HAVE_ERRNO_H
16#include <errno.h>
17#endif
18#if HAVE_UNISTD_H
19#include <unistd.h>
20#endif
21#if HAVE_SYS_IOCTL_H
22#include <sys/ioctl.h>
23#endif
24#if HAVE_SYS_MOUNT_H
25#include <sys/param.h>
26#include <sys/mount.h> /* This may define BLKFLSBUF */
27#endif
28
29#include "ext2_fs.h"
30#include "ext2fs.h"
31
32/*
33 * For Linux, define BLKFLSBUF and FDFLUSH if necessary, since
34 * not all portable header file does so for us. This really should be
35 * fixed in the glibc header files. (Recent glibcs appear to define
36 * BLKFLSBUF in sys/mount.h, but FDFLUSH still doesn't seem to be
37 * defined anywhere portable.) Until then....
38 */
39#ifdef __linux__
40#ifndef BLKFLSBUF
41#define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
42#endif
43#ifndef FDFLUSH
44#define FDFLUSH _IO(2,0x4b) /* flush floppy disk */
45#endif
46#endif
47
48/*
49 * This function will sync a device/file, and optionally attempt to
50 * flush the buffer cache. The latter is basically only useful for
51 * system benchmarks and for torturing systems in burn-in tests. :)
52 */
53errcode_t ext2fs_sync_device(int fd, int flushb)
54{
55 /*
56 * We always sync the device in case we're running on old
57 * kernels for which we can lose data if we don't. (There
58 * still is a race condition for those kernels, but this
59 * reduces it greatly.)
60 */
61 if (fsync (fd) == -1)
62 return errno;
63
64 if (flushb) {
65
66#ifdef BLKFLSBUF
67 if (ioctl (fd, BLKFLSBUF, 0) == 0)
68 return 0;
69#else
70#ifdef __GNUC__
71# warning BLKFLSBUF not defined
72#endif /* __GNUC__ */
73#endif
74#ifdef FDFLUSH
75 ioctl (fd, FDFLUSH, 0); /* In case this is a floppy */
76#else
77#ifdef __GNUC__
78# warning FDFLUSH not defined
79#endif /* __GNUC__ */
80#endif
81 }
82 return 0;
83}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/freefs.c b/e2fsprogs/old_e2fsprogs/ext2fs/freefs.c
deleted file mode 100644
index 0c5d48b11..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/freefs.c
+++ /dev/null
@@ -1,127 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * freefs.c --- free an ext2 filesystem
4 *
5 * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#if HAVE_UNISTD_H
15#include <unistd.h>
16#endif
17
18#include "ext2_fs.h"
19#include "ext2fsP.h"
20
21static void ext2fs_free_inode_cache(struct ext2_inode_cache *icache);
22
23void ext2fs_free(ext2_filsys fs)
24{
25 if (!fs || (fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS))
26 return;
27 if (fs->image_io != fs->io) {
28 if (fs->image_io)
29 io_channel_close(fs->image_io);
30 }
31 if (fs->io) {
32 io_channel_close(fs->io);
33 }
34 ext2fs_free_mem(&fs->device_name);
35 ext2fs_free_mem(&fs->super);
36 ext2fs_free_mem(&fs->orig_super);
37 ext2fs_free_mem(&fs->group_desc);
38 ext2fs_free_block_bitmap(fs->block_map);
39 ext2fs_free_inode_bitmap(fs->inode_map);
40
41 ext2fs_badblocks_list_free(fs->badblocks);
42 fs->badblocks = 0;
43
44 ext2fs_free_dblist(fs->dblist);
45
46 if (fs->icache)
47 ext2fs_free_inode_cache(fs->icache);
48
49 fs->magic = 0;
50
51 ext2fs_free_mem(&fs);
52}
53
54void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap)
55{
56 if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_GENERIC_BITMAP))
57 return;
58
59 bitmap->magic = 0;
60 ext2fs_free_mem(&bitmap->description);
61 ext2fs_free_mem(&bitmap->bitmap);
62 ext2fs_free_mem(&bitmap);
63}
64
65void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap)
66{
67 if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_INODE_BITMAP))
68 return;
69
70 bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
71 ext2fs_free_generic_bitmap(bitmap);
72}
73
74void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap)
75{
76 if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_BLOCK_BITMAP))
77 return;
78
79 bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
80 ext2fs_free_generic_bitmap(bitmap);
81}
82
83/*
84 * Free the inode cache structure
85 */
86static void ext2fs_free_inode_cache(struct ext2_inode_cache *icache)
87{
88 if (--icache->refcount)
89 return;
90 ext2fs_free_mem(&icache->buffer);
91 ext2fs_free_mem(&icache->cache);
92 icache->buffer_blk = 0;
93 ext2fs_free_mem(&icache);
94}
95
96/*
97 * This procedure frees a badblocks list.
98 */
99void ext2fs_u32_list_free(ext2_u32_list bb)
100{
101 if (!bb || bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
102 return;
103
104 ext2fs_free_mem(&bb->list);
105 ext2fs_free_mem(&bb);
106}
107
108void ext2fs_badblocks_list_free(ext2_badblocks_list bb)
109{
110 ext2fs_u32_list_free((ext2_u32_list) bb);
111}
112
113
114/*
115 * Free a directory block list
116 */
117void ext2fs_free_dblist(ext2_dblist dblist)
118{
119 if (!dblist || (dblist->magic != EXT2_ET_MAGIC_DBLIST))
120 return;
121
122 ext2fs_free_mem(&dblist->list);
123 if (dblist->fs && dblist->fs->dblist == dblist)
124 dblist->fs->dblist = 0;
125 dblist->magic = 0;
126 ext2fs_free_mem(&dblist);
127}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/gen_bitmap.c b/e2fsprogs/old_e2fsprogs/ext2fs/gen_bitmap.c
deleted file mode 100644
index d0869c919..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/gen_bitmap.c
+++ /dev/null
@@ -1,49 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * gen_bitmap.c --- Generic bitmap routines that used to be inlined.
4 *
5 * Copyright (C) 2001 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13
14#include <stdio.h>
15#include <string.h>
16#if HAVE_UNISTD_H
17#include <unistd.h>
18#endif
19#include <fcntl.h>
20#include <time.h>
21#if HAVE_SYS_STAT_H
22#include <sys/stat.h>
23#endif
24#if HAVE_SYS_TYPES_H
25#include <sys/types.h>
26#endif
27
28#include "ext2_fs.h"
29#include "ext2fs.h"
30
31int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
32 __u32 bitno)
33{
34 if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
35 ext2fs_warn_bitmap2(bitmap, EXT2FS_MARK_ERROR, bitno);
36 return 0;
37 }
38 return ext2fs_set_bit(bitno - bitmap->start, bitmap->bitmap);
39}
40
41int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
42 blk_t bitno)
43{
44 if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
45 ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno);
46 return 0;
47 }
48 return ext2fs_clear_bit(bitno - bitmap->start, bitmap->bitmap);
49}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/get_pathname.c b/e2fsprogs/old_e2fsprogs/ext2fs/get_pathname.c
deleted file mode 100644
index 2bb1cc25e..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/get_pathname.c
+++ /dev/null
@@ -1,156 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * get_pathname.c --- do directry/inode -> name translation
4 *
5 * Copyright (C) 1993, 1994, 1995 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 *
12 * ext2fs_get_pathname(fs, dir, ino, name)
13 *
14 * This function translates takes two inode numbers into a
15 * string, placing the result in <name>. <dir> is the containing
16 * directory inode, and <ino> is the inode number itself. If
17 * <ino> is zero, then ext2fs_get_pathname will return pathname
18 * of the directory <dir>.
19 *
20 */
21
22#include <stdio.h>
23#include <string.h>
24#if HAVE_UNISTD_H
25#include <unistd.h>
26#endif
27
28#include "ext2_fs.h"
29#include "ext2fs.h"
30
31struct get_pathname_struct {
32 ext2_ino_t search_ino;
33 ext2_ino_t parent;
34 char *name;
35 errcode_t errcode;
36};
37
38#ifdef __TURBOC__
39# pragma argsused
40#endif
41static int get_pathname_proc(struct ext2_dir_entry *dirent,
42 int offset EXT2FS_ATTR((unused)),
43 int blocksize EXT2FS_ATTR((unused)),
44 char *buf EXT2FS_ATTR((unused)),
45 void *priv_data)
46{
47 struct get_pathname_struct *gp;
48 errcode_t retval;
49
50 gp = (struct get_pathname_struct *) priv_data;
51
52 if (((dirent->name_len & 0xFF) == 2) &&
53 !strncmp(dirent->name, "..", 2))
54 gp->parent = dirent->inode;
55 if (dirent->inode == gp->search_ino) {
56 retval = ext2fs_get_mem((dirent->name_len & 0xFF) + 1,
57 &gp->name);
58 if (retval) {
59 gp->errcode = retval;
60 return DIRENT_ABORT;
61 }
62 strncpy(gp->name, dirent->name, (dirent->name_len & 0xFF));
63 gp->name[dirent->name_len & 0xFF] = '\0';
64 return DIRENT_ABORT;
65 }
66 return 0;
67}
68
69static errcode_t ext2fs_get_pathname_int(ext2_filsys fs, ext2_ino_t dir,
70 ext2_ino_t ino, int maxdepth,
71 char *buf, char **name)
72{
73 struct get_pathname_struct gp;
74 char *parent_name, *ret;
75 errcode_t retval;
76
77 if (dir == ino) {
78 retval = ext2fs_get_mem(2, name);
79 if (retval)
80 return retval;
81 strcpy(*name, (dir == EXT2_ROOT_INO) ? "/" : ".");
82 return 0;
83 }
84
85 if (!dir || (maxdepth < 0)) {
86 retval = ext2fs_get_mem(4, name);
87 if (retval)
88 return retval;
89 strcpy(*name, "...");
90 return 0;
91 }
92
93 gp.search_ino = ino;
94 gp.parent = 0;
95 gp.name = 0;
96 gp.errcode = 0;
97
98 retval = ext2fs_dir_iterate(fs, dir, 0, buf, get_pathname_proc, &gp);
99 if (retval)
100 goto cleanup;
101 if (gp.errcode) {
102 retval = gp.errcode;
103 goto cleanup;
104 }
105
106 retval = ext2fs_get_pathname_int(fs, gp.parent, dir, maxdepth-1,
107 buf, &parent_name);
108 if (retval)
109 goto cleanup;
110 if (!ino) {
111 *name = parent_name;
112 return 0;
113 }
114
115 if (gp.name)
116 retval = ext2fs_get_mem(strlen(parent_name)+strlen(gp.name)+2,
117 &ret);
118 else
119 retval = ext2fs_get_mem(strlen(parent_name)+5, &ret);
120 if (retval)
121 goto cleanup;
122
123 ret[0] = 0;
124 if (parent_name[1])
125 strcat(ret, parent_name);
126 strcat(ret, "/");
127 if (gp.name)
128 strcat(ret, gp.name);
129 else
130 strcat(ret, "???");
131 *name = ret;
132 ext2fs_free_mem(&parent_name);
133 retval = 0;
134
135cleanup:
136 ext2fs_free_mem(&gp.name);
137 return retval;
138}
139
140errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino,
141 char **name)
142{
143 char *buf;
144 errcode_t retval;
145
146 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
147
148 retval = ext2fs_get_mem(fs->blocksize, &buf);
149 if (retval)
150 return retval;
151 if (dir == ino)
152 ino = 0;
153 retval = ext2fs_get_pathname_int(fs, dir, ino, 32, buf, name);
154 ext2fs_free_mem(&buf);
155 return retval;
156}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/getsectsize.c b/e2fsprogs/old_e2fsprogs/ext2fs/getsectsize.c
deleted file mode 100644
index 163ec65e5..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/getsectsize.c
+++ /dev/null
@@ -1,58 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * getsectsize.c --- get the sector size of a device.
4 *
5 * Copyright (C) 1995, 1995 Theodore Ts'o.
6 * Copyright (C) 2003 VMware, Inc.
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the GNU Public
10 * License.
11 * %End-Header%
12 */
13
14#include <stdio.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#if HAVE_ERRNO_H
19#include <errno.h>
20#endif
21#include <fcntl.h>
22#ifdef HAVE_LINUX_FD_H
23#include <sys/ioctl.h>
24#include <linux/fd.h>
25#endif
26
27#if defined(__linux__) && defined(_IO) && !defined(BLKSSZGET)
28#define BLKSSZGET _IO(0x12,104)/* get block device sector size */
29#endif
30
31#include "ext2_fs.h"
32#include "ext2fs.h"
33
34/*
35 * Returns the number of blocks in a partition
36 */
37errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize)
38{
39 int fd;
40
41#ifdef CONFIG_LFS
42 fd = open64(file, O_RDONLY);
43#else
44 fd = open(file, O_RDONLY);
45#endif
46 if (fd < 0)
47 return errno;
48
49#ifdef BLKSSZGET
50 if (ioctl(fd, BLKSSZGET, sectsize) >= 0) {
51 close(fd);
52 return 0;
53 }
54#endif
55 *sectsize = 0;
56 close(fd);
57 return 0;
58}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/getsize.c b/e2fsprogs/old_e2fsprogs/ext2fs/getsize.c
deleted file mode 100644
index ee4bbb7b0..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/getsize.c
+++ /dev/null
@@ -1,291 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * getsize.c --- get the size of a partition.
4 *
5 * Copyright (C) 1995, 1995 Theodore Ts'o.
6 * Copyright (C) 2003 VMware, Inc.
7 *
8 * Windows version of ext2fs_get_device_size by Chris Li, VMware.
9 *
10 * %Begin-Header%
11 * This file may be redistributed under the terms of the GNU Public
12 * License.
13 * %End-Header%
14 */
15
16#include <stdio.h>
17#if HAVE_UNISTD_H
18#include <unistd.h>
19#endif
20#if HAVE_ERRNO_H
21#include <errno.h>
22#endif
23#include <fcntl.h>
24#ifdef HAVE_SYS_IOCTL_H
25#include <sys/ioctl.h>
26#endif
27#ifdef HAVE_LINUX_FD_H
28#include <linux/fd.h>
29#endif
30#ifdef HAVE_SYS_DISKLABEL_H
31#include <sys/disklabel.h>
32#endif
33#ifdef HAVE_SYS_DISK_H
34#ifdef HAVE_SYS_QUEUE_H
35#include <sys/queue.h> /* for LIST_HEAD */
36#endif
37#include <sys/disk.h>
38#endif
39#ifdef __linux__
40#include <sys/utsname.h>
41#endif
42
43#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
44#define BLKGETSIZE _IO(0x12,96) /* return device size */
45#endif
46
47#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
48#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
49#endif
50
51#ifdef APPLE_DARWIN
52#define BLKGETSIZE DKIOCGETBLOCKCOUNT32
53#endif /* APPLE_DARWIN */
54
55#include "ext2_fs.h"
56#include "ext2fs.h"
57
58#if defined(__CYGWIN__) || defined(WIN32)
59#include <windows.h>
60#include <winioctl.h>
61
62#if (_WIN32_WINNT >= 0x0500)
63#define HAVE_GET_FILE_SIZE_EX 1
64#endif
65
66errcode_t ext2fs_get_device_size(const char *file, int blocksize,
67 blk_t *retblocks)
68{
69 HANDLE dev;
70 PARTITION_INFORMATION pi;
71 DISK_GEOMETRY gi;
72 DWORD retbytes;
73#ifdef HAVE_GET_FILE_SIZE_EX
74 LARGE_INTEGER filesize;
75#else
76 DWORD filesize;
77#endif /* HAVE_GET_FILE_SIZE_EX */
78
79 dev = CreateFile(file, GENERIC_READ,
80 FILE_SHARE_READ | FILE_SHARE_WRITE ,
81 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
82
83 if (dev == INVALID_HANDLE_VALUE)
84 return EBADF;
85 if (DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO,
86 &pi, sizeof(PARTITION_INFORMATION),
87 &pi, sizeof(PARTITION_INFORMATION),
88 &retbytes, NULL)) {
89
90 *retblocks = pi.PartitionLength.QuadPart / blocksize;
91
92 } else if (DeviceIoControl(dev, IOCTL_DISK_GET_DRIVE_GEOMETRY,
93 &gi, sizeof(DISK_GEOMETRY),
94 &gi, sizeof(DISK_GEOMETRY),
95 &retbytes, NULL)) {
96
97 *retblocks = gi.BytesPerSector *
98 gi.SectorsPerTrack *
99 gi.TracksPerCylinder *
100 gi.Cylinders.QuadPart / blocksize;
101
102#ifdef HAVE_GET_FILE_SIZE_EX
103 } else if (GetFileSizeEx(dev, &filesize)) {
104 *retblocks = filesize.QuadPart / blocksize;
105 }
106#else
107 } else {
108 filesize = GetFileSize(dev, NULL);
109 if (INVALID_FILE_SIZE != filesize) {
110 *retblocks = filesize / blocksize;
111 }
112 }
113#endif /* HAVE_GET_FILE_SIZE_EX */
114
115 CloseHandle(dev);
116 return 0;
117}
118
119#else
120
121static int valid_offset (int fd, ext2_loff_t offset)
122{
123 char ch;
124
125 if (ext2fs_llseek (fd, offset, 0) < 0)
126 return 0;
127 if (read (fd, &ch, 1) < 1)
128 return 0;
129 return 1;
130}
131
132/*
133 * Returns the number of blocks in a partition
134 */
135errcode_t ext2fs_get_device_size(const char *file, int blocksize,
136 blk_t *retblocks)
137{
138 int fd;
139 int valid_blkgetsize64 = 1;
140#ifdef __linux__
141 struct utsname ut;
142#endif
143 unsigned long long size64;
144 unsigned long size;
145 ext2_loff_t high, low;
146#ifdef FDGETPRM
147 struct floppy_struct this_floppy;
148#endif
149#ifdef HAVE_SYS_DISKLABEL_H
150 int part;
151 struct disklabel lab;
152 struct partition *pp;
153 char ch;
154#endif /* HAVE_SYS_DISKLABEL_H */
155
156#ifdef CONFIG_LFS
157 fd = open64(file, O_RDONLY);
158#else
159 fd = open(file, O_RDONLY);
160#endif
161 if (fd < 0)
162 return errno;
163
164#ifdef DKIOCGETBLOCKCOUNT /* For Apple Darwin */
165 if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) {
166 if ((sizeof(*retblocks) < sizeof(unsigned long long))
167 && ((size64 / (blocksize / 512)) > 0xFFFFFFFF))
168 return EFBIG;
169 close(fd);
170 *retblocks = size64 / (blocksize / 512);
171 return 0;
172 }
173#endif
174
175#ifdef BLKGETSIZE64
176#ifdef __linux__
177 uname(&ut);
178 if ((ut.release[0] == '2') && (ut.release[1] == '.') &&
179 (ut.release[2] < '6') && (ut.release[3] == '.'))
180 valid_blkgetsize64 = 0;
181#endif
182 if (valid_blkgetsize64 &&
183 ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
184 if ((sizeof(*retblocks) < sizeof(unsigned long long))
185 && ((size64 / blocksize) > 0xFFFFFFFF))
186 return EFBIG;
187 close(fd);
188 *retblocks = size64 / blocksize;
189 return 0;
190 }
191#endif
192
193#ifdef BLKGETSIZE
194 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
195 close(fd);
196 *retblocks = size / (blocksize / 512);
197 return 0;
198 }
199#endif
200
201#ifdef FDGETPRM
202 if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) {
203 close(fd);
204 *retblocks = this_floppy.size / (blocksize / 512);
205 return 0;
206 }
207#endif
208
209#ifdef HAVE_SYS_DISKLABEL_H
210#if defined(DIOCGMEDIASIZE)
211 {
212 off_t ms;
213 u_int bs;
214 if (ioctl(fd, DIOCGMEDIASIZE, &ms) >= 0) {
215 *retblocks = ms / blocksize;
216 return 0;
217 }
218 }
219#elif defined(DIOCGDINFO)
220 /* old disklabel interface */
221 part = strlen(file) - 1;
222 if (part >= 0) {
223 ch = file[part];
224 if (isdigit(ch))
225 part = 0;
226 else if (ch >= 'a' && ch <= 'h')
227 part = ch - 'a';
228 else
229 part = -1;
230 }
231 if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
232 pp = &lab.d_partitions[part];
233 if (pp->p_size) {
234 close(fd);
235 *retblocks = pp->p_size / (blocksize / 512);
236 return 0;
237 }
238 }
239#endif /* defined(DIOCG*) */
240#endif /* HAVE_SYS_DISKLABEL_H */
241
242 /*
243 * OK, we couldn't figure it out by using a specialized ioctl,
244 * which is generally the best way. So do binary search to
245 * find the size of the partition.
246 */
247 low = 0;
248 for (high = 1024; valid_offset (fd, high); high *= 2)
249 low = high;
250 while (low < high - 1)
251 {
252 const ext2_loff_t mid = (low + high) / 2;
253
254 if (valid_offset (fd, mid))
255 low = mid;
256 else
257 high = mid;
258 }
259 valid_offset (fd, 0);
260 close(fd);
261 size64 = low + 1;
262 if ((sizeof(*retblocks) < sizeof(unsigned long long))
263 && ((size64 / blocksize) > 0xFFFFFFFF))
264 return EFBIG;
265 *retblocks = size64 / blocksize;
266 return 0;
267}
268
269#endif /* WIN32 */
270
271#ifdef DEBUG
272int main(int argc, char **argv)
273{
274 blk_t blocks;
275 int retval;
276
277 if (argc < 2) {
278 fprintf(stderr, "Usage: %s device\n", argv[0]);
279 exit(1);
280 }
281
282 retval = ext2fs_get_device_size(argv[1], 1024, &blocks);
283 if (retval) {
284 com_err(argv[0], retval,
285 "while calling ext2fs_get_device_size");
286 exit(1);
287 }
288 printf("Device %s has %d 1k blocks.\n", argv[1], blocks);
289 exit(0);
290}
291#endif
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/icount.c b/e2fsprogs/old_e2fsprogs/ext2fs/icount.c
deleted file mode 100644
index 7ab5f51f4..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/icount.c
+++ /dev/null
@@ -1,467 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * icount.c --- an efficient inode count abstraction
4 *
5 * Copyright (C) 1997 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#if HAVE_UNISTD_H
14#include <unistd.h>
15#endif
16#include <string.h>
17#include <stdio.h>
18
19#include "ext2_fs.h"
20#include "ext2fs.h"
21
22/*
23 * The data storage strategy used by icount relies on the observation
24 * that most inode counts are either zero (for non-allocated inodes),
25 * one (for most files), and only a few that are two or more
26 * (directories and files that are linked to more than one directory).
27 *
28 * Also, e2fsck tends to load the icount data sequentially.
29 *
30 * So, we use an inode bitmap to indicate which inodes have a count of
31 * one, and then use a sorted list to store the counts for inodes
32 * which are greater than one.
33 *
34 * We also use an optional bitmap to indicate which inodes are already
35 * in the sorted list, to speed up the use of this abstraction by
36 * e2fsck's pass 2. Pass 2 increments inode counts as it finds them,
37 * so this extra bitmap avoids searching the sorted list to see if a
38 * particular inode is on the sorted list already.
39 */
40
41struct ext2_icount_el {
42 ext2_ino_t ino;
43 __u16 count;
44};
45
46struct ext2_icount {
47 errcode_t magic;
48 ext2fs_inode_bitmap single;
49 ext2fs_inode_bitmap multiple;
50 ext2_ino_t count;
51 ext2_ino_t size;
52 ext2_ino_t num_inodes;
53 ext2_ino_t cursor;
54 struct ext2_icount_el *list;
55};
56
57void ext2fs_free_icount(ext2_icount_t icount)
58{
59 if (!icount)
60 return;
61
62 icount->magic = 0;
63 ext2fs_free_mem(&icount->list);
64 ext2fs_free_inode_bitmap(icount->single);
65 ext2fs_free_inode_bitmap(icount->multiple);
66 ext2fs_free_mem(&icount);
67}
68
69errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, unsigned int size,
70 ext2_icount_t hint, ext2_icount_t *ret)
71{
72 ext2_icount_t icount;
73 errcode_t retval;
74 size_t bytes;
75 ext2_ino_t i;
76
77 if (hint) {
78 EXT2_CHECK_MAGIC(hint, EXT2_ET_MAGIC_ICOUNT);
79 if (hint->size > size)
80 size = (size_t) hint->size;
81 }
82
83 retval = ext2fs_get_mem(sizeof(struct ext2_icount), &icount);
84 if (retval)
85 return retval;
86 memset(icount, 0, sizeof(struct ext2_icount));
87
88 retval = ext2fs_allocate_inode_bitmap(fs, 0,
89 &icount->single);
90 if (retval)
91 goto errout;
92
93 if (flags & EXT2_ICOUNT_OPT_INCREMENT) {
94 retval = ext2fs_allocate_inode_bitmap(fs, 0,
95 &icount->multiple);
96 if (retval)
97 goto errout;
98 } else
99 icount->multiple = 0;
100
101 if (size) {
102 icount->size = size;
103 } else {
104 /*
105 * Figure out how many special case inode counts we will
106 * have. We know we will need one for each directory;
107 * we also need to reserve some extra room for file links
108 */
109 retval = ext2fs_get_num_dirs(fs, &icount->size);
110 if (retval)
111 goto errout;
112 icount->size += fs->super->s_inodes_count / 50;
113 }
114
115 bytes = (size_t) (icount->size * sizeof(struct ext2_icount_el));
116 retval = ext2fs_get_mem(bytes, &icount->list);
117 if (retval)
118 goto errout;
119 memset(icount->list, 0, bytes);
120
121 icount->magic = EXT2_ET_MAGIC_ICOUNT;
122 icount->count = 0;
123 icount->cursor = 0;
124 icount->num_inodes = fs->super->s_inodes_count;
125
126 /*
127 * Populate the sorted list with those entries which were
128 * found in the hint icount (since those are ones which will
129 * likely need to be in the sorted list this time around).
130 */
131 if (hint) {
132 for (i=0; i < hint->count; i++)
133 icount->list[i].ino = hint->list[i].ino;
134 icount->count = hint->count;
135 }
136
137 *ret = icount;
138 return 0;
139
140errout:
141 ext2fs_free_icount(icount);
142 return retval;
143}
144
145errcode_t ext2fs_create_icount(ext2_filsys fs, int flags,
146 unsigned int size,
147 ext2_icount_t *ret)
148{
149 return ext2fs_create_icount2(fs, flags, size, 0, ret);
150}
151
152/*
153 * insert_icount_el() --- Insert a new entry into the sorted list at a
154 * specified position.
155 */
156static struct ext2_icount_el *insert_icount_el(ext2_icount_t icount,
157 ext2_ino_t ino, int pos)
158{
159 struct ext2_icount_el *el;
160 errcode_t retval;
161 ext2_ino_t new_size = 0;
162 int num;
163
164 if (icount->count >= icount->size) {
165 if (icount->count) {
166 new_size = icount->list[(unsigned)icount->count-1].ino;
167 new_size = (ext2_ino_t) (icount->count *
168 ((float) icount->num_inodes / new_size));
169 }
170 if (new_size < (icount->size + 100))
171 new_size = icount->size + 100;
172 retval = ext2fs_resize_mem((size_t) icount->size *
173 sizeof(struct ext2_icount_el),
174 (size_t) new_size *
175 sizeof(struct ext2_icount_el),
176 &icount->list);
177 if (retval)
178 return 0;
179 icount->size = new_size;
180 }
181 num = (int) icount->count - pos;
182 if (num < 0)
183 return 0; /* should never happen */
184 if (num) {
185 memmove(&icount->list[pos+1], &icount->list[pos],
186 sizeof(struct ext2_icount_el) * num);
187 }
188 icount->count++;
189 el = &icount->list[pos];
190 el->count = 0;
191 el->ino = ino;
192 return el;
193}
194
195/*
196 * get_icount_el() --- given an inode number, try to find icount
197 * information in the sorted list. If the create flag is set,
198 * and we can't find an entry, create one in the sorted list.
199 */
200static struct ext2_icount_el *get_icount_el(ext2_icount_t icount,
201 ext2_ino_t ino, int create)
202{
203 float range;
204 int low, high, mid;
205 ext2_ino_t lowval, highval;
206
207 if (!icount || !icount->list)
208 return 0;
209
210 if (create && ((icount->count == 0) ||
211 (ino > icount->list[(unsigned)icount->count-1].ino))) {
212 return insert_icount_el(icount, ino, (unsigned) icount->count);
213 }
214 if (icount->count == 0)
215 return 0;
216
217 if (icount->cursor >= icount->count)
218 icount->cursor = 0;
219 if (ino == icount->list[icount->cursor].ino)
220 return &icount->list[icount->cursor++];
221 low = 0;
222 high = (int) icount->count-1;
223 while (low <= high) {
224 if (low == high)
225 mid = low;
226 else {
227 /* Interpolate for efficiency */
228 lowval = icount->list[low].ino;
229 highval = icount->list[high].ino;
230
231 if (ino < lowval)
232 range = 0;
233 else if (ino > highval)
234 range = 1;
235 else
236 range = ((float) (ino - lowval)) /
237 (highval - lowval);
238 mid = low + ((int) (range * (high-low)));
239 }
240 if (ino == icount->list[mid].ino) {
241 icount->cursor = mid+1;
242 return &icount->list[mid];
243 }
244 if (ino < icount->list[mid].ino)
245 high = mid-1;
246 else
247 low = mid+1;
248 }
249 /*
250 * If we need to create a new entry, it should be right at
251 * low (where high will be left at low-1).
252 */
253 if (create)
254 return insert_icount_el(icount, ino, low);
255 return 0;
256}
257
258errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *out)
259{
260 errcode_t ret = 0;
261 unsigned int i;
262 const char *bad = "bad icount";
263
264 EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
265
266 if (icount->count > icount->size) {
267 fprintf(out, "%s: count > size\n", bad);
268 return EXT2_ET_INVALID_ARGUMENT;
269 }
270 for (i=1; i < icount->count; i++) {
271 if (icount->list[i-1].ino >= icount->list[i].ino) {
272 fprintf(out, "%s: list[%d].ino=%u, list[%d].ino=%u\n",
273 bad, i-1, icount->list[i-1].ino,
274 i, icount->list[i].ino);
275 ret = EXT2_ET_INVALID_ARGUMENT;
276 }
277 }
278 return ret;
279}
280
281errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, __u16 *ret)
282{
283 struct ext2_icount_el *el;
284
285 EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
286
287 if (!ino || (ino > icount->num_inodes))
288 return EXT2_ET_INVALID_ARGUMENT;
289
290 if (ext2fs_test_inode_bitmap(icount->single, ino)) {
291 *ret = 1;
292 return 0;
293 }
294 if (icount->multiple &&
295 !ext2fs_test_inode_bitmap(icount->multiple, ino)) {
296 *ret = 0;
297 return 0;
298 }
299 el = get_icount_el(icount, ino, 0);
300 if (!el) {
301 *ret = 0;
302 return 0;
303 }
304 *ret = el->count;
305 return 0;
306}
307
308errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino,
309 __u16 *ret)
310{
311 struct ext2_icount_el *el;
312
313 EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
314
315 if (!ino || (ino > icount->num_inodes))
316 return EXT2_ET_INVALID_ARGUMENT;
317
318 if (ext2fs_test_inode_bitmap(icount->single, ino)) {
319 /*
320 * If the existing count is 1, then we know there is
321 * no entry in the list.
322 */
323 el = get_icount_el(icount, ino, 1);
324 if (!el)
325 return EXT2_ET_NO_MEMORY;
326 ext2fs_unmark_inode_bitmap(icount->single, ino);
327 el->count = 2;
328 } else if (icount->multiple) {
329 /*
330 * The count is either zero or greater than 1; if the
331 * inode is set in icount->multiple, then there should
332 * be an entry in the list, so find it using
333 * get_icount_el().
334 */
335 if (ext2fs_test_inode_bitmap(icount->multiple, ino)) {
336 el = get_icount_el(icount, ino, 1);
337 if (!el)
338 return EXT2_ET_NO_MEMORY;
339 el->count++;
340 } else {
341 /*
342 * The count was zero; mark the single bitmap
343 * and return.
344 */
345 zero_count:
346 ext2fs_mark_inode_bitmap(icount->single, ino);
347 if (ret)
348 *ret = 1;
349 return 0;
350 }
351 } else {
352 /*
353 * The count is either zero or greater than 1; try to
354 * find an entry in the list to determine which.
355 */
356 el = get_icount_el(icount, ino, 0);
357 if (!el) {
358 /* No entry means the count was zero */
359 goto zero_count;
360 }
361 el = get_icount_el(icount, ino, 1);
362 if (!el)
363 return EXT2_ET_NO_MEMORY;
364 el->count++;
365 }
366 if (icount->multiple)
367 ext2fs_mark_inode_bitmap(icount->multiple, ino);
368 if (ret)
369 *ret = el->count;
370 return 0;
371}
372
373errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
374 __u16 *ret)
375{
376 struct ext2_icount_el *el;
377
378 if (!ino || (ino > icount->num_inodes))
379 return EXT2_ET_INVALID_ARGUMENT;
380
381 EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
382
383 if (ext2fs_test_inode_bitmap(icount->single, ino)) {
384 ext2fs_unmark_inode_bitmap(icount->single, ino);
385 if (icount->multiple)
386 ext2fs_unmark_inode_bitmap(icount->multiple, ino);
387 else {
388 el = get_icount_el(icount, ino, 0);
389 if (el)
390 el->count = 0;
391 }
392 if (ret)
393 *ret = 0;
394 return 0;
395 }
396
397 if (icount->multiple &&
398 !ext2fs_test_inode_bitmap(icount->multiple, ino))
399 return EXT2_ET_INVALID_ARGUMENT;
400
401 el = get_icount_el(icount, ino, 0);
402 if (!el || el->count == 0)
403 return EXT2_ET_INVALID_ARGUMENT;
404
405 el->count--;
406 if (el->count == 1)
407 ext2fs_mark_inode_bitmap(icount->single, ino);
408 if ((el->count == 0) && icount->multiple)
409 ext2fs_unmark_inode_bitmap(icount->multiple, ino);
410
411 if (ret)
412 *ret = el->count;
413 return 0;
414}
415
416errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
417 __u16 count)
418{
419 struct ext2_icount_el *el;
420
421 if (!ino || (ino > icount->num_inodes))
422 return EXT2_ET_INVALID_ARGUMENT;
423
424 EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
425
426 if (count == 1) {
427 ext2fs_mark_inode_bitmap(icount->single, ino);
428 if (icount->multiple)
429 ext2fs_unmark_inode_bitmap(icount->multiple, ino);
430 return 0;
431 }
432 if (count == 0) {
433 ext2fs_unmark_inode_bitmap(icount->single, ino);
434 if (icount->multiple) {
435 /*
436 * If the icount->multiple bitmap is enabled,
437 * we can just clear both bitmaps and we're done
438 */
439 ext2fs_unmark_inode_bitmap(icount->multiple, ino);
440 } else {
441 el = get_icount_el(icount, ino, 0);
442 if (el)
443 el->count = 0;
444 }
445 return 0;
446 }
447
448 /*
449 * Get the icount element
450 */
451 el = get_icount_el(icount, ino, 1);
452 if (!el)
453 return EXT2_ET_NO_MEMORY;
454 el->count = count;
455 ext2fs_unmark_inode_bitmap(icount->single, ino);
456 if (icount->multiple)
457 ext2fs_mark_inode_bitmap(icount->multiple, ino);
458 return 0;
459}
460
461ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount)
462{
463 if (!icount || icount->magic != EXT2_ET_MAGIC_ICOUNT)
464 return 0;
465
466 return icount->size;
467}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/imager.c b/e2fsprogs/old_e2fsprogs/ext2fs/imager.c
deleted file mode 100644
index 0f9cfcfaf..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/imager.c
+++ /dev/null
@@ -1,377 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * image.c --- writes out the critical parts of the filesystem as a
4 * flat file.
5 *
6 * Copyright (C) 2000 Theodore Ts'o.
7 *
8 * Note: this uses the POSIX IO interfaces, unlike most of the other
9 * functions in this library. So sue me.
10 *
11 * %Begin-Header%
12 * This file may be redistributed under the terms of the GNU Public
13 * License.
14 * %End-Header%
15 */
16
17#include <stdio.h>
18#include <string.h>
19#if HAVE_UNISTD_H
20#include <unistd.h>
21#endif
22#if HAVE_ERRNO_H
23#include <errno.h>
24#endif
25#include <fcntl.h>
26#include <time.h>
27#if HAVE_SYS_STAT_H
28#include <sys/stat.h>
29#endif
30#if HAVE_SYS_TYPES_H
31#include <sys/types.h>
32#endif
33
34#include "ext2_fs.h"
35#include "ext2fs.h"
36
37#ifndef HAVE_TYPE_SSIZE_T
38typedef int ssize_t;
39#endif
40
41/*
42 * This function returns 1 if the specified block is all zeros
43 */
44static int check_zero_block(char *buf, int blocksize)
45{
46 char *cp = buf;
47 int left = blocksize;
48
49 while (left > 0) {
50 if (*cp++)
51 return 0;
52 left--;
53 }
54 return 1;
55}
56
57/*
58 * Write the inode table out as a single block.
59 */
60#define BUF_BLOCKS 32
61
62errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags)
63{
64 unsigned int group, left, c, d;
65 char *buf, *cp;
66 blk_t blk;
67 ssize_t actual;
68 errcode_t retval;
69
70 buf = xmalloc(fs->blocksize * BUF_BLOCKS);
71
72 for (group = 0; group < fs->group_desc_count; group++) {
73 blk = fs->group_desc[(unsigned)group].bg_inode_table;
74 if (!blk)
75 return EXT2_ET_MISSING_INODE_TABLE;
76 left = fs->inode_blocks_per_group;
77 while (left) {
78 c = BUF_BLOCKS;
79 if (c > left)
80 c = left;
81 retval = io_channel_read_blk(fs->io, blk, c, buf);
82 if (retval)
83 goto errout;
84 cp = buf;
85 while (c) {
86 if (!(flags & IMAGER_FLAG_SPARSEWRITE)) {
87 d = c;
88 goto skip_sparse;
89 }
90 /* Skip zero blocks */
91 if (check_zero_block(cp, fs->blocksize)) {
92 c--;
93 blk++;
94 left--;
95 cp += fs->blocksize;
96 lseek(fd, fs->blocksize, SEEK_CUR);
97 continue;
98 }
99 /* Find non-zero blocks */
100 for (d=1; d < c; d++) {
101 if (check_zero_block(cp + d*fs->blocksize, fs->blocksize))
102 break;
103 }
104 skip_sparse:
105 actual = write(fd, cp, fs->blocksize * d);
106 if (actual == -1) {
107 retval = errno;
108 goto errout;
109 }
110 if (actual != (ssize_t) (fs->blocksize * d)) {
111 retval = EXT2_ET_SHORT_WRITE;
112 goto errout;
113 }
114 blk += d;
115 left -= d;
116 cp += fs->blocksize * d;
117 c -= d;
118 }
119 }
120 }
121 retval = 0;
122
123errout:
124 free(buf);
125 return retval;
126}
127
128/*
129 * Read in the inode table and stuff it into place
130 */
131errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd,
132 int flags EXT2FS_ATTR((unused)))
133{
134 unsigned int group, c, left;
135 char *buf;
136 blk_t blk;
137 ssize_t actual;
138 errcode_t retval;
139
140 buf = xmalloc(fs->blocksize * BUF_BLOCKS);
141
142 for (group = 0; group < fs->group_desc_count; group++) {
143 blk = fs->group_desc[(unsigned)group].bg_inode_table;
144 if (!blk) {
145 retval = EXT2_ET_MISSING_INODE_TABLE;
146 goto errout;
147 }
148 left = fs->inode_blocks_per_group;
149 while (left) {
150 c = BUF_BLOCKS;
151 if (c > left)
152 c = left;
153 actual = read(fd, buf, fs->blocksize * c);
154 if (actual == -1) {
155 retval = errno;
156 goto errout;
157 }
158 if (actual != (ssize_t) (fs->blocksize * c)) {
159 retval = EXT2_ET_SHORT_READ;
160 goto errout;
161 }
162 retval = io_channel_write_blk(fs->io, blk, c, buf);
163 if (retval)
164 goto errout;
165
166 blk += c;
167 left -= c;
168 }
169 }
170 retval = ext2fs_flush_icache(fs);
171
172errout:
173 free(buf);
174 return retval;
175}
176
177/*
178 * Write out superblock and group descriptors
179 */
180errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd,
181 int flags EXT2FS_ATTR((unused)))
182{
183 char *buf, *cp;
184 ssize_t actual;
185 errcode_t retval;
186
187 buf = xmalloc(fs->blocksize);
188
189 /*
190 * Write out the superblock
191 */
192 memset(buf, 0, fs->blocksize);
193 memcpy(buf, fs->super, SUPERBLOCK_SIZE);
194 actual = write(fd, buf, fs->blocksize);
195 if (actual == -1) {
196 retval = errno;
197 goto errout;
198 }
199 if (actual != (ssize_t) fs->blocksize) {
200 retval = EXT2_ET_SHORT_WRITE;
201 goto errout;
202 }
203
204 /*
205 * Now write out the block group descriptors
206 */
207 cp = (char *) fs->group_desc;
208 actual = write(fd, cp, fs->blocksize * fs->desc_blocks);
209 if (actual == -1) {
210 retval = errno;
211 goto errout;
212 }
213 if (actual != (ssize_t) (fs->blocksize * fs->desc_blocks)) {
214 retval = EXT2_ET_SHORT_WRITE;
215 goto errout;
216 }
217
218 retval = 0;
219
220errout:
221 free(buf);
222 return retval;
223}
224
225/*
226 * Read the superblock and group descriptors and overwrite them.
227 */
228errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd,
229 int flags EXT2FS_ATTR((unused)))
230{
231 char *buf;
232 ssize_t actual, size;
233 errcode_t retval;
234
235 size = fs->blocksize * (fs->group_desc_count + 1);
236 buf = xmalloc(size);
237
238 /*
239 * Read it all in.
240 */
241 actual = read(fd, buf, size);
242 if (actual == -1) {
243 retval = errno;
244 goto errout;
245 }
246 if (actual != size) {
247 retval = EXT2_ET_SHORT_READ;
248 goto errout;
249 }
250
251 /*
252 * Now copy in the superblock and group descriptors
253 */
254 memcpy(fs->super, buf, SUPERBLOCK_SIZE);
255
256 memcpy(fs->group_desc, buf + fs->blocksize,
257 fs->blocksize * fs->group_desc_count);
258
259 retval = 0;
260
261errout:
262 free(buf);
263 return retval;
264}
265
266/*
267 * Write the block/inode bitmaps.
268 */
269errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
270{
271 char *ptr;
272 int c, size;
273 char zero_buf[1024];
274 ssize_t actual;
275 errcode_t retval;
276
277 if (flags & IMAGER_FLAG_INODEMAP) {
278 if (!fs->inode_map) {
279 retval = ext2fs_read_inode_bitmap(fs);
280 if (retval)
281 return retval;
282 }
283 ptr = fs->inode_map->bitmap;
284 size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
285 } else {
286 if (!fs->block_map) {
287 retval = ext2fs_read_block_bitmap(fs);
288 if (retval)
289 return retval;
290 }
291 ptr = fs->block_map->bitmap;
292 size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
293 }
294 size = size * fs->group_desc_count;
295
296 actual = write(fd, ptr, size);
297 if (actual == -1) {
298 retval = errno;
299 goto errout;
300 }
301 if (actual != size) {
302 retval = EXT2_ET_SHORT_WRITE;
303 goto errout;
304 }
305 size = size % fs->blocksize;
306 memset(zero_buf, 0, sizeof(zero_buf));
307 if (size) {
308 size = fs->blocksize - size;
309 while (size) {
310 c = size;
311 if (c > (int) sizeof(zero_buf))
312 c = sizeof(zero_buf);
313 actual = write(fd, zero_buf, c);
314 if (actual == -1) {
315 retval = errno;
316 goto errout;
317 }
318 if (actual != c) {
319 retval = EXT2_ET_SHORT_WRITE;
320 goto errout;
321 }
322 size -= c;
323 }
324 }
325 retval = 0;
326errout:
327 return retval;
328}
329
330
331/*
332 * Read the block/inode bitmaps.
333 */
334errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
335{
336 char *ptr, *buf = NULL;
337 int size;
338 ssize_t actual;
339 errcode_t retval;
340
341 if (flags & IMAGER_FLAG_INODEMAP) {
342 if (!fs->inode_map) {
343 retval = ext2fs_read_inode_bitmap(fs);
344 if (retval)
345 return retval;
346 }
347 ptr = fs->inode_map->bitmap;
348 size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
349 } else {
350 if (!fs->block_map) {
351 retval = ext2fs_read_block_bitmap(fs);
352 if (retval)
353 return retval;
354 }
355 ptr = fs->block_map->bitmap;
356 size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
357 }
358 size = size * fs->group_desc_count;
359
360 buf = xmalloc(size);
361
362 actual = read(fd, buf, size);
363 if (actual == -1) {
364 retval = errno;
365 goto errout;
366 }
367 if (actual != size) {
368 retval = EXT2_ET_SHORT_WRITE;
369 goto errout;
370 }
371 memcpy(ptr, buf, size);
372
373 retval = 0;
374errout:
375 free(buf);
376 return retval;
377}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/ind_block.c b/e2fsprogs/old_e2fsprogs/ext2fs/ind_block.c
deleted file mode 100644
index a1038300b..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/ind_block.c
+++ /dev/null
@@ -1,69 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * ind_block.c --- indirect block I/O routines
4 *
5 * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
6 * 2001, 2002, 2003, 2004, 2005 by Theodore Ts'o.
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the GNU Public
10 * License.
11 * %End-Header%
12 */
13
14#include <stdio.h>
15#include <string.h>
16#if HAVE_UNISTD_H
17#include <unistd.h>
18#endif
19
20#include "ext2_fs.h"
21#include "ext2fs.h"
22
23errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf)
24{
25 errcode_t retval;
26#if BB_BIG_ENDIAN
27 blk_t *block_nr;
28 int i;
29 int limit = fs->blocksize >> 2;
30#endif
31
32 if ((fs->flags & EXT2_FLAG_IMAGE_FILE) &&
33 (fs->io != fs->image_io))
34 memset(buf, 0, fs->blocksize);
35 else {
36 retval = io_channel_read_blk(fs->io, blk, 1, buf);
37 if (retval)
38 return retval;
39 }
40#if BB_BIG_ENDIAN
41 if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_READ)) {
42 block_nr = (blk_t *) buf;
43 for (i = 0; i < limit; i++, block_nr++)
44 *block_nr = ext2fs_swab32(*block_nr);
45 }
46#endif
47 return 0;
48}
49
50errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf)
51{
52#if BB_BIG_ENDIAN
53 blk_t *block_nr;
54 int i;
55 int limit = fs->blocksize >> 2;
56#endif
57
58 if (fs->flags & EXT2_FLAG_IMAGE_FILE)
59 return 0;
60
61#if BB_BIG_ENDIAN
62 if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_WRITE)) {
63 block_nr = (blk_t *) buf;
64 for (i = 0; i < limit; i++, block_nr++)
65 *block_nr = ext2fs_swab32(*block_nr);
66 }
67#endif
68 return io_channel_write_blk(fs->io, blk, 1, buf);
69}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/initialize.c b/e2fsprogs/old_e2fsprogs/ext2fs/initialize.c
deleted file mode 100644
index 240335b32..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/initialize.c
+++ /dev/null
@@ -1,388 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * initialize.c --- initialize a filesystem handle given superblock
4 * parameters. Used by mke2fs when initializing a filesystem.
5 *
6 * Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the GNU Public
10 * License.
11 * %End-Header%
12 */
13
14#include <stdio.h>
15#include <string.h>
16#if HAVE_UNISTD_H
17#include <unistd.h>
18#endif
19#include <fcntl.h>
20#include <time.h>
21#if HAVE_SYS_STAT_H
22#include <sys/stat.h>
23#endif
24#if HAVE_SYS_TYPES_H
25#include <sys/types.h>
26#endif
27
28#include "ext2_fs.h"
29#include "ext2fs.h"
30
31#if defined(__linux__) && defined(EXT2_OS_LINUX)
32#define CREATOR_OS EXT2_OS_LINUX
33#else
34#if defined(__GNU__) && defined(EXT2_OS_HURD)
35#define CREATOR_OS EXT2_OS_HURD
36#else
37#if defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD)
38#define CREATOR_OS EXT2_OS_FREEBSD
39#else
40#if defined(LITES) && defined(EXT2_OS_LITES)
41#define CREATOR_OS EXT2_OS_LITES
42#else
43#define CREATOR_OS EXT2_OS_LINUX /* by default */
44#endif /* defined(LITES) && defined(EXT2_OS_LITES) */
45#endif /* defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD) */
46#endif /* defined(__GNU__) && defined(EXT2_OS_HURD) */
47#endif /* defined(__linux__) && defined(EXT2_OS_LINUX) */
48
49/*
50 * Note we override the kernel include file's idea of what the default
51 * check interval (never) should be. It's a good idea to check at
52 * least *occasionally*, specially since servers will never rarely get
53 * to reboot, since Linux is so robust these days. :-)
54 *
55 * 180 days (six months) seems like a good value.
56 */
57#ifdef EXT2_DFL_CHECKINTERVAL
58#undef EXT2_DFL_CHECKINTERVAL
59#endif
60#define EXT2_DFL_CHECKINTERVAL (86400L * 180L)
61
62/*
63 * Calculate the number of GDT blocks to reserve for online filesystem growth.
64 * The absolute maximum number of GDT blocks we can reserve is determined by
65 * the number of block pointers that can fit into a single block.
66 */
67static int calc_reserved_gdt_blocks(ext2_filsys fs)
68{
69 struct ext2_super_block *sb = fs->super;
70 unsigned long bpg = sb->s_blocks_per_group;
71 unsigned int gdpb = fs->blocksize / sizeof(struct ext2_group_desc);
72 unsigned long max_blocks = 0xffffffff;
73 unsigned long rsv_groups;
74 int rsv_gdb;
75
76 /* We set it at 1024x the current filesystem size, or
77 * the upper block count limit (2^32), whichever is lower.
78 */
79 if (sb->s_blocks_count < max_blocks / 1024)
80 max_blocks = sb->s_blocks_count * 1024;
81 rsv_groups = (max_blocks - sb->s_first_data_block + bpg - 1) / bpg;
82 rsv_gdb = (rsv_groups + gdpb - 1) / gdpb - fs->desc_blocks;
83 if (rsv_gdb > EXT2_ADDR_PER_BLOCK(sb))
84 rsv_gdb = EXT2_ADDR_PER_BLOCK(sb);
85#ifdef RES_GDT_DEBUG
86 printf("max_blocks %lu, rsv_groups = %lu, rsv_gdb = %u\n",
87 max_blocks, rsv_groups, rsv_gdb);
88#endif
89
90 return rsv_gdb;
91}
92
93errcode_t ext2fs_initialize(const char *name, int flags,
94 struct ext2_super_block *param,
95 io_manager manager, ext2_filsys *ret_fs)
96{
97 ext2_filsys fs;
98 errcode_t retval;
99 struct ext2_super_block *super;
100 int frags_per_block;
101 unsigned int rem;
102 unsigned int overhead = 0;
103 blk_t group_block;
104 unsigned int ipg;
105 dgrp_t i;
106 blk_t numblocks;
107 int rsv_gdt;
108 char *buf;
109
110 if (!param || !param->s_blocks_count)
111 return EXT2_ET_INVALID_ARGUMENT;
112
113 retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
114 if (retval)
115 return retval;
116
117 memset(fs, 0, sizeof(struct struct_ext2_filsys));
118 fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS;
119 fs->flags = flags | EXT2_FLAG_RW;
120 fs->umask = 022;
121#ifdef WORDS_BIGENDIAN
122 fs->flags |= EXT2_FLAG_SWAP_BYTES;
123#endif
124 retval = manager->open(name, IO_FLAG_RW, &fs->io);
125 if (retval)
126 goto cleanup;
127 fs->image_io = fs->io;
128 fs->io->app_data = fs;
129 retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name);
130 if (retval)
131 goto cleanup;
132
133 strcpy(fs->device_name, name);
134 retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super);
135 if (retval)
136 goto cleanup;
137 fs->super = super;
138
139 memset(super, 0, SUPERBLOCK_SIZE);
140
141#define set_field(field, default) (super->field = param->field ? \
142 param->field : (default))
143
144 super->s_magic = EXT2_SUPER_MAGIC;
145 super->s_state = EXT2_VALID_FS;
146
147 set_field(s_log_block_size, 0); /* default blocksize: 1024 bytes */
148 set_field(s_log_frag_size, 0); /* default fragsize: 1024 bytes */
149 set_field(s_first_data_block, super->s_log_block_size ? 0 : 1);
150 set_field(s_max_mnt_count, EXT2_DFL_MAX_MNT_COUNT);
151 set_field(s_errors, EXT2_ERRORS_DEFAULT);
152 set_field(s_feature_compat, 0);
153 set_field(s_feature_incompat, 0);
154 set_field(s_feature_ro_compat, 0);
155 set_field(s_first_meta_bg, 0);
156 if (super->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) {
157 retval = EXT2_ET_UNSUPP_FEATURE;
158 goto cleanup;
159 }
160 if (super->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
161 retval = EXT2_ET_RO_UNSUPP_FEATURE;
162 goto cleanup;
163 }
164
165 set_field(s_rev_level, EXT2_GOOD_OLD_REV);
166 if (super->s_rev_level >= EXT2_DYNAMIC_REV) {
167 set_field(s_first_ino, EXT2_GOOD_OLD_FIRST_INO);
168 set_field(s_inode_size, EXT2_GOOD_OLD_INODE_SIZE);
169 }
170
171 set_field(s_checkinterval, EXT2_DFL_CHECKINTERVAL);
172 super->s_mkfs_time = super->s_lastcheck = time(NULL);
173
174 super->s_creator_os = CREATOR_OS;
175
176 fs->blocksize = EXT2_BLOCK_SIZE(super);
177 fs->fragsize = EXT2_FRAG_SIZE(super);
178 frags_per_block = fs->blocksize / fs->fragsize;
179
180 /* default: (fs->blocksize*8) blocks/group, up to 2^16 (GDT limit) */
181 set_field(s_blocks_per_group, fs->blocksize * 8);
182 if (super->s_blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(super))
183 super->s_blocks_per_group = EXT2_MAX_BLOCKS_PER_GROUP(super);
184 super->s_frags_per_group = super->s_blocks_per_group * frags_per_block;
185
186 super->s_blocks_count = param->s_blocks_count;
187 super->s_r_blocks_count = param->s_r_blocks_count;
188 if (super->s_r_blocks_count >= param->s_blocks_count) {
189 retval = EXT2_ET_INVALID_ARGUMENT;
190 goto cleanup;
191 }
192
193 /*
194 * If we're creating an external journal device, we don't need
195 * to bother with the rest.
196 */
197 if (super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
198 fs->group_desc_count = 0;
199 ext2fs_mark_super_dirty(fs);
200 *ret_fs = fs;
201 return 0;
202 }
203
204retry:
205 fs->group_desc_count = (super->s_blocks_count -
206 super->s_first_data_block +
207 EXT2_BLOCKS_PER_GROUP(super) - 1)
208 / EXT2_BLOCKS_PER_GROUP(super);
209 if (fs->group_desc_count == 0) {
210 retval = EXT2_ET_TOOSMALL;
211 goto cleanup;
212 }
213 fs->desc_blocks = (fs->group_desc_count +
214 EXT2_DESC_PER_BLOCK(super) - 1)
215 / EXT2_DESC_PER_BLOCK(super);
216
217 i = fs->blocksize >= 4096 ? 1 : 4096 / fs->blocksize;
218 set_field(s_inodes_count, super->s_blocks_count / i);
219
220 /*
221 * Make sure we have at least EXT2_FIRST_INO + 1 inodes, so
222 * that we have enough inodes for the filesystem(!)
223 */
224 if (super->s_inodes_count < EXT2_FIRST_INODE(super)+1)
225 super->s_inodes_count = EXT2_FIRST_INODE(super)+1;
226
227 /*
228 * There should be at least as many inodes as the user
229 * requested. Figure out how many inodes per group that
230 * should be. But make sure that we don't allocate more than
231 * one bitmap's worth of inodes each group.
232 */
233 ipg = (super->s_inodes_count + fs->group_desc_count - 1) /
234 fs->group_desc_count;
235 if (ipg > fs->blocksize * 8) {
236 if (super->s_blocks_per_group >= 256) {
237 /* Try again with slightly different parameters */
238 super->s_blocks_per_group -= 8;
239 super->s_blocks_count = param->s_blocks_count;
240 super->s_frags_per_group = super->s_blocks_per_group *
241 frags_per_block;
242 goto retry;
243 } else
244 return EXT2_ET_TOO_MANY_INODES;
245 }
246
247 if (ipg > (unsigned) EXT2_MAX_INODES_PER_GROUP(super))
248 ipg = EXT2_MAX_INODES_PER_GROUP(super);
249
250 super->s_inodes_per_group = ipg;
251 if (super->s_inodes_count > ipg * fs->group_desc_count)
252 super->s_inodes_count = ipg * fs->group_desc_count;
253
254 /*
255 * Make sure the number of inodes per group completely fills
256 * the inode table blocks in the descriptor. If not, add some
257 * additional inodes/group. Waste not, want not...
258 */
259 fs->inode_blocks_per_group = (((super->s_inodes_per_group *
260 EXT2_INODE_SIZE(super)) +
261 EXT2_BLOCK_SIZE(super) - 1) /
262 EXT2_BLOCK_SIZE(super));
263 super->s_inodes_per_group = ((fs->inode_blocks_per_group *
264 EXT2_BLOCK_SIZE(super)) /
265 EXT2_INODE_SIZE(super));
266 /*
267 * Finally, make sure the number of inodes per group is a
268 * multiple of 8. This is needed to simplify the bitmap
269 * splicing code.
270 */
271 super->s_inodes_per_group &= ~7;
272 fs->inode_blocks_per_group = (((super->s_inodes_per_group *
273 EXT2_INODE_SIZE(super)) +
274 EXT2_BLOCK_SIZE(super) - 1) /
275 EXT2_BLOCK_SIZE(super));
276
277 /*
278 * adjust inode count to reflect the adjusted inodes_per_group
279 */
280 super->s_inodes_count = super->s_inodes_per_group *
281 fs->group_desc_count;
282 super->s_free_inodes_count = super->s_inodes_count;
283
284 /*
285 * check the number of reserved group descriptor table blocks
286 */
287 if (super->s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INO)
288 rsv_gdt = calc_reserved_gdt_blocks(fs);
289 else
290 rsv_gdt = 0;
291 set_field(s_reserved_gdt_blocks, rsv_gdt);
292 if (super->s_reserved_gdt_blocks > EXT2_ADDR_PER_BLOCK(super)) {
293 retval = EXT2_ET_RES_GDT_BLOCKS;
294 goto cleanup;
295 }
296
297 /*
298 * Overhead is the number of bookkeeping blocks per group. It
299 * includes the superblock backup, the group descriptor
300 * backups, the inode bitmap, the block bitmap, and the inode
301 * table.
302 */
303
304 overhead = (int) (2 + fs->inode_blocks_per_group);
305
306 if (ext2fs_bg_has_super(fs, fs->group_desc_count - 1))
307 overhead += 1 + fs->desc_blocks + super->s_reserved_gdt_blocks;
308
309 /* This can only happen if the user requested too many inodes */
310 if (overhead > super->s_blocks_per_group)
311 return EXT2_ET_TOO_MANY_INODES;
312
313 /*
314 * See if the last group is big enough to support the
315 * necessary data structures. If not, we need to get rid of
316 * it.
317 */
318 rem = ((super->s_blocks_count - super->s_first_data_block) %
319 super->s_blocks_per_group);
320 if ((fs->group_desc_count == 1) && rem && (rem < overhead))
321 return EXT2_ET_TOOSMALL;
322 if (rem && (rem < overhead+50)) {
323 super->s_blocks_count -= rem;
324 goto retry;
325 }
326
327 /*
328 * At this point we know how big the filesystem will be. So
329 * we can do any and all allocations that depend on the block
330 * count.
331 */
332
333 retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
334 if (retval)
335 goto cleanup;
336
337 sprintf(buf, "block bitmap for %s", fs->device_name);
338 retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
339 if (retval)
340 goto cleanup;
341
342 sprintf(buf, "inode bitmap for %s", fs->device_name);
343 retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
344 if (retval)
345 goto cleanup;
346
347 ext2fs_free_mem(&buf);
348
349 retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize,
350 &fs->group_desc);
351 if (retval)
352 goto cleanup;
353
354 memset(fs->group_desc, 0, (size_t) fs->desc_blocks * fs->blocksize);
355
356 /*
357 * Reserve the superblock and group descriptors for each
358 * group, and fill in the correct group statistics for group.
359 * Note that although the block bitmap, inode bitmap, and
360 * inode table have not been allocated (and in fact won't be
361 * by this routine), they are accounted for nevertheless.
362 */
363 group_block = super->s_first_data_block;
364 super->s_free_blocks_count = 0;
365 for (i = 0; i < fs->group_desc_count; i++) {
366 numblocks = ext2fs_reserve_super_and_bgd(fs, i, fs->block_map);
367
368 super->s_free_blocks_count += numblocks;
369 fs->group_desc[i].bg_free_blocks_count = numblocks;
370 fs->group_desc[i].bg_free_inodes_count =
371 fs->super->s_inodes_per_group;
372 fs->group_desc[i].bg_used_dirs_count = 0;
373
374 group_block += super->s_blocks_per_group;
375 }
376
377 ext2fs_mark_super_dirty(fs);
378 ext2fs_mark_bb_dirty(fs);
379 ext2fs_mark_ib_dirty(fs);
380
381 io_channel_set_blksize(fs->io, fs->blocksize);
382
383 *ret_fs = fs;
384 return 0;
385cleanup:
386 ext2fs_free(fs);
387 return retval;
388}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/inline.c b/e2fsprogs/old_e2fsprogs/ext2fs/inline.c
deleted file mode 100644
index 7457b9396..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/inline.c
+++ /dev/null
@@ -1,32 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * inline.c --- Includes the inlined functions defined in the header
4 * files as standalone functions, in case the application program
5 * is compiled with inlining turned off.
6 *
7 * Copyright (C) 1993, 1994 Theodore Ts'o.
8 *
9 * %Begin-Header%
10 * This file may be redistributed under the terms of the GNU Public
11 * License.
12 * %End-Header%
13 */
14
15
16#include <stdio.h>
17#include <string.h>
18#if HAVE_UNISTD_H
19#include <unistd.h>
20#endif
21#include <fcntl.h>
22#include <time.h>
23#if HAVE_SYS_STAT_H
24#include <sys/stat.h>
25#endif
26#if HAVE_SYS_TYPES_H
27#include <sys/types.h>
28#endif
29
30#include "ext2_fs.h"
31#define INCLUDE_INLINE_FUNCS
32#include "ext2fs.h"
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/inode.c b/e2fsprogs/old_e2fsprogs/ext2fs/inode.c
deleted file mode 100644
index 7a1d5c94b..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/inode.c
+++ /dev/null
@@ -1,766 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * inode.c --- utility routines to read and write inodes
4 *
5 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#if HAVE_ERRNO_H
19#include <errno.h>
20#endif
21#if HAVE_SYS_STAT_H
22#include <sys/stat.h>
23#endif
24#if HAVE_SYS_TYPES_H
25#include <sys/types.h>
26#endif
27
28#include "ext2_fs.h"
29#include "ext2fsP.h"
30#include "e2image.h"
31
32struct ext2_struct_inode_scan {
33 errcode_t magic;
34 ext2_filsys fs;
35 ext2_ino_t current_inode;
36 blk_t current_block;
37 dgrp_t current_group;
38 ext2_ino_t inodes_left;
39 blk_t blocks_left;
40 dgrp_t groups_left;
41 blk_t inode_buffer_blocks;
42 char * inode_buffer;
43 int inode_size;
44 char * ptr;
45 int bytes_left;
46 char *temp_buffer;
47 errcode_t (*done_group)(ext2_filsys fs,
48 dgrp_t group,
49 void * priv_data);
50 void * done_group_data;
51 int bad_block_ptr;
52 int scan_flags;
53 int reserved[6];
54};
55
56/*
57 * This routine flushes the icache, if it exists.
58 */
59errcode_t ext2fs_flush_icache(ext2_filsys fs)
60{
61 int i;
62
63 if (!fs->icache)
64 return 0;
65
66 for (i=0; i < fs->icache->cache_size; i++)
67 fs->icache->cache[i].ino = 0;
68
69 fs->icache->buffer_blk = 0;
70 return 0;
71}
72
73static errcode_t create_icache(ext2_filsys fs)
74{
75 errcode_t retval;
76
77 if (fs->icache)
78 return 0;
79 retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache), &fs->icache);
80 if (retval)
81 return retval;
82
83 memset(fs->icache, 0, sizeof(struct ext2_inode_cache));
84 retval = ext2fs_get_mem(fs->blocksize, &fs->icache->buffer);
85 if (retval) {
86 ext2fs_free_mem(&fs->icache);
87 return retval;
88 }
89 fs->icache->buffer_blk = 0;
90 fs->icache->cache_last = -1;
91 fs->icache->cache_size = 4;
92 fs->icache->refcount = 1;
93 retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache_ent)
94 * fs->icache->cache_size,
95 &fs->icache->cache);
96 if (retval) {
97 ext2fs_free_mem(&fs->icache->buffer);
98 ext2fs_free_mem(&fs->icache);
99 return retval;
100 }
101 ext2fs_flush_icache(fs);
102 return 0;
103}
104
105errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
106 ext2_inode_scan *ret_scan)
107{
108 ext2_inode_scan scan;
109 errcode_t retval;
110 errcode_t (*save_get_blocks)(ext2_filsys f, ext2_ino_t ino, blk_t *blocks);
111
112 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
113
114 /*
115 * If fs->badblocks isn't set, then set it --- since the inode
116 * scanning functions require it.
117 */
118 if (fs->badblocks == 0) {
119 /*
120 * Temporarly save fs->get_blocks and set it to zero,
121 * for compatibility with old e2fsck's.
122 */
123 save_get_blocks = fs->get_blocks;
124 fs->get_blocks = 0;
125 retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
126 if (retval) {
127 ext2fs_badblocks_list_free(fs->badblocks);
128 fs->badblocks = 0;
129 }
130 fs->get_blocks = save_get_blocks;
131 }
132
133 retval = ext2fs_get_mem(sizeof(struct ext2_struct_inode_scan), &scan);
134 if (retval)
135 return retval;
136 memset(scan, 0, sizeof(struct ext2_struct_inode_scan));
137
138 scan->magic = EXT2_ET_MAGIC_INODE_SCAN;
139 scan->fs = fs;
140 scan->inode_size = EXT2_INODE_SIZE(fs->super);
141 scan->bytes_left = 0;
142 scan->current_group = 0;
143 scan->groups_left = fs->group_desc_count - 1;
144 scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : 8;
145 scan->current_block = scan->fs->
146 group_desc[scan->current_group].bg_inode_table;
147 scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
148 scan->blocks_left = scan->fs->inode_blocks_per_group;
149 retval = ext2fs_get_mem((size_t) (scan->inode_buffer_blocks *
150 fs->blocksize),
151 &scan->inode_buffer);
152 scan->done_group = 0;
153 scan->done_group_data = 0;
154 scan->bad_block_ptr = 0;
155 if (retval) {
156 ext2fs_free_mem(&scan);
157 return retval;
158 }
159 retval = ext2fs_get_mem(scan->inode_size, &scan->temp_buffer);
160 if (retval) {
161 ext2fs_free_mem(&scan->inode_buffer);
162 ext2fs_free_mem(&scan);
163 return retval;
164 }
165 if (scan->fs->badblocks && scan->fs->badblocks->num)
166 scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS;
167 *ret_scan = scan;
168 return 0;
169}
170
171void ext2fs_close_inode_scan(ext2_inode_scan scan)
172{
173 if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
174 return;
175
176 ext2fs_free_mem(&scan->inode_buffer);
177 scan->inode_buffer = NULL;
178 ext2fs_free_mem(&scan->temp_buffer);
179 scan->temp_buffer = NULL;
180 ext2fs_free_mem(&scan);
181}
182
183void ext2fs_set_inode_callback(ext2_inode_scan scan,
184 errcode_t (*done_group)(ext2_filsys fs,
185 dgrp_t group,
186 void * priv_data),
187 void *done_group_data)
188{
189 if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
190 return;
191
192 scan->done_group = done_group;
193 scan->done_group_data = done_group_data;
194}
195
196int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags,
197 int clear_flags)
198{
199 int old_flags;
200
201 if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
202 return 0;
203
204 old_flags = scan->scan_flags;
205 scan->scan_flags &= ~clear_flags;
206 scan->scan_flags |= set_flags;
207 return old_flags;
208}
209
210/*
211 * This function is called by ext2fs_get_next_inode when it needs to
212 * get ready to read in a new blockgroup.
213 */
214static errcode_t get_next_blockgroup(ext2_inode_scan scan)
215{
216 scan->current_group++;
217 scan->groups_left--;
218
219 scan->current_block = scan->fs->
220 group_desc[scan->current_group].bg_inode_table;
221
222 scan->current_inode = scan->current_group *
223 EXT2_INODES_PER_GROUP(scan->fs->super);
224
225 scan->bytes_left = 0;
226 scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
227 scan->blocks_left = scan->fs->inode_blocks_per_group;
228 return 0;
229}
230
231errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,
232 int group)
233{
234 scan->current_group = group - 1;
235 scan->groups_left = scan->fs->group_desc_count - group;
236 return get_next_blockgroup(scan);
237}
238
239/*
240 * This function is called by get_next_blocks() to check for bad
241 * blocks in the inode table.
242 *
243 * This function assumes that badblocks_list->list is sorted in
244 * increasing order.
245 */
246static errcode_t check_for_inode_bad_blocks(ext2_inode_scan scan,
247 blk_t *num_blocks)
248{
249 blk_t blk = scan->current_block;
250 badblocks_list bb = scan->fs->badblocks;
251
252 /*
253 * If the inode table is missing, then obviously there are no
254 * bad blocks. :-)
255 */
256 if (blk == 0)
257 return 0;
258
259 /*
260 * If the current block is greater than the bad block listed
261 * in the bad block list, then advance the pointer until this
262 * is no longer the case. If we run out of bad blocks, then
263 * we don't need to do any more checking!
264 */
265 while (blk > bb->list[scan->bad_block_ptr]) {
266 if (++scan->bad_block_ptr >= bb->num) {
267 scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
268 return 0;
269 }
270 }
271
272 /*
273 * If the current block is equal to the bad block listed in
274 * the bad block list, then handle that one block specially.
275 * (We could try to handle runs of bad blocks, but that
276 * only increases CPU efficiency by a small amount, at the
277 * expense of a huge expense of code complexity, and for an
278 * uncommon case at that.)
279 */
280 if (blk == bb->list[scan->bad_block_ptr]) {
281 scan->scan_flags |= EXT2_SF_BAD_INODE_BLK;
282 *num_blocks = 1;
283 if (++scan->bad_block_ptr >= bb->num)
284 scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
285 return 0;
286 }
287
288 /*
289 * If there is a bad block in the range that we're about to
290 * read in, adjust the number of blocks to read so that we we
291 * don't read in the bad block. (Then the next block to read
292 * will be the bad block, which is handled in the above case.)
293 */
294 if ((blk + *num_blocks) > bb->list[scan->bad_block_ptr])
295 *num_blocks = (int) (bb->list[scan->bad_block_ptr] - blk);
296
297 return 0;
298}
299
300/*
301 * This function is called by ext2fs_get_next_inode when it needs to
302 * read in more blocks from the current blockgroup's inode table.
303 */
304static errcode_t get_next_blocks(ext2_inode_scan scan)
305{
306 blk_t num_blocks;
307 errcode_t retval;
308
309 /*
310 * Figure out how many blocks to read; we read at most
311 * inode_buffer_blocks, and perhaps less if there aren't that
312 * many blocks left to read.
313 */
314 num_blocks = scan->inode_buffer_blocks;
315 if (num_blocks > scan->blocks_left)
316 num_blocks = scan->blocks_left;
317
318 /*
319 * If the past block "read" was a bad block, then mark the
320 * left-over extra bytes as also being bad.
321 */
322 if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) {
323 if (scan->bytes_left)
324 scan->scan_flags |= EXT2_SF_BAD_EXTRA_BYTES;
325 scan->scan_flags &= ~EXT2_SF_BAD_INODE_BLK;
326 }
327
328 /*
329 * Do inode bad block processing, if necessary.
330 */
331 if (scan->scan_flags & EXT2_SF_CHK_BADBLOCKS) {
332 retval = check_for_inode_bad_blocks(scan, &num_blocks);
333 if (retval)
334 return retval;
335 }
336
337 if ((scan->scan_flags & EXT2_SF_BAD_INODE_BLK) ||
338 (scan->current_block == 0)) {
339 memset(scan->inode_buffer, 0,
340 (size_t) num_blocks * scan->fs->blocksize);
341 } else {
342 retval = io_channel_read_blk(scan->fs->io,
343 scan->current_block,
344 (int) num_blocks,
345 scan->inode_buffer);
346 if (retval)
347 return EXT2_ET_NEXT_INODE_READ;
348 }
349 scan->ptr = scan->inode_buffer;
350 scan->bytes_left = num_blocks * scan->fs->blocksize;
351
352 scan->blocks_left -= num_blocks;
353 if (scan->current_block)
354 scan->current_block += num_blocks;
355 return 0;
356}
357
358errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, ext2_ino_t *ino,
359 struct ext2_inode *inode, int bufsize)
360{
361 errcode_t retval;
362 int extra_bytes = 0;
363
364 EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN);
365
366 /*
367 * Do we need to start reading a new block group?
368 */
369 if (scan->inodes_left <= 0) {
370 force_new_group:
371 if (scan->done_group) {
372 retval = (scan->done_group)
373 (scan->fs, scan->current_group,
374 scan->done_group_data);
375 if (retval)
376 return retval;
377 }
378 if (scan->groups_left <= 0) {
379 *ino = 0;
380 return 0;
381 }
382 retval = get_next_blockgroup(scan);
383 if (retval)
384 return retval;
385 }
386 /*
387 * This is done outside the above if statement so that the
388 * check can be done for block group #0.
389 */
390 if (scan->current_block == 0) {
391 if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) {
392 goto force_new_group;
393 } else
394 return EXT2_ET_MISSING_INODE_TABLE;
395 }
396
397
398 /*
399 * Have we run out of space in the inode buffer? If so, we
400 * need to read in more blocks.
401 */
402 if (scan->bytes_left < scan->inode_size) {
403 memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left);
404 extra_bytes = scan->bytes_left;
405
406 retval = get_next_blocks(scan);
407 if (retval)
408 return retval;
409#if 0
410 /*
411 * XXX test Need check for used inode somehow.
412 * (Note: this is hard.)
413 */
414 if (is_empty_scan(scan))
415 goto force_new_group;
416#endif
417 }
418
419 retval = 0;
420 if (extra_bytes) {
421 memcpy(scan->temp_buffer+extra_bytes, scan->ptr,
422 scan->inode_size - extra_bytes);
423 scan->ptr += scan->inode_size - extra_bytes;
424 scan->bytes_left -= scan->inode_size - extra_bytes;
425
426#if BB_BIG_ENDIAN
427 if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) ||
428 (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
429 ext2fs_swap_inode_full(scan->fs,
430 (struct ext2_inode_large *) inode,
431 (struct ext2_inode_large *) scan->temp_buffer,
432 0, bufsize);
433 else
434#endif
435 *inode = *((struct ext2_inode *) scan->temp_buffer);
436 if (scan->scan_flags & EXT2_SF_BAD_EXTRA_BYTES)
437 retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
438 scan->scan_flags &= ~EXT2_SF_BAD_EXTRA_BYTES;
439 } else {
440#if BB_BIG_ENDIAN
441 if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) ||
442 (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
443 ext2fs_swap_inode_full(scan->fs,
444 (struct ext2_inode_large *) inode,
445 (struct ext2_inode_large *) scan->ptr,
446 0, bufsize);
447 else
448#endif
449 memcpy(inode, scan->ptr, bufsize);
450 scan->ptr += scan->inode_size;
451 scan->bytes_left -= scan->inode_size;
452 if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK)
453 retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
454 }
455
456 scan->inodes_left--;
457 scan->current_inode++;
458 *ino = scan->current_inode;
459 return retval;
460}
461
462errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino,
463 struct ext2_inode *inode)
464{
465 return ext2fs_get_next_inode_full(scan, ino, inode,
466 sizeof(struct ext2_inode));
467}
468
469/*
470 * Functions to read and write a single inode.
471 */
472errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
473 struct ext2_inode * inode, int bufsize)
474{
475 unsigned long group, block, block_nr, offset;
476 char *ptr;
477 errcode_t retval;
478 int clen, i, inodes_per_block, length;
479 io_channel io;
480
481 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
482
483 /* Check to see if user has an override function */
484 if (fs->read_inode) {
485 retval = (fs->read_inode)(fs, ino, inode);
486 if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
487 return retval;
488 }
489 /* Create inode cache if not present */
490 if (!fs->icache) {
491 retval = create_icache(fs);
492 if (retval)
493 return retval;
494 }
495 /* Check to see if it's in the inode cache */
496 if (bufsize == sizeof(struct ext2_inode)) {
497 /* only old good inode can be retrieve from the cache */
498 for (i=0; i < fs->icache->cache_size; i++) {
499 if (fs->icache->cache[i].ino == ino) {
500 *inode = fs->icache->cache[i].inode;
501 return 0;
502 }
503 }
504 }
505 if ((ino == 0) || (ino > fs->super->s_inodes_count))
506 return EXT2_ET_BAD_INODE_NUM;
507 if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
508 inodes_per_block = fs->blocksize / EXT2_INODE_SIZE(fs->super);
509 block_nr = fs->image_header->offset_inode / fs->blocksize;
510 block_nr += (ino - 1) / inodes_per_block;
511 offset = ((ino - 1) % inodes_per_block) *
512 EXT2_INODE_SIZE(fs->super);
513 io = fs->image_io;
514 } else {
515 group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
516 offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
517 EXT2_INODE_SIZE(fs->super);
518 block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
519 if (!fs->group_desc[(unsigned)group].bg_inode_table)
520 return EXT2_ET_MISSING_INODE_TABLE;
521 block_nr = fs->group_desc[(unsigned)group].bg_inode_table +
522 block;
523 io = fs->io;
524 }
525 offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
526
527 length = EXT2_INODE_SIZE(fs->super);
528 if (bufsize < length)
529 length = bufsize;
530
531 ptr = (char *) inode;
532 while (length) {
533 clen = length;
534 if ((offset + length) > fs->blocksize)
535 clen = fs->blocksize - offset;
536
537 if (block_nr != fs->icache->buffer_blk) {
538 retval = io_channel_read_blk(io, block_nr, 1,
539 fs->icache->buffer);
540 if (retval)
541 return retval;
542 fs->icache->buffer_blk = block_nr;
543 }
544
545 memcpy(ptr, ((char *) fs->icache->buffer) + (unsigned) offset,
546 clen);
547
548 offset = 0;
549 length -= clen;
550 ptr += clen;
551 block_nr++;
552 }
553
554#if BB_BIG_ENDIAN
555 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
556 (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
557 ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) inode,
558 (struct ext2_inode_large *) inode,
559 0, length);
560#endif
561
562 /* Update the inode cache */
563 fs->icache->cache_last = (fs->icache->cache_last + 1) %
564 fs->icache->cache_size;
565 fs->icache->cache[fs->icache->cache_last].ino = ino;
566 fs->icache->cache[fs->icache->cache_last].inode = *inode;
567
568 return 0;
569}
570
571errcode_t ext2fs_read_inode(ext2_filsys fs, ext2_ino_t ino,
572 struct ext2_inode * inode)
573{
574 return ext2fs_read_inode_full(fs, ino, inode,
575 sizeof(struct ext2_inode));
576}
577
578errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino,
579 struct ext2_inode * inode, int bufsize)
580{
581 unsigned long group, block, block_nr, offset;
582 errcode_t retval = 0;
583 struct ext2_inode_large temp_inode, *w_inode;
584 char *ptr;
585 int clen, i, length;
586
587 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
588
589 /* Check to see if user provided an override function */
590 if (fs->write_inode) {
591 retval = (fs->write_inode)(fs, ino, inode);
592 if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
593 return retval;
594 }
595
596 /* Check to see if the inode cache needs to be updated */
597 if (fs->icache) {
598 for (i=0; i < fs->icache->cache_size; i++) {
599 if (fs->icache->cache[i].ino == ino) {
600 fs->icache->cache[i].inode = *inode;
601 break;
602 }
603 }
604 } else {
605 retval = create_icache(fs);
606 if (retval)
607 return retval;
608 }
609
610 if (!(fs->flags & EXT2_FLAG_RW))
611 return EXT2_ET_RO_FILSYS;
612
613 if ((ino == 0) || (ino > fs->super->s_inodes_count))
614 return EXT2_ET_BAD_INODE_NUM;
615
616 length = bufsize;
617 if (length < EXT2_INODE_SIZE(fs->super))
618 length = EXT2_INODE_SIZE(fs->super);
619
620 if (length > (int) sizeof(struct ext2_inode_large)) {
621 w_inode = xmalloc(length);
622 } else
623 w_inode = &temp_inode;
624 memset(w_inode, 0, length);
625
626#if BB_BIG_ENDIAN
627 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
628 (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
629 ext2fs_swap_inode_full(fs, w_inode,
630 (struct ext2_inode_large *) inode,
631 1, bufsize);
632 else
633#endif
634 memcpy(w_inode, inode, bufsize);
635
636 group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
637 offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
638 EXT2_INODE_SIZE(fs->super);
639 block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
640 if (!fs->group_desc[(unsigned) group].bg_inode_table)
641 return EXT2_ET_MISSING_INODE_TABLE;
642 block_nr = fs->group_desc[(unsigned) group].bg_inode_table + block;
643
644 offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
645
646 length = EXT2_INODE_SIZE(fs->super);
647 if (length > bufsize)
648 length = bufsize;
649
650 ptr = (char *) w_inode;
651
652 while (length) {
653 clen = length;
654 if ((offset + length) > fs->blocksize)
655 clen = fs->blocksize - offset;
656
657 if (fs->icache->buffer_blk != block_nr) {
658 retval = io_channel_read_blk(fs->io, block_nr, 1,
659 fs->icache->buffer);
660 if (retval)
661 goto errout;
662 fs->icache->buffer_blk = block_nr;
663 }
664
665
666 memcpy((char *) fs->icache->buffer + (unsigned) offset,
667 ptr, clen);
668
669 retval = io_channel_write_blk(fs->io, block_nr, 1,
670 fs->icache->buffer);
671 if (retval)
672 goto errout;
673
674 offset = 0;
675 ptr += clen;
676 length -= clen;
677 block_nr++;
678 }
679
680 fs->flags |= EXT2_FLAG_CHANGED;
681errout:
682 if (w_inode && w_inode != &temp_inode)
683 free(w_inode);
684 return retval;
685}
686
687errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino,
688 struct ext2_inode *inode)
689{
690 return ext2fs_write_inode_full(fs, ino, inode,
691 sizeof(struct ext2_inode));
692}
693
694/*
695 * This function should be called when writing a new inode. It makes
696 * sure that extra part of large inodes is initialized properly.
697 */
698errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino,
699 struct ext2_inode *inode)
700{
701 struct ext2_inode *buf;
702 int size = EXT2_INODE_SIZE(fs->super);
703 struct ext2_inode_large *large_inode;
704
705 if (size == sizeof(struct ext2_inode))
706 return ext2fs_write_inode_full(fs, ino, inode,
707 sizeof(struct ext2_inode));
708
709 buf = xmalloc(size);
710
711 memset(buf, 0, size);
712 *buf = *inode;
713
714 large_inode = (struct ext2_inode_large *) buf;
715 large_inode->i_extra_isize = sizeof(struct ext2_inode_large) -
716 EXT2_GOOD_OLD_INODE_SIZE;
717
718 return ext2fs_write_inode_full(fs, ino, buf, size);
719}
720
721
722errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks)
723{
724 struct ext2_inode inode;
725 int i;
726 errcode_t retval;
727
728 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
729
730 if (ino > fs->super->s_inodes_count)
731 return EXT2_ET_BAD_INODE_NUM;
732
733 if (fs->get_blocks) {
734 if (!(*fs->get_blocks)(fs, ino, blocks))
735 return 0;
736 }
737 retval = ext2fs_read_inode(fs, ino, &inode);
738 if (retval)
739 return retval;
740 for (i=0; i < EXT2_N_BLOCKS; i++)
741 blocks[i] = inode.i_block[i];
742 return 0;
743}
744
745errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino)
746{
747 struct ext2_inode inode;
748 errcode_t retval;
749
750 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
751
752 if (ino > fs->super->s_inodes_count)
753 return EXT2_ET_BAD_INODE_NUM;
754
755 if (fs->check_directory) {
756 retval = (fs->check_directory)(fs, ino);
757 if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
758 return retval;
759 }
760 retval = ext2fs_read_inode(fs, ino, &inode);
761 if (retval)
762 return retval;
763 if (!LINUX_S_ISDIR(inode.i_mode))
764 return EXT2_ET_NO_DIRECTORY;
765 return 0;
766}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/inode_io.c b/e2fsprogs/old_e2fsprogs/ext2fs/inode_io.c
deleted file mode 100644
index b861d5ff6..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/inode_io.c
+++ /dev/null
@@ -1,270 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * inode_io.c --- This is allows an inode in an ext2 filesystem image
4 * to be accessed via the I/O manager interface.
5 *
6 * Copyright (C) 2002 Theodore Ts'o.
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the GNU Public
10 * License.
11 * %End-Header%
12 */
13
14#include <stdio.h>
15#include <string.h>
16#if HAVE_UNISTD_H
17#include <unistd.h>
18#endif
19#if HAVE_ERRNO_H
20#include <errno.h>
21#endif
22#include <time.h>
23
24#include "ext2_fs.h"
25#include "ext2fs.h"
26
27/*
28 * For checking structure magic numbers...
29 */
30
31#define EXT2_CHECK_MAGIC(struct, code) \
32 if ((struct)->magic != (code)) return (code)
33
34struct inode_private_data {
35 int magic;
36 char name[32];
37 ext2_file_t file;
38 ext2_filsys fs;
39 ext2_ino_t ino;
40 struct ext2_inode inode;
41 int flags;
42 struct inode_private_data *next;
43};
44
45#define CHANNEL_HAS_INODE 0x8000
46
47static struct inode_private_data *top_intern;
48static int ino_unique = 0;
49
50static errcode_t inode_open(const char *name, int flags, io_channel *channel);
51static errcode_t inode_close(io_channel channel);
52static errcode_t inode_set_blksize(io_channel channel, int blksize);
53static errcode_t inode_read_blk(io_channel channel, unsigned long block,
54 int count, void *data);
55static errcode_t inode_write_blk(io_channel channel, unsigned long block,
56 int count, const void *data);
57static errcode_t inode_flush(io_channel channel);
58static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
59 int size, const void *data);
60
61static struct struct_io_manager struct_inode_manager = {
62 EXT2_ET_MAGIC_IO_MANAGER,
63 "Inode I/O Manager",
64 inode_open,
65 inode_close,
66 inode_set_blksize,
67 inode_read_blk,
68 inode_write_blk,
69 inode_flush,
70 inode_write_byte
71};
72
73io_manager inode_io_manager = &struct_inode_manager;
74
75errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino,
76 struct ext2_inode *inode,
77 char **name)
78{
79 struct inode_private_data *data;
80 errcode_t retval;
81
82 if ((retval = ext2fs_get_mem(sizeof(struct inode_private_data),
83 &data)))
84 return retval;
85 data->magic = EXT2_ET_MAGIC_INODE_IO_CHANNEL;
86 sprintf(data->name, "%u:%d", ino, ino_unique++);
87 data->file = 0;
88 data->fs = fs;
89 data->ino = ino;
90 data->flags = 0;
91 if (inode) {
92 memcpy(&data->inode, inode, sizeof(struct ext2_inode));
93 data->flags |= CHANNEL_HAS_INODE;
94 }
95 data->next = top_intern;
96 top_intern = data;
97 *name = data->name;
98 return 0;
99}
100
101errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino,
102 char **name)
103{
104 return ext2fs_inode_io_intern2(fs, ino, NULL, name);
105}
106
107
108static errcode_t inode_open(const char *name, int flags, io_channel *channel)
109{
110 io_channel io = NULL;
111 struct inode_private_data *prev, *data = NULL;
112 errcode_t retval;
113 int open_flags;
114
115 if (name == 0)
116 return EXT2_ET_BAD_DEVICE_NAME;
117
118 for (data = top_intern, prev = NULL; data;
119 prev = data, data = data->next)
120 if (strcmp(name, data->name) == 0)
121 break;
122 if (!data)
123 return ENOENT;
124 if (prev)
125 prev->next = data->next;
126 else
127 top_intern = data->next;
128
129 retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
130 if (retval)
131 goto cleanup;
132 memset(io, 0, sizeof(struct struct_io_channel));
133
134 io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
135 io->manager = inode_io_manager;
136 retval = ext2fs_get_mem(strlen(name)+1, &io->name);
137 if (retval)
138 goto cleanup;
139
140 strcpy(io->name, name);
141 io->private_data = data;
142 io->block_size = 1024;
143 io->read_error = 0;
144 io->write_error = 0;
145 io->refcount = 1;
146
147 open_flags = (flags & IO_FLAG_RW) ? EXT2_FILE_WRITE : 0;
148 retval = ext2fs_file_open2(data->fs, data->ino,
149 (data->flags & CHANNEL_HAS_INODE) ?
150 &data->inode : 0, open_flags,
151 &data->file);
152 if (retval)
153 goto cleanup;
154
155 *channel = io;
156 return 0;
157
158cleanup:
159 if (data) {
160 ext2fs_free_mem(&data);
161 }
162 if (io)
163 ext2fs_free_mem(&io);
164 return retval;
165}
166
167static errcode_t inode_close(io_channel channel)
168{
169 struct inode_private_data *data;
170 errcode_t retval = 0;
171
172 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
173 data = (struct inode_private_data *) channel->private_data;
174 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
175
176 if (--channel->refcount > 0)
177 return 0;
178
179 retval = ext2fs_file_close(data->file);
180
181 ext2fs_free_mem(&channel->private_data);
182 if (channel->name)
183 ext2fs_free_mem(&channel->name);
184 ext2fs_free_mem(&channel);
185 return retval;
186}
187
188static errcode_t inode_set_blksize(io_channel channel, int blksize)
189{
190 struct inode_private_data *data;
191
192 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
193 data = (struct inode_private_data *) channel->private_data;
194 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
195
196 channel->block_size = blksize;
197 return 0;
198}
199
200
201static errcode_t inode_read_blk(io_channel channel, unsigned long block,
202 int count, void *buf)
203{
204 struct inode_private_data *data;
205 errcode_t retval;
206
207 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
208 data = (struct inode_private_data *) channel->private_data;
209 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
210
211 if ((retval = ext2fs_file_lseek(data->file,
212 block * channel->block_size,
213 EXT2_SEEK_SET, 0)))
214 return retval;
215
216 count = (count < 0) ? -count : (count * channel->block_size);
217
218 return ext2fs_file_read(data->file, buf, count, 0);
219}
220
221static errcode_t inode_write_blk(io_channel channel, unsigned long block,
222 int count, const void *buf)
223{
224 struct inode_private_data *data;
225 errcode_t retval;
226
227 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
228 data = (struct inode_private_data *) channel->private_data;
229 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
230
231 if ((retval = ext2fs_file_lseek(data->file,
232 block * channel->block_size,
233 EXT2_SEEK_SET, 0)))
234 return retval;
235
236 count = (count < 0) ? -count : (count * channel->block_size);
237
238 return ext2fs_file_write(data->file, buf, count, 0);
239}
240
241static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
242 int size, const void *buf)
243{
244 struct inode_private_data *data;
245 errcode_t retval = 0;
246
247 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
248 data = (struct inode_private_data *) channel->private_data;
249 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
250
251 if ((retval = ext2fs_file_lseek(data->file, offset,
252 EXT2_SEEK_SET, 0)))
253 return retval;
254
255 return ext2fs_file_write(data->file, buf, size, 0);
256}
257
258/*
259 * Flush data buffers to disk.
260 */
261static errcode_t inode_flush(io_channel channel)
262{
263 struct inode_private_data *data;
264
265 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
266 data = (struct inode_private_data *) channel->private_data;
267 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
268
269 return ext2fs_file_flush(data->file);
270}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/io_manager.c b/e2fsprogs/old_e2fsprogs/ext2fs/io_manager.c
deleted file mode 100644
index b47038602..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/io_manager.c
+++ /dev/null
@@ -1,70 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * io_manager.c --- the I/O manager abstraction
4 */
5
6#include <stdio.h>
7#include <string.h>
8#if HAVE_UNISTD_H
9#include <unistd.h>
10#endif
11#include <fcntl.h>
12#include <time.h>
13#if HAVE_SYS_STAT_H
14#include <sys/stat.h>
15#endif
16#if HAVE_SYS_TYPES_H
17#include <sys/types.h>
18#endif
19
20#include "ext2_fs.h"
21#include "ext2fs.h"
22
23errcode_t io_channel_set_options(io_channel channel, const char *opts)
24{
25 errcode_t retval = 0;
26 char *next, *ptr, *options, *arg;
27
28 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
29
30 if (!opts)
31 return 0;
32
33 if (!channel->manager->set_option)
34 return EXT2_ET_INVALID_ARGUMENT;
35
36 options = malloc(strlen(opts)+1);
37 if (!options)
38 return EXT2_ET_NO_MEMORY;
39 strcpy(options, opts);
40 ptr = options;
41
42 while (ptr && *ptr) {
43 next = strchr(ptr, '&');
44 if (next)
45 *next++ = 0;
46
47 arg = strchr(ptr, '=');
48 if (arg)
49 *arg++ = 0;
50
51 retval = (channel->manager->set_option)(channel, ptr, arg);
52 if (retval)
53 break;
54 ptr = next;
55 }
56 free(options);
57 return retval;
58}
59
60errcode_t io_channel_write_byte(io_channel channel, unsigned long offset,
61 int count, const void *data)
62{
63 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
64
65 if (channel->manager->write_byte)
66 return channel->manager->write_byte(channel, offset,
67 count, data);
68
69 return EXT2_ET_UNIMPLEMENTED;
70}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/irel.h b/e2fsprogs/old_e2fsprogs/ext2fs/irel.h
deleted file mode 100644
index 91d1d89d5..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/irel.h
+++ /dev/null
@@ -1,115 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * irel.h
4 *
5 * Copyright (C) 1996, 1997 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13struct ext2_inode_reference {
14 blk_t block;
15 __u16 offset;
16};
17
18struct ext2_inode_relocate_entry {
19 ext2_ino_t new;
20 ext2_ino_t orig;
21 __u16 flags;
22 __u16 max_refs;
23};
24
25typedef struct ext2_inode_relocation_table *ext2_irel;
26
27struct ext2_inode_relocation_table {
28 __u32 magic;
29 char *name;
30 ext2_ino_t current;
31 void *priv_data;
32
33 /*
34 * Add an inode relocation entry.
35 */
36 errcode_t (*put)(ext2_irel irel, ext2_ino_t old,
37 struct ext2_inode_relocate_entry *ent);
38 /*
39 * Get an inode relocation entry.
40 */
41 errcode_t (*get)(ext2_irel irel, ext2_ino_t old,
42 struct ext2_inode_relocate_entry *ent);
43
44 /*
45 * Get an inode relocation entry by its original inode number
46 */
47 errcode_t (*get_by_orig)(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old,
48 struct ext2_inode_relocate_entry *ent);
49
50 /*
51 * Initialize for iterating over the inode relocation entries.
52 */
53 errcode_t (*start_iter)(ext2_irel irel);
54
55 /*
56 * The iterator function for the inode relocation entries.
57 * Returns an inode number of 0 when out of entries.
58 */
59 errcode_t (*next)(ext2_irel irel, ext2_ino_t *old,
60 struct ext2_inode_relocate_entry *ent);
61
62 /*
63 * Add an inode reference (i.e., note the fact that a
64 * particular block/offset contains a reference to an inode)
65 */
66 errcode_t (*add_ref)(ext2_irel irel, ext2_ino_t ino,
67 struct ext2_inode_reference *ref);
68
69 /*
70 * Initialize for iterating over the inode references for a
71 * particular inode.
72 */
73 errcode_t (*start_iter_ref)(ext2_irel irel, ext2_ino_t ino);
74
75 /*
76 * The iterator function for the inode references for an
77 * inode. The references for only one inode can be interator
78 * over at a time, as the iterator state is stored in ext2_irel.
79 */
80 errcode_t (*next_ref)(ext2_irel irel,
81 struct ext2_inode_reference *ref);
82
83 /*
84 * Move the inode relocation table from one inode number to
85 * another. Note that the inode references also must move.
86 */
87 errcode_t (*move)(ext2_irel irel, ext2_ino_t old, ext2_ino_t new);
88
89 /*
90 * Remove an inode relocation entry, along with all of the
91 * inode references.
92 */
93 errcode_t (*delete)(ext2_irel irel, ext2_ino_t old);
94
95 /*
96 * Free the inode relocation table.
97 */
98 errcode_t (*free)(ext2_irel irel);
99};
100
101errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode,
102 ext2_irel *irel);
103
104#define ext2fs_irel_put(irel, old, ent) ((irel)->put((irel), old, ent))
105#define ext2fs_irel_get(irel, old, ent) ((irel)->get((irel), old, ent))
106#define ext2fs_irel_get_by_orig(irel, orig, old, ent) \
107 ((irel)->get_by_orig((irel), orig, old, ent))
108#define ext2fs_irel_start_iter(irel) ((irel)->start_iter((irel)))
109#define ext2fs_irel_next(irel, old, ent) ((irel)->next((irel), old, ent))
110#define ext2fs_irel_add_ref(irel, ino, ref) ((irel)->add_ref((irel), ino, ref))
111#define ext2fs_irel_start_iter_ref(irel, ino) ((irel)->start_iter_ref((irel), ino))
112#define ext2fs_irel_next_ref(irel, ref) ((irel)->next_ref((irel), ref))
113#define ext2fs_irel_move(irel, old, new) ((irel)->move((irel), old, new))
114#define ext2fs_irel_delete(irel, old) ((irel)->delete((irel), old))
115#define ext2fs_irel_free(irel) ((irel)->free((irel)))
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/irel_ma.c b/e2fsprogs/old_e2fsprogs/ext2fs/irel_ma.c
deleted file mode 100644
index c871b1891..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/irel_ma.c
+++ /dev/null
@@ -1,367 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * irel_ma.c
4 *
5 * Copyright (C) 1996, 1997 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <fcntl.h>
14#include <stdio.h>
15#include <string.h>
16#if HAVE_UNISTD_H
17#include <unistd.h>
18#endif
19#if HAVE_ERRNO_H
20#include <errno.h>
21#endif
22
23#include "ext2_fs.h"
24#include "ext2fs.h"
25#include "irel.h"
26
27static errcode_t ima_put(ext2_irel irel, ext2_ino_t old,
28 struct ext2_inode_relocate_entry *ent);
29static errcode_t ima_get(ext2_irel irel, ext2_ino_t old,
30 struct ext2_inode_relocate_entry *ent);
31static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old,
32 struct ext2_inode_relocate_entry *ent);
33static errcode_t ima_start_iter(ext2_irel irel);
34static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old,
35 struct ext2_inode_relocate_entry *ent);
36static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino,
37 struct ext2_inode_reference *ref);
38static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino);
39static errcode_t ima_next_ref(ext2_irel irel, struct ext2_inode_reference *ref);
40static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new);
41static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old);
42static errcode_t ima_free(ext2_irel irel);
43
44/*
45 * This data structure stores the array of inode references; there is
46 * a structure for each inode.
47 */
48struct inode_reference_entry {
49 __u16 num;
50 struct ext2_inode_reference *refs;
51};
52
53struct irel_ma {
54 __u32 magic;
55 ext2_ino_t max_inode;
56 ext2_ino_t ref_current;
57 int ref_iter;
58 ext2_ino_t *orig_map;
59 struct ext2_inode_relocate_entry *entries;
60 struct inode_reference_entry *ref_entries;
61};
62
63errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode,
64 ext2_irel *new_irel)
65{
66 ext2_irel irel = 0;
67 errcode_t retval;
68 struct irel_ma *ma = 0;
69 size_t size;
70
71 *new_irel = 0;
72
73 /*
74 * Allocate memory structures
75 */
76 retval = ext2fs_get_mem(sizeof(struct ext2_inode_relocation_table),
77 &irel);
78 if (retval)
79 goto errout;
80 memset(irel, 0, sizeof(struct ext2_inode_relocation_table));
81
82 retval = ext2fs_get_mem(strlen(name)+1, &irel->name);
83 if (retval)
84 goto errout;
85 strcpy(irel->name, name);
86
87 retval = ext2fs_get_mem(sizeof(struct irel_ma), &ma);
88 if (retval)
89 goto errout;
90 memset(ma, 0, sizeof(struct irel_ma));
91 irel->priv_data = ma;
92
93 size = (size_t) (sizeof(ext2_ino_t) * (max_inode+1));
94 retval = ext2fs_get_mem(size, &ma->orig_map);
95 if (retval)
96 goto errout;
97 memset(ma->orig_map, 0, size);
98
99 size = (size_t) (sizeof(struct ext2_inode_relocate_entry) *
100 (max_inode+1));
101 retval = ext2fs_get_mem(size, &ma->entries);
102 if (retval)
103 goto errout;
104 memset(ma->entries, 0, size);
105
106 size = (size_t) (sizeof(struct inode_reference_entry) *
107 (max_inode+1));
108 retval = ext2fs_get_mem(size, &ma->ref_entries);
109 if (retval)
110 goto errout;
111 memset(ma->ref_entries, 0, size);
112 ma->max_inode = max_inode;
113
114 /*
115 * Fill in the irel data structure
116 */
117 irel->put = ima_put;
118 irel->get = ima_get;
119 irel->get_by_orig = ima_get_by_orig;
120 irel->start_iter = ima_start_iter;
121 irel->next = ima_next;
122 irel->add_ref = ima_add_ref;
123 irel->start_iter_ref = ima_start_iter_ref;
124 irel->next_ref = ima_next_ref;
125 irel->move = ima_move;
126 irel->delete = ima_delete;
127 irel->free = ima_free;
128
129 *new_irel = irel;
130 return 0;
131
132errout:
133 ima_free(irel);
134 return retval;
135}
136
137static errcode_t ima_put(ext2_irel irel, ext2_ino_t old,
138 struct ext2_inode_relocate_entry *ent)
139{
140 struct inode_reference_entry *ref_ent;
141 struct irel_ma *ma;
142 errcode_t retval;
143 size_t size, old_size;
144
145 ma = irel->priv_data;
146 if (old > ma->max_inode)
147 return EXT2_ET_INVALID_ARGUMENT;
148
149 /*
150 * Force the orig field to the correct value; the application
151 * program shouldn't be messing with this field.
152 */
153 if (ma->entries[(unsigned) old].new == 0)
154 ent->orig = old;
155 else
156 ent->orig = ma->entries[(unsigned) old].orig;
157
158 /*
159 * If max_refs has changed, reallocate the refs array
160 */
161 ref_ent = ma->ref_entries + (unsigned) old;
162 if (ref_ent->refs && ent->max_refs !=
163 ma->entries[(unsigned) old].max_refs) {
164 size = (sizeof(struct ext2_inode_reference) * ent->max_refs);
165 old_size = (sizeof(struct ext2_inode_reference) *
166 ma->entries[(unsigned) old].max_refs);
167 retval = ext2fs_resize_mem(old_size, size, &ref_ent->refs);
168 if (retval)
169 return retval;
170 }
171
172 ma->entries[(unsigned) old] = *ent;
173 ma->orig_map[(unsigned) ent->orig] = old;
174 return 0;
175}
176
177static errcode_t ima_get(ext2_irel irel, ext2_ino_t old,
178 struct ext2_inode_relocate_entry *ent)
179{
180 struct irel_ma *ma;
181
182 ma = irel->priv_data;
183 if (old > ma->max_inode)
184 return EXT2_ET_INVALID_ARGUMENT;
185 if (ma->entries[(unsigned) old].new == 0)
186 return ENOENT;
187 *ent = ma->entries[(unsigned) old];
188 return 0;
189}
190
191static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old,
192 struct ext2_inode_relocate_entry *ent)
193{
194 struct irel_ma *ma;
195 ext2_ino_t ino;
196
197 ma = irel->priv_data;
198 if (orig > ma->max_inode)
199 return EXT2_ET_INVALID_ARGUMENT;
200 ino = ma->orig_map[(unsigned) orig];
201 if (ino == 0)
202 return ENOENT;
203 *old = ino;
204 *ent = ma->entries[(unsigned) ino];
205 return 0;
206}
207
208static errcode_t ima_start_iter(ext2_irel irel)
209{
210 irel->current = 0;
211 return 0;
212}
213
214static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old,
215 struct ext2_inode_relocate_entry *ent)
216{
217 struct irel_ma *ma;
218
219 ma = irel->priv_data;
220 while (++irel->current < ma->max_inode) {
221 if (ma->entries[(unsigned) irel->current].new == 0)
222 continue;
223 *old = irel->current;
224 *ent = ma->entries[(unsigned) irel->current];
225 return 0;
226 }
227 *old = 0;
228 return 0;
229}
230
231static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino,
232 struct ext2_inode_reference *ref)
233{
234 struct irel_ma *ma;
235 size_t size;
236 struct inode_reference_entry *ref_ent;
237 struct ext2_inode_relocate_entry *ent;
238 errcode_t retval;
239
240 ma = irel->priv_data;
241 if (ino > ma->max_inode)
242 return EXT2_ET_INVALID_ARGUMENT;
243
244 ref_ent = ma->ref_entries + (unsigned) ino;
245 ent = ma->entries + (unsigned) ino;
246
247 /*
248 * If the inode reference array doesn't exist, create it.
249 */
250 if (ref_ent->refs == 0) {
251 size = (size_t) ((sizeof(struct ext2_inode_reference) *
252 ent->max_refs));
253 retval = ext2fs_get_mem(size, &ref_ent->refs);
254 if (retval)
255 return retval;
256 memset(ref_ent->refs, 0, size);
257 ref_ent->num = 0;
258 }
259
260 if (ref_ent->num >= ent->max_refs)
261 return EXT2_ET_TOO_MANY_REFS;
262
263 ref_ent->refs[(unsigned) ref_ent->num++] = *ref;
264 return 0;
265}
266
267static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino)
268{
269 struct irel_ma *ma;
270
271 ma = irel->priv_data;
272 if (ino > ma->max_inode)
273 return EXT2_ET_INVALID_ARGUMENT;
274 if (ma->entries[(unsigned) ino].new == 0)
275 return ENOENT;
276 ma->ref_current = ino;
277 ma->ref_iter = 0;
278 return 0;
279}
280
281static errcode_t ima_next_ref(ext2_irel irel,
282 struct ext2_inode_reference *ref)
283{
284 struct irel_ma *ma;
285 struct inode_reference_entry *ref_ent;
286
287 ma = irel->priv_data;
288
289 ref_ent = ma->ref_entries + ma->ref_current;
290
291 if ((ref_ent->refs == NULL) ||
292 (ma->ref_iter >= ref_ent->num)) {
293 ref->block = 0;
294 ref->offset = 0;
295 return 0;
296 }
297 *ref = ref_ent->refs[ma->ref_iter++];
298 return 0;
299}
300
301
302static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new)
303{
304 struct irel_ma *ma;
305
306 ma = irel->priv_data;
307 if ((old > ma->max_inode) || (new > ma->max_inode))
308 return EXT2_ET_INVALID_ARGUMENT;
309 if (ma->entries[(unsigned) old].new == 0)
310 return ENOENT;
311
312 ma->entries[(unsigned) new] = ma->entries[(unsigned) old];
313 ext2fs_free_mem(&ma->ref_entries[(unsigned) new].refs);
314 ma->ref_entries[(unsigned) new] = ma->ref_entries[(unsigned) old];
315
316 ma->entries[(unsigned) old].new = 0;
317 ma->ref_entries[(unsigned) old].num = 0;
318 ma->ref_entries[(unsigned) old].refs = 0;
319
320 ma->orig_map[ma->entries[new].orig] = new;
321 return 0;
322}
323
324static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old)
325{
326 struct irel_ma *ma;
327
328 ma = irel->priv_data;
329 if (old > ma->max_inode)
330 return EXT2_ET_INVALID_ARGUMENT;
331 if (ma->entries[(unsigned) old].new == 0)
332 return ENOENT;
333
334 ma->entries[old].new = 0;
335 ext2fs_free_mem(&ma->ref_entries[(unsigned) old].refs);
336 ma->orig_map[ma->entries[(unsigned) old].orig] = 0;
337
338 ma->ref_entries[(unsigned) old].num = 0;
339 ma->ref_entries[(unsigned) old].refs = 0;
340 return 0;
341}
342
343static errcode_t ima_free(ext2_irel irel)
344{
345 struct irel_ma *ma;
346 ext2_ino_t ino;
347
348 if (!irel)
349 return 0;
350
351 ma = irel->priv_data;
352
353 if (ma) {
354 ext2fs_free_mem(&ma->orig_map);
355 ext2fs_free_mem(&ma->entries);
356 if (ma->ref_entries) {
357 for (ino = 0; ino <= ma->max_inode; ino++) {
358 ext2fs_free_mem(&ma->ref_entries[(unsigned) ino].refs);
359 }
360 ext2fs_free_mem(&ma->ref_entries);
361 }
362 ext2fs_free_mem(&ma);
363 }
364 ext2fs_free_mem(&irel->name);
365 ext2fs_free_mem(&irel);
366 return 0;
367}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/ismounted.c b/e2fsprogs/old_e2fsprogs/ext2fs/ismounted.c
deleted file mode 100644
index f5f6f31cd..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/ismounted.c
+++ /dev/null
@@ -1,357 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * ismounted.c --- Check to see if the filesystem was mounted
4 *
5 * Copyright (C) 1995,1996,1997,1998,1999,2000 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#if HAVE_UNISTD_H
15#include <unistd.h>
16#endif
17#if HAVE_ERRNO_H
18#include <errno.h>
19#endif
20#include <fcntl.h>
21#ifdef HAVE_LINUX_FD_H
22#include <linux/fd.h>
23#endif
24#ifdef HAVE_MNTENT_H
25#include <mntent.h>
26#endif
27#ifdef HAVE_GETMNTINFO
28#include <paths.h>
29#include <sys/param.h>
30#include <sys/mount.h>
31#endif /* HAVE_GETMNTINFO */
32#include <string.h>
33#include <sys/stat.h>
34
35#include "ext2_fs.h"
36#include "ext2fs.h"
37
38#ifdef HAVE_MNTENT_H
39/*
40 * Helper function which checks a file in /etc/mtab format to see if a
41 * filesystem is mounted. Returns an error if the file doesn't exist
42 * or can't be opened.
43 */
44static errcode_t check_mntent_file(const char *mtab_file, const char *file,
45 int *mount_flags, char *mtpt, int mtlen)
46{
47 struct mntent *mnt;
48 struct stat st_buf;
49 errcode_t retval = 0;
50 dev_t file_dev=0, file_rdev=0;
51 ino_t file_ino=0;
52 FILE *f;
53 int fd;
54
55 *mount_flags = 0;
56 if ((f = setmntent (mtab_file, "r")) == NULL)
57 return errno;
58 if (stat(file, &st_buf) == 0) {
59 if (S_ISBLK(st_buf.st_mode)) {
60#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
61 file_rdev = st_buf.st_rdev;
62#endif /* __GNU__ */
63 } else {
64 file_dev = st_buf.st_dev;
65 file_ino = st_buf.st_ino;
66 }
67 }
68 while ((mnt = getmntent (f)) != NULL) {
69 if (strcmp(file, mnt->mnt_fsname) == 0)
70 break;
71 if (stat(mnt->mnt_fsname, &st_buf) == 0) {
72 if (S_ISBLK(st_buf.st_mode)) {
73#ifndef __GNU__
74 if (file_rdev && (file_rdev == st_buf.st_rdev))
75 break;
76#endif /* __GNU__ */
77 } else {
78 if (file_dev && ((file_dev == st_buf.st_dev) &&
79 (file_ino == st_buf.st_ino)))
80 break;
81 }
82 }
83 }
84
85 if (mnt == 0) {
86#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
87 /*
88 * Do an extra check to see if this is the root device. We
89 * can't trust /etc/mtab, and /proc/mounts will only list
90 * /dev/root for the root filesystem. Argh. Instead we
91 * check if the given device has the same major/minor number
92 * as the device that the root directory is on.
93 */
94 if (file_rdev && stat("/", &st_buf) == 0) {
95 if (st_buf.st_dev == file_rdev) {
96 *mount_flags = EXT2_MF_MOUNTED;
97 if (mtpt)
98 strncpy(mtpt, "/", mtlen);
99 goto is_root;
100 }
101 }
102#endif /* __GNU__ */
103 goto errout;
104 }
105#ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */
106 /* Validate the entry in case /etc/mtab is out of date */
107 /*
108 * We need to be paranoid, because some broken distributions
109 * (read: Slackware) don't initialize /etc/mtab before checking
110 * all of the non-root filesystems on the disk.
111 */
112 if (stat(mnt->mnt_dir, &st_buf) < 0) {
113 retval = errno;
114 if (retval == ENOENT) {
115#ifdef DEBUG
116 printf("Bogus entry in %s! (%s does not exist)\n",
117 mtab_file, mnt->mnt_dir);
118#endif /* DEBUG */
119 retval = 0;
120 }
121 goto errout;
122 }
123 if (file_rdev && (st_buf.st_dev != file_rdev)) {
124#ifdef DEBUG
125 printf("Bogus entry in %s! (%s not mounted on %s)\n",
126 mtab_file, file, mnt->mnt_dir);
127#endif /* DEBUG */
128 goto errout;
129 }
130#endif /* __GNU__ */
131 *mount_flags = EXT2_MF_MOUNTED;
132
133#ifdef MNTOPT_RO
134 /* Check to see if the ro option is set */
135 if (hasmntopt(mnt, MNTOPT_RO))
136 *mount_flags |= EXT2_MF_READONLY;
137#endif
138
139 if (mtpt)
140 strncpy(mtpt, mnt->mnt_dir, mtlen);
141 /*
142 * Check to see if we're referring to the root filesystem.
143 * If so, do a manual check to see if we can open /etc/mtab
144 * read/write, since if the root is mounted read/only, the
145 * contents of /etc/mtab may not be accurate.
146 */
147 if (LONE_CHAR(mnt->mnt_dir, '/')) {
148is_root:
149#define TEST_FILE "/.ismount-test-file"
150 *mount_flags |= EXT2_MF_ISROOT;
151 fd = open(TEST_FILE, O_RDWR|O_CREAT);
152 if (fd < 0) {
153 if (errno == EROFS)
154 *mount_flags |= EXT2_MF_READONLY;
155 } else
156 close(fd);
157 (void) unlink(TEST_FILE);
158 }
159 retval = 0;
160errout:
161 endmntent (f);
162 return retval;
163}
164
165static errcode_t check_mntent(const char *file, int *mount_flags,
166 char *mtpt, int mtlen)
167{
168 errcode_t retval;
169
170#ifdef DEBUG
171 retval = check_mntent_file("/tmp/mtab", file, mount_flags,
172 mtpt, mtlen);
173 if (retval == 0)
174 return 0;
175#endif /* DEBUG */
176#ifdef __linux__
177 retval = check_mntent_file("/proc/mounts", file, mount_flags,
178 mtpt, mtlen);
179 if (retval == 0 && (*mount_flags != 0))
180 return 0;
181#endif /* __linux__ */
182#if defined(MOUNTED) || defined(_PATH_MOUNTED)
183#ifndef MOUNTED
184#define MOUNTED _PATH_MOUNTED
185#endif /* MOUNTED */
186 retval = check_mntent_file(MOUNTED, file, mount_flags, mtpt, mtlen);
187 return retval;
188#else
189 *mount_flags = 0;
190 return 0;
191#endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */
192}
193
194#else
195#if defined(HAVE_GETMNTINFO)
196
197static errcode_t check_getmntinfo(const char *file, int *mount_flags,
198 char *mtpt, int mtlen)
199{
200 struct statfs *mp;
201 int len, n;
202 const char *s1;
203 char *s2;
204
205 n = getmntinfo(&mp, MNT_NOWAIT);
206 if (n == 0)
207 return errno;
208
209 len = sizeof(_PATH_DEV) - 1;
210 s1 = file;
211 if (strncmp(_PATH_DEV, s1, len) == 0)
212 s1 += len;
213
214 *mount_flags = 0;
215 while (--n >= 0) {
216 s2 = mp->f_mntfromname;
217 if (strncmp(_PATH_DEV, s2, len) == 0) {
218 s2 += len - 1;
219 *s2 = 'r';
220 }
221 if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) {
222 *mount_flags = EXT2_MF_MOUNTED;
223 break;
224 }
225 ++mp;
226 }
227 if (mtpt)
228 strncpy(mtpt, mp->f_mntonname, mtlen);
229 return 0;
230}
231#endif /* HAVE_GETMNTINFO */
232#endif /* HAVE_MNTENT_H */
233
234/*
235 * Check to see if we're dealing with the swap device.
236 */
237static int is_swap_device(const char *file)
238{
239 FILE *f;
240 char buf[1024], *cp;
241 dev_t file_dev;
242 struct stat st_buf;
243 int ret = 0;
244
245 file_dev = 0;
246#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
247 if ((stat(file, &st_buf) == 0) &&
248 S_ISBLK(st_buf.st_mode))
249 file_dev = st_buf.st_rdev;
250#endif /* __GNU__ */
251
252 if (!(f = fopen_for_read("/proc/swaps")))
253 return 0;
254 /* Skip the first line */
255 fgets(buf, sizeof(buf), f);
256 while (!feof(f)) {
257 if (!fgets(buf, sizeof(buf), f))
258 break;
259 if ((cp = strchr(buf, ' ')) != NULL)
260 *cp = 0;
261 if ((cp = strchr(buf, '\t')) != NULL)
262 *cp = 0;
263 if (strcmp(buf, file) == 0) {
264 ret++;
265 break;
266 }
267#ifndef __GNU__
268 if (file_dev && (stat(buf, &st_buf) == 0) &&
269 S_ISBLK(st_buf.st_mode) &&
270 file_dev == st_buf.st_rdev) {
271 ret++;
272 break;
273 }
274#endif /* __GNU__ */
275 }
276 fclose(f);
277 return ret;
278}
279
280
281/*
282 * ext2fs_check_mount_point() returns 1 if the device is mounted, 0
283 * otherwise. If mtpt is non-NULL, the directory where the device is
284 * mounted is copied to where mtpt is pointing, up to mtlen
285 * characters.
286 */
287#ifdef __TURBOC__
288# pragma argsused
289#endif
290errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags,
291 char *mtpt, int mtlen)
292{
293 if (is_swap_device(device)) {
294 *mount_flags = EXT2_MF_MOUNTED | EXT2_MF_SWAP;
295 strncpy(mtpt, "<swap>", mtlen);
296 return 0;
297 }
298#ifdef HAVE_MNTENT_H
299 return check_mntent(device, mount_flags, mtpt, mtlen);
300#else
301#ifdef HAVE_GETMNTINFO
302 return check_getmntinfo(device, mount_flags, mtpt, mtlen);
303#else
304#ifdef __GNUC__
305 #warning "Can't use getmntent or getmntinfo to check for mounted filesystems!"
306#endif
307 *mount_flags = 0;
308 return 0;
309#endif /* HAVE_GETMNTINFO */
310#endif /* HAVE_MNTENT_H */
311}
312
313/*
314 * ext2fs_check_if_mounted() sets the mount_flags EXT2_MF_MOUNTED,
315 * EXT2_MF_READONLY, and EXT2_MF_ROOT
316 *
317 */
318errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags)
319{
320 return ext2fs_check_mount_point(file, mount_flags, NULL, 0);
321}
322
323#ifdef DEBUG
324int main(int argc, char **argv)
325{
326 int retval, mount_flags;
327 char mntpt[80];
328
329 if (argc < 2) {
330 fprintf(stderr, "Usage: %s device\n", argv[0]);
331 exit(1);
332 }
333
334 mntpt[0] = 0;
335 retval = ext2fs_check_mount_point(argv[1], &mount_flags,
336 mntpt, sizeof(mntpt));
337 if (retval) {
338 com_err(argv[0], retval,
339 "while calling ext2fs_check_if_mounted");
340 exit(1);
341 }
342 printf("Device %s reports flags %02x\n", argv[1], mount_flags);
343 if (mount_flags & EXT2_MF_BUSY)
344 printf("\t%s is apparently in use.\n", argv[1]);
345 if (mount_flags & EXT2_MF_MOUNTED)
346 printf("\t%s is mounted.\n", argv[1]);
347 if (mount_flags & EXT2_MF_SWAP)
348 printf("\t%s is a swap device.\n", argv[1]);
349 if (mount_flags & EXT2_MF_READONLY)
350 printf("\t%s is read-only.\n", argv[1]);
351 if (mount_flags & EXT2_MF_ISROOT)
352 printf("\t%s is the root filesystem.\n", argv[1]);
353 if (mntpt[0])
354 printf("\t%s is mounted on %s.\n", argv[1], mntpt);
355 exit(0);
356}
357#endif /* DEBUG */
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/jfs_dat.h b/e2fsprogs/old_e2fsprogs/ext2fs/jfs_dat.h
deleted file mode 100644
index 17c586a29..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/jfs_dat.h
+++ /dev/null
@@ -1,63 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * jfs_dat.h --- stripped down header file which only contains the JFS
4 * on-disk data structures
5 */
6
7#define JFS_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */
8
9/*
10 * On-disk structures
11 */
12
13/*
14 * Descriptor block types:
15 */
16
17#define JFS_DESCRIPTOR_BLOCK 1
18#define JFS_COMMIT_BLOCK 2
19#define JFS_SUPERBLOCK 3
20
21/*
22 * Standard header for all descriptor blocks:
23 */
24typedef struct journal_header_s
25{
26 __u32 h_magic;
27 __u32 h_blocktype;
28 __u32 h_sequence;
29} journal_header_t;
30
31
32/*
33 * The block tag: used to describe a single buffer in the journal
34 */
35typedef struct journal_block_tag_s
36{
37 __u32 t_blocknr; /* The on-disk block number */
38 __u32 t_flags; /* See below */
39} journal_block_tag_t;
40
41/* Definitions for the journal tag flags word: */
42#define JFS_FLAG_ESCAPE 1 /* on-disk block is escaped */
43#define JFS_FLAG_SAME_UUID 2 /* block has same uuid as previous */
44#define JFS_FLAG_DELETED 4 /* block deleted by this transaction */
45#define JFS_FLAG_LAST_TAG 8 /* last tag in this descriptor block */
46
47
48/*
49 * The journal superblock
50 */
51typedef struct journal_superblock_s
52{
53 journal_header_t s_header;
54
55 /* Static information describing the journal */
56 __u32 s_blocksize; /* journal device blocksize */
57 __u32 s_maxlen; /* total blocks in journal file */
58 __u32 s_first; /* first block of log information */
59
60 /* Dynamic information describing the current state of the log */
61 __u32 s_sequence; /* first commit ID expected in log */
62 __u32 s_start; /* blocknr of start of log */
63} journal_superblock_t;
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/kernel-jbd.h b/e2fsprogs/old_e2fsprogs/ext2fs/kernel-jbd.h
deleted file mode 100644
index 853d97ac7..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/kernel-jbd.h
+++ /dev/null
@@ -1,235 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * linux/include/linux/jbd.h
4 *
5 * Written by Stephen C. Tweedie <sct@redhat.com>
6 *
7 * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved
8 *
9 * This file is part of the Linux kernel and is made available under
10 * the terms of the GNU General Public License, version 2, or at your
11 * option, any later version, incorporated herein by reference.
12 *
13 * Definitions for transaction data structures for the buffer cache
14 * filesystem journaling support.
15 */
16#ifndef LINUX_JBD_H
17#define LINUX_JBD_H 1
18
19#include <sys/types.h>
20#include <linux/types.h>
21#include "ext2fs.h"
22
23/*
24 * Standard header for all descriptor blocks:
25 */
26
27typedef struct journal_header_s
28{
29 __u32 h_magic;
30 __u32 h_blocktype;
31 __u32 h_sequence;
32} journal_header_t;
33
34/*
35 * This is the global e2fsck structure.
36 */
37typedef struct e2fsck_struct *e2fsck_t;
38
39
40struct inode {
41 e2fsck_t i_ctx;
42 ext2_ino_t i_ino;
43 struct ext2_inode i_ext2;
44};
45
46
47/*
48 * The journal superblock. All fields are in big-endian byte order.
49 */
50typedef struct journal_superblock_s
51{
52/* 0x0000 */
53 journal_header_t s_header;
54
55/* 0x000C */
56 /* Static information describing the journal */
57 __u32 s_blocksize; /* journal device blocksize */
58 __u32 s_maxlen; /* total blocks in journal file */
59 __u32 s_first; /* first block of log information */
60
61/* 0x0018 */
62 /* Dynamic information describing the current state of the log */
63 __u32 s_sequence; /* first commit ID expected in log */
64 __u32 s_start; /* blocknr of start of log */
65
66/* 0x0020 */
67 /* Error value, as set by journal_abort(). */
68 __s32 s_errno;
69
70/* 0x0024 */
71 /* Remaining fields are only valid in a version-2 superblock */
72 __u32 s_feature_compat; /* compatible feature set */
73 __u32 s_feature_incompat; /* incompatible feature set */
74 __u32 s_feature_ro_compat; /* readonly-compatible feature set */
75/* 0x0030 */
76 __u8 s_uuid[16]; /* 128-bit uuid for journal */
77
78/* 0x0040 */
79 __u32 s_nr_users; /* Nr of filesystems sharing log */
80
81 __u32 s_dynsuper; /* Blocknr of dynamic superblock copy*/
82
83/* 0x0048 */
84 __u32 s_max_transaction; /* Limit of journal blocks per trans.*/
85 __u32 s_max_trans_data; /* Limit of data blocks per trans. */
86
87/* 0x0050 */
88 __u32 s_padding[44];
89
90/* 0x0100 */
91 __u8 s_users[16*48]; /* ids of all fs'es sharing the log */
92/* 0x0400 */
93} journal_superblock_t;
94
95
96extern int journal_blocks_per_page(struct inode *inode);
97extern int jbd_blocks_per_page(struct inode *inode);
98
99#define JFS_MIN_JOURNAL_BLOCKS 1024
100
101
102/*
103 * Internal structures used by the logging mechanism:
104 */
105
106#define JFS_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */
107
108/*
109 * Descriptor block types:
110 */
111
112#define JFS_DESCRIPTOR_BLOCK 1
113#define JFS_COMMIT_BLOCK 2
114#define JFS_SUPERBLOCK_V1 3
115#define JFS_SUPERBLOCK_V2 4
116#define JFS_REVOKE_BLOCK 5
117
118/*
119 * The block tag: used to describe a single buffer in the journal
120 */
121typedef struct journal_block_tag_s
122{
123 __u32 t_blocknr; /* The on-disk block number */
124 __u32 t_flags; /* See below */
125} journal_block_tag_t;
126
127/*
128 * The revoke descriptor: used on disk to describe a series of blocks to
129 * be revoked from the log
130 */
131typedef struct journal_revoke_header_s
132{
133 journal_header_t r_header;
134 int r_count; /* Count of bytes used in the block */
135} journal_revoke_header_t;
136
137
138/* Definitions for the journal tag flags word: */
139#define JFS_FLAG_ESCAPE 1 /* on-disk block is escaped */
140#define JFS_FLAG_SAME_UUID 2 /* block has same uuid as previous */
141#define JFS_FLAG_DELETED 4 /* block deleted by this transaction */
142#define JFS_FLAG_LAST_TAG 8 /* last tag in this descriptor block */
143
144
145
146
147#define JFS_HAS_COMPAT_FEATURE(j,mask) \
148 ((j)->j_format_version >= 2 && \
149 ((j)->j_superblock->s_feature_compat & cpu_to_be32((mask))))
150#define JFS_HAS_RO_COMPAT_FEATURE(j,mask) \
151 ((j)->j_format_version >= 2 && \
152 ((j)->j_superblock->s_feature_ro_compat & cpu_to_be32((mask))))
153#define JFS_HAS_INCOMPAT_FEATURE(j,mask) \
154 ((j)->j_format_version >= 2 && \
155 ((j)->j_superblock->s_feature_incompat & cpu_to_be32((mask))))
156
157#define JFS_FEATURE_INCOMPAT_REVOKE 0x00000001
158
159/* Features known to this kernel version: */
160#define JFS_KNOWN_COMPAT_FEATURES 0
161#define JFS_KNOWN_ROCOMPAT_FEATURES 0
162#define JFS_KNOWN_INCOMPAT_FEATURES JFS_FEATURE_INCOMPAT_REVOKE
163
164/* Comparison functions for transaction IDs: perform comparisons using
165 * modulo arithmetic so that they work over sequence number wraps. */
166
167
168/*
169 * Definitions which augment the buffer_head layer
170 */
171
172/* journaling buffer types */
173#define BJ_None 0 /* Not journaled */
174#define BJ_SyncData 1 /* Normal data: flush before commit */
175#define BJ_AsyncData 2 /* writepage data: wait on it before commit */
176#define BJ_Metadata 3 /* Normal journaled metadata */
177#define BJ_Forget 4 /* Buffer superceded by this transaction */
178#define BJ_IO 5 /* Buffer is for temporary IO use */
179#define BJ_Shadow 6 /* Buffer contents being shadowed to the log */
180#define BJ_LogCtl 7 /* Buffer contains log descriptors */
181#define BJ_Reserved 8 /* Buffer is reserved for access by journal */
182#define BJ_Types 9
183
184
185struct kdev_s {
186 e2fsck_t k_ctx;
187 int k_dev;
188};
189
190typedef struct kdev_s *kdev_t;
191typedef unsigned int tid_t;
192
193struct journal_s
194{
195 unsigned long j_flags;
196 int j_errno;
197 struct buffer_head * j_sb_buffer;
198 struct journal_superblock_s *j_superblock;
199 int j_format_version;
200 unsigned long j_head;
201 unsigned long j_tail;
202 unsigned long j_free;
203 unsigned long j_first, j_last;
204 kdev_t j_dev;
205 kdev_t j_fs_dev;
206 int j_blocksize;
207 unsigned int j_blk_offset;
208 unsigned int j_maxlen;
209 struct inode * j_inode;
210 tid_t j_tail_sequence;
211 tid_t j_transaction_sequence;
212 __u8 j_uuid[16];
213 struct jbd_revoke_table_s *j_revoke;
214};
215
216typedef struct journal_s journal_t;
217
218extern int journal_recover (journal_t *journal);
219extern int journal_skip_recovery (journal_t *);
220
221/* Primary revoke support */
222extern int journal_init_revoke(journal_t *, int);
223extern void journal_destroy_revoke_caches(void);
224extern int journal_init_revoke_caches(void);
225
226/* Recovery revoke support */
227extern int journal_set_revoke(journal_t *, unsigned long, tid_t);
228extern int journal_test_revoke(journal_t *, unsigned long, tid_t);
229extern void journal_clear_revoke(journal_t *);
230extern void journal_brelse_array(struct buffer_head *b[], int n);
231
232extern void journal_destroy_revoke(journal_t *);
233
234
235#endif
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/kernel-list.h b/e2fsprogs/old_e2fsprogs/ext2fs/kernel-list.h
deleted file mode 100644
index d80716a45..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/kernel-list.h
+++ /dev/null
@@ -1,113 +0,0 @@
1/* vi: set sw=4 ts=4: */
2#ifndef LINUX_LIST_H
3#define LINUX_LIST_H 1
4
5/*
6 * Simple doubly linked list implementation.
7 *
8 * Some of the internal functions ("__xxx") are useful when
9 * manipulating whole lists rather than single entries, as
10 * sometimes we already know the next/prev entries and we can
11 * generate better code by using them directly rather than
12 * using the generic single-entry routines.
13 */
14
15struct list_head {
16 struct list_head *next, *prev;
17};
18
19#define LIST_HEAD_INIT(name) { &(name), &(name) }
20
21#define LIST_HEAD(name) \
22 struct list_head name = { &name, &name }
23
24#define INIT_LIST_HEAD(ptr) do { \
25 (ptr)->next = (ptr); (ptr)->prev = (ptr); \
26} while (0)
27
28#if (!defined(__GNUC__) && !defined(__WATCOMC__))
29#define __inline__
30#endif
31
32/*
33 * Insert a new entry between two known consecutive entries.
34 *
35 * This is only for internal list manipulation where we know
36 * the prev/next entries already!
37 */
38static __inline__ void __list_add(struct list_head * new,
39 struct list_head * prev,
40 struct list_head * next)
41{
42 next->prev = new;
43 new->next = next;
44 new->prev = prev;
45 prev->next = new;
46}
47
48/*
49 * Insert a new entry after the specified head..
50 */
51static __inline__ void list_add(struct list_head *new, struct list_head *head)
52{
53 __list_add(new, head, head->next);
54}
55
56/*
57 * Insert a new entry at the tail
58 */
59static __inline__ void list_add_tail(struct list_head *new, struct list_head *head)
60{
61 __list_add(new, head->prev, head);
62}
63
64/*
65 * Delete a list entry by making the prev/next entries
66 * point to each other.
67 *
68 * This is only for internal list manipulation where we know
69 * the prev/next entries already!
70 */
71static __inline__ void __list_del(struct list_head * prev,
72 struct list_head * next)
73{
74 next->prev = prev;
75 prev->next = next;
76}
77
78static __inline__ void list_del(struct list_head *entry)
79{
80 __list_del(entry->prev, entry->next);
81}
82
83static __inline__ int list_empty(struct list_head *head)
84{
85 return head->next == head;
86}
87
88/*
89 * Splice in "list" into "head"
90 */
91static __inline__ void list_splice(struct list_head *list, struct list_head *head)
92{
93 struct list_head *first = list->next;
94
95 if (first != list) {
96 struct list_head *last = list->prev;
97 struct list_head *at = head->next;
98
99 first->prev = head;
100 head->next = first;
101
102 last->next = at;
103 at->prev = last;
104 }
105}
106
107#define list_entry(ptr, type, member) \
108 ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
109
110#define list_for_each(pos, head) \
111 for (pos = (head)->next; pos != (head); pos = pos->next)
112
113#endif
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/link.c b/e2fsprogs/old_e2fsprogs/ext2fs/link.c
deleted file mode 100644
index 08b2e9673..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/link.c
+++ /dev/null
@@ -1,135 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * link.c --- create links in a ext2fs directory
4 *
5 * Copyright (C) 1993, 1994 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18
19#include "ext2_fs.h"
20#include "ext2fs.h"
21
22struct link_struct {
23 const char *name;
24 int namelen;
25 ext2_ino_t inode;
26 int flags;
27 int done;
28 struct ext2_super_block *sb;
29};
30
31static int link_proc(struct ext2_dir_entry *dirent,
32 int offset,
33 int blocksize,
34 char *buf,
35 void *priv_data)
36{
37 struct link_struct *ls = (struct link_struct *) priv_data;
38 struct ext2_dir_entry *next;
39 int rec_len, min_rec_len;
40 int ret = 0;
41
42 rec_len = EXT2_DIR_REC_LEN(ls->namelen);
43
44 /*
45 * See if the following directory entry (if any) is unused;
46 * if so, absorb it into this one.
47 */
48 next = (struct ext2_dir_entry *) (buf + offset + dirent->rec_len);
49 if ((offset + dirent->rec_len < blocksize - 8) &&
50 (next->inode == 0) &&
51 (offset + dirent->rec_len + next->rec_len <= blocksize)) {
52 dirent->rec_len += next->rec_len;
53 ret = DIRENT_CHANGED;
54 }
55
56 /*
57 * If the directory entry is used, see if we can split the
58 * directory entry to make room for the new name. If so,
59 * truncate it and return.
60 */
61 if (dirent->inode) {
62 min_rec_len = EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
63 if (dirent->rec_len < (min_rec_len + rec_len))
64 return ret;
65 rec_len = dirent->rec_len - min_rec_len;
66 dirent->rec_len = min_rec_len;
67 next = (struct ext2_dir_entry *) (buf + offset +
68 dirent->rec_len);
69 next->inode = 0;
70 next->name_len = 0;
71 next->rec_len = rec_len;
72 return DIRENT_CHANGED;
73 }
74
75 /*
76 * If we get this far, then the directory entry is not used.
77 * See if we can fit the request entry in. If so, do it.
78 */
79 if (dirent->rec_len < rec_len)
80 return ret;
81 dirent->inode = ls->inode;
82 dirent->name_len = ls->namelen;
83 strncpy(dirent->name, ls->name, ls->namelen);
84 if (ls->sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
85 dirent->name_len |= (ls->flags & 0x7) << 8;
86
87 ls->done++;
88 return DIRENT_ABORT|DIRENT_CHANGED;
89}
90
91/*
92 * Note: the low 3 bits of the flags field are used as the directory
93 * entry filetype.
94 */
95#ifdef __TURBOC__
96# pragma argsused
97#endif
98errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name,
99 ext2_ino_t ino, int flags)
100{
101 errcode_t retval;
102 struct link_struct ls;
103 struct ext2_inode inode;
104
105 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
106
107 if (!(fs->flags & EXT2_FLAG_RW))
108 return EXT2_ET_RO_FILSYS;
109
110 ls.name = name;
111 ls.namelen = name ? strlen(name) : 0;
112 ls.inode = ino;
113 ls.flags = flags;
114 ls.done = 0;
115 ls.sb = fs->super;
116
117 retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY,
118 0, link_proc, &ls);
119 if (retval)
120 return retval;
121
122 if (!ls.done)
123 return EXT2_ET_DIR_NO_SPACE;
124
125 if ((retval = ext2fs_read_inode(fs, dir, &inode)) != 0)
126 return retval;
127
128 if (inode.i_flags & EXT2_INDEX_FL) {
129 inode.i_flags &= ~EXT2_INDEX_FL;
130 if ((retval = ext2fs_write_inode(fs, dir, &inode)) != 0)
131 return retval;
132 }
133
134 return 0;
135}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/lookup.c b/e2fsprogs/old_e2fsprogs/ext2fs/lookup.c
deleted file mode 100644
index b2e8de8ec..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/lookup.c
+++ /dev/null
@@ -1,68 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * lookup.c --- ext2fs directory lookup operations
4 *
5 * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18
19#include "ext2_fs.h"
20#include "ext2fs.h"
21
22struct lookup_struct {
23 const char *name;
24 int len;
25 ext2_ino_t *inode;
26 int found;
27};
28
29#ifdef __TURBOC__
30# pragma argsused
31#endif
32static int lookup_proc(struct ext2_dir_entry *dirent,
33 int offset EXT2FS_ATTR((unused)),
34 int blocksize EXT2FS_ATTR((unused)),
35 char *buf EXT2FS_ATTR((unused)),
36 void *priv_data)
37{
38 struct lookup_struct *ls = (struct lookup_struct *) priv_data;
39
40 if (ls->len != (dirent->name_len & 0xFF))
41 return 0;
42 if (strncmp(ls->name, dirent->name, (dirent->name_len & 0xFF)))
43 return 0;
44 *ls->inode = dirent->inode;
45 ls->found++;
46 return DIRENT_ABORT;
47}
48
49
50errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name,
51 int namelen, char *buf, ext2_ino_t *inode)
52{
53 errcode_t retval;
54 struct lookup_struct ls;
55
56 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
57
58 ls.name = name;
59 ls.len = namelen;
60 ls.inode = inode;
61 ls.found = 0;
62
63 retval = ext2fs_dir_iterate(fs, dir, 0, buf, lookup_proc, &ls);
64 if (retval)
65 return retval;
66
67 return (ls.found) ? 0 : EXT2_ET_FILE_NOT_FOUND;
68}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/mkdir.c b/e2fsprogs/old_e2fsprogs/ext2fs/mkdir.c
deleted file mode 100644
index a86ac8e93..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/mkdir.c
+++ /dev/null
@@ -1,139 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * mkdir.c --- make a directory in the filesystem
4 *
5 * Copyright (C) 1994, 1995 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#include <fcntl.h>
19#include <time.h>
20#if HAVE_SYS_STAT_H
21#include <sys/stat.h>
22#endif
23#if HAVE_SYS_TYPES_H
24#include <sys/types.h>
25#endif
26
27#include "ext2_fs.h"
28#include "ext2fs.h"
29
30#ifndef EXT2_FT_DIR
31#define EXT2_FT_DIR 2
32#endif
33
34errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
35 const char *name)
36{
37 errcode_t retval;
38 struct ext2_inode parent_inode, inode;
39 ext2_ino_t ino = inum;
40 ext2_ino_t scratch_ino;
41 blk_t blk;
42 char *block = NULL;
43
44 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
45
46 /*
47 * Allocate an inode, if necessary
48 */
49 if (!ino) {
50 retval = ext2fs_new_inode(fs, parent, LINUX_S_IFDIR | 0755,
51 0, &ino);
52 if (retval)
53 goto cleanup;
54 }
55
56 /*
57 * Allocate a data block for the directory
58 */
59 retval = ext2fs_new_block(fs, 0, 0, &blk);
60 if (retval)
61 goto cleanup;
62
63 /*
64 * Create a scratch template for the directory
65 */
66 retval = ext2fs_new_dir_block(fs, ino, parent, &block);
67 if (retval)
68 goto cleanup;
69
70 /*
71 * Get the parent's inode, if necessary
72 */
73 if (parent != ino) {
74 retval = ext2fs_read_inode(fs, parent, &parent_inode);
75 if (retval)
76 goto cleanup;
77 } else
78 memset(&parent_inode, 0, sizeof(parent_inode));
79
80 /*
81 * Create the inode structure....
82 */
83 memset(&inode, 0, sizeof(struct ext2_inode));
84 inode.i_mode = LINUX_S_IFDIR | (0777 & ~fs->umask);
85 inode.i_uid = inode.i_gid = 0;
86 inode.i_blocks = fs->blocksize / 512;
87 inode.i_block[0] = blk;
88 inode.i_links_count = 2;
89 inode.i_ctime = inode.i_atime = inode.i_mtime = time(NULL);
90 inode.i_size = fs->blocksize;
91
92 /*
93 * Write out the inode and inode data block
94 */
95 retval = ext2fs_write_dir_block(fs, blk, block);
96 if (retval)
97 goto cleanup;
98 retval = ext2fs_write_new_inode(fs, ino, &inode);
99 if (retval)
100 goto cleanup;
101
102 /*
103 * Link the directory into the filesystem hierarchy
104 */
105 if (name) {
106 retval = ext2fs_lookup(fs, parent, name, strlen(name), 0,
107 &scratch_ino);
108 if (!retval) {
109 retval = EXT2_ET_DIR_EXISTS;
110 name = 0;
111 goto cleanup;
112 }
113 if (retval != EXT2_ET_FILE_NOT_FOUND)
114 goto cleanup;
115 retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_DIR);
116 if (retval)
117 goto cleanup;
118 }
119
120 /*
121 * Update parent inode's counts
122 */
123 if (parent != ino) {
124 parent_inode.i_links_count++;
125 retval = ext2fs_write_inode(fs, parent, &parent_inode);
126 if (retval)
127 goto cleanup;
128 }
129
130 /*
131 * Update accounting....
132 */
133 ext2fs_block_alloc_stats(fs, blk, +1);
134 ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
135
136cleanup:
137 ext2fs_free_mem(&block);
138 return retval;
139}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/mkjournal.c b/e2fsprogs/old_e2fsprogs/ext2fs/mkjournal.c
deleted file mode 100644
index 748d9abc7..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/mkjournal.c
+++ /dev/null
@@ -1,426 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * mkjournal.c --- make a journal for a filesystem
4 *
5 * Copyright (C) 2000 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#if HAVE_ERRNO_H
19#include <errno.h>
20#endif
21#include <fcntl.h>
22#include <time.h>
23#if HAVE_SYS_STAT_H
24#include <sys/stat.h>
25#endif
26#if HAVE_SYS_TYPES_H
27#include <sys/types.h>
28#endif
29#if HAVE_SYS_IOCTL_H
30#include <sys/ioctl.h>
31#endif
32#if HAVE_NETINET_IN_H
33#include <netinet/in.h>
34#endif
35
36#include "ext2_fs.h"
37#include "../e2p/e2p.h"
38#include "../e2fsck.h"
39#include "ext2fs.h"
40#include "kernel-jbd.h"
41
42/*
43 * This function automatically sets up the journal superblock and
44 * returns it as an allocated block.
45 */
46errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
47 __u32 size, int flags,
48 char **ret_jsb)
49{
50 errcode_t retval;
51 journal_superblock_t *jsb;
52
53 if (size < 1024)
54 return EXT2_ET_JOURNAL_TOO_SMALL;
55
56 if ((retval = ext2fs_get_mem(fs->blocksize, &jsb)))
57 return retval;
58
59 memset (jsb, 0, fs->blocksize);
60
61 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
62 if (flags & EXT2_MKJOURNAL_V1_SUPER)
63 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V1);
64 else
65 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
66 jsb->s_blocksize = htonl(fs->blocksize);
67 jsb->s_maxlen = htonl(size);
68 jsb->s_nr_users = htonl(1);
69 jsb->s_first = htonl(1);
70 jsb->s_sequence = htonl(1);
71 memcpy(jsb->s_uuid, fs->super->s_uuid, sizeof(fs->super->s_uuid));
72 /*
73 * If we're creating an external journal device, we need to
74 * adjust these fields.
75 */
76 if (fs->super->s_feature_incompat &
77 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
78 jsb->s_nr_users = 0;
79 if (fs->blocksize == 1024)
80 jsb->s_first = htonl(3);
81 else
82 jsb->s_first = htonl(2);
83 }
84
85 *ret_jsb = (char *) jsb;
86 return 0;
87}
88
89/*
90 * This function writes a journal using POSIX routines. It is used
91 * for creating external journals and creating journals on live
92 * filesystems.
93 */
94static errcode_t write_journal_file(ext2_filsys fs, char *filename,
95 blk_t size, int flags)
96{
97 errcode_t retval;
98 char *buf = NULL;
99 int fd, ret_size;
100 blk_t i;
101
102 if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf)))
103 return retval;
104
105 /* Open the device or journal file */
106 if ((fd = open(filename, O_WRONLY)) < 0) {
107 retval = errno;
108 goto errout;
109 }
110
111 /* Write the superblock out */
112 retval = EXT2_ET_SHORT_WRITE;
113 ret_size = write(fd, buf, fs->blocksize);
114 if (ret_size < 0) {
115 retval = errno;
116 goto errout;
117 }
118 if (ret_size != (int) fs->blocksize)
119 goto errout;
120 memset(buf, 0, fs->blocksize);
121
122 for (i = 1; i < size; i++) {
123 ret_size = write(fd, buf, fs->blocksize);
124 if (ret_size < 0) {
125 retval = errno;
126 goto errout;
127 }
128 if (ret_size != (int) fs->blocksize)
129 goto errout;
130 }
131 close(fd);
132
133 retval = 0;
134errout:
135 ext2fs_free_mem(&buf);
136 return retval;
137}
138
139/*
140 * Helper function for creating the journal using direct I/O routines
141 */
142struct mkjournal_struct {
143 int num_blocks;
144 int newblocks;
145 char *buf;
146 errcode_t err;
147};
148
149static int mkjournal_proc(ext2_filsys fs,
150 blk_t *blocknr,
151 e2_blkcnt_t blockcnt,
152 blk_t ref_block EXT2FS_ATTR((unused)),
153 int ref_offset EXT2FS_ATTR((unused)),
154 void *priv_data)
155{
156 struct mkjournal_struct *es = (struct mkjournal_struct *) priv_data;
157 blk_t new_blk;
158 static blk_t last_blk = 0;
159 errcode_t retval;
160
161 if (*blocknr) {
162 last_blk = *blocknr;
163 return 0;
164 }
165 retval = ext2fs_new_block(fs, last_blk, 0, &new_blk);
166 if (retval) {
167 es->err = retval;
168 return BLOCK_ABORT;
169 }
170 if (blockcnt > 0)
171 es->num_blocks--;
172
173 es->newblocks++;
174 retval = io_channel_write_blk(fs->io, new_blk, 1, es->buf);
175
176 if (blockcnt == 0)
177 memset(es->buf, 0, fs->blocksize);
178
179 if (retval) {
180 es->err = retval;
181 return BLOCK_ABORT;
182 }
183 *blocknr = new_blk;
184 last_blk = new_blk;
185 ext2fs_block_alloc_stats(fs, new_blk, +1);
186
187 if (es->num_blocks == 0)
188 return (BLOCK_CHANGED | BLOCK_ABORT);
189 else
190 return BLOCK_CHANGED;
191}
192
193/*
194 * This function creates a journal using direct I/O routines.
195 */
196static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
197 blk_t size, int flags)
198{
199 char *buf;
200 errcode_t retval;
201 struct ext2_inode inode;
202 struct mkjournal_struct es;
203
204 if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf)))
205 return retval;
206
207 if ((retval = ext2fs_read_bitmaps(fs)))
208 return retval;
209
210 if ((retval = ext2fs_read_inode(fs, journal_ino, &inode)))
211 return retval;
212
213 if (inode.i_blocks > 0)
214 return EEXIST;
215
216 es.num_blocks = size;
217 es.newblocks = 0;
218 es.buf = buf;
219 es.err = 0;
220
221 retval = ext2fs_block_iterate2(fs, journal_ino, BLOCK_FLAG_APPEND,
222 0, mkjournal_proc, &es);
223 if (es.err) {
224 retval = es.err;
225 goto errout;
226 }
227
228 if ((retval = ext2fs_read_inode(fs, journal_ino, &inode)))
229 goto errout;
230
231 inode.i_size += fs->blocksize * size;
232 inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
233 inode.i_mtime = inode.i_ctime = time(NULL);
234 inode.i_links_count = 1;
235 inode.i_mode = LINUX_S_IFREG | 0600;
236
237 if ((retval = ext2fs_write_inode(fs, journal_ino, &inode)))
238 goto errout;
239 retval = 0;
240
241 memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4);
242 fs->super->s_jnl_blocks[16] = inode.i_size;
243 fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
244 ext2fs_mark_super_dirty(fs);
245
246errout:
247 ext2fs_free_mem(&buf);
248 return retval;
249}
250
251/*
252 * This function adds a journal device to a filesystem
253 */
254errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev)
255{
256 struct stat st;
257 errcode_t retval;
258 char buf[1024];
259 journal_superblock_t *jsb;
260 int start;
261 __u32 i, nr_users;
262
263 /* Make sure the device exists and is a block device */
264 if (stat(journal_dev->device_name, &st) < 0)
265 return errno;
266
267 if (!S_ISBLK(st.st_mode))
268 return EXT2_ET_JOURNAL_NOT_BLOCK; /* Must be a block device */
269
270 /* Get the journal superblock */
271 start = 1;
272 if (journal_dev->blocksize == 1024)
273 start++;
274 if ((retval = io_channel_read_blk(journal_dev->io, start, -1024, buf)))
275 return retval;
276
277 jsb = (journal_superblock_t *) buf;
278 if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) ||
279 (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2)))
280 return EXT2_ET_NO_JOURNAL_SB;
281
282 if (ntohl(jsb->s_blocksize) != (unsigned long) fs->blocksize)
283 return EXT2_ET_UNEXPECTED_BLOCK_SIZE;
284
285 /* Check and see if this filesystem has already been added */
286 nr_users = ntohl(jsb->s_nr_users);
287 for (i=0; i < nr_users; i++) {
288 if (memcmp(fs->super->s_uuid,
289 &jsb->s_users[i*16], 16) == 0)
290 break;
291 }
292 if (i >= nr_users) {
293 memcpy(&jsb->s_users[nr_users*16],
294 fs->super->s_uuid, 16);
295 jsb->s_nr_users = htonl(nr_users+1);
296 }
297
298 /* Writeback the journal superblock */
299 if ((retval = io_channel_write_blk(journal_dev->io, start, -1024, buf)))
300 return retval;
301
302 fs->super->s_journal_inum = 0;
303 fs->super->s_journal_dev = st.st_rdev;
304 memcpy(fs->super->s_journal_uuid, jsb->s_uuid,
305 sizeof(fs->super->s_journal_uuid));
306 fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
307 ext2fs_mark_super_dirty(fs);
308 return 0;
309}
310
311/*
312 * This function adds a journal inode to a filesystem, using either
313 * POSIX routines if the filesystem is mounted, or using direct I/O
314 * functions if it is not.
315 */
316errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size, int flags)
317{
318 errcode_t retval;
319 ext2_ino_t journal_ino;
320 struct stat st;
321 char jfile[1024];
322 int fd, mount_flags, f;
323
324 retval = ext2fs_check_mount_point(fs->device_name, &mount_flags,
325 jfile, sizeof(jfile)-10);
326 if (retval)
327 return retval;
328
329 if (mount_flags & EXT2_MF_MOUNTED) {
330 strcat(jfile, "/.journal");
331
332 /*
333 * If .../.journal already exists, make sure any
334 * immutable or append-only flags are cleared.
335 */
336#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP)
337 (void) chflags (jfile, 0);
338#else
339#if HAVE_EXT2_IOCTLS
340 fd = open(jfile, O_RDONLY);
341 if (fd >= 0) {
342 f = 0;
343 ioctl(fd, EXT2_IOC_SETFLAGS, &f);
344 close(fd);
345 }
346#endif
347#endif
348
349 /* Create the journal file */
350 if ((fd = open(jfile, O_CREAT|O_WRONLY, 0600)) < 0)
351 return errno;
352
353 if ((retval = write_journal_file(fs, jfile, size, flags)))
354 goto errout;
355
356 /* Get inode number of the journal file */
357 if (fstat(fd, &st) < 0)
358 goto errout;
359
360#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP)
361 retval = fchflags (fd, UF_NODUMP|UF_IMMUTABLE);
362#else
363#if HAVE_EXT2_IOCTLS
364 f = EXT2_NODUMP_FL | EXT2_IMMUTABLE_FL;
365 retval = ioctl(fd, EXT2_IOC_SETFLAGS, &f);
366#endif
367#endif
368 if (retval)
369 goto errout;
370
371 close(fd);
372 journal_ino = st.st_ino;
373 } else {
374 journal_ino = EXT2_JOURNAL_INO;
375 if ((retval = write_journal_inode(fs, journal_ino,
376 size, flags)))
377 return retval;
378 }
379
380 fs->super->s_journal_inum = journal_ino;
381 fs->super->s_journal_dev = 0;
382 memset(fs->super->s_journal_uuid, 0,
383 sizeof(fs->super->s_journal_uuid));
384 fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
385
386 ext2fs_mark_super_dirty(fs);
387 return 0;
388errout:
389 close(fd);
390 return retval;
391}
392
393#ifdef DEBUG
394main(int argc, char **argv)
395{
396 errcode_t retval;
397 char *device_name;
398 ext2_filsys fs;
399
400 if (argc < 2) {
401 fprintf(stderr, "Usage: %s filesystem\n", argv[0]);
402 exit(1);
403 }
404 device_name = argv[1];
405
406 retval = ext2fs_open (device_name, EXT2_FLAG_RW, 0, 0,
407 unix_io_manager, &fs);
408 if (retval) {
409 com_err(argv[0], retval, "while opening %s", device_name);
410 exit(1);
411 }
412
413 retval = ext2fs_add_journal_inode(fs, 1024);
414 if (retval) {
415 com_err(argv[0], retval, "while adding journal to %s",
416 device_name);
417 exit(1);
418 }
419 retval = ext2fs_flush(fs);
420 if (retval) {
421 printf("Warning, had trouble writing out superblocks.\n");
422 }
423 ext2fs_close(fs);
424 exit(0);
425}
426#endif
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/namei.c b/e2fsprogs/old_e2fsprogs/ext2fs/namei.c
deleted file mode 100644
index 18244613c..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/namei.c
+++ /dev/null
@@ -1,204 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * namei.c --- ext2fs directory lookup operations
4 *
5 * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18
19/* #define NAMEI_DEBUG */
20
21#include "ext2_fs.h"
22#include "ext2fs.h"
23
24static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base,
25 const char *pathname, size_t pathlen, int follow,
26 int link_count, char *buf, ext2_ino_t *res_inode);
27
28static errcode_t follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir,
29 ext2_ino_t inode, int link_count,
30 char *buf, ext2_ino_t *res_inode)
31{
32 char *pathname;
33 char *buffer = NULL;
34 errcode_t retval;
35 struct ext2_inode ei;
36
37#ifdef NAMEI_DEBUG
38 printf("follow_link: root=%lu, dir=%lu, inode=%lu, lc=%d\n",
39 root, dir, inode, link_count);
40
41#endif
42 retval = ext2fs_read_inode (fs, inode, &ei);
43 if (retval) return retval;
44 if (!LINUX_S_ISLNK (ei.i_mode)) {
45 *res_inode = inode;
46 return 0;
47 }
48 if (link_count++ > 5) {
49 return EXT2_ET_SYMLINK_LOOP;
50 }
51 if (ext2fs_inode_data_blocks(fs, &ei)) {
52 retval = ext2fs_get_mem(fs->blocksize, &buffer);
53 if (retval)
54 return retval;
55 retval = io_channel_read_blk(fs->io, ei.i_block[0], 1, buffer);
56 if (retval) {
57 ext2fs_free_mem(&buffer);
58 return retval;
59 }
60 pathname = buffer;
61 } else
62 pathname = (char *)&(ei.i_block[0]);
63 retval = open_namei(fs, root, dir, pathname, ei.i_size, 1,
64 link_count, buf, res_inode);
65 ext2fs_free_mem(&buffer);
66 return retval;
67}
68
69/*
70 * This routine interprets a pathname in the context of the current
71 * directory and the root directory, and returns the inode of the
72 * containing directory, and a pointer to the filename of the file
73 * (pointing into the pathname) and the length of the filename.
74 */
75static errcode_t dir_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir,
76 const char *pathname, int pathlen,
77 int link_count, char *buf,
78 const char **name, int *namelen,
79 ext2_ino_t *res_inode)
80{
81 char c;
82 const char *thisname;
83 int len;
84 ext2_ino_t inode;
85 errcode_t retval;
86
87 if ((c = *pathname) == '/') {
88 dir = root;
89 pathname++;
90 pathlen--;
91 }
92 while (1) {
93 thisname = pathname;
94 for (len=0; --pathlen >= 0;len++) {
95 c = *(pathname++);
96 if (c == '/')
97 break;
98 }
99 if (pathlen < 0)
100 break;
101 retval = ext2fs_lookup (fs, dir, thisname, len, buf, &inode);
102 if (retval) return retval;
103 retval = follow_link (fs, root, dir, inode,
104 link_count, buf, &dir);
105 if (retval) return retval;
106 }
107 *name = thisname;
108 *namelen = len;
109 *res_inode = dir;
110 return 0;
111}
112
113static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base,
114 const char *pathname, size_t pathlen, int follow,
115 int link_count, char *buf, ext2_ino_t *res_inode)
116{
117 const char *basename;
118 int namelen;
119 ext2_ino_t dir, inode;
120 errcode_t retval;
121
122#ifdef NAMEI_DEBUG
123 printf("open_namei: root=%lu, dir=%lu, path=%*s, lc=%d\n",
124 root, base, pathlen, pathname, link_count);
125#endif
126 retval = dir_namei(fs, root, base, pathname, pathlen,
127 link_count, buf, &basename, &namelen, &dir);
128 if (retval) return retval;
129 if (!namelen) { /* special case: '/usr/' etc */
130 *res_inode=dir;
131 return 0;
132 }
133 retval = ext2fs_lookup (fs, dir, basename, namelen, buf, &inode);
134 if (retval)
135 return retval;
136 if (follow) {
137 retval = follow_link(fs, root, dir, inode, link_count,
138 buf, &inode);
139 if (retval)
140 return retval;
141 }
142#ifdef NAMEI_DEBUG
143 printf("open_namei: (link_count=%d) returns %lu\n",
144 link_count, inode);
145#endif
146 *res_inode = inode;
147 return 0;
148}
149
150errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
151 const char *name, ext2_ino_t *inode)
152{
153 char *buf;
154 errcode_t retval;
155
156 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
157
158 retval = ext2fs_get_mem(fs->blocksize, &buf);
159 if (retval)
160 return retval;
161
162 retval = open_namei(fs, root, cwd, name, strlen(name), 0, 0,
163 buf, inode);
164
165 ext2fs_free_mem(&buf);
166 return retval;
167}
168
169errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
170 const char *name, ext2_ino_t *inode)
171{
172 char *buf;
173 errcode_t retval;
174
175 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
176
177 retval = ext2fs_get_mem(fs->blocksize, &buf);
178 if (retval)
179 return retval;
180
181 retval = open_namei(fs, root, cwd, name, strlen(name), 1, 0,
182 buf, inode);
183
184 ext2fs_free_mem(&buf);
185 return retval;
186}
187
188errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
189 ext2_ino_t inode, ext2_ino_t *res_inode)
190{
191 char *buf;
192 errcode_t retval;
193
194 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
195
196 retval = ext2fs_get_mem(fs->blocksize, &buf);
197 if (retval)
198 return retval;
199
200 retval = follow_link(fs, root, cwd, inode, 0, buf, res_inode);
201
202 ext2fs_free_mem(&buf);
203 return retval;
204}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/newdir.c b/e2fsprogs/old_e2fsprogs/ext2fs/newdir.c
deleted file mode 100644
index 9f156626d..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/newdir.c
+++ /dev/null
@@ -1,72 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * newdir.c --- create a new directory block
4 *
5 * Copyright (C) 1994, 1995 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18
19#include "ext2_fs.h"
20#include "ext2fs.h"
21
22#ifndef EXT2_FT_DIR
23#define EXT2_FT_DIR 2
24#endif
25
26/*
27 * Create new directory block
28 */
29errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino,
30 ext2_ino_t parent_ino, char **block)
31{
32 struct ext2_dir_entry *dir = NULL;
33 errcode_t retval;
34 char *buf;
35 int rec_len;
36 int filetype = 0;
37
38 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
39
40 retval = ext2fs_get_mem(fs->blocksize, &buf);
41 if (retval)
42 return retval;
43 memset(buf, 0, fs->blocksize);
44 dir = (struct ext2_dir_entry *) buf;
45 dir->rec_len = fs->blocksize;
46
47 if (dir_ino) {
48 if (fs->super->s_feature_incompat &
49 EXT2_FEATURE_INCOMPAT_FILETYPE)
50 filetype = EXT2_FT_DIR << 8;
51 /*
52 * Set up entry for '.'
53 */
54 dir->inode = dir_ino;
55 dir->name_len = 1 | filetype;
56 dir->name[0] = '.';
57 rec_len = dir->rec_len - EXT2_DIR_REC_LEN(1);
58 dir->rec_len = EXT2_DIR_REC_LEN(1);
59
60 /*
61 * Set up entry for '..'
62 */
63 dir = (struct ext2_dir_entry *) (buf + dir->rec_len);
64 dir->rec_len = rec_len;
65 dir->inode = parent_ino;
66 dir->name_len = 2 | filetype;
67 dir->name[0] = '.';
68 dir->name[1] = '.';
69 }
70 *block = buf;
71 return 0;
72}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/openfs.c b/e2fsprogs/old_e2fsprogs/ext2fs/openfs.c
deleted file mode 100644
index 1b271196b..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/openfs.c
+++ /dev/null
@@ -1,330 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * openfs.c --- open an ext2 filesystem
4 *
5 * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#include <fcntl.h>
19#include <time.h>
20#if HAVE_SYS_STAT_H
21#include <sys/stat.h>
22#endif
23#if HAVE_SYS_TYPES_H
24#include <sys/types.h>
25#endif
26
27#include "ext2_fs.h"
28
29
30#include "ext2fs.h"
31#include "e2image.h"
32
33blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, dgrp_t i)
34{
35 int bg;
36 int has_super = 0;
37 int ret_blk;
38
39 if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
40 (i < fs->super->s_first_meta_bg))
41 return (group_block + i + 1);
42
43 bg = (fs->blocksize / sizeof (struct ext2_group_desc)) * i;
44 if (ext2fs_bg_has_super(fs, bg))
45 has_super = 1;
46 ret_blk = (fs->super->s_first_data_block + has_super +
47 (bg * fs->super->s_blocks_per_group));
48 /*
49 * If group_block is not the normal value, we're trying to use
50 * the backup group descriptors and superblock --- so use the
51 * alternate location of the second block group in the
52 * metablock group. Ideally we should be testing each bg
53 * descriptor block individually for correctness, but we don't
54 * have the infrastructure in place to do that.
55 */
56 if (group_block != fs->super->s_first_data_block &&
57 ((ret_blk + fs->super->s_blocks_per_group) <
58 fs->super->s_blocks_count))
59 ret_blk += fs->super->s_blocks_per_group;
60 return ret_blk;
61}
62
63errcode_t ext2fs_open(const char *name, int flags, int superblock,
64 unsigned int block_size, io_manager manager,
65 ext2_filsys *ret_fs)
66{
67 return ext2fs_open2(name, 0, flags, superblock, block_size,
68 manager, ret_fs);
69}
70
71/*
72 * Note: if superblock is non-zero, block-size must also be non-zero.
73 * Superblock and block_size can be zero to use the default size.
74 *
75 * Valid flags for ext2fs_open()
76 *
77 * EXT2_FLAG_RW - Open the filesystem for read/write.
78 * EXT2_FLAG_FORCE - Open the filesystem even if some of the
79 * features aren't supported.
80 * EXT2_FLAG_JOURNAL_DEV_OK - Open an ext3 journal device
81 */
82errcode_t ext2fs_open2(const char *name, const char *io_options,
83 int flags, int superblock,
84 unsigned int block_size, io_manager manager,
85 ext2_filsys *ret_fs)
86{
87 ext2_filsys fs;
88 errcode_t retval;
89 unsigned long i;
90 int groups_per_block, blocks_per_group;
91 blk_t group_block, blk;
92 char *dest, *cp;
93#if BB_BIG_ENDIAN
94 int j;
95 struct ext2_group_desc *gdp;
96#endif
97
98 EXT2_CHECK_MAGIC(manager, EXT2_ET_MAGIC_IO_MANAGER);
99
100 retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
101 if (retval)
102 return retval;
103
104 memset(fs, 0, sizeof(struct struct_ext2_filsys));
105 fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS;
106 fs->flags = flags;
107 fs->umask = 022;
108 retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name);
109 if (retval)
110 goto cleanup;
111 strcpy(fs->device_name, name);
112 cp = strchr(fs->device_name, '?');
113 if (!io_options && cp) {
114 *cp++ = 0;
115 io_options = cp;
116 }
117
118 retval = manager->open(fs->device_name,
119 (flags & EXT2_FLAG_RW) ? IO_FLAG_RW : 0,
120 &fs->io);
121 if (retval)
122 goto cleanup;
123 if (io_options &&
124 (retval = io_channel_set_options(fs->io, io_options)))
125 goto cleanup;
126 fs->image_io = fs->io;
127 fs->io->app_data = fs;
128 retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->super);
129 if (retval)
130 goto cleanup;
131 if (flags & EXT2_FLAG_IMAGE_FILE) {
132 retval = ext2fs_get_mem(sizeof(struct ext2_image_hdr),
133 &fs->image_header);
134 if (retval)
135 goto cleanup;
136 retval = io_channel_read_blk(fs->io, 0,
137 -(int)sizeof(struct ext2_image_hdr),
138 fs->image_header);
139 if (retval)
140 goto cleanup;
141 if (fs->image_header->magic_number != EXT2_ET_MAGIC_E2IMAGE)
142 return EXT2_ET_MAGIC_E2IMAGE;
143 superblock = 1;
144 block_size = fs->image_header->fs_blocksize;
145 }
146
147 /*
148 * If the user specifies a specific block # for the
149 * superblock, then he/she must also specify the block size!
150 * Otherwise, read the master superblock located at offset
151 * SUPERBLOCK_OFFSET from the start of the partition.
152 *
153 * Note: we only save a backup copy of the superblock if we
154 * are reading the superblock from the primary superblock location.
155 */
156 if (superblock) {
157 if (!block_size) {
158 retval = EXT2_ET_INVALID_ARGUMENT;
159 goto cleanup;
160 }
161 io_channel_set_blksize(fs->io, block_size);
162 group_block = superblock;
163 fs->orig_super = 0;
164 } else {
165 io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET);
166 superblock = 1;
167 group_block = 0;
168 retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super);
169 if (retval)
170 goto cleanup;
171 }
172 retval = io_channel_read_blk(fs->io, superblock, -SUPERBLOCK_SIZE,
173 fs->super);
174 if (retval)
175 goto cleanup;
176 if (fs->orig_super)
177 memcpy(fs->orig_super, fs->super, SUPERBLOCK_SIZE);
178
179#if BB_BIG_ENDIAN
180 if ((fs->super->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC)) ||
181 (fs->flags & EXT2_FLAG_SWAP_BYTES)) {
182 fs->flags |= EXT2_FLAG_SWAP_BYTES;
183
184 ext2fs_swap_super(fs->super);
185 }
186#endif
187
188 if (fs->super->s_magic != EXT2_SUPER_MAGIC) {
189 retval = EXT2_ET_BAD_MAGIC;
190 goto cleanup;
191 }
192 if (fs->super->s_rev_level > EXT2_LIB_CURRENT_REV) {
193 retval = EXT2_ET_REV_TOO_HIGH;
194 goto cleanup;
195 }
196
197 /*
198 * Check for feature set incompatibility
199 */
200 if (!(flags & EXT2_FLAG_FORCE)) {
201 if (fs->super->s_feature_incompat &
202 ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) {
203 retval = EXT2_ET_UNSUPP_FEATURE;
204 goto cleanup;
205 }
206 if ((flags & EXT2_FLAG_RW) &&
207 (fs->super->s_feature_ro_compat &
208 ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP)) {
209 retval = EXT2_ET_RO_UNSUPP_FEATURE;
210 goto cleanup;
211 }
212 if (!(flags & EXT2_FLAG_JOURNAL_DEV_OK) &&
213 (fs->super->s_feature_incompat &
214 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
215 retval = EXT2_ET_UNSUPP_FEATURE;
216 goto cleanup;
217 }
218 }
219
220 fs->blocksize = EXT2_BLOCK_SIZE(fs->super);
221 if (fs->blocksize == 0) {
222 retval = EXT2_ET_CORRUPT_SUPERBLOCK;
223 goto cleanup;
224 }
225 fs->fragsize = EXT2_FRAG_SIZE(fs->super);
226 fs->inode_blocks_per_group = ((fs->super->s_inodes_per_group *
227 EXT2_INODE_SIZE(fs->super) +
228 EXT2_BLOCK_SIZE(fs->super) - 1) /
229 EXT2_BLOCK_SIZE(fs->super));
230 if (block_size) {
231 if (block_size != fs->blocksize) {
232 retval = EXT2_ET_UNEXPECTED_BLOCK_SIZE;
233 goto cleanup;
234 }
235 }
236 /*
237 * Set the blocksize to the filesystem's blocksize.
238 */
239 io_channel_set_blksize(fs->io, fs->blocksize);
240
241 /*
242 * If this is an external journal device, don't try to read
243 * the group descriptors, because they're not there.
244 */
245 if (fs->super->s_feature_incompat &
246 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
247 fs->group_desc_count = 0;
248 *ret_fs = fs;
249 return 0;
250 }
251
252 /*
253 * Read group descriptors
254 */
255 blocks_per_group = EXT2_BLOCKS_PER_GROUP(fs->super);
256 if (blocks_per_group == 0 ||
257 blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(fs->super) ||
258 fs->inode_blocks_per_group > EXT2_MAX_INODES_PER_GROUP(fs->super)) {
259 retval = EXT2_ET_CORRUPT_SUPERBLOCK;
260 goto cleanup;
261 }
262 fs->group_desc_count = (fs->super->s_blocks_count -
263 fs->super->s_first_data_block +
264 blocks_per_group - 1) / blocks_per_group;
265 fs->desc_blocks = (fs->group_desc_count +
266 EXT2_DESC_PER_BLOCK(fs->super) - 1)
267 / EXT2_DESC_PER_BLOCK(fs->super);
268 retval = ext2fs_get_mem(fs->desc_blocks * fs->blocksize,
269 &fs->group_desc);
270 if (retval)
271 goto cleanup;
272 if (!group_block)
273 group_block = fs->super->s_first_data_block;
274 dest = (char *) fs->group_desc;
275 groups_per_block = fs->blocksize / sizeof(struct ext2_group_desc);
276 for (i = 0; i < fs->desc_blocks; i++) {
277 blk = ext2fs_descriptor_block_loc(fs, group_block, i);
278 retval = io_channel_read_blk(fs->io, blk, 1, dest);
279 if (retval)
280 goto cleanup;
281#if BB_BIG_ENDIAN
282 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
283 gdp = (struct ext2_group_desc *) dest;
284 for (j=0; j < groups_per_block; j++)
285 ext2fs_swap_group_desc(gdp++);
286 }
287#endif
288 dest += fs->blocksize;
289 }
290
291 *ret_fs = fs;
292 return 0;
293cleanup:
294 ext2fs_free(fs);
295 return retval;
296}
297
298/*
299 * Set/get the filesystem data I/O channel.
300 *
301 * These functions are only valid if EXT2_FLAG_IMAGE_FILE is true.
302 */
303errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io)
304{
305 if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0)
306 return EXT2_ET_NOT_IMAGE_FILE;
307 if (old_io) {
308 *old_io = (fs->image_io == fs->io) ? 0 : fs->io;
309 }
310 return 0;
311}
312
313errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io)
314{
315 if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0)
316 return EXT2_ET_NOT_IMAGE_FILE;
317 fs->io = new_io ? new_io : fs->image_io;
318 return 0;
319}
320
321errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io)
322{
323 if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0)
324 return EXT2_ET_NOT_IMAGE_FILE;
325 fs->io = fs->image_io = new_io;
326 fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_RW |
327 EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
328 fs->flags &= ~EXT2_FLAG_IMAGE_FILE;
329 return 0;
330}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/read_bb.c b/e2fsprogs/old_e2fsprogs/ext2fs/read_bb.c
deleted file mode 100644
index ce77bc9f6..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/read_bb.c
+++ /dev/null
@@ -1,96 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * read_bb --- read the bad blocks inode
4 *
5 * Copyright (C) 1994 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#include <fcntl.h>
19#include <time.h>
20#if HAVE_SYS_STAT_H
21#include <sys/stat.h>
22#endif
23#if HAVE_SYS_TYPES_H
24#include <sys/types.h>
25#endif
26
27#include "ext2_fs.h"
28#include "ext2fs.h"
29
30struct read_bb_record {
31 ext2_badblocks_list bb_list;
32 errcode_t err;
33};
34
35/*
36 * Helper function for ext2fs_read_bb_inode()
37 */
38#ifdef __TURBOC__
39# pragma argsused
40#endif
41static int mark_bad_block(ext2_filsys fs, blk_t *block_nr,
42 e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
43 blk_t ref_block EXT2FS_ATTR((unused)),
44 int ref_offset EXT2FS_ATTR((unused)),
45 void *priv_data)
46{
47 struct read_bb_record *rb = (struct read_bb_record *) priv_data;
48
49 if (blockcnt < 0)
50 return 0;
51
52 if ((*block_nr < fs->super->s_first_data_block) ||
53 (*block_nr >= fs->super->s_blocks_count))
54 return 0; /* Ignore illegal blocks */
55
56 rb->err = ext2fs_badblocks_list_add(rb->bb_list, *block_nr);
57 if (rb->err)
58 return BLOCK_ABORT;
59 return 0;
60}
61
62/*
63 * Reads the current bad blocks from the bad blocks inode.
64 */
65errcode_t ext2fs_read_bb_inode(ext2_filsys fs, ext2_badblocks_list *bb_list)
66{
67 errcode_t retval;
68 struct read_bb_record rb;
69 struct ext2_inode inode;
70 blk_t numblocks;
71
72 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
73
74 if (!*bb_list) {
75 retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode);
76 if (retval)
77 return retval;
78 if (inode.i_blocks < 500)
79 numblocks = (inode.i_blocks /
80 (fs->blocksize / 512)) + 20;
81 else
82 numblocks = 500;
83 retval = ext2fs_badblocks_list_create(bb_list, numblocks);
84 if (retval)
85 return retval;
86 }
87
88 rb.bb_list = *bb_list;
89 rb.err = 0;
90 retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, 0, 0,
91 mark_bad_block, &rb);
92 if (retval)
93 return retval;
94
95 return rb.err;
96}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/read_bb_file.c b/e2fsprogs/old_e2fsprogs/ext2fs/read_bb_file.c
deleted file mode 100644
index bf1fc328b..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/read_bb_file.c
+++ /dev/null
@@ -1,96 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * read_bb_file.c --- read a list of bad blocks from a FILE *
4 *
5 * Copyright (C) 1994, 1995, 2000 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#include <fcntl.h>
19#include <time.h>
20#if HAVE_SYS_STAT_H
21#include <sys/stat.h>
22#endif
23#if HAVE_SYS_TYPES_H
24#include <sys/types.h>
25#endif
26
27#include "ext2_fs.h"
28#include "ext2fs.h"
29
30/*
31 * Reads a list of bad blocks from a FILE *
32 */
33errcode_t ext2fs_read_bb_FILE2(ext2_filsys fs, FILE *f,
34 ext2_badblocks_list *bb_list,
35 void *priv_data,
36 void (*invalid)(ext2_filsys fs,
37 blk_t blk,
38 char *badstr,
39 void *priv_data))
40{
41 errcode_t retval;
42 blk_t blockno;
43 int count;
44 char buf[128];
45
46 if (fs)
47 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
48
49 if (!*bb_list) {
50 retval = ext2fs_badblocks_list_create(bb_list, 10);
51 if (retval)
52 return retval;
53 }
54
55 while (!feof (f)) {
56 if (fgets(buf, sizeof(buf), f) == NULL)
57 break;
58 count = sscanf(buf, "%u", &blockno);
59 if (count <= 0)
60 continue;
61 if (fs &&
62 ((blockno < fs->super->s_first_data_block) ||
63 (blockno >= fs->super->s_blocks_count))) {
64 if (invalid)
65 (invalid)(fs, blockno, buf, priv_data);
66 continue;
67 }
68 retval = ext2fs_badblocks_list_add(*bb_list, blockno);
69 if (retval)
70 return retval;
71 }
72 return 0;
73}
74
75static void call_compat_invalid(ext2_filsys fs, blk_t blk,
76 char *badstr EXT2FS_ATTR((unused)),
77 void *priv_data)
78{
79 void (*invalid)(ext2_filsys, blk_t);
80
81 invalid = (void (*)(ext2_filsys, blk_t)) priv_data;
82 if (invalid)
83 invalid(fs, blk);
84}
85
86
87/*
88 * Reads a list of bad blocks from a FILE *
89 */
90errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f,
91 ext2_badblocks_list *bb_list,
92 void (*invalid)(ext2_filsys fs, blk_t blk))
93{
94 return ext2fs_read_bb_FILE2(fs, f, bb_list, (void *) invalid,
95 call_compat_invalid);
96}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/res_gdt.c b/e2fsprogs/old_e2fsprogs/ext2fs/res_gdt.c
deleted file mode 100644
index 403463a90..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/res_gdt.c
+++ /dev/null
@@ -1,220 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * res_gdt.c --- reserve blocks for growing the group descriptor table
4 * during online resizing.
5 *
6 * Copyright (C) 2002 Andreas Dilger
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the GNU Public
10 * License.
11 * %End-Header%
12 */
13
14#include <stdio.h>
15#include <string.h>
16#include <time.h>
17#include "ext2_fs.h"
18#include "ext2fs.h"
19
20/*
21 * Iterate through the groups which hold BACKUP superblock/GDT copies in an
22 * ext3 filesystem. The counters should be initialized to 1, 5, and 7 before
23 * calling this for the first time. In a sparse filesystem it will be the
24 * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ...
25 * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ...
26 */
27static unsigned int list_backups(ext2_filsys fs, unsigned int *three,
28 unsigned int *five, unsigned int *seven)
29{
30 unsigned int *min = three;
31 int mult = 3;
32 unsigned int ret;
33
34 if (!(fs->super->s_feature_ro_compat &
35 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
36 ret = *min;
37 *min += 1;
38 return ret;
39 }
40
41 if (*five < *min) {
42 min = five;
43 mult = 5;
44 }
45 if (*seven < *min) {
46 min = seven;
47 mult = 7;
48 }
49
50 ret = *min;
51 *min *= mult;
52
53 return ret;
54}
55
56/*
57 * This code assumes that the reserved blocks have already been marked in-use
58 * during ext2fs_initialize(), so that they are not allocated for other
59 * uses before we can add them to the resize inode (which has to come
60 * after the creation of the inode table).
61 */
62errcode_t ext2fs_create_resize_inode(ext2_filsys fs)
63{
64 errcode_t retval, retval2;
65 struct ext2_super_block *sb;
66 struct ext2_inode inode;
67 __u32 *dindir_buf, *gdt_buf;
68 int rsv_add;
69 unsigned long long apb, inode_size;
70 blk_t dindir_blk, rsv_off, gdt_off, gdt_blk;
71 int dindir_dirty = 0, inode_dirty = 0;
72
73 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
74
75 sb = fs->super;
76
77 retval = ext2fs_get_mem(2 * fs->blocksize, (void *)&dindir_buf);
78 if (retval)
79 goto out_free;
80 gdt_buf = (__u32 *)((char *)dindir_buf + fs->blocksize);
81
82 retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
83 if (retval)
84 goto out_free;
85
86 /* Maximum possible file size (we donly use the dindirect blocks) */
87 apb = EXT2_ADDR_PER_BLOCK(sb);
88 rsv_add = fs->blocksize / 512;
89 if ((dindir_blk = inode.i_block[EXT2_DIND_BLOCK])) {
90#ifdef RES_GDT_DEBUG
91 printf("reading GDT dindir %u\n", dindir_blk);
92#endif
93 retval = ext2fs_read_ind_block(fs, dindir_blk, dindir_buf);
94 if (retval)
95 goto out_inode;
96 } else {
97 blk_t goal = 3 + sb->s_reserved_gdt_blocks +
98 fs->desc_blocks + fs->inode_blocks_per_group;
99
100 retval = ext2fs_alloc_block(fs, goal, 0, &dindir_blk);
101 if (retval)
102 goto out_free;
103 inode.i_mode = LINUX_S_IFREG | 0600;
104 inode.i_links_count = 1;
105 inode.i_block[EXT2_DIND_BLOCK] = dindir_blk;
106 inode.i_blocks = rsv_add;
107 memset(dindir_buf, 0, fs->blocksize);
108#ifdef RES_GDT_DEBUG
109 printf("allocated GDT dindir %u\n", dindir_blk);
110#endif
111 dindir_dirty = inode_dirty = 1;
112 inode_size = apb*apb + apb + EXT2_NDIR_BLOCKS;
113 inode_size *= fs->blocksize;
114 inode.i_size = inode_size & 0xFFFFFFFF;
115 inode.i_size_high = (inode_size >> 32) & 0xFFFFFFFF;
116 if (inode.i_size_high) {
117 sb->s_feature_ro_compat |=
118 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
119 }
120 inode.i_ctime = time(NULL);
121 }
122
123 for (rsv_off = 0, gdt_off = fs->desc_blocks,
124 gdt_blk = sb->s_first_data_block + 1 + fs->desc_blocks;
125 rsv_off < sb->s_reserved_gdt_blocks;
126 rsv_off++, gdt_off++, gdt_blk++) {
127 unsigned int three = 1, five = 5, seven = 7;
128 unsigned int grp, last = 0;
129 int gdt_dirty = 0;
130
131 gdt_off %= apb;
132 if (!dindir_buf[gdt_off]) {
133 /* FIXME XXX XXX
134 blk_t new_blk;
135
136 retval = ext2fs_new_block(fs, gdt_blk, 0, &new_blk);
137 if (retval)
138 goto out_free;
139 if (new_blk != gdt_blk) {
140 // XXX free block
141 retval = -1; // XXX
142 }
143 */
144 gdt_dirty = dindir_dirty = inode_dirty = 1;
145 memset(gdt_buf, 0, fs->blocksize);
146 dindir_buf[gdt_off] = gdt_blk;
147 inode.i_blocks += rsv_add;
148#ifdef RES_GDT_DEBUG
149 printf("added primary GDT block %u at %u[%u]\n",
150 gdt_blk, dindir_blk, gdt_off);
151#endif
152 } else if (dindir_buf[gdt_off] == gdt_blk) {
153#ifdef RES_GDT_DEBUG
154 printf("reading primary GDT block %u\n", gdt_blk);
155#endif
156 retval = ext2fs_read_ind_block(fs, gdt_blk, gdt_buf);
157 if (retval)
158 goto out_dindir;
159 } else {
160#ifdef RES_GDT_DEBUG
161 printf("bad primary GDT %u != %u at %u[%u]\n",
162 dindir_buf[gdt_off], gdt_blk,dindir_blk,gdt_off);
163#endif
164 retval = EXT2_ET_RESIZE_INODE_CORRUPT;
165 goto out_dindir;
166 }
167
168 while ((grp = list_backups(fs, &three, &five, &seven)) <
169 fs->group_desc_count) {
170 blk_t expect = gdt_blk + grp * sb->s_blocks_per_group;
171
172 if (!gdt_buf[last]) {
173#ifdef RES_GDT_DEBUG
174 printf("added backup GDT %u grp %u@%u[%u]\n",
175 expect, grp, gdt_blk, last);
176#endif
177 gdt_buf[last] = expect;
178 inode.i_blocks += rsv_add;
179 gdt_dirty = inode_dirty = 1;
180 } else if (gdt_buf[last] != expect) {
181#ifdef RES_GDT_DEBUG
182 printf("bad backup GDT %u != %u at %u[%u]\n",
183 gdt_buf[last], expect, gdt_blk, last);
184#endif
185 retval = EXT2_ET_RESIZE_INODE_CORRUPT;
186 goto out_dindir;
187 }
188 last++;
189 }
190 if (gdt_dirty) {
191#ifdef RES_GDT_DEBUG
192 printf("writing primary GDT block %u\n", gdt_blk);
193#endif
194 retval = ext2fs_write_ind_block(fs, gdt_blk, gdt_buf);
195 if (retval)
196 goto out_dindir;
197 }
198 }
199
200out_dindir:
201 if (dindir_dirty) {
202 retval2 = ext2fs_write_ind_block(fs, dindir_blk, dindir_buf);
203 if (!retval)
204 retval = retval2;
205 }
206out_inode:
207#ifdef RES_GDT_DEBUG
208 printf("inode.i_blocks = %u, i_size = %u\n", inode.i_blocks,
209 inode.i_size);
210#endif
211 if (inode_dirty) {
212 inode.i_atime = inode.i_mtime = time(NULL);
213 retval2 = ext2fs_write_inode(fs, EXT2_RESIZE_INO, &inode);
214 if (!retval)
215 retval = retval2;
216 }
217out_free:
218 ext2fs_free_mem((void *)&dindir_buf);
219 return retval;
220}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/rs_bitmap.c b/e2fsprogs/old_e2fsprogs/ext2fs/rs_bitmap.c
deleted file mode 100644
index 32e87b77a..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/rs_bitmap.c
+++ /dev/null
@@ -1,106 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * rs_bitmap.c --- routine for changing the size of a bitmap
4 *
5 * Copyright (C) 1996, 1997 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#include <fcntl.h>
19#include <time.h>
20#ifdef HAVE_SYS_STAT_H
21#include <sys/stat.h>
22#endif
23#ifdef HAVE_SYS_TYPES_H
24#include <sys/types.h>
25#endif
26
27#include "ext2_fs.h"
28#include "ext2fs.h"
29
30errcode_t ext2fs_resize_generic_bitmap(__u32 new_end, __u32 new_real_end,
31 ext2fs_generic_bitmap bmap)
32{
33 errcode_t retval;
34 size_t size, new_size;
35 __u32 bitno;
36
37 if (!bmap)
38 return EXT2_ET_INVALID_ARGUMENT;
39
40 EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_GENERIC_BITMAP);
41
42 /*
43 * If we're expanding the bitmap, make sure all of the new
44 * parts of the bitmap are zero.
45 */
46 if (new_end > bmap->end) {
47 bitno = bmap->real_end;
48 if (bitno > new_end)
49 bitno = new_end;
50 for (; bitno > bmap->end; bitno--)
51 ext2fs_clear_bit(bitno - bmap->start, bmap->bitmap);
52 }
53 if (new_real_end == bmap->real_end) {
54 bmap->end = new_end;
55 return 0;
56 }
57
58 size = ((bmap->real_end - bmap->start) / 8) + 1;
59 new_size = ((new_real_end - bmap->start) / 8) + 1;
60
61 if (size != new_size) {
62 retval = ext2fs_resize_mem(size, new_size, &bmap->bitmap);
63 if (retval)
64 return retval;
65 }
66 if (new_size > size)
67 memset(bmap->bitmap + size, 0, new_size - size);
68
69 bmap->end = new_end;
70 bmap->real_end = new_real_end;
71 return 0;
72}
73
74errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
75 ext2fs_inode_bitmap bmap)
76{
77 errcode_t retval;
78
79 if (!bmap)
80 return EXT2_ET_INVALID_ARGUMENT;
81
82 EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_INODE_BITMAP);
83
84 bmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
85 retval = ext2fs_resize_generic_bitmap(new_end, new_real_end,
86 bmap);
87 bmap->magic = EXT2_ET_MAGIC_INODE_BITMAP;
88 return retval;
89}
90
91errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
92 ext2fs_block_bitmap bmap)
93{
94 errcode_t retval;
95
96 if (!bmap)
97 return EXT2_ET_INVALID_ARGUMENT;
98
99 EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_BLOCK_BITMAP);
100
101 bmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
102 retval = ext2fs_resize_generic_bitmap(new_end, new_real_end,
103 bmap);
104 bmap->magic = EXT2_ET_MAGIC_BLOCK_BITMAP;
105 return retval;
106}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/rw_bitmaps.c b/e2fsprogs/old_e2fsprogs/ext2fs/rw_bitmaps.c
deleted file mode 100644
index bba432679..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/rw_bitmaps.c
+++ /dev/null
@@ -1,294 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * rw_bitmaps.c --- routines to read and write the inode and block bitmaps.
4 *
5 * Copyright (C) 1993, 1994, 1994, 1996 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#include <fcntl.h>
19#include <time.h>
20#ifdef HAVE_SYS_STAT_H
21#include <sys/stat.h>
22#endif
23#ifdef HAVE_SYS_TYPES_H
24#include <sys/types.h>
25#endif
26
27#include "ext2_fs.h"
28#include "ext2fs.h"
29#include "e2image.h"
30
31#if defined(__powerpc__) && BB_BIG_ENDIAN
32/*
33 * On the PowerPC, the big-endian variant of the ext2 filesystem
34 * has its bitmaps stored as 32-bit words with bit 0 as the LSB
35 * of each word. Thus a bitmap with only bit 0 set would be, as
36 * a string of bytes, 00 00 00 01 00 ...
37 * To cope with this, we byte-reverse each word of a bitmap if
38 * we have a big-endian filesystem, that is, if we are *not*
39 * byte-swapping other word-sized numbers.
40 */
41#define EXT2_BIG_ENDIAN_BITMAPS
42#endif
43
44#ifdef EXT2_BIG_ENDIAN_BITMAPS
45static void ext2fs_swap_bitmap(ext2_filsys fs, char *bitmap, int nbytes)
46{
47 __u32 *p = (__u32 *) bitmap;
48 int n;
49
50 for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
51 *p = ext2fs_swab32(*p);
52}
53#endif
54
55errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs)
56{
57 dgrp_t i;
58 size_t nbytes;
59 errcode_t retval;
60 char * inode_bitmap = fs->inode_map->bitmap;
61 char * bitmap_block = NULL;
62 blk_t blk;
63
64 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
65
66 if (!(fs->flags & EXT2_FLAG_RW))
67 return EXT2_ET_RO_FILSYS;
68 if (!inode_bitmap)
69 return 0;
70 nbytes = (size_t) ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8);
71
72 retval = ext2fs_get_mem(fs->blocksize, &bitmap_block);
73 if (retval)
74 return retval;
75 memset(bitmap_block, 0xff, fs->blocksize);
76 for (i = 0; i < fs->group_desc_count; i++) {
77 memcpy(bitmap_block, inode_bitmap, nbytes);
78 blk = fs->group_desc[i].bg_inode_bitmap;
79 if (blk) {
80#ifdef EXT2_BIG_ENDIAN_BITMAPS
81 if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
82 (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
83 ext2fs_swap_bitmap(fs, bitmap_block, nbytes);
84#endif
85 retval = io_channel_write_blk(fs->io, blk, 1,
86 bitmap_block);
87 if (retval)
88 return EXT2_ET_INODE_BITMAP_WRITE;
89 }
90 inode_bitmap += nbytes;
91 }
92 fs->flags &= ~EXT2_FLAG_IB_DIRTY;
93 ext2fs_free_mem(&bitmap_block);
94 return 0;
95}
96
97errcode_t ext2fs_write_block_bitmap (ext2_filsys fs)
98{
99 dgrp_t i;
100 unsigned int j;
101 int nbytes;
102 unsigned int nbits;
103 errcode_t retval;
104 char * block_bitmap = fs->block_map->bitmap;
105 char * bitmap_block = NULL;
106 blk_t blk;
107
108 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
109
110 if (!(fs->flags & EXT2_FLAG_RW))
111 return EXT2_ET_RO_FILSYS;
112 if (!block_bitmap)
113 return 0;
114 nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
115 retval = ext2fs_get_mem(fs->blocksize, &bitmap_block);
116 if (retval)
117 return retval;
118 memset(bitmap_block, 0xff, fs->blocksize);
119 for (i = 0; i < fs->group_desc_count; i++) {
120 memcpy(bitmap_block, block_bitmap, nbytes);
121 if (i == fs->group_desc_count - 1) {
122 /* Force bitmap padding for the last group */
123 nbits = ((fs->super->s_blocks_count
124 - fs->super->s_first_data_block)
125 % EXT2_BLOCKS_PER_GROUP(fs->super));
126 if (nbits)
127 for (j = nbits; j < fs->blocksize * 8; j++)
128 ext2fs_set_bit(j, bitmap_block);
129 }
130 blk = fs->group_desc[i].bg_block_bitmap;
131 if (blk) {
132#ifdef EXT2_BIG_ENDIAN_BITMAPS
133 if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
134 (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
135 ext2fs_swap_bitmap(fs, bitmap_block, nbytes);
136#endif
137 retval = io_channel_write_blk(fs->io, blk, 1,
138 bitmap_block);
139 if (retval)
140 return EXT2_ET_BLOCK_BITMAP_WRITE;
141 }
142 block_bitmap += nbytes;
143 }
144 fs->flags &= ~EXT2_FLAG_BB_DIRTY;
145 ext2fs_free_mem(&bitmap_block);
146 return 0;
147}
148
149static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
150{
151 dgrp_t i;
152 char *block_bitmap = NULL, *inode_bitmap = NULL;
153 char *buf;
154 errcode_t retval;
155 int block_nbytes = (int) EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
156 int inode_nbytes = (int) EXT2_INODES_PER_GROUP(fs->super) / 8;
157 blk_t blk;
158
159 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
160
161 fs->write_bitmaps = ext2fs_write_bitmaps;
162
163 retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
164 if (retval)
165 return retval;
166 if (do_block) {
167 ext2fs_free_block_bitmap(fs->block_map);
168 sprintf(buf, "block bitmap for %s", fs->device_name);
169 retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
170 if (retval)
171 goto cleanup;
172 block_bitmap = fs->block_map->bitmap;
173 }
174 if (do_inode) {
175 ext2fs_free_inode_bitmap(fs->inode_map);
176 sprintf(buf, "inode bitmap for %s", fs->device_name);
177 retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
178 if (retval)
179 goto cleanup;
180 inode_bitmap = fs->inode_map->bitmap;
181 }
182 ext2fs_free_mem(&buf);
183
184 if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
185 if (inode_bitmap) {
186 blk = (fs->image_header->offset_inodemap /
187 fs->blocksize);
188 retval = io_channel_read_blk(fs->image_io, blk,
189 -(inode_nbytes * fs->group_desc_count),
190 inode_bitmap);
191 if (retval)
192 goto cleanup;
193 }
194 if (block_bitmap) {
195 blk = (fs->image_header->offset_blockmap /
196 fs->blocksize);
197 retval = io_channel_read_blk(fs->image_io, blk,
198 -(block_nbytes * fs->group_desc_count),
199 block_bitmap);
200 if (retval)
201 goto cleanup;
202 }
203 return 0;
204 }
205
206 for (i = 0; i < fs->group_desc_count; i++) {
207 if (block_bitmap) {
208 blk = fs->group_desc[i].bg_block_bitmap;
209 if (blk) {
210 retval = io_channel_read_blk(fs->io, blk,
211 -block_nbytes, block_bitmap);
212 if (retval) {
213 retval = EXT2_ET_BLOCK_BITMAP_READ;
214 goto cleanup;
215 }
216#ifdef EXT2_BIG_ENDIAN_BITMAPS
217 if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
218 (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)))
219 ext2fs_swap_bitmap(fs, block_bitmap, block_nbytes);
220#endif
221 } else
222 memset(block_bitmap, 0, block_nbytes);
223 block_bitmap += block_nbytes;
224 }
225 if (inode_bitmap) {
226 blk = fs->group_desc[i].bg_inode_bitmap;
227 if (blk) {
228 retval = io_channel_read_blk(fs->io, blk,
229 -inode_nbytes, inode_bitmap);
230 if (retval) {
231 retval = EXT2_ET_INODE_BITMAP_READ;
232 goto cleanup;
233 }
234#ifdef EXT2_BIG_ENDIAN_BITMAPS
235 if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
236 (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)))
237 ext2fs_swap_bitmap(fs, inode_bitmap, inode_nbytes);
238#endif
239 } else
240 memset(inode_bitmap, 0, inode_nbytes);
241 inode_bitmap += inode_nbytes;
242 }
243 }
244 return 0;
245
246cleanup:
247 if (do_block) {
248 ext2fs_free_mem(&fs->block_map);
249 }
250 if (do_inode) {
251 ext2fs_free_mem(&fs->inode_map);
252 }
253 ext2fs_free_mem(&buf);
254 return retval;
255}
256
257errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs)
258{
259 return read_bitmaps(fs, 1, 0);
260}
261
262errcode_t ext2fs_read_block_bitmap(ext2_filsys fs)
263{
264 return read_bitmaps(fs, 0, 1);
265}
266
267errcode_t ext2fs_read_bitmaps(ext2_filsys fs)
268{
269 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
270
271 if (fs->inode_map && fs->block_map)
272 return 0;
273
274 return read_bitmaps(fs, !fs->inode_map, !fs->block_map);
275}
276
277errcode_t ext2fs_write_bitmaps(ext2_filsys fs)
278{
279 errcode_t retval;
280
281 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
282
283 if (fs->block_map && ext2fs_test_bb_dirty(fs)) {
284 retval = ext2fs_write_block_bitmap(fs);
285 if (retval)
286 return retval;
287 }
288 if (fs->inode_map && ext2fs_test_ib_dirty(fs)) {
289 retval = ext2fs_write_inode_bitmap(fs);
290 if (retval)
291 return retval;
292 }
293 return 0;
294}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/sparse.c b/e2fsprogs/old_e2fsprogs/ext2fs/sparse.c
deleted file mode 100644
index b3d3071e9..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/sparse.c
+++ /dev/null
@@ -1,79 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * sparse.c --- find the groups in an ext2 filesystem with metadata backups
4 *
5 * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
6 * Copyright (C) 2002 Andreas Dilger.
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the GNU Public
10 * License.
11 * %End-Header%
12 */
13
14#include <stdio.h>
15
16#include "ext2_fs.h"
17#include "ext2fsP.h"
18
19static int test_root(int a, int b)
20{
21 if (a == 0)
22 return 1;
23 while (1) {
24 if (a == 1)
25 return 1;
26 if (a % b)
27 return 0;
28 a = a / b;
29 }
30}
31
32int ext2fs_bg_has_super(ext2_filsys fs, int group_block)
33{
34 if (!(fs->super->s_feature_ro_compat &
35 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
36 return 1;
37
38 if (test_root(group_block, 3) || (test_root(group_block, 5)) ||
39 test_root(group_block, 7))
40 return 1;
41
42 return 0;
43}
44
45/*
46 * Iterate through the groups which hold BACKUP superblock/GDT copies in an
47 * ext3 filesystem. The counters should be initialized to 1, 5, and 7 before
48 * calling this for the first time. In a sparse filesystem it will be the
49 * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ...
50 * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ...
51 */
52unsigned int ext2fs_list_backups(ext2_filsys fs, unsigned int *three,
53 unsigned int *five, unsigned int *seven)
54{
55 unsigned int *min = three;
56 int mult = 3;
57 unsigned int ret;
58
59 if (!(fs->super->s_feature_ro_compat &
60 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
61 ret = *min;
62 *min += 1;
63 return ret;
64 }
65
66 if (*five < *min) {
67 min = five;
68 mult = 5;
69 }
70 if (*seven < *min) {
71 min = seven;
72 mult = 7;
73 }
74
75 ret = *min;
76 *min *= mult;
77
78 return ret;
79}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/swapfs.c b/e2fsprogs/old_e2fsprogs/ext2fs/swapfs.c
deleted file mode 100644
index 07b757abd..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/swapfs.c
+++ /dev/null
@@ -1,234 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * swapfs.c --- swap ext2 filesystem data structures
4 *
5 * Copyright (C) 1995, 1996, 2002 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <unistd.h>
15#include <string.h>
16#include <time.h>
17
18#include "ext2_fs.h"
19#include "ext2fs.h"
20#include "ext2_ext_attr.h"
21
22#if BB_BIG_ENDIAN
23void ext2fs_swap_super(struct ext2_super_block * sb)
24{
25 int i;
26 sb->s_inodes_count = ext2fs_swab32(sb->s_inodes_count);
27 sb->s_blocks_count = ext2fs_swab32(sb->s_blocks_count);
28 sb->s_r_blocks_count = ext2fs_swab32(sb->s_r_blocks_count);
29 sb->s_free_blocks_count = ext2fs_swab32(sb->s_free_blocks_count);
30 sb->s_free_inodes_count = ext2fs_swab32(sb->s_free_inodes_count);
31 sb->s_first_data_block = ext2fs_swab32(sb->s_first_data_block);
32 sb->s_log_block_size = ext2fs_swab32(sb->s_log_block_size);
33 sb->s_log_frag_size = ext2fs_swab32(sb->s_log_frag_size);
34 sb->s_blocks_per_group = ext2fs_swab32(sb->s_blocks_per_group);
35 sb->s_frags_per_group = ext2fs_swab32(sb->s_frags_per_group);
36 sb->s_inodes_per_group = ext2fs_swab32(sb->s_inodes_per_group);
37 sb->s_mtime = ext2fs_swab32(sb->s_mtime);
38 sb->s_wtime = ext2fs_swab32(sb->s_wtime);
39 sb->s_mnt_count = ext2fs_swab16(sb->s_mnt_count);
40 sb->s_max_mnt_count = ext2fs_swab16(sb->s_max_mnt_count);
41 sb->s_magic = ext2fs_swab16(sb->s_magic);
42 sb->s_state = ext2fs_swab16(sb->s_state);
43 sb->s_errors = ext2fs_swab16(sb->s_errors);
44 sb->s_minor_rev_level = ext2fs_swab16(sb->s_minor_rev_level);
45 sb->s_lastcheck = ext2fs_swab32(sb->s_lastcheck);
46 sb->s_checkinterval = ext2fs_swab32(sb->s_checkinterval);
47 sb->s_creator_os = ext2fs_swab32(sb->s_creator_os);
48 sb->s_rev_level = ext2fs_swab32(sb->s_rev_level);
49 sb->s_def_resuid = ext2fs_swab16(sb->s_def_resuid);
50 sb->s_def_resgid = ext2fs_swab16(sb->s_def_resgid);
51 sb->s_first_ino = ext2fs_swab32(sb->s_first_ino);
52 sb->s_inode_size = ext2fs_swab16(sb->s_inode_size);
53 sb->s_block_group_nr = ext2fs_swab16(sb->s_block_group_nr);
54 sb->s_feature_compat = ext2fs_swab32(sb->s_feature_compat);
55 sb->s_feature_incompat = ext2fs_swab32(sb->s_feature_incompat);
56 sb->s_feature_ro_compat = ext2fs_swab32(sb->s_feature_ro_compat);
57 sb->s_algorithm_usage_bitmap = ext2fs_swab32(sb->s_algorithm_usage_bitmap);
58 sb->s_reserved_gdt_blocks = ext2fs_swab16(sb->s_reserved_gdt_blocks);
59 sb->s_journal_inum = ext2fs_swab32(sb->s_journal_inum);
60 sb->s_journal_dev = ext2fs_swab32(sb->s_journal_dev);
61 sb->s_last_orphan = ext2fs_swab32(sb->s_last_orphan);
62 sb->s_default_mount_opts = ext2fs_swab32(sb->s_default_mount_opts);
63 sb->s_first_meta_bg = ext2fs_swab32(sb->s_first_meta_bg);
64 sb->s_mkfs_time = ext2fs_swab32(sb->s_mkfs_time);
65 for (i=0; i < 4; i++)
66 sb->s_hash_seed[i] = ext2fs_swab32(sb->s_hash_seed[i]);
67 for (i=0; i < 17; i++)
68 sb->s_jnl_blocks[i] = ext2fs_swab32(sb->s_jnl_blocks[i]);
69}
70
71void ext2fs_swap_group_desc(struct ext2_group_desc *gdp)
72{
73 gdp->bg_block_bitmap = ext2fs_swab32(gdp->bg_block_bitmap);
74 gdp->bg_inode_bitmap = ext2fs_swab32(gdp->bg_inode_bitmap);
75 gdp->bg_inode_table = ext2fs_swab32(gdp->bg_inode_table);
76 gdp->bg_free_blocks_count = ext2fs_swab16(gdp->bg_free_blocks_count);
77 gdp->bg_free_inodes_count = ext2fs_swab16(gdp->bg_free_inodes_count);
78 gdp->bg_used_dirs_count = ext2fs_swab16(gdp->bg_used_dirs_count);
79}
80
81void ext2fs_swap_ext_attr(char *to, char *from, int bufsize, int has_header)
82{
83 struct ext2_ext_attr_header *from_header =
84 (struct ext2_ext_attr_header *)from;
85 struct ext2_ext_attr_header *to_header =
86 (struct ext2_ext_attr_header *)to;
87 struct ext2_ext_attr_entry *from_entry, *to_entry;
88 char *from_end = (char *)from_header + bufsize;
89 int n;
90
91 if (to_header != from_header)
92 memcpy(to_header, from_header, bufsize);
93
94 from_entry = (struct ext2_ext_attr_entry *)from_header;
95 to_entry = (struct ext2_ext_attr_entry *)to_header;
96
97 if (has_header) {
98 to_header->h_magic = ext2fs_swab32(from_header->h_magic);
99 to_header->h_blocks = ext2fs_swab32(from_header->h_blocks);
100 to_header->h_refcount = ext2fs_swab32(from_header->h_refcount);
101 for (n=0; n<4; n++)
102 to_header->h_reserved[n] =
103 ext2fs_swab32(from_header->h_reserved[n]);
104 from_entry = (struct ext2_ext_attr_entry *)(from_header+1);
105 to_entry = (struct ext2_ext_attr_entry *)(to_header+1);
106 }
107
108 while ((char *)from_entry < from_end && *(__u32 *)from_entry) {
109 to_entry->e_value_offs =
110 ext2fs_swab16(from_entry->e_value_offs);
111 to_entry->e_value_block =
112 ext2fs_swab32(from_entry->e_value_block);
113 to_entry->e_value_size =
114 ext2fs_swab32(from_entry->e_value_size);
115 from_entry = EXT2_EXT_ATTR_NEXT(from_entry);
116 to_entry = EXT2_EXT_ATTR_NEXT(to_entry);
117 }
118}
119
120void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t,
121 struct ext2_inode_large *f, int hostorder,
122 int bufsize)
123{
124 unsigned i;
125 int islnk = 0;
126 __u32 *eaf, *eat;
127
128 if (hostorder && LINUX_S_ISLNK(f->i_mode))
129 islnk = 1;
130 t->i_mode = ext2fs_swab16(f->i_mode);
131 if (!hostorder && LINUX_S_ISLNK(t->i_mode))
132 islnk = 1;
133 t->i_uid = ext2fs_swab16(f->i_uid);
134 t->i_size = ext2fs_swab32(f->i_size);
135 t->i_atime = ext2fs_swab32(f->i_atime);
136 t->i_ctime = ext2fs_swab32(f->i_ctime);
137 t->i_mtime = ext2fs_swab32(f->i_mtime);
138 t->i_dtime = ext2fs_swab32(f->i_dtime);
139 t->i_gid = ext2fs_swab16(f->i_gid);
140 t->i_links_count = ext2fs_swab16(f->i_links_count);
141 t->i_blocks = ext2fs_swab32(f->i_blocks);
142 t->i_flags = ext2fs_swab32(f->i_flags);
143 t->i_file_acl = ext2fs_swab32(f->i_file_acl);
144 t->i_dir_acl = ext2fs_swab32(f->i_dir_acl);
145 if (!islnk || ext2fs_inode_data_blocks(fs, (struct ext2_inode *)t)) {
146 for (i = 0; i < EXT2_N_BLOCKS; i++)
147 t->i_block[i] = ext2fs_swab32(f->i_block[i]);
148 } else if (t != f) {
149 for (i = 0; i < EXT2_N_BLOCKS; i++)
150 t->i_block[i] = f->i_block[i];
151 }
152 t->i_generation = ext2fs_swab32(f->i_generation);
153 t->i_faddr = ext2fs_swab32(f->i_faddr);
154
155 switch (fs->super->s_creator_os) {
156 case EXT2_OS_LINUX:
157 t->osd1.linux1.l_i_reserved1 =
158 ext2fs_swab32(f->osd1.linux1.l_i_reserved1);
159 t->osd2.linux2.l_i_frag = f->osd2.linux2.l_i_frag;
160 t->osd2.linux2.l_i_fsize = f->osd2.linux2.l_i_fsize;
161 t->osd2.linux2.i_pad1 = ext2fs_swab16(f->osd2.linux2.i_pad1);
162 t->osd2.linux2.l_i_uid_high =
163 ext2fs_swab16 (f->osd2.linux2.l_i_uid_high);
164 t->osd2.linux2.l_i_gid_high =
165 ext2fs_swab16 (f->osd2.linux2.l_i_gid_high);
166 t->osd2.linux2.l_i_reserved2 =
167 ext2fs_swab32(f->osd2.linux2.l_i_reserved2);
168 break;
169 case EXT2_OS_HURD:
170 t->osd1.hurd1.h_i_translator =
171 ext2fs_swab32 (f->osd1.hurd1.h_i_translator);
172 t->osd2.hurd2.h_i_frag = f->osd2.hurd2.h_i_frag;
173 t->osd2.hurd2.h_i_fsize = f->osd2.hurd2.h_i_fsize;
174 t->osd2.hurd2.h_i_mode_high =
175 ext2fs_swab16 (f->osd2.hurd2.h_i_mode_high);
176 t->osd2.hurd2.h_i_uid_high =
177 ext2fs_swab16 (f->osd2.hurd2.h_i_uid_high);
178 t->osd2.hurd2.h_i_gid_high =
179 ext2fs_swab16 (f->osd2.hurd2.h_i_gid_high);
180 t->osd2.hurd2.h_i_author =
181 ext2fs_swab32 (f->osd2.hurd2.h_i_author);
182 break;
183 case EXT2_OS_MASIX:
184 t->osd1.masix1.m_i_reserved1 =
185 ext2fs_swab32(f->osd1.masix1.m_i_reserved1);
186 t->osd2.masix2.m_i_frag = f->osd2.masix2.m_i_frag;
187 t->osd2.masix2.m_i_fsize = f->osd2.masix2.m_i_fsize;
188 t->osd2.masix2.m_pad1 = ext2fs_swab16(f->osd2.masix2.m_pad1);
189 t->osd2.masix2.m_i_reserved2[0] =
190 ext2fs_swab32(f->osd2.masix2.m_i_reserved2[0]);
191 t->osd2.masix2.m_i_reserved2[1] =
192 ext2fs_swab32(f->osd2.masix2.m_i_reserved2[1]);
193 break;
194 }
195
196 if (bufsize < (int) (sizeof(struct ext2_inode) + sizeof(__u16)))
197 return; /* no i_extra_isize field */
198
199 t->i_extra_isize = ext2fs_swab16(f->i_extra_isize);
200 if (t->i_extra_isize > EXT2_INODE_SIZE(fs->super) -
201 sizeof(struct ext2_inode)) {
202 /* this is error case: i_extra_size is too large */
203 return;
204 }
205
206 i = sizeof(struct ext2_inode) + t->i_extra_isize + sizeof(__u32);
207 if (bufsize < (int) i)
208 return; /* no space for EA magic */
209
210 eaf = (__u32 *) (((char *) f) + sizeof(struct ext2_inode) +
211 f->i_extra_isize);
212
213 if (ext2fs_swab32(*eaf) != EXT2_EXT_ATTR_MAGIC)
214 return; /* it seems no magic here */
215
216 eat = (__u32 *) (((char *) t) + sizeof(struct ext2_inode) +
217 f->i_extra_isize);
218 *eat = ext2fs_swab32(*eaf);
219
220 /* convert EA(s) */
221 ext2fs_swap_ext_attr((char *) (eat + 1), (char *) (eaf + 1),
222 bufsize - sizeof(struct ext2_inode) -
223 t->i_extra_isize - sizeof(__u32), 0);
224}
225
226void ext2fs_swap_inode(ext2_filsys fs, struct ext2_inode *t,
227 struct ext2_inode *f, int hostorder)
228{
229 ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) t,
230 (struct ext2_inode_large *) f, hostorder,
231 sizeof(struct ext2_inode));
232}
233
234#endif
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/test_io.c b/e2fsprogs/old_e2fsprogs/ext2fs/test_io.c
deleted file mode 100644
index 3d40d9a97..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/test_io.c
+++ /dev/null
@@ -1,380 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * test_io.c --- This is the Test I/O interface.
4 *
5 * Copyright (C) 1996 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#include <fcntl.h>
19#include <time.h>
20#if HAVE_SYS_STAT_H
21#include <sys/stat.h>
22#endif
23#if HAVE_SYS_TYPES_H
24#include <sys/types.h>
25#endif
26
27#include "ext2_fs.h"
28#include "ext2fs.h"
29
30/*
31 * For checking structure magic numbers...
32 */
33
34#define EXT2_CHECK_MAGIC(struct, code) \
35 if ((struct)->magic != (code)) return (code)
36
37struct test_private_data {
38 int magic;
39 io_channel real;
40 int flags;
41 FILE *outfile;
42 unsigned long block;
43 int read_abort_count, write_abort_count;
44 void (*read_blk)(unsigned long block, int count, errcode_t err);
45 void (*write_blk)(unsigned long block, int count, errcode_t err);
46 void (*set_blksize)(int blksize, errcode_t err);
47 void (*write_byte)(unsigned long block, int count, errcode_t err);
48};
49
50static errcode_t test_open(const char *name, int flags, io_channel *channel);
51static errcode_t test_close(io_channel channel);
52static errcode_t test_set_blksize(io_channel channel, int blksize);
53static errcode_t test_read_blk(io_channel channel, unsigned long block,
54 int count, void *data);
55static errcode_t test_write_blk(io_channel channel, unsigned long block,
56 int count, const void *data);
57static errcode_t test_flush(io_channel channel);
58static errcode_t test_write_byte(io_channel channel, unsigned long offset,
59 int count, const void *buf);
60static errcode_t test_set_option(io_channel channel, const char *option,
61 const char *arg);
62
63static struct struct_io_manager struct_test_manager = {
64 EXT2_ET_MAGIC_IO_MANAGER,
65 "Test I/O Manager",
66 test_open,
67 test_close,
68 test_set_blksize,
69 test_read_blk,
70 test_write_blk,
71 test_flush,
72 test_write_byte,
73 test_set_option
74};
75
76io_manager test_io_manager = &struct_test_manager;
77
78/*
79 * These global variable can be set by the test program as
80 * necessary *before* calling test_open
81 */
82io_manager test_io_backing_manager = 0;
83void (*test_io_cb_read_blk)
84 (unsigned long block, int count, errcode_t err) = 0;
85void (*test_io_cb_write_blk)
86 (unsigned long block, int count, errcode_t err) = 0;
87void (*test_io_cb_set_blksize)
88 (int blksize, errcode_t err) = 0;
89void (*test_io_cb_write_byte)
90 (unsigned long block, int count, errcode_t err) = 0;
91
92/*
93 * Test flags
94 */
95#define TEST_FLAG_READ 0x01
96#define TEST_FLAG_WRITE 0x02
97#define TEST_FLAG_SET_BLKSIZE 0x04
98#define TEST_FLAG_FLUSH 0x08
99#define TEST_FLAG_DUMP 0x10
100#define TEST_FLAG_SET_OPTION 0x20
101
102static void test_dump_block(io_channel channel,
103 struct test_private_data *data,
104 unsigned long block, const void *buf)
105{
106 const unsigned char *cp;
107 FILE *f = data->outfile;
108 int i;
109 unsigned long cksum = 0;
110
111 for (i=0, cp = buf; i < channel->block_size; i++, cp++) {
112 cksum += *cp;
113 }
114 fprintf(f, "Contents of block %lu, checksum %08lu:\n", block, cksum);
115 for (i=0, cp = buf; i < channel->block_size; i++, cp++) {
116 if ((i % 16) == 0)
117 fprintf(f, "%04x: ", i);
118 fprintf(f, "%02x%c", *cp, ((i % 16) == 15) ? '\n' : ' ');
119 }
120}
121
122static void test_abort(io_channel channel, unsigned long block)
123{
124 struct test_private_data *data;
125 FILE *f;
126
127 data = (struct test_private_data *) channel->private_data;
128 f = data->outfile;
129 test_flush(channel);
130
131 fprintf(f, "Aborting due to I/O to block %lu\n", block);
132 fflush(f);
133 abort();
134}
135
136static errcode_t test_open(const char *name, int flags, io_channel *channel)
137{
138 io_channel io = NULL;
139 struct test_private_data *data = NULL;
140 errcode_t retval;
141 char *value;
142
143 if (name == 0)
144 return EXT2_ET_BAD_DEVICE_NAME;
145 retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
146 if (retval)
147 return retval;
148 memset(io, 0, sizeof(struct struct_io_channel));
149 io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
150 retval = ext2fs_get_mem(sizeof(struct test_private_data), &data);
151 if (retval) {
152 retval = EXT2_ET_NO_MEMORY;
153 goto cleanup;
154 }
155 io->manager = test_io_manager;
156 retval = ext2fs_get_mem(strlen(name)+1, &io->name);
157 if (retval)
158 goto cleanup;
159
160 strcpy(io->name, name);
161 io->private_data = data;
162 io->block_size = 1024;
163 io->read_error = 0;
164 io->write_error = 0;
165 io->refcount = 1;
166
167 memset(data, 0, sizeof(struct test_private_data));
168 data->magic = EXT2_ET_MAGIC_TEST_IO_CHANNEL;
169 if (test_io_backing_manager) {
170 retval = test_io_backing_manager->open(name, flags,
171 &data->real);
172 if (retval)
173 goto cleanup;
174 } else
175 data->real = 0;
176 data->read_blk = test_io_cb_read_blk;
177 data->write_blk = test_io_cb_write_blk;
178 data->set_blksize = test_io_cb_set_blksize;
179 data->write_byte = test_io_cb_write_byte;
180
181 data->outfile = NULL;
182 if ((value = getenv("TEST_IO_LOGFILE")) != NULL)
183 data->outfile = fopen_for_write(value);
184 if (!data->outfile)
185 data->outfile = stderr;
186
187 data->flags = 0;
188 if ((value = getenv("TEST_IO_FLAGS")) != NULL)
189 data->flags = strtoul(value, NULL, 0);
190
191 data->block = 0;
192 if ((value = getenv("TEST_IO_BLOCK")) != NULL)
193 data->block = strtoul(value, NULL, 0);
194
195 data->read_abort_count = 0;
196 if ((value = getenv("TEST_IO_READ_ABORT")) != NULL)
197 data->read_abort_count = strtoul(value, NULL, 0);
198
199 data->write_abort_count = 0;
200 if ((value = getenv("TEST_IO_WRITE_ABORT")) != NULL)
201 data->write_abort_count = strtoul(value, NULL, 0);
202
203 *channel = io;
204 return 0;
205
206cleanup:
207 ext2fs_free_mem(&io);
208 ext2fs_free_mem(&data);
209 return retval;
210}
211
212static errcode_t test_close(io_channel channel)
213{
214 struct test_private_data *data;
215 errcode_t retval = 0;
216
217 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
218 data = (struct test_private_data *) channel->private_data;
219 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
220
221 if (--channel->refcount > 0)
222 return 0;
223
224 if (data->real)
225 retval = io_channel_close(data->real);
226
227 if (data->outfile && data->outfile != stderr)
228 fclose(data->outfile);
229
230 ext2fs_free_mem(&channel->private_data);
231 ext2fs_free_mem(&channel->name);
232 ext2fs_free_mem(&channel);
233 return retval;
234}
235
236static errcode_t test_set_blksize(io_channel channel, int blksize)
237{
238 struct test_private_data *data;
239 errcode_t retval = 0;
240
241 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
242 data = (struct test_private_data *) channel->private_data;
243 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
244
245 if (data->real)
246 retval = io_channel_set_blksize(data->real, blksize);
247 if (data->set_blksize)
248 data->set_blksize(blksize, retval);
249 if (data->flags & TEST_FLAG_SET_BLKSIZE)
250 fprintf(data->outfile,
251 "Test_io: set_blksize(%d) returned %s\n",
252 blksize, retval ? error_message(retval) : "OK");
253 channel->block_size = blksize;
254 return retval;
255}
256
257
258static errcode_t test_read_blk(io_channel channel, unsigned long block,
259 int count, void *buf)
260{
261 struct test_private_data *data;
262 errcode_t retval = 0;
263
264 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
265 data = (struct test_private_data *) channel->private_data;
266 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
267
268 if (data->real)
269 retval = io_channel_read_blk(data->real, block, count, buf);
270 if (data->read_blk)
271 data->read_blk(block, count, retval);
272 if (data->flags & TEST_FLAG_READ)
273 fprintf(data->outfile,
274 "Test_io: read_blk(%lu, %d) returned %s\n",
275 block, count, retval ? error_message(retval) : "OK");
276 if (data->block && data->block == block) {
277 if (data->flags & TEST_FLAG_DUMP)
278 test_dump_block(channel, data, block, buf);
279 if (--data->read_abort_count == 0)
280 test_abort(channel, block);
281 }
282 return retval;
283}
284
285static errcode_t test_write_blk(io_channel channel, unsigned long block,
286 int count, const void *buf)
287{
288 struct test_private_data *data;
289 errcode_t retval = 0;
290
291 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
292 data = (struct test_private_data *) channel->private_data;
293 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
294
295 if (data->real)
296 retval = io_channel_write_blk(data->real, block, count, buf);
297 if (data->write_blk)
298 data->write_blk(block, count, retval);
299 if (data->flags & TEST_FLAG_WRITE)
300 fprintf(data->outfile,
301 "Test_io: write_blk(%lu, %d) returned %s\n",
302 block, count, retval ? error_message(retval) : "OK");
303 if (data->block && data->block == block) {
304 if (data->flags & TEST_FLAG_DUMP)
305 test_dump_block(channel, data, block, buf);
306 if (--data->write_abort_count == 0)
307 test_abort(channel, block);
308 }
309 return retval;
310}
311
312static errcode_t test_write_byte(io_channel channel, unsigned long offset,
313 int count, const void *buf)
314{
315 struct test_private_data *data;
316 errcode_t retval = 0;
317
318 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
319 data = (struct test_private_data *) channel->private_data;
320 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
321
322 if (data->real && data->real->manager->write_byte)
323 retval = io_channel_write_byte(data->real, offset, count, buf);
324 if (data->write_byte)
325 data->write_byte(offset, count, retval);
326 if (data->flags & TEST_FLAG_WRITE)
327 fprintf(data->outfile,
328 "Test_io: write_byte(%lu, %d) returned %s\n",
329 offset, count, retval ? error_message(retval) : "OK");
330 return retval;
331}
332
333/*
334 * Flush data buffers to disk.
335 */
336static errcode_t test_flush(io_channel channel)
337{
338 struct test_private_data *data;
339 errcode_t retval = 0;
340
341 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
342 data = (struct test_private_data *) channel->private_data;
343 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
344
345 if (data->real)
346 retval = io_channel_flush(data->real);
347
348 if (data->flags & TEST_FLAG_FLUSH)
349 fprintf(data->outfile, "Test_io: flush() returned %s\n",
350 retval ? error_message(retval) : "OK");
351
352 return retval;
353}
354
355static errcode_t test_set_option(io_channel channel, const char *option,
356 const char *arg)
357{
358 struct test_private_data *data;
359 errcode_t retval = 0;
360
361 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
362 data = (struct test_private_data *) channel->private_data;
363 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
364
365
366 if (data->flags & TEST_FLAG_SET_OPTION)
367 fprintf(data->outfile, "Test_io: set_option(%s, %s) ",
368 option, arg);
369 if (data->real && data->real->manager->set_option) {
370 retval = (data->real->manager->set_option)(data->real,
371 option, arg);
372 if (data->flags & TEST_FLAG_SET_OPTION)
373 fprintf(data->outfile, "returned %s\n",
374 retval ? error_message(retval) : "OK");
375 } else {
376 if (data->flags & TEST_FLAG_SET_OPTION)
377 fprintf(data->outfile, "not implemented\n");
378 }
379 return retval;
380}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/unix_io.c b/e2fsprogs/old_e2fsprogs/ext2fs/unix_io.c
deleted file mode 100644
index 3c95829f0..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/unix_io.c
+++ /dev/null
@@ -1,703 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * unix_io.c --- This is the Unix (well, really POSIX) implementation
4 * of the I/O manager.
5 *
6 * Implements a one-block write-through cache.
7 *
8 * Includes support for Windows NT support under Cygwin.
9 *
10 * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
11 * 2002 by Theodore Ts'o.
12 *
13 * %Begin-Header%
14 * This file may be redistributed under the terms of the GNU Public
15 * License.
16 * %End-Header%
17 */
18
19#include <stdio.h>
20#include <string.h>
21#if HAVE_UNISTD_H
22#include <unistd.h>
23#endif
24#if HAVE_ERRNO_H
25#include <errno.h>
26#endif
27#include <fcntl.h>
28#include <time.h>
29#ifdef __linux__
30#include <sys/utsname.h>
31#endif
32#if HAVE_SYS_STAT_H
33#include <sys/stat.h>
34#endif
35#if HAVE_SYS_TYPES_H
36#include <sys/types.h>
37#endif
38#include <sys/resource.h>
39
40#include "ext2_fs.h"
41#include "ext2fs.h"
42
43/*
44 * For checking structure magic numbers...
45 */
46
47#define EXT2_CHECK_MAGIC(struct, code) \
48 if ((struct)->magic != (code)) return (code)
49
50struct unix_cache {
51 char *buf;
52 unsigned long block;
53 int access_time;
54 unsigned dirty:1;
55 unsigned in_use:1;
56};
57
58#define CACHE_SIZE 8
59#define WRITE_DIRECT_SIZE 4 /* Must be smaller than CACHE_SIZE */
60#define READ_DIRECT_SIZE 4 /* Should be smaller than CACHE_SIZE */
61
62struct unix_private_data {
63 int magic;
64 int dev;
65 int flags;
66 int access_time;
67 ext2_loff_t offset;
68 struct unix_cache cache[CACHE_SIZE];
69};
70
71static errcode_t unix_open(const char *name, int flags, io_channel *channel);
72static errcode_t unix_close(io_channel channel);
73static errcode_t unix_set_blksize(io_channel channel, int blksize);
74static errcode_t unix_read_blk(io_channel channel, unsigned long block,
75 int count, void *data);
76static errcode_t unix_write_blk(io_channel channel, unsigned long block,
77 int count, const void *data);
78static errcode_t unix_flush(io_channel channel);
79static errcode_t unix_write_byte(io_channel channel, unsigned long offset,
80 int size, const void *data);
81static errcode_t unix_set_option(io_channel channel, const char *option,
82 const char *arg);
83
84static void reuse_cache(io_channel channel, struct unix_private_data *data,
85 struct unix_cache *cache, unsigned long block);
86
87/* __FreeBSD_kernel__ is defined by GNU/kFreeBSD - the FreeBSD kernel
88 * does not know buffered block devices - everything is raw. */
89#if defined(__CYGWIN__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
90#define NEED_BOUNCE_BUFFER
91#else
92#undef NEED_BOUNCE_BUFFER
93#endif
94
95static struct struct_io_manager struct_unix_manager = {
96 EXT2_ET_MAGIC_IO_MANAGER,
97 "Unix I/O Manager",
98 unix_open,
99 unix_close,
100 unix_set_blksize,
101 unix_read_blk,
102 unix_write_blk,
103 unix_flush,
104#ifdef NEED_BOUNCE_BUFFER
105 0,
106#else
107 unix_write_byte,
108#endif
109 unix_set_option
110};
111
112io_manager unix_io_manager = &struct_unix_manager;
113
114/*
115 * Here are the raw I/O functions
116 */
117#ifndef NEED_BOUNCE_BUFFER
118static errcode_t raw_read_blk(io_channel channel,
119 struct unix_private_data *data,
120 unsigned long block,
121 int count, void *buf)
122{
123 errcode_t retval;
124 ssize_t size;
125 ext2_loff_t location;
126 int actual = 0;
127
128 size = (count < 0) ? -count : count * channel->block_size;
129 location = ((ext2_loff_t) block * channel->block_size) + data->offset;
130 if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
131 retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
132 goto error_out;
133 }
134 actual = read(data->dev, buf, size);
135 if (actual != size) {
136 if (actual < 0)
137 actual = 0;
138 retval = EXT2_ET_SHORT_READ;
139 goto error_out;
140 }
141 return 0;
142
143error_out:
144 memset((char *) buf+actual, 0, size-actual);
145 if (channel->read_error)
146 retval = (channel->read_error)(channel, block, count, buf,
147 size, actual, retval);
148 return retval;
149}
150#else /* NEED_BOUNCE_BUFFER */
151/*
152 * Windows and FreeBSD block devices only allow sector alignment IO in offset and size
153 */
154static errcode_t raw_read_blk(io_channel channel,
155 struct unix_private_data *data,
156 unsigned long block,
157 int count, void *buf)
158{
159 errcode_t retval;
160 size_t size, alignsize, fragment;
161 ext2_loff_t location;
162 int total = 0, actual;
163#define BLOCKALIGN 512
164 char sector[BLOCKALIGN];
165
166 size = (count < 0) ? -count : count * channel->block_size;
167 location = ((ext2_loff_t) block * channel->block_size) + data->offset;
168#ifdef DEBUG
169 printf("count=%d, size=%d, block=%d, blk_size=%d, location=%lx\n",
170 count, size, block, channel->block_size, location);
171#endif
172 if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
173 retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
174 goto error_out;
175 }
176 fragment = size % BLOCKALIGN;
177 alignsize = size - fragment;
178 if (alignsize) {
179 actual = read(data->dev, buf, alignsize);
180 if (actual != alignsize)
181 goto short_read;
182 }
183 if (fragment) {
184 actual = read(data->dev, sector, BLOCKALIGN);
185 if (actual != BLOCKALIGN)
186 goto short_read;
187 memcpy(buf+alignsize, sector, fragment);
188 }
189 return 0;
190
191short_read:
192 if (actual>0)
193 total += actual;
194 retval = EXT2_ET_SHORT_READ;
195
196error_out:
197 memset((char *) buf+total, 0, size-actual);
198 if (channel->read_error)
199 retval = (channel->read_error)(channel, block, count, buf,
200 size, actual, retval);
201 return retval;
202}
203#endif
204
205static errcode_t raw_write_blk(io_channel channel,
206 struct unix_private_data *data,
207 unsigned long block,
208 int count, const void *buf)
209{
210 ssize_t size;
211 ext2_loff_t location;
212 int actual = 0;
213 errcode_t retval;
214
215 if (count == 1)
216 size = channel->block_size;
217 else {
218 if (count < 0)
219 size = -count;
220 else
221 size = count * channel->block_size;
222 }
223
224 location = ((ext2_loff_t) block * channel->block_size) + data->offset;
225 if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
226 retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
227 goto error_out;
228 }
229
230 actual = write(data->dev, buf, size);
231 if (actual != size) {
232 retval = EXT2_ET_SHORT_WRITE;
233 goto error_out;
234 }
235 return 0;
236
237error_out:
238 if (channel->write_error)
239 retval = (channel->write_error)(channel, block, count, buf,
240 size, actual, retval);
241 return retval;
242}
243
244
245/*
246 * Here we implement the cache functions
247 */
248
249/* Allocate the cache buffers */
250static errcode_t alloc_cache(io_channel channel,
251 struct unix_private_data *data)
252{
253 errcode_t retval;
254 struct unix_cache *cache;
255 int i;
256
257 data->access_time = 0;
258 for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
259 cache->block = 0;
260 cache->access_time = 0;
261 cache->dirty = 0;
262 cache->in_use = 0;
263 if ((retval = ext2fs_get_mem(channel->block_size,
264 &cache->buf)))
265 return retval;
266 }
267 return 0;
268}
269
270/* Free the cache buffers */
271static void free_cache(struct unix_private_data *data)
272{
273 struct unix_cache *cache;
274 int i;
275
276 data->access_time = 0;
277 for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
278 cache->block = 0;
279 cache->access_time = 0;
280 cache->dirty = 0;
281 cache->in_use = 0;
282 ext2fs_free_mem(&cache->buf);
283 cache->buf = 0;
284 }
285}
286
287#ifndef NO_IO_CACHE
288/*
289 * Try to find a block in the cache. If the block is not found, and
290 * eldest is a non-zero pointer, then fill in eldest with the cache
291 * entry to that should be reused.
292 */
293static struct unix_cache *find_cached_block(struct unix_private_data *data,
294 unsigned long block,
295 struct unix_cache **eldest)
296{
297 struct unix_cache *cache, *unused_cache, *oldest_cache;
298 int i;
299
300 unused_cache = oldest_cache = 0;
301 for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
302 if (!cache->in_use) {
303 if (!unused_cache)
304 unused_cache = cache;
305 continue;
306 }
307 if (cache->block == block) {
308 cache->access_time = ++data->access_time;
309 return cache;
310 }
311 if (!oldest_cache ||
312 (cache->access_time < oldest_cache->access_time))
313 oldest_cache = cache;
314 }
315 if (eldest)
316 *eldest = (unused_cache) ? unused_cache : oldest_cache;
317 return 0;
318}
319
320/*
321 * Reuse a particular cache entry for another block.
322 */
323static void reuse_cache(io_channel channel, struct unix_private_data *data,
324 struct unix_cache *cache, unsigned long block)
325{
326 if (cache->dirty && cache->in_use)
327 raw_write_blk(channel, data, cache->block, 1, cache->buf);
328
329 cache->in_use = 1;
330 cache->dirty = 0;
331 cache->block = block;
332 cache->access_time = ++data->access_time;
333}
334
335/*
336 * Flush all of the blocks in the cache
337 */
338static errcode_t flush_cached_blocks(io_channel channel,
339 struct unix_private_data *data,
340 int invalidate)
341
342{
343 struct unix_cache *cache;
344 errcode_t retval, retval2;
345 int i;
346
347 retval2 = 0;
348 for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
349 if (!cache->in_use)
350 continue;
351
352 if (invalidate)
353 cache->in_use = 0;
354
355 if (!cache->dirty)
356 continue;
357
358 retval = raw_write_blk(channel, data,
359 cache->block, 1, cache->buf);
360 if (retval)
361 retval2 = retval;
362 else
363 cache->dirty = 0;
364 }
365 return retval2;
366}
367#endif /* NO_IO_CACHE */
368
369static errcode_t unix_open(const char *name, int flags, io_channel *channel)
370{
371 io_channel io = NULL;
372 struct unix_private_data *data = NULL;
373 errcode_t retval;
374 int open_flags;
375 struct stat st;
376#ifdef __linux__
377 struct utsname ut;
378#endif
379
380 if (name == 0)
381 return EXT2_ET_BAD_DEVICE_NAME;
382 retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
383 if (retval)
384 return retval;
385 memset(io, 0, sizeof(struct struct_io_channel));
386 io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
387 retval = ext2fs_get_mem(sizeof(struct unix_private_data), &data);
388 if (retval)
389 goto cleanup;
390
391 io->manager = unix_io_manager;
392 retval = ext2fs_get_mem(strlen(name)+1, &io->name);
393 if (retval)
394 goto cleanup;
395
396 strcpy(io->name, name);
397 io->private_data = data;
398 io->block_size = 1024;
399 io->read_error = 0;
400 io->write_error = 0;
401 io->refcount = 1;
402
403 memset(data, 0, sizeof(struct unix_private_data));
404 data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL;
405
406 if ((retval = alloc_cache(io, data)))
407 goto cleanup;
408
409 open_flags = (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY;
410#ifdef CONFIG_LFS
411 data->dev = open64(io->name, open_flags);
412#else
413 data->dev = open(io->name, open_flags);
414#endif
415 if (data->dev < 0) {
416 retval = errno;
417 goto cleanup;
418 }
419
420#ifdef __linux__
421#undef RLIM_INFINITY
422#if (defined(__alpha__) || ((defined(__sparc__) || defined(__mips__)) && (SIZEOF_LONG == 4)))
423#define RLIM_INFINITY ((unsigned long)(~0UL>>1))
424#else
425#define RLIM_INFINITY (~0UL)
426#endif
427 /*
428 * Work around a bug in 2.4.10-2.4.18 kernels where writes to
429 * block devices are wrongly getting hit by the filesize
430 * limit. This workaround isn't perfect, since it won't work
431 * if glibc wasn't built against 2.2 header files. (Sigh.)
432 *
433 */
434 if ((flags & IO_FLAG_RW) &&
435 (uname(&ut) == 0) &&
436 ((ut.release[0] == '2') && (ut.release[1] == '.') &&
437 (ut.release[2] == '4') && (ut.release[3] == '.') &&
438 (ut.release[4] == '1') && (ut.release[5] >= '0') &&
439 (ut.release[5] < '8')) &&
440 (fstat(data->dev, &st) == 0) &&
441 (S_ISBLK(st.st_mode))) {
442 struct rlimit rlim;
443
444 rlim.rlim_cur = rlim.rlim_max = (unsigned long) RLIM_INFINITY;
445 setrlimit(RLIMIT_FSIZE, &rlim);
446 getrlimit(RLIMIT_FSIZE, &rlim);
447 if (((unsigned long) rlim.rlim_cur) <
448 ((unsigned long) rlim.rlim_max)) {
449 rlim.rlim_cur = rlim.rlim_max;
450 setrlimit(RLIMIT_FSIZE, &rlim);
451 }
452 }
453#endif
454 *channel = io;
455 return 0;
456
457cleanup:
458 if (data) {
459 free_cache(data);
460 ext2fs_free_mem(&data);
461 }
462 ext2fs_free_mem(&io);
463 return retval;
464}
465
466static errcode_t unix_close(io_channel channel)
467{
468 struct unix_private_data *data;
469 errcode_t retval = 0;
470
471 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
472 data = (struct unix_private_data *) channel->private_data;
473 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
474
475 if (--channel->refcount > 0)
476 return 0;
477
478#ifndef NO_IO_CACHE
479 retval = flush_cached_blocks(channel, data, 0);
480#endif
481
482 if (close(data->dev) < 0)
483 retval = errno;
484 free_cache(data);
485
486 ext2fs_free_mem(&channel->private_data);
487 ext2fs_free_mem(&channel->name);
488 ext2fs_free_mem(&channel);
489 return retval;
490}
491
492static errcode_t unix_set_blksize(io_channel channel, int blksize)
493{
494 struct unix_private_data *data;
495 errcode_t retval;
496
497 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
498 data = (struct unix_private_data *) channel->private_data;
499 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
500
501 if (channel->block_size != blksize) {
502#ifndef NO_IO_CACHE
503 if ((retval = flush_cached_blocks(channel, data, 0)))
504 return retval;
505#endif
506
507 channel->block_size = blksize;
508 free_cache(data);
509 if ((retval = alloc_cache(channel, data)))
510 return retval;
511 }
512 return 0;
513}
514
515
516static errcode_t unix_read_blk(io_channel channel, unsigned long block,
517 int count, void *buf)
518{
519 struct unix_private_data *data;
520 struct unix_cache *cache, *reuse[READ_DIRECT_SIZE];
521 errcode_t retval;
522 char *cp;
523 int i, j;
524
525 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
526 data = (struct unix_private_data *) channel->private_data;
527 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
528
529#ifdef NO_IO_CACHE
530 return raw_read_blk(channel, data, block, count, buf);
531#else
532 /*
533 * If we're doing an odd-sized read or a very large read,
534 * flush out the cache and then do a direct read.
535 */
536 if (count < 0 || count > WRITE_DIRECT_SIZE) {
537 if ((retval = flush_cached_blocks(channel, data, 0)))
538 return retval;
539 return raw_read_blk(channel, data, block, count, buf);
540 }
541
542 cp = buf;
543 while (count > 0) {
544 /* If it's in the cache, use it! */
545 if ((cache = find_cached_block(data, block, &reuse[0]))) {
546#ifdef DEBUG
547 printf("Using cached block %lu\n", block);
548#endif
549 memcpy(cp, cache->buf, channel->block_size);
550 count--;
551 block++;
552 cp += channel->block_size;
553 continue;
554 }
555 /*
556 * Find the number of uncached blocks so we can do a
557 * single read request
558 */
559 for (i=1; i < count; i++)
560 if (find_cached_block(data, block+i, &reuse[i]))
561 break;
562#ifdef DEBUG
563 printf("Reading %d blocks starting at %lu\n", i, block);
564#endif
565 if ((retval = raw_read_blk(channel, data, block, i, cp)))
566 return retval;
567
568 /* Save the results in the cache */
569 for (j=0; j < i; j++) {
570 count--;
571 cache = reuse[j];
572 reuse_cache(channel, data, cache, block++);
573 memcpy(cache->buf, cp, channel->block_size);
574 cp += channel->block_size;
575 }
576 }
577 return 0;
578#endif /* NO_IO_CACHE */
579}
580
581static errcode_t unix_write_blk(io_channel channel, unsigned long block,
582 int count, const void *buf)
583{
584 struct unix_private_data *data;
585 struct unix_cache *cache, *reuse;
586 errcode_t retval = 0;
587 const char *cp;
588 int writethrough;
589
590 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
591 data = (struct unix_private_data *) channel->private_data;
592 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
593
594#ifdef NO_IO_CACHE
595 return raw_write_blk(channel, data, block, count, buf);
596#else
597 /*
598 * If we're doing an odd-sized write or a very large write,
599 * flush out the cache completely and then do a direct write.
600 */
601 if (count < 0 || count > WRITE_DIRECT_SIZE) {
602 if ((retval = flush_cached_blocks(channel, data, 1)))
603 return retval;
604 return raw_write_blk(channel, data, block, count, buf);
605 }
606
607 /*
608 * For a moderate-sized multi-block write, first force a write
609 * if we're in write-through cache mode, and then fill the
610 * cache with the blocks.
611 */
612 writethrough = channel->flags & CHANNEL_FLAGS_WRITETHROUGH;
613 if (writethrough)
614 retval = raw_write_blk(channel, data, block, count, buf);
615
616 cp = buf;
617 while (count > 0) {
618 cache = find_cached_block(data, block, &reuse);
619 if (!cache) {
620 cache = reuse;
621 reuse_cache(channel, data, cache, block);
622 }
623 memcpy(cache->buf, cp, channel->block_size);
624 cache->dirty = !writethrough;
625 count--;
626 block++;
627 cp += channel->block_size;
628 }
629 return retval;
630#endif /* NO_IO_CACHE */
631}
632
633static errcode_t unix_write_byte(io_channel channel, unsigned long offset,
634 int size, const void *buf)
635{
636 struct unix_private_data *data;
637 errcode_t retval = 0;
638 ssize_t actual;
639
640 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
641 data = (struct unix_private_data *) channel->private_data;
642 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
643
644#ifndef NO_IO_CACHE
645 /*
646 * Flush out the cache completely
647 */
648 if ((retval = flush_cached_blocks(channel, data, 1)))
649 return retval;
650#endif
651
652 if (lseek(data->dev, offset + data->offset, SEEK_SET) < 0)
653 return errno;
654
655 actual = write(data->dev, buf, size);
656 if (actual != size)
657 return EXT2_ET_SHORT_WRITE;
658
659 return 0;
660}
661
662/*
663 * Flush data buffers to disk.
664 */
665static errcode_t unix_flush(io_channel channel)
666{
667 struct unix_private_data *data;
668 errcode_t retval = 0;
669
670 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
671 data = (struct unix_private_data *) channel->private_data;
672 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
673
674#ifndef NO_IO_CACHE
675 retval = flush_cached_blocks(channel, data, 0);
676#endif
677 fsync(data->dev);
678 return retval;
679}
680
681static errcode_t unix_set_option(io_channel channel, const char *option,
682 const char *arg)
683{
684 struct unix_private_data *data;
685 unsigned long tmp;
686 char *end;
687
688 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
689 data = (struct unix_private_data *) channel->private_data;
690 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
691
692 if (!strcmp(option, "offset")) {
693 if (!arg)
694 return EXT2_ET_INVALID_ARGUMENT;
695
696 tmp = strtoul(arg, &end, 0);
697 if (*end)
698 return EXT2_ET_INVALID_ARGUMENT;
699 data->offset = tmp;
700 return 0;
701 }
702 return EXT2_ET_INVALID_ARGUMENT;
703}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/unlink.c b/e2fsprogs/old_e2fsprogs/ext2fs/unlink.c
deleted file mode 100644
index 71a9ffcb9..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/unlink.c
+++ /dev/null
@@ -1,99 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * unlink.c --- delete links in a ext2fs directory
4 *
5 * Copyright (C) 1993, 1994, 1997 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18
19#include "ext2_fs.h"
20#include "ext2fs.h"
21
22struct link_struct {
23 const char *name;
24 int namelen;
25 ext2_ino_t inode;
26 int flags;
27 struct ext2_dir_entry *prev;
28 int done;
29};
30
31#ifdef __TURBOC__
32# pragma argsused
33#endif
34static int unlink_proc(struct ext2_dir_entry *dirent,
35 int offset EXT2FS_ATTR((unused)),
36 int blocksize EXT2FS_ATTR((unused)),
37 char *buf EXT2FS_ATTR((unused)),
38 void *priv_data)
39{
40 struct link_struct *ls = (struct link_struct *) priv_data;
41 struct ext2_dir_entry *prev;
42
43 prev = ls->prev;
44 ls->prev = dirent;
45
46 if (ls->name) {
47 if ((dirent->name_len & 0xFF) != ls->namelen)
48 return 0;
49 if (strncmp(ls->name, dirent->name, dirent->name_len & 0xFF))
50 return 0;
51 }
52 if (ls->inode) {
53 if (dirent->inode != ls->inode)
54 return 0;
55 } else {
56 if (!dirent->inode)
57 return 0;
58 }
59
60 if (prev)
61 prev->rec_len += dirent->rec_len;
62 else
63 dirent->inode = 0;
64 ls->done++;
65 return DIRENT_ABORT|DIRENT_CHANGED;
66}
67
68#ifdef __TURBOC__
69 #pragma argsused
70#endif
71errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir,
72 const char *name, ext2_ino_t ino,
73 int flags EXT2FS_ATTR((unused)))
74{
75 errcode_t retval;
76 struct link_struct ls;
77
78 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
79
80 if (!name && !ino)
81 return EXT2_ET_INVALID_ARGUMENT;
82
83 if (!(fs->flags & EXT2_FLAG_RW))
84 return EXT2_ET_RO_FILSYS;
85
86 ls.name = name;
87 ls.namelen = name ? strlen(name) : 0;
88 ls.inode = ino;
89 ls.flags = 0;
90 ls.done = 0;
91 ls.prev = 0;
92
93 retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY,
94 0, unlink_proc, &ls);
95 if (retval)
96 return retval;
97
98 return (ls.done) ? 0 : EXT2_ET_DIR_NO_SPACE;
99}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/valid_blk.c b/e2fsprogs/old_e2fsprogs/ext2fs/valid_blk.c
deleted file mode 100644
index 8ed77ae2a..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/valid_blk.c
+++ /dev/null
@@ -1,57 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * valid_blk.c --- does the inode have valid blocks?
4 *
5 * Copyright 1997 by Theodore Ts'o
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 *
12 */
13
14#include <stdio.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#include <string.h>
19#include <time.h>
20
21#include "ext2_fs.h"
22#include "ext2fs.h"
23
24/*
25 * This function returns 1 if the inode's block entries actually
26 * contain block entries.
27 */
28int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode)
29{
30 /*
31 * Only directories, regular files, and some symbolic links
32 * have valid block entries.
33 */
34 if (!LINUX_S_ISDIR(inode->i_mode) && !LINUX_S_ISREG(inode->i_mode) &&
35 !LINUX_S_ISLNK(inode->i_mode))
36 return 0;
37
38 /*
39 * If the symbolic link is a "fast symlink", then the symlink
40 * target is stored in the block entries.
41 */
42 if (LINUX_S_ISLNK (inode->i_mode)) {
43 if (inode->i_file_acl == 0) {
44 /* With no EA block, we can rely on i_blocks */
45 if (inode->i_blocks == 0)
46 return 0;
47 } else {
48 /* With an EA block, life gets more tricky */
49 if (inode->i_size >= EXT2_N_BLOCKS*4)
50 return 1; /* definitely using i_block[] */
51 if (inode->i_size > 4 && inode->i_block[1] == 0)
52 return 1; /* definitely using i_block[] */
53 return 0; /* Probably a fast symlink */
54 }
55 }
56 return 1;
57}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/version.c b/e2fsprogs/old_e2fsprogs/ext2fs/version.c
deleted file mode 100644
index d2981e867..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/version.c
+++ /dev/null
@@ -1,51 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * version.c --- Return the version of the ext2 library
4 *
5 * Copyright (C) 1997 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#if HAVE_UNISTD_H
14#include <unistd.h>
15#endif
16#include <string.h>
17#include <stdio.h>
18#include <ctype.h>
19
20#include "ext2_fs.h"
21#include "ext2fs.h"
22
23static const char *lib_version = E2FSPROGS_VERSION;
24static const char *lib_date = E2FSPROGS_DATE;
25
26int ext2fs_parse_version_string(const char *ver_string)
27{
28 const char *cp;
29 int version = 0;
30
31 for (cp = ver_string; *cp; cp++) {
32 if (*cp == '.')
33 continue;
34 if (!isdigit(*cp))
35 break;
36 version = (version * 10) + (*cp - '0');
37 }
38 return version;
39}
40
41
42int ext2fs_get_library_version(const char **ver_string,
43 const char **date_string)
44{
45 if (ver_string)
46 *ver_string = lib_version;
47 if (date_string)
48 *date_string = lib_date;
49
50 return ext2fs_parse_version_string(lib_version);
51}
diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/write_bb_file.c b/e2fsprogs/old_e2fsprogs/ext2fs/write_bb_file.c
deleted file mode 100644
index 5b19eefa0..000000000
--- a/e2fsprogs/old_e2fsprogs/ext2fs/write_bb_file.c
+++ /dev/null
@@ -1,35 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * write_bb_file.c --- write a list of bad blocks to a FILE *
4 *
5 * Copyright (C) 1994, 1995 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14
15#include "ext2_fs.h"
16#include "ext2fs.h"
17
18errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list,
19 unsigned int flags EXT2FS_ATTR((unused)),
20 FILE *f)
21{
22 badblocks_iterate bb_iter;
23 blk_t blk;
24 errcode_t retval;
25
26 retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter);
27 if (retval)
28 return retval;
29
30 while (ext2fs_badblocks_list_iterate(bb_iter, &blk)) {
31 fprintf(f, "%d\n", blk);
32 }
33 ext2fs_badblocks_list_iterate_end(bb_iter);
34 return 0;
35}
diff --git a/e2fsprogs/old_e2fsprogs/fsck.c b/e2fsprogs/old_e2fsprogs/fsck.c
deleted file mode 100644
index 87874ce71..000000000
--- a/e2fsprogs/old_e2fsprogs/fsck.c
+++ /dev/null
@@ -1,1371 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * pfsck --- A generic, parallelizing front-end for the fsck program.
4 * It will automatically try to run fsck programs in parallel if the
5 * devices are on separate spindles. It is based on the same ideas as
6 * the generic front end for fsck by David Engel and Fred van Kempen,
7 * but it has been completely rewritten from scratch to support
8 * parallel execution.
9 *
10 * Written by Theodore Ts'o, <tytso@mit.edu>
11 *
12 * Miquel van Smoorenburg (miquels@drinkel.ow.org) 20-Oct-1994:
13 * o Changed -t fstype to behave like with mount when -A (all file
14 * systems) or -M (like mount) is specified.
15 * o fsck looks if it can find the fsck.type program to decide
16 * if it should ignore the fs type. This way more fsck programs
17 * can be added without changing this front-end.
18 * o -R flag skip root file system.
19 *
20 * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
21 * 2001, 2002, 2003, 2004, 2005 by Theodore Ts'o.
22 *
23 * Licensed under GPLv2, see file LICENSE in this source tree.
24 */
25
26#include <sys/types.h>
27#include <sys/wait.h>
28#include <sys/stat.h>
29#include <limits.h>
30#include <stdio.h>
31#include <ctype.h>
32#include <string.h>
33#include <time.h>
34#include <stdlib.h>
35#include <errno.h>
36#include <paths.h>
37#include <unistd.h>
38#include <errno.h>
39#include <signal.h>
40
41#include "fsck.h"
42#include "blkid/blkid.h"
43
44#include "e2fsbb.h"
45
46#include "libbb.h"
47
48#ifndef _PATH_MNTTAB
49#define _PATH_MNTTAB "/etc/fstab"
50#endif
51
52/*
53 * fsck.h
54 */
55
56#ifndef DEFAULT_FSTYPE
57#define DEFAULT_FSTYPE "ext2"
58#endif
59
60#define MAX_DEVICES 32
61#define MAX_ARGS 32
62
63/*
64 * Internal structure for mount tabel entries.
65 */
66
67struct fs_info {
68 char *device;
69 char *mountpt;
70 char *type;
71 char *opts;
72 int freq;
73 int passno;
74 int flags;
75 struct fs_info *next;
76};
77
78#define FLAG_DONE 1
79#define FLAG_PROGRESS 2
80
81/*
82 * Structure to allow exit codes to be stored
83 */
84struct fsck_instance {
85 int pid;
86 int flags;
87 int exit_status;
88 time_t start_time;
89 char * prog;
90 char * type;
91 char * device;
92 char * base_device;
93 struct fsck_instance *next;
94};
95
96/*
97 * base_device.c
98 *
99 * Return the "base device" given a particular device; this is used to
100 * assure that we only fsck one partition on a particular drive at any
101 * one time. Otherwise, the disk heads will be seeking all over the
102 * place. If the base device cannot be determined, return NULL.
103 *
104 * The base_device() function returns an allocated string which must
105 * be freed.
106 *
107 */
108
109
110#ifdef CONFIG_FEATURE_DEVFS
111/*
112 * Required for the uber-silly devfs /dev/ide/host1/bus2/target3/lun3
113 * pathames.
114 */
115static const char *const devfs_hier[] = {
116 "host", "bus", "target", "lun", 0
117};
118#endif
119
120static char *base_device(const char *device)
121{
122 char *str, *cp;
123#ifdef CONFIG_FEATURE_DEVFS
124 const char *const *hier;
125 const char *disk;
126 int len;
127#endif
128
129 cp = str = xstrdup(device);
130
131 /* Skip over /dev/; if it's not present, give up. */
132 if (strncmp(cp, "/dev/", 5) != 0)
133 goto errout;
134 cp += 5;
135
136 /*
137 * For md devices, we treat them all as if they were all
138 * on one disk, since we don't know how to parallelize them.
139 */
140 if (cp[0] == 'm' && cp[1] == 'd') {
141 *(cp+2) = 0;
142 return str;
143 }
144
145 /* Handle DAC 960 devices */
146 if (strncmp(cp, "rd/", 3) == 0) {
147 cp += 3;
148 if (cp[0] != 'c' || cp[2] != 'd' ||
149 !isdigit(cp[1]) || !isdigit(cp[3]))
150 goto errout;
151 *(cp+4) = 0;
152 return str;
153 }
154
155 /* Now let's handle /dev/hd* and /dev/sd* devices.... */
156 if ((cp[0] == 'h' || cp[0] == 's') && (cp[1] == 'd')) {
157 cp += 2;
158 /* If there's a single number after /dev/hd, skip it */
159 if (isdigit(*cp))
160 cp++;
161 /* What follows must be an alpha char, or give up */
162 if (!isalpha(*cp))
163 goto errout;
164 *(cp + 1) = 0;
165 return str;
166 }
167
168#ifdef CONFIG_FEATURE_DEVFS
169 /* Now let's handle devfs (ugh) names */
170 len = 0;
171 if (strncmp(cp, "ide/", 4) == 0)
172 len = 4;
173 if (strncmp(cp, "scsi/", 5) == 0)
174 len = 5;
175 if (len) {
176 cp += len;
177 /*
178 * Now we proceed down the expected devfs hierarchy.
179 * i.e., .../host1/bus2/target3/lun4/...
180 * If we don't find the expected token, followed by
181 * some number of digits at each level, abort.
182 */
183 for (hier = devfs_hier; *hier; hier++) {
184 len = strlen(*hier);
185 if (strncmp(cp, *hier, len) != 0)
186 goto errout;
187 cp += len;
188 while (*cp != '/' && *cp != 0) {
189 if (!isdigit(*cp))
190 goto errout;
191 cp++;
192 }
193 cp++;
194 }
195 *(cp - 1) = 0;
196 return str;
197 }
198
199 /* Now handle devfs /dev/disc or /dev/disk names */
200 disk = 0;
201 if (strncmp(cp, "discs/", 6) == 0)
202 disk = "disc";
203 else if (strncmp(cp, "disks/", 6) == 0)
204 disk = "disk";
205 if (disk) {
206 cp += 6;
207 if (strncmp(cp, disk, 4) != 0)
208 goto errout;
209 cp += 4;
210 while (*cp != '/' && *cp != 0) {
211 if (!isdigit(*cp))
212 goto errout;
213 cp++;
214 }
215 *cp = 0;
216 return str;
217 }
218#endif
219
220errout:
221 free(str);
222 return NULL;
223}
224
225
226static const char *const ignored_types[] = {
227 "ignore",
228 "iso9660",
229 "nfs",
230 "proc",
231 "sw",
232 "swap",
233 "tmpfs",
234 "devpts",
235 NULL
236};
237
238static const char *const really_wanted[] = {
239 "minix",
240 "ext2",
241 "ext3",
242 "jfs",
243 "reiserfs",
244 "xiafs",
245 "xfs",
246 NULL
247};
248
249#define BASE_MD "/dev/md"
250
251/*
252 * Global variables for options
253 */
254static char *devices[MAX_DEVICES];
255static char *args[MAX_ARGS];
256static int num_devices, num_args;
257
258static int verbose;
259static int doall;
260static int noexecute;
261static int serialize;
262static int skip_root;
263static int like_mount;
264static int notitle;
265static int parallel_root;
266static int progress;
267static int progress_fd;
268static int force_all_parallel;
269static int num_running;
270static int max_running;
271static volatile int cancel_requested;
272static int kill_sent;
273static char *fstype;
274static struct fs_info *filesys_info, *filesys_last;
275static struct fsck_instance *instance_list;
276static char *fsck_path;
277static blkid_cache cache;
278
279static char *string_copy(const char *s)
280{
281 char *ret;
282
283 if (!s)
284 return 0;
285 ret = xstrdup(s);
286 return ret;
287}
288
289static int string_to_int(const char *s)
290{
291 long l;
292 char *p;
293
294 l = strtol(s, &p, 0);
295 if (*p || l == LONG_MIN || l == LONG_MAX || l < 0 || l > INT_MAX)
296 return -1;
297 else
298 return (int) l;
299}
300
301static char *skip_over_blank(char *cp)
302{
303 while (*cp && isspace(*cp))
304 cp++;
305 return cp;
306}
307
308static char *skip_over_word(char *cp)
309{
310 while (*cp && !isspace(*cp))
311 cp++;
312 return cp;
313}
314
315static void strip_line(char *line)
316{
317 char *p;
318
319 while (*line) {
320 p = line + strlen(line) - 1;
321 if ((*p == '\n') || (*p == '\r'))
322 *p = 0;
323 else
324 break;
325 }
326}
327
328static char *parse_word(char **buf)
329{
330 char *word, *next;
331
332 word = *buf;
333 if (*word == 0)
334 return 0;
335
336 word = skip_over_blank(word);
337 next = skip_over_word(word);
338 if (*next)
339 *next++ = 0;
340 *buf = next;
341 return word;
342}
343
344static void parse_escape(char *word)
345{
346 char *q, c;
347 const char *p;
348
349 if (!word)
350 return;
351
352 strcpy_and_process_escape_sequences(word, word);
353}
354
355static void free_instance(struct fsck_instance *i)
356{
357 free(i->prog);
358 free(i->device);
359 free(i->base_device);
360 free(i);
361}
362
363static struct fs_info *create_fs_device(const char *device, const char *mntpnt,
364 const char *type, const char *opts,
365 int freq, int passno)
366{
367 struct fs_info *fs;
368
369 fs = xmalloc(sizeof(struct fs_info));
370
371 fs->device = string_copy(device);
372 fs->mountpt = string_copy(mntpnt);
373 fs->type = string_copy(type);
374 fs->opts = string_copy(opts ? opts : "");
375 fs->freq = freq;
376 fs->passno = passno;
377 fs->flags = 0;
378 fs->next = NULL;
379
380 if (!filesys_info)
381 filesys_info = fs;
382 else
383 filesys_last->next = fs;
384 filesys_last = fs;
385
386 return fs;
387}
388
389
390
391static int parse_fstab_line(char *line, struct fs_info **ret_fs)
392{
393 char *dev, *device, *mntpnt, *type, *opts, *freq, *passno, *cp;
394 struct fs_info *fs;
395
396 *ret_fs = 0;
397 strip_line(line);
398 if ((cp = strchr(line, '#')))
399 *cp = 0; /* Ignore everything after the comment char */
400 cp = line;
401
402 device = parse_word(&cp);
403 mntpnt = parse_word(&cp);
404 type = parse_word(&cp);
405 opts = parse_word(&cp);
406 freq = parse_word(&cp);
407 passno = parse_word(&cp);
408
409 if (!device)
410 return 0; /* Allow blank lines */
411
412 if (!mntpnt || !type)
413 return -1;
414
415 parse_escape(device);
416 parse_escape(mntpnt);
417 parse_escape(type);
418 parse_escape(opts);
419 parse_escape(freq);
420 parse_escape(passno);
421
422 dev = blkid_get_devname(cache, device, NULL);
423 if (dev)
424 device = dev;
425
426 if (strchr(type, ','))
427 type = 0;
428
429 fs = create_fs_device(device, mntpnt, type ? type : "auto", opts,
430 freq ? atoi(freq) : -1,
431 passno ? atoi(passno) : -1);
432 free(dev);
433
434 if (!fs)
435 return -1;
436 *ret_fs = fs;
437 return 0;
438}
439
440static void interpret_type(struct fs_info *fs)
441{
442 char *t;
443
444 if (strcmp(fs->type, "auto") != 0)
445 return;
446 t = blkid_get_tag_value(cache, "TYPE", fs->device);
447 if (t) {
448 free(fs->type);
449 fs->type = t;
450 }
451}
452
453/*
454 * Load the filesystem database from /etc/fstab
455 */
456static void load_fs_info(const char *filename)
457{
458 FILE *f;
459 char buf[1024];
460 int lineno = 0;
461 int old_fstab = 1;
462 struct fs_info *fs;
463
464 if ((f = fopen_or_warn(filename, "r")) == NULL) {
465 return;
466 }
467 while (!feof(f)) {
468 lineno++;
469 if (!fgets(buf, sizeof(buf), f))
470 break;
471 buf[sizeof(buf)-1] = 0;
472 if (parse_fstab_line(buf, &fs) < 0) {
473 bb_error_msg("WARNING: bad format "
474 "on line %d of %s\n", lineno, filename);
475 continue;
476 }
477 if (!fs)
478 continue;
479 if (fs->passno < 0)
480 fs->passno = 0;
481 else
482 old_fstab = 0;
483 }
484
485 fclose(f);
486
487 if (old_fstab) {
488 fputs("\007\007\007"
489 "WARNING: Your /etc/fstab does not contain the fsck passno\n"
490 " field. I will kludge around things for you, but you\n"
491 " should fix your /etc/fstab file as soon as you can.\n\n", stderr);
492
493 for (fs = filesys_info; fs; fs = fs->next) {
494 fs->passno = 1;
495 }
496 }
497}
498
499/* Lookup filesys in /etc/fstab and return the corresponding entry. */
500static struct fs_info *lookup(char *filesys)
501{
502 struct fs_info *fs;
503
504 /* No filesys name given. */
505 if (filesys == NULL)
506 return NULL;
507
508 for (fs = filesys_info; fs; fs = fs->next) {
509 if (!strcmp(filesys, fs->device) ||
510 (fs->mountpt && !strcmp(filesys, fs->mountpt)))
511 break;
512 }
513
514 return fs;
515}
516
517/* Find fsck program for a given fs type. */
518static char *find_fsck(char *type)
519{
520 char *s;
521 const char *tpl;
522 char *p = string_copy(fsck_path);
523 struct stat st;
524
525 /* Are we looking for a program or just a type? */
526 tpl = (strncmp(type, "fsck.", 5) ? "%s/fsck.%s" : "%s/%s");
527
528 for (s = strtok(p, ":"); s; s = strtok(NULL, ":")) {
529 s = xasprintf(tpl, s, type);
530 if (stat(s, &st) == 0) break;
531 free(s);
532 }
533 free(p);
534 return s;
535}
536
537static int progress_active(void)
538{
539 struct fsck_instance *inst;
540
541 for (inst = instance_list; inst; inst = inst->next) {
542 if (inst->flags & FLAG_DONE)
543 continue;
544 if (inst->flags & FLAG_PROGRESS)
545 return 1;
546 }
547 return 0;
548}
549
550/*
551 * Execute a particular fsck program, and link it into the list of
552 * child processes we are waiting for.
553 */
554static int execute(const char *type, const char *device, const char *mntpt,
555 int interactive)
556{
557 char *s, *argv[80];
558 char *prog;
559 int argc, i;
560 struct fsck_instance *inst, *p;
561 pid_t pid;
562
563 inst = xzalloc(sizeof(struct fsck_instance));
564
565 prog = xasprintf("fsck.%s", type);
566 argv[0] = prog;
567 argc = 1;
568
569 for (i=0; i <num_args; i++)
570 argv[argc++] = string_copy(args[i]);
571
572 if (progress && !progress_active()) {
573 if ((strcmp(type, "ext2") == 0) ||
574 (strcmp(type, "ext3") == 0)) {
575 char tmp[80];
576 snprintf(tmp, 80, "-C%d", progress_fd);
577 argv[argc++] = string_copy(tmp);
578 inst->flags |= FLAG_PROGRESS;
579 }
580 }
581
582 argv[argc++] = string_copy(device);
583 argv[argc] = 0;
584
585 s = find_fsck(prog);
586 if (s == NULL) {
587 bb_error_msg("%s: not found", prog);
588 return ENOENT;
589 }
590
591 if (verbose || noexecute) {
592 printf("[%s (%d) -- %s] ", s, num_running,
593 mntpt ? mntpt : device);
594 for (i=0; i < argc; i++)
595 printf("%s ", argv[i]);
596 bb_putchar('\n');
597 }
598
599 /* Fork and execute the correct program. */
600 if (noexecute)
601 pid = -1;
602 else if ((pid = fork()) < 0) {
603 perror("vfork"+1);
604 return errno;
605 } else if (pid == 0) {
606 if (!interactive)
607 close(0);
608 (void) execv(s, argv);
609 bb_simple_perror_msg_and_die(argv[0]);
610 }
611
612 for (i = 1; i < argc; i++)
613 free(argv[i]);
614
615 free(s);
616 inst->pid = pid;
617 inst->prog = prog;
618 inst->type = string_copy(type);
619 inst->device = string_copy(device);
620 inst->base_device = base_device(device);
621 inst->start_time = time(0);
622 inst->next = NULL;
623
624 /*
625 * Find the end of the list, so we add the instance on at the end.
626 */
627 for (p = instance_list; p && p->next; p = p->next);
628
629 if (p)
630 p->next = inst;
631 else
632 instance_list = inst;
633
634 return 0;
635}
636
637/*
638 * Send a signal to all outstanding fsck child processes
639 */
640static int kill_all(int signum)
641{
642 struct fsck_instance *inst;
643 int n = 0;
644
645 for (inst = instance_list; inst; inst = inst->next) {
646 if (inst->flags & FLAG_DONE)
647 continue;
648 kill(inst->pid, signum);
649 n++;
650 }
651 return n;
652}
653
654/*
655 * Wait for one child process to exit; when it does, unlink it from
656 * the list of executing child processes, and return it.
657 */
658static struct fsck_instance *wait_one(int flags)
659{
660 int status;
661 int sig;
662 struct fsck_instance *inst, *inst2, *prev;
663 pid_t pid;
664
665 if (!instance_list)
666 return NULL;
667
668 if (noexecute) {
669 inst = instance_list;
670 prev = 0;
671#ifdef RANDOM_DEBUG
672 while (inst->next && (random() & 1)) {
673 prev = inst;
674 inst = inst->next;
675 }
676#endif
677 inst->exit_status = 0;
678 goto ret_inst;
679 }
680
681 /*
682 * gcc -Wall fails saving throw against stupidity
683 * (inst and prev are thought to be uninitialized variables)
684 */
685 inst = prev = NULL;
686
687 do {
688 pid = waitpid(-1, &status, flags);
689 if (cancel_requested && !kill_sent) {
690 kill_all(SIGTERM);
691 kill_sent++;
692 }
693 if ((pid == 0) && (flags & WNOHANG))
694 return NULL;
695 if (pid < 0) {
696 if ((errno == EINTR) || (errno == EAGAIN))
697 continue;
698 if (errno == ECHILD) {
699 bb_error_msg("wait: no more child process?!?");
700 return NULL;
701 }
702 perror("wait");
703 continue;
704 }
705 for (prev = 0, inst = instance_list;
706 inst;
707 prev = inst, inst = inst->next) {
708 if (inst->pid == pid)
709 break;
710 }
711 } while (!inst);
712
713 if (WIFEXITED(status))
714 status = WEXITSTATUS(status);
715 else if (WIFSIGNALED(status)) {
716 sig = WTERMSIG(status);
717 if (sig == SIGINT) {
718 status = EXIT_UNCORRECTED;
719 } else {
720 printf("Warning... %s for device %s exited "
721 "with signal %d.\n",
722 inst->prog, inst->device, sig);
723 status = EXIT_ERROR;
724 }
725 } else {
726 printf("%s %s: status is %x, should never happen.\n",
727 inst->prog, inst->device, status);
728 status = EXIT_ERROR;
729 }
730 inst->exit_status = status;
731 if (progress && (inst->flags & FLAG_PROGRESS) &&
732 !progress_active()) {
733 for (inst2 = instance_list; inst2; inst2 = inst2->next) {
734 if (inst2->flags & FLAG_DONE)
735 continue;
736 if (strcmp(inst2->type, "ext2") &&
737 strcmp(inst2->type, "ext3"))
738 continue;
739 /*
740 * If we've just started the fsck, wait a tiny
741 * bit before sending the kill, to give it
742 * time to set up the signal handler
743 */
744 if (inst2->start_time < time(0)+2) {
745 if (fork() == 0) {
746 sleep(1);
747 kill(inst2->pid, SIGUSR1);
748 exit(0);
749 }
750 } else
751 kill(inst2->pid, SIGUSR1);
752 inst2->flags |= FLAG_PROGRESS;
753 break;
754 }
755 }
756ret_inst:
757 if (prev)
758 prev->next = inst->next;
759 else
760 instance_list = inst->next;
761 if (verbose > 1)
762 printf("Finished with %s (exit status %d)\n",
763 inst->device, inst->exit_status);
764 num_running--;
765 return inst;
766}
767
768#define FLAG_WAIT_ALL 0
769#define FLAG_WAIT_ATLEAST_ONE 1
770/*
771 * Wait until all executing child processes have exited; return the
772 * logical OR of all of their exit code values.
773 */
774static int wait_many(int flags)
775{
776 struct fsck_instance *inst;
777 int global_status = 0;
778 int wait_flags = 0;
779
780 while ((inst = wait_one(wait_flags))) {
781 global_status |= inst->exit_status;
782 free_instance(inst);
783#ifdef RANDOM_DEBUG
784 if (noexecute && (flags & WNOHANG) && !(random() % 3))
785 break;
786#endif
787 if (flags & FLAG_WAIT_ATLEAST_ONE)
788 wait_flags = WNOHANG;
789 }
790 return global_status;
791}
792
793/*
794 * Run the fsck program on a particular device
795 *
796 * If the type is specified using -t, and it isn't prefixed with "no"
797 * (as in "noext2") and only one filesystem type is specified, then
798 * use that type regardless of what is specified in /etc/fstab.
799 *
800 * If the type isn't specified by the user, then use either the type
801 * specified in /etc/fstab, or DEFAULT_FSTYPE.
802 */
803static void fsck_device(struct fs_info *fs, int interactive)
804{
805 const char *type;
806 int retval;
807
808 interpret_type(fs);
809
810 if (strcmp(fs->type, "auto") != 0)
811 type = fs->type;
812 else if (fstype && strncmp(fstype, "no", 2) &&
813 strncmp(fstype, "opts=", 5) && strncmp(fstype, "loop", 4) &&
814 !strchr(fstype, ','))
815 type = fstype;
816 else
817 type = DEFAULT_FSTYPE;
818
819 num_running++;
820 retval = execute(type, fs->device, fs->mountpt, interactive);
821 if (retval) {
822 bb_error_msg("error %d while executing fsck.%s for %s",
823 retval, type, fs->device);
824 num_running--;
825 }
826}
827
828
829/*
830 * Deal with the fsck -t argument.
831 */
832struct fs_type_compile {
833 char **list;
834 int *type;
835 int negate;
836} fs_type_compiled;
837
838#define FS_TYPE_NORMAL 0
839#define FS_TYPE_OPT 1
840#define FS_TYPE_NEGOPT 2
841
842static const char fs_type_syntax_error[] =
843"Either all or none of the filesystem types passed to -t must be prefixed\n"
844 "with 'no' or '!'.";
845
846static void compile_fs_type(char *fs_type, struct fs_type_compile *cmp)
847{
848 char *cp, *list, *s;
849 int num = 2;
850 int negate, first_negate = 1;
851
852 if (fs_type) {
853 for (cp=fs_type; *cp; cp++) {
854 if (*cp == ',')
855 num++;
856 }
857 }
858
859 cmp->list = xzalloc(num * sizeof(char *));
860 cmp->type = xzalloc(num * sizeof(int));
861 cmp->negate = 0;
862
863 if (!fs_type)
864 return;
865
866 list = string_copy(fs_type);
867 num = 0;
868 s = strtok(list, ",");
869 while (s) {
870 negate = 0;
871 if (strncmp(s, "no", 2) == 0) {
872 s += 2;
873 negate = 1;
874 } else if (*s == '!') {
875 s++;
876 negate = 1;
877 }
878 if (strcmp(s, "loop") == 0)
879 /* loop is really short-hand for opts=loop */
880 goto loop_special_case;
881 else if (strncmp(s, "opts=", 5) == 0) {
882 s += 5;
883 loop_special_case:
884 cmp->type[num] = negate ? FS_TYPE_NEGOPT : FS_TYPE_OPT;
885 } else {
886 if (first_negate) {
887 cmp->negate = negate;
888 first_negate = 0;
889 }
890 if ((negate && !cmp->negate) ||
891 (!negate && cmp->negate)) {
892 bb_error_msg_and_die("%s", fs_type_syntax_error);
893 }
894 }
895 cmp->list[num++] = string_copy(s);
896 s = strtok(NULL, ",");
897 }
898 free(list);
899}
900
901/*
902 * This function returns true if a particular option appears in a
903 * comma-delimited options list
904 */
905static int opt_in_list(char *opt, char *optlist)
906{
907 char *list, *s;
908
909 if (!optlist)
910 return 0;
911 list = string_copy(optlist);
912
913 s = strtok(list, ",");
914 while (s) {
915 if (strcmp(s, opt) == 0) {
916 free(list);
917 return 1;
918 }
919 s = strtok(NULL, ",");
920 }
921 free(list);
922 return 0;
923}
924
925/* See if the filesystem matches the criteria given by the -t option */
926static int fs_match(struct fs_info *fs, struct fs_type_compile *cmp)
927{
928 int n, ret = 0, checked_type = 0;
929 char *cp;
930
931 if (cmp->list == 0 || cmp->list[0] == 0)
932 return 1;
933
934 for (n=0; (cp = cmp->list[n]); n++) {
935 switch (cmp->type[n]) {
936 case FS_TYPE_NORMAL:
937 checked_type++;
938 if (strcmp(cp, fs->type) == 0) {
939 ret = 1;
940 }
941 break;
942 case FS_TYPE_NEGOPT:
943 if (opt_in_list(cp, fs->opts))
944 return 0;
945 break;
946 case FS_TYPE_OPT:
947 if (!opt_in_list(cp, fs->opts))
948 return 0;
949 break;
950 }
951 }
952 if (checked_type == 0)
953 return 1;
954 return (cmp->negate ? !ret : ret);
955}
956
957/* Check if we should ignore this filesystem. */
958static int ignore(struct fs_info *fs)
959{
960 int wanted;
961 char *s;
962
963 /*
964 * If the pass number is 0, ignore it.
965 */
966 if (fs->passno == 0)
967 return 1;
968
969 interpret_type(fs);
970
971 /*
972 * If a specific fstype is specified, and it doesn't match,
973 * ignore it.
974 */
975 if (!fs_match(fs, &fs_type_compiled)) return 1;
976
977 /* Are we ignoring this type? */
978 if (index_in_str_array(ignored_types, fs->type) >= 0)
979 return 1;
980
981 /* Do we really really want to check this fs? */
982 wanted = index_in_str_array(really_wanted, fs->type) >= 0;
983
984 /* See if the <fsck.fs> program is available. */
985 s = find_fsck(fs->type);
986 if (s == NULL) {
987 if (wanted)
988 bb_error_msg("can't check %s: fsck.%s not found",
989 fs->device, fs->type);
990 return 1;
991 }
992 free(s);
993
994 /* We can and want to check this file system type. */
995 return 0;
996}
997
998/*
999 * Returns TRUE if a partition on the same disk is already being
1000 * checked.
1001 */
1002static int device_already_active(char *device)
1003{
1004 struct fsck_instance *inst;
1005 char *base;
1006
1007 if (force_all_parallel)
1008 return 0;
1009
1010#ifdef BASE_MD
1011 /* Don't check a soft raid disk with any other disk */
1012 if (instance_list &&
1013 (!strncmp(instance_list->device, BASE_MD, sizeof(BASE_MD)-1) ||
1014 !strncmp(device, BASE_MD, sizeof(BASE_MD)-1)))
1015 return 1;
1016#endif
1017
1018 base = base_device(device);
1019 /*
1020 * If we don't know the base device, assume that the device is
1021 * already active if there are any fsck instances running.
1022 */
1023 if (!base)
1024 return (instance_list != 0);
1025 for (inst = instance_list; inst; inst = inst->next) {
1026 if (!inst->base_device || !strcmp(base, inst->base_device)) {
1027 free(base);
1028 return 1;
1029 }
1030 }
1031 free(base);
1032 return 0;
1033}
1034
1035/* Check all file systems, using the /etc/fstab table. */
1036static int check_all(void)
1037{
1038 struct fs_info *fs = NULL;
1039 int status = EXIT_OK;
1040 int not_done_yet = 1;
1041 int passno = 1;
1042 int pass_done;
1043
1044 if (verbose)
1045 fputs("Checking all file systems.\n", stdout);
1046
1047 /*
1048 * Do an initial scan over the filesystem; mark filesystems
1049 * which should be ignored as done, and resolve any "auto"
1050 * filesystem types (done as a side-effect of calling ignore()).
1051 */
1052 for (fs = filesys_info; fs; fs = fs->next) {
1053 if (ignore(fs))
1054 fs->flags |= FLAG_DONE;
1055 }
1056
1057 /*
1058 * Find and check the root filesystem.
1059 */
1060 if (!parallel_root) {
1061 for (fs = filesys_info; fs; fs = fs->next) {
1062 if (LONE_CHAR(fs->mountpt, '/'))
1063 break;
1064 }
1065 if (fs) {
1066 if (!skip_root && !ignore(fs)) {
1067 fsck_device(fs, 1);
1068 status |= wait_many(FLAG_WAIT_ALL);
1069 if (status > EXIT_NONDESTRUCT)
1070 return status;
1071 }
1072 fs->flags |= FLAG_DONE;
1073 }
1074 }
1075 /*
1076 * This is for the bone-headed user who enters the root
1077 * filesystem twice. Skip root will skep all root entries.
1078 */
1079 if (skip_root)
1080 for (fs = filesys_info; fs; fs = fs->next)
1081 if (LONE_CHAR(fs->mountpt, '/'))
1082 fs->flags |= FLAG_DONE;
1083
1084 while (not_done_yet) {
1085 not_done_yet = 0;
1086 pass_done = 1;
1087
1088 for (fs = filesys_info; fs; fs = fs->next) {
1089 if (cancel_requested)
1090 break;
1091 if (fs->flags & FLAG_DONE)
1092 continue;
1093 /*
1094 * If the filesystem's pass number is higher
1095 * than the current pass number, then we don't
1096 * do it yet.
1097 */
1098 if (fs->passno > passno) {
1099 not_done_yet++;
1100 continue;
1101 }
1102 /*
1103 * If a filesystem on a particular device has
1104 * already been spawned, then we need to defer
1105 * this to another pass.
1106 */
1107 if (device_already_active(fs->device)) {
1108 pass_done = 0;
1109 continue;
1110 }
1111 /*
1112 * Spawn off the fsck process
1113 */
1114 fsck_device(fs, serialize);
1115 fs->flags |= FLAG_DONE;
1116
1117 /*
1118 * Only do one filesystem at a time, or if we
1119 * have a limit on the number of fsck's extant
1120 * at one time, apply that limit.
1121 */
1122 if (serialize ||
1123 (max_running && (num_running >= max_running))) {
1124 pass_done = 0;
1125 break;
1126 }
1127 }
1128 if (cancel_requested)
1129 break;
1130 if (verbose > 1)
1131 printf("--waiting-- (pass %d)\n", passno);
1132 status |= wait_many(pass_done ? FLAG_WAIT_ALL :
1133 FLAG_WAIT_ATLEAST_ONE);
1134 if (pass_done) {
1135 if (verbose > 1)
1136 printf("----------------------------------\n");
1137 passno++;
1138 } else
1139 not_done_yet++;
1140 }
1141 if (cancel_requested && !kill_sent) {
1142 kill_all(SIGTERM);
1143 kill_sent++;
1144 }
1145 status |= wait_many(FLAG_WAIT_ATLEAST_ONE);
1146 return status;
1147}
1148
1149static void signal_cancel(int sig FSCK_ATTR((unused)))
1150{
1151 cancel_requested++;
1152}
1153
1154static void PRS(int argc, char **argv)
1155{
1156 int i, j;
1157 char *arg, *dev, *tmp = NULL;
1158 char options[128];
1159 int opt = 0;
1160 int opts_for_fsck = 0;
1161 struct sigaction sa;
1162
1163 /*
1164 * Set up signal action
1165 */
1166 memset(&sa, 0, sizeof(struct sigaction));
1167 sa.sa_handler = signal_cancel;
1168 sigaction(SIGINT, &sa, 0);
1169 sigaction(SIGTERM, &sa, 0);
1170
1171 num_devices = 0;
1172 num_args = 0;
1173 instance_list = 0;
1174
1175 for (i=1; i < argc; i++) {
1176 arg = argv[i];
1177 if (!arg)
1178 continue;
1179 if ((arg[0] == '/' && !opts_for_fsck) || strchr(arg, '=')) {
1180 if (num_devices >= MAX_DEVICES) {
1181 bb_error_msg_and_die("too many devices");
1182 }
1183 dev = blkid_get_devname(cache, arg, NULL);
1184 if (!dev && strchr(arg, '=')) {
1185 /*
1186 * Check to see if we failed because
1187 * /proc/partitions isn't found.
1188 */
1189 if (access("/proc/partitions", R_OK) < 0) {
1190 bb_perror_msg_and_die("can't open /proc/partitions "
1191 "(is /proc mounted?)");
1192 }
1193 /*
1194 * Check to see if this is because
1195 * we're not running as root
1196 */
1197 if (geteuid())
1198 bb_error_msg_and_die(
1199 "must be root to scan for matching filesystems: %s\n", arg);
1200 else
1201 bb_error_msg_and_die(
1202 "can't find matching filesystem: %s", arg);
1203 }
1204 devices[num_devices++] = dev ? dev : string_copy(arg);
1205 continue;
1206 }
1207 if (arg[0] != '-' || opts_for_fsck) {
1208 if (num_args >= MAX_ARGS) {
1209 bb_error_msg_and_die("too many arguments");
1210 }
1211 args[num_args++] = string_copy(arg);
1212 continue;
1213 }
1214 for (j=1; arg[j]; j++) {
1215 if (opts_for_fsck) {
1216 options[++opt] = arg[j];
1217 continue;
1218 }
1219 switch (arg[j]) {
1220 case 'A':
1221 doall++;
1222 break;
1223 case 'C':
1224 progress++;
1225 if (arg[j+1]) {
1226 progress_fd = string_to_int(arg+j+1);
1227 if (progress_fd < 0)
1228 progress_fd = 0;
1229 else
1230 goto next_arg;
1231 } else if ((i+1) < argc
1232 && argv[i+1][0] != '-') {
1233 progress_fd = string_to_int(argv[i]);
1234 if (progress_fd < 0)
1235 progress_fd = 0;
1236 else {
1237 goto next_arg;
1238 }
1239 }
1240 break;
1241 case 'V':
1242 verbose++;
1243 break;
1244 case 'N':
1245 noexecute++;
1246 break;
1247 case 'R':
1248 skip_root++;
1249 break;
1250 case 'T':
1251 notitle++;
1252 break;
1253 case 'M':
1254 like_mount++;
1255 break;
1256 case 'P':
1257 parallel_root++;
1258 break;
1259 case 's':
1260 serialize++;
1261 break;
1262 case 't':
1263 tmp = 0;
1264 if (fstype)
1265 bb_show_usage();
1266 if (arg[j+1])
1267 tmp = arg+j+1;
1268 else if ((i+1) < argc)
1269 tmp = argv[++i];
1270 else
1271 bb_show_usage();
1272 fstype = string_copy(tmp);
1273 compile_fs_type(fstype, &fs_type_compiled);
1274 goto next_arg;
1275 case '-':
1276 opts_for_fsck++;
1277 break;
1278 case '?':
1279 bb_show_usage();
1280 break;
1281 default:
1282 options[++opt] = arg[j];
1283 break;
1284 }
1285 }
1286 next_arg:
1287 if (opt) {
1288 options[0] = '-';
1289 options[++opt] = '\0';
1290 if (num_args >= MAX_ARGS) {
1291 bb_error_msg("too many arguments");
1292 }
1293 args[num_args++] = string_copy(options);
1294 opt = 0;
1295 }
1296 }
1297 if (getenv("FSCK_FORCE_ALL_PARALLEL"))
1298 force_all_parallel++;
1299 if ((tmp = getenv("FSCK_MAX_INST")))
1300 max_running = atoi(tmp);
1301}
1302
1303int fsck_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1304int fsck_main(int argc, char **argv)
1305{
1306 int i, status = 0;
1307 int interactive = 0;
1308 const char *fstab;
1309 struct fs_info *fs;
1310
1311 setvbuf(stdout, NULL, _IONBF, BUFSIZ);
1312 setvbuf(stderr, NULL, _IONBF, BUFSIZ);
1313
1314 blkid_get_cache(&cache, NULL);
1315 PRS(argc, argv);
1316
1317 if (!notitle)
1318 printf("fsck %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE);
1319
1320 fstab = getenv("FSTAB_FILE");
1321 if (!fstab)
1322 fstab = _PATH_MNTTAB;
1323 load_fs_info(fstab);
1324
1325 fsck_path = e2fs_set_sbin_path();
1326
1327 if ((num_devices == 1) || (serialize))
1328 interactive = 1;
1329
1330 /* If -A was specified ("check all"), do that! */
1331 if (doall)
1332 return check_all();
1333
1334 if (num_devices == 0) {
1335 serialize++;
1336 interactive++;
1337 return check_all();
1338 }
1339 for (i = 0; i < num_devices; i++) {
1340 if (cancel_requested) {
1341 if (!kill_sent) {
1342 kill_all(SIGTERM);
1343 kill_sent++;
1344 }
1345 break;
1346 }
1347 fs = lookup(devices[i]);
1348 if (!fs) {
1349 fs = create_fs_device(devices[i], 0, "auto",
1350 0, -1, -1);
1351 if (!fs)
1352 continue;
1353 }
1354 fsck_device(fs, interactive);
1355 if (serialize ||
1356 (max_running && (num_running >= max_running))) {
1357 struct fsck_instance *inst;
1358
1359 inst = wait_one(0);
1360 if (inst) {
1361 status |= inst->exit_status;
1362 free_instance(inst);
1363 }
1364 if (verbose > 1)
1365 printf("----------------------------------\n");
1366 }
1367 }
1368 status |= wait_many(FLAG_WAIT_ALL);
1369 blkid_put_cache(cache);
1370 return status;
1371}
diff --git a/e2fsprogs/old_e2fsprogs/fsck.h b/e2fsprogs/old_e2fsprogs/fsck.h
deleted file mode 100644
index 2ca2af7da..000000000
--- a/e2fsprogs/old_e2fsprogs/fsck.h
+++ /dev/null
@@ -1,16 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * fsck.h
4 */
5
6#define FSCK_ATTR(x) __attribute__(x)
7
8#define EXIT_OK 0
9#define EXIT_NONDESTRUCT 1
10#define EXIT_DESTRUCT 2
11#define EXIT_UNCORRECTED 4
12#define EXIT_ERROR 8
13#define EXIT_USAGE 16
14#define FSCK_CANCELED 32 /* Aborted with a signal or ^C */
15
16extern char *e2fs_set_sbin_path(void);
diff --git a/e2fsprogs/old_e2fsprogs/lsattr.c b/e2fsprogs/old_e2fsprogs/lsattr.c
deleted file mode 100644
index 9eab68b5b..000000000
--- a/e2fsprogs/old_e2fsprogs/lsattr.c
+++ /dev/null
@@ -1,129 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * lsattr.c - List file attributes on an ext2 file system
4 *
5 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
6 * Laboratoire MASI, Institut Blaise Pascal
7 * Universite Pierre et Marie Curie (Paris VI)
8 *
9 * This file can be redistributed under the terms of the GNU General
10 * Public License
11 */
12
13/*
14 * History:
15 * 93/10/30 - Creation
16 * 93/11/13 - Replace stat() calls by lstat() to avoid loops
17 * 94/02/27 - Integrated in Ted's distribution
18 * 98/12/29 - Display version info only when -V specified (G M Sipe)
19 */
20
21#include <sys/types.h>
22#include <dirent.h>
23#include <errno.h>
24#include <fcntl.h>
25#include <getopt.h>
26#include <stdio.h>
27#include <unistd.h>
28#include <stdlib.h>
29#include <string.h>
30#include <sys/param.h>
31#include <sys/stat.h>
32
33#include "ext2fs/ext2_fs.h"
34#include "e2fsbb.h"
35#include "e2p/e2p.h"
36
37#define OPT_RECUR 1
38#define OPT_ALL 2
39#define OPT_DIRS_OPT 4
40#define OPT_PF_LONG 8
41#define OPT_GENERATION 16
42static int flags;
43
44static void list_attributes(const char *name)
45{
46 unsigned long fsflags;
47 unsigned long generation;
48
49 if (fgetflags(name, &fsflags) == -1)
50 goto read_err;
51 if (flags & OPT_GENERATION) {
52 if (fgetversion(name, &generation) == -1)
53 goto read_err;
54 printf("%5lu ", generation);
55 }
56
57 if (flags & OPT_PF_LONG) {
58 printf("%-28s ", name);
59 print_e2flags(stdout, fsflags, PFOPT_LONG);
60 bb_putchar('\n');
61 } else {
62 print_e2flags(stdout, fsflags, 0);
63 printf(" %s\n", name);
64 }
65
66 return;
67read_err:
68 bb_perror_msg("reading %s", name);
69}
70
71static int lsattr_dir_proc(const char *, struct dirent *, void *);
72
73static void lsattr_args(const char *name)
74{
75 struct stat st;
76
77 if (lstat(name, &st) == -1) {
78 bb_perror_msg("stating %s", name);
79 } else {
80 if (S_ISDIR(st.st_mode) && !(flags & OPT_DIRS_OPT))
81 iterate_on_dir(name, lsattr_dir_proc, NULL);
82 else
83 list_attributes(name);
84 }
85}
86
87static int lsattr_dir_proc(const char *dir_name, struct dirent *de,
88 void *private)
89{
90 struct stat st;
91 char *path;
92
93 path = concat_path_file(dir_name, de->d_name);
94
95 if (lstat(path, &st) == -1)
96 bb_simple_perror_msg(path);
97 else {
98 if (de->d_name[0] != '.' || (flags & OPT_ALL)) {
99 list_attributes(path);
100 if (S_ISDIR(st.st_mode) && (flags & OPT_RECUR) &&
101 (de->d_name[0] != '.' && (de->d_name[1] != '\0' ||
102 (de->d_name[1] != '.' && de->d_name[2] != '\0')))) {
103 printf("\n%s:\n", path);
104 iterate_on_dir(path, lsattr_dir_proc, NULL);
105 bb_putchar('\n');
106 }
107 }
108 }
109
110 free(path);
111
112 return 0;
113}
114
115int lsattr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
116int lsattr_main(int argc, char **argv)
117{
118 int i;
119
120 flags = getopt32(argv, "Radlv");
121
122 if (optind > argc - 1)
123 lsattr_args(".");
124 else
125 for (i = optind; i < argc; i++)
126 lsattr_args(argv[i]);
127
128 return EXIT_SUCCESS;
129}
diff --git a/e2fsprogs/old_e2fsprogs/mke2fs.c b/e2fsprogs/old_e2fsprogs/mke2fs.c
deleted file mode 100644
index ebcb46cf2..000000000
--- a/e2fsprogs/old_e2fsprogs/mke2fs.c
+++ /dev/null
@@ -1,1333 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * mke2fs.c - Make a ext2fs filesystem.
4 *
5 * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
6 * 2003, 2004, 2005 by Theodore Ts'o.
7 *
8 * Licensed under GPLv2, see file LICENSE in this source tree.
9 */
10
11/* Usage: mke2fs [options] device
12 *
13 * The device may be a block device or a image of one, but this isn't
14 * enforced (but it's not much fun on a character device :-).
15 */
16
17#include <stdio.h>
18#include <string.h>
19#include <fcntl.h>
20#include <ctype.h>
21#include <time.h>
22#include <getopt.h>
23#include <unistd.h>
24#include <stdlib.h>
25#include <errno.h>
26#include <mntent.h>
27#include <sys/ioctl.h>
28#include <sys/types.h>
29
30#include "e2fsbb.h"
31#include "ext2fs/ext2_fs.h"
32#include "uuid/uuid.h"
33#include "e2p/e2p.h"
34#include "ext2fs/ext2fs.h"
35#include "util.h"
36
37#define STRIDE_LENGTH 8
38
39#ifndef __sparc__
40#define ZAP_BOOTBLOCK
41#endif
42
43static const char * device_name;
44
45/* Command line options */
46static int cflag;
47static int quiet;
48static int super_only;
49static int force;
50static int noaction;
51static int journal_size;
52static int journal_flags;
53static const char *bad_blocks_filename;
54static __u32 fs_stride;
55
56static struct ext2_super_block param;
57static char *creator_os;
58static char *volume_label;
59static char *mount_dir;
60static char *journal_device = NULL;
61static int sync_kludge; /* Set using the MKE2FS_SYNC env. option */
62
63static int sys_page_size = 4096;
64static int linux_version_code = 0;
65
66static int int_log2(int arg)
67{
68 int l = 0;
69
70 arg >>= 1;
71 while (arg) {
72 l++;
73 arg >>= 1;
74 }
75 return l;
76}
77
78static int int_log10(unsigned int arg)
79{
80 int l;
81
82 for (l = 0; arg; l++)
83 arg = arg / 10;
84 return l;
85}
86
87/*
88 * This function sets the default parameters for a filesystem
89 *
90 * The type is specified by the user. The size is the maximum size
91 * (in megabytes) for which a set of parameters applies, with a size
92 * of zero meaning that it is the default parameter for the type.
93 * Note that order is important in the table below.
94 */
95#define DEF_MAX_BLOCKSIZE -1
96static const char default_str[] = "default";
97struct mke2fs_defaults {
98 const char *type;
99 int size;
100 int blocksize;
101 int inode_ratio;
102};
103
104static const struct mke2fs_defaults settings[] = {
105 { default_str, 0, 4096, 8192 },
106 { default_str, 512, 1024, 4096 },
107 { default_str, 3, 1024, 8192 },
108 { "journal", 0, 4096, 8192 },
109 { "news", 0, 4096, 4096 },
110 { "largefile", 0, 4096, 1024 * 1024 },
111 { "largefile4", 0, 4096, 4096 * 1024 },
112 { 0, 0, 0, 0},
113};
114
115static void set_fs_defaults(const char *fs_type,
116 struct ext2_super_block *super,
117 int blocksize, int sector_size,
118 int *inode_ratio)
119{
120 int megs;
121 int ratio = 0;
122 const struct mke2fs_defaults *p;
123 int use_bsize = 1024;
124
125 megs = super->s_blocks_count * (EXT2_BLOCK_SIZE(super) / 1024) / 1024;
126 if (inode_ratio)
127 ratio = *inode_ratio;
128 if (!fs_type)
129 fs_type = default_str;
130 for (p = settings; p->type; p++) {
131 if ((strcmp(p->type, fs_type) != 0) &&
132 (strcmp(p->type, default_str) != 0))
133 continue;
134 if ((p->size != 0) && (megs > p->size))
135 continue;
136 if (ratio == 0)
137 *inode_ratio = p->inode_ratio < blocksize ?
138 blocksize : p->inode_ratio;
139 use_bsize = p->blocksize;
140 }
141 if (blocksize <= 0) {
142 if (use_bsize == DEF_MAX_BLOCKSIZE) {
143 use_bsize = sys_page_size;
144 if ((linux_version_code < (2*65536 + 6*256)) &&
145 (use_bsize > 4096))
146 use_bsize = 4096;
147 }
148 if (sector_size && use_bsize < sector_size)
149 use_bsize = sector_size;
150 if ((blocksize < 0) && (use_bsize < (-blocksize)))
151 use_bsize = -blocksize;
152 blocksize = use_bsize;
153 super->s_blocks_count /= blocksize / 1024;
154 }
155 super->s_log_frag_size = super->s_log_block_size =
156 int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
157}
158
159
160/*
161 * Helper function for read_bb_file and test_disk
162 */
163static void invalid_block(ext2_filsys fs EXT2FS_ATTR((unused)), blk_t blk)
164{
165 bb_error_msg("Bad block %u out of range; ignored", blk);
166}
167
168/*
169 * Busybox stuff
170 */
171static void mke2fs_error_msg_and_die(int retval, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
172static void mke2fs_error_msg_and_die(int retval, const char *fmt, ...)
173{
174 va_list ap;
175
176 if (retval) {
177 va_start(ap, fmt);
178 fprintf(stderr, "\nCould not ");
179 vfprintf(stderr, fmt, ap);
180 fprintf(stderr, "\n");
181 va_end(ap);
182 exit(EXIT_FAILURE);
183 }
184}
185
186static void mke2fs_verbose(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
187static void mke2fs_verbose(const char *fmt, ...)
188{
189 va_list ap;
190
191 if (!quiet) {
192 va_start(ap, fmt);
193 vfprintf(stdout, fmt, ap);
194 fflush(stdout);
195 va_end(ap);
196 }
197}
198
199static void mke2fs_verbose_done(void)
200{
201 mke2fs_verbose("done\n");
202}
203
204static void mke2fs_warning_msg(int retval, char *fmt, ... ) __attribute__ ((format (printf, 2, 3)));
205static void mke2fs_warning_msg(int retval, char *fmt, ... )
206{
207 va_list ap;
208
209 if (retval) {
210 va_start(ap, fmt);
211 fprintf(stderr, "\nWarning: ");
212 vfprintf(stderr, fmt, ap);
213 fprintf(stderr, "\n");
214 va_end(ap);
215 }
216}
217
218/*
219 * Reads the bad blocks list from a file
220 */
221static void read_bb_file(ext2_filsys fs, badblocks_list *bb_list,
222 const char *bad_blocks_file)
223{
224 FILE *f;
225 errcode_t retval;
226
227 f = xfopen_for_read(bad_blocks_file);
228 retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block);
229 fclose (f);
230 mke2fs_error_msg_and_die(retval, "read bad blocks from list");
231}
232
233/*
234 * Runs the badblocks program to test the disk
235 */
236static void test_disk(ext2_filsys fs, badblocks_list *bb_list)
237{
238 FILE *f;
239 errcode_t retval;
240 char buf[1024];
241
242 sprintf(buf, "badblocks -b %u %s%s%s %d", fs->blocksize,
243 quiet ? "" : "-s ", (cflag > 1) ? "-w " : "",
244 fs->device_name, fs->super->s_blocks_count);
245 mke2fs_verbose("Running command: %s\n", buf);
246 f = popen(buf, "r");
247 if (!f) {
248 bb_perror_msg_and_die("can't run '%s'", buf);
249 }
250 retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block);
251 pclose(f);
252 mke2fs_error_msg_and_die(retval, "read bad blocks from program");
253}
254
255static void handle_bad_blocks(ext2_filsys fs, badblocks_list bb_list)
256{
257 dgrp_t i;
258 blk_t j;
259 unsigned must_be_good;
260 blk_t blk;
261 badblocks_iterate bb_iter;
262 errcode_t retval;
263 blk_t group_block;
264 int group;
265 int group_bad;
266
267 if (!bb_list)
268 return;
269
270 /*
271 * The primary superblock and group descriptors *must* be
272 * good; if not, abort.
273 */
274 must_be_good = fs->super->s_first_data_block + 1 + fs->desc_blocks;
275 for (i = fs->super->s_first_data_block; i <= must_be_good; i++) {
276 if (ext2fs_badblocks_list_test(bb_list, i)) {
277 bb_error_msg_and_die(
278 "Block %d in primary superblock/group descriptor area bad\n"
279 "Blocks %d through %d must be good in order to build a filesystem\n"
280 "Aborting ...", i, fs->super->s_first_data_block, must_be_good);
281 }
282 }
283
284 /*
285 * See if any of the bad blocks are showing up in the backup
286 * superblocks and/or group descriptors. If so, issue a
287 * warning and adjust the block counts appropriately.
288 */
289 group_block = fs->super->s_first_data_block +
290 fs->super->s_blocks_per_group;
291
292 for (i = 1; i < fs->group_desc_count; i++) {
293 group_bad = 0;
294 for (j=0; j < fs->desc_blocks+1; j++) {
295 if (ext2fs_badblocks_list_test(bb_list,
296 group_block + j)) {
297 mke2fs_warning_msg(!group_bad,
298 "the backup superblock/group descriptors at block %d contain\n"
299 "bad blocks\n", group_block);
300 group_bad++;
301 group = ext2fs_group_of_blk(fs, group_block+j);
302 fs->group_desc[group].bg_free_blocks_count++;
303 fs->super->s_free_blocks_count++;
304 }
305 }
306 group_block += fs->super->s_blocks_per_group;
307 }
308
309 /*
310 * Mark all the bad blocks as used...
311 */
312 retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter);
313 mke2fs_error_msg_and_die(retval, "mark bad blocks as used");
314
315 while (ext2fs_badblocks_list_iterate(bb_iter, &blk))
316 ext2fs_mark_block_bitmap(fs->block_map, blk);
317 ext2fs_badblocks_list_iterate_end(bb_iter);
318}
319
320/*
321 * These functions implement a generalized progress meter.
322 */
323struct progress_struct {
324 char format[20];
325 char backup[80];
326 __u32 max;
327 int skip_progress;
328};
329
330static void progress_init(struct progress_struct *progress,
331 const char *label,__u32 max)
332{
333 int i;
334
335 memset(progress, 0, sizeof(struct progress_struct));
336 if (quiet)
337 return;
338
339 /*
340 * Figure out how many digits we need
341 */
342 i = int_log10(max);
343 sprintf(progress->format, "%%%dd/%%%dld", i, i);
344 memset(progress->backup, '\b', sizeof(progress->backup)-1);
345 progress->backup[sizeof(progress->backup)-1] = 0;
346 if ((2*i)+1 < (int) sizeof(progress->backup))
347 progress->backup[(2*i)+1] = 0;
348 progress->max = max;
349
350 progress->skip_progress = 0;
351 if (getenv("MKE2FS_SKIP_PROGRESS"))
352 progress->skip_progress++;
353
354 fputs(label, stdout);
355 fflush(stdout);
356}
357
358static void progress_update(struct progress_struct *progress, __u32 val)
359{
360 if ((progress->format[0] == 0) || progress->skip_progress)
361 return;
362 printf(progress->format, val, progress->max);
363 fputs(progress->backup, stdout);
364}
365
366static void progress_close(struct progress_struct *progress)
367{
368 if (progress->format[0] == 0)
369 return;
370 printf("%-28s\n", "done");
371}
372
373
374/*
375 * Helper function which zeros out _num_ blocks starting at _blk_. In
376 * case of an error, the details of the error is returned via _ret_blk_
377 * and _ret_count_ if they are non-NULL pointers. Returns 0 on
378 * success, and an error code on an error.
379 *
380 * As a special case, if the first argument is NULL, then it will
381 * attempt to free the static zeroizing buffer. (This is to keep
382 * programs that check for memory leaks happy.)
383 */
384static errcode_t zero_blocks(ext2_filsys fs, blk_t blk, int num,
385 struct progress_struct *progress,
386 blk_t *ret_blk, int *ret_count)
387{
388 int j, count, next_update;
389 static char *buf;
390 errcode_t retval;
391
392 /* If fs is null, clean up the static buffer and return */
393 if (!fs) {
394 if (buf) {
395 free(buf);
396 buf = 0;
397 }
398 return 0;
399 }
400 /* Allocate the zeroizing buffer if necessary */
401 if (!buf) {
402 buf = xzalloc(fs->blocksize * STRIDE_LENGTH);
403 }
404 /* OK, do the write loop */
405 next_update = 0;
406
407 for (j=0; j < num; j += STRIDE_LENGTH, blk += STRIDE_LENGTH) {
408 count = num - j;
409 if (count > STRIDE_LENGTH)
410 count = STRIDE_LENGTH;
411 retval = io_channel_write_blk(fs->io, blk, count, buf);
412 if (retval) {
413 if (ret_count)
414 *ret_count = count;
415 if (ret_blk)
416 *ret_blk = blk;
417 return retval;
418 }
419 if (progress && j > next_update) {
420 next_update += num / 100;
421 progress_update(progress, blk);
422 }
423 }
424 return 0;
425}
426
427static void write_inode_tables(ext2_filsys fs)
428{
429 errcode_t retval;
430 blk_t blk;
431 dgrp_t i;
432 int num;
433 struct progress_struct progress;
434
435 if (quiet)
436 memset(&progress, 0, sizeof(progress));
437 else
438 progress_init(&progress, "Writing inode tables: ",
439 fs->group_desc_count);
440
441 for (i = 0; i < fs->group_desc_count; i++) {
442 progress_update(&progress, i);
443
444 blk = fs->group_desc[i].bg_inode_table;
445 num = fs->inode_blocks_per_group;
446
447 retval = zero_blocks(fs, blk, num, 0, &blk, &num);
448 mke2fs_error_msg_and_die(retval,
449 "write %d blocks in inode table starting at %d.",
450 num, blk);
451 if (sync_kludge) {
452 if (sync_kludge == 1)
453 sync();
454 else if ((i % sync_kludge) == 0)
455 sync();
456 }
457 }
458 zero_blocks(0, 0, 0, 0, 0, 0);
459 progress_close(&progress);
460}
461
462static void create_root_dir(ext2_filsys fs)
463{
464 errcode_t retval;
465 struct ext2_inode inode;
466
467 retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, 0);
468 mke2fs_error_msg_and_die(retval, "create root dir");
469 if (geteuid()) {
470 retval = ext2fs_read_inode(fs, EXT2_ROOT_INO, &inode);
471 mke2fs_error_msg_and_die(retval, "read root inode");
472 inode.i_uid = getuid();
473 if (inode.i_uid)
474 inode.i_gid = getgid();
475 retval = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
476 mke2fs_error_msg_and_die(retval, "set root inode ownership");
477 }
478}
479
480static void create_lost_and_found(ext2_filsys fs)
481{
482 errcode_t retval;
483 ext2_ino_t ino;
484 const char *name = "lost+found";
485 int i = 1;
486 char *msg = "create";
487 int lpf_size = 0;
488
489 fs->umask = 077;
490 retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, 0, name);
491 if (retval) {
492 goto CREATE_LOST_AND_FOUND_ERROR;
493 }
494
495 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name, strlen(name), 0, &ino);
496 if (retval) {
497 msg = "lookup";
498 goto CREATE_LOST_AND_FOUND_ERROR;
499 }
500
501 for (; i < EXT2_NDIR_BLOCKS; i++) {
502 if ((lpf_size += fs->blocksize) >= 16*1024)
503 break;
504 retval = ext2fs_expand_dir(fs, ino);
505 msg = "expand";
506CREATE_LOST_AND_FOUND_ERROR:
507 mke2fs_error_msg_and_die(retval, "%s %s", msg, name);
508 }
509}
510
511static void create_bad_block_inode(ext2_filsys fs, badblocks_list bb_list)
512{
513 errcode_t retval;
514
515 ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_BAD_INO);
516 fs->group_desc[0].bg_free_inodes_count--;
517 fs->super->s_free_inodes_count--;
518 retval = ext2fs_update_bb_inode(fs, bb_list);
519 mke2fs_error_msg_and_die(retval, "set bad block inode");
520}
521
522static void reserve_inodes(ext2_filsys fs)
523{
524 ext2_ino_t i;
525 int group;
526
527 for (i = EXT2_ROOT_INO + 1; i < EXT2_FIRST_INODE(fs->super); i++) {
528 ext2fs_mark_inode_bitmap(fs->inode_map, i);
529 group = ext2fs_group_of_ino(fs, i);
530 fs->group_desc[group].bg_free_inodes_count--;
531 fs->super->s_free_inodes_count--;
532 }
533 ext2fs_mark_ib_dirty(fs);
534}
535
536#define BSD_DISKMAGIC (0x82564557UL) /* The disk magic number */
537#define BSD_MAGICDISK (0x57455682UL) /* The disk magic number reversed */
538#define BSD_LABEL_OFFSET 64
539
540static void zap_sector(ext2_filsys fs, int sect, int nsect)
541{
542 char *buf;
543 char *fmt = "could not %s %d";
544 int retval;
545 unsigned int *magic;
546
547 buf = xmalloc(512*nsect);
548
549 if (sect == 0) {
550 /* Check for a BSD disklabel, and don't erase it if so */
551 retval = io_channel_read_blk(fs->io, 0, -512, buf);
552 if (retval)
553 mke2fs_warning_msg(retval, fmt, "read block", 0);
554 else {
555 magic = (unsigned int *) (buf + BSD_LABEL_OFFSET);
556 if ((*magic == BSD_DISKMAGIC) ||
557 (*magic == BSD_MAGICDISK))
558 return;
559 }
560 }
561
562 memset(buf, 0, 512*nsect);
563 io_channel_set_blksize(fs->io, 512);
564 retval = io_channel_write_blk(fs->io, sect, -512*nsect, buf);
565 io_channel_set_blksize(fs->io, fs->blocksize);
566 free(buf);
567 mke2fs_warning_msg(retval, fmt, "erase sector", sect);
568}
569
570static void create_journal_dev(ext2_filsys fs)
571{
572 struct progress_struct progress;
573 errcode_t retval;
574 char *buf;
575 char *fmt = "%s journal superblock";
576 blk_t blk;
577 int count;
578
579 retval = ext2fs_create_journal_superblock(fs,
580 fs->super->s_blocks_count, 0, &buf);
581 mke2fs_error_msg_and_die(retval, fmt, "init");
582 if (quiet)
583 memset(&progress, 0, sizeof(progress));
584 else
585 progress_init(&progress, "Zeroing journal device: ",
586 fs->super->s_blocks_count);
587
588 retval = zero_blocks(fs, 0, fs->super->s_blocks_count,
589 &progress, &blk, &count);
590 mke2fs_error_msg_and_die(retval, "zero journal device (block %u, count %d)",
591 blk, count);
592 zero_blocks(0, 0, 0, 0, 0, 0);
593
594 retval = io_channel_write_blk(fs->io,
595 fs->super->s_first_data_block+1,
596 1, buf);
597 mke2fs_error_msg_and_die(retval, fmt, "write");
598 progress_close(&progress);
599}
600
601static void show_stats(ext2_filsys fs)
602{
603 struct ext2_super_block *s = fs->super;
604 char *os;
605 blk_t group_block;
606 dgrp_t i;
607 int need, col_left;
608
609 mke2fs_warning_msg((param.s_blocks_count != s->s_blocks_count),
610 "%d blocks unused\n", param.s_blocks_count - s->s_blocks_count);
611 os = e2p_os2string(fs->super->s_creator_os);
612 printf( "Filesystem label=%.*s\n"
613 "OS type: %s\n"
614 "Block size=%u (log=%u)\n"
615 "Fragment size=%u (log=%u)\n"
616 "%u inodes, %u blocks\n"
617 "%u blocks (%2.2f%%) reserved for the super user\n"
618 "First data block=%u\n",
619 (int) sizeof(s->s_volume_name),
620 s->s_volume_name,
621 os,
622 fs->blocksize, s->s_log_block_size,
623 fs->fragsize, s->s_log_frag_size,
624 s->s_inodes_count, s->s_blocks_count,
625 s->s_r_blocks_count, 100.0 * s->s_r_blocks_count / s->s_blocks_count,
626 s->s_first_data_block);
627 free(os);
628 if (s->s_reserved_gdt_blocks) {
629 printf("Maximum filesystem blocks=%lu\n",
630 (s->s_reserved_gdt_blocks + fs->desc_blocks) *
631 (fs->blocksize / sizeof(struct ext2_group_desc)) *
632 s->s_blocks_per_group);
633 }
634 printf( "%u block group%s\n"
635 "%u blocks per group, %u fragments per group\n"
636 "%u inodes per group\n",
637 fs->group_desc_count, (fs->group_desc_count > 1) ? "s" : "",
638 s->s_blocks_per_group, s->s_frags_per_group,
639 s->s_inodes_per_group);
640 if (fs->group_desc_count == 1) {
641 bb_putchar('\n');
642 return;
643 }
644
645 printf("Superblock backups stored on blocks: ");
646 group_block = s->s_first_data_block;
647 col_left = 0;
648 for (i = 1; i < fs->group_desc_count; i++) {
649 group_block += s->s_blocks_per_group;
650 if (!ext2fs_bg_has_super(fs, i))
651 continue;
652 if (i != 1)
653 printf(", ");
654 need = int_log10(group_block) + 2;
655 if (need > col_left) {
656 printf("\n\t");
657 col_left = 72;
658 }
659 col_left -= need;
660 printf("%u", group_block);
661 }
662 puts("\n");
663}
664
665/*
666 * Set the S_CREATOR_OS field. Return true if OS is known,
667 * otherwise, 0.
668 */
669static int set_os(struct ext2_super_block *sb, char *os)
670{
671 if (isdigit (*os)) {
672 sb->s_creator_os = atoi(os);
673 return 1;
674 }
675
676 if ((sb->s_creator_os = e2p_string2os(os)) >= 0) {
677 return 1;
678 } else if (!strcasecmp("GNU", os)) {
679 sb->s_creator_os = EXT2_OS_HURD;
680 return 1;
681 }
682 return 0;
683}
684
685static void parse_extended_opts(struct ext2_super_block *sb_param,
686 const char *opts)
687{
688 char *buf, *token, *next, *p, *arg;
689 int r_usage = 0;
690
691 buf = xstrdup(opts);
692 for (token = buf; token && *token; token = next) {
693 p = strchr(token, ',');
694 next = 0;
695 if (p) {
696 *p = 0;
697 next = p+1;
698 }
699 arg = strchr(token, '=');
700 if (arg) {
701 *arg = 0;
702 arg++;
703 }
704 if (strcmp(token, "stride") == 0) {
705 if (!arg) {
706 r_usage++;
707 continue;
708 }
709 fs_stride = strtoul(arg, &p, 0);
710 if (*p || (fs_stride == 0)) {
711 bb_error_msg("Invalid stride parameter: %s", arg);
712 r_usage++;
713 continue;
714 }
715 } else if (!strcmp(token, "resize")) {
716 unsigned long resize, bpg, rsv_groups;
717 unsigned long group_desc_count, desc_blocks;
718 unsigned int gdpb, blocksize;
719 int rsv_gdb;
720
721 if (!arg) {
722 r_usage++;
723 continue;
724 }
725
726 resize = parse_num_blocks(arg,
727 sb_param->s_log_block_size);
728
729 if (resize == 0) {
730 bb_error_msg("Invalid resize parameter: %s", arg);
731 r_usage++;
732 continue;
733 }
734 if (resize <= sb_param->s_blocks_count) {
735 bb_error_msg("The resize maximum must be greater "
736 "than the filesystem size");
737 r_usage++;
738 continue;
739 }
740
741 blocksize = EXT2_BLOCK_SIZE(sb_param);
742 bpg = sb_param->s_blocks_per_group;
743 if (!bpg)
744 bpg = blocksize * 8;
745 gdpb = blocksize / sizeof(struct ext2_group_desc);
746 group_desc_count = (sb_param->s_blocks_count +
747 bpg - 1) / bpg;
748 desc_blocks = (group_desc_count +
749 gdpb - 1) / gdpb;
750 rsv_groups = (resize + bpg - 1) / bpg;
751 rsv_gdb = (rsv_groups + gdpb - 1) / gdpb -
752 desc_blocks;
753 if (rsv_gdb > EXT2_ADDR_PER_BLOCK(sb_param))
754 rsv_gdb = EXT2_ADDR_PER_BLOCK(sb_param);
755
756 if (rsv_gdb > 0) {
757 sb_param->s_feature_compat |=
758 EXT2_FEATURE_COMPAT_RESIZE_INO;
759
760 sb_param->s_reserved_gdt_blocks = rsv_gdb;
761 }
762 } else
763 r_usage++;
764 }
765 if (r_usage) {
766 bb_error_msg_and_die(
767 "\nBad options specified.\n\n"
768 "Extended options are separated by commas, "
769 "and may take an argument which\n"
770 "\tis set off by an equals ('=') sign.\n\n"
771 "Valid extended options are:\n"
772 "\tstride=<stride length in blocks>\n"
773 "\tresize=<resize maximum size in blocks>\n");
774 }
775}
776
777static __u32 ok_features[3] = {
778 EXT3_FEATURE_COMPAT_HAS_JOURNAL |
779 EXT2_FEATURE_COMPAT_RESIZE_INO |
780 EXT2_FEATURE_COMPAT_DIR_INDEX, /* Compat */
781 EXT2_FEATURE_INCOMPAT_FILETYPE| /* Incompat */
782 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|
783 EXT2_FEATURE_INCOMPAT_META_BG,
784 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER /* R/O compat */
785};
786
787static int PRS(int argc, char **argv)
788{
789 int c;
790 int size;
791 char * tmp;
792 int blocksize = 0;
793 int inode_ratio = 0;
794 int inode_size = 0;
795 int reserved_ratio = 5;
796 int sector_size = 0;
797 int show_version_only = 0;
798 ext2_ino_t num_inodes = 0;
799 errcode_t retval;
800 char * extended_opts = NULL;
801 const char * fs_type = NULL;
802 blk_t dev_size;
803 long sysval;
804
805 /* Update our PATH to include /sbin */
806 e2fs_set_sbin_path();
807
808 tmp = getenv("MKE2FS_SYNC");
809 if (tmp)
810 sync_kludge = atoi(tmp);
811
812 /* Determine the system page size if possible */
813#if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE))
814#define _SC_PAGESIZE _SC_PAGE_SIZE
815#endif
816#ifdef _SC_PAGESIZE
817 sysval = sysconf(_SC_PAGESIZE);
818 if (sysval > 0)
819 sys_page_size = sysval;
820#endif /* _SC_PAGESIZE */
821
822 setbuf(stdout, NULL);
823 setbuf(stderr, NULL);
824 memset(&param, 0, sizeof(struct ext2_super_block));
825 param.s_rev_level = 1; /* Create revision 1 filesystems now */
826 param.s_feature_incompat |= EXT2_FEATURE_INCOMPAT_FILETYPE;
827 param.s_feature_ro_compat |= EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
828
829#ifdef __linux__
830 linux_version_code = get_linux_version_code();
831 if (linux_version_code && linux_version_code < KERNEL_VERSION(2,2,0)) {
832 param.s_rev_level = 0;
833 param.s_feature_incompat = 0;
834 param.s_feature_compat = 0;
835 param.s_feature_ro_compat = 0;
836 }
837#endif
838
839 /* If called as mkfs.ext3, create a journal inode */
840 if (last_char_is(applet_name, '3'))
841 journal_size = -1;
842
843 while ((c = getopt (argc, argv,
844 "b:cE:f:g:i:jl:m:no:qr:R:s:tvI:J:ST:FL:M:N:O:V")) != EOF) {
845 switch (c) {
846 case 'b':
847 blocksize = xatou_range(optarg, EXT2_MIN_BLOCK_SIZE, EXT2_MAX_BLOCK_SIZE);
848 mke2fs_warning_msg((blocksize > 4096),
849 "blocksize %d not usable on most systems",
850 blocksize);
851 param.s_log_block_size =
852 int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
853 break;
854 case 'c': /* Check for bad blocks */
855 case 't': /* deprecated */
856 cflag++;
857 break;
858 case 'f':
859 size = xatou_range(optarg, EXT2_MIN_BLOCK_SIZE, EXT2_MAX_BLOCK_SIZE);
860 param.s_log_frag_size =
861 int_log2(size >> EXT2_MIN_BLOCK_LOG_SIZE);
862 mke2fs_warning_msg(1, "fragments not supported. Ignoring -f option");
863 break;
864 case 'g':
865 param.s_blocks_per_group = xatou32(optarg);
866 if ((param.s_blocks_per_group % 8) != 0) {
867 bb_error_msg_and_die("blocks per group must be multiple of 8");
868 }
869 break;
870 case 'i':
871 /* Huh? is "* 1024" correct? */
872 inode_ratio = xatou_range(optarg, EXT2_MIN_BLOCK_SIZE, EXT2_MAX_BLOCK_SIZE * 1024);
873 break;
874 case 'J':
875 parse_journal_opts(&journal_device, &journal_flags, &journal_size, optarg);
876 break;
877 case 'j':
878 param.s_feature_compat |=
879 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
880 if (!journal_size)
881 journal_size = -1;
882 break;
883 case 'l':
884 bad_blocks_filename = optarg;
885 break;
886 case 'm':
887 reserved_ratio = xatou_range(optarg, 0, 50);
888 break;
889 case 'n':
890 noaction++;
891 break;
892 case 'o':
893 creator_os = optarg;
894 break;
895 case 'r':
896 param.s_rev_level = xatoi_positive(optarg);
897 if (param.s_rev_level == EXT2_GOOD_OLD_REV) {
898 param.s_feature_incompat = 0;
899 param.s_feature_compat = 0;
900 param.s_feature_ro_compat = 0;
901 }
902 break;
903 case 's': /* deprecated */
904 if (xatou(optarg))
905 param.s_feature_ro_compat |=
906 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
907 else
908 param.s_feature_ro_compat &=
909 ~EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
910 break;
911#ifdef EXT2_DYNAMIC_REV
912 case 'I':
913 inode_size = xatoi_positive(optarg);
914 break;
915#endif
916 case 'N':
917 num_inodes = xatoi_positive(optarg);
918 break;
919 case 'v':
920 quiet = 0;
921 break;
922 case 'q':
923 quiet = 1;
924 break;
925 case 'F':
926 force = 1;
927 break;
928 case 'L':
929 volume_label = optarg;
930 break;
931 case 'M':
932 mount_dir = optarg;
933 break;
934 case 'O':
935 if (!strcmp(optarg, "none")) {
936 param.s_feature_compat = 0;
937 param.s_feature_incompat = 0;
938 param.s_feature_ro_compat = 0;
939 break;
940 }
941 if (e2p_edit_feature(optarg,
942 &param.s_feature_compat,
943 ok_features)) {
944 bb_error_msg_and_die("Invalid filesystem option set: %s", optarg);
945 }
946 break;
947 case 'E':
948 case 'R':
949 extended_opts = optarg;
950 break;
951 case 'S':
952 super_only = 1;
953 break;
954 case 'T':
955 fs_type = optarg;
956 break;
957 case 'V':
958 /* Print version number and exit */
959 show_version_only = 1;
960 quiet = 0;
961 break;
962 default:
963 bb_show_usage();
964 }
965 }
966 if ((optind == argc) /*&& !show_version_only*/)
967 bb_show_usage();
968 device_name = argv[optind++];
969
970 mke2fs_verbose("mke2fs %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE);
971
972 if (show_version_only) {
973 return 0;
974 }
975
976 /*
977 * If there's no blocksize specified and there is a journal
978 * device, use it to figure out the blocksize
979 */
980 if (blocksize <= 0 && journal_device) {
981 ext2_filsys jfs;
982 io_manager io_ptr;
983
984#ifdef CONFIG_TESTIO_DEBUG
985 io_ptr = test_io_manager;
986 test_io_backing_manager = unix_io_manager;
987#else
988 io_ptr = unix_io_manager;
989#endif
990 retval = ext2fs_open(journal_device,
991 EXT2_FLAG_JOURNAL_DEV_OK, 0,
992 0, io_ptr, &jfs);
993 mke2fs_error_msg_and_die(retval, "open journal device %s", journal_device);
994 if ((blocksize < 0) && (jfs->blocksize < (unsigned) (-blocksize))) {
995 bb_error_msg_and_die(
996 "Journal dev blocksize (%d) smaller than "
997 "minimum blocksize %d\n", jfs->blocksize,
998 -blocksize);
999 }
1000 blocksize = jfs->blocksize;
1001 param.s_log_block_size =
1002 int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
1003 ext2fs_close(jfs);
1004 }
1005
1006 if (blocksize > sys_page_size) {
1007 mke2fs_warning_msg(1, "%d-byte blocks too big for system (max %d)",
1008 blocksize, sys_page_size);
1009 if (!force) {
1010 proceed_question();
1011 }
1012 bb_error_msg("Forced to continue");
1013 }
1014 mke2fs_warning_msg(((blocksize > 4096) &&
1015 (param.s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)),
1016 "some 2.4 kernels do not support "
1017 "blocksizes greater than 4096 using ext3.\n"
1018 "Use -b 4096 if this is an issue for you\n");
1019
1020 if (optind < argc) {
1021 param.s_blocks_count = parse_num_blocks(argv[optind++],
1022 param.s_log_block_size);
1023 mke2fs_error_msg_and_die(!param.s_blocks_count, "invalid blocks count - %s", argv[optind - 1]);
1024 }
1025 if (optind < argc)
1026 bb_show_usage();
1027
1028 if (param.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
1029 if (!fs_type)
1030 fs_type = "journal";
1031 reserved_ratio = 0;
1032 param.s_feature_incompat = EXT3_FEATURE_INCOMPAT_JOURNAL_DEV;
1033 param.s_feature_compat = 0;
1034 param.s_feature_ro_compat = 0;
1035 }
1036 if (param.s_rev_level == EXT2_GOOD_OLD_REV &&
1037 (param.s_feature_compat || param.s_feature_ro_compat ||
1038 param.s_feature_incompat))
1039 param.s_rev_level = 1; /* Create a revision 1 filesystem */
1040
1041 check_plausibility(device_name , force);
1042 check_mount(device_name, force, "filesystem");
1043
1044 param.s_log_frag_size = param.s_log_block_size;
1045
1046 if (noaction && param.s_blocks_count) {
1047 dev_size = param.s_blocks_count;
1048 retval = 0;
1049 } else {
1050 retry:
1051 retval = ext2fs_get_device_size(device_name,
1052 EXT2_BLOCK_SIZE(&param),
1053 &dev_size);
1054 if ((retval == EFBIG) &&
1055 (blocksize == 0) &&
1056 (param.s_log_block_size == 0)) {
1057 param.s_log_block_size = 2;
1058 blocksize = 4096;
1059 goto retry;
1060 }
1061 }
1062
1063 mke2fs_error_msg_and_die((retval && (retval != EXT2_ET_UNIMPLEMENTED)),"determine filesystem size");
1064
1065 if (!param.s_blocks_count) {
1066 if (retval == EXT2_ET_UNIMPLEMENTED) {
1067 mke2fs_error_msg_and_die(1,
1068 "determine device size; you "
1069 "must specify\nthe size of the "
1070 "filesystem");
1071 } else {
1072 if (dev_size == 0) {
1073 bb_error_msg_and_die(
1074 "Device size reported to be zero. "
1075 "Invalid partition specified, or\n\t"
1076 "partition table wasn't reread "
1077 "after running fdisk, due to\n\t"
1078 "a modified partition being busy "
1079 "and in use. You may need to reboot\n\t"
1080 "to re-read your partition table.\n"
1081 );
1082 }
1083 param.s_blocks_count = dev_size;
1084 if (sys_page_size > EXT2_BLOCK_SIZE(&param))
1085 param.s_blocks_count &= ~((sys_page_size /
1086 EXT2_BLOCK_SIZE(&param))-1);
1087 }
1088
1089 } else if (!force && (param.s_blocks_count > dev_size)) {
1090 bb_error_msg("Filesystem larger than apparent device size");
1091 proceed_question();
1092 }
1093
1094 /*
1095 * If the user asked for HAS_JOURNAL, then make sure a journal
1096 * gets created.
1097 */
1098 if ((param.s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
1099 !journal_size)
1100 journal_size = -1;
1101
1102 /* Set first meta blockgroup via an environment variable */
1103 /* (this is mostly for debugging purposes) */
1104 if ((param.s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) &&
1105 ((tmp = getenv("MKE2FS_FIRST_META_BG"))))
1106 param.s_first_meta_bg = atoi(tmp);
1107
1108 /* Get the hardware sector size, if available */
1109 retval = ext2fs_get_device_sectsize(device_name, &sector_size);
1110 mke2fs_error_msg_and_die(retval, "determine hardware sector size");
1111
1112 if ((tmp = getenv("MKE2FS_DEVICE_SECTSIZE")) != NULL)
1113 sector_size = atoi(tmp);
1114
1115 set_fs_defaults(fs_type, &param, blocksize, sector_size, &inode_ratio);
1116 blocksize = EXT2_BLOCK_SIZE(&param);
1117
1118 if (extended_opts)
1119 parse_extended_opts(&param, extended_opts);
1120
1121 /* Since sparse_super is the default, we would only have a problem
1122 * here if it was explicitly disabled.
1123 */
1124 if ((param.s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INO) &&
1125 !(param.s_feature_ro_compat&EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
1126 bb_error_msg_and_die("reserved online resize blocks not supported "
1127 "on non-sparse filesystem");
1128 }
1129
1130 if (param.s_blocks_per_group) {
1131 if (param.s_blocks_per_group < 256 ||
1132 param.s_blocks_per_group > 8 * (unsigned) blocksize) {
1133 bb_error_msg_and_die("blocks per group count out of range");
1134 }
1135 }
1136
1137 if (!force && param.s_blocks_count >= (1 << 31)) {
1138 bb_error_msg_and_die("Filesystem too large. No more than 2**31-1 blocks\n"
1139 "\t (8TB using a blocksize of 4k) are currently supported.");
1140 }
1141
1142 if (inode_size) {
1143 if (inode_size < EXT2_GOOD_OLD_INODE_SIZE ||
1144 inode_size > EXT2_BLOCK_SIZE(&param) ||
1145 inode_size & (inode_size - 1)) {
1146 bb_error_msg_and_die("invalid inode size %d (min %d/max %d)",
1147 inode_size, EXT2_GOOD_OLD_INODE_SIZE,
1148 blocksize);
1149 }
1150 mke2fs_warning_msg((inode_size != EXT2_GOOD_OLD_INODE_SIZE),
1151 "%d-byte inodes not usable on most systems",
1152 inode_size);
1153 param.s_inode_size = inode_size;
1154 }
1155
1156 /*
1157 * Calculate number of inodes based on the inode ratio
1158 */
1159 param.s_inodes_count = num_inodes ? num_inodes :
1160 ((__u64) param.s_blocks_count * blocksize)
1161 / inode_ratio;
1162
1163 /*
1164 * Calculate number of blocks to reserve
1165 */
1166 param.s_r_blocks_count = (param.s_blocks_count * reserved_ratio) / 100;
1167 return 1;
1168}
1169
1170static void mke2fs_clean_up(void)
1171{
1172 if (ENABLE_FEATURE_CLEAN_UP && journal_device) free(journal_device);
1173}
1174
1175int mke2fs_main (int argc, char **argv);
1176int mke2fs_main (int argc, char **argv)
1177{
1178 errcode_t retval;
1179 ext2_filsys fs;
1180 badblocks_list bb_list = 0;
1181 unsigned int i;
1182 int val;
1183 io_manager io_ptr;
1184
1185 if (ENABLE_FEATURE_CLEAN_UP)
1186 atexit(mke2fs_clean_up);
1187 if (!PRS(argc, argv))
1188 return 0;
1189
1190#ifdef CONFIG_TESTIO_DEBUG
1191 io_ptr = test_io_manager;
1192 test_io_backing_manager = unix_io_manager;
1193#else
1194 io_ptr = unix_io_manager;
1195#endif
1196
1197 /*
1198 * Initialize the superblock....
1199 */
1200 retval = ext2fs_initialize(device_name, 0, &param,
1201 io_ptr, &fs);
1202 mke2fs_error_msg_and_die(retval, "set up superblock");
1203
1204 /*
1205 * Wipe out the old on-disk superblock
1206 */
1207 if (!noaction)
1208 zap_sector(fs, 2, 6);
1209
1210 /*
1211 * Generate a UUID for it...
1212 */
1213 uuid_generate(fs->super->s_uuid);
1214
1215 /*
1216 * Initialize the directory index variables
1217 */
1218 fs->super->s_def_hash_version = EXT2_HASH_TEA;
1219 uuid_generate((unsigned char *) fs->super->s_hash_seed);
1220
1221 /*
1222 * Add "jitter" to the superblock's check interval so that we
1223 * don't check all the filesystems at the same time. We use a
1224 * kludgy hack of using the UUID to derive a random jitter value.
1225 */
1226 for (i = 0, val = 0; i < sizeof(fs->super->s_uuid); i++)
1227 val += fs->super->s_uuid[i];
1228 fs->super->s_max_mnt_count += val % EXT2_DFL_MAX_MNT_COUNT;
1229
1230 /*
1231 * Override the creator OS, if applicable
1232 */
1233 if (creator_os && !set_os(fs->super, creator_os)) {
1234 bb_error_msg_and_die("unknown os - %s", creator_os);
1235 }
1236
1237 /*
1238 * For the Hurd, we will turn off filetype since it doesn't
1239 * support it.
1240 */
1241 if (fs->super->s_creator_os == EXT2_OS_HURD)
1242 fs->super->s_feature_incompat &=
1243 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
1244
1245 /*
1246 * Set the volume label...
1247 */
1248 if (volume_label) {
1249 snprintf(fs->super->s_volume_name, sizeof(fs->super->s_volume_name), "%s", volume_label);
1250 }
1251
1252 /*
1253 * Set the last mount directory
1254 */
1255 if (mount_dir) {
1256 snprintf(fs->super->s_last_mounted, sizeof(fs->super->s_last_mounted), "%s", mount_dir);
1257 }
1258
1259 if (!quiet || noaction)
1260 show_stats(fs);
1261
1262 if (noaction)
1263 return 0;
1264
1265 if (fs->super->s_feature_incompat &
1266 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
1267 create_journal_dev(fs);
1268 return (ext2fs_close(fs) ? 1 : 0);
1269 }
1270
1271 if (bad_blocks_filename)
1272 read_bb_file(fs, &bb_list, bad_blocks_filename);
1273 if (cflag)
1274 test_disk(fs, &bb_list);
1275
1276 handle_bad_blocks(fs, bb_list);
1277 fs->stride = fs_stride;
1278 retval = ext2fs_allocate_tables(fs);
1279 mke2fs_error_msg_and_die(retval, "allocate filesystem tables");
1280 if (super_only) {
1281 fs->super->s_state |= EXT2_ERROR_FS;
1282 fs->flags &= ~(EXT2_FLAG_IB_DIRTY|EXT2_FLAG_BB_DIRTY);
1283 } else {
1284 /* rsv must be a power of two (64kB is MD RAID sb alignment) */
1285 unsigned int rsv = 65536 / fs->blocksize;
1286 unsigned long blocks = fs->super->s_blocks_count;
1287 unsigned long start;
1288 blk_t ret_blk;
1289
1290#ifdef ZAP_BOOTBLOCK
1291 zap_sector(fs, 0, 2);
1292#endif
1293
1294 /*
1295 * Wipe out any old MD RAID (or other) metadata at the end
1296 * of the device. This will also verify that the device is
1297 * as large as we think. Be careful with very small devices.
1298 */
1299 start = (blocks & ~(rsv - 1));
1300 if (start > rsv)
1301 start -= rsv;
1302 if (start > 0)
1303 retval = zero_blocks(fs, start, blocks - start,
1304 NULL, &ret_blk, NULL);
1305
1306 mke2fs_warning_msg(retval, "can't zero block %u at end of filesystem", ret_blk);
1307 write_inode_tables(fs);
1308 create_root_dir(fs);
1309 create_lost_and_found(fs);
1310 reserve_inodes(fs);
1311 create_bad_block_inode(fs, bb_list);
1312 if (fs->super->s_feature_compat &
1313 EXT2_FEATURE_COMPAT_RESIZE_INO) {
1314 retval = ext2fs_create_resize_inode(fs);
1315 mke2fs_error_msg_and_die(retval, "reserve blocks for online resize");
1316 }
1317 }
1318
1319 if (journal_device) {
1320 make_journal_device(journal_device, fs, quiet, force);
1321 } else if (journal_size) {
1322 make_journal_blocks(fs, journal_size, journal_flags, quiet);
1323 }
1324
1325 mke2fs_verbose("Writing superblocks and filesystem accounting information: ");
1326 retval = ext2fs_flush(fs);
1327 mke2fs_warning_msg(retval, "had trouble writing out superblocks");
1328 mke2fs_verbose_done();
1329 if (!quiet && !getenv("MKE2FS_SKIP_CHECK_MSG"))
1330 print_check_message(fs);
1331 val = ext2fs_close(fs);
1332 return (retval || val) ? 1 : 0;
1333}
diff --git a/e2fsprogs/old_e2fsprogs/tune2fs.c b/e2fsprogs/old_e2fsprogs/tune2fs.c
deleted file mode 100644
index bbe30e5a0..000000000
--- a/e2fsprogs/old_e2fsprogs/tune2fs.c
+++ /dev/null
@@ -1,710 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * tune2fs.c - Change the file system parameters on an ext2 file system
4 *
5 * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr>
6 * Laboratoire MASI, Institut Blaise Pascal
7 * Universite Pierre et Marie Curie (Paris VI)
8 *
9 * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o.
10 *
11 * Licensed under GPLv2, see file LICENSE in this source tree.
12 */
13
14/*
15 * History:
16 * 93/06/01 - Creation
17 * 93/10/31 - Added the -c option to change the maximal mount counts
18 * 93/12/14 - Added -l flag to list contents of superblock
19 * M.J.E. Mol (marcel@duteca.et.tudelft.nl)
20 * F.W. ten Wolde (franky@duteca.et.tudelft.nl)
21 * 93/12/29 - Added the -e option to change errors behavior
22 * 94/02/27 - Ported to use the ext2fs library
23 * 94/03/06 - Added the checks interval from Uwe Ohse (uwe@tirka.gun.de)
24 */
25
26#include <sys/types.h>
27#include <fcntl.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <time.h>
32#include <unistd.h>
33#include <getopt.h>
34
35#include "e2fsbb.h"
36#include "ext2fs/ext2_fs.h"
37#include "ext2fs/ext2fs.h"
38#include "uuid/uuid.h"
39#include "e2p/e2p.h"
40#include "ext2fs/kernel-jbd.h"
41#include "util.h"
42#include "blkid/blkid.h"
43
44#include "libbb.h"
45
46static char * device_name = NULL;
47static char * new_label, *new_last_mounted, *new_UUID;
48static char * io_options;
49static int c_flag, C_flag, e_flag, f_flag, g_flag, i_flag, l_flag, L_flag;
50static int m_flag, M_flag, r_flag, s_flag = -1, u_flag, U_flag, T_flag;
51static time_t last_check_time;
52static int print_label;
53static int max_mount_count, mount_count, mount_flags;
54static unsigned long interval, reserved_blocks;
55static unsigned reserved_ratio;
56static unsigned long resgid, resuid;
57static unsigned short errors;
58static int open_flag;
59static char *features_cmd;
60static char *mntopts_cmd;
61
62static int journal_size, journal_flags;
63static char *journal_device = NULL;
64
65static const char *please_fsck = "Please run e2fsck on the filesystem\n";
66
67static __u32 ok_features[3] = {
68 EXT3_FEATURE_COMPAT_HAS_JOURNAL | EXT2_FEATURE_COMPAT_DIR_INDEX,
69 EXT2_FEATURE_INCOMPAT_FILETYPE,
70 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
71};
72
73/*
74 * Remove an external journal from the filesystem
75 */
76static void remove_journal_device(ext2_filsys fs)
77{
78 char *journal_path;
79 ext2_filsys jfs;
80 char buf[1024];
81 journal_superblock_t *jsb;
82 int i, nr_users;
83 errcode_t retval;
84 int commit_remove_journal = 0;
85 io_manager io_ptr;
86
87 if (f_flag)
88 commit_remove_journal = 1; /* force removal even if error */
89
90 uuid_unparse(fs->super->s_journal_uuid, buf);
91 journal_path = blkid_get_devname(NULL, "UUID", buf);
92
93 if (!journal_path) {
94 journal_path =
95 ext2fs_find_block_device(fs->super->s_journal_dev);
96 if (!journal_path)
97 return;
98 }
99
100 io_ptr = unix_io_manager;
101 retval = ext2fs_open(journal_path, EXT2_FLAG_RW|
102 EXT2_FLAG_JOURNAL_DEV_OK, 0,
103 fs->blocksize, io_ptr, &jfs);
104 if (retval) {
105 bb_error_msg("Failed to open external journal");
106 goto no_valid_journal;
107 }
108 if (!(jfs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
109 bb_error_msg("%s is not a journal device", journal_path);
110 goto no_valid_journal;
111 }
112
113 /* Get the journal superblock */
114 if ((retval = io_channel_read_blk(jfs->io, 1, -1024, buf))) {
115 bb_error_msg("Failed to read journal superblock");
116 goto no_valid_journal;
117 }
118
119 jsb = (journal_superblock_t *) buf;
120 if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) ||
121 (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2))) {
122 bb_error_msg("Journal superblock not found!");
123 goto no_valid_journal;
124 }
125
126 /* Find the filesystem UUID */
127 nr_users = ntohl(jsb->s_nr_users);
128 for (i=0; i < nr_users; i++) {
129 if (memcmp(fs->super->s_uuid,
130 &jsb->s_users[i*16], 16) == 0)
131 break;
132 }
133 if (i >= nr_users) {
134 bb_error_msg("Filesystem's UUID not found on journal device");
135 commit_remove_journal = 1;
136 goto no_valid_journal;
137 }
138 nr_users--;
139 for (i=0; i < nr_users; i++)
140 memcpy(&jsb->s_users[i*16], &jsb->s_users[(i+1)*16], 16);
141 jsb->s_nr_users = htonl(nr_users);
142
143 /* Write back the journal superblock */
144 if ((retval = io_channel_write_blk(jfs->io, 1, -1024, buf))) {
145 bb_error_msg("Failed to write journal superblock");
146 goto no_valid_journal;
147 }
148
149 commit_remove_journal = 1;
150
151no_valid_journal:
152 if (commit_remove_journal == 0)
153 bb_error_msg_and_die("Journal NOT removed");
154 fs->super->s_journal_dev = 0;
155 uuid_clear(fs->super->s_journal_uuid);
156 ext2fs_mark_super_dirty(fs);
157 puts("Journal removed");
158 free(journal_path);
159}
160
161/* Helper function for remove_journal_inode */
162static int release_blocks_proc(ext2_filsys fs, blk_t *blocknr,
163 int blockcnt EXT2FS_ATTR((unused)),
164 void *private EXT2FS_ATTR((unused)))
165{
166 blk_t block;
167 int group;
168
169 block = *blocknr;
170 ext2fs_unmark_block_bitmap(fs->block_map,block);
171 group = ext2fs_group_of_blk(fs, block);
172 fs->group_desc[group].bg_free_blocks_count++;
173 fs->super->s_free_blocks_count++;
174 return 0;
175}
176
177/*
178 * Remove the journal inode from the filesystem
179 */
180static void remove_journal_inode(ext2_filsys fs)
181{
182 struct ext2_inode inode;
183 errcode_t retval;
184 ino_t ino = fs->super->s_journal_inum;
185 char *msg = "to read";
186 char *s = "journal inode";
187
188 retval = ext2fs_read_inode(fs, ino, &inode);
189 if (retval)
190 goto REMOVE_JOURNAL_INODE_ERROR;
191 if (ino == EXT2_JOURNAL_INO) {
192 retval = ext2fs_read_bitmaps(fs);
193 if (retval) {
194 msg = "to read bitmaps";
195 s = "";
196 goto REMOVE_JOURNAL_INODE_ERROR;
197 }
198 retval = ext2fs_block_iterate(fs, ino, 0, NULL,
199 release_blocks_proc, NULL);
200 if (retval) {
201 msg = "clearing";
202 goto REMOVE_JOURNAL_INODE_ERROR;
203 }
204 memset(&inode, 0, sizeof(inode));
205 ext2fs_mark_bb_dirty(fs);
206 fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
207 } else
208 inode.i_flags &= ~EXT2_IMMUTABLE_FL;
209 retval = ext2fs_write_inode(fs, ino, &inode);
210 if (retval) {
211 msg = "writing";
212REMOVE_JOURNAL_INODE_ERROR:
213 bb_error_msg_and_die("Failed %s %s", msg, s);
214 }
215 fs->super->s_journal_inum = 0;
216 ext2fs_mark_super_dirty(fs);
217}
218
219/*
220 * Update the default mount options
221 */
222static void update_mntopts(ext2_filsys fs, char *mntopts)
223{
224 struct ext2_super_block *sb= fs->super;
225
226 if (e2p_edit_mntopts(mntopts, &sb->s_default_mount_opts, ~0))
227 bb_error_msg_and_die("Invalid mount option set: %s", mntopts);
228 ext2fs_mark_super_dirty(fs);
229}
230
231/*
232 * Update the feature set as provided by the user.
233 */
234static void update_feature_set(ext2_filsys fs, char *features)
235{
236 int sparse, old_sparse, filetype, old_filetype;
237 int journal, old_journal, dxdir, old_dxdir;
238 struct ext2_super_block *sb= fs->super;
239 __u32 old_compat, old_incompat, old_ro_compat;
240
241 old_compat = sb->s_feature_compat;
242 old_ro_compat = sb->s_feature_ro_compat;
243 old_incompat = sb->s_feature_incompat;
244
245 old_sparse = sb->s_feature_ro_compat &
246 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
247 old_filetype = sb->s_feature_incompat &
248 EXT2_FEATURE_INCOMPAT_FILETYPE;
249 old_journal = sb->s_feature_compat &
250 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
251 old_dxdir = sb->s_feature_compat &
252 EXT2_FEATURE_COMPAT_DIR_INDEX;
253 if (e2p_edit_feature(features, &sb->s_feature_compat, ok_features))
254 bb_error_msg_and_die("Invalid filesystem option set: %s", features);
255 sparse = sb->s_feature_ro_compat &
256 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
257 filetype = sb->s_feature_incompat &
258 EXT2_FEATURE_INCOMPAT_FILETYPE;
259 journal = sb->s_feature_compat &
260 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
261 dxdir = sb->s_feature_compat &
262 EXT2_FEATURE_COMPAT_DIR_INDEX;
263 if (old_journal && !journal) {
264 if ((mount_flags & EXT2_MF_MOUNTED) &&
265 !(mount_flags & EXT2_MF_READONLY)) {
266 bb_error_msg_and_die(
267 "The has_journal flag may only be "
268 "cleared when the filesystem is\n"
269 "unmounted or mounted "
270 "read-only");
271 }
272 if (sb->s_feature_incompat &
273 EXT3_FEATURE_INCOMPAT_RECOVER) {
274 bb_error_msg_and_die(
275 "The needs_recovery flag is set. "
276 "%s before clearing the has_journal flag.",
277 please_fsck);
278 }
279 if (sb->s_journal_inum) {
280 remove_journal_inode(fs);
281 }
282 if (sb->s_journal_dev) {
283 remove_journal_device(fs);
284 }
285 }
286 if (journal && !old_journal) {
287 /*
288 * If adding a journal flag, let the create journal
289 * code below handle creating setting the flag and
290 * creating the journal. We supply a default size if
291 * necessary.
292 */
293 if (!journal_size)
294 journal_size = -1;
295 sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
296 }
297 if (dxdir && !old_dxdir) {
298 if (!sb->s_def_hash_version)
299 sb->s_def_hash_version = EXT2_HASH_TEA;
300 if (uuid_is_null((unsigned char *) sb->s_hash_seed))
301 uuid_generate((unsigned char *) sb->s_hash_seed);
302 }
303
304 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
305 (sb->s_feature_compat || sb->s_feature_ro_compat ||
306 sb->s_feature_incompat))
307 ext2fs_update_dynamic_rev(fs);
308 if ((sparse != old_sparse) ||
309 (filetype != old_filetype)) {
310 sb->s_state &= ~EXT2_VALID_FS;
311 printf("\n%s\n", please_fsck);
312 }
313 if ((old_compat != sb->s_feature_compat) ||
314 (old_ro_compat != sb->s_feature_ro_compat) ||
315 (old_incompat != sb->s_feature_incompat))
316 ext2fs_mark_super_dirty(fs);
317}
318
319/*
320 * Add a journal to the filesystem.
321 */
322static void add_journal(ext2_filsys fs)
323{
324 if (fs->super->s_feature_compat &
325 EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
326 bb_error_msg_and_die("The filesystem already has a journal");
327 }
328 if (journal_device) {
329 make_journal_device(journal_device, fs, 0, 0);
330 } else if (journal_size) {
331 make_journal_blocks(fs, journal_size, journal_flags, 0);
332 /*
333 * If the filesystem wasn't mounted, we need to force
334 * the block group descriptors out.
335 */
336 if ((mount_flags & EXT2_MF_MOUNTED) == 0)
337 fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
338 }
339 print_check_message(fs);
340}
341
342/*
343 * Busybox stuff
344 */
345static char * x_blkid_get_devname(const char *token)
346{
347 char * dev_name;
348
349 if (!(dev_name = blkid_get_devname(NULL, token, NULL)))
350 bb_error_msg_and_die("Unable to resolve '%s'", token);
351 return dev_name;
352}
353
354#ifdef CONFIG_E2LABEL
355static void parse_e2label_options(int argc, char ** argv)
356{
357 if ((argc < 2) || (argc > 3))
358 bb_show_usage();
359 io_options = strchr(argv[1], '?');
360 if (io_options)
361 *io_options++ = 0;
362 device_name = x_blkid_get_devname(argv[1]);
363 if (argc == 3) {
364 open_flag = EXT2_FLAG_RW | EXT2_FLAG_JOURNAL_DEV_OK;
365 L_flag = 1;
366 new_label = argv[2];
367 } else
368 print_label++;
369}
370#else
371#define parse_e2label_options(x,y)
372#endif
373
374static time_t parse_time(char *str)
375{
376 struct tm ts;
377
378 if (strcmp(str, "now") == 0) {
379 return time(0);
380 }
381 memset(&ts, 0, sizeof(ts));
382#ifdef HAVE_STRPTIME
383 strptime(str, "%Y%m%d%H%M%S", &ts);
384#else
385 sscanf(str, "%4d%2d%2d%2d%2d%2d", &ts.tm_year, &ts.tm_mon,
386 &ts.tm_mday, &ts.tm_hour, &ts.tm_min, &ts.tm_sec);
387 ts.tm_year -= 1900;
388 ts.tm_mon -= 1;
389 if (ts.tm_year < 0 || ts.tm_mon < 0 || ts.tm_mon > 11 ||
390 ts.tm_mday < 0 || ts.tm_mday > 31 || ts.tm_hour > 23 ||
391 ts.tm_min > 59 || ts.tm_sec > 61)
392 ts.tm_mday = 0;
393#endif
394 if (ts.tm_mday == 0) {
395 bb_error_msg_and_die("can't parse date/time specifier: %s", str);
396 }
397 return mktime(&ts);
398}
399
400static void parse_tune2fs_options(int argc, char **argv)
401{
402 int c;
403 char * tmp;
404
405 printf("tune2fs %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE);
406 while ((c = getopt(argc, argv, "c:e:fg:i:jlm:o:r:s:u:C:J:L:M:O:T:U:")) != EOF)
407 switch (c)
408 {
409 case 'c':
410 max_mount_count = xatou_range(optarg, 0, 16000);
411 if (max_mount_count == 0)
412 max_mount_count = -1;
413 c_flag = 1;
414 open_flag = EXT2_FLAG_RW;
415 break;
416 case 'C':
417 mount_count = xatou_range(optarg, 0, 16000);
418 C_flag = 1;
419 open_flag = EXT2_FLAG_RW;
420 break;
421 case 'e':
422 if (strcmp (optarg, "continue") == 0)
423 errors = EXT2_ERRORS_CONTINUE;
424 else if (strcmp (optarg, "remount-ro") == 0)
425 errors = EXT2_ERRORS_RO;
426 else if (strcmp (optarg, "panic") == 0)
427 errors = EXT2_ERRORS_PANIC;
428 else {
429 bb_error_msg_and_die("bad error behavior - %s", optarg);
430 }
431 e_flag = 1;
432 open_flag = EXT2_FLAG_RW;
433 break;
434 case 'f': /* Force */
435 f_flag = 1;
436 break;
437 case 'g':
438 resgid = bb_strtoul(optarg, NULL, 10);
439 if (errno)
440 resgid = xgroup2gid(optarg);
441 g_flag = 1;
442 open_flag = EXT2_FLAG_RW;
443 break;
444 case 'i':
445 interval = strtoul(optarg, &tmp, 0);
446 switch (*tmp) {
447 case 's':
448 tmp++;
449 break;
450 case '\0':
451 case 'd':
452 case 'D': /* days */
453 interval *= 86400;
454 if (*tmp != '\0')
455 tmp++;
456 break;
457 case 'm':
458 case 'M': /* months! */
459 interval *= 86400 * 30;
460 tmp++;
461 break;
462 case 'w':
463 case 'W': /* weeks */
464 interval *= 86400 * 7;
465 tmp++;
466 break;
467 }
468 if (*tmp || interval > (365 * 86400)) {
469 bb_error_msg_and_die("bad interval - %s", optarg);
470 }
471 i_flag = 1;
472 open_flag = EXT2_FLAG_RW;
473 break;
474 case 'j':
475 if (!journal_size)
476 journal_size = -1;
477 open_flag = EXT2_FLAG_RW;
478 break;
479 case 'J':
480 parse_journal_opts(&journal_device, &journal_flags, &journal_size, optarg);
481 open_flag = EXT2_FLAG_RW;
482 break;
483 case 'l':
484 l_flag = 1;
485 break;
486 case 'L':
487 new_label = optarg;
488 L_flag = 1;
489 open_flag = EXT2_FLAG_RW |
490 EXT2_FLAG_JOURNAL_DEV_OK;
491 break;
492 case 'm':
493 reserved_ratio = xatou_range(optarg, 0, 50);
494 m_flag = 1;
495 open_flag = EXT2_FLAG_RW;
496 break;
497 case 'M':
498 new_last_mounted = optarg;
499 M_flag = 1;
500 open_flag = EXT2_FLAG_RW;
501 break;
502 case 'o':
503 if (mntopts_cmd) {
504 bb_error_msg_and_die("-o may only be specified once");
505 }
506 mntopts_cmd = optarg;
507 open_flag = EXT2_FLAG_RW;
508 break;
509
510 case 'O':
511 if (features_cmd) {
512 bb_error_msg_and_die("-O may only be specified once");
513 }
514 features_cmd = optarg;
515 open_flag = EXT2_FLAG_RW;
516 break;
517 case 'r':
518 reserved_blocks = xatoul(optarg);
519 r_flag = 1;
520 open_flag = EXT2_FLAG_RW;
521 break;
522 case 's':
523 s_flag = atoi(optarg);
524 open_flag = EXT2_FLAG_RW;
525 break;
526 case 'T':
527 T_flag = 1;
528 last_check_time = parse_time(optarg);
529 open_flag = EXT2_FLAG_RW;
530 break;
531 case 'u':
532 resuid = bb_strtoul(optarg, NULL, 10);
533 if (errno)
534 resuid = xuname2uid(optarg);
535 u_flag = 1;
536 open_flag = EXT2_FLAG_RW;
537 break;
538 case 'U':
539 new_UUID = optarg;
540 U_flag = 1;
541 open_flag = EXT2_FLAG_RW |
542 EXT2_FLAG_JOURNAL_DEV_OK;
543 break;
544 default:
545 bb_show_usage();
546 }
547 if (optind < argc - 1 || optind == argc)
548 bb_show_usage();
549 if (!open_flag && !l_flag)
550 bb_show_usage();
551 io_options = strchr(argv[optind], '?');
552 if (io_options)
553 *io_options++ = 0;
554 device_name = x_blkid_get_devname(argv[optind]);
555}
556
557static void tune2fs_clean_up(void)
558{
559 if (ENABLE_FEATURE_CLEAN_UP && device_name) free(device_name);
560 if (ENABLE_FEATURE_CLEAN_UP && journal_device) free(journal_device);
561}
562
563int tune2fs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
564int tune2fs_main(int argc, char **argv)
565{
566 errcode_t retval;
567 ext2_filsys fs;
568 struct ext2_super_block *sb;
569 io_manager io_ptr;
570
571 if (ENABLE_FEATURE_CLEAN_UP)
572 atexit(tune2fs_clean_up);
573
574 if (ENABLE_E2LABEL && (applet_name[0] == 'e')) /* e2label */
575 parse_e2label_options(argc, argv);
576 else
577 parse_tune2fs_options(argc, argv); /* tune2fs */
578
579 io_ptr = unix_io_manager;
580 retval = ext2fs_open2(device_name, io_options, open_flag,
581 0, 0, io_ptr, &fs);
582 if (retval)
583 bb_error_msg_and_die("No valid superblock on %s", device_name);
584 sb = fs->super;
585 if (print_label) {
586 /* For e2label emulation */
587 printf("%.*s\n", (int) sizeof(sb->s_volume_name),
588 sb->s_volume_name);
589 return 0;
590 }
591 retval = ext2fs_check_if_mounted(device_name, &mount_flags);
592 if (retval)
593 bb_error_msg_and_die("can't determine if %s is mounted", device_name);
594 /* Normally we only need to write out the superblock */
595 fs->flags |= EXT2_FLAG_SUPER_ONLY;
596
597 if (c_flag) {
598 sb->s_max_mnt_count = max_mount_count;
599 ext2fs_mark_super_dirty(fs);
600 printf("Setting maximal mount count to %d\n", max_mount_count);
601 }
602 if (C_flag) {
603 sb->s_mnt_count = mount_count;
604 ext2fs_mark_super_dirty(fs);
605 printf("Setting current mount count to %d\n", mount_count);
606 }
607 if (e_flag) {
608 sb->s_errors = errors;
609 ext2fs_mark_super_dirty(fs);
610 printf("Setting error behavior to %u\n", errors);
611 }
612 if (g_flag) {
613 sb->s_def_resgid = resgid;
614 ext2fs_mark_super_dirty(fs);
615 printf("Setting reserved blocks gid to %lu\n", resgid);
616 }
617 if (i_flag) {
618 sb->s_checkinterval = interval;
619 ext2fs_mark_super_dirty(fs);
620 printf("Setting interval between check %lu seconds\n", interval);
621 }
622 if (m_flag) {
623 sb->s_r_blocks_count = (sb->s_blocks_count / 100)
624 * reserved_ratio;
625 ext2fs_mark_super_dirty(fs);
626 printf("Setting reserved blocks percentage to %u (%u blocks)\n",
627 reserved_ratio, sb->s_r_blocks_count);
628 }
629 if (r_flag) {
630 if (reserved_blocks >= sb->s_blocks_count/2)
631 bb_error_msg_and_die("reserved blocks count is too big (%lu)", reserved_blocks);
632 sb->s_r_blocks_count = reserved_blocks;
633 ext2fs_mark_super_dirty(fs);
634 printf("Setting reserved blocks count to %lu\n", reserved_blocks);
635 }
636 if (s_flag == 1) {
637 if (sb->s_feature_ro_compat &
638 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)
639 bb_error_msg("\nThe filesystem already has sparse superblocks");
640 else {
641 sb->s_feature_ro_compat |=
642 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
643 sb->s_state &= ~EXT2_VALID_FS;
644 ext2fs_mark_super_dirty(fs);
645 printf("\nSparse superblock flag set. %s", please_fsck);
646 }
647 }
648 if (s_flag == 0) {
649 if (!(sb->s_feature_ro_compat &
650 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
651 bb_error_msg("\nThe filesystem already has sparse superblocks disabled");
652 else {
653 sb->s_feature_ro_compat &=
654 ~EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
655 sb->s_state &= ~EXT2_VALID_FS;
656 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
657 ext2fs_mark_super_dirty(fs);
658 printf("\nSparse superblock flag cleared. %s", please_fsck);
659 }
660 }
661 if (T_flag) {
662 sb->s_lastcheck = last_check_time;
663 ext2fs_mark_super_dirty(fs);
664 printf("Setting time filesystem last checked to %s\n",
665 ctime(&last_check_time));
666 }
667 if (u_flag) {
668 sb->s_def_resuid = resuid;
669 ext2fs_mark_super_dirty(fs);
670 printf("Setting reserved blocks uid to %lu\n", resuid);
671 }
672 if (L_flag) {
673 if (strlen(new_label) > sizeof(sb->s_volume_name))
674 bb_error_msg("Warning: label too long, truncating");
675 memset(sb->s_volume_name, 0, sizeof(sb->s_volume_name));
676 safe_strncpy(sb->s_volume_name, new_label,
677 sizeof(sb->s_volume_name));
678 ext2fs_mark_super_dirty(fs);
679 }
680 if (M_flag) {
681 memset(sb->s_last_mounted, 0, sizeof(sb->s_last_mounted));
682 safe_strncpy(sb->s_last_mounted, new_last_mounted,
683 sizeof(sb->s_last_mounted));
684 ext2fs_mark_super_dirty(fs);
685 }
686 if (mntopts_cmd)
687 update_mntopts(fs, mntopts_cmd);
688 if (features_cmd)
689 update_feature_set(fs, features_cmd);
690 if (journal_size || journal_device)
691 add_journal(fs);
692
693 if (U_flag) {
694 if ((strcasecmp(new_UUID, "null") == 0) ||
695 (strcasecmp(new_UUID, "clear") == 0)) {
696 uuid_clear(sb->s_uuid);
697 } else if (strcasecmp(new_UUID, "time") == 0) {
698 uuid_generate_time(sb->s_uuid);
699 } else if (strcasecmp(new_UUID, "random") == 0) {
700 uuid_generate(sb->s_uuid);
701 } else if (uuid_parse(new_UUID, sb->s_uuid)) {
702 bb_error_msg_and_die("Invalid UUID format");
703 }
704 ext2fs_mark_super_dirty(fs);
705 }
706
707 if (l_flag)
708 list_super (sb);
709 return (ext2fs_close (fs) ? 1 : 0);
710}
diff --git a/e2fsprogs/old_e2fsprogs/util.c b/e2fsprogs/old_e2fsprogs/util.c
deleted file mode 100644
index 3e7ee8e75..000000000
--- a/e2fsprogs/old_e2fsprogs/util.c
+++ /dev/null
@@ -1,263 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * util.c --- helper functions used by tune2fs and mke2fs
4 *
5 * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o.
6 *
7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */
9
10#include <stdio.h>
11#include <string.h>
12#include <errno.h>
13#include <linux/major.h>
14#include <sys/stat.h>
15
16#include "e2fsbb.h"
17#include "e2p/e2p.h"
18#include "ext2fs/ext2_fs.h"
19#include "ext2fs/ext2fs.h"
20#include "blkid/blkid.h"
21#include "util.h"
22
23void proceed_question(void)
24{
25 fputs("Proceed anyway? (y,n) ", stdout);
26 if (bb_ask_confirmation() == 0)
27 exit(1);
28}
29
30void check_plausibility(const char *device, int force)
31{
32 int val;
33 struct stat s;
34 val = stat(device, &s);
35 if (force)
36 return;
37 if (val == -1)
38 bb_perror_msg_and_die("can't stat '%s'", device);
39 if (!S_ISBLK(s.st_mode)) {
40 printf("%s is not a block special device.\n", device);
41 proceed_question();
42 return;
43 }
44
45#ifdef HAVE_LINUX_MAJOR_H
46#ifndef MAJOR
47#define MAJOR(dev) ((dev)>>8)
48#define MINOR(dev) ((dev) & 0xff)
49#endif
50#ifndef SCSI_BLK_MAJOR
51#ifdef SCSI_DISK0_MAJOR
52#ifdef SCSI_DISK8_MAJOR
53#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
54 ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR) || \
55 ((M) >= SCSI_DISK8_MAJOR && (M) <= SCSI_DISK15_MAJOR))
56#else
57#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
58 ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
59#endif /* defined(SCSI_DISK8_MAJOR) */
60#define SCSI_BLK_MAJOR(M) (SCSI_DISK_MAJOR((M)) || (M) == SCSI_CDROM_MAJOR)
61#else
62#define SCSI_BLK_MAJOR(M) ((M) == SCSI_DISK_MAJOR || (M) == SCSI_CDROM_MAJOR)
63#endif /* defined(SCSI_DISK0_MAJOR) */
64#endif /* defined(SCSI_BLK_MAJOR) */
65 if (((MAJOR(s.st_rdev) == HD_MAJOR &&
66 MINOR(s.st_rdev)%64 == 0) ||
67 (SCSI_BLK_MAJOR(MAJOR(s.st_rdev)) &&
68 MINOR(s.st_rdev)%16 == 0))) {
69 printf("%s is entire device, not just one partition!\n", device);
70 proceed_question();
71 }
72#endif
73}
74
75void check_mount(const char *device, int force, const char *type)
76{
77 errcode_t retval;
78 int mount_flags;
79
80 retval = ext2fs_check_if_mounted(device, &mount_flags);
81 if (retval) {
82 bb_error_msg("can't determine if %s is mounted", device);
83 return;
84 }
85 if (mount_flags & EXT2_MF_MOUNTED) {
86 bb_error_msg("%s is mounted !", device);
87force_check:
88 if (force)
89 bb_error_msg("badblocks forced anyways");
90 else
91 bb_error_msg_and_die("it's not safe to run badblocks!");
92 }
93
94 if (mount_flags & EXT2_MF_BUSY) {
95 bb_error_msg("%s is apparently in use by the system", device);
96 goto force_check;
97 }
98}
99
100void parse_journal_opts(char **journal_device, int *journal_flags,
101 int *journal_size, const char *opts)
102{
103 char *buf, *token, *next, *p, *arg;
104 int journal_usage = 0;
105 buf = xstrdup(opts);
106 for (token = buf; token && *token; token = next) {
107 p = strchr(token, ',');
108 next = 0;
109 if (p) {
110 *p = 0;
111 next = p+1;
112 }
113 arg = strchr(token, '=');
114 if (arg) {
115 *arg = 0;
116 arg++;
117 }
118 if (strcmp(token, "device") == 0) {
119 *journal_device = blkid_get_devname(NULL, arg, NULL);
120 if (!*journal_device) {
121 journal_usage++;
122 continue;
123 }
124 } else if (strcmp(token, "size") == 0) {
125 if (!arg) {
126 journal_usage++;
127 continue;
128 }
129 (*journal_size) = strtoul(arg, &p, 0);
130 if (*p)
131 journal_usage++;
132 } else if (strcmp(token, "v1_superblock") == 0) {
133 (*journal_flags) |= EXT2_MKJOURNAL_V1_SUPER;
134 continue;
135 } else
136 journal_usage++;
137 }
138 if (journal_usage)
139 bb_error_msg_and_die(
140 "\nBad journal options specified.\n\n"
141 "Journal options are separated by commas, "
142 "and may take an argument which\n"
143 "\tis set off by an equals ('=') sign.\n\n"
144 "Valid journal options are:\n"
145 "\tsize=<journal size in megabytes>\n"
146 "\tdevice=<journal device>\n\n"
147 "The journal size must be between "
148 "1024 and 102400 filesystem blocks.\n\n");
149}
150
151/*
152 * Determine the number of journal blocks to use, either via
153 * user-specified # of megabytes, or via some intelligently selected
154 * defaults.
155 *
156 * Find a reasonable journal file size (in blocks) given the number of blocks
157 * in the filesystem. For very small filesystems, it is not reasonable to
158 * have a journal that fills more than half of the filesystem.
159 */
160int figure_journal_size(int size, ext2_filsys fs)
161{
162 blk_t j_blocks;
163
164 if (fs->super->s_blocks_count < 2048) {
165 bb_error_msg("Filesystem too small for a journal");
166 return 0;
167 }
168
169 if (size >= 0) {
170 j_blocks = size * 1024 / (fs->blocksize / 1024);
171 if (j_blocks < 1024 || j_blocks > 102400)
172 bb_error_msg_and_die("\nThe requested journal "
173 "size is %d blocks;\n it must be "
174 "between 1024 and 102400 blocks; Aborting",
175 j_blocks);
176 if (j_blocks > fs->super->s_free_blocks_count)
177 bb_error_msg_and_die("Journal size too big for filesystem");
178 return j_blocks;
179 }
180
181 if (fs->super->s_blocks_count < 32768)
182 j_blocks = 1024;
183 else if (fs->super->s_blocks_count < 256*1024)
184 j_blocks = 4096;
185 else if (fs->super->s_blocks_count < 512*1024)
186 j_blocks = 8192;
187 else if (fs->super->s_blocks_count < 1024*1024)
188 j_blocks = 16384;
189 else
190 j_blocks = 32768;
191
192 return j_blocks;
193}
194
195void print_check_message(ext2_filsys fs)
196{
197 printf("This filesystem will be automatically "
198 "checked every %d mounts or\n"
199 "%g days, whichever comes first. "
200 "Use tune2fs -c or -i to override.\n",
201 fs->super->s_max_mnt_count,
202 (double)fs->super->s_checkinterval / (3600 * 24));
203}
204
205void make_journal_device(char *journal_device, ext2_filsys fs, int quiet, int force)
206{
207 errcode_t retval;
208 ext2_filsys jfs;
209 io_manager io_ptr;
210
211 check_plausibility(journal_device, force);
212 check_mount(journal_device, force, "journal");
213 io_ptr = unix_io_manager;
214 retval = ext2fs_open(journal_device, EXT2_FLAG_RW|
215 EXT2_FLAG_JOURNAL_DEV_OK, 0,
216 fs->blocksize, io_ptr, &jfs);
217 if (retval)
218 bb_error_msg_and_die("can't journal device %s", journal_device);
219 if (!quiet)
220 printf("Adding journal to device %s: ", journal_device);
221 fflush(stdout);
222 retval = ext2fs_add_journal_device(fs, jfs);
223 if (retval)
224 bb_error_msg_and_die("\nFailed to add journal to device %s", journal_device);
225 if (!quiet)
226 puts("done");
227 ext2fs_close(jfs);
228}
229
230void make_journal_blocks(ext2_filsys fs, int journal_size, int journal_flags, int quiet)
231{
232 unsigned long journal_blocks;
233 errcode_t retval;
234
235 journal_blocks = figure_journal_size(journal_size, fs);
236 if (!journal_blocks) {
237 fs->super->s_feature_compat &=
238 ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
239 return;
240 }
241 if (!quiet)
242 printf("Creating journal (%lu blocks): ", journal_blocks);
243 fflush(stdout);
244 retval = ext2fs_add_journal_inode(fs, journal_blocks,
245 journal_flags);
246 if (retval)
247 bb_error_msg_and_die("can't create journal");
248 if (!quiet)
249 puts("done");
250}
251
252char *e2fs_set_sbin_path(void)
253{
254 char *oldpath = getenv("PATH");
255 /* Update our PATH to include /sbin */
256#define PATH_SET "/sbin"
257 if (oldpath)
258 oldpath = xasprintf("%s:%s", PATH_SET, oldpath);
259 else
260 oldpath = PATH_SET;
261 putenv(oldpath);
262 return oldpath;
263}
diff --git a/e2fsprogs/old_e2fsprogs/util.h b/e2fsprogs/old_e2fsprogs/util.h
deleted file mode 100644
index 80d241718..000000000
--- a/e2fsprogs/old_e2fsprogs/util.h
+++ /dev/null
@@ -1,22 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * util.h --- header file defining prototypes for helper functions
4 * used by tune2fs and mke2fs
5 *
6 * Copyright 2000 by Theodore Ts'o.
7 *
8 * %Begin-Header%
9 * This file may be redistributed under the terms of the GNU Public
10 * License.
11 * %End-Header%
12 */
13
14extern void proceed_question(void);
15extern void check_plausibility(const char *device, int force);
16extern void parse_journal_opts(char **, int *, int *, const char *opts);
17extern void check_mount(const char *device, int force, const char *type);
18extern int figure_journal_size(int size, ext2_filsys fs);
19extern void print_check_message(ext2_filsys fs);
20extern void make_journal_device(char *journal_device, ext2_filsys fs, int quiet, int force);
21extern void make_journal_blocks(ext2_filsys fs, int journal_size, int journal_flags, int quiet);
22extern char *e2fs_set_sbin_path(void);
diff --git a/e2fsprogs/old_e2fsprogs/uuid/Kbuild.src b/e2fsprogs/old_e2fsprogs/uuid/Kbuild.src
deleted file mode 100644
index b8c687d30..000000000
--- a/e2fsprogs/old_e2fsprogs/uuid/Kbuild.src
+++ /dev/null
@@ -1,16 +0,0 @@
1# Makefile for busybox
2#
3# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
4#
5# Licensed under GPLv2, see file LICENSE in this source tree.
6
7NEEDED-$(CONFIG_E2FSCK) = y
8NEEDED-$(CONFIG_FSCK) = y
9NEEDED-$(CONFIG_MKE2FS) = y
10NEEDED-$(CONFIG_TUNE2FS) = y
11
12lib-y:=
13
14INSERT
15lib-$(NEEDED-y) += compare.o gen_uuid.o pack.o parse.o unpack.o unparse.o \
16 uuid_time.o
diff --git a/e2fsprogs/old_e2fsprogs/uuid/compare.c b/e2fsprogs/old_e2fsprogs/uuid/compare.c
deleted file mode 100644
index 348ea7c1f..000000000
--- a/e2fsprogs/old_e2fsprogs/uuid/compare.c
+++ /dev/null
@@ -1,55 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * compare.c --- compare whether or not two UUID's are the same
4 *
5 * Returns 0 if the two UUID's are different, and 1 if they are the same.
6 *
7 * Copyright (C) 1996, 1997 Theodore Ts'o.
8 *
9 * %Begin-Header%
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, and the entire permission notice in its entirety,
15 * including the disclaimer of warranties.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote
20 * products derived from this software without specific prior
21 * written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
26 * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
29 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
33 * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
34 * DAMAGE.
35 * %End-Header%
36 */
37
38#include "uuidP.h"
39#include <string.h>
40
41#define UUCMP(u1,u2) if (u1 != u2) return (u1 < u2) ? -1 : 1;
42
43int uuid_compare(const uuid_t uu1, const uuid_t uu2)
44{
45 struct uuid uuid1, uuid2;
46
47 uuid_unpack(uu1, &uuid1);
48 uuid_unpack(uu2, &uuid2);
49
50 UUCMP(uuid1.time_low, uuid2.time_low);
51 UUCMP(uuid1.time_mid, uuid2.time_mid);
52 UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version);
53 UUCMP(uuid1.clock_seq, uuid2.clock_seq);
54 return memcmp(uuid1.node, uuid2.node, 6);
55}
diff --git a/e2fsprogs/old_e2fsprogs/uuid/gen_uuid.c b/e2fsprogs/old_e2fsprogs/uuid/gen_uuid.c
deleted file mode 100644
index 4310c17db..000000000
--- a/e2fsprogs/old_e2fsprogs/uuid/gen_uuid.c
+++ /dev/null
@@ -1,304 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * gen_uuid.c --- generate a DCE-compatible uuid
4 *
5 * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, and the entire permission notice in its entirety,
13 * including the disclaimer of warranties.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote
18 * products derived from this software without specific prior
19 * written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
24 * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
32 * DAMAGE.
33 * %End-Header%
34 */
35
36#include <unistd.h>
37#include <stdlib.h>
38#include <string.h>
39#include <fcntl.h>
40#include <errno.h>
41#include <sys/types.h>
42#include <sys/stat.h>
43#include <sys/file.h>
44#include <sys/time.h>
45#ifdef HAVE_SYS_IOCTL_H
46#include <sys/ioctl.h>
47#endif
48#include <sys/socket.h>
49#ifdef HAVE_SYS_SOCKIO_H
50#include <sys/sockio.h>
51#endif
52#ifdef HAVE_NET_IF_H
53#include <net/if.h>
54#endif
55#ifdef HAVE_NETINET_IN_H
56#include <netinet/in.h>
57#endif
58#ifdef HAVE_NET_IF_DL_H
59#include <net/if_dl.h>
60#endif
61
62#include "uuidP.h"
63
64#ifdef HAVE_SRANDOM
65#define srand(x) srandom(x)
66#define rand() random()
67#endif
68
69static int get_random_fd(void)
70{
71 struct timeval tv;
72 static int fd = -2;
73 int i;
74
75 if (fd == -2) {
76 gettimeofday(&tv, 0);
77 fd = open("/dev/urandom", O_RDONLY);
78 if (fd == -1)
79 fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
80 srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
81 }
82 /* Crank the random number generator a few times */
83 gettimeofday(&tv, 0);
84 for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
85 rand();
86 return fd;
87}
88
89
90/*
91 * Generate a series of random bytes. Use /dev/urandom if possible,
92 * and if not, use srandom/random.
93 */
94static void get_random_bytes(void *buf, int nbytes)
95{
96 int i, n = nbytes, fd = get_random_fd();
97 int lose_counter = 0;
98 unsigned char *cp = (unsigned char *) buf;
99
100 if (fd >= 0) {
101 while (n > 0) {
102 i = read(fd, cp, n);
103 if (i <= 0) {
104 if (lose_counter++ > 16)
105 break;
106 continue;
107 }
108 n -= i;
109 cp += i;
110 lose_counter = 0;
111 }
112 }
113
114 /*
115 * We do this all the time, but this is the only source of
116 * randomness if /dev/random/urandom is out to lunch.
117 */
118 for (cp = buf, i = 0; i < nbytes; i++)
119 *cp++ ^= (rand() >> 7) & 0xFF;
120}
121
122/*
123 * Get the ethernet hardware address, if we can find it...
124 */
125static int get_node_id(unsigned char *node_id)
126{
127#ifdef HAVE_NET_IF_H
128 int sd;
129 struct ifreq ifr, *ifrp;
130 struct ifconf ifc;
131 char buf[1024];
132 int n, i;
133 unsigned char *a;
134#ifdef HAVE_NET_IF_DL_H
135 struct sockaddr_dl *sdlp;
136#endif
137
138/*
139 * BSD 4.4 defines the size of an ifreq to be
140 * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
141 * However, under earlier systems, sa_len isn't present, so the size is
142 * just sizeof(struct ifreq)
143 */
144#ifdef HAVE_SA_LEN
145#ifndef max
146#define max(a,b) ((a) > (b) ? (a) : (b))
147#endif
148#define ifreq_size(i) max(sizeof(struct ifreq),\
149 sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
150#else
151#define ifreq_size(i) sizeof(struct ifreq)
152#endif /* HAVE_SA_LEN*/
153
154 sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
155 if (sd < 0) {
156 return -1;
157 }
158 memset(buf, 0, sizeof(buf));
159 ifc.ifc_len = sizeof(buf);
160 ifc.ifc_buf = buf;
161 if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) {
162 close(sd);
163 return -1;
164 }
165 n = ifc.ifc_len;
166 for (i = 0; i < n; i+= ifreq_size(*ifrp) ) {
167 ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
168 strncpy_IFNAMSIZ(ifr.ifr_name, ifrp->ifr_name);
169#ifdef SIOCGIFHWADDR
170 if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
171 continue;
172 a = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
173#else
174#ifdef SIOCGENADDR
175 if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
176 continue;
177 a = (unsigned char *) ifr.ifr_enaddr;
178#else
179#ifdef HAVE_NET_IF_DL_H
180 sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr;
181 if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6))
182 continue;
183 a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen];
184#else
185 /*
186 * XXX we don't have a way of getting the hardware
187 * address
188 */
189 close(sd);
190 return 0;
191#endif /* HAVE_NET_IF_DL_H */
192#endif /* SIOCGENADDR */
193#endif /* SIOCGIFHWADDR */
194 if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
195 continue;
196 if (node_id) {
197 memcpy(node_id, a, 6);
198 close(sd);
199 return 1;
200 }
201 }
202 close(sd);
203#endif
204 return 0;
205}
206
207/* Assume that the gettimeofday() has microsecond granularity */
208#define MAX_ADJUSTMENT 10
209
210static int get_clock(uint32_t *clock_high, uint32_t *clock_low, uint16_t *ret_clock_seq)
211{
212 static int adjustment = 0;
213 static struct timeval last = {0, 0};
214 static uint16_t clock_seq;
215 struct timeval tv;
216 unsigned long long clock_reg;
217
218try_again:
219 gettimeofday(&tv, 0);
220 if ((last.tv_sec == 0) && (last.tv_usec == 0)) {
221 get_random_bytes(&clock_seq, sizeof(clock_seq));
222 clock_seq &= 0x3FFF;
223 last = tv;
224 last.tv_sec--;
225 }
226 if ((tv.tv_sec < last.tv_sec) ||
227 ((tv.tv_sec == last.tv_sec) &&
228 (tv.tv_usec < last.tv_usec))) {
229 clock_seq = (clock_seq+1) & 0x3FFF;
230 adjustment = 0;
231 last = tv;
232 } else if ((tv.tv_sec == last.tv_sec) &&
233 (tv.tv_usec == last.tv_usec)) {
234 if (adjustment >= MAX_ADJUSTMENT)
235 goto try_again;
236 adjustment++;
237 } else {
238 adjustment = 0;
239 last = tv;
240 }
241
242 clock_reg = tv.tv_usec*10 + adjustment;
243 clock_reg += ((unsigned long long) tv.tv_sec)*10000000;
244 clock_reg += (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000;
245
246 *clock_high = clock_reg >> 32;
247 *clock_low = clock_reg;
248 *ret_clock_seq = clock_seq;
249 return 0;
250}
251
252void uuid_generate_time(uuid_t out)
253{
254 static unsigned char node_id[6];
255 static int has_init = 0;
256 struct uuid uu;
257 uint32_t clock_mid;
258
259 if (!has_init) {
260 if (get_node_id(node_id) <= 0) {
261 get_random_bytes(node_id, 6);
262 /*
263 * Set multicast bit, to prevent conflicts
264 * with IEEE 802 addresses obtained from
265 * network cards
266 */
267 node_id[0] |= 0x01;
268 }
269 has_init = 1;
270 }
271 get_clock(&clock_mid, &uu.time_low, &uu.clock_seq);
272 uu.clock_seq |= 0x8000;
273 uu.time_mid = (uint16_t) clock_mid;
274 uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000;
275 memcpy(uu.node, node_id, 6);
276 uuid_pack(&uu, out);
277}
278
279void uuid_generate_random(uuid_t out)
280{
281 uuid_t buf;
282 struct uuid uu;
283
284 get_random_bytes(buf, sizeof(buf));
285 uuid_unpack(buf, &uu);
286
287 uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
288 uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000;
289 uuid_pack(&uu, out);
290}
291
292/*
293 * This is the generic front-end to uuid_generate_random and
294 * uuid_generate_time. It uses uuid_generate_random only if
295 * /dev/urandom is available, since otherwise we won't have
296 * high-quality randomness.
297 */
298void uuid_generate(uuid_t out)
299{
300 if (get_random_fd() >= 0)
301 uuid_generate_random(out);
302 else
303 uuid_generate_time(out);
304}
diff --git a/e2fsprogs/old_e2fsprogs/uuid/pack.c b/e2fsprogs/old_e2fsprogs/uuid/pack.c
deleted file mode 100644
index 217cfce5d..000000000
--- a/e2fsprogs/old_e2fsprogs/uuid/pack.c
+++ /dev/null
@@ -1,69 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Internal routine for packing UUID's
4 *
5 * Copyright (C) 1996, 1997 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, and the entire permission notice in its entirety,
13 * including the disclaimer of warranties.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote
18 * products derived from this software without specific prior
19 * written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
24 * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
32 * DAMAGE.
33 * %End-Header%
34 */
35
36#include <string.h>
37#include "uuidP.h"
38
39void uuid_pack(const struct uuid *uu, uuid_t ptr)
40{
41 uint32_t tmp;
42 unsigned char *out = ptr;
43
44 tmp = uu->time_low;
45 out[3] = (unsigned char) tmp;
46 tmp >>= 8;
47 out[2] = (unsigned char) tmp;
48 tmp >>= 8;
49 out[1] = (unsigned char) tmp;
50 tmp >>= 8;
51 out[0] = (unsigned char) tmp;
52
53 tmp = uu->time_mid;
54 out[5] = (unsigned char) tmp;
55 tmp >>= 8;
56 out[4] = (unsigned char) tmp;
57
58 tmp = uu->time_hi_and_version;
59 out[7] = (unsigned char) tmp;
60 tmp >>= 8;
61 out[6] = (unsigned char) tmp;
62
63 tmp = uu->clock_seq;
64 out[9] = (unsigned char) tmp;
65 tmp >>= 8;
66 out[8] = (unsigned char) tmp;
67
68 memcpy(out+10, uu->node, 6);
69}
diff --git a/e2fsprogs/old_e2fsprogs/uuid/parse.c b/e2fsprogs/old_e2fsprogs/uuid/parse.c
deleted file mode 100644
index 9a3f9cb92..000000000
--- a/e2fsprogs/old_e2fsprogs/uuid/parse.c
+++ /dev/null
@@ -1,80 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * parse.c --- UUID parsing
4 *
5 * Copyright (C) 1996, 1997 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, and the entire permission notice in its entirety,
13 * including the disclaimer of warranties.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote
18 * products derived from this software without specific prior
19 * written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
24 * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
32 * DAMAGE.
33 * %End-Header%
34 */
35
36#include <stdlib.h>
37#include <stdio.h>
38#include <ctype.h>
39#include <string.h>
40
41#include "uuidP.h"
42
43int uuid_parse(const char *in, uuid_t uu)
44{
45 struct uuid uuid;
46 int i;
47 const char *cp;
48 char buf[3];
49
50 if (strlen(in) != 36)
51 return -1;
52 for (i=0, cp = in; i <= 36; i++,cp++) {
53 if ((i == 8) || (i == 13) || (i == 18) ||
54 (i == 23)) {
55 if (*cp == '-')
56 continue;
57 else
58 return -1;
59 }
60 if (i== 36)
61 if (*cp == 0)
62 continue;
63 if (!isxdigit(*cp))
64 return -1;
65 }
66 uuid.time_low = strtoul(in, NULL, 16);
67 uuid.time_mid = strtoul(in+9, NULL, 16);
68 uuid.time_hi_and_version = strtoul(in+14, NULL, 16);
69 uuid.clock_seq = strtoul(in+19, NULL, 16);
70 cp = in+24;
71 buf[2] = 0;
72 for (i=0; i < 6; i++) {
73 buf[0] = *cp++;
74 buf[1] = *cp++;
75 uuid.node[i] = strtoul(buf, NULL, 16);
76 }
77
78 uuid_pack(&uuid, uu);
79 return 0;
80}
diff --git a/e2fsprogs/old_e2fsprogs/uuid/unpack.c b/e2fsprogs/old_e2fsprogs/uuid/unpack.c
deleted file mode 100644
index 95d3aab4a..000000000
--- a/e2fsprogs/old_e2fsprogs/uuid/unpack.c
+++ /dev/null
@@ -1,63 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Internal routine for unpacking UUID
4 *
5 * Copyright (C) 1996, 1997 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, and the entire permission notice in its entirety,
13 * including the disclaimer of warranties.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote
18 * products derived from this software without specific prior
19 * written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
24 * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
32 * DAMAGE.
33 * %End-Header%
34 */
35
36#include <string.h>
37#include "uuidP.h"
38
39void uuid_unpack(const uuid_t in, struct uuid *uu)
40{
41 const uint8_t *ptr = in;
42 uint32_t tmp;
43
44 tmp = *ptr++;
45 tmp = (tmp << 8) | *ptr++;
46 tmp = (tmp << 8) | *ptr++;
47 tmp = (tmp << 8) | *ptr++;
48 uu->time_low = tmp;
49
50 tmp = *ptr++;
51 tmp = (tmp << 8) | *ptr++;
52 uu->time_mid = tmp;
53
54 tmp = *ptr++;
55 tmp = (tmp << 8) | *ptr++;
56 uu->time_hi_and_version = tmp;
57
58 tmp = *ptr++;
59 tmp = (tmp << 8) | *ptr++;
60 uu->clock_seq = tmp;
61
62 memcpy(uu->node, ptr, 6);
63}
diff --git a/e2fsprogs/old_e2fsprogs/uuid/unparse.c b/e2fsprogs/old_e2fsprogs/uuid/unparse.c
deleted file mode 100644
index d2948fe6d..000000000
--- a/e2fsprogs/old_e2fsprogs/uuid/unparse.c
+++ /dev/null
@@ -1,77 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * unparse.c -- convert a UUID to string
4 *
5 * Copyright (C) 1996, 1997 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, and the entire permission notice in its entirety,
13 * including the disclaimer of warranties.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote
18 * products derived from this software without specific prior
19 * written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
24 * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
32 * DAMAGE.
33 * %End-Header%
34 */
35
36#include <stdio.h>
37
38#include "uuidP.h"
39
40static const char *fmt_lower =
41 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
42
43static const char *fmt_upper =
44 "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X";
45
46#ifdef UUID_UNPARSE_DEFAULT_UPPER
47#define FMT_DEFAULT fmt_upper
48#else
49#define FMT_DEFAULT fmt_lower
50#endif
51
52static void uuid_unparse_x(const uuid_t uu, char *out, const char *fmt)
53{
54 struct uuid uuid;
55
56 uuid_unpack(uu, &uuid);
57 sprintf(out, fmt,
58 uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
59 uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
60 uuid.node[0], uuid.node[1], uuid.node[2],
61 uuid.node[3], uuid.node[4], uuid.node[5]);
62}
63
64void uuid_unparse_lower(const uuid_t uu, char *out)
65{
66 uuid_unparse_x(uu, out, fmt_lower);
67}
68
69void uuid_unparse_upper(const uuid_t uu, char *out)
70{
71 uuid_unparse_x(uu, out, fmt_upper);
72}
73
74void uuid_unparse(const uuid_t uu, char *out)
75{
76 uuid_unparse_x(uu, out, FMT_DEFAULT);
77}
diff --git a/e2fsprogs/old_e2fsprogs/uuid/uuid.h b/e2fsprogs/old_e2fsprogs/uuid/uuid.h
deleted file mode 100644
index 7a9706449..000000000
--- a/e2fsprogs/old_e2fsprogs/uuid/uuid.h
+++ /dev/null
@@ -1,103 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Public include file for the UUID library
4 *
5 * Copyright (C) 1996, 1997, 1998 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, and the entire permission notice in its entirety,
13 * including the disclaimer of warranties.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote
18 * products derived from this software without specific prior
19 * written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
24 * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
32 * DAMAGE.
33 * %End-Header%
34 */
35#ifndef UUID_UUID_H
36#define UUID_UUID_H 1
37
38#include <sys/types.h>
39#include <time.h>
40
41typedef unsigned char uuid_t[16];
42
43/* UUID Variant definitions */
44#define UUID_VARIANT_NCS 0
45#define UUID_VARIANT_DCE 1
46#define UUID_VARIANT_MICROSOFT 2
47#define UUID_VARIANT_OTHER 3
48
49/* UUID Type definitions */
50#define UUID_TYPE_DCE_TIME 1
51#define UUID_TYPE_DCE_RANDOM 4
52
53/* Allow UUID constants to be defined */
54#ifdef __GNUC__
55#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \
56 static const uuid_t name UNUSED_PARAM = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15}
57#else
58#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \
59 static const uuid_t name = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15}
60#endif
61
62#ifdef __cplusplus
63extern "C" {
64#endif
65
66/* clear.c */
67/*void uuid_clear(uuid_t uu);*/
68#define uuid_clear(uu) memset(uu, 0, sizeof(uu))
69
70/* compare.c */
71int uuid_compare(const uuid_t uu1, const uuid_t uu2);
72
73/* copy.c */
74/*void uuid_copy(uuid_t dst, const uuid_t src);*/
75#define uuid_copy(dst,src) memcpy(dst, src, sizeof(dst))
76
77/* gen_uuid.c */
78void uuid_generate(uuid_t out);
79void uuid_generate_random(uuid_t out);
80void uuid_generate_time(uuid_t out);
81
82/* isnull.c */
83/*int uuid_is_null(const uuid_t uu);*/
84#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)))
85
86/* parse.c */
87int uuid_parse(const char *in, uuid_t uu);
88
89/* unparse.c */
90void uuid_unparse(const uuid_t uu, char *out);
91void uuid_unparse_lower(const uuid_t uu, char *out);
92void uuid_unparse_upper(const uuid_t uu, char *out);
93
94/* uuid_time.c */
95time_t uuid_time(const uuid_t uu, struct timeval *ret_tv);
96int uuid_type(const uuid_t uu);
97int uuid_variant(const uuid_t uu);
98
99#ifdef __cplusplus
100}
101#endif
102
103#endif /* _UUID_UUID_H */
diff --git a/e2fsprogs/old_e2fsprogs/uuid/uuidP.h b/e2fsprogs/old_e2fsprogs/uuid/uuidP.h
deleted file mode 100644
index 87041ef0a..000000000
--- a/e2fsprogs/old_e2fsprogs/uuid/uuidP.h
+++ /dev/null
@@ -1,60 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * uuid.h -- private header file for uuids
4 *
5 * Copyright (C) 1996, 1997 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, and the entire permission notice in its entirety,
13 * including the disclaimer of warranties.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote
18 * products derived from this software without specific prior
19 * written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
24 * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
32 * DAMAGE.
33 * %End-Header%
34 */
35
36#include <inttypes.h>
37#include <sys/types.h>
38
39#include "uuid.h"
40
41/*
42 * Offset between 15-Oct-1582 and 1-Jan-70
43 */
44#define TIME_OFFSET_HIGH 0x01B21DD2
45#define TIME_OFFSET_LOW 0x13814000
46
47struct uuid {
48 uint32_t time_low;
49 uint16_t time_mid;
50 uint16_t time_hi_and_version;
51 uint16_t clock_seq;
52 uint8_t node[6];
53};
54
55
56/*
57 * prototypes
58 */
59void uuid_pack(const struct uuid *uu, uuid_t ptr);
60void uuid_unpack(const uuid_t in, struct uuid *uu);
diff --git a/e2fsprogs/old_e2fsprogs/uuid/uuid_time.c b/e2fsprogs/old_e2fsprogs/uuid/uuid_time.c
deleted file mode 100644
index b6f73e6dc..000000000
--- a/e2fsprogs/old_e2fsprogs/uuid/uuid_time.c
+++ /dev/null
@@ -1,161 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * uuid_time.c --- Interpret the time field from a uuid. This program
4 * violates the UUID abstraction barrier by reaching into the guts
5 * of a UUID and interpreting it.
6 *
7 * Copyright (C) 1998, 1999 Theodore Ts'o.
8 *
9 * %Begin-Header%
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, and the entire permission notice in its entirety,
15 * including the disclaimer of warranties.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote
20 * products derived from this software without specific prior
21 * written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
26 * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
29 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
33 * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
34 * DAMAGE.
35 * %End-Header%
36 */
37
38#include <stdio.h>
39#include <unistd.h>
40#include <stdlib.h>
41#include <sys/types.h>
42#include <time.h>
43
44#include "uuidP.h"
45
46time_t uuid_time(const uuid_t uu, struct timeval *ret_tv)
47{
48 struct uuid uuid;
49 uint32_t high;
50 struct timeval tv;
51 unsigned long long clock_reg;
52
53 uuid_unpack(uu, &uuid);
54
55 high = uuid.time_mid | ((uuid.time_hi_and_version & 0xFFF) << 16);
56 clock_reg = uuid.time_low | ((unsigned long long) high << 32);
57
58 clock_reg -= (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000;
59 tv.tv_sec = clock_reg / 10000000;
60 tv.tv_usec = (clock_reg % 10000000) / 10;
61
62 if (ret_tv)
63 *ret_tv = tv;
64
65 return tv.tv_sec;
66}
67
68int uuid_type(const uuid_t uu)
69{
70 struct uuid uuid;
71
72 uuid_unpack(uu, &uuid);
73 return ((uuid.time_hi_and_version >> 12) & 0xF);
74}
75
76int uuid_variant(const uuid_t uu)
77{
78 struct uuid uuid;
79 int var;
80
81 uuid_unpack(uu, &uuid);
82 var = uuid.clock_seq;
83
84 if ((var & 0x8000) == 0)
85 return UUID_VARIANT_NCS;
86 if ((var & 0x4000) == 0)
87 return UUID_VARIANT_DCE;
88 if ((var & 0x2000) == 0)
89 return UUID_VARIANT_MICROSOFT;
90 return UUID_VARIANT_OTHER;
91}
92
93#ifdef DEBUG
94static const char *variant_string(int variant)
95{
96 switch (variant) {
97 case UUID_VARIANT_NCS:
98 return "NCS";
99 case UUID_VARIANT_DCE:
100 return "DCE";
101 case UUID_VARIANT_MICROSOFT:
102 return "Microsoft";
103 default:
104 return "Other";
105 }
106}
107
108
109int
110main(int argc, char **argv)
111{
112 uuid_t buf;
113 time_t time_reg;
114 struct timeval tv;
115 int type, variant;
116
117 if (argc != 2) {
118 fprintf(stderr, "Usage: %s uuid\n", argv[0]);
119 exit(1);
120 }
121 if (uuid_parse(argv[1], buf)) {
122 fprintf(stderr, "Invalid UUID: %s\n", argv[1]);
123 exit(1);
124 }
125 variant = uuid_variant(buf);
126 type = uuid_type(buf);
127 time_reg = uuid_time(buf, &tv);
128
129 printf("UUID variant is %d (%s)\n", variant, variant_string(variant));
130 if (variant != UUID_VARIANT_DCE) {
131 printf("Warning: This program only knows how to interpret "
132 "DCE UUIDs.\n\tThe rest of the output is likely "
133 "to be incorrect!!\n");
134 }
135 printf("UUID type is %d", type);
136 switch (type) {
137 case 1:
138 printf(" (time based)\n");
139 break;
140 case 2:
141 printf(" (DCE)\n");
142 break;
143 case 3:
144 printf(" (name-based)\n");
145 break;
146 case 4:
147 printf(" (random)\n");
148 break;
149 default:
150 bb_putchar('\n');
151 }
152 if (type != 1) {
153 printf("Warning: not a time-based UUID, so UUID time "
154 "decoding will likely not work!\n");
155 }
156 printf("UUID time is: (%ld, %ld): %s\n", tv.tv_sec, tv.tv_usec,
157 ctime(&time_reg));
158
159 return 0;
160}
161#endif
diff --git a/editors/diff.c b/editors/diff.c
index cf14b1d03..e0adcee59 100644
--- a/editors/diff.c
+++ b/editors/diff.c
@@ -658,8 +658,8 @@ static bool diff(FILE* fp[2], char *file[2])
658 } 658 }
659 659
660 for (j = 0; j < 2; j++) 660 for (j = 0; j < 2; j++)
661 for (k = v[j].a; k < v[j].b; k++) 661 for (k = v[j].a; k <= v[j].b; k++)
662 nonempty |= (ix[j][k+1] - ix[j][k] != 1); 662 nonempty |= (ix[j][k] - ix[j][k - 1] != 1);
663 663
664 vec = xrealloc_vector(vec, 6, ++idx); 664 vec = xrealloc_vector(vec, 6, ++idx);
665 memcpy(vec[idx], v, sizeof(v)); 665 memcpy(vec[idx], v, sizeof(v));
diff --git a/include/applets.src.h b/include/applets.src.h
index b80c4f4e8..9f3ac78cb 100644
--- a/include/applets.src.h
+++ b/include/applets.src.h
@@ -337,7 +337,6 @@ IF_SVLOGD(APPLET(svlogd, BB_DIR_USR_SBIN, BB_SUID_DROP))
337IF_SWAPONOFF(APPLET_ODDNAME(swapoff, swap_on_off, BB_DIR_SBIN, BB_SUID_DROP, swapoff)) 337IF_SWAPONOFF(APPLET_ODDNAME(swapoff, swap_on_off, BB_DIR_SBIN, BB_SUID_DROP, swapoff))
338IF_SWAPONOFF(APPLET_ODDNAME(swapon, swap_on_off, BB_DIR_SBIN, BB_SUID_DROP, swapon)) 338IF_SWAPONOFF(APPLET_ODDNAME(swapon, swap_on_off, BB_DIR_SBIN, BB_SUID_DROP, swapon))
339IF_SWITCH_ROOT(APPLET(switch_root, BB_DIR_SBIN, BB_SUID_DROP)) 339IF_SWITCH_ROOT(APPLET(switch_root, BB_DIR_SBIN, BB_SUID_DROP))
340IF_SYNC(APPLET_NOFORK(sync, sync, BB_DIR_BIN, BB_SUID_DROP, sync))
341IF_BB_SYSCTL(APPLET(sysctl, BB_DIR_SBIN, BB_SUID_DROP)) 340IF_BB_SYSCTL(APPLET(sysctl, BB_DIR_SBIN, BB_SUID_DROP))
342IF_SYSLOGD(APPLET(syslogd, BB_DIR_SBIN, BB_SUID_DROP)) 341IF_SYSLOGD(APPLET(syslogd, BB_DIR_SBIN, BB_SUID_DROP))
343IF_TAC(APPLET_NOEXEC(tac, tac, BB_DIR_USR_BIN, BB_SUID_DROP, tac)) 342IF_TAC(APPLET_NOEXEC(tac, tac, BB_DIR_USR_BIN, BB_SUID_DROP, tac))
diff --git a/include/libbb.h b/include/libbb.h
index eb53312cd..729704974 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -684,6 +684,7 @@ uint16_t inet_cksum(uint16_t *addr, int len) FAST_FUNC;
684 684
685char *xstrdup(const char *s) FAST_FUNC RETURNS_MALLOC; 685char *xstrdup(const char *s) FAST_FUNC RETURNS_MALLOC;
686char *xstrndup(const char *s, int n) FAST_FUNC RETURNS_MALLOC; 686char *xstrndup(const char *s, int n) FAST_FUNC RETURNS_MALLOC;
687void *xmemdup(const void *s, int n) FAST_FUNC RETURNS_MALLOC;
687void overlapping_strcpy(char *dst, const char *src) FAST_FUNC; 688void overlapping_strcpy(char *dst, const char *src) FAST_FUNC;
688char *safe_strncpy(char *dst, const char *src, size_t size) FAST_FUNC; 689char *safe_strncpy(char *dst, const char *src, size_t size) FAST_FUNC;
689char *strncpy_IFNAMSIZ(char *dst, const char *src) FAST_FUNC; 690char *strncpy_IFNAMSIZ(char *dst, const char *src) FAST_FUNC;
diff --git a/libbb/procps.c b/libbb/procps.c
index b597b74f9..32dae43e3 100644
--- a/libbb/procps.c
+++ b/libbb/procps.c
@@ -555,8 +555,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
555 break; 555 break;
556 if (flags & PSSCAN_ARGVN) { 556 if (flags & PSSCAN_ARGVN) {
557 sp->argv_len = n; 557 sp->argv_len = n;
558 sp->argv0 = xmalloc(n + 1); 558 sp->argv0 = xmemdup(buf, n + 1);
559 memcpy(sp->argv0, buf, n + 1);
560 /* sp->argv0[n] = '\0'; - buf has it */ 559 /* sp->argv0[n] = '\0'; - buf has it */
561 } else { 560 } else {
562 sp->argv_len = 0; 561 sp->argv_len = 0;
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c
index e4ac6a002..73488908d 100644
--- a/libbb/xfuncs_printf.c
+++ b/libbb/xfuncs_printf.c
@@ -112,6 +112,11 @@ char* FAST_FUNC xstrndup(const char *s, int n)
112 return memcpy(t, s, n); 112 return memcpy(t, s, n);
113} 113}
114 114
115void* FAST_FUNC xmemdup(const void *s, int n)
116{
117 return memcpy(xmalloc(n), s, n);
118}
119
115// Die if we can't open a file and return a FILE* to it. 120// Die if we can't open a file and return a FILE* to it.
116// Notice we haven't got xfread(), This is for use with fscanf() and friends. 121// Notice we haven't got xfread(), This is for use with fscanf() and friends.
117FILE* FAST_FUNC xfopen(const char *path, const char *mode) 122FILE* FAST_FUNC xfopen(const char *path, const char *mode)
diff --git a/miscutils/last_fancy.c b/miscutils/last_fancy.c
index 8194e31b5..e56e0ba85 100644
--- a/miscutils/last_fancy.c
+++ b/miscutils/last_fancy.c
@@ -233,7 +233,7 @@ int last_main(int argc UNUSED_PARAM, char **argv)
233 break; 233 break;
234 } 234 }
235 /* add_entry */ 235 /* add_entry */
236 llist_add_to(&zlist, memcpy(xmalloc(sizeof(ut)), &ut, sizeof(ut))); 236 llist_add_to(&zlist, xmemdup(&ut, sizeof(ut)));
237 break; 237 break;
238 case USER_PROCESS: { 238 case USER_PROCESS: {
239 int show; 239 int show;
@@ -275,7 +275,7 @@ int last_main(int argc UNUSED_PARAM, char **argv)
275 show_entry(&ut, state, boot_time); 275 show_entry(&ut, state, boot_time);
276 } 276 }
277 /* add_entry */ 277 /* add_entry */
278 llist_add_to(&zlist, memcpy(xmalloc(sizeof(ut)), &ut, sizeof(ut))); 278 llist_add_to(&zlist, xmemdup(&ut, sizeof(ut)));
279 break; 279 break;
280 } 280 }
281 } 281 }
diff --git a/miscutils/less.c b/miscutils/less.c
index d5a68d1e1..7a441bf7e 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -48,6 +48,14 @@
48//config: help 48//config: help
49//config: The -M/-m flag enables a more sophisticated status line. 49//config: The -M/-m flag enables a more sophisticated status line.
50//config: 50//config:
51//config:config FEATURE_LESS_TRUNCATE
52//config: bool "Enable -S"
53//config: default y
54//config: depends on LESS
55//config: help
56//config: The -S flag causes long lines to be truncated rather than
57//config: wrapped.
58//config:
51//config:config FEATURE_LESS_MARKS 59//config:config FEATURE_LESS_MARKS
52//config: bool "Enable marks" 60//config: bool "Enable marks"
53//config: default y 61//config: default y
@@ -98,7 +106,8 @@
98//config: Enables "-N" command. 106//config: Enables "-N" command.
99 107
100//usage:#define less_trivial_usage 108//usage:#define less_trivial_usage
101//usage: "[-E" IF_FEATURE_LESS_REGEXP("I")IF_FEATURE_LESS_FLAGS("Mm") "Nh~] [FILE]..." 109//usage: "[-E" IF_FEATURE_LESS_REGEXP("I")IF_FEATURE_LESS_FLAGS("Mm")
110//usage: "N" IF_FEATURE_LESS_TRUNCATE("S") "h~] [FILE]..."
102//usage:#define less_full_usage "\n\n" 111//usage:#define less_full_usage "\n\n"
103//usage: "View FILE (or stdin) one screenful at a time\n" 112//usage: "View FILE (or stdin) one screenful at a time\n"
104//usage: "\n -E Quit once the end of a file is reached" 113//usage: "\n -E Quit once the end of a file is reached"
@@ -110,6 +119,9 @@
110//usage: "\n and percentage through the file" 119//usage: "\n and percentage through the file"
111//usage: ) 120//usage: )
112//usage: "\n -N Prefix line number to each line" 121//usage: "\n -N Prefix line number to each line"
122//usage: IF_FEATURE_LESS_TRUNCATE(
123//usage: "\n -S Truncate long lines"
124//usage: )
113//usage: "\n -~ Suppress ~s displayed past EOF" 125//usage: "\n -~ Suppress ~s displayed past EOF"
114 126
115#include <sched.h> /* sched_yield() */ 127#include <sched.h> /* sched_yield() */
@@ -144,7 +156,7 @@ enum {
144 FLAG_N = 1 << 3, 156 FLAG_N = 1 << 3,
145 FLAG_TILDE = 1 << 4, 157 FLAG_TILDE = 1 << 4,
146 FLAG_I = 1 << 5, 158 FLAG_I = 1 << 5,
147 FLAG_S = (1 << 6) * ENABLE_FEATURE_LESS_DASHCMD, 159 FLAG_S = (1 << 6) * ENABLE_FEATURE_LESS_TRUNCATE,
148/* hijack command line options variable for internal state vars */ 160/* hijack command line options variable for internal state vars */
149 LESS_STATE_MATCH_BACKWARDS = 1 << 15, 161 LESS_STATE_MATCH_BACKWARDS = 1 << 15,
150}; 162};
@@ -176,6 +188,12 @@ struct globals {
176 unsigned current_file; 188 unsigned current_file;
177 char *filename; 189 char *filename;
178 char **files; 190 char **files;
191#if ENABLE_FEATURE_LESS_FLAGS
192 int num_lines; /* a flag if < 0, line count if >= 0 */
193# define REOPEN_AND_COUNT (-1)
194# define REOPEN_STDIN (-2)
195# define NOT_REGULAR_FILE (-3)
196#endif
179#if ENABLE_FEATURE_LESS_MARKS 197#if ENABLE_FEATURE_LESS_MARKS
180 unsigned num_marks; 198 unsigned num_marks;
181 unsigned mark_lines[15][2]; 199 unsigned mark_lines[15][2];
@@ -217,6 +235,7 @@ struct globals {
217#define current_file (G.current_file ) 235#define current_file (G.current_file )
218#define filename (G.filename ) 236#define filename (G.filename )
219#define files (G.files ) 237#define files (G.files )
238#define num_lines (G.num_lines )
220#define num_marks (G.num_marks ) 239#define num_marks (G.num_marks )
221#define mark_lines (G.mark_lines ) 240#define mark_lines (G.mark_lines )
222#if ENABLE_FEATURE_LESS_REGEXP 241#if ENABLE_FEATURE_LESS_REGEXP
@@ -319,8 +338,10 @@ static void re_wrap(void)
319 *d = *s; 338 *d = *s;
320 if (*d != '\0') { 339 if (*d != '\0') {
321 new_line_pos++; 340 new_line_pos++;
322 if (*d == '\t') /* tab */ 341 if (*d == '\t') { /* tab */
323 new_line_pos += 7; 342 new_line_pos += 7;
343 new_line_pos &= (~7);
344 }
324 s++; 345 s++;
325 d++; 346 d++;
326 if (new_line_pos >= w) { 347 if (new_line_pos >= w) {
@@ -382,6 +403,14 @@ static void fill_match_lines(unsigned pos);
382#define fill_match_lines(pos) ((void)0) 403#define fill_match_lines(pos) ((void)0)
383#endif 404#endif
384 405
406static int at_end(void)
407{
408 return (option_mask32 & FLAG_S)
409 ? !(cur_fline <= max_fline &&
410 max_lineno > LINENO(flines[cur_fline]) + max_displayed_line)
411 : !(max_fline > cur_fline + max_displayed_line);
412}
413
385/* Devilishly complex routine. 414/* Devilishly complex routine.
386 * 415 *
387 * Has to deal with EOF and EPIPE on input, 416 * Has to deal with EOF and EPIPE on input,
@@ -480,16 +509,6 @@ static void read_lines(void)
480 *--p = '\0'; 509 *--p = '\0';
481 continue; 510 continue;
482 } 511 }
483 {
484 size_t new_last_line_pos = last_line_pos + 1;
485 if (c == '\t') {
486 new_last_line_pos += 7;
487 new_last_line_pos &= (~7);
488 }
489 if ((int)new_last_line_pos >= w)
490 break;
491 last_line_pos = new_last_line_pos;
492 }
493 /* ok, we will eat this char */ 512 /* ok, we will eat this char */
494 readpos++; 513 readpos++;
495 if (c == '\n') { 514 if (c == '\n') {
@@ -501,6 +520,16 @@ static void read_lines(void)
501 if (c == '\0') c = '\n'; 520 if (c == '\0') c = '\n';
502 *p++ = c; 521 *p++ = c;
503 *p = '\0'; 522 *p = '\0';
523 {
524 size_t new_last_line_pos = last_line_pos + 1;
525 if (c == '\t') {
526 new_last_line_pos += 7;
527 new_last_line_pos &= (~7);
528 }
529 if ((int)new_last_line_pos >= w)
530 break;
531 last_line_pos = new_last_line_pos;
532 }
504 } /* end of "read chars until we have a line" loop */ 533 } /* end of "read chars until we have a line" loop */
505#if 0 534#if 0
506//BUG: also triggers on this: 535//BUG: also triggers on this:
@@ -528,11 +557,7 @@ static void read_lines(void)
528 eof_error = 0; /* Pretend we saw EOF */ 557 eof_error = 0; /* Pretend we saw EOF */
529 break; 558 break;
530 } 559 }
531 if (!(option_mask32 & FLAG_S) 560 if (!at_end()) {
532 ? (max_fline > cur_fline + max_displayed_line)
533 : (max_fline >= cur_fline
534 && max_lineno > LINENO(flines[cur_fline]) + max_displayed_line)
535 ) {
536#if !ENABLE_FEATURE_LESS_REGEXP 561#if !ENABLE_FEATURE_LESS_REGEXP
537 break; 562 break;
538#else 563#else
@@ -560,6 +585,10 @@ static void read_lines(void)
560 print_statusline(bb_msg_read_error); 585 print_statusline(bb_msg_read_error);
561 } 586 }
562 } 587 }
588#if ENABLE_FEATURE_LESS_FLAGS
589 else if (eof_error == 0)
590 num_lines = max_lineno;
591#endif
563 592
564 fill_match_lines(old_max_fline); 593 fill_match_lines(old_max_fline);
565#if ENABLE_FEATURE_LESS_REGEXP 594#if ENABLE_FEATURE_LESS_REGEXP
@@ -570,18 +599,61 @@ static void read_lines(void)
570} 599}
571 600
572#if ENABLE_FEATURE_LESS_FLAGS 601#if ENABLE_FEATURE_LESS_FLAGS
573/* Interestingly, writing calc_percent as a function saves around 32 bytes 602static int safe_lineno(int fline)
574 * on my build. */
575static int calc_percent(void)
576{ 603{
577 unsigned p = (100 * (cur_fline+max_displayed_line+1) + max_fline/2) / (max_fline+1); 604 if (fline >= max_fline)
578 return p <= 100 ? p : 100; 605 fline = max_fline - 1;
606
607 /* also catches empty file (max_fline == 0) */
608 if (fline < 0)
609 return 0;
610
611 return LINENO(flines[fline]) + 1;
612}
613
614/* count number of lines in file */
615static void update_num_lines(void)
616{
617 int count, fd;
618 struct stat stbuf;
619 ssize_t len, i;
620 char buf[4096];
621
622 /* only do this for regular files */
623 if (num_lines == REOPEN_AND_COUNT || num_lines == REOPEN_STDIN) {
624 count = 0;
625 fd = open("/proc/self/fd/0", O_RDONLY);
626 if (fd < 0 && num_lines == REOPEN_AND_COUNT) {
627 /* "filename" is valid only if REOPEN_AND_COUNT */
628 fd = open(filename, O_RDONLY);
629 }
630 if (fd < 0) {
631 /* somebody stole my file! */
632 num_lines = NOT_REGULAR_FILE;
633 return;
634 }
635 if (fstat(fd, &stbuf) != 0 || !S_ISREG(stbuf.st_mode)) {
636 num_lines = NOT_REGULAR_FILE;
637 goto do_close;
638 }
639 while ((len = safe_read(fd, buf, sizeof(buf))) > 0) {
640 for (i = 0; i < len; ++i) {
641 if (buf[i] == '\n' && ++count == MAXLINES)
642 goto done;
643 }
644 }
645 done:
646 num_lines = count;
647 do_close:
648 close(fd);
649 }
579} 650}
580 651
581/* Print a status line if -M was specified */ 652/* Print a status line if -M was specified */
582static void m_status_print(void) 653static void m_status_print(void)
583{ 654{
584 int percentage; 655 int first, last;
656 unsigned percent;
585 657
586 if (less_gets_pos >= 0) /* don't touch statusline while input is done! */ 658 if (less_gets_pos >= 0) /* don't touch statusline while input is done! */
587 return; 659 return;
@@ -590,17 +662,26 @@ static void m_status_print(void)
590 printf(HIGHLIGHT"%s", filename); 662 printf(HIGHLIGHT"%s", filename);
591 if (num_files > 1) 663 if (num_files > 1)
592 printf(" (file %i of %i)", current_file, num_files); 664 printf(" (file %i of %i)", current_file, num_files);
593 printf(" lines %i-%i/%i ", 665
594 cur_fline + 1, cur_fline + max_displayed_line + 1, 666 first = safe_lineno(cur_fline);
595 max_fline + 1); 667 last = (option_mask32 & FLAG_S)
596 if (cur_fline >= (int)(max_fline - max_displayed_line)) { 668 ? MIN(first + max_displayed_line, max_lineno)
597 printf("(END)"NORMAL); 669 : safe_lineno(cur_fline + max_displayed_line);
670 printf(" lines %i-%i", first, last);
671
672 update_num_lines();
673 if (num_lines >= 0)
674 printf("/%i", num_lines);
675
676 if (at_end()) {
677 printf(" (END)");
598 if (num_files > 1 && current_file != num_files) 678 if (num_files > 1 && current_file != num_files)
599 printf(HIGHLIGHT" - next: %s"NORMAL, files[current_file]); 679 printf(" - next: %s", files[current_file]);
600 return; 680 } else if (num_lines > 0) {
681 percent = (100 * last + num_lines/2) / num_lines;
682 printf(" %i%%", percent <= 100 ? percent : 100);
601 } 683 }
602 percentage = calc_percent(); 684 printf(NORMAL);
603 printf("%i%%"NORMAL, percentage);
604} 685}
605#endif 686#endif
606 687
@@ -622,7 +703,7 @@ static void status_print(void)
622#endif 703#endif
623 704
624 clear_line(); 705 clear_line();
625 if (cur_fline && cur_fline < (int)(max_fline - max_displayed_line)) { 706 if (cur_fline && !at_end()) {
626 bb_putchar(':'); 707 bb_putchar(':');
627 return; 708 return;
628 } 709 }
@@ -637,23 +718,6 @@ static void status_print(void)
637 print_hilite(p); 718 print_hilite(p);
638} 719}
639 720
640static void cap_cur_fline(int nlines)
641{
642 int diff;
643 if (cur_fline < 0)
644 cur_fline = 0;
645 if (cur_fline + max_displayed_line > max_fline + TILDES) {
646 cur_fline -= nlines;
647 if (cur_fline < 0)
648 cur_fline = 0;
649 diff = max_fline - (cur_fline + max_displayed_line) + TILDES;
650 /* As the number of lines requested was too large, we just move
651 * to the end of the file */
652 if (diff > 0)
653 cur_fline += diff;
654 }
655}
656
657static const char controls[] ALIGN1 = 721static const char controls[] ALIGN1 =
658 /* NUL: never encountered; TAB: not converted */ 722 /* NUL: never encountered; TAB: not converted */
659 /**/"\x01\x02\x03\x04\x05\x06\x07\x08" "\x0a\x0b\x0c\x0d\x0e\x0f" 723 /**/"\x01\x02\x03\x04\x05\x06\x07\x08" "\x0a\x0b\x0c\x0d\x0e\x0f"
@@ -665,27 +729,21 @@ static const char ctrlconv[] ALIGN1 =
665 "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x40\x4b\x4c\x4d\x4e\x4f" 729 "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x40\x4b\x4c\x4d\x4e\x4f"
666 "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"; 730 "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f";
667 731
668static void lineno_str(char *nbuf9, const char *line) 732static void print_lineno(const char *line)
669{ 733{
670 nbuf9[0] = '\0'; 734 const char *fmt = " ";
671 if (option_mask32 & FLAG_N) { 735 unsigned n = n; /* for compiler */
672 const char *fmt; 736
673 unsigned n; 737 if (line != empty_line_marker) {
674
675 if (line == empty_line_marker) {
676 memset(nbuf9, ' ', 8);
677 nbuf9[8] = '\0';
678 return;
679 }
680 /* Width of 7 preserves tab spacing in the text */ 738 /* Width of 7 preserves tab spacing in the text */
681 fmt = "%7u "; 739 fmt = "%7u ";
682 n = LINENO(line) + 1; 740 n = LINENO(line) + 1;
683 if (n > 9999999) { 741 if (n > 9999999 && MAXLINES > 9999999) {
684 n %= 10000000; 742 n %= 10000000;
685 fmt = "%07u "; 743 fmt = "%07u ";
686 } 744 }
687 sprintf(nbuf9, fmt, n);
688 } 745 }
746 printf(fmt, n);
689} 747}
690 748
691 749
@@ -698,7 +756,6 @@ static void print_found(const char *line)
698 regmatch_t match_structs; 756 regmatch_t match_structs;
699 757
700 char buf[width]; 758 char buf[width];
701 char nbuf9[9];
702 const char *str = line; 759 const char *str = line;
703 char *p = buf; 760 char *p = buf;
704 size_t n; 761 size_t n;
@@ -748,12 +805,7 @@ static void print_found(const char *line)
748 match_status = 1; 805 match_status = 1;
749 } 806 }
750 807
751 lineno_str(nbuf9, line); 808 printf("%s%s\n", growline ? growline : "", str);
752 if (!growline) {
753 printf(CLEAR_2_EOL"%s%s\n", nbuf9, str);
754 return;
755 }
756 printf(CLEAR_2_EOL"%s%s%s\n", nbuf9, growline, str);
757 free(growline); 809 free(growline);
758} 810}
759#else 811#else
@@ -763,13 +815,9 @@ void print_found(const char *line);
763static void print_ascii(const char *str) 815static void print_ascii(const char *str)
764{ 816{
765 char buf[width]; 817 char buf[width];
766 char nbuf9[9];
767 char *p; 818 char *p;
768 size_t n; 819 size_t n;
769 820
770 lineno_str(nbuf9, str);
771 printf(CLEAR_2_EOL"%s", nbuf9);
772
773 while (*str) { 821 while (*str) {
774 n = strcspn(str, controls); 822 n = strcspn(str, controls);
775 if (n) { 823 if (n) {
@@ -803,6 +851,9 @@ static void buffer_print(void)
803 851
804 move_cursor(0, 0); 852 move_cursor(0, 0);
805 for (i = 0; i <= max_displayed_line; i++) { 853 for (i = 0; i <= max_displayed_line; i++) {
854 printf(CLEAR_2_EOL);
855 if (option_mask32 & FLAG_N)
856 print_lineno(buffer[i]);
806 if (pattern_valid) 857 if (pattern_valid)
807 print_found(buffer[i]); 858 print_found(buffer[i]);
808 else 859 else
@@ -820,7 +871,7 @@ static void buffer_print(void)
820static void buffer_fill_and_print(void) 871static void buffer_fill_and_print(void)
821{ 872{
822 unsigned i; 873 unsigned i;
823#if ENABLE_FEATURE_LESS_DASHCMD 874#if ENABLE_FEATURE_LESS_TRUNCATE
824 int fpos = cur_fline; 875 int fpos = cur_fline;
825 876
826 if (option_mask32 & FLAG_S) { 877 if (option_mask32 & FLAG_S) {
@@ -852,45 +903,112 @@ static void buffer_fill_and_print(void)
852 buffer_print(); 903 buffer_print();
853} 904}
854 905
906/* move cur_fline to a given line number, reading lines if necessary */
907static void goto_lineno(int target)
908{
909 if (target <= 0 ) {
910 cur_fline = 0;
911 }
912 else if (target > LINENO(flines[cur_fline])) {
913 retry:
914 while (LINENO(flines[cur_fline]) != target && cur_fline < max_fline)
915 ++cur_fline;
916 /* target not reached but more input is available */
917 if (LINENO(flines[cur_fline]) != target && eof_error > 0) {
918 read_lines();
919 goto retry;
920 }
921 }
922 else {
923 /* search backwards through already-read lines */
924 while (LINENO(flines[cur_fline]) != target && cur_fline > 0)
925 --cur_fline;
926 }
927}
928
929static void cap_cur_fline(void)
930{
931 if ((option_mask32 & FLAG_S)) {
932 if (cur_fline > max_fline)
933 cur_fline = max_fline;
934 if (LINENO(flines[cur_fline]) + max_displayed_line > max_lineno + TILDES) {
935 goto_lineno(max_lineno - max_displayed_line + TILDES);
936 read_lines();
937 }
938 }
939 else {
940 if (cur_fline + max_displayed_line > max_fline + TILDES)
941 cur_fline = max_fline - max_displayed_line + TILDES;
942 if (cur_fline < 0)
943 cur_fline = 0;
944 }
945}
946
855/* Move the buffer up and down in the file in order to scroll */ 947/* Move the buffer up and down in the file in order to scroll */
856static void buffer_down(int nlines) 948static void buffer_down(int nlines)
857{ 949{
858 cur_fline += nlines; 950 if ((option_mask32 & FLAG_S))
951 goto_lineno(LINENO(flines[cur_fline]) + nlines);
952 else
953 cur_fline += nlines;
859 read_lines(); 954 read_lines();
860 cap_cur_fline(nlines); 955 cap_cur_fline();
861 buffer_fill_and_print(); 956 buffer_fill_and_print();
862} 957}
863 958
864static void buffer_up(int nlines) 959static void buffer_up(int nlines)
865{ 960{
866 cur_fline -= nlines; 961 if ((option_mask32 & FLAG_S)) {
867 if (cur_fline < 0) cur_fline = 0; 962 goto_lineno(LINENO(flines[cur_fline]) - nlines);
963 }
964 else {
965 cur_fline -= nlines;
966 if (cur_fline < 0)
967 cur_fline = 0;
968 }
868 read_lines(); 969 read_lines();
869 buffer_fill_and_print(); 970 buffer_fill_and_print();
870} 971}
871 972
872static void buffer_line(int linenum) 973/* display a given line where the argument can be either an index into
974 * the flines array or a line number */
975static void buffer_to_line(int linenum, int is_lineno)
873{ 976{
874 if (linenum < 0) 977 if (linenum <= 0)
875 linenum = 0; 978 cur_fline = 0;
876 cur_fline = linenum; 979 else if (is_lineno)
980 goto_lineno(linenum);
981 else
982 cur_fline = linenum;
877 read_lines(); 983 read_lines();
878 if (linenum + max_displayed_line > max_fline) 984 cap_cur_fline();
879 linenum = max_fline - max_displayed_line + TILDES;
880 if (linenum < 0)
881 linenum = 0;
882 cur_fline = linenum;
883 buffer_fill_and_print(); 985 buffer_fill_and_print();
884} 986}
885 987
988static void buffer_line(int linenum)
989{
990 buffer_to_line(linenum, FALSE);
991}
992
993static void buffer_lineno(int lineno)
994{
995 buffer_to_line(lineno, TRUE);
996}
997
886static void open_file_and_read_lines(void) 998static void open_file_and_read_lines(void)
887{ 999{
888 if (filename) { 1000 if (filename) {
889 xmove_fd(xopen(filename, O_RDONLY), STDIN_FILENO); 1001 xmove_fd(xopen(filename, O_RDONLY), STDIN_FILENO);
1002#if ENABLE_FEATURE_LESS_FLAGS
1003 num_lines = REOPEN_AND_COUNT;
1004#endif
890 } else { 1005 } else {
891 /* "less" with no arguments in argv[] */ 1006 /* "less" with no arguments in argv[] */
892 /* For status line only */ 1007 /* For status line only */
893 filename = xstrdup(bb_msg_standard_input); 1008 filename = xstrdup(bb_msg_standard_input);
1009#if ENABLE_FEATURE_LESS_FLAGS
1010 num_lines = REOPEN_STDIN;
1011#endif
894 } 1012 }
895 readpos = 0; 1013 readpos = 0;
896 readeof = 0; 1014 readeof = 0;
@@ -942,12 +1060,7 @@ static int64_t getch_nowait(void)
942 */ 1060 */
943 rd = 1; 1061 rd = 1;
944 /* Are we interested in stdin? */ 1062 /* Are we interested in stdin? */
945//TODO: reuse code for determining this 1063 if (at_end()) {
946 if (!(option_mask32 & FLAG_S)
947 ? !(max_fline > cur_fline + max_displayed_line)
948 : !(max_fline >= cur_fline
949 && max_lineno > LINENO(flines[cur_fline]) + max_displayed_line)
950 ) {
951 if (eof_error > 0) /* did NOT reach eof yet */ 1064 if (eof_error > 0) /* did NOT reach eof yet */
952 rd = 0; /* yes, we are interested in stdin */ 1065 rd = 0; /* yes, we are interested in stdin */
953 } 1066 }
@@ -1258,7 +1371,7 @@ static void number_process(int first_digit)
1258 i = 1; 1371 i = 1;
1259 while (i < sizeof(num_input)-1) { 1372 while (i < sizeof(num_input)-1) {
1260 keypress = less_getch(i + 1); 1373 keypress = less_getch(i + 1);
1261 if ((unsigned)keypress > 255 || !isdigit(num_input[i])) 1374 if ((unsigned)keypress > 255 || !isdigit(keypress))
1262 break; 1375 break;
1263 num_input[i] = keypress; 1376 num_input[i] = keypress;
1264 bb_putchar(keypress); 1377 bb_putchar(keypress);
@@ -1282,15 +1395,16 @@ static void number_process(int first_digit)
1282 buffer_up(num); 1395 buffer_up(num);
1283 break; 1396 break;
1284 case 'g': case '<': case 'G': case '>': 1397 case 'g': case '<': case 'G': case '>':
1285 cur_fline = num + max_displayed_line; 1398 buffer_lineno(num - 1);
1286 read_lines();
1287 buffer_line(num - 1);
1288 break; 1399 break;
1289 case 'p': case '%': 1400 case 'p': case '%':
1290 num = num * (max_fline / 100); /* + max_fline / 2; */ 1401#if ENABLE_FEATURE_LESS_FLAGS
1291 cur_fline = num + max_displayed_line; 1402 update_num_lines();
1292 read_lines(); 1403 num = num * (num_lines > 0 ? num_lines : max_lineno) / 100;
1293 buffer_line(num); 1404#else
1405 num = num * max_lineno / 100;
1406#endif
1407 buffer_lineno(num);
1294 break; 1408 break;
1295#if ENABLE_FEATURE_LESS_REGEXP 1409#if ENABLE_FEATURE_LESS_REGEXP
1296 case 'n': 1410 case 'n':
@@ -1330,10 +1444,12 @@ static void flag_change(void)
1330 case '~': 1444 case '~':
1331 option_mask32 ^= FLAG_TILDE; 1445 option_mask32 ^= FLAG_TILDE;
1332 break; 1446 break;
1447#if ENABLE_FEATURE_LESS_TRUNCATE
1333 case 'S': 1448 case 'S':
1334 option_mask32 ^= FLAG_S; 1449 option_mask32 ^= FLAG_S;
1335 buffer_fill_and_print(); 1450 buffer_fill_and_print();
1336 break; 1451 break;
1452#endif
1337#if ENABLE_FEATURE_LESS_LINENUMS 1453#if ENABLE_FEATURE_LESS_LINENUMS
1338 case 'N': 1454 case 'N':
1339 option_mask32 ^= FLAG_N; 1455 option_mask32 ^= FLAG_N;
@@ -1638,7 +1754,7 @@ int less_main(int argc, char **argv)
1638 * -s: condense many empty lines to one 1754 * -s: condense many empty lines to one
1639 * (used by some setups for manpage display) 1755 * (used by some setups for manpage display)
1640 */ 1756 */
1641 getopt32(argv, "EMmN~I" IF_FEATURE_LESS_DASHCMD("S") /*ignored:*/"s"); 1757 getopt32(argv, "EMmN~I" IF_FEATURE_LESS_TRUNCATE("S") /*ignored:*/"s");
1642 argc -= optind; 1758 argc -= optind;
1643 argv += optind; 1759 argv += optind;
1644 num_files = argc; 1760 num_files = argc;
diff --git a/networking/traceroute.c b/networking/traceroute.c
index 97a7a19e0..12ba614e8 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -387,15 +387,6 @@ struct globals {
387#define outudp ((struct udphdr *)(outip + 1)) 387#define outudp ((struct udphdr *)(outip + 1))
388 388
389 389
390/* libbb candidate? tftp uses this idiom too */
391static len_and_sockaddr* dup_sockaddr(const len_and_sockaddr *lsa)
392{
393 len_and_sockaddr *new_lsa = xzalloc(LSA_LEN_SIZE + lsa->len);
394 memcpy(new_lsa, lsa, LSA_LEN_SIZE + lsa->len);
395 return new_lsa;
396}
397
398
399static int 390static int
400wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to, unsigned *timestamp_us, int *left_ms) 391wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to, unsigned *timestamp_us, int *left_ms)
401{ 392{
@@ -1074,7 +1065,7 @@ common_traceroute_main(int op, char **argv)
1074 printf(" from %s", source); 1065 printf(" from %s", source);
1075 printf(", %d hops max, %d byte packets\n", max_ttl, packlen); 1066 printf(", %d hops max, %d byte packets\n", max_ttl, packlen);
1076 1067
1077 from_lsa = dup_sockaddr(dest_lsa); 1068 from_lsa = xmemdup(dest_lsa, LSA_LEN_SIZE + dest_lsa->len);
1078 lastaddr = xzalloc(dest_lsa->len); 1069 lastaddr = xzalloc(dest_lsa->len);
1079 to = xzalloc(dest_lsa->len); 1070 to = xzalloc(dest_lsa->len);
1080 seq = 0; 1071 seq = 0;
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c
index 044f04673..4e9b705b9 100644
--- a/networking/udhcp/d6_dhcpc.c
+++ b/networking/udhcp/d6_dhcpc.c
@@ -118,7 +118,7 @@ static void *d6_copy_option(uint8_t *option, uint8_t *option_end, unsigned code)
118 uint8_t *opt = d6_find_option(option, option_end, code); 118 uint8_t *opt = d6_find_option(option, option_end, code);
119 if (!opt) 119 if (!opt)
120 return opt; 120 return opt;
121 return memcpy(xmalloc(opt[3] + 4), opt, opt[3] + 4); 121 return xmemdup(opt, opt[3] + 4);
122} 122}
123 123
124static void *d6_store_blob(void *dst, const void *src, unsigned len) 124static void *d6_store_blob(void *dst, const void *src, unsigned len)
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index 9d3d1a31c..811a1a1ee 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -156,10 +156,6 @@ static const char *valid_domain_label(const char *label)
156 for (;;) { 156 for (;;) {
157 ch = *label; 157 ch = *label;
158 if ((ch|0x20) < 'a' || (ch|0x20) > 'z') { 158 if ((ch|0x20) < 'a' || (ch|0x20) > 'z') {
159 if (pos == 0) {
160 /* label must begin with letter */
161 return NULL;
162 }
163 if (ch < '0' || ch > '9') { 159 if (ch < '0' || ch > '9') {
164 if (ch == '\0' || ch == '.') 160 if (ch == '\0' || ch == '.')
165 return label; 161 return label;
diff --git a/networking/zcip.c b/networking/zcip.c
index 962ba2e60..69644b230 100644
--- a/networking/zcip.c
+++ b/networking/zcip.c
@@ -56,26 +56,26 @@ struct arp_packet {
56} PACKED; 56} PACKED;
57 57
58enum { 58enum {
59/* 169.254.0.0 */ 59 /* 169.254.0.0 */
60 LINKLOCAL_ADDR = 0xa9fe0000, 60 LINKLOCAL_ADDR = 0xa9fe0000,
61 61
62/* protocol timeout parameters, specified in seconds */ 62 /* 0-1 seconds before sending 1st probe */
63 PROBE_WAIT = 1, 63 PROBE_WAIT = 1,
64 /* 1-2 seconds between probes */
64 PROBE_MIN = 1, 65 PROBE_MIN = 1,
65 PROBE_MAX = 2, 66 PROBE_MAX = 2,
66 PROBE_NUM = 3, 67 PROBE_NUM = 3, /* total probes to send */
67 MAX_CONFLICTS = 10, 68 ANNOUNCE_INTERVAL = 2, /* 2 seconds between announces */
68 RATE_LIMIT_INTERVAL = 60, 69 ANNOUNCE_NUM = 3, /* announces to send */
69 ANNOUNCE_WAIT = 2, 70 /* if probe/announce sees a conflict, multiply RANDOM(NUM_CONFLICT) by... */
70 ANNOUNCE_NUM = 2, 71 CONFLICT_MULTIPLIER = 2,
71 ANNOUNCE_INTERVAL = 2, 72 /* if we monitor and see a conflict, how long is defend state? */
72 DEFEND_INTERVAL = 10 73 DEFEND_INTERVAL = 10
73}; 74};
74 75
75/* States during the configuration process. */ 76/* States during the configuration process. */
76enum { 77enum {
77 PROBE = 0, 78 PROBE = 0,
78 RATE_LIMIT_PROBE,
79 ANNOUNCE, 79 ANNOUNCE,
80 MONITOR, 80 MONITOR,
81 DEFEND 81 DEFEND
@@ -89,13 +89,11 @@ enum {
89}; 89};
90 90
91struct globals { 91struct globals {
92 struct sockaddr saddr; 92 struct sockaddr iface_sockaddr;
93 struct ether_addr eth_addr; 93 struct ether_addr eth_addr;
94 uint32_t localnet_ip; 94 uint32_t localnet_ip;
95} FIX_ALIASING; 95} FIX_ALIASING;
96#define G (*(struct globals*)&bb_common_bufsiz1) 96#define G (*(struct globals*)&bb_common_bufsiz1)
97#define saddr (G.saddr )
98#define eth_addr (G.eth_addr)
99#define INIT_G() do { } while (0) 97#define INIT_G() do { } while (0)
100 98
101 99
@@ -113,17 +111,24 @@ static uint32_t pick_nip(void)
113 return htonl((G.localnet_ip + 0x0100) + tmp); 111 return htonl((G.localnet_ip + 0x0100) + tmp);
114} 112}
115 113
114static const char *nip_to_a(uint32_t nip)
115{
116 struct in_addr in;
117 in.s_addr = nip;
118 return inet_ntoa(in);
119}
120
116/** 121/**
117 * Broadcast an ARP packet. 122 * Broadcast an ARP packet.
118 */ 123 */
119static void arp( 124static void arp(
120 /* int op, - always ARPOP_REQUEST */ 125 /* int op, - always ARPOP_REQUEST */
121 /* const struct ether_addr *source_eth, - always &eth_addr */ 126 /* const struct ether_addr *source_eth, - always &G.eth_addr */
122 struct in_addr source_ip, 127 uint32_t source_nip,
123 const struct ether_addr *target_eth, struct in_addr target_ip) 128 const struct ether_addr *target_eth, uint32_t target_nip)
124{ 129{
125 enum { op = ARPOP_REQUEST }; 130 enum { op = ARPOP_REQUEST };
126#define source_eth (&eth_addr) 131#define source_eth (&G.eth_addr)
127 132
128 struct arp_packet p; 133 struct arp_packet p;
129 memset(&p, 0, sizeof(p)); 134 memset(&p, 0, sizeof(p));
@@ -140,18 +145,18 @@ static void arp(
140 p.arp.arp_pln = 4; 145 p.arp.arp_pln = 4;
141 p.arp.arp_op = htons(op); 146 p.arp.arp_op = htons(op);
142 memcpy(&p.arp.arp_sha, source_eth, ETH_ALEN); 147 memcpy(&p.arp.arp_sha, source_eth, ETH_ALEN);
143 memcpy(&p.arp.arp_spa, &source_ip, sizeof(p.arp.arp_spa)); 148 memcpy(&p.arp.arp_spa, &source_nip, 4);
144 memcpy(&p.arp.arp_tha, target_eth, ETH_ALEN); 149 memcpy(&p.arp.arp_tha, target_eth, ETH_ALEN);
145 memcpy(&p.arp.arp_tpa, &target_ip, sizeof(p.arp.arp_tpa)); 150 memcpy(&p.arp.arp_tpa, &target_nip, 4);
146 151
147 // send it 152 // send it
148 // Even though sock_fd is already bound to saddr, just send() 153 // Even though sock_fd is already bound to G.iface_sockaddr, just send()
149 // won't work, because "socket is not connected" 154 // won't work, because "socket is not connected"
150 // (and connect() won't fix that, "operation not supported"). 155 // (and connect() won't fix that, "operation not supported").
151 // Thus we sendto() to saddr. I wonder which sockaddr 156 // Thus we sendto() to G.iface_sockaddr. I wonder which sockaddr
152 // (from bind() or from sendto()?) kernel actually uses 157 // (from bind() or from sendto()?) kernel actually uses
153 // to determine iface to emit the packet from... 158 // to determine iface to emit the packet from...
154 xsendto(sock_fd, &p, sizeof(p), &saddr, sizeof(saddr)); 159 xsendto(sock_fd, &p, sizeof(p), &G.iface_sockaddr, sizeof(G.iface_sockaddr));
155#undef source_eth 160#undef source_eth
156} 161}
157 162
@@ -159,18 +164,18 @@ static void arp(
159 * Run a script. 164 * Run a script.
160 * argv[0]:intf argv[1]:script_name argv[2]:junk argv[3]:NULL 165 * argv[0]:intf argv[1]:script_name argv[2]:junk argv[3]:NULL
161 */ 166 */
162static int run(char *argv[3], const char *param, struct in_addr *ip) 167static int run(char *argv[3], const char *param, uint32_t nip)
163{ 168{
164 int status; 169 int status;
165 char *addr = addr; /* for gcc */ 170 const char *addr = addr; /* for gcc */
166 const char *fmt = "%s %s %s" + 3; 171 const char *fmt = "%s %s %s" + 3;
167 172
168 argv[2] = (char*)param; 173 argv[2] = (char*)param;
169 174
170 VDBG("%s run %s %s\n", argv[0], argv[1], argv[2]); 175 VDBG("%s run %s %s\n", argv[0], argv[1], argv[2]);
171 176
172 if (ip) { 177 if (nip != 0) {
173 addr = inet_ntoa(*ip); 178 addr = nip_to_a(nip);
174 xsetenv("ip", addr); 179 xsetenv("ip", addr);
175 fmt -= 3; 180 fmt -= 3;
176 } 181 }
@@ -207,26 +212,22 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
207 212
208 // ugly trick, but I want these zeroed in one go 213 // ugly trick, but I want these zeroed in one go
209 struct { 214 struct {
210 const struct in_addr null_ip;
211 const struct ether_addr null_addr; 215 const struct ether_addr null_addr;
212 struct in_addr ip;
213 struct ifreq ifr; 216 struct ifreq ifr;
217 uint32_t chosen_nip;
214 int timeout_ms; /* must be signed */ 218 int timeout_ms; /* must be signed */
215 unsigned conflicts; 219 unsigned conflicts;
216 unsigned nprobes; 220 unsigned nprobes;
217 unsigned nclaims; 221 unsigned nclaims;
218 int ready;
219 int verbose; 222 int verbose;
220 } L; 223 } L;
221#define null_ip (L.null_ip )
222#define null_addr (L.null_addr ) 224#define null_addr (L.null_addr )
223#define ip (L.ip ) 225#define chosen_nip (L.chosen_nip)
224#define ifr (L.ifr ) 226#define ifr (L.ifr )
225#define timeout_ms (L.timeout_ms) 227#define timeout_ms (L.timeout_ms)
226#define conflicts (L.conflicts ) 228#define conflicts (L.conflicts )
227#define nprobes (L.nprobes ) 229#define nprobes (L.nprobes )
228#define nclaims (L.nclaims ) 230#define nclaims (L.nclaims )
229#define ready (L.ready )
230#define verbose (L.verbose ) 231#define verbose (L.verbose )
231 232
232 memset(&L, 0, sizeof(L)); 233 memset(&L, 0, sizeof(L));
@@ -264,11 +265,13 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
264 G.localnet_ip = ntohl(net.s_addr); 265 G.localnet_ip = ntohl(net.s_addr);
265 } 266 }
266 if (opts & 4) { // -r n.n.n.n 267 if (opts & 4) { // -r n.n.n.n
268 struct in_addr ip;
267 if (inet_aton(r_opt, &ip) == 0 269 if (inet_aton(r_opt, &ip) == 0
268 || (ntohl(ip.s_addr) & IN_CLASSB_NET) != G.localnet_ip 270 || (ntohl(ip.s_addr) & IN_CLASSB_NET) != G.localnet_ip
269 ) { 271 ) {
270 bb_error_msg_and_die("invalid link address"); 272 bb_error_msg_and_die("invalid link address");
271 } 273 }
274 chosen_nip = ip.s_addr;
272 } 275 }
273 argv += optind - 1; 276 argv += optind - 1;
274 277
@@ -282,23 +285,23 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
282 xsetenv("interface", argv_intf); 285 xsetenv("interface", argv_intf);
283 286
284 // initialize the interface (modprobe, ifup, etc) 287 // initialize the interface (modprobe, ifup, etc)
285 if (run(argv, "init", NULL)) 288 if (run(argv, "init", 0))
286 return EXIT_FAILURE; 289 return EXIT_FAILURE;
287 290
288 // initialize saddr 291 // initialize G.iface_sockaddr
289 // saddr is: { u16 sa_family; u8 sa_data[14]; } 292 // G.iface_sockaddr is: { u16 sa_family; u8 sa_data[14]; }
290 //memset(&saddr, 0, sizeof(saddr)); 293 //memset(&G.iface_sockaddr, 0, sizeof(G.iface_sockaddr));
291 //TODO: are we leaving sa_family == 0 (AF_UNSPEC)?! 294 //TODO: are we leaving sa_family == 0 (AF_UNSPEC)?!
292 safe_strncpy(saddr.sa_data, argv_intf, sizeof(saddr.sa_data)); 295 safe_strncpy(G.iface_sockaddr.sa_data, argv_intf, sizeof(G.iface_sockaddr.sa_data));
293 296
294 // bind to the interface's ARP socket 297 // bind to the interface's ARP socket
295 xbind(sock_fd, &saddr, sizeof(saddr)); 298 xbind(sock_fd, &G.iface_sockaddr, sizeof(G.iface_sockaddr));
296 299
297 // get the interface's ethernet address 300 // get the interface's ethernet address
298 //memset(&ifr, 0, sizeof(ifr)); 301 //memset(&ifr, 0, sizeof(ifr));
299 strncpy_IFNAMSIZ(ifr.ifr_name, argv_intf); 302 strncpy_IFNAMSIZ(ifr.ifr_name, argv_intf);
300 xioctl(sock_fd, SIOCGIFHWADDR, &ifr); 303 xioctl(sock_fd, SIOCGIFHWADDR, &ifr);
301 memcpy(&eth_addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN); 304 memcpy(&G.eth_addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
302 305
303 // start with some stable ip address, either a function of 306 // start with some stable ip address, either a function of
304 // the hardware address or else the last address we used. 307 // the hardware address or else the last address we used.
@@ -308,11 +311,11 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
308 // depending on when we detect conflicts. 311 // depending on when we detect conflicts.
309 { 312 {
310 uint32_t t; 313 uint32_t t;
311 move_from_unaligned32(t, ((char *)&eth_addr + 2)); 314 move_from_unaligned32(t, ((char *)&G.eth_addr + 2));
312 srand(t); 315 srand(t);
313 } 316 }
314 if (ip.s_addr == 0) 317 if (chosen_nip == 0)
315 ip.s_addr = pick_nip(); 318 chosen_nip = pick_nip();
316 319
317 // FIXME cases to handle: 320 // FIXME cases to handle:
318 // - zcip already running! 321 // - zcip already running!
@@ -331,7 +334,9 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
331 // - start with some address we want to try 334 // - start with some address we want to try
332 // - short random delay 335 // - short random delay
333 // - arp probes to see if another host uses it 336 // - arp probes to see if another host uses it
337 // 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff, ARP (0x0806): arp who-has 169.254.194.171 tell 0.0.0.0
334 // - arp announcements that we're claiming it 338 // - arp announcements that we're claiming it
339 // 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff, ARP (0x0806): arp who-has 169.254.194.171 (00:04:e2:64:23:c2) tell 169.254.194.171
335 // - use it 340 // - use it
336 // - defend it, within limits 341 // - defend it, within limits
337 // exit if: 342 // exit if:
@@ -382,78 +387,47 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
382 if (nprobes < PROBE_NUM) { 387 if (nprobes < PROBE_NUM) {
383 nprobes++; 388 nprobes++;
384 VDBG("probe/%u %s@%s\n", 389 VDBG("probe/%u %s@%s\n",
385 nprobes, argv_intf, inet_ntoa(ip)); 390 nprobes, argv_intf, nip_to_a(chosen_nip));
386 timeout_ms = PROBE_MIN * 1000; 391 timeout_ms = PROBE_MIN * 1000;
387 timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN); 392 timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN);
388 arp(/* ARPOP_REQUEST, */ 393 arp(/* ARPOP_REQUEST, */
389 /* &eth_addr, */ null_ip, 394 /* &G.eth_addr, */ 0,
390 &null_addr, ip); 395 &null_addr, chosen_nip);
391 } 396 break;
392 else {
393 // Switch to announce state.
394 state = ANNOUNCE;
395 nclaims = 0;
396 VDBG("announce/%u %s@%s\n",
397 nclaims, argv_intf, inet_ntoa(ip));
398 timeout_ms = ANNOUNCE_INTERVAL * 1000;
399 arp(/* ARPOP_REQUEST, */
400 /* &eth_addr, */ ip,
401 &eth_addr, ip);
402 } 397 }
403 break; 398 // Switch to announce state.
404 case RATE_LIMIT_PROBE:
405 // timeouts in the RATE_LIMIT_PROBE state mean no conflicting ARP packets
406 // have been received, so we can move immediately to the announce state
407 state = ANNOUNCE;
408 nclaims = 0; 399 nclaims = 0;
409 VDBG("announce/%u %s@%s\n", 400 state = ANNOUNCE;
410 nclaims, argv_intf, inet_ntoa(ip)); 401 goto send_announce;
411 timeout_ms = ANNOUNCE_INTERVAL * 1000;
412 arp(/* ARPOP_REQUEST, */
413 /* &eth_addr, */ ip,
414 &eth_addr, ip);
415 break;
416 case ANNOUNCE: 402 case ANNOUNCE:
417 // timeouts in the ANNOUNCE state mean no conflicting ARP packets 403 // timeouts in the ANNOUNCE state mean no conflicting ARP packets
418 // have been received, so we can progress through the states 404 // have been received, so we can progress through the states
419 if (nclaims < ANNOUNCE_NUM) { 405 if (nclaims < ANNOUNCE_NUM) {
406 send_announce:
420 nclaims++; 407 nclaims++;
421 VDBG("announce/%u %s@%s\n", 408 VDBG("announce/%u %s@%s\n",
422 nclaims, argv_intf, inet_ntoa(ip)); 409 nclaims, argv_intf, nip_to_a(chosen_nip));
423 timeout_ms = ANNOUNCE_INTERVAL * 1000; 410 timeout_ms = ANNOUNCE_INTERVAL * 1000;
424 arp(/* ARPOP_REQUEST, */ 411 arp(/* ARPOP_REQUEST, */
425 /* &eth_addr, */ ip, 412 /* &G.eth_addr, */ chosen_nip,
426 &eth_addr, ip); 413 &G.eth_addr, chosen_nip);
427 } 414 break;
428 else {
429 // Switch to monitor state.
430 state = MONITOR;
431 // link is ok to use earlier
432 // FIXME update filters
433 run(argv, "config", &ip);
434 ready = 1;
435 conflicts = 0;
436 timeout_ms = -1; // Never timeout in the monitor state.
437
438 // NOTE: all other exit paths
439 // should deconfig ...
440 if (QUIT)
441 return EXIT_SUCCESS;
442 } 415 }
416 // Switch to monitor state.
417 // FIXME update filters
418 run(argv, "config", chosen_nip);
419 // NOTE: all other exit paths should deconfig...
420 if (QUIT)
421 return EXIT_SUCCESS;
422 conflicts = 0;
423 timeout_ms = -1; // Never timeout in the monitor state.
424 state = MONITOR;
443 break; 425 break;
444 case DEFEND: 426 case DEFEND:
445 // We won! No ARP replies, so just go back to monitor. 427 // Defend period ended with no ARP replies - we won.
446 state = MONITOR;
447 timeout_ms = -1;
448 conflicts = 0; 428 conflicts = 0;
449 break; 429 timeout_ms = -1;
450 default: 430 state = MONITOR;
451 // Invalid, should never happen. Restart the whole protocol.
452 state = PROBE;
453 ip.s_addr = pick_nip();
454 timeout_ms = 0;
455 nprobes = 0;
456 nclaims = 0;
457 break; 431 break;
458 } // switch (state) 432 } // switch (state)
459 break; // case 0 (timeout) 433 break; // case 0 (timeout)
@@ -466,13 +440,10 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
466 unsigned diff = deadline_us - MONOTONIC_US(); 440 unsigned diff = deadline_us - MONOTONIC_US();
467 if ((int)(diff) < 0) { 441 if ((int)(diff) < 0) {
468 // Current time is greater than the expected timeout time. 442 // Current time is greater than the expected timeout time.
469 // Should never happen. 443 diff = 0;
470 VDBG("missed an expected timeout\n");
471 timeout_ms = 0;
472 } else {
473 VDBG("adjusting timeout\n");
474 timeout_ms = (diff / 1000) | 1; /* never 0 */
475 } 444 }
445 VDBG("adjusting timeout\n");
446 timeout_ms = (diff / 1000) | 1; /* never 0 */
476 } 447 }
477 448
478 if ((fds[0].revents & POLLIN) == 0) { 449 if ((fds[0].revents & POLLIN) == 0) {
@@ -480,8 +451,9 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
480 // FIXME: links routinely go down; 451 // FIXME: links routinely go down;
481 // this shouldn't necessarily exit. 452 // this shouldn't necessarily exit.
482 bb_error_msg("iface %s is down", argv_intf); 453 bb_error_msg("iface %s is down", argv_intf);
483 if (ready) { 454 if (state >= MONITOR) {
484 run(argv, "deconfig", &ip); 455 /* only if we are in MONITOR or DEFEND */
456 run(argv, "deconfig", chosen_nip);
485 } 457 }
486 return EXIT_FAILURE; 458 return EXIT_FAILURE;
487 } 459 }
@@ -492,8 +464,14 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
492 if (safe_read(sock_fd, &p, sizeof(p)) < 0) { 464 if (safe_read(sock_fd, &p, sizeof(p)) < 0) {
493 bb_perror_msg_and_die(bb_msg_read_error); 465 bb_perror_msg_and_die(bb_msg_read_error);
494 } 466 }
467
495 if (p.eth.ether_type != htons(ETHERTYPE_ARP)) 468 if (p.eth.ether_type != htons(ETHERTYPE_ARP))
496 continue; 469 continue;
470 if (p.arp.arp_op != htons(ARPOP_REQUEST)
471 && p.arp.arp_op != htons(ARPOP_REPLY)
472 ) {
473 continue;
474 }
497#ifdef DEBUG 475#ifdef DEBUG
498 { 476 {
499 struct ether_addr *sha = (struct ether_addr *) p.arp.arp_sha; 477 struct ether_addr *sha = (struct ether_addr *) p.arp.arp_sha;
@@ -511,23 +489,17 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
511 inet_ntoa(*tpa)); 489 inet_ntoa(*tpa));
512 } 490 }
513#endif 491#endif
514 if (p.arp.arp_op != htons(ARPOP_REQUEST)
515 && p.arp.arp_op != htons(ARPOP_REPLY)
516 ) {
517 continue;
518 }
519
520 source_ip_conflict = 0; 492 source_ip_conflict = 0;
521 target_ip_conflict = 0; 493 target_ip_conflict = 0;
522 494
523 if (memcmp(&p.arp.arp_sha, &eth_addr, ETH_ALEN) != 0) { 495 if (memcmp(&p.arp.arp_sha, &G.eth_addr, ETH_ALEN) != 0) {
524 if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr)) == 0) { 496 if (memcmp(p.arp.arp_spa, &chosen_nip, 4) == 0) {
525 /* A probe or reply with source_ip == chosen ip */ 497 /* A probe or reply with source_ip == chosen ip */
526 source_ip_conflict = 1; 498 source_ip_conflict = 1;
527 } 499 }
528 if (p.arp.arp_op == htons(ARPOP_REQUEST) 500 if (p.arp.arp_op == htons(ARPOP_REQUEST)
529 && memcmp(p.arp.arp_spa, &null_ip, sizeof(struct in_addr)) == 0 501 && memcmp(p.arp.arp_spa, &const_int_0, 4) == 0
530 && memcmp(p.arp.arp_tpa, &ip.s_addr, sizeof(struct in_addr)) == 0 502 && memcmp(p.arp.arp_tpa, &chosen_nip, 4) == 0
531 ) { 503 ) {
532 /* A probe with source_ip == 0.0.0.0, target_ip == chosen ip: 504 /* A probe with source_ip == 0.0.0.0, target_ip == chosen ip:
533 * another host trying to claim this ip! 505 * another host trying to claim this ip!
@@ -545,54 +517,39 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
545 // and other hosts doing ARP probes (target IP conflicts). 517 // and other hosts doing ARP probes (target IP conflicts).
546 if (source_ip_conflict || target_ip_conflict) { 518 if (source_ip_conflict || target_ip_conflict) {
547 conflicts++; 519 conflicts++;
548 if (conflicts >= MAX_CONFLICTS) { 520 timeout_ms = PROBE_MIN * 1000
549 VDBG("%s ratelimit\n", argv_intf); 521 + CONFLICT_MULTIPLIER * random_delay_ms(conflicts);
550 timeout_ms = RATE_LIMIT_INTERVAL * 1000; 522 chosen_nip = pick_nip();
551 state = RATE_LIMIT_PROBE;
552 }
553
554 // restart the whole protocol
555 ip.s_addr = pick_nip();
556 timeout_ms = 0;
557 nprobes = 0; 523 nprobes = 0;
558 nclaims = 0; 524 nclaims = 0;
525 state = PROBE;
559 } 526 }
560 break; 527 break;
561 case MONITOR: 528 case MONITOR:
562 // If a conflict, we try to defend with a single ARP probe. 529 // If a conflict, we try to defend with a single ARP probe.
563 if (source_ip_conflict) { 530 if (source_ip_conflict) {
564 VDBG("monitor conflict -- defending\n"); 531 VDBG("monitor conflict -- defending\n");
565 state = DEFEND;
566 timeout_ms = DEFEND_INTERVAL * 1000; 532 timeout_ms = DEFEND_INTERVAL * 1000;
533 state = DEFEND;
567 arp(/* ARPOP_REQUEST, */ 534 arp(/* ARPOP_REQUEST, */
568 /* &eth_addr, */ ip, 535 /* &G.eth_addr, */ chosen_nip,
569 &eth_addr, ip); 536 &G.eth_addr, chosen_nip);
570 } 537 }
571 break; 538 break;
572 case DEFEND: 539 case DEFEND:
573 // Well, we tried. Start over (on conflict). 540 // Well, we tried. Start over (on conflict).
574 if (source_ip_conflict) { 541 if (source_ip_conflict) {
575 state = PROBE;
576 VDBG("defend conflict -- starting over\n"); 542 VDBG("defend conflict -- starting over\n");
577 ready = 0; 543 run(argv, "deconfig", chosen_nip);
578 run(argv, "deconfig", &ip);
579 544
580 // restart the whole protocol 545 // restart the whole protocol
581 ip.s_addr = pick_nip();
582 timeout_ms = 0; 546 timeout_ms = 0;
547 chosen_nip = pick_nip();
583 nprobes = 0; 548 nprobes = 0;
584 nclaims = 0; 549 nclaims = 0;
550 state = PROBE;
585 } 551 }
586 break; 552 break;
587 default:
588 // Invalid, should never happen. Restart the whole protocol.
589 VDBG("invalid state -- starting over\n");
590 state = PROBE;
591 ip.s_addr = pick_nip();
592 timeout_ms = 0;
593 nprobes = 0;
594 nclaims = 0;
595 break;
596 } // switch state 553 } // switch state
597 break; // case 1 (packets arriving) 554 break; // case 1 (packets arriving)
598 } // switch poll 555 } // switch poll
diff --git a/shell/ash.c b/shell/ash.c
index 349e9deb8..f23a3e1ff 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -5030,7 +5030,7 @@ forkchild(struct job *jp, union node *n, int mode)
5030 * Our solution: ONLY bare $(trap) or `trap` is special. 5030 * Our solution: ONLY bare $(trap) or `trap` is special.
5031 */ 5031 */
5032 /* Save trap handler strings for trap builtin to print */ 5032 /* Save trap handler strings for trap builtin to print */
5033 trap_ptr = memcpy(xmalloc(sizeof(trap)), trap, sizeof(trap)); 5033 trap_ptr = xmemdup(trap, sizeof(trap));
5034 /* Fall through into clearing traps */ 5034 /* Fall through into clearing traps */
5035 } 5035 }
5036 clear_traps(); 5036 clear_traps();
diff --git a/testsuite/diff.tests b/testsuite/diff.tests
index 84d853852..0ced0f248 100755
--- a/testsuite/diff.tests
+++ b/testsuite/diff.tests
@@ -98,6 +98,18 @@ testing "diff -B does not ignore changes whose lines are not all blank" \
98 "a\n" \ 98 "a\n" \
99 "\nb\n\n" 99 "\nb\n\n"
100 100
101testing "diff -B ignores blank single line change" \
102 'diff -qB - input; echo $?' \
103 "0\n" \
104 "\n1\n" \
105 "1\n"
106
107testing "diff -B does not ignore non-blank single line change" \
108 'diff -qB - input; echo $?' \
109 "Files - and input differ\n1\n" \
110 "0\n" \
111 "1\n"
112
101testing "diff always takes context from old file" \ 113testing "diff always takes context from old file" \
102 "diff -ub - input | $TRIM_TAB" \ 114 "diff -ub - input | $TRIM_TAB" \
103"\ 115"\
diff --git a/util-linux/fbset.c b/util-linux/fbset.c
index e9aacce4f..ac0082f70 100644
--- a/util-linux/fbset.c
+++ b/util-linux/fbset.c
@@ -349,10 +349,10 @@ static int read_mode_db(struct fb_var_screeninfo *base, const char *fn,
349 int transp_offset, transp_length; 349 int transp_offset, transp_length;
350 350
351 sscanf(p, "%d/%d,%d/%d,%d/%d,%d/%d", 351 sscanf(p, "%d/%d,%d/%d,%d/%d,%d/%d",
352 &red_offset, &red_length, 352 &red_length, &red_offset,
353 &green_offset, &green_length, 353 &green_length, &green_offset,
354 &blue_offset, &blue_length, 354 &blue_length, &blue_offset,
355 &transp_offset, &transp_length); 355 &transp_length, &transp_offset);
356 base->red.offset = red_offset; 356 base->red.offset = red_offset;
357 base->red.length = red_length; 357 base->red.length = red_length;
358 base->red.msb_right = 0; 358 base->red.msb_right = 0;
diff --git a/util-linux/mdev.c b/util-linux/mdev.c
index ca4b91510..662e8ab38 100644
--- a/util-linux/mdev.c
+++ b/util-linux/mdev.c
@@ -471,7 +471,7 @@ static const struct rule *next_rule(void)
471 if (G.parser) { 471 if (G.parser) {
472 parse_next_rule(); 472 parse_next_rule();
473 if (G.rule_vec) { /* mdev -s */ 473 if (G.rule_vec) { /* mdev -s */
474 rule = memcpy(xmalloc(sizeof(G.cur_rule)), &G.cur_rule, sizeof(G.cur_rule)); 474 rule = xmemdup(&G.cur_rule, sizeof(G.cur_rule));
475 G.rule_vec = xrealloc_vector(G.rule_vec, 4, G.rule_idx); 475 G.rule_vec = xrealloc_vector(G.rule_vec, 4, G.rule_idx);
476 G.rule_vec[G.rule_idx++] = rule; 476 G.rule_vec[G.rule_idx++] = rule;
477 dbg3("> G.rule_vec[G.rule_idx:%d]=%p", G.rule_idx, G.rule_vec[G.rule_idx]); 477 dbg3("> G.rule_vec[G.rule_idx:%d]=%p", G.rule_idx, G.rule_vec[G.rule_idx]);